From 65a766e459685a5c9e20881dfa184b0fefffcd0c Mon Sep 17 00:00:00 2001 From: DangaRanga Date: Sun, 23 May 2021 12:21:39 -0500 Subject: [PATCH 01/34] Updated branching strategy --- CONTRIBUTING.md | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d4a02270b6..8f9ee51f7f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -36,18 +36,15 @@ Make sure you are following [issue report guidelines](https://github.com/Palisad [Pull Request guidelines](https://github.com/PalisadoesFoundation/talawa-admin/blob/master/PR-guidelines.md) is best resource to follow to start working on open issues. -#### Git Flow +#### Branching Strategy -For Talawa Admin, we utilize the GitFlow branching model. GitFlow is geared towards efficiently tracking development and managing releases. The model makes parallel development efforts easy and safe by isolating new development efforts from completed work. +For Talawa Admin, to simplify the development process, and to ensure that only stable code is pushed to the `master` branch, we had employed the following branching strategy: -The different types of branches we may use are: +- Develop branch: For unstable code and bug fixing +- Alpha-x.x.x: for stability teesting +- Master: Where the stable production ready code lies -- Feature branches (feature/branch-name) -- Release branches (release/1.XX) -- Bug branches (bugfix/branch-name) -- Hotfix branches (hotfix/branch-name) - -Detailed document containing how GitFlow works: https://nvie.com/posts/a-successful-git-branching-model/ +### Contributing Code ### Contributing Code From 0a6d4d61478df168a4ef3f94b65d040abdf2cd7f Mon Sep 17 00:00:00 2001 From: DangaRanga Date: Sun, 23 May 2021 12:22:05 -0500 Subject: [PATCH 02/34] Removed duplicate entry --- CONTRIBUTING.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8f9ee51f7f..dc1f9c837e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -46,8 +46,6 @@ For Talawa Admin, to simplify the development process, and to ensure that only s ### Contributing Code -### Contributing Code - Code contributions to Talawa come in the form of pull requests. These are done by forking the repo and making changes locally. Make sure you have read the [Documentation for Setting up the Project](https://github.com/PalisadoesFoundation/talawa-admin#project-setup) From e16a3ad9b4374fb9654451c8582ebc5139e677b8 Mon Sep 17 00:00:00 2001 From: DangaRanga Date: Sun, 23 May 2021 12:24:01 -0500 Subject: [PATCH 03/34] Updated contributing.md --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dc1f9c837e..6e4b6b8fe3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -38,7 +38,7 @@ Make sure you are following [issue report guidelines](https://github.com/Palisad #### Branching Strategy -For Talawa Admin, to simplify the development process, and to ensure that only stable code is pushed to the `master` branch, we had employed the following branching strategy: +For Talawa Admin, we had employed the following branching strategy to simplify the development process and to ensure that only stable code is pushed to the `master` branch: - Develop branch: For unstable code and bug fixing - Alpha-x.x.x: for stability teesting From 653345efa94011bb533a5a55b37d388099be0ef9 Mon Sep 17 00:00:00 2001 From: DangaRanga Date: Sun, 23 May 2021 12:25:16 -0500 Subject: [PATCH 04/34] Added extra markdown styling to contribute.md --- CONTRIBUTING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6e4b6b8fe3..8fbed29549 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -40,9 +40,9 @@ Make sure you are following [issue report guidelines](https://github.com/Palisad For Talawa Admin, we had employed the following branching strategy to simplify the development process and to ensure that only stable code is pushed to the `master` branch: -- Develop branch: For unstable code and bug fixing -- Alpha-x.x.x: for stability teesting -- Master: Where the stable production ready code lies +- `develop`: For unstable code and bug fixing +- `alpha-x.x.x`: for stability teesting +- `master`: Where the stable production ready code lies ### Contributing Code From 07f44657abcd37dadb7502699a5cb9e1145a818f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 30 May 2021 00:41:30 +0000 Subject: [PATCH 05/34] Bump dns-packet from 1.3.1 to 1.3.4 Bumps [dns-packet](https://github.com/mafintosh/dns-packet) from 1.3.1 to 1.3.4. - [Release notes](https://github.com/mafintosh/dns-packet/releases) - [Changelog](https://github.com/mafintosh/dns-packet/blob/master/CHANGELOG.md) - [Commits](https://github.com/mafintosh/dns-packet/compare/v1.3.1...v1.3.4) Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 27c0be6951..b9f81e8c57 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4183,9 +4183,9 @@ dns-equal@^1.0.0: integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0= dns-packet@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.1.tgz#12aa426981075be500b910eedcd0b47dd7deda5a" - integrity sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg== + version "1.3.4" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.4.tgz#e3455065824a2507ba886c55a89963bb107dec6f" + integrity sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA== dependencies: ip "^1.1.0" safe-buffer "^5.0.1" From 1a57176748cf5b045c096eff720c25806588fc9a Mon Sep 17 00:00:00 2001 From: Peter Harrison Date: Sun, 30 May 2021 10:51:48 -0700 Subject: [PATCH 06/34] Update pull_request_template.md --- .github/pull_request_template.md | 33 +++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index b3f679554c..c2a991ba29 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,13 +1,38 @@ - + + + **What kind of change does this PR introduce?** +**Issue Number:** + +Fixes # + **Did you add tests for your changes?** + + +**Snapshots/Videos:** + + + **If relevant, did you update the documentation?** + + **Summary** @@ -18,3 +43,9 @@ **Other information** + + + +**Have you read the [contributing guide](https://github.com/PalisadoesFoundation/talawa-admin/blob/master/CONTRIBUTING.md)?** + + From c4580fa42311feebe1098981634dc4b89442ef98 Mon Sep 17 00:00:00 2001 From: Akshat Garg <60404253+akshatgarg12@users.noreply.github.com> Date: Sun, 6 Jun 2021 23:47:03 +0530 Subject: [PATCH 07/34] disabled CodeQL cron jobs and push actions (#72) --- .github/workflows/codeql-analysis.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index ccd6fc3705..c2c875b9ce 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -12,13 +12,14 @@ name: "CodeQL" on: - push: - branches: [ master ] + # push: + # branches: [ master ] pull_request: # The branches below must be a subset of the branches above - branches: [ master ] - schedule: - - cron: '22 0 * * 5' + branches: + - '**' + # schedule: + # - cron: '22 0 * * 5' jobs: analyze: From f71bc1151b6c551df4ed3c787438c465627326f1 Mon Sep 17 00:00:00 2001 From: Md Noman Khan <54404474+noman2002@users.noreply.github.com> Date: Thu, 30 Nov 2023 21:44:04 +0530 Subject: [PATCH 08/34] Merge Develop into Main (#1099) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update authorized-changes-detection.yml * Code Coverage @ 87.1% * Update .gitignore * Delete codecov This executable should not be in the repo * added translation hint text in placeholders (#487) * Update pull-requests.yml * Create DOCUMENTATION.md * Rename issue-guidelines.md to ISSUE_GUIDELINES.md * Update CONTRIBUTING.md * Update issue.yml * Rename PR-guidelines.md to PR_GUIDELINES.md * Update CONTRIBUTING.md * Update pull-request-target.yml * Delete PULL_REQUEST_TEMPLATE.md * Delete ISSUE_TEMPLATE.md * Rename Code_Style.md to CODE_STYLE.md * added removeMember mutation (#491) * added removeMember mutation * changed mutation name * remove contributions from router (#502) * Fixed Settings page Header (#501) * fixed cani-use lite warning * fixed the alignments for smaller screens and also added spacing on places where it was needed * fixed the linting errors * ran prettier to remove styling errors * made the orgSetting title dynamic * linted the code and made the settings header as required and also made the settings page navbar responsive * linted code and made necessary changes * errors fixed * Added dropdown for Applanguage in UserUpdation form (#498) * Added dropdown for Applanguage in UserUpdation form * App language code changed to Default language * Change the Scalar Types [Provides relevant client side changes for #1085 in Talawa-API] (#500) * Change typedefs * Fix date parsing * Move ID to ObjectID scalar * Client changes for Adding GraphQL Scalars (#511) * Change typedefs * Fix date parsing * Move ID to ObjectID scalar * Revert ObjectID to ID * Change ObjectID to ID * modal closed after organization creation (#516) * most recently added Org displays at the top (#515) * Add Husky (#520) * updated contributing (#521) * Display and choose Organisation image (#512) * upload image working for createOrganisation * Organisation image showing everywhere * Testcase failure fixed * Linting fixed * convertToBase64 func made and tests for it * CI/CD error fixed * tests added for AdminNavbar & OrganisationDashboard * Linting fixed * fixed translation on the plugin tab (#510) * added OrgName to the Navbar (#525) * Fix create event mutation [Fixes part of #1101 in Talawa-API] (#523) * Add format fix * Fix updation of posts * Test coverage improved for organizationPeople.tsx (#526) * Update INSTALLATION.md * Update INSTALLATION.md * Update INSTALLATION.md * Update stale.yml * Remove tags (#532) * Fixed navbar added tests (#534) * Fixed navbar added tests * Fixed the translation of All orgnaizations btn in AdminNavbar * Fix the updateOrg page, and made it to create mutation request [Fixes #531] (#536) * fix orgUpdate system * fix translations * Update CONTRIBUTING.md * Code Coverage @ 88% * Fixes #478 : Implemeneted calendar to the Event tab (#537) * calendar-implemented * calendar-implemented * fixed tests * Added post-merge hook using husky (#541) * Added post-merge hook using husky * made required changes to installation.md * make changes to documentation for husky * made the required changes in installation guide * Update pull-requests.yml * Fixed yarn installation instructions (#584) * organization sorting for all organization (#619) * removed redundant notification (#577) * Profile Page for Members (#543) * Initial member page made * Changed query added Org and Events section * Homescreen ready * initial translation added for Profile * initial translation added for Profile * Added translations * Added translations * Revised translation * Fixed failing tests for components * Link added to OrgAdminListCard * Linting fixed for OrgPeopleListCard * Added tests, removed logs * Uniform design * Fix:routing issue for orgdash page (#580) * Fix:routing issue for orgdash page * fix:failing test of SuperDashListCard * Rectify Warnings: EventListCard.test.tsx (#595) * Added logic to close modal after successful submission (#623) * Feature Request: Position of the search bar. (#631) * Feature Request: Position of the search bar #614 resolved * Feature Request: Position of the search bar #614 resolved * fixes: #550 added test for the calendar (#552) * added test for the calendar * updates mocks * Update Router Function [Fixes #636] (#638) * Update Router Function * Empty commit * Fix about content overflow (#632) Signed-off-by: Ekene Nwobodo * removed duplicate rows per page section in orgposts (#648) * fixed :made card in organization dashboard interactive (#620) * Implemented manage functionality for admin and super admin after login (#539) * Implememnted manage functinality for admin/superadmin after login * Update AdminDashListCard.module.css * Some formatting issues with module file * resolved workflow issues * Added folding feature to posts (#581) * added folding feature to posts * added fold feature to posts * brought code under code coverage * added tests * added tests for remainging uncovered lines * brought code coverage to 100% for the changes * Code coverage @87.2% * Fix User Update Details Page and Add Update Password Page [Fixes #530] (#657) * fixed updateuser logic * update translations * fix lint * lint fix 2 * fix tests * fixed:move orgLocation & remove duplicate orgName (#655) * fixed:move orgLocation & remove duplicate orgName * Dummy commit * fixes - [#597] - Navbar navlinks hover and button styles (#603) * fixed: #585 - Password error showing. Tested * fix: #590 - fixed navbar hover issues * fix: #590 - fixed navbar hover issues * Code Coverage 87.4% * fixes 599 (#653) * fixed errors and removed window.replace * written test case for ensure window.location.replace * written test case for ensure window.location.replace * added useHistory to keep track of routing behind the scenes * fixed merge conflicts and errors * updated comments for file changes * Added warning comments for routing --------- Co-authored-by: Adepeju * fix org search location (#682) Signed-off-by: Ekene Nwobodo * fixed the issue of validate the input before submit #674 (#678) * Adds required tests for OrganizationEvents.tsx and Fixes a minor bug in Calendar (#527) * adds tests for organization events * removes the unrequired branch from OrganizationEvents.tsx * fixes failing tests * fixes failing lint tests * Update password preview feature with coverage tests (#629) * Fix to the issue #585 (#607) * [fix]- fixed the password error warning * [fix]- fixed the password error warning * [fix]- fixed the password error warning * [fix]-fixed the password error warning * [fix]-fixed the password error warning * [fix]-fixed the password error warning * [fix]-fixed the password error warning * [feat]-added test cases for password error warning * [feat]- added test cases for password error warning * [feat]- added test cases for password error warning * [fix]- fixed the linting * Improve test coverage for calendar.tsx (#679) * Improve test coverage for calendar.tsx * Restore previous tests * remove --coverage * i rebased my codebase and resolved the initial issue (#669) * fixed the issue use of toast in place of window.alert #645 (#687) * Update ISSUE_GUIDELINES.md * fixed the static time data under Organization card in the Organization List tab (#689) * fixed the static time in org card * formatted the date to MM D, YYYY --------- Co-authored-by: thesaaddevloper * Fixed the pagination alignment issue (#702) * [fix]- fixed the password error warning * [fix]- fixed the password error warning * [fix]- fixed the password error warning * [fix]-fixed the password error warning * [fix]-fixed the password error warning * [fix]-fixed the password error warning * [fix]-fixed the password error warning * [feat]-added test cases for password error warning * [feat]- added test cases for password error warning * [feat]- added test cases for password error warning * [fix]- fixed the linting * [fix]- fixed the pagination alignment issue * [fix]- fixed the pagination alignment issue * [fix]- fixed the pagination alignment issue * Removed overlapping (#675) * changes input element to textarea and changes in test (#710) * Code Coverage @90.7% * Indicating active tabs (#691) * added underline to active links in navbar * fixed lint error * fixed the org default image #688 and removed stock image (#695) * fixed the org default image #688 and removed stock image * removed eslint warning * added new img as default org img * Update INSTALLATION.md * Added Clear Error and Warn Messages when API is unavailable (#670) * Added error and warn messages * Added tests & fixed inconsistency in mocks * Lint fix LoginPage * Lint Fix LoginPage.test * minor fix * Minor update to LoginPage * Minor change to LoginPage.test * Replaced toast.warn() with toast.error() * Fixed test accordingly * Lint Fix * Minor fix * Extra edge case handled * code coverage fix * Lint fix * Update LoginPage * Update LoginPage.test * Lint fix * improve test coverage for orgpost.tsx (#718) * Improve test coverage for calendar.tsx * Restore previous tests * remove --coverage * improve test for orgpost.tsx * Implemented Proper Error Handling for all Screens [Fixes: #535] (#731) * Handled error cases for all screens * Some more fixes * Some more fixes * Added StaticMockLink to use Mocks multiple times [Fixes Multiple Issues] (#745) * add StaticMockLink * lint fix * remove showWarning * Added prompt to Register on Login Page (#628) * Add prompt to Login page - Add prompt in other languages: fr, sp, hi, zh. - switch styling of Login Button with Reg Button * format with prettier * fixed event checkboxes to update (#707) * Block/Unblock functionality for only members of the organization (#690) * Implememnted manage functinality for admin/superadmin after login * Update AdminDashListCard.module.css * Some formatting issues with module file * resolved workflow issues * Updated block/unblock page preventing users who are not members of organiztion * Update BlockUser.test.tsx to resolve failing tests Modified the mocks fields according to the corresponding changes in BlockUser.tsx file. * created a reusable postNotFound Component with responsive UI (#717) * created a reusable postNotFound Component with responsive UI * run test error solved * added translation to the component and also created the test.tsx for the error component * fixed the failing test and added the postNotFound reusable component for OrgList --------- Co-authored-by: thesaaddevloper * fix: #601 modal responsive width (#621) * added dynamic title to OrgPeople section (#704) * added dynamic title to OrgPeople section * fixed code coverage * fixed code coverage * uncommented the mistakenly added code * Delete er * Updated session timeout notification toast with already existing one (#734) * Added a toast to notify users that session has expired and redirects to the login page * Updated toast notification on session timeout with already existing one * eliminated the use of magic numbers * minor error correction on the timeout minutes --------- Co-authored-by: TheoCathy * Fixed the empty space in the OrgList (#751) * created a reusable postNotFound Component with responsive UI * run test error solved * added translation to the component and also created the test.tsx for the error component * fixed the failing test and added the postNotFound reusable component for OrgList * fixed the empty space in orgList * fixed the failing test * removed the unwanted files --------- Co-authored-by: thesaaddevloper * align navbar items (#755) * align navbar items * replace More with a hamburger icon * replace More with a hamburger icon to fix workflow error * replace More with a hamburger icon to fix workflow error * Fixes: toggle password for registration (#758) * added toggle-password * updated * formatting * added icon for toggle password * Super Admin Dashboard Error When Organizations Absent (#754) * No Organization Warning on OrgList * Minor Fix * Fixed failing tests * Added Warning on Roles and Request Pages * Added Tests for OrgList * Testing Fixes * Added more tests * Added Tests for Roles and Request Pages * Code Coverage @ 91.0% * Add link to dashboard admin card (#760) * image upload made functional (#677) * image upload made functional * lint * fixed failing test * linting * re run test , remove yarn.lock changes * updateUser test cov * OrgPost * rerun tests * Empty commit * reverted last 2 commits changes * re run code cov * update userUpdate * rerun code cov again * revert last commit * Update PR_GUIDELINES.md * Implemented Search bar and the radio buttons in orgPost page that searches both title and text of post (#770) * created a reusable postNotFound Component with responsive UI * run test error solved * added translation to the component and also created the test.tsx for the error component * fixed the failing test and added the postNotFound reusable component for OrgList * fixed the empty space in orgList * fixed the failing test * removed the unwanted files * the one search bar which searches both text and title of post * testing file * orpost file testing * code coverage is increased * fixed the failing test --------- Co-authored-by: thesaaddevloper Co-authored-by: saadabban76 <–115649011+saadabban76@users.noreply.github.com> * center org image on mobile (#778) Signed-off-by: Ekene Nwobodo * removed link for plugin dropdown toggle (#781) * removed link for plugin dropdown toggle * added id * align superadmin nav items and fix failed tests (#766) * changed the handleSearchByName function in searchByName in Roles page (#735) * changed the handleSearchByName function to search using target's value instead of searchByName variable * updated the file Roles.tsx to take care of useState lag * changed tests for suiting searchByName * changed tests for searchByName including backspaces * added tests for paginationList and changing rowsPerPage * added tests to increase coverage in Roles.tsx * changed the package.json file's test command * removed extra scrollbars (#800) * Recently added Post displays at top (#773) * Recently added Post displays at top * reversed the posts as required in the query * Increased the OrgList Code Coverage (#786) * increased the orgList coverage to 95$ * increased the orgList Code Coverage * increased the orgList Code Coverage * increased the orgList Code Coverage * fixed image rendering in orgPost page * increased the code coverage for orgList Component * increased code coverage to 97% in orgList Component --------- Co-authored-by: saadabban76 <–115649011+saadabban76@users.noreply.github.com> * Modify event visibility for non-admins (#796) * Modify event visibility for non-admins Signed-off-by: Ekene Nwobodo * Add test suites for events visibilty --------- Signed-off-by: Ekene Nwobodo * Bug Fix: Drawer menu visibility (#794) * Remove filter by event field (#807) * increased the orgList coverage to 95$ * increased the orgList Code Coverage * increased the orgList Code Coverage * increased the orgList Code Coverage * fixed image rendering in orgPost page * increased the code coverage for orgList Component * increased code coverage to 97% in orgList Component * removed the filter by event section in orgPeople's component * fixed the failing test --------- Co-authored-by: saadabban76 <–115649011+saadabban76@users.noreply.github.com> * Add image to post (#804) * increased the orgList coverage to 95$ * increased the orgList Code Coverage * increased the orgList Code Coverage * increased the orgList Code Coverage * fixed image rendering in orgPost page * increased the code coverage for orgList Component * increased code coverage to 97% in orgList Component * added Image to the post's card * replaced external links with codebase default image * replaced external links with codebase default image * replaced blank image with the default image * fixed the failing test --------- Co-authored-by: saadabban76 <–115649011+saadabban76@users.noreply.github.com> * Update pull-request-target.yml * Update pull-request-target.yml * Update pull-request-target.yml * Update pull-request-target.yml * Update pull-request-target.yml * Update pull-request-target.yml * Upgrade Yarn to NPM in Talawa Admin Project (#802) * npm upgrade * remove package lock * Update push.yml * empty * upgrade yarn to npm * fix docs * fix scripts * empty * stop watch mode * fix ymls * empty * fix scripts * empty commit * update scripts * Redirect to dashboard on organization update (#816) * Redirect to dashboard on organization update * Minor Change * Proper Testing Of Pagination In All List Views (#797) * install faker package used for mocks in tests * Test init for pagination * install dependencies needed to implement certain tests * add a data-testid attribute to their markup for use in tests * add data-testid attributes to its markup being referenced from tests * add test to ensure the number of organization displayed on the page corresponds to the option selected from rowsPerPage * add prop to allow rendering of component in test environment * add data-testid attributes to their markup being referenced from tests * add data-testid attributes to its markup being referenced from tests * add test to affirm that the number of persons displayed on the webpage is same with the selected option from rowsPerPage * install dependencies for certain tests * fix lint errors * tests fix * remove unnecessary dependencies * lint fix * tests fix update * restore file to previous state * empty commit * tests fix update * lint fix * Conditional Usage of Google reCAPTCHA [Fixes #798] (#820) * conditonal recaptcha * Update INSTALLATION.md * add tests * fixed the issue of Mismatched passwords validation #722 (#824) * fixed the issue of Mismatched passwords validation #722 * fixed lint code error * Code Coverage @ 92% * Replace Talawa Portal with Talawa Admin Portal #817 (#821) * Update website title to Talawa Admin Portal in en * Update website title in fr json file * Update website title in sp json file * Update website title in zh json file * Update website title in hi json file * Update the test in ListNavbar file * Update the test in LoginPage.test file * Create a function for the tex macher to make test * Fix lint errors in the LandingPage test file * Remove console.log in LandingPage test file * Upgrade to use npm instead of yarn * Delete yarn.lock file * Fix lint errors * Fix lint errors * Update the heading in hi.json file * Remove unused codes * Fix lint error in LanfingPage file * Correct the talawa_portal value in Fr json file * Correct the talawa_portal value in sp json file * Remove anused package in package.json file * Organization Form Redirect Issue Prevents User Navigation, Affecting User Experience. Issue #808 (#815) * addressing issue #808 * finished - requested changes * addressing warning * Added: event preview modal to view event details (#772) * added event preview model * added event preview model * fixed formatting * added test * added test * added test * failing tests * test * tests * Update workflow (#832) * Workflow fix (#833) * Update pull-requests.yml * Update pull-requests.yml * Update pull-requests.yml * Code Coverage @ 91.0% * Feature: Separation of ADMIN and SUPERADMIN functionalities (#826) * Initial changes * Commit to sync repo * Made changes to OrgList * Some fixes * Minor fix * Added tests for OrgList * Added tests for OrgList * Coverage fix * Required changes added * Made changes to OrgList * Some fix * Some fixes * fixes test for OrgList * Some more fixes * Empty commit * Lint fix * Fixed test * Lint fix * Added Whitespace Validation to Organization and Post create forms (#838) * Added whitespace check in Org Create form * Added Tests * Added Empty String check to OrgPost Form * Added Tests for OrgPost * fixed the issue of Toast msg is not available in all languages #740 (#845) * fixed the issue of Toast msg is not available in all languages #740 * format issue * Empty-Commit * Fixed Org Update (#843) * Prevent Admins and Super Admins from downgrading their own roles (#840) * Code Cleanup * Disabled Super Admins from changing their roles * Added Tests * Added more tests * Improved Code Quality * Revert "Fixed Org Update (#843)" (#847) This reverts commit 53c3fef28ef986d63b1eec45663acb7d07cf1b8d. * Fixed Organization Update and Translation (#849) * Fixed Organization Update * Minor Changes * Success message updated * Fail tests on warning [Priority Needed] (#856) * fix warnings Signed-off-by: Ansh Goyal * fix warnings Signed-off-by: Ansh Goyal * fix warnings Signed-off-by: Ansh Goyal * fix warnings Signed-off-by: Ansh Goyal * fix warnings Signed-off-by: Ansh Goyal * restore addonregister Signed-off-by: Ansh Goyal --------- Signed-off-by: Ansh Goyal * Code duplicacy removed (#852) * Code duplicacy removed * Tests added * Added comments * Fixed failing tests * Code formatted * Unused packages removed, flag icons package updated to latest version (#860) * Unused packages removed, flag icons updated to latest version * Empty commit * Changes in package-lock.json * Fixes #848: limiting mulitple toast (#851) * limiting-toast * added test * Organization People Filters Improved (#855) * Added Filters to Users and Organizations Query * Added Last Name Filter on User, Member and Admin * Added Translation * Fixed Failing Tests * Added Tests for Filters * Fixed Failing Tests * Code Cleanup * Fixed Tests * Added Translation * remove graphql-boost dep (#866) Signed-off-by: Ansh Goyal * added UserNotFound component to the Roles page and improved the search (#865) * changed the handleSearchByName function to search using target's value instead of searchByName variable * updated the file Roles.tsx to take care of useState lag * changed tests for suiting searchByName * changed tests for searchByName including backspaces * added tests for paginationList and changing rowsPerPage * added tests to increase coverage in Roles.tsx * changed the package.json file's test command * changed PostNotFound component to be used as a reusable one and added it in Roles section and set languages option in locales folder * changed formatting in locales changed files * removed comments in Roles.tsx * Empty commit * renamed the PostNotFound component and modifiied relevant files * changed Roles.tsx filtering * empty commit * reverted changes in package.json * Improved signupform validations (#828) * Improved signupform validations * updated signup form validation to show all messages at once * improved test coverage for LoginPage * Fixed failing test --------- Co-authored-by: Joyce Malicha * added tests for Search Bar in the Organization List Page of SUPERADMIN #827 (#867) * added tests for Search Bar in the Organization List Page of SUPERADMIN #827 * added tests for Search Bar in the Organization List Page of SUPERADMIN #827 * Added Tests Previews (#868) * Installed jest-preview * Automatic Setup * Fiixed Failing Test Command * Added Basic CSS * Added PostCSS Module * Fixed MUI Styling * Minor Changes * Added cross-env to support windows * Adaptar for React 17 and CSS Modules Mock * Added Mocked Styles to Tests * Documentatin Updated * Fixed Failing Tests * Minorr change in documentation * Jest is now Dev Dependency * Workflow Test * Jest Module Path Updates * Module Path Tese 2 * Github Workflow Fixed * Removed Legacy Test Command * Added Documentation to Debug Tests * Fixed Documentation * Docs Image Added To Repo * Images Reorganization * Organized Images * Revert "Improved signupform validations (#828)" (#875) This reverts commit 5820dd9ec05256551b48470c8880fcdc05452fda. * Restored SearchBar Test for OrgList Page (#878) * Restored searchBar test * Lint fix * Coverage fix * Lint fix * Some fixes * Some fixes * fixed the issue of Users filter to fetch corresponding Users to Organisation #701 (#853) * fixed the issue of Users filter to fetch corresponding Users to Organisation #701 * removedd uunused variable * fixed failing text * fixed merged issue * fixed lint error * swap variable * Revert "Restored SearchBar Test for OrgList Page (#878)" (#879) This reverts commit 3d39c524d54e81853490d2d8a1f844ce67252365. * Fixed crashing on error in Block/Unblock page (#862) * Website crash fixed * lint fixed * Added tests for empty response from server * More tests added * Rerun tests empty commit * Redirect on error functioning * Fixed failing tests * Testcase and Title added when users not found * Linting fixed * Typo fixed * Fixed failing tests * Linting fixed * Added NotFound component in OrgPeople and changed Roles.tsx (#882) * changed the handleSearchByName function to search using target's value instead of searchByName variable * updated the file Roles.tsx to take care of useState lag * changed tests for suiting searchByName * changed tests for searchByName including backspaces * added tests for paginationList and changing rowsPerPage * added tests to increase coverage in Roles.tsx * changed the package.json file's test command * changed PostNotFound component to be used as a reusable one and added it in Roles section and set languages option in locales folder * changed formatting in locales changed files * removed comments in Roles.tsx * Empty commit * renamed the PostNotFound component and modifiied relevant files * changed Roles.tsx filtering * empty commit * reverted changes in package.json * added NotFound component in OrgPeople, made changes in the locales files and made some changes to Roles too * added NotFound component to OrgPeople, changerd locales files and changed Roles.tsx * minor change * Restored Search-Bar Test for OrgList Page (#880) * Restored searchBar test * Lint fix * Coverage fix * Lint fix * Some fixes * Some fixes * Fixed Org Dashboard Error (#873) * Fixed TypeError * Minor Change * Fixed Tests * Added back logo512 * Fixed auth header getting copied on login (#890) * fix user update (#876) * fix user detials update * remove userType from update-user page * fix failed test for userUpdate.test.tsx * Removed and Replaced Ant Design from the project (#891) * Fixed auth header getting copied on login * Removed/Replaced Ant Design from the project * Fixed failing tests * Removed comment * Add today functionality in calendar (#897) * Update countline.py * Update pull-requests.yml * Updated countlines.py to cover .spec. files (#900) Co-authored-by: Peter Harrison * fixed the Inability to set user roles for specific organizations #556 (#898) * fixed the Inability to set user roles for specific organizations #556 * added all language translation * Revert "fixed the Inability to set user roles for specific organizations #556 (#898)" (#901) This reverts commit 891d898eb5543116bb9042a6386b5a12e474159c. * Documentation updated, Redundant css files removed (#896) * Doc updated unused files removed * Removed unused css files from setup tests * Added small calendar in the events #887 (#903) * added small clanedar * added small clanedar * fixed Code Coverage: Create tests for OrgSettings.tsx #396 (#905) * remove redundancy from orgPostCard (#906) * Revert "remove redundancy from orgPostCard (#906)" (#910) This reverts commit d5ce4aa27ee241b0687f7db3d6acd1b62339562f. * Block/Unblock Page Improvements (#885) * Added Radio Buttons * Optimized Queries * Optimized Query and Added Last Name Filter * Radio Button Working * Added Translations * Fixed Filter Name * Fixed Debounce * Fixed Asynchronous Debounce * Added Tests * Better Error and Loading State Handline * Fixed Loader * Fixed Loader * Modulrised Mock Data * Minor Change * Fixed Tests * Increase Coverage * User query replaced with OrgMemberConnection * Fixed Tests * Code Coverage Increase * Code Cov * Fixed Translations * Fixed Failing Tests * fix in failing test (#913) * Improve and Standardize Automated Linting Tests (#916) * added linting rules * added linting rules * added linting rules * Rename `data` variables to more readable name [Fixes #829] (#835) * Refactor screens * Update components * Fix test * Fix typecheck errors * Increase test coverage * Merge latest adminUI-Redesign into Develop (#927) * Updated CODE_STYLE.md * Updated CODE_STYLE.md (#917) * Updated CODE_STYLE.md * Import section update * Upgrade and Migrate from Bootstrap 4 to Bootstrap 5 (#925) * Updated CODE_STYLE.md * Latest Boostrap v5.3.0 & react-bootstrap v2.7.4 installed * Buttons replaced from normal ones to Bootstrap ones * Import section update * Error fixed for Buttons * Language dropdowns and Change language * InputBoxes & Checkboxes fixed and imported from BS * Removed unused package popper.js * Replaced react-modal with Bootstrap one in Login Page * Modals converted to React Bootstrap one * Completely replaced react-modal with react-bootstrap/Modal from the project * Removed react-modal from the project * Removed classbased modal and unused images * Notification navbar migrated * Modal migration * Modal migration * Modal migration done for OrgPostCard * Empty commit to make workflow run * Empty commit to make workflow run * Empty commit to run the workflow --------- Co-authored-by: Anwer Sayeed * Introduces API versioning check in CI/CD (#924) * a random change * husky precommit * one more try * one more try * one more try * one more try * one more try * one more try * second try * removed unwanted deps * removed unwanted deps * resolved the error * updated variable name * rerun test * rerun test * added test to pull.yml * removed push check * resolved conflict * Update stale.yml * Update CONTRIBUTING.md * Merge talawa-user-portal into develop (#935) * Create login and register page for user portal * Lint public locales * Create tests for login page components * Add react import in tests * Create organizations screen for user portal * Fix failing tests and lint code * fix failing tests * Add tests for organization screen and componenets * Fix non-null assertions * Fix non-null assertions in organizations test * Fix bootstrap migration changes * Merge latest Admin UI Redesign into Develop (#934) * Updated CODE_STYLE.md * Updated CODE_STYLE.md (#917) * Updated CODE_STYLE.md * Import section update * Upgrade and Migrate from Bootstrap 4 to Bootstrap 5 (#925) * Updated CODE_STYLE.md * Latest Boostrap v5.3.0 & react-bootstrap v2.7.4 installed * Buttons replaced from normal ones to Bootstrap ones * Import section update * Error fixed for Buttons * Language dropdowns and Change language * InputBoxes & Checkboxes fixed and imported from BS * Removed unused package popper.js * Replaced react-modal with Bootstrap one in Login Page * Modals converted to React Bootstrap one * Completely replaced react-modal with react-bootstrap/Modal from the project * Removed react-modal from the project * Removed classbased modal and unused images * Notification navbar migrated * Modal migration * Modal migration * Modal migration done for OrgPostCard * Empty commit to make workflow run * Empty commit to make workflow run * Empty commit to run the workflow * Sass filed added with documentation * Linting fixed * Fixed the folder structure and naming convention * Customised Bootstrap (#929) * Sass filed added with documentation * Linting fixed * Fixed the folder structure and naming convention * Assets typo fixed * Typo fix * Merge conflict error fixed --------- Co-authored-by: Anwer Sayeed * test PR for API versioning check (#932) * testPR * test2 * testing the change * testing it again * test--no-verify * test--no-verify * echo token * test-again * test-again * test * test * read-only * clone * clone * redesigned newsfeed (#939) * Revert "redesigned newsfeed (#939)" (#943) This reverts commit a645eca7cf2ce1335374f48b52335a293e344580. * Make Talawa-Admin mutations in sync with the backend (#946) * Initial change * Redundant Notification removed * Fixed linting and other issues * Tests fixed * Add Home Screen And People Screen along with other components (#940) * Create login and register page for user portal * Lint public locales * Create tests for login page components * Add react import in tests * Create organizations screen for user portal * Fix failing tests and lint code * fix failing tests * Add tests for organization screen and componenets * Fix non-null assertions * Fix non-null assertions in organizations test * Fix bootstrap migration changes * Add Home Screen along with other components * Fix failing tests * Add required tests and Offcanvas navbar * Remove unused variables from tests * Sync the Mutations with talawa-api * Merge AdminUI-Redesign into Develop (#947) * Updated CODE_STYLE.md * Updated CODE_STYLE.md (#917) * Updated CODE_STYLE.md * Import section update * Upgrade and Migrate from Bootstrap 4 to Bootstrap 5 (#925) * Updated CODE_STYLE.md * Latest Boostrap v5.3.0 & react-bootstrap v2.7.4 installed * Buttons replaced from normal ones to Bootstrap ones * Import section update * Error fixed for Buttons * Language dropdowns and Change language * InputBoxes & Checkboxes fixed and imported from BS * Removed unused package popper.js * Replaced react-modal with Bootstrap one in Login Page * Modals converted to React Bootstrap one * Completely replaced react-modal with react-bootstrap/Modal from the project * Removed react-modal from the project * Removed classbased modal and unused images * Notification navbar migrated * Modal migration * Modal migration * Modal migration done for OrgPostCard * Empty commit to make workflow run * Empty commit to make workflow run * Empty commit to run the workflow * Sass filed added with documentation * Linting fixed * Fixed the folder structure and naming convention * Customised Bootstrap (#929) * Sass filed added with documentation * Linting fixed * Fixed the folder structure and naming convention * Assets typo fixed * Typo fix * Initial login page work * Merge conflict error fixed * Theming modified and Added Loader over every screen * Fixed UI issue for navbar and login * Fixed production bug * Removed unused variable * Tests fixed * Added Change Language Btn dropdown * Merge conflict fixed, merge latest develop into adminUI-redesign (#938) * Merge latest adminUI-Redesign into Develop (#927) * Updated CODE_STYLE.md * Updated CODE_STYLE.md (#917) * Updated CODE_STYLE.md * Import section update * Upgrade and Migrate from Bootstrap 4 to Bootstrap 5 (#925) * Updated CODE_STYLE.md * Latest Boostrap v5.3.0 & react-bootstrap v2.7.4 installed * Buttons replaced from normal ones to Bootstrap ones * Import section update * Error fixed for Buttons * Language dropdowns and Change language * InputBoxes & Checkboxes fixed and imported from BS * Removed unused package popper.js * Replaced react-modal with Bootstrap one in Login Page * Modals converted to React Bootstrap one * Completely replaced react-modal with react-bootstrap/Modal from the project * Removed react-modal from the project * Removed classbased modal and unused images * Notification navbar migrated * Modal migration * Modal migration * Modal migration done for OrgPostCard * Empty commit to make workflow run * Empty commit to make workflow run * Empty commit to run the workflow --------- Co-authored-by: Anwer Sayeed * Introduces API versioning check in CI/CD (#924) * a random change * husky precommit * one more try * one more try * one more try * one more try * one more try * one more try * second try * removed unwanted deps * removed unwanted deps * resolved the error * updated variable name * rerun test * rerun test * added test to pull.yml * removed push check * resolved conflict * Sass filed added with documentation * Linting fixed * Fixed the folder structure and naming convention * Update stale.yml * Typo fix * Update CONTRIBUTING.md * Merge talawa-user-portal into develop (#935) * Create login and register page for user portal * Lint public locales * Create tests for login page components * Add react import in tests * Create organizations screen for user portal * Fix failing tests and lint code * fix failing tests * Add tests for organization screen and componenets * Fix non-null assertions * Fix non-null assertions in organizations test * Fix bootstrap migration changes * Merge conflict error fixed --------- Co-authored-by: Anwer Sayeed Co-authored-by: Kanishka Bansode <96020697+kb-0311@users.noreply.github.com> Co-authored-by: Peter Harrison <16875803+palisadoes@users.noreply.github.com> Co-authored-by: Noble Mittal <62551163+beingnoble03@users.noreply.github.com> * Random checkout * Design ready for homescreen * Login page 100% code c=coverage * Login page icon adjustment * Added translations * Fixed the failing tests * Revert to older version of loader * Animation added fixed warnings * Fixed accessability * Mutations and Tests foxed * Fixed coloring in UserPortal * Tests fixed and ChangeLanguageDropdown used in UserLoginPage * Linting Fixed --------- Co-authored-by: Anwer Sayeed Co-authored-by: Kanishka Bansode <96020697+kb-0311@users.noreply.github.com> Co-authored-by: Peter Harrison <16875803+palisadoes@users.noreply.github.com> Co-authored-by: Noble Mittal <62551163+beingnoble03@users.noreply.github.com> * Merge latest adminUI-Redesign (#950) * Initial Organizations screen done * Removed yellow scrollbar * Linting fixed * Replaced images with svgs for logos * Styling done for btnsContainer * Better typechecking and readability * Animated Drawer working * Responsive page ready * OrgCard responsive * Fixed navbar issue and added webkit keyframes * LeftDrawer ready * Translations added * Added shimmer loading effect * Styling issue fixed * Failing tests fixed for OrgList * Removed unused vars * Tests done for LeftDrawer * Succesfully made component without causing any breaking change * 100% Code coverage achieved for Requests Screen * Fix alignment * Roles screen UI done * Role screen fixed with 100% test coverage * Changing screen activeness fixed * Unused vars and Typos fixed * Language support added * Linting and typos fixed * Fixed failing tests for LeftDrawer * Completed tests of AdminDashListCard with 100% code coverage * OrgListCard done * Finalised tests * Requests user search made functional again ! * Fixed loading on refetch and UX on all screens * OrgList failing errors fixed * Fixed all failing tests * Achieved 100% code coverage for OrgList.tsx * Wrote tests and mod LeftDrawer for admins * Minor ui issue fixed * Fixed failing test * UI bug dropdown * Frontend insync with Backend attempt 1 * Introspection fail fix 1 * Introspection error fix 3 * Introspection error fix another attempt * Another attempt * [Talawa-user-portal] Add Settings and Donate Screen, along with other UI fixes (#953) * Create login and register page for user portal * Lint public locales * Create tests for login page components * Add react import in tests * Create organizations screen for user portal * Fix failing tests and lint code * fix failing tests * Add tests for organization screen and componenets * Fix non-null assertions * Fix non-null assertions in organizations test * Fix bootstrap migration changes * Add Home Screen along with other components * Fix failing tests * Add required tests and Offcanvas navbar * Remove unused variables from tests * Sync the Mutations with talawa-api * Add Settings and Donate Screen * Add multilingual support for the screens * Add Event Project and Volunteer Management (#961) * Add screens for adding and updating event projects * Add delete operation for event projects and debug update * Remove yarn.lock * Begin testing * Add display of tasks and functionality to add tasks * Add modal for edit task * Add UpdateTaskModal * Add Delete Task Modal and volunteers display * Add test for DeleteEventProjectModal.tsx * Add tests for add and update event project modal * Add screen for managing volunteers * Add option to assign and remove volunteers * Add tests for AddTaskModal.tsx * Add tests for TaskListItem.tsx and DeleteTaskModal.tsx * Complete testing for all Task Modals * Add completed display to tasks * Add tests for event dashboard * Restructure files * Add attendee management modal * Add testing for EventAttendeeModal * Move to 100% testing and wrapper for attendees modal * Add basic checkIn functionality for users * Add testing for CheckIn modals * Introduce the tag generation into the repository * Update linting rule and fix errors * Remove alloted seat and alloted room * Fix testing * Correct some tests * Migrate from attendees to registrants * Migrate Event Project modals to new design * Migrate registrants modals and checkin modals to new design with 100% test coverage * Move task modals to new styles * Move to 100% test coverage * Admin workflow completed with updated package.json (#960) * Merge latest AdminUI Redesign into develop (#956) * Initial Organizations screen done * Removed yellow scrollbar * Linting fixed * Replaced images with svgs for logos * Styling done for btnsContainer * Better typechecking and readability * Animated Drawer working * Responsive page ready * OrgCard responsive * Fixed navbar issue and added webkit keyframes * LeftDrawer ready * Translations added * Added shimmer loading effect * Styling issue fixed * Failing tests fixed for OrgList * Removed unused vars * Tests done for LeftDrawer * Succesfully made component without causing any breaking change * 100% Code coverage achieved for Requests Screen * Fix alignment * Roles screen UI done * Role screen fixed with 100% test coverage * Changing screen activeness fixed * Unused vars and Typos fixed * Language support added * Linting and typos fixed * Fixed failing tests for LeftDrawer * Completed tests of AdminDashListCard with 100% code coverage * OrgListCard done * Finalised tests * Requests user search made functional again ! * Fixed loading on refetch and UX on all screens * OrgList failing errors fixed * Fixed all failing tests * Achieved 100% code coverage for OrgList.tsx * Wrote tests and mod LeftDrawer for admins * Minor ui issue fixed * Fixed failing test * UI bug dropdown * Frontend insync with Backend attempt 1 * Introspection fail fix 1 * Introspection error fix 3 * Introspection error fix another attempt * Another attempt * Fixed Default Animation on Organizations Screen * Fixed typo * Loading data from localstorage functional * Fixed name conventions * Fixed typo * UI Fix * Changed screen name * Table Loader added * Added LeftOrg drawer and Organization screen comp to Screens * routesReducer tests fixed * Redundant adminNavbar removed from project * MemberDetail issue fixed * Achieved 100% code coverage for LeftDrawerOrg, Added Empty div in images * Fixed failing tests * Fix tests * Fixed warnings * Linting fixes * Linting issues fixed * Achieved 100% code coverage for CollapsibleDropdown * Achieved 100% CC on IconComponent and removed useless imports * Achieved 100% cc for LeftDrawer Component * Achieved 100% CC on SuperAdminScreen Component * Fixed typo * Integrated Event Dashboard * Failing tests for LeftDrawer LeftDrawerOrg OrgList screen fixed * Removed redundant code * Removed useless imports * Linting fixed * Removed LeftDrawerOrg * Update documentation * copy-docs -to-talawa branch update to develop * removed dependance of code copying from generate segment * Update push.yml (#969) * Update push.yml (#970) * Feature Request: Adding a dialog to go to plugin store after an organization is created by the admin (#951) * Add/ test for OrgPost.tsx * fix: org post back to default * Added Dialog 2 * Updated Dialog UI * Removed Extra code * Updated Plugin store * fix: warnings and solves #951 & #948 * fix: warnings and solves #951 & #948 * fix: warnings and solves #951 & #948 * Fix: UI Redesign * fix: merge * fix * Update AddOnStore.tsx * Fixed Merge Errors * Add test: for OrgEntry * Test 3 * fix test 4 * Merge latest AdminUI Redesign into develop (#972) * Initial Organizations screen done * Removed yellow scrollbar * Linting fixed * Replaced images with svgs for logos * Styling done for btnsContainer * Better typechecking and readability * Animated Drawer working * Responsive page ready * OrgCard responsive * Fixed navbar issue and added webkit keyframes * LeftDrawer ready * Translations added * Added shimmer loading effect * Styling issue fixed * Failing tests fixed for OrgList * Removed unused vars * Tests done for LeftDrawer * Succesfully made component without causing any breaking change * 100% Code coverage achieved for Requests Screen * Fix alignment * Roles screen UI done * Role screen fixed with 100% test coverage * Changing screen activeness fixed * Unused vars and Typos fixed * Language support added * Linting and typos fixed * Fixed failing tests for LeftDrawer * Completed tests of AdminDashListCard with 100% code coverage * OrgListCard done * Finalised tests * Requests user search made functional again ! * Fixed loading on refetch and UX on all screens * OrgList failing errors fixed * Fixed all failing tests * Achieved 100% code coverage for OrgList.tsx * Wrote tests and mod LeftDrawer for admins * Minor ui issue fixed * Fixed failing test * UI bug dropdown * Frontend insync with Backend attempt 1 * Introspection fail fix 1 * Introspection error fix 3 * Introspection error fix another attempt * Another attempt * Fixed Default Animation on Organizations Screen * Fixed typo * Loading data from localstorage functional * Fixed name conventions * Fixed typo * UI Fix * Changed screen name * Table Loader added * Added LeftOrg drawer and Organization screen comp to Screens * routesReducer tests fixed * Redundant adminNavbar removed from project * MemberDetail issue fixed * Achieved 100% code coverage for LeftDrawerOrg, Added Empty div in images * Fixed failing tests * Fix tests * Fixed warnings * Linting fixes * Linting issues fixed * Achieved 100% code coverage for CollapsibleDropdown * Achieved 100% CC on IconComponent and removed useless imports * Achieved 100% cc for LeftDrawer Component * Achieved 100% CC on SuperAdminScreen Component * Fixed typo * Integrated Event Dashboard * Failing tests for LeftDrawer LeftDrawerOrg OrgList screen fixed * Removed redundant code * Removed useless imports * Linting fixed * Removed LeftDrawerOrg * Dashboard screen ui almost ready * Org Dash ready * Block/Unblock screen ready * Organization settings page ready * Lang changes * Page refresh on updating org removed * OrgUpdate tests done * OrgUpdate 100% test coverage achieved * OrgSettings Tests done * Organization Dashboard Cards done * Organization Dashboard achieved 100% CC * 100% CC achieved for BlockUser screen * Finalised changes * Small change * Tests fixed * Separate OrgSettings component made * Linting fixed * Formatting fixed * Events screen and Post Comment Modal for Talawa-user-portal (#963) * Create login and register page for user portal * Lint public locales * Create tests for login page components * Add react import in tests * Create organizations screen for user portal * Fix failing tests and lint code * fix failing tests * Add tests for organization screen and componenets * Fix non-null assertions * Fix non-null assertions in organizations test * Fix bootstrap migration changes * Add Home Screen along with other components * Fix failing tests * Add required tests and Offcanvas navbar * Remove unused variables from tests * Sync the Mutations with talawa-api * Add Settings and Donate Screen * Add multilingual support for the screens * Add events screen without calendar view * Add multilingual support to Events screen * Fix failing tests due to merge * Add Post Comment functionality * Refactor Events tests * Deprecate event registrants from query * Update README.md * Add My Tasks screen and Fix UI bugs [User Portal] (#978) * Create login and register page for user portal * Lint public locales * Create tests for login page components * Add react import in tests * Create organizations screen for user portal * Fix failing tests and lint code * fix failing tests * Add tests for organization screen and componenets * Fix non-null assertions * Fix non-null assertions in organizations test * Fix bootstrap migration changes * Add Home Screen along with other components * Fix failing tests * Add required tests and Offcanvas navbar * Remove unused variables from tests * Sync the Mutations with talawa-api * Add Settings and Donate Screen * Add multilingual support for the screens * Add events screen without calendar view * Add multilingual support to Events screen * Fix failing tests due to merge * Add Post Comment functionality * Refactor Events tests * Deprecate event registrants from query * Add my tasks screen for user portal * Remove unnecessary comments from test files * Add Feedback UI Components to Talawa Admin (#980) * Add feedback component * Add tests for feedback modal * Add handling for empty feedback * Add Average Rating and Reviews component * Add testing for all the added cards * Fix tests and move to 100% coverage * Add bugfix * Add merge function to fix failing tests * Add key definitons * Change merge policy * Add custom merge policy to all the Event Stat tests * remove cache * Migrate to a single query in the parent * Adding Plugin Logic to the Talawa Mobile Web App (#976) * Add/ test for OrgPost.tsx * fix: org post back to default * Added Dialog 2 * Updated Dialog UI * Removed Extra code * Updated Plugin store * fix: warnings and solves #951 & #948 * fix: warnings and solves #951 & #948 * fix: warnings and solves #951 & #948 * Fix: UI Redesign * fix: merge * fix * Update AddOnStore.tsx * Fixed Merge Errors * Add test: for OrgEntry * Test 3 * fix test 4 * chores: version changes * Add: Initial Websocket setup on talawa mobile web * Add: plugin logic * Add: plugin logic * removed extra * removed extra * Added: Tests * fix * Add Side Navigation to Event Dashboard (#981) * Create left drawer for event dashboard * Add basic styles to the event dashboard * Fix button styling * Add testing * Add testing for the left event drawer * Add 100% line coverage for all components * Increase timeout for tests * Move maximum rating in feedback from 10 to 5 [Fixes #990] (#987) * Move maximum rating in feedbacks from 10 to 5 * Fix failing tests * Add chat screen to talawa-user-portal (#986) * Create login and register page for user portal * Lint public locales * Create tests for login page components * Add react import in tests * Create organizations screen for user portal * Fix failing tests and lint code * fix failing tests * Add tests for organization screen and componenets * Fix non-null assertions * Fix non-null assertions in organizations test * Fix bootstrap migration changes * Add Home Screen along with other components * Fix failing tests * Add required tests and Offcanvas navbar * Remove unused variables from tests * Sync the Mutations with talawa-api * Add Settings and Donate Screen * Add multilingual support for the screens * Add events screen without calendar view * Add multilingual support to Events screen * Fix failing tests due to merge * Add Post Comment functionality * Refactor Events tests * Deprecate event registrants from query * Add my tasks screen for user portal * Remove unnecessary comments from test files * Add chat screen along with components * Add mui/system package for x-chart support * Add chat screen tests and fix other bugs * Update issue.yml * Update stale.yml * Merge latest AdminUI Redesign into Master (#1006) * Pagination Done for Orglist * Fixed warnings * Infinite scroll and search working for Requests screen * Simplified the code * Infinite scroll enabled and functioning on OrgList Requests and Users screen * FIxed warning * Fixed typo * Fixed bug * Joined and Blockedbyorgs screen and mdoal ready * Tables ready ! * Remove user from organization functionality working well * Update user role in organization feature ready * Minor changes * Done with tests on OrgList * Done with testss of Requests screen * 100% CC achieved for Users screen * Main tests done for UserTableItem * 100% Code Coverage Achieved for UserTableItem * Removed Redundant Landing Page * 100% CC achieved for TableLoader * Translation added for Users Screen * Translation done for Requests screen * Translation done for dashboard screen * Linting and warnings fixed * Improved login page * UI Done for Forgot Password Screen * Forgot Password Screen Tests done! * Fixed all pending tests * Better message for btns and coloring * Linting issues fixed * Fixed code styles * SUPPRESSED UNKNOWN ERROR * Fixed formatting * Updated typoed message * Fixed failing tests accompanying typo * fix createEvent to close modal and show events without refresh (#1014) * fix: Ensure Full Visibility of Logo on 404 Error Page (#1018) - Adjusted the positioning of the logo on the 404 error page to ensure full visibility. - Implemented CSS modifications to prevent the logo from being covered or cut off. - Tested the changes by navigating to various undefined endpoints, confirming that the logo is now displayed correctly on the 404 error page. This commit addresses the bug by ensuring the proper display of the logo on the 404 error page, enhancing the user experience. Fixes #1016 Signed-off-by: Akhilender * Implemented featurs for Postfeed Management (#982) * redesigned newsfeed * added test * newsfeed management * pinned post * postfeed management * pin unpin tag and video control * changes part 2 * newsfeed changes * changes in Card Preview of newsfeed * changes in Card Preview of newsfeed * testing phase 1 * translation * tests * tests * merged intto develop * test * Added query * Update pull-requests.yml * update and delete buttons of event modal are now working (#1051) * update and delete buttons of event modal are now working * fixed the naming conventions and style of the modal * Dynamic dashboard Enhancements (#979) * Dynamic Organization Dashboard * Dynamic Organization Dashboard * refined organization dashboard * Update src/utils/handleLatestFeed.ts Co-authored-by: Noble Mittal <62551163+beingnoble03@users.noreply.github.com> * fixed inconsistent casing * fixed org dashboard test * fixed org dashboard test * revert previous commit * final changes * final changes --------- Co-authored-by: Noble Mittal <62551163+beingnoble03@users.noreply.github.com> * Fix dashboard items (#1007) * Dashboard items are working now. * added variables for links -fix dashboard items * Added variables for links -fix dashboard items. * made the changes as said * Removed : string from variable assignment. * remove repititive code and resolved falling tests * Fix repeating code and falling tests. * Resolved some more falling tests * write test for missed lines * Fix event creation issue with white spaces. (#1025) * fix event creation with white spaces * Add test for empty input values * chore: fix unit test (#1052) * Fix layout distortion due to untruncated title description of events. (#1049) * Fix layout distortion due to untruncated title description of events * Add test * add test for LeftDrawerEvent.tsx * fixed some tests * add test complete * test: SecuredRouteForUser component 100% Test Coverage and fixed uncovered lines (#1048) * SecuredRouteForUser test case added * Fixed Linting Errors * Update SecuredRouteForUser.test.tsx * Update SecuredRouteForUser.test.tsx * linting fix * Update SecuredRouteForUser.test.tsx * Update SecuredRouteForUser.test.tsx * Fix incorrect toast Notification. (#1053) * correct toast notification for TableRow.tsx with full test coverage * Add correct toast with full code coverage * Add correct toast for deleteEventProjectModal.tsx with full test coverage * Add correct toast for UpdateEventProjectModal.tsx with full test coverage * Add correct toast for EventRegistrantsModal.tsx and full test coverage. * Add correct toast for AddTaskModal.tsx with full test coverage * Add correct toast for UpdateTaskModal.tsx with full test coverage * minor fix * Add correct toast to EventRegistrantsModal.tsx * fix EventRegitrantsModal.tsx * created a return button on event dashboard (#1057) * test: Loader Component 100% Test Coverage and Fix Uncovered Lines (#1047) * test: Achieve 100% Test Coverage and Fix Uncovered Lines - Improved the test coverage for the Loader component, addressing the previously uncovered lines and ensuring that all tests pass successfully. - Added a test to ensure that the component renders correctly with a custom 'sm' size. I verified that both the spinner-wrapper and spinner elements are present and that the correct class is applied. - Added a test to ensure that the component renders correctly with a 'lg' size. I verified that the spinner element has the appropriate class. - Added a test to ensure that the component renders correctly with an 'xl' size. I verified that the spinner element has the correct class. With these new tests, I now have 100% test coverage, and there are no more uncovered lines. The Loader component is thoroughly tested for different size scenarios, and all tests pass successfully. Signed-off-by: Akhilender * Fixed linting in Loader component Signed-off-by: Akhilender * Test: Increasing the test level - Trying to meet the code coverage level for Loader component. Signed-off-by: Akhilender * Fixed Linting Signed-off-by: Akhilender * fix: Linting Signed-off-by: Akhilender * Improving test coverage for Loader Component - Fixed lint errors Signed-off-by: Akhilender * test: Improving the tests on the Loader Component - Added a new aspect in the test-case1 Signed-off-by: Akhilender * Fixed: Removed runtime-generated classes from testing - Eliminated all checks for classes associated with bootstrap components assigned at runtime. - Recognized that validating classes assigned during runtime is inappropriate. Signed-off-by: Akhilender --------- Signed-off-by: Akhilender * Simulated Test Database (#984) * Dynamic Organization Dashboard * Dynamic Organization Dashboard * Sample Org Implementation * removed unnecessary changes * removed unnecessary svgs * removed unnecessary import * added appropriate button style * fixed OrgListCard tests * Fixed OrgList and OrgListCard Tests * Removed Unnecessary 'container' Variable * Added Missing Translations and removed unused variable * Fixed event check in management not updating automatically bug (#1062) * fixed the event checkIn bug * fixed the failing test * fixed the CheckInWrapper test * Fix user profile buttons layout and added form validation (#1064) * Fix user profile buttons layout and added form validation * Fix falling tests and warnings * Add test for missed lines * fix falling tests * test: Achieved 100% test coverage and fixed uncovered lines (#1068) * test: Achieved 100% test coverage and fixed uncovered lines - Improved the test coverage for the User-Password-Update component, addressing the previously uncovered lines and ensuring that all tests pass successfully. - Added two new tests 1. Empty Password Field Test: - The first test ensures that an error is displayed when attempting to save changes with an empty password field. 2. Mismatched New and Confirm Passwords Test - The second test covers the scenario where the new and confirm password fields do not match. With these new tests, I now have 100% test coverage, and there are no more uncovered lines. Signed-off-by: Akhilender * Altered the formData - Altered the formData to make sure all are related to the organization name. Signed-off-by: Akhilender --------- Signed-off-by: Akhilender * created test for src/components/UserPortal/EventCard/EventCard.tsx (#1079) * created test for eventCard of User portal * corrected the start and end time * Feature request: Adding advertisement screen (#994) * Add/ test for OrgPost.tsx * fix: org post back to default * Added Dialog 2 * Updated Dialog UI * Removed Extra code * Updated Plugin store * fix: warnings and solves #951 & #948 * fix: warnings and solves #951 & #948 * fix: warnings and solves #951 & #948 * Fix: UI Redesign * fix: merge * fix * Update AddOnStore.tsx * Fixed Merge Errors * Add test: for OrgEntry * Test 3 * fix test 4 * chores: version changes * Add: Initial Websocket setup on talawa mobile web * Add: plugin logic * Add: plugin logic * removed extra * removed extra * Added: Tests * fix * Added WEBSOCKET_URL in .env.example * Advertisement Management Screen * Feature: Create and Delete advertisement * Only current OrgIDs are visible to admin * Showing advertisements in the User end app * Message: fix * formatting * update test * Fix # 1071 * Added test for entry file * Added test for entry file2 * Added test for entry file2 * feat: Implemented Sorting Functionality for Users Screen (#1081) * feat: Implemented Sorting Functionality for Users Screen Changes Made: - Implemented sorting functionality for the users screen. - Added options for sorting users by latest first and oldest first. - Wrote corresponding tests to ensure the sorting behavior is accurate. - Tested the sorting feature by logging into the Talawa admin dashboard, navigating to the users option, and checking the sort button. Signed-off-by: Akhilender * fix: altering the words - Made Latest to Newest Signed-off-by: Akhilender --------- Signed-off-by: Akhilender * fix: user profile page details responsive for mobile screen (#1087) * MVP Talawa Admin : Hiding Chat Feature from Talawa Web App (#1078) * chat changes * test case * Update CONTRIBUTING.md * Added Test for PromotedPost.tsx (#1093) * Update CONTRIBUTING.md * Update PR_GUIDELINES.md * Update PR_GUIDELINES.md * Update pull_request_template.md * Added Tests for AdvertisementRegister.tsx (#1094) * Fixes Event Project Responsiveness (#1090) * Fixed the error while loading the origanization data (#1086) * Implement Token Refresh in talawa-admin for Seamless Session Renewal (#1061) * refresh token * added tests * fixed react scope error * Fixed date in advertisements (#1097) --------- Signed-off-by: Ekene Nwobodo Signed-off-by: Ansh Goyal Signed-off-by: Akhilender Co-authored-by: Peter Harrison Co-authored-by: Aashima wadhwa <73706697+aashimawadhwa@users.noreply.github.com> Co-authored-by: Kanishka Bansode <96020697+kb-0311@users.noreply.github.com> Co-authored-by: Ansh Goyal Co-authored-by: Anurag Kamboj Co-authored-by: Rishav Jha <76212518+rishav-jha-mech@users.noreply.github.com> Co-authored-by: Eshaan Aggarwal <96648934+EshaanAgg@users.noreply.github.com> Co-authored-by: Nishant Singh Co-authored-by: Aditya Shelke <103348863+adi-uchiha@users.noreply.github.com> Co-authored-by: Aviral Yadav <121368112+aviraldevv@users.noreply.github.com> Co-authored-by: Akanksha <72144454+akankshat05@users.noreply.github.com> Co-authored-by: Syed Aman Ali Co-authored-by: Akunne Pascal <48069624+Kodecheff@users.noreply.github.com> Co-authored-by: Samuel Mintah Co-authored-by: Olofu Ojoachubione <87946002+Shugo52@users.noreply.github.com> Co-authored-by: Nwobodo Leonard Co-authored-by: Pratik Aswani <69317773+pratik9333@users.noreply.github.com> Co-authored-by: Raj Abdulmumin <65510943+techfussion@users.noreply.github.com> Co-authored-by: Manoramsharma <84619980+Manoramsharma@users.noreply.github.com> Co-authored-by: Nafisat Faruk <80838239+Phyya@users.noreply.github.com> Co-authored-by: Orefejo Adepeju Co-authored-by: Adepeju Co-authored-by: Sumit Maithani <86047367+Sumitmaithani@users.noreply.github.com> Co-authored-by: Noble Mittal <62551163+beingnoble03@users.noreply.github.com> Co-authored-by: Aimanosi <104039356+Aimanosi@users.noreply.github.com> Co-authored-by: Arushi Agrawal <78142604+arushi2715@users.noreply.github.com> Co-authored-by: D.karlson Co-authored-by: Mohammed Saad Abban <115649011+saadabban76@users.noreply.github.com> Co-authored-by: thesaaddevloper Co-authored-by: akhilender-bongirwar <112749383+akhilender-bongirwar@users.noreply.github.com> Co-authored-by: Bhuvanesh Patil Co-authored-by: Nweneary Uzochukwu Winnie <99335288+Wineshuga@users.noreply.github.com> Co-authored-by: Theodora <107179983+TheoCathy@users.noreply.github.com> Co-authored-by: TheoCathy Co-authored-by: Prathamesh Mutkure Co-authored-by: saadabban76 <–115649011+saadabban76@users.noreply.github.com> Co-authored-by: R.Pranauv Kumar <97829544+Pranauv-Kumar1803@users.noreply.github.com> Co-authored-by: Indresh Goswami Co-authored-by: Victor Michael <114509848+Sheguun@users.noreply.github.com> Co-authored-by: Toussaint Saraza Co-authored-by: Su Myat Aung Co-authored-by: Joyce <51859049+jmalisha@users.noreply.github.com> Co-authored-by: Joyce Malicha Co-authored-by: Peter Harrison Co-authored-by: Anwer Sayeed Co-authored-by: Peter Harrison <16875803+palisadoes@users.noreply.github.com> Co-authored-by: Nitya Pasrija <97171261+Nitya-Pasrija@users.noreply.github.com> Co-authored-by: TASNEEM KOUSHAR Co-authored-by: Siddhesh Bhupendra Kuakde Co-authored-by: Sandeep Kumar Bhagat Co-authored-by: Kanhaiya yadav <93936630+kanhaiya04@users.noreply.github.com> Co-authored-by: Jamari McFarlane <71823011+JamarTG@users.noreply.github.com> Co-authored-by: Aldrin <53973174+Dhoni77@users.noreply.github.com> Co-authored-by: Shekhar Patel <90516956+duplixx@users.noreply.github.com> Co-authored-by: Mahendra Dani <116940083+MahendraDani@users.noreply.github.com> Co-authored-by: Aarish Shah Mohsin <49566965+aarishshahmohsin@users.noreply.github.com> Co-authored-by: Alok Gupta Co-authored-by: Aman Singh Co-authored-by: Patel Divyesh --- .env.example | 23 + .eslintignore | 2 + .eslintrc.json | 78 +- .../{bug_report.md => bug-report.md} | 13 +- ...{feature_request.md => feature-request.md} | 12 +- .github/pull_request_template.md | 4 +- .github/workflows/README.md | 47 + .../authorized-changes-detection.yml | 34 + .github/workflows/ci.yml | 13 - .github/workflows/codeql-analysis.yml | 68 - .github/workflows/codeql-codescan.yml | 43 + .github/workflows/countline.py | 297 + .github/workflows/issue.yml | 28 +- .github/workflows/linter.yml | 11 - .github/workflows/npm-publish.yml | 47 - .github/workflows/pull-request-target.yml | 72 + .github/workflows/pull-requests.yml | 82 + .github/workflows/push.yml | 114 + .github/workflows/stale.yml | 43 + .gitignore | 13 +- .husky/post-merge | 4 + .husky/pre-commit | 8 + .prettierignore | 4 +- .prettierrc | 3 +- CODEOWNERS | 2 + CODE_STYLE.md | 233 + CONTRIBUTING.md | 155 +- DOCUMENTATION.md | 21 + Docker_Container/.dockerignore | 5 - Docker_Container/README.md | 50 - Docker_Container/docker-compose.yml | 16 - Docker_Container/dockerfile | 21 - INSTALLATION.md | 217 + ISSUE_GUIDELINES.md | 59 + ISSUE_TEMPLATE.md | 38 - PR-guidelines.md | 21 - PR_GUIDELINES.md | 57 + PULL_REQUEST_TEMPLATE.md | 15 - README.md | 48 +- issue-guidelines.md | 12 - jest-preview.config.ts | 5 + jest.config.js | 64 + package-lock.json | 25207 ++++++++++++++++ package.json | 113 +- public/favicon.ico | Bin 3870 -> 870 bytes public/favicon_palisadoes.ico | Bin 0 -> 870 bytes public/images/REACT_SITE_KEY.webp | Bin 0 -> 35286 bytes public/images/jest-preview.webp | Bin 0 -> 145414 bytes public/{ => images}/logo512.png | Bin public/index.html | 5 +- public/locales/en.json | 690 + public/locales/fr.json | 668 + public/locales/hi.json | 668 + public/locales/sp.json | 668 + public/locales/zh.json | 668 + public/logo192.png | Bin 5347 -> 0 bytes public/manifest.json | 4 +- schema.graphql | 1152 + scripts/custom-test-env.js | 17 + scripts/test.js | 53 + src/App.test.tsx | 95 +- src/App.tsx | 157 +- src/Constant/constant.spec.ts | 29 + src/Constant/constant.ts | 6 + src/GraphQl/Mutations/mutations.ts | 742 + src/GraphQl/Queries/Queries.ts | 845 + src/assets/css/app.css | 12589 ++++++++ src/assets/images/blank.png | Bin 0 -> 5911 bytes src/assets/images/defaultImg.png | Bin 0 -> 585990 bytes src/assets/images/palisadoes_logo.png | Bin 0 -> 169634 bytes src/assets/images/talawa-logo-200x200.png | Bin 0 -> 5468 bytes .../{ => images}/talawa-logo-dark-200x200.png | Bin .../images/talawa-logo-lite-200x200.png | Bin 0 -> 5061 bytes src/{App.css => assets/scss/_colors.scss} | 0 src/assets/scss/_general.scss | 63 + src/assets/scss/_talawa.scss | 136 + src/assets/scss/_utilities.scss | 0 src/assets/scss/_variables.scss | 30 + src/assets/scss/app.scss | 14 + src/assets/scss/components/_accordion.scss | 34 + src/assets/scss/components/_alert.scss | 10 + src/assets/scss/components/_badge.scss | 6 + src/assets/scss/components/_breadcrumb.scss | 11 + src/assets/scss/components/_buttons.scss | 68 + src/assets/scss/components/_card.scss | 19 + src/assets/scss/components/_carousel.scss | 27 + src/assets/scss/components/_close.scss | 12 + src/assets/scss/components/_dropdown.scss | 35 + src/assets/scss/components/_list-group.scss | 26 + src/assets/scss/components/_modal.scss | 43 + src/assets/scss/components/_nav.scss | 28 + src/assets/scss/components/_navbar.scss | 31 + src/assets/scss/components/_offcanvas.scss | 13 + src/assets/scss/components/_pagination.scss | 43 + src/assets/scss/components/_placeholder.scss | 2 + src/assets/scss/components/_progress.scss | 17 + src/assets/scss/components/_spinners.scss | 24 + src/assets/scss/content/_table.scss | 37 + src/assets/scss/content/_typography.scss | 69 + src/assets/scss/forms/_check-radios.scss | 34 + src/assets/scss/forms/_floating-label.scss | 12 + src/assets/scss/forms/_form-control.scss | 106 + src/assets/scss/forms/_input-group.scss | 6 + src/assets/scss/forms/_range.scss | 19 + src/assets/scss/forms/_select.scss | 44 + src/assets/scss/forms/_validation.scss | 20 + src/assets/svgs/addEventProject.svg | 1 + src/assets/svgs/admin.svg | 5 + src/assets/svgs/angleRight.svg | 3 + src/assets/svgs/blockUser.svg | 3 + src/assets/svgs/blockedUser.svg | 3 + src/assets/svgs/checkInRegistrants.svg | 1 + src/assets/svgs/dashboard.svg | 3 + src/assets/svgs/date.svg | 1 + src/assets/svgs/event.svg | 3 + src/assets/svgs/eventStats.svg | 1 + src/assets/svgs/events.svg | 3 + src/assets/svgs/flask.svg | 1 + src/assets/svgs/key.svg | 4 + src/assets/svgs/listEventRegistrants.svg | 1 + src/assets/svgs/location.svg | 1 + src/assets/svgs/logout.svg | 3 + src/assets/svgs/organizations.svg | 5 + src/assets/svgs/palisadoes.svg | 12 + src/assets/svgs/people.svg | 4 + src/assets/svgs/plugins.svg | 7 + src/assets/svgs/post.svg | 3 + src/assets/svgs/posts.svg | 3 + src/assets/svgs/requests.svg | 10 + src/assets/svgs/roles.svg | 3 + src/assets/svgs/settings.svg | 4 + src/assets/svgs/tags.svg | 4 + src/assets/svgs/talawa.svg | 7 + src/assets/svgs/user.svg | 1 + src/assets/svgs/users.svg | 3 + src/assets/talawa-logo-lite-200x200.png | Bin 5133 -> 0 bytes src/components/AddOn/AddOn.module.css | 0 src/components/AddOn/AddOn.test.tsx | 34 + src/components/AddOn/AddOn.tsx | 36 + .../core/AddOnEntry/AddOnEntry.module.css | 20 + .../AddOn/core/AddOnEntry/AddOnEntry.test.tsx | 98 + .../AddOn/core/AddOnEntry/AddOnEntry.tsx | 126 + .../AddOnRegister/AddOnRegister.module.css | 9 + .../core/AddOnRegister/AddOnRegister.test.tsx | 72 + .../core/AddOnRegister/AddOnRegister.tsx | 159 + .../core/AddOnStore/AddOnStore.module.css | 31 + .../AddOn/core/AddOnStore/AddOnStore.test.tsx | 60 + .../AddOn/core/AddOnStore/AddOnStore.tsx | 360 + .../components/Action/Action.module.css | 0 .../support/components/Action/Action.test.tsx | 24 + .../support/components/Action/Action.tsx | 21 + .../MainContent/MainContent.module.css | 4 + .../MainContent/MainContent.test.tsx | 26 + .../components/MainContent/MainContent.tsx | 18 + .../components/SidePanel/SidePanel.module.css | 12 + .../components/SidePanel/SidePanel.test.tsx | 27 + .../components/SidePanel/SidePanel.tsx | 26 + .../support/services/Plugin.helper.test.ts | 46 + .../AddOn/support/services/Plugin.helper.ts | 24 + .../AddOn/support/services/Render.helper.ts | 3 + .../Advertisements/Advertisements.module.css | 31 + .../Advertisements/Advertisements.test.tsx | 95 + .../Advertisements/Advertisements.tsx | 197 + .../AdvertisementEntry.module.css | 20 + .../AdvertisementEntry.test.tsx | 60 + .../AdvertisementEntry/AdvertisementEntry.tsx | 103 + .../AdvertisementRegister.module.css | 9 + .../AdvertisementRegister.test.tsx | 137 + .../AdvertisementRegister.tsx | 207 + .../ChangeLanguageDropDown.tsx | 65 + .../ChangeLanguageDropdown.test.tsx | 106 + .../CheckIn/CheckInModal.module.css | 43 + src/components/CheckIn/CheckInModal.test.tsx | 58 + src/components/CheckIn/CheckInModal.tsx | 121 + .../CheckIn/CheckInWrapper.module.css | 13 + .../CheckIn/CheckInWrapper.test.tsx | 58 + src/components/CheckIn/CheckInWrapper.tsx | 41 + src/components/CheckIn/TableRow.test.tsx | 141 + src/components/CheckIn/TableRow.tsx | 76 + src/components/CheckIn/mocks.ts | 82 + src/components/CheckIn/tagTemplate.ts | 22 + src/components/CheckIn/types.ts | 48 + .../CollapsibleDropdown.module.css | 14 + .../CollapsibleDropdown.test.tsx | 77 + .../CollapsibleDropdown.tsx | 91 + .../ContriStats/ContriStats.module.css | 7 + .../ContriStats/ContriStats.test.tsx | 39 + src/components/ContriStats/ContriStats.tsx | 33 + src/components/DeleteOrg/DeleteOrg.module.css | 25 + src/components/DeleteOrg/DeleteOrg.test.tsx | 84 + src/components/DeleteOrg/DeleteOrg.tsx | 111 + .../EventCalendar/EventCalendar.module.css | 82 + .../EventCalendar/EventCalendar.test.tsx | 215 + .../EventCalendar/EventCalendar.tsx | 242 + .../EventListCard/EventListCard.module.css | 193 + .../EventListCard/EventListCard.test.tsx | 344 + .../EventListCard/EventListCard.tsx | 465 + .../AddEventProjectModal.test.tsx | 132 + .../AddEventProjectModal.tsx | 99 + .../DeleteEventProjectModal.test.tsx | 108 + .../DeleteEventProjectModal.tsx | 70 + .../UpdateEventProjectModal.test.tsx | 155 + .../UpdateEventProjectModal.tsx | 103 + .../EventRegistrantsModal.module.css | 43 + .../EventRegistrantsModal.test.tsx | 336 + .../EventRegistrantsModal.tsx | 156 + .../EventRegistrantsWrapper.module.css | 13 + .../EventRegistrantsWrapper.test.tsx | 92 + .../EventRegistrantsWrapper.tsx | 46 + src/components/EventStats/EventStats.test.tsx | 62 + src/components/EventStats/EventStats.tsx | 59 + .../EventStats/EventStatsWrapper.module.css | 13 + .../EventStats/EventStatsWrapper.test.tsx | 76 + .../EventStats/EventStatsWrapper.tsx | 37 + src/components/EventStats/Loader.module.css | 43 + .../Statistics/AverageRating.test.tsx | 58 + .../EventStats/Statistics/AverageRating.tsx | 60 + .../EventStats/Statistics/Feedback.test.tsx | 100 + .../EventStats/Statistics/Feedback.tsx | 102 + .../EventStats/Statistics/Review.test.tsx | 95 + .../EventStats/Statistics/Review.tsx | 57 + .../IconComponent/IconComponent.test.tsx | 69 + .../IconComponent/IconComponent.tsx | 103 + .../LeftDrawer/LeftDrawer.module.css | 246 + src/components/LeftDrawer/LeftDrawer.test.tsx | 258 + src/components/LeftDrawer/LeftDrawer.tsx | 183 + .../LeftDrawerEvent.module.css | 291 + .../LeftDrawerEvent/LeftDrawerEvent.test.tsx | 243 + .../LeftDrawerEvent/LeftDrawerEvent.tsx | 199 + .../LeftDrawerEventWrapper.module.css | 60 + .../LeftDrawerEventWrapper.test.tsx | 94 + .../LeftDrawerEventWrapper.tsx | 62 + .../LeftDrawerOrg/LeftDrawerOrg.module.css | 290 + .../LeftDrawerOrg/LeftDrawerOrg.test.tsx | 395 + .../LeftDrawerOrg/LeftDrawerOrg.tsx | 230 + src/components/Loader/Loader.module.css | 25 + src/components/Loader/Loader.test.tsx | 26 + src/components/Loader/Loader.tsx | 36 + .../MemberRequestCard.module.css | 57 + .../MemberRequestCard.test.tsx | 122 + .../MemberRequestCard/MemberRequestCard.tsx | 125 + src/components/NotFound/NotFound.module.css | 24 + src/components/NotFound/NotFound.test.tsx | 26 + src/components/NotFound/NotFound.tsx | 25 + .../OrgAdminListCard.module.css | 74 + .../OrgAdminListCard.test.tsx | 99 + .../OrgAdminListCard/OrgAdminListCard.tsx | 120 + .../OrgContriCards/OrgContriCards.module.css | 22 + .../OrgContriCards/OrgContriCards.test.tsx | 50 + .../OrgContriCards/OrgContriCards.tsx | 42 + src/components/OrgDelete/OrgDelete.test.tsx | 27 + src/components/OrgDelete/OrgDelete.tsx | 17 + .../OrgListCard/OrgListCard.module.css | 92 + .../OrgListCard/OrgListCard.test.tsx | 119 + src/components/OrgListCard/OrgListCard.tsx | 90 + .../OrgPeopleListCard.module.css | 74 + .../OrgPeopleListCard.test.tsx | 103 + .../OrgPeopleListCard/OrgPeopleListCard.tsx | 123 + .../OrgPostCard/OrgPostCard.module.css | 278 + .../OrgPostCard/OrgPostCard.test.tsx | 403 + src/components/OrgPostCard/OrgPostCard.tsx | 629 + src/components/OrgUpdate/OrgUpdate.module.css | 13 + src/components/OrgUpdate/OrgUpdate.test.tsx | 174 + src/components/OrgUpdate/OrgUpdate.tsx | 220 + src/components/OrgUpdate/OrgUpdateMocks.ts | 157 + .../OrganizationCard.module.css | 46 + .../OrganizationCard.test.tsx | 41 + .../OrganizationCard/OrganizationCard.tsx | 49 + .../OrganizationCardStart.module.css | 46 + .../OrganizationCardStart.test.tsx | 31 + .../OrganizationCardStart.tsx | 41 + .../OrganizationDashCards/CardItem.module.css | 60 + .../OrganizationDashCards/CardItem.test.tsx | 47 + .../OrganizationDashCards/CardItem.tsx | 88 + .../OrganizationDashCards/CardItemLoading.tsx | 24 + .../DashboardCard.test.tsx | 18 + .../OrganizationDashCards/DashboardCard.tsx | 32 + .../DashboardCardLoading.tsx | 36 + .../Dashboardcard.module.css | 60 + .../OrganizationScreen.module.css | 60 + .../OrganizationScreen.test.tsx | 39 + .../OrganizationScreen/OrganizationScreen.tsx | 66 + src/components/Pagination/Pagination.test.tsx | 62 + src/components/Pagination/Pagination.tsx | 97 + .../PaginationList/PaginationList.css | 7 + .../PaginationList/PaginationList.tsx | 81 + src/components/SecuredRoute/SecuredRoute.tsx | 39 + .../SuperAdminScreen.module.css | 60 + .../SuperAdminScreen.test.tsx | 42 + .../SuperAdminScreen/SuperAdminScreen.tsx | 56 + .../TableLoader/TableLoader.module.css | 3 + .../TableLoader/TableLoader.test.tsx | 78 + src/components/TableLoader/TableLoader.tsx | 67 + .../TaskListItem/TaskListItem.test.tsx | 130 + src/components/TaskListItem/TaskListItem.tsx | 106 + .../TaskModals/AddTaskModal.test.tsx | 150 + src/components/TaskModals/AddTaskModal.tsx | 114 + .../TaskModals/DeleteTaskModal.test.tsx | 100 + src/components/TaskModals/DeleteTaskModal.tsx | 64 + .../TaskModals/ManageVolunteerModal.test.tsx | 135 + .../TaskModals/ManageVolunteerModal.tsx | 102 + .../TaskModals/UpdateTaskModal.test.tsx | 262 + src/components/TaskModals/UpdateTaskModal.tsx | 222 + .../UserListCard/UserListCard.module.css | 74 + .../UserListCard/UserListCard.test.tsx | 98 + src/components/UserListCard/UserListCard.tsx | 95 + .../UserPasswordUpdate.module.css | 93 + .../UserPasswordUpdate.test.tsx | 150 + .../UserPasswordUpdate/UserPasswordUpdate.tsx | 156 + .../UserPortal/ChatRoom/ChatRoom.module.css | 13 + .../UserPortal/ChatRoom/ChatRoom.tsx | 81 + .../CommentCard/CommentCard.module.css | 46 + .../CommentCard/CommentCard.test.tsx | 228 + .../UserPortal/CommentCard/CommentCard.tsx | 101 + .../ContactCard/ContactCard.module.css | 33 + .../ContactCard/ContactCard.test.tsx | 116 + .../UserPortal/ContactCard/ContactCard.tsx | 53 + .../DonationCard/DonationCard.module.css | 22 + .../UserPortal/DonationCard/DonationCard.tsx | 24 + .../UserPortal/EventCard/EventCard.module.css | 26 + .../UserPortal/EventCard/EventCard.test.tsx | 185 + .../UserPortal/EventCard/EventCard.tsx | 124 + .../UserPortal/Login/Login.module.css | 29 + .../UserPortal/Login/Login.test.tsx | 296 + src/components/UserPortal/Login/Login.tsx | 147 + .../OrganizationCard.module.css | 22 + .../OrganizationCard.test.tsx | 67 + .../OrganizationCard/OrganizationCard.tsx | 30 + .../OrganizationNavbar.module.css | 27 + .../OrganizationNavbar.test.tsx | 236 + .../OrganizationNavbar/OrganizationNavbar.tsx | 252 + .../OrganizationSidebar.module.css | 76 + .../OrganizationSidebar.test.tsx | 174 + .../OrganizationSidebar.tsx | 157 + .../PeopleCard/PeopleCard.module.css | 22 + .../UserPortal/PeopleCard/PeopleCard.test.tsx | 67 + .../UserPortal/PeopleCard/PeopleCard.tsx | 31 + .../UserPortal/PostCard/PostCard.module.css | 55 + .../UserPortal/PostCard/PostCard.test.tsx | 419 + .../UserPortal/PostCard/PostCard.tsx | 291 + .../PromotedPost/PromotedPost.module.css | 56 + .../PromotedPost/PromotedPost.test.tsx | 127 + .../UserPortal/PromotedPost/PromotedPost.tsx | 32 + .../UserPortal/Register/Register.module.css | 15 + .../UserPortal/Register/Register.test.tsx | 267 + .../UserPortal/Register/Register.tsx | 221 + .../SecuredRouteForUser.test.tsx | 54 + .../SecuredRouteForUser.tsx | 15 + .../UserPortal/TaskCard/TaskCard.module.css | 41 + .../UserPortal/TaskCard/TaskCard.test.tsx | 95 + .../UserPortal/TaskCard/TaskCard.tsx | 131 + .../UserNavbar/UserNavbar.module.css | 26 + .../UserPortal/UserNavbar/UserNavbar.test.tsx | 177 + .../UserPortal/UserNavbar/UserNavbar.tsx | 119 + .../UserSidebar/UserSidebar.module.css | 71 + .../UserSidebar/UserSidebar.test.tsx | 252 + .../UserPortal/UserSidebar/UserSidebar.tsx | 123 + .../UserUpdate/UserUpdate.module.css | 93 + src/components/UserUpdate/UserUpdate.test.tsx | 159 + src/components/UserUpdate/UserUpdate.tsx | 257 + .../UsersTableItem/UserTableItem.test.tsx | 1054 + .../UsersTableItem/UserTableItemMocks.ts | 59 + .../UsersTableItem/UsersTableItem.module.css | 26 + .../UsersTableItem/UsersTableItem.tsx | 598 + .../DummyPlugin/DummyPlugin.module.css | 0 .../plugins/DummyPlugin/DummyPlugin.test.jsx | 30 + .../plugins/DummyPlugin/DummyPlugin.tsx | 17 + .../DummyPlugin2/DummyPlugin2.module.css | 0 .../DummyPlugin2/DummyPlugin2.test.jsx | 19 + .../plugins/DummyPlugin2/DummyPlugin2.tsx | 12 + src/components/plugins/index.ts | 4 + src/index.css | 13 - src/index.tsx | 113 +- src/reportWebVitals.ts | 2 +- src/screens/BlockUser/BlockUser.module.css | 102 + src/screens/BlockUser/BlockUser.test.tsx | 612 + src/screens/BlockUser/BlockUser.tsx | 295 + .../EventDashboard/EventDashboard.mocks.ts | 227 + .../EventDashboard/EventDashboard.module.css | 198 + .../EventDashboard/EventDashboard.test.tsx | 192 + src/screens/EventDashboard/EventDashboard.tsx | 252 + .../ForgotPassword/ForgotPassword.module.css | 71 + .../ForgotPassword/ForgotPassword.test.tsx | 259 + src/screens/ForgotPassword/ForgotPassword.tsx | 247 + src/screens/LoginPage/LoginPage.module.css | 188 + src/screens/LoginPage/LoginPage.test.tsx | 582 + src/screens/LoginPage/LoginPage.tsx | 564 + .../MemberDetail/MemberDetail.module.css | 446 + .../MemberDetail/MemberDetail.test.tsx | 309 + src/screens/MemberDetail/MemberDetail.tsx | 324 + .../OrgContribution.module.css | 258 + .../OrgContribution/OrgContribution.test.tsx | 47 + .../OrgContribution/OrgContribution.tsx | 74 + src/screens/OrgList/OrgList.module.css | 350 + src/screens/OrgList/OrgList.test.tsx | 202 + src/screens/OrgList/OrgList.tsx | 648 + src/screens/OrgList/OrgListMocks.ts | 163 + src/screens/OrgPost/OrgPost.module.css | 323 + src/screens/OrgPost/OrgPost.test.tsx | 548 + src/screens/OrgPost/OrgPost.tsx | 502 + .../OrgSettings/OrgSettings.module.css | 25 + src/screens/OrgSettings/OrgSettings.test.tsx | 121 + src/screens/OrgSettings/OrgSettings.tsx | 58 + .../OrganizationDashboard.module.css | 24 + .../OrganizationDashboard.test.tsx | 150 + .../OrganizationDashboard.tsx | 349 + .../OrganizationDashboardMocks.ts | 282 + .../OrganizationEvents.module.css | 312 + .../OrganizationEvents.test.tsx | 430 + .../OrganizationEvents/OrganizationEvents.tsx | 363 + src/screens/OrganizationEvents/calendar.css | 146 + .../OrganizationPeople.module.css | 282 + .../OrganizationPeople.test.tsx | 1033 + .../OrganizationPeople/OrganizationPeople.tsx | 419 + .../PageNotFound/PageNotFound.module.css | 109 + .../PageNotFound/PageNotFound.test.tsx | 30 + src/screens/PageNotFound/PageNotFound.tsx | 34 + src/screens/Requests/Requests.module.css | 95 + src/screens/Requests/Requests.test.tsx | 169 + src/screens/Requests/Requests.tsx | 380 + src/screens/Requests/RequestsMocks.ts | 220 + src/screens/UserPortal/Chat/Chat.module.css | 63 + src/screens/UserPortal/Chat/Chat.test.tsx | 173 + src/screens/UserPortal/Chat/Chat.tsx | 142 + .../UserPortal/Donate/Donate.module.css | 56 + src/screens/UserPortal/Donate/Donate.test.tsx | 183 + src/screens/UserPortal/Donate/Donate.tsx | 202 + .../UserPortal/Events/Events.module.css | 83 + src/screens/UserPortal/Events/Events.test.tsx | 473 + src/screens/UserPortal/Events/Events.tsx | 485 + src/screens/UserPortal/Home/Home.module.css | 71 + src/screens/UserPortal/Home/Home.test.tsx | 285 + src/screens/UserPortal/Home/Home.tsx | 291 + .../Organizations/Organizations.module.css | 48 + .../Organizations/Organizations.test.tsx | 221 + .../Organizations/Organizations.tsx | 221 + .../UserPortal/People/People.module.css | 48 + src/screens/UserPortal/People/People.test.tsx | 206 + src/screens/UserPortal/People/People.tsx | 217 + .../UserPortal/Settings/Settings.module.css | 26 + .../UserPortal/Settings/Settings.test.tsx | 139 + src/screens/UserPortal/Settings/Settings.tsx | 144 + src/screens/UserPortal/Tasks/Tasks.module.css | 48 + src/screens/UserPortal/Tasks/Tasks.test.tsx | 130 + src/screens/UserPortal/Tasks/Tasks.tsx | 173 + .../UserLoginPage/UserLoginPage.module.css | 48 + .../UserLoginPage/UserLoginPage.test.tsx | 39 + .../UserLoginPage/UserLoginPage.tsx | 49 + src/screens/Users/Users.module.css | 95 + src/screens/Users/Users.test.tsx | 216 + src/screens/Users/Users.tsx | 350 + src/screens/Users/UsersMocks.ts | 216 + src/setupTests.ts | 35 + src/state/action-creators/index.test.ts | 47 + src/state/action-creators/index.ts | 35 + src/state/helpers/Action.test.ts | 8 + src/state/helpers/Action.ts | 4 + src/state/index.ts | 1 + src/state/reducers/index.ts | 10 + src/state/reducers/pluginReducer.test.ts | 102 + src/state/reducers/pluginReducer.ts | 43 + src/state/reducers/routesReducer.test.ts | 228 + src/state/reducers/routesReducer.ts | 117 + src/state/store.test.tsx | 28 + src/state/store.ts | 5 + src/utils/StaticMockLink.ts | 174 + src/utils/convertToBase64.test.ts | 33 + src/utils/convertToBase64.ts | 15 + src/utils/debounce.ts | 9 + src/utils/errorHandler.test.tsx | 34 + src/utils/errorHandler.tsx | 17 + src/utils/getOrganizationId.ts | 8 + src/utils/getRefreshToken.test.ts | 52 + src/utils/getRefreshToken.ts | 31 + src/utils/i18n.ts | 25 + src/utils/i18nForTest.ts | 28 + src/utils/interfaces.ts | 167 + src/utils/languages.ts | 31 + talawa-admin-docs/.nojekyll | 1 + talawa-admin-docs/README.md | 40 + ..._support_services_Plugin_helper.default.md | 71 + ..._support_services_Render_helper.default.md | 17 + ..._CheckIn_types.InterfaceAttendeeCheckIn.md | 43 + ...In_types.InterfaceAttendeeQueryResponse.md | 28 + ...onents_CheckIn_types.InterfaceModalProp.md | 51 + ...nts_CheckIn_types.InterfaceTableCheckIn.md | 65 + ...onents_CheckIn_types.InterfaceTableData.md | 43 + .../components_CheckIn_types.InterfaceUser.md | 43 + ...leDropdown.InterfaceCollapsibleDropdown.md | 32 + ...nt_IconComponent.InterfaceIconComponent.md | 54 + ..._LeftDrawerOrg.InterfaceLeftDrawerProps.md | 65 + ...wer_LeftDrawer.InterfaceLeftDrawerProps.md | 43 + ...d_OrgListCard.InterfaceOrgListCardProps.md | 21 + ...Screen.InterfaceOrganizationScreenProps.md | 43 + ...inScreen.InterfaceSuperAdminScreenProps.md | 43 + talawa-admin-docs/modules.md | 181 + .../modules/components_AddOn_AddOn.default.md | 48 + .../modules/components_AddOn_AddOn.md | 33 + .../modules/components_AddOn_AddOn_test.md | 3 + ...ddOn_core_AddOnEntry_AddOnEntry.default.md | 52 + ...onents_AddOn_core_AddOnEntry_AddOnEntry.md | 33 + ...s_AddOn_core_AddOnEntry_AddOnEntry_test.md | 3 + ...ore_AddOnRegister_AddOnRegister.default.md | 44 + ..._AddOn_core_AddOnRegister_AddOnRegister.md | 33 + ...n_core_AddOnRegister_AddOnRegister_test.md | 3 + ...ddOn_core_AddOnStore_AddOnStore.default.md | 32 + ...onents_AddOn_core_AddOnStore_AddOnStore.md | 27 + ...s_AddOn_core_AddOnStore_AddOnStore_test.md | 3 + ..._AddOn_support_components_Action_Action.md | 29 + ...n_support_components_Action_Action_test.md | 3 + ...port_components_MainContent_MainContent.md | 29 + ...components_MainContent_MainContent_test.md | 3 + ..._support_components_SidePanel_SidePanel.md | 29 + ...ort_components_SidePanel_SidePanel_test.md | 3 + ...ts_AddOn_support_services_Plugin_helper.md | 9 + ...ts_AddOn_support_services_Render_helper.md | 9 + ...LanguageDropdown_ChangeLanguageDropDown.md | 50 + ...ageDropdown_ChangeLanguageDropdown_test.md | 3 + .../components_CheckIn_CheckInModal.md | 29 + .../components_CheckIn_CheckInModal_test.md | 3 + .../components_CheckIn_CheckInWrapper.md | 29 + .../components_CheckIn_CheckInWrapper_test.md | 3 + .../modules/components_CheckIn_TableRow.md | 31 + .../components_CheckIn_TableRow_test.md | 3 + .../modules/components_CheckIn_mocks.md | 41 + .../modules/components_CheckIn_tagTemplate.md | 19 + .../modules/components_CheckIn_types.md | 14 + ...CollapsibleDropdown_CollapsibleDropdown.md | 33 + ...psibleDropdown_CollapsibleDropdown_test.md | 3 + .../components_ContriStats_ContriStats.md | 29 + ...components_ContriStats_ContriStats_test.md | 3 + .../components_EventCalendar_EventCalendar.md | 30 + ...onents_EventCalendar_EventCalendar_test.md | 3 + .../components_EventListCard_EventListCard.md | 29 + ...onents_EventListCard_EventListCard_test.md | 3 + ...EventProjectModals_AddEventProjectModal.md | 29 + ...ProjectModals_AddEventProjectModal_test.md | 3 + ...ntProjectModals_DeleteEventProjectModal.md | 29 + ...jectModals_DeleteEventProjectModal_test.md | 3 + ...ntProjectModals_UpdateEventProjectModal.md | 29 + ...jectModals_UpdateEventProjectModal_test.md | 3 + ...tRegistrantsModal_EventRegistrantsModal.md | 29 + ...strantsModal_EventRegistrantsModal_test.md | 3 + ...egistrantsModal_EventRegistrantsWrapper.md | 29 + ...rantsModal_EventRegistrantsWrapper_test.md | 3 + .../components_IconComponent_IconComponent.md | 33 + ...onents_IconComponent_IconComponent_test.md | 3 + .../components_LandingPage_LandingPage.md | 23 + ...components_LandingPage_LandingPage_test.md | 3 + .../components_LeftDrawerOrg_LeftDrawerOrg.md | 33 + ...onents_LeftDrawerOrg_LeftDrawerOrg_test.md | 3 + .../components_LeftDrawer_LeftDrawer.md | 33 + .../components_LeftDrawer_LeftDrawer_test.md | 3 + .../modules/components_Loader_Loader.md | 23 + .../modules/components_Loader_Loader_test.md | 3 + ...nts_MemberRequestCard_MemberRequestCard.md | 29 + ...emberRequestCard_MemberRequestCard_test.md | 3 + .../modules/components_NotFound_NotFound.md | 29 + .../components_NotFound_NotFound_test.md | 3 + ...nents_OrgAdminListCard_OrgAdminListCard.md | 29 + ..._OrgAdminListCard_OrgAdminListCard_test.md | 3 + ...omponents_OrgContriCards_OrgContriCards.md | 29 + ...ents_OrgContriCards_OrgContriCards_test.md | 3 + .../modules/components_OrgDelete_OrgDelete.md | 23 + .../components_OrgDelete_OrgDelete_test.md | 3 + .../components_OrgListCard_OrgListCard.md | 33 + ...components_OrgListCard_OrgListCard_test.md | 3 + ...nts_OrgPeopleListCard_OrgPeopleListCard.md | 29 + ...rgPeopleListCard_OrgPeopleListCard_test.md | 3 + .../components_OrgPostCard_OrgPostCard.md | 29 + ...components_OrgPostCard_OrgPostCard_test.md | 3 + .../modules/components_OrgUpdate_OrgUpdate.md | 29 + .../components_OrgUpdate_OrgUpdate_test.md | 3 + ...nizationCardStart_OrganizationCardStart.md | 29 + ...ionCardStart_OrganizationCardStart_test.md | 3 + ...nents_OrganizationCard_OrganizationCard.md | 29 + ..._OrganizationCard_OrganizationCard_test.md | 3 + ...s_OrganizationScreen_OrganizationScreen.md | 33 + ...anizationScreen_OrganizationScreen_test.md | 3 + ...omponents_PaginationList_PaginationList.md | 29 + .../components_Pagination_Pagination.md | 29 + .../components_Pagination_Pagination_test.md | 3 + .../components_SecuredRoute_SecuredRoute.md | 29 + ...nents_SuperAdminScreen_SuperAdminScreen.md | 33 + ..._SuperAdminScreen_SuperAdminScreen_test.md | 3 + .../components_TableLoader_TableLoader.md | 29 + ...components_TableLoader_TableLoader_test.md | 3 + .../components_TaskListItem_TaskListItem.md | 29 + ...mponents_TaskListItem_TaskListItem_test.md | 3 + .../components_TaskModals_AddTaskModal.md | 29 + ...components_TaskModals_AddTaskModal_test.md | 3 + .../components_TaskModals_DeleteTaskModal.md | 29 + ...ponents_TaskModals_DeleteTaskModal_test.md | 3 + ...ponents_TaskModals_ManageVolunteerModal.md | 29 + ...ts_TaskModals_ManageVolunteerModal_test.md | 3 + .../components_TaskModals_UpdateTaskModal.md | 55 + ...ponents_TaskModals_UpdateTaskModal_test.md | 3 + .../components_UserListCard_UserListCard.md | 29 + ...mponents_UserListCard_UserListCard_test.md | 3 + ...s_UserPasswordUpdate_UserPasswordUpdate.md | 30 + ...rPasswordUpdate_UserPasswordUpdate_test.md | 3 + ...ts_UserPortal_DonationCard_DonationCard.md | 29 + .../components_UserPortal_Login_Login.md | 29 + .../components_UserPortal_Login_Login_test.md | 3 + ...ortal_OrganizationCard_OrganizationCard.md | 29 + ..._OrganizationCard_OrganizationCard_test.md | 3 + ...l_OrganizationNavbar_OrganizationNavbar.md | 29 + ...anizationNavbar_OrganizationNavbar_test.md | 3 + ...OrganizationSidebar_OrganizationSidebar.md | 23 + ...izationSidebar_OrganizationSidebar_test.md | 3 + ...onents_UserPortal_PeopleCard_PeopleCard.md | 29 + ...s_UserPortal_PeopleCard_PeopleCard_test.md | 3 + ...components_UserPortal_PostCard_PostCard.md | 29 + ...nents_UserPortal_PostCard_PostCard_test.md | 3 + ...components_UserPortal_Register_Register.md | 29 + ...nents_UserPortal_Register_Register_test.md | 3 + ...SecuredRouteForUser_SecuredRouteForUser.md | 29 + ...onents_UserPortal_UserNavbar_UserNavbar.md | 23 + ...s_UserPortal_UserNavbar_UserNavbar_test.md | 3 + ...ents_UserPortal_UserSidebar_UserSidebar.md | 23 + ...UserPortal_UserSidebar_UserSidebar_test.md | 3 + .../components_UserUpdate_UserUpdate.md | 30 + .../components_UserUpdate_UserUpdate_test.md | 3 + .../modules/components_plugins.md | 22 + ...ugins_DummyPlugin2_DummyPlugin2.default.md | 32 + ...nents_plugins_DummyPlugin2_DummyPlugin2.md | 27 + ..._plugins_DummyPlugin2_DummyPlugin2_test.md | 3 + ...plugins_DummyPlugin_DummyPlugin.default.md | 32 + ...ponents_plugins_DummyPlugin_DummyPlugin.md | 27 + ...ts_plugins_DummyPlugin_DummyPlugin_test.md | 3 + .../modules/screens_BlockUser_BlockUser.md | 23 + .../screens_BlockUser_BlockUser_test.md | 3 + .../screens_EventDashboard_EventDashboard.md | 23 + ...ens_EventDashboard_EventDashboard_mocks.md | 52 + ...eens_EventDashboard_EventDashboard_test.md | 3 + .../screens_ForgotPassword_ForgotPassword.md | 23 + ...eens_ForgotPassword_ForgotPassword_test.md | 3 + .../modules/screens_LoginPage_LoginPage.md | 23 + .../screens_LoginPage_LoginPage_test.md | 3 + .../screens_MemberDetail_MemberDetail.md | 72 + .../screens_MemberDetail_MemberDetail_test.md | 3 + ...screens_OrgContribution_OrgContribution.md | 23 + ...ns_OrgContribution_OrgContribution_test.md | 3 + .../modules/screens_OrgList_OrgList.md | 23 + .../modules/screens_OrgList_OrgListMocks.md | 41 + .../modules/screens_OrgList_OrgList_test.md | 3 + .../modules/screens_OrgPost_OrgPost.md | 23 + .../modules/screens_OrgPost_OrgPost_test.md | 3 + .../screens_OrgSettings_OrgSettings.md | 23 + .../screens_OrgSettings_OrgSettings_test.md | 3 + ...nizationDashboard_OrganizationDashboard.md | 23 + ...ionDashboard_OrganizationDashboardMocks.md | 41 + ...ionDashboard_OrganizationDashboard_test.md | 3 + ...s_OrganizationEvents_OrganizationEvents.md | 23 + ...anizationEvents_OrganizationEvents_test.md | 3 + ...s_OrganizationPeople_OrganizationPeople.md | 23 + ...anizationPeople_OrganizationPeople_test.md | 3 + .../screens_PageNotFound_PageNotFound.md | 23 + .../screens_PageNotFound_PageNotFound_test.md | 3 + .../modules/screens_Requests_Requests.md | 23 + .../modules/screens_Requests_Requests_test.md | 3 + .../screens_UserPortal_Donate_Donate.md | 23 + .../screens_UserPortal_Donate_Donate_test.md | 3 + .../modules/screens_UserPortal_Home_Home.md | 23 + .../screens_UserPortal_Home_Home_test.md | 3 + ..._UserPortal_Organizations_Organizations.md | 23 + ...Portal_Organizations_Organizations_test.md | 3 + .../screens_UserPortal_People_People.md | 23 + .../screens_UserPortal_People_People_test.md | 3 + .../screens_UserPortal_Settings_Settings.md | 23 + ...reens_UserPortal_Settings_Settings_test.md | 3 + ..._UserPortal_UserLoginPage_UserLoginPage.md | 23 + ...Portal_UserLoginPage_UserLoginPage_test.md | 3 + .../modules/screens_Users_Users.md | 23 + .../modules/screens_Users_Users_test.md | 3 + tsconfig.json | 3 +- yarn.lock | 11845 -------- 677 files changed, 94973 insertions(+), 12334 deletions(-) create mode 100644 .env.example rename .github/ISSUE_TEMPLATE/{bug_report.md => bug-report.md} (60%) rename .github/ISSUE_TEMPLATE/{feature_request.md => feature-request.md} (69%) create mode 100644 .github/workflows/README.md create mode 100644 .github/workflows/authorized-changes-detection.yml delete mode 100644 .github/workflows/ci.yml delete mode 100644 .github/workflows/codeql-analysis.yml create mode 100644 .github/workflows/codeql-codescan.yml create mode 100755 .github/workflows/countline.py delete mode 100644 .github/workflows/linter.yml delete mode 100644 .github/workflows/npm-publish.yml create mode 100644 .github/workflows/pull-request-target.yml create mode 100644 .github/workflows/pull-requests.yml create mode 100644 .github/workflows/push.yml create mode 100644 .github/workflows/stale.yml create mode 100755 .husky/post-merge create mode 100755 .husky/pre-commit create mode 100644 CODEOWNERS create mode 100644 CODE_STYLE.md create mode 100644 DOCUMENTATION.md delete mode 100644 Docker_Container/.dockerignore delete mode 100644 Docker_Container/README.md delete mode 100644 Docker_Container/docker-compose.yml delete mode 100644 Docker_Container/dockerfile create mode 100644 INSTALLATION.md create mode 100644 ISSUE_GUIDELINES.md delete mode 100644 ISSUE_TEMPLATE.md delete mode 100644 PR-guidelines.md create mode 100644 PR_GUIDELINES.md delete mode 100644 PULL_REQUEST_TEMPLATE.md delete mode 100644 issue-guidelines.md create mode 100644 jest-preview.config.ts create mode 100644 jest.config.js create mode 100644 package-lock.json create mode 100644 public/favicon_palisadoes.ico create mode 100644 public/images/REACT_SITE_KEY.webp create mode 100644 public/images/jest-preview.webp rename public/{ => images}/logo512.png (100%) create mode 100644 public/locales/en.json create mode 100644 public/locales/fr.json create mode 100644 public/locales/hi.json create mode 100644 public/locales/sp.json create mode 100644 public/locales/zh.json delete mode 100644 public/logo192.png create mode 100644 schema.graphql create mode 100644 scripts/custom-test-env.js create mode 100644 scripts/test.js create mode 100644 src/Constant/constant.spec.ts create mode 100644 src/Constant/constant.ts create mode 100644 src/GraphQl/Mutations/mutations.ts create mode 100644 src/GraphQl/Queries/Queries.ts create mode 100644 src/assets/css/app.css create mode 100644 src/assets/images/blank.png create mode 100644 src/assets/images/defaultImg.png create mode 100644 src/assets/images/palisadoes_logo.png create mode 100644 src/assets/images/talawa-logo-200x200.png rename src/assets/{ => images}/talawa-logo-dark-200x200.png (100%) create mode 100644 src/assets/images/talawa-logo-lite-200x200.png rename src/{App.css => assets/scss/_colors.scss} (100%) create mode 100644 src/assets/scss/_general.scss create mode 100644 src/assets/scss/_talawa.scss create mode 100644 src/assets/scss/_utilities.scss create mode 100644 src/assets/scss/_variables.scss create mode 100644 src/assets/scss/app.scss create mode 100644 src/assets/scss/components/_accordion.scss create mode 100644 src/assets/scss/components/_alert.scss create mode 100644 src/assets/scss/components/_badge.scss create mode 100644 src/assets/scss/components/_breadcrumb.scss create mode 100644 src/assets/scss/components/_buttons.scss create mode 100644 src/assets/scss/components/_card.scss create mode 100644 src/assets/scss/components/_carousel.scss create mode 100644 src/assets/scss/components/_close.scss create mode 100644 src/assets/scss/components/_dropdown.scss create mode 100644 src/assets/scss/components/_list-group.scss create mode 100644 src/assets/scss/components/_modal.scss create mode 100644 src/assets/scss/components/_nav.scss create mode 100644 src/assets/scss/components/_navbar.scss create mode 100644 src/assets/scss/components/_offcanvas.scss create mode 100644 src/assets/scss/components/_pagination.scss create mode 100644 src/assets/scss/components/_placeholder.scss create mode 100644 src/assets/scss/components/_progress.scss create mode 100644 src/assets/scss/components/_spinners.scss create mode 100644 src/assets/scss/content/_table.scss create mode 100644 src/assets/scss/content/_typography.scss create mode 100644 src/assets/scss/forms/_check-radios.scss create mode 100644 src/assets/scss/forms/_floating-label.scss create mode 100644 src/assets/scss/forms/_form-control.scss create mode 100644 src/assets/scss/forms/_input-group.scss create mode 100644 src/assets/scss/forms/_range.scss create mode 100644 src/assets/scss/forms/_select.scss create mode 100644 src/assets/scss/forms/_validation.scss create mode 100644 src/assets/svgs/addEventProject.svg create mode 100644 src/assets/svgs/admin.svg create mode 100644 src/assets/svgs/angleRight.svg create mode 100644 src/assets/svgs/blockUser.svg create mode 100644 src/assets/svgs/blockedUser.svg create mode 100644 src/assets/svgs/checkInRegistrants.svg create mode 100644 src/assets/svgs/dashboard.svg create mode 100644 src/assets/svgs/date.svg create mode 100644 src/assets/svgs/event.svg create mode 100644 src/assets/svgs/eventStats.svg create mode 100644 src/assets/svgs/events.svg create mode 100644 src/assets/svgs/flask.svg create mode 100644 src/assets/svgs/key.svg create mode 100644 src/assets/svgs/listEventRegistrants.svg create mode 100644 src/assets/svgs/location.svg create mode 100644 src/assets/svgs/logout.svg create mode 100644 src/assets/svgs/organizations.svg create mode 100644 src/assets/svgs/palisadoes.svg create mode 100644 src/assets/svgs/people.svg create mode 100644 src/assets/svgs/plugins.svg create mode 100644 src/assets/svgs/post.svg create mode 100644 src/assets/svgs/posts.svg create mode 100644 src/assets/svgs/requests.svg create mode 100644 src/assets/svgs/roles.svg create mode 100644 src/assets/svgs/settings.svg create mode 100644 src/assets/svgs/tags.svg create mode 100644 src/assets/svgs/talawa.svg create mode 100644 src/assets/svgs/user.svg create mode 100644 src/assets/svgs/users.svg delete mode 100644 src/assets/talawa-logo-lite-200x200.png create mode 100644 src/components/AddOn/AddOn.module.css create mode 100644 src/components/AddOn/AddOn.test.tsx create mode 100644 src/components/AddOn/AddOn.tsx create mode 100644 src/components/AddOn/core/AddOnEntry/AddOnEntry.module.css create mode 100644 src/components/AddOn/core/AddOnEntry/AddOnEntry.test.tsx create mode 100644 src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx create mode 100644 src/components/AddOn/core/AddOnRegister/AddOnRegister.module.css create mode 100644 src/components/AddOn/core/AddOnRegister/AddOnRegister.test.tsx create mode 100644 src/components/AddOn/core/AddOnRegister/AddOnRegister.tsx create mode 100644 src/components/AddOn/core/AddOnStore/AddOnStore.module.css create mode 100644 src/components/AddOn/core/AddOnStore/AddOnStore.test.tsx create mode 100644 src/components/AddOn/core/AddOnStore/AddOnStore.tsx create mode 100644 src/components/AddOn/support/components/Action/Action.module.css create mode 100644 src/components/AddOn/support/components/Action/Action.test.tsx create mode 100644 src/components/AddOn/support/components/Action/Action.tsx create mode 100644 src/components/AddOn/support/components/MainContent/MainContent.module.css create mode 100644 src/components/AddOn/support/components/MainContent/MainContent.test.tsx create mode 100644 src/components/AddOn/support/components/MainContent/MainContent.tsx create mode 100644 src/components/AddOn/support/components/SidePanel/SidePanel.module.css create mode 100644 src/components/AddOn/support/components/SidePanel/SidePanel.test.tsx create mode 100644 src/components/AddOn/support/components/SidePanel/SidePanel.tsx create mode 100644 src/components/AddOn/support/services/Plugin.helper.test.ts create mode 100644 src/components/AddOn/support/services/Plugin.helper.ts create mode 100644 src/components/AddOn/support/services/Render.helper.ts create mode 100644 src/components/Advertisements/Advertisements.module.css create mode 100644 src/components/Advertisements/Advertisements.test.tsx create mode 100644 src/components/Advertisements/Advertisements.tsx create mode 100644 src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.module.css create mode 100644 src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.test.tsx create mode 100644 src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.tsx create mode 100644 src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.module.css create mode 100644 src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.test.tsx create mode 100644 src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.tsx create mode 100644 src/components/ChangeLanguageDropdown/ChangeLanguageDropDown.tsx create mode 100644 src/components/ChangeLanguageDropdown/ChangeLanguageDropdown.test.tsx create mode 100644 src/components/CheckIn/CheckInModal.module.css create mode 100644 src/components/CheckIn/CheckInModal.test.tsx create mode 100644 src/components/CheckIn/CheckInModal.tsx create mode 100644 src/components/CheckIn/CheckInWrapper.module.css create mode 100644 src/components/CheckIn/CheckInWrapper.test.tsx create mode 100644 src/components/CheckIn/CheckInWrapper.tsx create mode 100644 src/components/CheckIn/TableRow.test.tsx create mode 100644 src/components/CheckIn/TableRow.tsx create mode 100644 src/components/CheckIn/mocks.ts create mode 100644 src/components/CheckIn/tagTemplate.ts create mode 100644 src/components/CheckIn/types.ts create mode 100644 src/components/CollapsibleDropdown/CollapsibleDropdown.module.css create mode 100644 src/components/CollapsibleDropdown/CollapsibleDropdown.test.tsx create mode 100644 src/components/CollapsibleDropdown/CollapsibleDropdown.tsx create mode 100644 src/components/ContriStats/ContriStats.module.css create mode 100644 src/components/ContriStats/ContriStats.test.tsx create mode 100644 src/components/ContriStats/ContriStats.tsx create mode 100644 src/components/DeleteOrg/DeleteOrg.module.css create mode 100644 src/components/DeleteOrg/DeleteOrg.test.tsx create mode 100644 src/components/DeleteOrg/DeleteOrg.tsx create mode 100644 src/components/EventCalendar/EventCalendar.module.css create mode 100644 src/components/EventCalendar/EventCalendar.test.tsx create mode 100644 src/components/EventCalendar/EventCalendar.tsx create mode 100644 src/components/EventListCard/EventListCard.module.css create mode 100644 src/components/EventListCard/EventListCard.test.tsx create mode 100644 src/components/EventListCard/EventListCard.tsx create mode 100644 src/components/EventProjectModals/AddEventProjectModal.test.tsx create mode 100644 src/components/EventProjectModals/AddEventProjectModal.tsx create mode 100644 src/components/EventProjectModals/DeleteEventProjectModal.test.tsx create mode 100644 src/components/EventProjectModals/DeleteEventProjectModal.tsx create mode 100644 src/components/EventProjectModals/UpdateEventProjectModal.test.tsx create mode 100644 src/components/EventProjectModals/UpdateEventProjectModal.tsx create mode 100644 src/components/EventRegistrantsModal/EventRegistrantsModal.module.css create mode 100644 src/components/EventRegistrantsModal/EventRegistrantsModal.test.tsx create mode 100644 src/components/EventRegistrantsModal/EventRegistrantsModal.tsx create mode 100644 src/components/EventRegistrantsModal/EventRegistrantsWrapper.module.css create mode 100644 src/components/EventRegistrantsModal/EventRegistrantsWrapper.test.tsx create mode 100644 src/components/EventRegistrantsModal/EventRegistrantsWrapper.tsx create mode 100644 src/components/EventStats/EventStats.test.tsx create mode 100644 src/components/EventStats/EventStats.tsx create mode 100644 src/components/EventStats/EventStatsWrapper.module.css create mode 100644 src/components/EventStats/EventStatsWrapper.test.tsx create mode 100644 src/components/EventStats/EventStatsWrapper.tsx create mode 100644 src/components/EventStats/Loader.module.css create mode 100644 src/components/EventStats/Statistics/AverageRating.test.tsx create mode 100644 src/components/EventStats/Statistics/AverageRating.tsx create mode 100644 src/components/EventStats/Statistics/Feedback.test.tsx create mode 100644 src/components/EventStats/Statistics/Feedback.tsx create mode 100644 src/components/EventStats/Statistics/Review.test.tsx create mode 100644 src/components/EventStats/Statistics/Review.tsx create mode 100644 src/components/IconComponent/IconComponent.test.tsx create mode 100644 src/components/IconComponent/IconComponent.tsx create mode 100644 src/components/LeftDrawer/LeftDrawer.module.css create mode 100644 src/components/LeftDrawer/LeftDrawer.test.tsx create mode 100644 src/components/LeftDrawer/LeftDrawer.tsx create mode 100644 src/components/LeftDrawerEvent/LeftDrawerEvent.module.css create mode 100644 src/components/LeftDrawerEvent/LeftDrawerEvent.test.tsx create mode 100644 src/components/LeftDrawerEvent/LeftDrawerEvent.tsx create mode 100644 src/components/LeftDrawerEvent/LeftDrawerEventWrapper.module.css create mode 100644 src/components/LeftDrawerEvent/LeftDrawerEventWrapper.test.tsx create mode 100644 src/components/LeftDrawerEvent/LeftDrawerEventWrapper.tsx create mode 100644 src/components/LeftDrawerOrg/LeftDrawerOrg.module.css create mode 100644 src/components/LeftDrawerOrg/LeftDrawerOrg.test.tsx create mode 100644 src/components/LeftDrawerOrg/LeftDrawerOrg.tsx create mode 100644 src/components/Loader/Loader.module.css create mode 100644 src/components/Loader/Loader.test.tsx create mode 100644 src/components/Loader/Loader.tsx create mode 100644 src/components/MemberRequestCard/MemberRequestCard.module.css create mode 100644 src/components/MemberRequestCard/MemberRequestCard.test.tsx create mode 100644 src/components/MemberRequestCard/MemberRequestCard.tsx create mode 100644 src/components/NotFound/NotFound.module.css create mode 100644 src/components/NotFound/NotFound.test.tsx create mode 100644 src/components/NotFound/NotFound.tsx create mode 100644 src/components/OrgAdminListCard/OrgAdminListCard.module.css create mode 100644 src/components/OrgAdminListCard/OrgAdminListCard.test.tsx create mode 100644 src/components/OrgAdminListCard/OrgAdminListCard.tsx create mode 100644 src/components/OrgContriCards/OrgContriCards.module.css create mode 100644 src/components/OrgContriCards/OrgContriCards.test.tsx create mode 100644 src/components/OrgContriCards/OrgContriCards.tsx create mode 100644 src/components/OrgDelete/OrgDelete.test.tsx create mode 100644 src/components/OrgDelete/OrgDelete.tsx create mode 100644 src/components/OrgListCard/OrgListCard.module.css create mode 100644 src/components/OrgListCard/OrgListCard.test.tsx create mode 100644 src/components/OrgListCard/OrgListCard.tsx create mode 100644 src/components/OrgPeopleListCard/OrgPeopleListCard.module.css create mode 100644 src/components/OrgPeopleListCard/OrgPeopleListCard.test.tsx create mode 100644 src/components/OrgPeopleListCard/OrgPeopleListCard.tsx create mode 100644 src/components/OrgPostCard/OrgPostCard.module.css create mode 100644 src/components/OrgPostCard/OrgPostCard.test.tsx create mode 100644 src/components/OrgPostCard/OrgPostCard.tsx create mode 100644 src/components/OrgUpdate/OrgUpdate.module.css create mode 100644 src/components/OrgUpdate/OrgUpdate.test.tsx create mode 100644 src/components/OrgUpdate/OrgUpdate.tsx create mode 100644 src/components/OrgUpdate/OrgUpdateMocks.ts create mode 100644 src/components/OrganizationCard/OrganizationCard.module.css create mode 100644 src/components/OrganizationCard/OrganizationCard.test.tsx create mode 100644 src/components/OrganizationCard/OrganizationCard.tsx create mode 100644 src/components/OrganizationCardStart/OrganizationCardStart.module.css create mode 100644 src/components/OrganizationCardStart/OrganizationCardStart.test.tsx create mode 100644 src/components/OrganizationCardStart/OrganizationCardStart.tsx create mode 100644 src/components/OrganizationDashCards/CardItem.module.css create mode 100644 src/components/OrganizationDashCards/CardItem.test.tsx create mode 100644 src/components/OrganizationDashCards/CardItem.tsx create mode 100644 src/components/OrganizationDashCards/CardItemLoading.tsx create mode 100644 src/components/OrganizationDashCards/DashboardCard.test.tsx create mode 100644 src/components/OrganizationDashCards/DashboardCard.tsx create mode 100644 src/components/OrganizationDashCards/DashboardCardLoading.tsx create mode 100644 src/components/OrganizationDashCards/Dashboardcard.module.css create mode 100644 src/components/OrganizationScreen/OrganizationScreen.module.css create mode 100644 src/components/OrganizationScreen/OrganizationScreen.test.tsx create mode 100644 src/components/OrganizationScreen/OrganizationScreen.tsx create mode 100644 src/components/Pagination/Pagination.test.tsx create mode 100644 src/components/Pagination/Pagination.tsx create mode 100644 src/components/PaginationList/PaginationList.css create mode 100644 src/components/PaginationList/PaginationList.tsx create mode 100644 src/components/SecuredRoute/SecuredRoute.tsx create mode 100644 src/components/SuperAdminScreen/SuperAdminScreen.module.css create mode 100644 src/components/SuperAdminScreen/SuperAdminScreen.test.tsx create mode 100644 src/components/SuperAdminScreen/SuperAdminScreen.tsx create mode 100644 src/components/TableLoader/TableLoader.module.css create mode 100644 src/components/TableLoader/TableLoader.test.tsx create mode 100644 src/components/TableLoader/TableLoader.tsx create mode 100644 src/components/TaskListItem/TaskListItem.test.tsx create mode 100644 src/components/TaskListItem/TaskListItem.tsx create mode 100644 src/components/TaskModals/AddTaskModal.test.tsx create mode 100644 src/components/TaskModals/AddTaskModal.tsx create mode 100644 src/components/TaskModals/DeleteTaskModal.test.tsx create mode 100644 src/components/TaskModals/DeleteTaskModal.tsx create mode 100644 src/components/TaskModals/ManageVolunteerModal.test.tsx create mode 100644 src/components/TaskModals/ManageVolunteerModal.tsx create mode 100644 src/components/TaskModals/UpdateTaskModal.test.tsx create mode 100644 src/components/TaskModals/UpdateTaskModal.tsx create mode 100644 src/components/UserListCard/UserListCard.module.css create mode 100644 src/components/UserListCard/UserListCard.test.tsx create mode 100644 src/components/UserListCard/UserListCard.tsx create mode 100644 src/components/UserPasswordUpdate/UserPasswordUpdate.module.css create mode 100644 src/components/UserPasswordUpdate/UserPasswordUpdate.test.tsx create mode 100644 src/components/UserPasswordUpdate/UserPasswordUpdate.tsx create mode 100644 src/components/UserPortal/ChatRoom/ChatRoom.module.css create mode 100644 src/components/UserPortal/ChatRoom/ChatRoom.tsx create mode 100644 src/components/UserPortal/CommentCard/CommentCard.module.css create mode 100644 src/components/UserPortal/CommentCard/CommentCard.test.tsx create mode 100644 src/components/UserPortal/CommentCard/CommentCard.tsx create mode 100644 src/components/UserPortal/ContactCard/ContactCard.module.css create mode 100644 src/components/UserPortal/ContactCard/ContactCard.test.tsx create mode 100644 src/components/UserPortal/ContactCard/ContactCard.tsx create mode 100644 src/components/UserPortal/DonationCard/DonationCard.module.css create mode 100644 src/components/UserPortal/DonationCard/DonationCard.tsx create mode 100644 src/components/UserPortal/EventCard/EventCard.module.css create mode 100644 src/components/UserPortal/EventCard/EventCard.test.tsx create mode 100644 src/components/UserPortal/EventCard/EventCard.tsx create mode 100644 src/components/UserPortal/Login/Login.module.css create mode 100644 src/components/UserPortal/Login/Login.test.tsx create mode 100644 src/components/UserPortal/Login/Login.tsx create mode 100644 src/components/UserPortal/OrganizationCard/OrganizationCard.module.css create mode 100644 src/components/UserPortal/OrganizationCard/OrganizationCard.test.tsx create mode 100644 src/components/UserPortal/OrganizationCard/OrganizationCard.tsx create mode 100644 src/components/UserPortal/OrganizationNavbar/OrganizationNavbar.module.css create mode 100644 src/components/UserPortal/OrganizationNavbar/OrganizationNavbar.test.tsx create mode 100644 src/components/UserPortal/OrganizationNavbar/OrganizationNavbar.tsx create mode 100644 src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.module.css create mode 100644 src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.test.tsx create mode 100644 src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.tsx create mode 100644 src/components/UserPortal/PeopleCard/PeopleCard.module.css create mode 100644 src/components/UserPortal/PeopleCard/PeopleCard.test.tsx create mode 100644 src/components/UserPortal/PeopleCard/PeopleCard.tsx create mode 100644 src/components/UserPortal/PostCard/PostCard.module.css create mode 100644 src/components/UserPortal/PostCard/PostCard.test.tsx create mode 100644 src/components/UserPortal/PostCard/PostCard.tsx create mode 100644 src/components/UserPortal/PromotedPost/PromotedPost.module.css create mode 100644 src/components/UserPortal/PromotedPost/PromotedPost.test.tsx create mode 100644 src/components/UserPortal/PromotedPost/PromotedPost.tsx create mode 100644 src/components/UserPortal/Register/Register.module.css create mode 100644 src/components/UserPortal/Register/Register.test.tsx create mode 100644 src/components/UserPortal/Register/Register.tsx create mode 100644 src/components/UserPortal/SecuredRouteForUser/SecuredRouteForUser.test.tsx create mode 100644 src/components/UserPortal/SecuredRouteForUser/SecuredRouteForUser.tsx create mode 100644 src/components/UserPortal/TaskCard/TaskCard.module.css create mode 100644 src/components/UserPortal/TaskCard/TaskCard.test.tsx create mode 100644 src/components/UserPortal/TaskCard/TaskCard.tsx create mode 100644 src/components/UserPortal/UserNavbar/UserNavbar.module.css create mode 100644 src/components/UserPortal/UserNavbar/UserNavbar.test.tsx create mode 100644 src/components/UserPortal/UserNavbar/UserNavbar.tsx create mode 100644 src/components/UserPortal/UserSidebar/UserSidebar.module.css create mode 100644 src/components/UserPortal/UserSidebar/UserSidebar.test.tsx create mode 100644 src/components/UserPortal/UserSidebar/UserSidebar.tsx create mode 100644 src/components/UserUpdate/UserUpdate.module.css create mode 100644 src/components/UserUpdate/UserUpdate.test.tsx create mode 100644 src/components/UserUpdate/UserUpdate.tsx create mode 100644 src/components/UsersTableItem/UserTableItem.test.tsx create mode 100644 src/components/UsersTableItem/UserTableItemMocks.ts create mode 100644 src/components/UsersTableItem/UsersTableItem.module.css create mode 100644 src/components/UsersTableItem/UsersTableItem.tsx create mode 100644 src/components/plugins/DummyPlugin/DummyPlugin.module.css create mode 100644 src/components/plugins/DummyPlugin/DummyPlugin.test.jsx create mode 100644 src/components/plugins/DummyPlugin/DummyPlugin.tsx create mode 100644 src/components/plugins/DummyPlugin2/DummyPlugin2.module.css create mode 100644 src/components/plugins/DummyPlugin2/DummyPlugin2.test.jsx create mode 100644 src/components/plugins/DummyPlugin2/DummyPlugin2.tsx create mode 100644 src/components/plugins/index.ts delete mode 100644 src/index.css create mode 100644 src/screens/BlockUser/BlockUser.module.css create mode 100644 src/screens/BlockUser/BlockUser.test.tsx create mode 100644 src/screens/BlockUser/BlockUser.tsx create mode 100644 src/screens/EventDashboard/EventDashboard.mocks.ts create mode 100644 src/screens/EventDashboard/EventDashboard.module.css create mode 100644 src/screens/EventDashboard/EventDashboard.test.tsx create mode 100644 src/screens/EventDashboard/EventDashboard.tsx create mode 100644 src/screens/ForgotPassword/ForgotPassword.module.css create mode 100644 src/screens/ForgotPassword/ForgotPassword.test.tsx create mode 100644 src/screens/ForgotPassword/ForgotPassword.tsx create mode 100644 src/screens/LoginPage/LoginPage.module.css create mode 100644 src/screens/LoginPage/LoginPage.test.tsx create mode 100644 src/screens/LoginPage/LoginPage.tsx create mode 100644 src/screens/MemberDetail/MemberDetail.module.css create mode 100644 src/screens/MemberDetail/MemberDetail.test.tsx create mode 100644 src/screens/MemberDetail/MemberDetail.tsx create mode 100644 src/screens/OrgContribution/OrgContribution.module.css create mode 100644 src/screens/OrgContribution/OrgContribution.test.tsx create mode 100644 src/screens/OrgContribution/OrgContribution.tsx create mode 100644 src/screens/OrgList/OrgList.module.css create mode 100644 src/screens/OrgList/OrgList.test.tsx create mode 100644 src/screens/OrgList/OrgList.tsx create mode 100644 src/screens/OrgList/OrgListMocks.ts create mode 100644 src/screens/OrgPost/OrgPost.module.css create mode 100644 src/screens/OrgPost/OrgPost.test.tsx create mode 100644 src/screens/OrgPost/OrgPost.tsx create mode 100644 src/screens/OrgSettings/OrgSettings.module.css create mode 100644 src/screens/OrgSettings/OrgSettings.test.tsx create mode 100644 src/screens/OrgSettings/OrgSettings.tsx create mode 100644 src/screens/OrganizationDashboard/OrganizationDashboard.module.css create mode 100644 src/screens/OrganizationDashboard/OrganizationDashboard.test.tsx create mode 100644 src/screens/OrganizationDashboard/OrganizationDashboard.tsx create mode 100644 src/screens/OrganizationDashboard/OrganizationDashboardMocks.ts create mode 100644 src/screens/OrganizationEvents/OrganizationEvents.module.css create mode 100644 src/screens/OrganizationEvents/OrganizationEvents.test.tsx create mode 100644 src/screens/OrganizationEvents/OrganizationEvents.tsx create mode 100644 src/screens/OrganizationEvents/calendar.css create mode 100644 src/screens/OrganizationPeople/OrganizationPeople.module.css create mode 100644 src/screens/OrganizationPeople/OrganizationPeople.test.tsx create mode 100644 src/screens/OrganizationPeople/OrganizationPeople.tsx create mode 100644 src/screens/PageNotFound/PageNotFound.module.css create mode 100644 src/screens/PageNotFound/PageNotFound.test.tsx create mode 100644 src/screens/PageNotFound/PageNotFound.tsx create mode 100644 src/screens/Requests/Requests.module.css create mode 100644 src/screens/Requests/Requests.test.tsx create mode 100644 src/screens/Requests/Requests.tsx create mode 100644 src/screens/Requests/RequestsMocks.ts create mode 100644 src/screens/UserPortal/Chat/Chat.module.css create mode 100644 src/screens/UserPortal/Chat/Chat.test.tsx create mode 100644 src/screens/UserPortal/Chat/Chat.tsx create mode 100644 src/screens/UserPortal/Donate/Donate.module.css create mode 100644 src/screens/UserPortal/Donate/Donate.test.tsx create mode 100644 src/screens/UserPortal/Donate/Donate.tsx create mode 100644 src/screens/UserPortal/Events/Events.module.css create mode 100644 src/screens/UserPortal/Events/Events.test.tsx create mode 100644 src/screens/UserPortal/Events/Events.tsx create mode 100644 src/screens/UserPortal/Home/Home.module.css create mode 100644 src/screens/UserPortal/Home/Home.test.tsx create mode 100644 src/screens/UserPortal/Home/Home.tsx create mode 100644 src/screens/UserPortal/Organizations/Organizations.module.css create mode 100644 src/screens/UserPortal/Organizations/Organizations.test.tsx create mode 100644 src/screens/UserPortal/Organizations/Organizations.tsx create mode 100644 src/screens/UserPortal/People/People.module.css create mode 100644 src/screens/UserPortal/People/People.test.tsx create mode 100644 src/screens/UserPortal/People/People.tsx create mode 100644 src/screens/UserPortal/Settings/Settings.module.css create mode 100644 src/screens/UserPortal/Settings/Settings.test.tsx create mode 100644 src/screens/UserPortal/Settings/Settings.tsx create mode 100644 src/screens/UserPortal/Tasks/Tasks.module.css create mode 100644 src/screens/UserPortal/Tasks/Tasks.test.tsx create mode 100644 src/screens/UserPortal/Tasks/Tasks.tsx create mode 100644 src/screens/UserPortal/UserLoginPage/UserLoginPage.module.css create mode 100644 src/screens/UserPortal/UserLoginPage/UserLoginPage.test.tsx create mode 100644 src/screens/UserPortal/UserLoginPage/UserLoginPage.tsx create mode 100644 src/screens/Users/Users.module.css create mode 100644 src/screens/Users/Users.test.tsx create mode 100644 src/screens/Users/Users.tsx create mode 100644 src/screens/Users/UsersMocks.ts create mode 100644 src/state/action-creators/index.test.ts create mode 100644 src/state/action-creators/index.ts create mode 100644 src/state/helpers/Action.test.ts create mode 100644 src/state/helpers/Action.ts create mode 100644 src/state/index.ts create mode 100644 src/state/reducers/index.ts create mode 100644 src/state/reducers/pluginReducer.test.ts create mode 100644 src/state/reducers/pluginReducer.ts create mode 100644 src/state/reducers/routesReducer.test.ts create mode 100644 src/state/reducers/routesReducer.ts create mode 100644 src/state/store.test.tsx create mode 100644 src/state/store.ts create mode 100644 src/utils/StaticMockLink.ts create mode 100644 src/utils/convertToBase64.test.ts create mode 100644 src/utils/convertToBase64.ts create mode 100644 src/utils/debounce.ts create mode 100644 src/utils/errorHandler.test.tsx create mode 100644 src/utils/errorHandler.tsx create mode 100644 src/utils/getOrganizationId.ts create mode 100644 src/utils/getRefreshToken.test.ts create mode 100644 src/utils/getRefreshToken.ts create mode 100644 src/utils/i18n.ts create mode 100644 src/utils/i18nForTest.ts create mode 100644 src/utils/interfaces.ts create mode 100644 src/utils/languages.ts create mode 100644 talawa-admin-docs/.nojekyll create mode 100644 talawa-admin-docs/README.md create mode 100644 talawa-admin-docs/classes/components_AddOn_support_services_Plugin_helper.default.md create mode 100644 talawa-admin-docs/classes/components_AddOn_support_services_Render_helper.default.md create mode 100644 talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceAttendeeCheckIn.md create mode 100644 talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceAttendeeQueryResponse.md create mode 100644 talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceModalProp.md create mode 100644 talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceTableCheckIn.md create mode 100644 talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceTableData.md create mode 100644 talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceUser.md create mode 100644 talawa-admin-docs/interfaces/components_CollapsibleDropdown_CollapsibleDropdown.InterfaceCollapsibleDropdown.md create mode 100644 talawa-admin-docs/interfaces/components_IconComponent_IconComponent.InterfaceIconComponent.md create mode 100644 talawa-admin-docs/interfaces/components_LeftDrawerOrg_LeftDrawerOrg.InterfaceLeftDrawerProps.md create mode 100644 talawa-admin-docs/interfaces/components_LeftDrawer_LeftDrawer.InterfaceLeftDrawerProps.md create mode 100644 talawa-admin-docs/interfaces/components_OrgListCard_OrgListCard.InterfaceOrgListCardProps.md create mode 100644 talawa-admin-docs/interfaces/components_OrganizationScreen_OrganizationScreen.InterfaceOrganizationScreenProps.md create mode 100644 talawa-admin-docs/interfaces/components_SuperAdminScreen_SuperAdminScreen.InterfaceSuperAdminScreenProps.md create mode 100644 talawa-admin-docs/modules.md create mode 100644 talawa-admin-docs/modules/components_AddOn_AddOn.default.md create mode 100644 talawa-admin-docs/modules/components_AddOn_AddOn.md create mode 100644 talawa-admin-docs/modules/components_AddOn_AddOn_test.md create mode 100644 talawa-admin-docs/modules/components_AddOn_core_AddOnEntry_AddOnEntry.default.md create mode 100644 talawa-admin-docs/modules/components_AddOn_core_AddOnEntry_AddOnEntry.md create mode 100644 talawa-admin-docs/modules/components_AddOn_core_AddOnEntry_AddOnEntry_test.md create mode 100644 talawa-admin-docs/modules/components_AddOn_core_AddOnRegister_AddOnRegister.default.md create mode 100644 talawa-admin-docs/modules/components_AddOn_core_AddOnRegister_AddOnRegister.md create mode 100644 talawa-admin-docs/modules/components_AddOn_core_AddOnRegister_AddOnRegister_test.md create mode 100644 talawa-admin-docs/modules/components_AddOn_core_AddOnStore_AddOnStore.default.md create mode 100644 talawa-admin-docs/modules/components_AddOn_core_AddOnStore_AddOnStore.md create mode 100644 talawa-admin-docs/modules/components_AddOn_core_AddOnStore_AddOnStore_test.md create mode 100644 talawa-admin-docs/modules/components_AddOn_support_components_Action_Action.md create mode 100644 talawa-admin-docs/modules/components_AddOn_support_components_Action_Action_test.md create mode 100644 talawa-admin-docs/modules/components_AddOn_support_components_MainContent_MainContent.md create mode 100644 talawa-admin-docs/modules/components_AddOn_support_components_MainContent_MainContent_test.md create mode 100644 talawa-admin-docs/modules/components_AddOn_support_components_SidePanel_SidePanel.md create mode 100644 talawa-admin-docs/modules/components_AddOn_support_components_SidePanel_SidePanel_test.md create mode 100644 talawa-admin-docs/modules/components_AddOn_support_services_Plugin_helper.md create mode 100644 talawa-admin-docs/modules/components_AddOn_support_services_Render_helper.md create mode 100644 talawa-admin-docs/modules/components_ChangeLanguageDropdown_ChangeLanguageDropDown.md create mode 100644 talawa-admin-docs/modules/components_ChangeLanguageDropdown_ChangeLanguageDropdown_test.md create mode 100644 talawa-admin-docs/modules/components_CheckIn_CheckInModal.md create mode 100644 talawa-admin-docs/modules/components_CheckIn_CheckInModal_test.md create mode 100644 talawa-admin-docs/modules/components_CheckIn_CheckInWrapper.md create mode 100644 talawa-admin-docs/modules/components_CheckIn_CheckInWrapper_test.md create mode 100644 talawa-admin-docs/modules/components_CheckIn_TableRow.md create mode 100644 talawa-admin-docs/modules/components_CheckIn_TableRow_test.md create mode 100644 talawa-admin-docs/modules/components_CheckIn_mocks.md create mode 100644 talawa-admin-docs/modules/components_CheckIn_tagTemplate.md create mode 100644 talawa-admin-docs/modules/components_CheckIn_types.md create mode 100644 talawa-admin-docs/modules/components_CollapsibleDropdown_CollapsibleDropdown.md create mode 100644 talawa-admin-docs/modules/components_CollapsibleDropdown_CollapsibleDropdown_test.md create mode 100644 talawa-admin-docs/modules/components_ContriStats_ContriStats.md create mode 100644 talawa-admin-docs/modules/components_ContriStats_ContriStats_test.md create mode 100644 talawa-admin-docs/modules/components_EventCalendar_EventCalendar.md create mode 100644 talawa-admin-docs/modules/components_EventCalendar_EventCalendar_test.md create mode 100644 talawa-admin-docs/modules/components_EventListCard_EventListCard.md create mode 100644 talawa-admin-docs/modules/components_EventListCard_EventListCard_test.md create mode 100644 talawa-admin-docs/modules/components_EventProjectModals_AddEventProjectModal.md create mode 100644 talawa-admin-docs/modules/components_EventProjectModals_AddEventProjectModal_test.md create mode 100644 talawa-admin-docs/modules/components_EventProjectModals_DeleteEventProjectModal.md create mode 100644 talawa-admin-docs/modules/components_EventProjectModals_DeleteEventProjectModal_test.md create mode 100644 talawa-admin-docs/modules/components_EventProjectModals_UpdateEventProjectModal.md create mode 100644 talawa-admin-docs/modules/components_EventProjectModals_UpdateEventProjectModal_test.md create mode 100644 talawa-admin-docs/modules/components_EventRegistrantsModal_EventRegistrantsModal.md create mode 100644 talawa-admin-docs/modules/components_EventRegistrantsModal_EventRegistrantsModal_test.md create mode 100644 talawa-admin-docs/modules/components_EventRegistrantsModal_EventRegistrantsWrapper.md create mode 100644 talawa-admin-docs/modules/components_EventRegistrantsModal_EventRegistrantsWrapper_test.md create mode 100644 talawa-admin-docs/modules/components_IconComponent_IconComponent.md create mode 100644 talawa-admin-docs/modules/components_IconComponent_IconComponent_test.md create mode 100644 talawa-admin-docs/modules/components_LandingPage_LandingPage.md create mode 100644 talawa-admin-docs/modules/components_LandingPage_LandingPage_test.md create mode 100644 talawa-admin-docs/modules/components_LeftDrawerOrg_LeftDrawerOrg.md create mode 100644 talawa-admin-docs/modules/components_LeftDrawerOrg_LeftDrawerOrg_test.md create mode 100644 talawa-admin-docs/modules/components_LeftDrawer_LeftDrawer.md create mode 100644 talawa-admin-docs/modules/components_LeftDrawer_LeftDrawer_test.md create mode 100644 talawa-admin-docs/modules/components_Loader_Loader.md create mode 100644 talawa-admin-docs/modules/components_Loader_Loader_test.md create mode 100644 talawa-admin-docs/modules/components_MemberRequestCard_MemberRequestCard.md create mode 100644 talawa-admin-docs/modules/components_MemberRequestCard_MemberRequestCard_test.md create mode 100644 talawa-admin-docs/modules/components_NotFound_NotFound.md create mode 100644 talawa-admin-docs/modules/components_NotFound_NotFound_test.md create mode 100644 talawa-admin-docs/modules/components_OrgAdminListCard_OrgAdminListCard.md create mode 100644 talawa-admin-docs/modules/components_OrgAdminListCard_OrgAdminListCard_test.md create mode 100644 talawa-admin-docs/modules/components_OrgContriCards_OrgContriCards.md create mode 100644 talawa-admin-docs/modules/components_OrgContriCards_OrgContriCards_test.md create mode 100644 talawa-admin-docs/modules/components_OrgDelete_OrgDelete.md create mode 100644 talawa-admin-docs/modules/components_OrgDelete_OrgDelete_test.md create mode 100644 talawa-admin-docs/modules/components_OrgListCard_OrgListCard.md create mode 100644 talawa-admin-docs/modules/components_OrgListCard_OrgListCard_test.md create mode 100644 talawa-admin-docs/modules/components_OrgPeopleListCard_OrgPeopleListCard.md create mode 100644 talawa-admin-docs/modules/components_OrgPeopleListCard_OrgPeopleListCard_test.md create mode 100644 talawa-admin-docs/modules/components_OrgPostCard_OrgPostCard.md create mode 100644 talawa-admin-docs/modules/components_OrgPostCard_OrgPostCard_test.md create mode 100644 talawa-admin-docs/modules/components_OrgUpdate_OrgUpdate.md create mode 100644 talawa-admin-docs/modules/components_OrgUpdate_OrgUpdate_test.md create mode 100644 talawa-admin-docs/modules/components_OrganizationCardStart_OrganizationCardStart.md create mode 100644 talawa-admin-docs/modules/components_OrganizationCardStart_OrganizationCardStart_test.md create mode 100644 talawa-admin-docs/modules/components_OrganizationCard_OrganizationCard.md create mode 100644 talawa-admin-docs/modules/components_OrganizationCard_OrganizationCard_test.md create mode 100644 talawa-admin-docs/modules/components_OrganizationScreen_OrganizationScreen.md create mode 100644 talawa-admin-docs/modules/components_OrganizationScreen_OrganizationScreen_test.md create mode 100644 talawa-admin-docs/modules/components_PaginationList_PaginationList.md create mode 100644 talawa-admin-docs/modules/components_Pagination_Pagination.md create mode 100644 talawa-admin-docs/modules/components_Pagination_Pagination_test.md create mode 100644 talawa-admin-docs/modules/components_SecuredRoute_SecuredRoute.md create mode 100644 talawa-admin-docs/modules/components_SuperAdminScreen_SuperAdminScreen.md create mode 100644 talawa-admin-docs/modules/components_SuperAdminScreen_SuperAdminScreen_test.md create mode 100644 talawa-admin-docs/modules/components_TableLoader_TableLoader.md create mode 100644 talawa-admin-docs/modules/components_TableLoader_TableLoader_test.md create mode 100644 talawa-admin-docs/modules/components_TaskListItem_TaskListItem.md create mode 100644 talawa-admin-docs/modules/components_TaskListItem_TaskListItem_test.md create mode 100644 talawa-admin-docs/modules/components_TaskModals_AddTaskModal.md create mode 100644 talawa-admin-docs/modules/components_TaskModals_AddTaskModal_test.md create mode 100644 talawa-admin-docs/modules/components_TaskModals_DeleteTaskModal.md create mode 100644 talawa-admin-docs/modules/components_TaskModals_DeleteTaskModal_test.md create mode 100644 talawa-admin-docs/modules/components_TaskModals_ManageVolunteerModal.md create mode 100644 talawa-admin-docs/modules/components_TaskModals_ManageVolunteerModal_test.md create mode 100644 talawa-admin-docs/modules/components_TaskModals_UpdateTaskModal.md create mode 100644 talawa-admin-docs/modules/components_TaskModals_UpdateTaskModal_test.md create mode 100644 talawa-admin-docs/modules/components_UserListCard_UserListCard.md create mode 100644 talawa-admin-docs/modules/components_UserListCard_UserListCard_test.md create mode 100644 talawa-admin-docs/modules/components_UserPasswordUpdate_UserPasswordUpdate.md create mode 100644 talawa-admin-docs/modules/components_UserPasswordUpdate_UserPasswordUpdate_test.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_DonationCard_DonationCard.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_Login_Login.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_Login_Login_test.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_OrganizationCard_OrganizationCard.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_OrganizationCard_OrganizationCard_test.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_OrganizationNavbar_OrganizationNavbar.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_OrganizationNavbar_OrganizationNavbar_test.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_OrganizationSidebar_OrganizationSidebar.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_OrganizationSidebar_OrganizationSidebar_test.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_PeopleCard_PeopleCard.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_PeopleCard_PeopleCard_test.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_PostCard_PostCard.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_PostCard_PostCard_test.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_Register_Register.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_Register_Register_test.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_SecuredRouteForUser_SecuredRouteForUser.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_UserNavbar_UserNavbar.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_UserNavbar_UserNavbar_test.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_UserSidebar_UserSidebar.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_UserSidebar_UserSidebar_test.md create mode 100644 talawa-admin-docs/modules/components_UserUpdate_UserUpdate.md create mode 100644 talawa-admin-docs/modules/components_UserUpdate_UserUpdate_test.md create mode 100644 talawa-admin-docs/modules/components_plugins.md create mode 100644 talawa-admin-docs/modules/components_plugins_DummyPlugin2_DummyPlugin2.default.md create mode 100644 talawa-admin-docs/modules/components_plugins_DummyPlugin2_DummyPlugin2.md create mode 100644 talawa-admin-docs/modules/components_plugins_DummyPlugin2_DummyPlugin2_test.md create mode 100644 talawa-admin-docs/modules/components_plugins_DummyPlugin_DummyPlugin.default.md create mode 100644 talawa-admin-docs/modules/components_plugins_DummyPlugin_DummyPlugin.md create mode 100644 talawa-admin-docs/modules/components_plugins_DummyPlugin_DummyPlugin_test.md create mode 100644 talawa-admin-docs/modules/screens_BlockUser_BlockUser.md create mode 100644 talawa-admin-docs/modules/screens_BlockUser_BlockUser_test.md create mode 100644 talawa-admin-docs/modules/screens_EventDashboard_EventDashboard.md create mode 100644 talawa-admin-docs/modules/screens_EventDashboard_EventDashboard_mocks.md create mode 100644 talawa-admin-docs/modules/screens_EventDashboard_EventDashboard_test.md create mode 100644 talawa-admin-docs/modules/screens_ForgotPassword_ForgotPassword.md create mode 100644 talawa-admin-docs/modules/screens_ForgotPassword_ForgotPassword_test.md create mode 100644 talawa-admin-docs/modules/screens_LoginPage_LoginPage.md create mode 100644 talawa-admin-docs/modules/screens_LoginPage_LoginPage_test.md create mode 100644 talawa-admin-docs/modules/screens_MemberDetail_MemberDetail.md create mode 100644 talawa-admin-docs/modules/screens_MemberDetail_MemberDetail_test.md create mode 100644 talawa-admin-docs/modules/screens_OrgContribution_OrgContribution.md create mode 100644 talawa-admin-docs/modules/screens_OrgContribution_OrgContribution_test.md create mode 100644 talawa-admin-docs/modules/screens_OrgList_OrgList.md create mode 100644 talawa-admin-docs/modules/screens_OrgList_OrgListMocks.md create mode 100644 talawa-admin-docs/modules/screens_OrgList_OrgList_test.md create mode 100644 talawa-admin-docs/modules/screens_OrgPost_OrgPost.md create mode 100644 talawa-admin-docs/modules/screens_OrgPost_OrgPost_test.md create mode 100644 talawa-admin-docs/modules/screens_OrgSettings_OrgSettings.md create mode 100644 talawa-admin-docs/modules/screens_OrgSettings_OrgSettings_test.md create mode 100644 talawa-admin-docs/modules/screens_OrganizationDashboard_OrganizationDashboard.md create mode 100644 talawa-admin-docs/modules/screens_OrganizationDashboard_OrganizationDashboardMocks.md create mode 100644 talawa-admin-docs/modules/screens_OrganizationDashboard_OrganizationDashboard_test.md create mode 100644 talawa-admin-docs/modules/screens_OrganizationEvents_OrganizationEvents.md create mode 100644 talawa-admin-docs/modules/screens_OrganizationEvents_OrganizationEvents_test.md create mode 100644 talawa-admin-docs/modules/screens_OrganizationPeople_OrganizationPeople.md create mode 100644 talawa-admin-docs/modules/screens_OrganizationPeople_OrganizationPeople_test.md create mode 100644 talawa-admin-docs/modules/screens_PageNotFound_PageNotFound.md create mode 100644 talawa-admin-docs/modules/screens_PageNotFound_PageNotFound_test.md create mode 100644 talawa-admin-docs/modules/screens_Requests_Requests.md create mode 100644 talawa-admin-docs/modules/screens_Requests_Requests_test.md create mode 100644 talawa-admin-docs/modules/screens_UserPortal_Donate_Donate.md create mode 100644 talawa-admin-docs/modules/screens_UserPortal_Donate_Donate_test.md create mode 100644 talawa-admin-docs/modules/screens_UserPortal_Home_Home.md create mode 100644 talawa-admin-docs/modules/screens_UserPortal_Home_Home_test.md create mode 100644 talawa-admin-docs/modules/screens_UserPortal_Organizations_Organizations.md create mode 100644 talawa-admin-docs/modules/screens_UserPortal_Organizations_Organizations_test.md create mode 100644 talawa-admin-docs/modules/screens_UserPortal_People_People.md create mode 100644 talawa-admin-docs/modules/screens_UserPortal_People_People_test.md create mode 100644 talawa-admin-docs/modules/screens_UserPortal_Settings_Settings.md create mode 100644 talawa-admin-docs/modules/screens_UserPortal_Settings_Settings_test.md create mode 100644 talawa-admin-docs/modules/screens_UserPortal_UserLoginPage_UserLoginPage.md create mode 100644 talawa-admin-docs/modules/screens_UserPortal_UserLoginPage_UserLoginPage_test.md create mode 100644 talawa-admin-docs/modules/screens_Users_Users.md create mode 100644 talawa-admin-docs/modules/screens_Users_Users_test.md delete mode 100644 yarn.lock diff --git a/.env.example b/.env.example new file mode 100644 index 0000000000..bd9529ea79 --- /dev/null +++ b/.env.example @@ -0,0 +1,23 @@ +# 👋 Welcome, we're glad you're setting up an installation of Talawa-admin. Copy this +# file to .env or set the variables in your local environment manually. + + +# Run Talawa-api locally in your system, and put its url into the same. + +REACT_APP_TALAWA_URL= + +# Do you want to setup and use "I'm not a robot" Checkbox (Google Recaptcha)? +# If no, leave blank, else write yes +# Example: REACT_APP_USE_RECAPTCHA=yes + +REACT_APP_USE_RECAPTCHA= + +# If you are using Google Recaptcha, i.e., REACT_APP_USE_RECAPTCHA=yes, read the following steps +# Get the google recaptcha site key from google recaptcha admin or https://www.google.com/recaptcha/admin/create +# from here for reCAPTCHA v2 and "I'm not a robot" Checkbox, and paste the key here. +# Note: In domains, fill localhost + +REACT_APP_RECAPTCHA_SITE_KEY= + +# has to be inserted in the env file to use plugins and other websocket based features. +REACT_APP_BACKEND_WEBSOCKET_URL=ws://localhost:4000/graphql \ No newline at end of file diff --git a/.eslintignore b/.eslintignore index e69de29bb2..7e45de312a 100644 --- a/.eslintignore +++ b/.eslintignore @@ -0,0 +1,2 @@ +# Contains the PDF file of the Tag as JSON string, thus does not need to be linted +src/components/CheckIn/tagTemplate.ts \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json index a1f8002a3c..dfb93ff263 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,6 +1,7 @@ { "env": { "browser": true, + "node": true, "es6": true }, @@ -26,12 +27,76 @@ }, // Specify the ESLint plugins tobe used - "plugins": ["react", "@typescript-eslint", "react-hooks", "jest"], + "plugins": ["react", "@typescript-eslint", "jest"], "rules": { - "react/destructuring-assignment": ["warn", "always"], - "react/no-multi-comp": ["error", { "ignoreStateless": false }], - "react/jsx-filename-extension": ["error", { "extensions": [".tsx"] }], + "react/destructuring-assignment": ["off"], + "@typescript-eslint/no-explicit-any": ["off"], + "@typescript-eslint/explicit-module-boundary-types": ["off"], + "react/no-multi-comp": [ + "error", + { + "ignoreStateless": false + } + ], + "react/jsx-filename-extension": [ + "error", + { + "extensions": [".tsx"] + } + ], + "@typescript-eslint/ban-types": "error", + "@typescript-eslint/no-duplicate-enum-values": "error", + "@typescript-eslint/array-type": "error", + "@typescript-eslint/consistent-type-assertions": "error", + "@typescript-eslint/consistent-type-imports": "error", + "@typescript-eslint/explicit-function-return-type": [ + 2, + { + "allowExpressions": true, + "allowTypedFunctionExpressions": true + } + ], + "@typescript-eslint/naming-convention": [ + "error", + // Interfaces must begin with Interface or TestInterface followed by a PascalCase name + { + "selector": "interface", + "format": ["PascalCase"], + "prefix": ["Interface", "TestInterface"] + }, + // Type Aliases must be in PascalCase + { + "selector": ["typeAlias", "typeLike", "enum"], + "format": ["PascalCase"] + }, + { + "selector": "typeParameter", + "format": ["PascalCase"], + "prefix": ["T"] + }, + { + "selector": "variable", + "format": ["camelCase", "UPPER_CASE"], + "leadingUnderscore": "allow" + }, + { + "selector": "parameter", + "format": ["camelCase"], + "leadingUnderscore": "allow" + }, + { + "selector": "function", + "format": ["camelCase"] + }, + { + "selector": "memberLike", + "modifiers": ["private"], + "format": ["camelCase"], + "leadingUnderscore": "require" + }, + { "selector": "variable", "modifiers": ["exported"], "format": null } + ], // Ensures that components are always written in PascalCase "react/jsx-pascal-case": [ "error", @@ -42,6 +107,9 @@ "react/jsx-equals-spacing": ["warn", "never"], "react/no-this-in-sfc": "error", + // All tests must need not have an assertion + "jest/expect-expect": 0, + // Ensures that components are always indented by 2 spaces "react/jsx-indent": ["warn", 2], "react/jsx-tag-spacing": [ @@ -56,7 +124,7 @@ // Enforce Strictly functional components "react/no-unstable-nested-components": ["error", { "allowAsProps": true }], "react/function-component-definition": [ - "error", + 0, { "namedComponents": "function-declaration" } ] }, diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug-report.md similarity index 60% rename from .github/ISSUE_TEMPLATE/bug_report.md rename to .github/ISSUE_TEMPLATE/bug-report.md index ccbb9c4d8e..493322305f 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -1,9 +1,10 @@ --- -name: Bug report +name: Bug Report about: Create a report to help us improve. -title: Bug report -labels: Bug -assignees: "" +title: Bug Report +labels: bug +assignees: '' + --- **Describe the bug** @@ -27,3 +28,7 @@ A clear and concise description of how the code performed w.r.t expectations. If applicable, add screenshots to help explain your problem. **Additional details** +Add any other context or screenshots about the feature request here. + +**Potential internship candidates** +Please read this if you are planning to apply for a Palisadoes Foundation internship https://github.com/PalisadoesFoundation/talawa/issues/359 diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature-request.md similarity index 69% rename from .github/ISSUE_TEMPLATE/feature_request.md rename to .github/ISSUE_TEMPLATE/feature-request.md index 1c93611c44..60d6401dcf 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature-request.md @@ -1,9 +1,10 @@ --- -name: Feature request +name: Feature Request about: Suggest an idea for this project -title: Feature request -labels: Feature -assignees: "" +title: Feature Request +labels: feature request +assignees: '' + --- **Is your feature request related to a problem? Please describe.** @@ -20,3 +21,6 @@ A clear and concise description of approach to be followed. **Additional context** Add any other context or screenshots about the feature request here. + +**Potential internship candidates** +Please read this if you are planning to apply for a Palisadoes Foundation internship https://github.com/PalisadoesFoundation/talawa/issues/359 diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index c2a991ba29..9e3081d0ee 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -4,9 +4,11 @@ This section can be deleted after reading. We employ the following branching strategy to simplify the development process and to ensure that only stable code is pushed to the `master` branch: - `develop`: For unstable code: New features and bug fixes. -- `alpha-x.x.x`: For stability testing: Only bug fixes accepted. - `master`: Where the stable production ready code lies. Only security related bugs. +NOTE!!! + +ONLY SUBMIT PRS AGAINST OUR `DEVELOP` BRANCH. THE DEFAULT IS `MAIN`, SO YOU WILL HAVE TO MODIFY THIS BEFORE SUBMITTING YOUR PR FOR REVIEW. PRS MADE AGAINST `MAIN` WILL BE CLOSED. --> + +- [Issue Report Guidelines](#issue-report-guidelines) + - [Table of Contents](#table-of-contents) + - [Issue Management](#issue-management) + - [New Issues](#new-issues) + - [Existing Issues](#existing-issues) + - [Feature Request Issues](#feature-request-issues) + - [Monitoring the Creation of New Issues](#monitoring-the-creation-of-new-issues) + - [General Guidelines](#general-guidelines) + + +___ +## Issue Management + +In all cases please use the [GitHub open issue search](https://github.com/PalisadoesFoundation/talawa-admin/issues) to check whether the issue has already been reported. + +### New Issues +To create new issues follow these steps: + +1. Your issue may have already been created. Search for duplicate open issues before submitting yours.for similar deficiencies in the code.duplicate issues are created. +1. Verify whether the issue has been fixed by trying to reproduce it using the latest master or development branch in the repository. +1. Click on the [`New Issue`](https://github.com/PalisadoesFoundation/talawa-admin/issues/new/choose) button +1. Use the templates to create a standardized report of what needs to be done and why. +1. If you want to be assigned the issue that you have created, then add a comment immediately after submitting it. + +We welcome contributors who find new ways to make the code better. + +### Existing Issues + +You can also be a valuable contributor by searching for dormant issues. Here's how you can do that: + +1. **Previously Assigned Issues**: We regularly review issues and add a [`no-issue-activity`](https://github.com/PalisadoesFoundation/talawa-admin/issues?q=is%3Aissue+is%3Aopen+label%3Ano-issue-activity) label to them. Use the issue comments to ask whether the assignee is still working on the issue, and if not, ask for the issue to be assigned to you. +1. **Unassigned Issues**: If the issue is already reported and [not assigned to anyone](https://github.com/PalisadoesFoundation/talawa-admin/issues?q=is%3Aissue+is%3Aopen+no%3Aassignee) and you are interested in working on the issue then: + 1. Ask for the issue to be assigned to you in the issue comments + 2. Ask our contributors to assign it to you in `#talawa` slack channel. + +Working on these types of existing issues is a good way of getting started with the community. + +### Feature Request Issues + +Feature requests are welcome. But take a moment to find out whether your idea fits with the scope and aims of the project. It's up to you to make a strong case to convince the mentors of the merits of this feature. Please provide as much detail and context as possible. + +### Monitoring the Creation of New Issues +1. Join our `#talawa-github` slack channel for automatic issue and pull request updates + +## General Guidelines + +1. Discuss issues in our various slack channels when necessary +2. Please do not derail or troll issues. +3. Keep the discussion on topic and respect the opinions of others. diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md deleted file mode 100644 index c59e24c1ee..0000000000 --- a/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,38 +0,0 @@ - - -## Expected Behavior - - - -## Current Behavior - - - -## Possible Solution - - - -## Steps to Reproduce - - - - -1. -2. -3. -4. - -## Context (Environment) - - - - - - -## Detailed Description - - - -## Possible Implementation - - diff --git a/PR-guidelines.md b/PR-guidelines.md deleted file mode 100644 index c469028b0b..0000000000 --- a/PR-guidelines.md +++ /dev/null @@ -1,21 +0,0 @@ -# Pull Request Guidelines - -:+1::tada: First off, thanks for taking the time to contribute! :tada::+1: - -In order to give everyone a chance to submit a pull request and contribute to the Talawa API project, we have put restrictions in place. This section outlines the guidelines that should be imposed upon pull requests in the Talawa API project. - -1. Do not start working on any open issue and raise a PR unless it is assigned to you. -2. Pull requests must be based on [open issues](https://github.com/PalisadoesFoundation/talawa-admin/issues) available. -3. [Use this method to automatically close the issue when the PR is completed.](https://docs.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue) -4. Each contributor may only create one pull request at a time. We have this rule in place due to our limited resources - if everyone was allowed to post multiple pull requests we will not be able to review them properly. It is also better for contributors because you can focus on creating one quality PR - so spend time making sure it is as good as it can be. -5. If the pull request's code quality is not up to par, or it would break the app, it will more likely be closed. So please be careful when creating a PR. -6. Please follow the [PR template](https://github.com/PalisadoesFoundation/talawa-admin/blob/master/templates/pr-template.md). Ensure the PR title clearly describes the problem it is solving. In the description, include the relevant issue number, snapshots and videos after changes added. -7. If you are borrowing code, please disclose it. It is fine and sometimes even recommended to borrow code, but we need to know about it to assess your work. If we find out that your pull request contains a lot of code copied from elsewhere, we will close the pull request. -8. All pull request must have test units. If for some reason it is not possible to add tests, please let us know and explain why. In that case, you'll need to tell us what steps you followed to manually test your changes. -9. No Work In Progress. ONLY completed and working pull requests, and with test units, will be accepted. A WIP would fall under rule 4 and be closed immediately. -10. Please do not @mention contributors and mentors. Sometimes it takes time before we can review your pull request or answer your questions but we'll get to it sooner or later. @mentioning someone just adds to the pile of notifications we get and it won't make us look at your issue faster. -11. Do not force push. If you make changes to your pull request, please simply add a new commit as that makes it easy for us to review your new changes. If you force push, we'll have to review everything from the beginning. -12. PR should be small, easy to review and should follow standard coding styles. -13. If PR has conflicts because of recently added changes to the same file, resolve issues, test new changes and submit PR again for review. -14. PRs should be atomic. That is, they should address one item (issue or feature) -15. After submitting PR, if you are not replying within 48 hours then in that case we may need to assign issue to other contributors based on priority of the issue. diff --git a/PR_GUIDELINES.md b/PR_GUIDELINES.md new file mode 100644 index 0000000000..d1c2a0b2d9 --- /dev/null +++ b/PR_GUIDELINES.md @@ -0,0 +1,57 @@ +# Pull Request Guidelines + +:+1::tada: First off, thanks for taking the time to contribute! :tada::+1: + +In order to give everyone a chance to submit a pull request and contribute to the Talawa project, we have put restrictions in place. This section outlines the guidelines that should be imposed upon pull requests in the Talawa project. + +## Pull Requests and Issues + +1. Do not start working on any open issue and raise a PR unless the issue is assigned to you. PRs that don't meet these guidelines will be closed. +1. Pull requests must be based on [open issues](https://github.com/PalisadoesFoundation/talawa-admin/issues) available. +1. [Use this method to automatically close the issue when the PR is completed.](https://docs.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue) + +## Linting and Formatting + +All the pull requests must have code that is properly linted and formatted, so that uniformity across the repository can be ensured. + +Before opening a PR, you can run the following scripts to automatically lint and format the code properly: + +``` +npm run lint:fix +npm run format:fix +``` + +Both of these scripts also have a `check` counterpart, which would be used by the GitHub CI to ensure that the code is properly formatted. +You can run the following scripts yourself to ensure that your pull request doesn't fail due to linting and formatting errors: + +``` +npm run lint:check +npm run format:check +``` + +## Testing + +1. All pull requests must have test units. If, for some reason, it is not possible to add tests, please let us know and explain why. In that case, you'll need to tell us what steps you followed to manually test your changes. +1. Please read our [CONTRIBUTING.md](CONTRIBUTING.md) document for details on our testing policy. + +## Pull Request Processing +These are key guidelines for the procedure: + +### Only submit PRs against our `develop` branch, not the default `main` branch + +1. Only submit PRs against our `develop` branch. The default is `main`, so you will have to modify this before submitting your PR for review. PRs made against `main` will be closed. +1. We do not accept draft Pull Requests. They will be closed if submitted. We focus on work that is ready for immediate review. +1. Removing assigned reviewers from your Pull Request will cause it to be closed. The quality of our code is very important to us. Therefore we make experienced maintainers of our code base review your code. Removing these assigned persons is not in the best interest of this goal. +1. If you have not done so already, please read the `Pull Requests and Issues` and `Testing` sections above. +1. Each contributor may only create one pull request at a time. We have this rule in place due to our limited resources - if everyone was allowed to post multiple pull requests, we would not be able to review them properly. It is also better for contributors because you can focus on creating one quality PR - so spend time making sure it is as good as it can be. +1. Upon successful push to the fork, check if all tests are passing; if not, fix the issues and then create a pull request. +1. If the pull request's code quality is not up to par, or it would break the app, it will more likely be closed. So please be careful when creating a PR. +1. Please follow the PR template provided. Ensure the PR title clearly describes the problem it is solving. In the description, include the relevant issue number, snapshots, and videos after changes are added. +1. If you are borrowing a code, please disclose it. It is fine and sometimes even recommended to borrow code, but we need to know about it to assess your work. If we find out that your pull request contains a lot of code copied from elsewhere, we will close the pull request. +1. No Work In Progress. ONLY completed and working pull requests and with respective test units will be accepted. A WIP would fall under rule 4 and be closed immediately. +1. Please do not @mention contributors and mentors. Sometimes it takes time before we can review your pull request or answer your questions, but we'll get to it sooner or later. @mentioning someone just adds to the pile of notifications we get and it won't make us look at your issue faster. +1. Do not force push. If you make changes to your pull request, please simply add a new commit, as that makes it easy for us to review your new changes. If you force push, we'll have to review everything from the beginning. +1. PR should be small, easy to review and should follow standard coding styles. +1. If PR has conflicts because of recently added changes to the same file, resolve issues, test new changes, and submit PR again for review. +1. PRs should be atomic. That is, they should address one item (issue or feature) +1. After submitting PR, if you are not replying within 48 hours, then in that case, we may need to assign the issue to other contributors based on the priority of the issue. diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index 435ecf4ada..0000000000 --- a/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,15 +0,0 @@ -- **Please check if the PR fulfills these requirements** - -* [ ] The commit message follows our guidelines -* [ ] Tests for the changes have been added (for bug fixes / features) -* [ ] Docs have been added / updated (for bug fixes / features) - -- **What kind of change does this PR introduce?** (Bug fix, feature, docs update, ...) - -- **What is the current behavior?** (You can also link to an open issue here) - -- **What is the new behavior (if this is a feature change)?** - -- **Does this PR introduce a breaking change?** (What changes might users need to make in their application due to this PR?) - -- **Other information**: diff --git a/README.md b/README.md index 66d98dd25c..39be8dbb3d 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,12 @@ # Talawa Admin +💬 Join the community on Slack. The link can be found in the `Talawa` [README.md](https://github.com/PalisadoesFoundation/talawa) file. + +![talawa-logo-lite-200x200](https://github.com/PalisadoesFoundation/talawa-admin/assets/16875803/26291ec5-d3c1-4135-8bc7-80885dff613d) [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) [![GitHub stars](https://img.shields.io/github/stars/PalisadoesFoundation/talawa-admin.svg?style=social&label=Star&maxAge=2592000)](https://github.com/PalisadoesFoundation/talawa-admin) [![GitHub forks](https://img.shields.io/github/forks/PalisadoesFoundation/talawa-admin.svg?style=social&label=Fork&maxAge=2592000)](https://github.com/PalisadoesFoundation/talawa-admin) - -[![N|Solid](src/assets/talawa-logo-lite-200x200.png)](https://github.com/PalisadoesFoundation/talawa-admin) +[![codecov](https://codecov.io/gh/PalisadoesFoundation/talawa-admin/branch/develop/graph/badge.svg?token=II0R0RREES)](https://codecov.io/gh/PalisadoesFoundation/talawa-admin) Talawa is a modular open source project to manage group activities of both non-profit organizations and businesses. @@ -29,44 +31,10 @@ Core features include: # Documentation -- The `talawa` documentation can be found [here](https://palisadoesfoundation.github.io/talawa-docs/). -- Want to contribute? Look at [CONTRIBUTING.md](CONTRIBUTING.md) to get started. +- The `talawa` documentation can be found [here](https://docs.talawa.io). +- Want to contribute? Look at [CONTRIBUTING.md](https://github.com/PalisadoesFoundation/talawa-admin/blob/develop/CONTRIBUTING.md) to get started. - Visit the [Talawa-Docs GitHub](https://github.com/PalisadoesFoundation/talawa-docs) to see the code. -# Project Setup - -``` -yarn install -``` - -## Compiles and hot-reloads for development - -``` -yarn serve -``` - -## Compiles and minifies for production - -``` -yarn build -``` - -## Run your end-to-end tests - -``` -yarn test:e2e -``` - -## Lints and fixes files - -``` -yarn lint -``` - -## Customize configuration - -See [Configuration Reference](https://cli.vuejs.org/config/). - -## Project setup using docker +# Installation -See [Docker Container](Docker_Container/README.md) +[Follow this guide](https://github.com/PalisadoesFoundation/talawa-admin/blob/develop/INSTALLATION.md) diff --git a/issue-guidelines.md b/issue-guidelines.md deleted file mode 100644 index 5d626c332d..0000000000 --- a/issue-guidelines.md +++ /dev/null @@ -1,12 +0,0 @@ -# Issue Report Guidelines - -:+1::tada: First off, thanks for taking the time to contribute! :tada::+1: - -In order to give everyone a chance to submit a issues reports and contribute to the Talawa API project, we have put restrictions in place. This section outlines the guidelines that should be imposed upon issue reports in the Talawa API project. - -1. Use the [GitHub open issue search](https://github.com/PalisadoesFoundation/talawa-admin/issues) — check if the issue has already been reported. -2. If the issue is already reported and not assigned to anyone, if you are interested to work on the issue then ask mentors to assign issign to you in #talawa-api slack channel. -3. Check if the issue has been fixed — try to reproduce it using the latest master or development branch in the repository. -4. For newly found unfixed issues or features, start discussing it in #gsoc-newissues channel with mentors. Please do not derail or troll issues. Keep the discussion on topic and respect the opinions of others. -5. After mentor approval you can create a new issue by following [issue template](https://github.com/PalisadoesFoundation/talawa-admin/blob/master/templates/issue-template.md) available here. -6. Feature requests are welcome. But take a moment to find out whether your idea fits with the scope and aims of the project. It's up to you to make a strong case to convince the mentors of the merits of this feature. Please provide as much detail and context as possible. diff --git a/jest-preview.config.ts b/jest-preview.config.ts new file mode 100644 index 0000000000..0bcc13d4c7 --- /dev/null +++ b/jest-preview.config.ts @@ -0,0 +1,5 @@ +export default { + moduleNameMapper: { + '^@mui/(.*)$': '/node_modules/@mui/$1', + }, +}; diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000000..78be9e4e43 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,64 @@ +export default { + roots: ['/src'], + collectCoverageFrom: ['src/**/*.{ts,tsx}', '!src/index.tsx'], + setupFiles: ['react-app-polyfill/jsdom'], + setupFilesAfterEnv: ['/src/setupTests.ts'], + testMatch: [ + '/src/**/__tests__/**/*.{js,jsx,ts,tsx}', + '/src/**/*.{spec,test}.{js,jsx,ts,tsx}', + ], + testEnvironment: 'jsdom', + transform: { + '^.+\\.(js|jsx|mjs|cjs|ts|tsx)$': + 'react-scripts/config/jest/babelTransform.js', + '^.+\\.(css|scss|sass|less)$': 'jest-preview/transforms/css', + '^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)': + 'jest-preview/transforms/file', + }, + transformIgnorePatterns: [ + '[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs|cjs|ts|tsx)$', + ], + modulePaths: [ + '/Users/prathamesh/Desktop/Open-Source/palisadoes/talawa-admin/src', + '/src', + ], + moduleNameMapper: { + '^react-native$': 'react-native-web', + '^@mui/(.*)$': '/node_modules/@mui/$1', + }, + moduleFileExtensions: [ + 'web.js', + 'js', + 'web.ts', + 'ts', + 'web.tsx', + 'tsx', + 'json', + 'web.jsx', + 'jsx', + 'node', + ], + watchPlugins: [ + 'jest-watch-typeahead/filename', + 'jest-watch-typeahead/testname', + ], + resetMocks: false, + coveragePathIgnorePatterns: [ + 'src/state/index.ts', + 'src/components/plugins/index.ts', + 'src/components/AddOn/support/services/Render.helper.ts', + 'src/components/SecuredRoute/SecuredRoute.tsx', + 'src/reportWebVitals.ts', + ], + coverageThreshold: { + global: { + lines: 20, + statements: 20, + }, + }, + testPathIgnorePatterns: [ + '/node_modules/', + '/build/', + '/public/', + ], +}; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000000..f11ca8eb3f --- /dev/null +++ b/package-lock.json @@ -0,0 +1,25207 @@ +{ + "name": "talawa-admin", + "version": "3.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "talawa-admin", + "version": "3.0.0", + "dependencies": { + "@apollo/client": "^3.4.0-beta.19", + "@apollo/link-error": "^2.0.0-beta.3", + "@apollo/react-testing": "^4.0.0", + "@emotion/react": "^11.11.1", + "@emotion/styled": "^11.11.0", + "@mui/icons-material": "^5.8.3", + "@mui/material": "^5.14.1", + "@mui/private-theming": "^5.14.13", + "@mui/system": "^5.14.12", + "@mui/x-charts": "^6.0.0-alpha.13", + "@mui/x-data-grid": "^6.8.0", + "@mui/x-date-pickers": "^6.6.0", + "@pdfme/generator": "^1.2.6", + "@testing-library/jest-dom": "^5.14.1", + "@testing-library/react": "^11.1.0", + "@testing-library/user-event": "^12.1.10", + "@types/enzyme-adapter-react-16": "^1.0.6", + "@types/jest": "^26.0.24", + "@types/jquery": "^3.5.6", + "@types/node": "^12.20.16", + "@types/react-bootstrap": "^0.32.32", + "@types/react-datepicker": "^4.1.4", + "@types/react-dom": "^17.0.9", + "@types/react-google-recaptcha": "^2.1.5", + "@types/react-modal": "^3.12.1", + "bootstrap": "^5.3.0", + "dayjs": "^1.10.7", + "detect-newline": "^4.0.0", + "enzyme": "^3.11.0", + "enzyme-adapter-react-16": "^1.15.6", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-jest": "^25.3.4", + "eslint-plugin-prettier": "^3.4.0", + "flag-icons": "^6.6.6", + "graphql": "^15.5.1", + "graphql-tag": "^2.12.6", + "graphql-ws": "^5.14.0", + "i18next": "^21.8.14", + "i18next-browser-languagedetector": "^6.1.4", + "i18next-http-backend": "^1.4.1", + "jest-docblock": "^27.4.0", + "js-cookie": "^3.0.1", + "node-sass": "^9.0.0", + "prettier": "^2.3.2", + "react": "^17.0.2", + "react-bootstrap": "^2.7.4", + "react-calendar": "^4.2.1", + "react-datepicker": "^4.2.0", + "react-dom": "^17.0.2", + "react-google-recaptcha": "^2.1.0", + "react-i18next": "^11.18.1", + "react-infinite-scroll-component": "^6.1.0", + "react-redux": "^7.2.5", + "react-router-dom": "^5.2.0", + "react-scripts": "5.0.1", + "react-toastify": "^9.0.3", + "redux": "^4.1.1", + "redux-thunk": "^2.3.0", + "typedoc": "^0.24.8", + "typedoc-plugin-markdown": "^3.16.0", + "typescript": "^4.3.5", + "web-vitals": "^1.0.1", + "yarn": "^1.22.17" + }, + "devDependencies": { + "@babel/plugin-proposal-private-property-in-object": "^7.21.11", + "@fortawesome/fontawesome-svg-core": "^1.2.35", + "@fortawesome/free-brands-svg-icons": "^5.15.3", + "@fortawesome/react-fontawesome": "^0.1.14", + "@types/enzyme": "^3.10.9", + "@types/js-cookie": "^3.0.2", + "@types/react": "^17.0.14", + "@types/react-router-dom": "^5.1.8", + "@typescript-eslint/eslint-plugin": "^5.9.0", + "@typescript-eslint/parser": "^5.9.0", + "@wojtekmaj/enzyme-adapter-react-17": "^0.8.0", + "cross-env": "^7.0.3", + "husky": "^8.0.3", + "identity-obj-proxy": "^3.0.0", + "jest": "^27.4.5", + "jest-enzyme": "^7.1.2", + "jest-localstorage-mock": "^2.4.19", + "jest-location-mock": "^1.0.9", + "jest-preview": "^0.3.1", + "jquery": "^3.2.1", + "postcss-modules": "^6.0.0" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@adobe/css-tools": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.2.0.tgz", + "integrity": "sha512-E09FiIft46CmH5Qnjb0wsW54/YQd69LsxeKUOWawmws1XWvyFGURnAChH0mlr7YPFR1ofwvUQfcL0J3lMxXqPA==" + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@apideck/better-ajv-errors": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.6.tgz", + "integrity": "sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==", + "dependencies": { + "json-schema": "^0.4.0", + "jsonpointer": "^5.0.0", + "leven": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "ajv": ">=8" + } + }, + "node_modules/@apollo/client": { + "version": "3.7.17", + "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.7.17.tgz", + "integrity": "sha512-0EErSHEtKPNl5wgWikHJbKFAzJ/k11O0WO2QyqZSHpdxdAnw7UWHY4YiLbHCFG7lhrD+NTQ3Z/H9Jn4rcikoJA==", + "dependencies": { + "@graphql-typed-document-node/core": "^3.1.1", + "@wry/context": "^0.7.0", + "@wry/equality": "^0.5.0", + "@wry/trie": "^0.4.0", + "graphql-tag": "^2.12.6", + "hoist-non-react-statics": "^3.3.2", + "optimism": "^0.16.2", + "prop-types": "^15.7.2", + "response-iterator": "^0.2.6", + "symbol-observable": "^4.0.0", + "ts-invariant": "^0.10.3", + "tslib": "^2.3.0", + "zen-observable-ts": "^1.2.5" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0", + "graphql-ws": "^5.5.5", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", + "subscriptions-transport-ws": "^0.9.0 || ^0.11.0" + }, + "peerDependenciesMeta": { + "graphql-ws": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "subscriptions-transport-ws": { + "optional": true + } + } + }, + "node_modules/@apollo/link-error": { + "version": "2.0.0-beta.3", + "resolved": "https://registry.npmjs.org/@apollo/link-error/-/link-error-2.0.0-beta.3.tgz", + "integrity": "sha512-blNBBi9+4SEfb4Bhn8cYqGFhb0C7MjqLiRwNdUqwGefl1w+G8Ze8pCLHAyPxXLcslirtht9LY0i6ZOpCzSXHCg==", + "dependencies": { + "@apollo/client": "^3.0.0-beta.23", + "tslib": "^1.9.3" + } + }, + "node_modules/@apollo/link-error/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@apollo/react-testing": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@apollo/react-testing/-/react-testing-4.0.0.tgz", + "integrity": "sha512-P7Z/flUHpRRZYc3FkIqxZH9XD3FuP2Sgks1IXqGq2Zb7qI0aaTfVeRsLYmZNUcFOh2pTHxs0NXgPnH1VfYOpig==", + "dependencies": { + "@apollo/client": "latest" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", + "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", + "dependencies": { + "@babel/highlight": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz", + "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.9.tgz", + "integrity": "sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.5", + "@babel/generator": "^7.22.9", + "@babel/helper-compilation-targets": "^7.22.9", + "@babel/helper-module-transforms": "^7.22.9", + "@babel/helpers": "^7.22.6", + "@babel/parser": "^7.22.7", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.8", + "@babel/types": "^7.22.5", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.2", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/eslint-parser": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.22.9.tgz", + "integrity": "sha512-xdMkt39/nviO/4vpVdrEYPwXCsYIXSSAr6mC7WQsNIlGnuxKyKE7GZjalcnbSWiC4OXGNNN3UQPeHfjSC6sTDA==", + "dependencies": { + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || >=14.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.11.0", + "eslint": "^7.5.0 || ^8.0.0" + } + }, + "node_modules/@babel/eslint-parser/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/@babel/eslint-parser/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.9.tgz", + "integrity": "sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==", + "dependencies": { + "@babel/types": "^7.22.5", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.5.tgz", + "integrity": "sha512-m1EP3lVOPptR+2DwD125gziZNcmoNSHGmJROKoy87loWUQyJaVXDgpmruWqDARZSmtYQ+Dl25okU8+qhVzuykw==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.9.tgz", + "integrity": "sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw==", + "dependencies": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.5", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.9.tgz", + "integrity": "sha512-Pwyi89uO4YrGKxL/eNJ8lfEH55DnRloGPOseaA8NFNL6jAUnn+KccaISiFazCj5IolPPDjGSdzQzXVzODVRqUQ==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-member-expression-to-functions": "^7.22.5", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.9.tgz", + "integrity": "sha512-+svjVa/tFwsNSG4NEy1h85+HQ5imbT92Q5/bgtS7P0GTQlP8WuFdqsiABmQouhiFGyV66oGxZFpeYHza1rNsKw==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.1.tgz", + "integrity": "sha512-kX4oXixDxG197yhX+J3Wp+NpL2wuCFjWQAr6yX2jtCnflK9ulMI51ULFGIrWiX1jGfvAxdHp+XQCcP2bZGPs9A==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0-0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", + "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", + "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", + "dependencies": { + "@babel/template": "^7.22.5", + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.5.tgz", + "integrity": "sha512-aBiH1NKMG0H2cGZqspNvsaBe6wNGjbJjuLy29aU+eDZjSbbN53BaxlpB02xm9v34pLTZ1nIQPFYn2qMZoa5BQQ==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", + "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz", + "integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.9.tgz", + "integrity": "sha512-8WWC4oR4Px+tr+Fp0X3RHDVfINGpF3ad1HIbrc8A77epiR6eMMc6jsgozkzT2uDiOOdoS9cLIQ+XD2XvI2WSmQ==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-wrap-function": "^7.22.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.9.tgz", + "integrity": "sha512-LJIKvvpgPOPUThdYqcX6IXRuIcTkcAub0IaDRGCZH0p5GPUp7PhRU9QVgFcDDd51BaPkk77ZjqFwh6DZTAEmGg==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-member-expression-to-functions": "^7.22.5", + "@babel/helper-optimise-call-expression": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", + "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", + "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.9.tgz", + "integrity": "sha512-sZ+QzfauuUEfxSEjKFmi3qDSHgLsTPK/pEpoD/qonZKOtTPTLbf59oabPQ4rKekt9lFcj/hTZaOhWwFYrgjk+Q==", + "dependencies": { + "@babel/helper-function-name": "^7.22.5", + "@babel/template": "^7.22.5", + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz", + "integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==", + "dependencies": { + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.6", + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", + "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.5", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.22.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz", + "integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.5.tgz", + "integrity": "sha512-NP1M5Rf+u2Gw9qfSO4ihjcTGW5zXTi36ITLd4/EoAcEhIZ0yjMqmftDNl3QC19CX7olhrjpyU454g/2W7X0jvQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.5.tgz", + "integrity": "sha512-31Bb65aZaUwqCbWMnZPduIZxCBngHFlzyN6Dq6KAJjtx+lx6ohKHubc61OomYi7XwVD4Ol0XCVz4h+pYFR048g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-decorators": { + "version": "7.22.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.22.7.tgz", + "integrity": "sha512-omXqPF7Onq4Bb7wHxXjM3jSMSJvUUbvDvmmds7KI5n9Cq6Ln5I05I1W2nRlRof1rGdiUxJrxwe285WF96XlBXQ==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/plugin-syntax-decorators": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", + "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-numeric-separator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", + "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-chaining": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", + "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-methods": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", + "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz", + "integrity": "sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.21.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-unicode-property-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", + "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-decorators": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.22.5.tgz", + "integrity": "sha512-avpUOBS7IU6al8MmF1XpAyj9QYeLPuSDJI5D4pVMSMdL7xQokKqJPYQC67RCT0aCTashUXPiGwMJ0DEXXCEmMA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-flow": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.22.5.tgz", + "integrity": "sha512-9RdCl0i+q0QExayk2nOS7853w08yLucnnPML6EN9S8fgMPVtdLDCdx/cOQ/i44Lb9UeQX9A35yaqBBOMMZxPxQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz", + "integrity": "sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.22.5.tgz", + "integrity": "sha512-KwvoWDeNKPETmozyFE0P2rOLqh39EoQHNjqizrI5B8Vt0ZNS7M56s7dAiAqbYfiAYOuIzIh96z3iR2ktgu3tEg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz", + "integrity": "sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.22.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.7.tgz", + "integrity": "sha512-7HmE7pk/Fmke45TODvxvkxRMV9RazV+ZZzhOL9AG8G29TLrr3jkjwF7uJfxZ30EoXpO+LJkq4oA8NjO2DTnEDg==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.5", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.22.5.tgz", + "integrity": "sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz", + "integrity": "sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.5.tgz", + "integrity": "sha512-EcACl1i5fSQ6bt+YGuU/XGCeZKStLmyVGytWkpyhCLeQVA0eu6Wtiw92V+I1T/hnezUv7j74dA/Ro69gWcU+hg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.22.5.tgz", + "integrity": "sha512-nDkQ0NfkOhPTq8YCLiWNxp1+f9fCobEjCb0n8WdbNUBc4IB5V7P1QnX9IjpSoquKrXF5SKojHleVNs2vGeHCHQ==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.5.tgz", + "integrity": "sha512-SPToJ5eYZLxlnp1UzdARpOGeC2GbHvr9d/UV0EukuVx8atktg194oe+C5BqQ8jRTkgLRVOPYeXRSBg1IlMoVRA==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.6.tgz", + "integrity": "sha512-58EgM6nuPNG6Py4Z3zSuu0xWu2VfodiMi72Jt5Kj2FECmaYk1RrTXA45z6KBFsu9tRgwQDwIiY4FXTt+YsSFAQ==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz", + "integrity": "sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/template": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.5.tgz", + "integrity": "sha512-GfqcFuGW8vnEqTUBM7UtPd5A4q797LTvvwKxXTgRsFjoqaJiEg9deBG6kWeQYkVEL569NpnmpC0Pkr/8BLKGnQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz", + "integrity": "sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.22.5.tgz", + "integrity": "sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.5.tgz", + "integrity": "sha512-0MC3ppTB1AMxd8fXjSrbPa7LT9hrImt+/fcj+Pg5YMD7UQyWp/02+JWpdnCymmsXwIx5Z+sYn1bwCn4ZJNvhqQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz", + "integrity": "sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==", + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.5.tgz", + "integrity": "sha512-X4hhm7FRnPgd4nDA4b/5V280xCx6oL7Oob5+9qVS5C13Zq4bh1qq7LU0GgRU6b5dBWBvhGaXYVB4AcN6+ol6vg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-flow-strip-types": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.22.5.tgz", + "integrity": "sha512-tujNbZdxdG0/54g/oua8ISToaXTFBf8EnSb5PgQSciIXWOWKX3S4+JR7ZE9ol8FZwf9kxitzkGQ+QWeov/mCiA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-flow": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.5.tgz", + "integrity": "sha512-3kxQjX1dU9uudwSshyLeEipvrLjBCVthCgeTp6CzE/9JYrlAIaeekVxRpCWsDDfYTfRZRoCeZatCQvwo+wvK8A==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz", + "integrity": "sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.5.tgz", + "integrity": "sha512-DuCRB7fu8MyTLbEQd1ew3R85nx/88yMoqo2uPSjevMj3yoN7CDM8jkgrY0wmVxfJZyJ/B9fE1iq7EQppWQmR5A==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz", + "integrity": "sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.5.tgz", + "integrity": "sha512-MQQOUW1KL8X0cDWfbwYP+TbVbZm16QmQXJQ+vndPtH/BoO0lOKpVoEDMI7+PskYxH+IiE0tS8xZye0qr1lGzSA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz", + "integrity": "sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.22.5.tgz", + "integrity": "sha512-R+PTfLTcYEmb1+kK7FNkhQ1gP4KgjpSO6HfH9+f8/yfp2Nt3ggBjiVpRwmwTlfqZLafYKJACy36yDXlEmI9HjQ==", + "dependencies": { + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.5.tgz", + "integrity": "sha512-B4pzOXj+ONRmuaQTg05b3y/4DuFz3WcCNAXPLb2Q0GT0TrGKGxNKV4jwsXts+StaM0LQczZbOpj8o1DLPDJIiA==", + "dependencies": { + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.22.5.tgz", + "integrity": "sha512-emtEpoaTMsOs6Tzz+nbmcePl6AKVtS1yC4YNAeMun9U8YCsgadPNxnOPQ8GhHFB2qdx+LZu9LgoC0Lthuu05DQ==", + "dependencies": { + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz", + "integrity": "sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==", + "dependencies": { + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", + "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.5.tgz", + "integrity": "sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.5.tgz", + "integrity": "sha512-6CF8g6z1dNYZ/VXok5uYkkBBICHZPiGEl7oDnAx2Mt1hlHVHOSIKWJaXHjQJA5VB43KZnXZDIexMchY4y2PGdA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.5.tgz", + "integrity": "sha512-NbslED1/6M+sXiwwtcAB/nieypGw02Ejf4KtDeMkCEpP6gWFMX1wI9WKYua+4oBneCCEmulOkRpwywypVZzs/g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.5.tgz", + "integrity": "sha512-Kk3lyDmEslH9DnvCDA1s1kkd3YWQITiBOHngOtDL9Pt6BZjzqb6hiOlb8VfjiiQJ2unmegBqZu0rx5RxJb5vmQ==", + "dependencies": { + "@babel/compat-data": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz", + "integrity": "sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.5.tgz", + "integrity": "sha512-pH8orJahy+hzZje5b8e2QIlBWQvGpelS76C63Z+jhZKsmzfNaPQ+LaW6dcJ9bxTpo1mtXbgHwy765Ro3jftmUg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.6.tgz", + "integrity": "sha512-Vd5HiWml0mDVtcLHIoEU5sw6HOUW/Zk0acLs/SAeuLzkGNOPc9DB4nkUajemhCmTIz3eiaKREZn2hQQqF79YTg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.5.tgz", + "integrity": "sha512-AVkFUBurORBREOmHRKo06FjHYgjrabpdqRSwq6+C7R5iTCZOsM4QbcB27St0a4U6fffyAOqh3s/qEfybAhfivg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.22.5.tgz", + "integrity": "sha512-PPjh4gyrQnGe97JTalgRGMuU4icsZFnWkzicB/fUtzlKUqvsWBKEpPPfr5a2JiyirZkHxnAqkQMO5Z5B2kK3fA==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.5.tgz", + "integrity": "sha512-/9xnaTTJcVoBtSSmrVyhtSvO3kbqS2ODoh2juEU72c3aYonNF0OMGiaz2gjukyKM2wBBYJP38S4JiE0Wfb5VMQ==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz", + "integrity": "sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-constant-elements": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.22.5.tgz", + "integrity": "sha512-BF5SXoO+nX3h5OhlN78XbbDrBOffv+AxPP2ENaJOVqjWCgBDeOY3WcaUcddutGSfoap+5NEQ/q/4I3WZIvgkXA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.22.5.tgz", + "integrity": "sha512-PVk3WPYudRF5z4GKMEYUrLjPl38fJSKNaEOkFuoprioowGuWN6w2RKznuFNSlJx7pzzXXStPUnNSOEO0jL5EVw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.5.tgz", + "integrity": "sha512-rog5gZaVbUip5iWDMTYbVM15XQq+RkUKhET/IHR6oizR+JEoN6CAfTTuHcK4vwUyzca30qqHqEpzBOnaRMWYMA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-jsx": "^7.22.5", + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz", + "integrity": "sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==", + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.22.5.tgz", + "integrity": "sha512-gP4k85wx09q+brArVinTXhWiyzLl9UpmGva0+mWyKxk6JZequ05x3eUcIUE+FyttPKJFRRVtAvQaJ6YF9h1ZpA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.5.tgz", + "integrity": "sha512-rR7KePOE7gfEtNTh9Qw+iO3Q/e4DEsoQ+hdvM6QUDH7JRJ5qxq5AA52ZzBWbI5i9lfNuvySgOGP8ZN7LAmaiPw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "regenerator-transform": "^0.15.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz", + "integrity": "sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.22.9.tgz", + "integrity": "sha512-9KjBH61AGJetCPYp/IEyLEp47SyybZb0nDRpBvmtEkm+rUIwxdlKpyNHI1TmsGkeuLclJdleQHRZ8XLBnnh8CQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "babel-plugin-polyfill-corejs2": "^0.4.4", + "babel-plugin-polyfill-corejs3": "^0.8.2", + "babel-plugin-polyfill-regenerator": "^0.5.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz", + "integrity": "sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz", + "integrity": "sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.22.5.tgz", + "integrity": "sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz", + "integrity": "sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.22.5.tgz", + "integrity": "sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.9.tgz", + "integrity": "sha512-BnVR1CpKiuD0iobHPaM1iLvcwPYN2uVFAqoLVSpEDKWuOikoCv5HbKLxclhKYUXlWkX86DoZGtqI4XhbOsyrMg==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.9", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-typescript": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.5.tgz", + "integrity": "sha512-biEmVg1IYB/raUO5wT1tgfacCef15Fbzhkx493D3urBI++6hpJ+RFG4SrWMn0NEZLfvilqKf3QDrRVZHo08FYg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.22.5.tgz", + "integrity": "sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.22.5.tgz", + "integrity": "sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.22.5.tgz", + "integrity": "sha512-lhMfi4FC15j13eKrh3DnYHjpGj6UKQHtNKTbtc1igvAhRy4+kLhV07OpLcsN0VgDEw/MjAvJO4BdMJsHwMhzCg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.22.9.tgz", + "integrity": "sha512-wNi5H/Emkhll/bqPjsjQorSykrlfY5OWakd6AulLvMEytpKasMVUpVy8RL4qBIBs5Ac6/5i0/Rv0b/Fg6Eag/g==", + "dependencies": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-compilation-targets": "^7.22.9", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.5", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.5", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.22.5", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.22.5", + "@babel/plugin-syntax-import-attributes": "^7.22.5", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.22.5", + "@babel/plugin-transform-async-generator-functions": "^7.22.7", + "@babel/plugin-transform-async-to-generator": "^7.22.5", + "@babel/plugin-transform-block-scoped-functions": "^7.22.5", + "@babel/plugin-transform-block-scoping": "^7.22.5", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-class-static-block": "^7.22.5", + "@babel/plugin-transform-classes": "^7.22.6", + "@babel/plugin-transform-computed-properties": "^7.22.5", + "@babel/plugin-transform-destructuring": "^7.22.5", + "@babel/plugin-transform-dotall-regex": "^7.22.5", + "@babel/plugin-transform-duplicate-keys": "^7.22.5", + "@babel/plugin-transform-dynamic-import": "^7.22.5", + "@babel/plugin-transform-exponentiation-operator": "^7.22.5", + "@babel/plugin-transform-export-namespace-from": "^7.22.5", + "@babel/plugin-transform-for-of": "^7.22.5", + "@babel/plugin-transform-function-name": "^7.22.5", + "@babel/plugin-transform-json-strings": "^7.22.5", + "@babel/plugin-transform-literals": "^7.22.5", + "@babel/plugin-transform-logical-assignment-operators": "^7.22.5", + "@babel/plugin-transform-member-expression-literals": "^7.22.5", + "@babel/plugin-transform-modules-amd": "^7.22.5", + "@babel/plugin-transform-modules-commonjs": "^7.22.5", + "@babel/plugin-transform-modules-systemjs": "^7.22.5", + "@babel/plugin-transform-modules-umd": "^7.22.5", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", + "@babel/plugin-transform-new-target": "^7.22.5", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.5", + "@babel/plugin-transform-numeric-separator": "^7.22.5", + "@babel/plugin-transform-object-rest-spread": "^7.22.5", + "@babel/plugin-transform-object-super": "^7.22.5", + "@babel/plugin-transform-optional-catch-binding": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.22.6", + "@babel/plugin-transform-parameters": "^7.22.5", + "@babel/plugin-transform-private-methods": "^7.22.5", + "@babel/plugin-transform-private-property-in-object": "^7.22.5", + "@babel/plugin-transform-property-literals": "^7.22.5", + "@babel/plugin-transform-regenerator": "^7.22.5", + "@babel/plugin-transform-reserved-words": "^7.22.5", + "@babel/plugin-transform-shorthand-properties": "^7.22.5", + "@babel/plugin-transform-spread": "^7.22.5", + "@babel/plugin-transform-sticky-regex": "^7.22.5", + "@babel/plugin-transform-template-literals": "^7.22.5", + "@babel/plugin-transform-typeof-symbol": "^7.22.5", + "@babel/plugin-transform-unicode-escapes": "^7.22.5", + "@babel/plugin-transform-unicode-property-regex": "^7.22.5", + "@babel/plugin-transform-unicode-regex": "^7.22.5", + "@babel/plugin-transform-unicode-sets-regex": "^7.22.5", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.22.5", + "babel-plugin-polyfill-corejs2": "^0.4.4", + "babel-plugin-polyfill-corejs3": "^0.8.2", + "babel-plugin-polyfill-regenerator": "^0.5.1", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", + "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-react": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.22.5.tgz", + "integrity": "sha512-M+Is3WikOpEJHgR385HbuCITPTaPRaNkibTEa9oiofmJvIsrceb4yp9RL9Kb+TE8LznmeyZqpP+Lopwcx59xPQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.5", + "@babel/plugin-transform-react-display-name": "^7.22.5", + "@babel/plugin-transform-react-jsx": "^7.22.5", + "@babel/plugin-transform-react-jsx-development": "^7.22.5", + "@babel/plugin-transform-react-pure-annotations": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.22.5.tgz", + "integrity": "sha512-YbPaal9LxztSGhmndR46FmAbkJ/1fAsw293tSU+I5E5h+cnJ3d4GTwyUgGYmOXJYdGA+uNePle4qbaRzj2NISQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.5", + "@babel/plugin-syntax-jsx": "^7.22.5", + "@babel/plugin-transform-modules-commonjs": "^7.22.5", + "@babel/plugin-transform-typescript": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" + }, + "node_modules/@babel/runtime": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz", + "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime-corejs3": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.22.6.tgz", + "integrity": "sha512-M+37LLIRBTEVjktoJjbw4KVhupF0U/3PYUCbBwgAd9k17hoKhRu1n935QiG7Tuxv0LJOMrb2vuKEeYUlv0iyiw==", + "dependencies": { + "core-js-pure": "^3.30.2", + "regenerator-runtime": "^0.13.11" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime/node_modules/regenerator-runtime": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + }, + "node_modules/@babel/template": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", + "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", + "dependencies": { + "@babel/code-frame": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.22.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz", + "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==", + "dependencies": { + "@babel/code-frame": "^7.22.5", + "@babel/generator": "^7.22.7", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.22.7", + "@babel/types": "^7.22.5", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", + "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" + }, + "node_modules/@cnakazawa/watch": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.4.tgz", + "integrity": "sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ==", + "dev": true, + "dependencies": { + "exec-sh": "^0.3.2", + "minimist": "^1.2.0" + }, + "bin": { + "watch": "cli.js" + }, + "engines": { + "node": ">=0.1.95" + } + }, + "node_modules/@csstools/normalize.css": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-12.0.0.tgz", + "integrity": "sha512-M0qqxAcwCsIVfpFQSlGN5XjXWu8l5JDZN+fPt1LeW5SZexQTgnaEvgXAY+CeygRw0EeppWHi12JxESWiWrB0Sg==" + }, + "node_modules/@csstools/postcss-cascade-layers": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-1.1.1.tgz", + "integrity": "sha512-+KdYrpKC5TgomQr2DlZF4lDEpHcoxnj5IGddYYfBWJAKfj1JtuHUIqMa+E1pJJ+z3kvDViWMqyqPlG4Ja7amQA==", + "dependencies": { + "@csstools/selector-specificity": "^2.0.2", + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-color-function": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-1.1.1.tgz", + "integrity": "sha512-Bc0f62WmHdtRDjf5f3e2STwRAl89N2CLb+9iAwzrv4L2hncrbDwnQD9PCq0gtAt7pOI2leIV08HIBUd4jxD8cw==", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "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-font-format-keywords": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-1.0.1.tgz", + "integrity": "sha512-ZgrlzuUAjXIOc2JueK0X5sZDjCtgimVp/O5CEqTcs5ShWBa6smhWYbS0x5cVc/+rycTDbjjzoP0KTDnUneZGOg==", + "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-hwb-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-1.0.2.tgz", + "integrity": "sha512-YHdEru4o3Rsbjmu6vHy4UKOXZD+Rn2zmkAmLRfPet6+Jz4Ojw8cbWxe1n42VaXQhD3CQUXXTooIy8OkVbUcL+w==", + "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-ic-unit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-1.0.1.tgz", + "integrity": "sha512-Ot1rcwRAaRHNKC9tAqoqNZhjdYBzKk1POgWfhN4uCOE47ebGcLRqXjKkApVDpjifL6u2/55ekkpnFcp+s/OZUw==", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "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-is-pseudo-class": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-2.0.7.tgz", + "integrity": "sha512-7JPeVVZHd+jxYdULl87lvjgvWldYu+Bc62s9vD/ED6/QTGjy0jy0US/f6BG53sVMTBJ1lzKZFpYmofBN9eaRiA==", + "dependencies": { + "@csstools/selector-specificity": "^2.0.0", + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "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", + "integrity": "sha512-jcOanIbv55OFKQ3sYeFD/T0Ti7AMXc9nM1hZWu8m/2722gOTxFg7xYu4RDLJLeZmPUVQlGzo4jhzvTUq3x4ZUw==", + "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-oklab-function": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-1.1.1.tgz", + "integrity": "sha512-nJpJgsdA3dA9y5pgyb/UfEzE7W5Ka7u0CX0/HIMVBNWzWemdcTH3XwANECU6anWv/ao4vVNLTMxhiPNZsTK6iA==", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "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-progressive-custom-properties": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-1.3.0.tgz", + "integrity": "sha512-ASA9W1aIy5ygskZYuWams4BzafD12ULvSypmaLJT2jvQ8G0M3I8PRQhC0h7mG0Z3LI05+agZjqSR9+K9yaQQjA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/@csstools/postcss-stepped-value-functions": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-1.0.1.tgz", + "integrity": "sha512-dz0LNoo3ijpTOQqEJLY8nyaapl6umbmDcgj4AD0lgVQ572b2eqA1iGZYTTWhrcrHztWDDRAX2DGYyw2VBjvCvQ==", + "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-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", + "integrity": "sha512-woKaLO///4bb+zZC2s80l+7cm07M7268MsyG3M0ActXXEFi6SuhvriQYcb58iiKGbjwwIU7n45iRLEHypB47Og==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-unset-value": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-1.0.2.tgz", + "integrity": "sha512-c8J4roPBILnelAsdLr4XOAR/GsTm0GJi4XpcfvoWk3U6KiTCqiFYc63KhRMQQX35jYMp4Ao8Ij9+IZRgMfJp1g==", + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/selector-specificity": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz", + "integrity": "sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==", + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss-selector-parser": "^6.0.10" + } + }, + "node_modules/@emotion/babel-plugin": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", + "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/serialize": "^1.1.2", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/cache": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", + "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", + "dependencies": { + "@emotion/memoize": "^0.8.1", + "@emotion/sheet": "^1.2.2", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", + "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==", + "dependencies": { + "@emotion/memoize": "^0.8.1" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "node_modules/@emotion/react": { + "version": "11.11.1", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.1.tgz", + "integrity": "sha512-5mlW1DquU5HaxjLkfkGN1GA/fvVGdyHURRiX/0FHl2cfIfRxSOfmxEH5YS43edp0OldZrZ+dkBKbngxcNCdZvA==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.11.0", + "@emotion/cache": "^11.11.0", + "@emotion/serialize": "^1.1.2", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.2.tgz", + "integrity": "sha512-zR6a/fkFP4EAcCMQtLOhIgpprZOwNmCldtpaISpvz348+DP4Mz8ZoKaGGCQpbzepNIUWbq4w6hNZkwDyKoS+HA==", + "dependencies": { + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/unitless": "^0.8.1", + "@emotion/utils": "^1.2.1", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", + "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" + }, + "node_modules/@emotion/styled": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.0.tgz", + "integrity": "sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.11.0", + "@emotion/is-prop-valid": "^1.2.1", + "@emotion/serialize": "^1.1.2", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", + "@emotion/utils": "^1.2.1" + }, + "peerDependencies": { + "@emotion/react": "^11.0.0-rc.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", + "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", + "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", + "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", + "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz", + "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "8.44.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz", + "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.5.0.tgz", + "integrity": "sha512-kK1h4m36DQ0UHGj5Ah4db7R0rHemTqqO0QLvUqi1/mUUp3LuAWbWxdxSIf/XsnH9VS6rRVPLJCncjRzUvyCLXg==", + "dependencies": { + "@floating-ui/utils": "^0.1.3" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.3.tgz", + "integrity": "sha512-ClAbQnEqJAKCJOEbbLo5IUlZHkNszqhuxS4fHAVxRPXPya6Ysf2G8KypnYcOTpx6I8xcgF9bbHb6g/2KpbV8qA==", + "dependencies": { + "@floating-ui/core": "^1.4.2", + "@floating-ui/utils": "^0.1.3" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.2.tgz", + "integrity": "sha512-5qhlDvjaLmAst/rKb3VdlCinwTF4EYMiVxuuc/HVUjs46W0zgtbMmAZ1UTsDrRTxRmUEzl92mOtWbeeXL26lSQ==", + "dependencies": { + "@floating-ui/dom": "^1.5.1" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.6.tgz", + "integrity": "sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==" + }, + "node_modules/@fortawesome/fontawesome-common-types": { + "version": "0.2.36", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz", + "integrity": "sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg==", + "dev": true, + "hasInstallScript": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/fontawesome-svg-core": { + "version": "1.2.36", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.36.tgz", + "integrity": "sha512-YUcsLQKYb6DmaJjIHdDWpBIGCcyE/W+p/LMGvjQem55Mm2XWVAP5kWTMKWLv9lwpCVjpLxPyOMOyUocP1GxrtA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "^0.2.36" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-brands-svg-icons": { + "version": "5.15.4", + "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-5.15.4.tgz", + "integrity": "sha512-f1witbwycL9cTENJegcmcZRYyawAFbm8+c6IirLmwbbpqz46wyjbQYLuxOc7weXFXfB7QR8/Vd2u5R3q6JYD9g==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "^0.2.36" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/react-fontawesome": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.19.tgz", + "integrity": "sha512-Hyb+lB8T18cvLNX0S3llz7PcSOAJMLwiVKBuuzwM/nI5uoBw+gQjnf9il0fR1C3DKOI5Kc79pkJ4/xB0Uw9aFQ==", + "dev": true, + "dependencies": { + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "@fortawesome/fontawesome-svg-core": "~1 || ~6", + "react": ">=16.x" + } + }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==" + }, + "node_modules/@graphql-typed-document-node/core": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", + "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", + "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "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", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jedmao/location": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@jedmao/location/-/location-3.0.0.tgz", + "integrity": "sha512-p7mzNlgJbCioUYLUEKds3cQG4CHONVFJNYqMe6ocEtENCL/jYmMo1Q3ApwsMmU+L0ZkaDJEyv4HokaByLoPwlQ==", + "dev": true + }, + "node_modules/@jest/console": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", + "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/console/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/core": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", + "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/reporters": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^27.5.1", + "jest-config": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-resolve-dependencies": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "jest-watcher": "^27.5.1", + "micromatch": "^4.0.4", + "rimraf": "^3.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/core/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/environment": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", + "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "dependencies": { + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", + "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "dependencies": { + "@jest/types": "^27.5.1", + "@sinonjs/fake-timers": "^8.0.1", + "@types/node": "*", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", + "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/types": "^27.5.1", + "expect": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", + "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.2", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-haste-map": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "slash": "^3.0.0", + "source-map": "^0.6.0", + "string-length": "^4.0.1", + "terminal-link": "^2.0.0", + "v8-to-istanbul": "^8.1.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/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/reporters/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@jest/schemas": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", + "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", + "dependencies": { + "@sinclair/typebox": "^0.24.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", + "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", + "dependencies": { + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9", + "source-map": "^0.6.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/source-map/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@jest/test-result": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", + "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", + "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", + "dependencies": { + "@jest/test-result": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-runtime": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "dependencies": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/transform/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/transform/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/types/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/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.18", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", + "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "dependencies": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", + "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" + }, + "node_modules/@mui/base": { + "version": "5.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.17.tgz", + "integrity": "sha512-xNbk7iOXrglNdIxFBN0k3ySsPIFLWCnFxqsAYl7CIcDkD9low4kJ7IUuy6ctwx/HAy2fenrT3KXHr1sGjAMgpQ==", + "dependencies": { + "@babel/runtime": "^7.22.15", + "@floating-ui/react-dom": "^2.0.2", + "@mui/types": "^7.2.4", + "@mui/utils": "^5.14.11", + "@popperjs/core": "^2.11.8", + "clsx": "^2.0.0", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/base/node_modules/clsx": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", + "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@mui/core-downloads-tracker": { + "version": "5.14.11", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.14.11.tgz", + "integrity": "sha512-uY8FLQURhXe3f3O4dS5OSGML9KDm9+IE226cBu78jarVIzdQGPlXwGIlSI9VJR8MvZDA6C0+6XfWDhWCHruC5Q==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui" + } + }, + "node_modules/@mui/icons-material": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.14.0.tgz", + "integrity": "sha512-z7lYNteDi1GMkF9JP/m2RWuCYK1M/FlaeBSUK7/IhIYzIXNhAVjfD8jRq5vFBV31qkEi2aGBS2z5SfLXwH6U0A==", + "dependencies": { + "@babel/runtime": "^7.22.5" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui" + }, + "peerDependencies": { + "@mui/material": "^5.0.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material": { + "version": "5.14.11", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.14.11.tgz", + "integrity": "sha512-DnSdJzcR7lwG12JA5L2t8JF+RDzMygu5rCNW+logWb/KW2/TRzwLyVWO+CorHTBjBRd38DBxnwOCDiYkDd+N3A==", + "dependencies": { + "@babel/runtime": "^7.22.15", + "@mui/base": "5.0.0-beta.17", + "@mui/core-downloads-tracker": "^5.14.11", + "@mui/system": "^5.14.11", + "@mui/types": "^7.2.4", + "@mui/utils": "^5.14.11", + "@types/react-transition-group": "^4.4.6", + "clsx": "^2.0.0", + "csstype": "^3.1.2", + "prop-types": "^15.8.1", + "react-is": "^18.2.0", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material/node_modules/clsx": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", + "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@mui/private-theming": { + "version": "5.14.15", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.14.15.tgz", + "integrity": "sha512-V2Xh+Tu6A07NoSpup0P9m29GwvNMYl5DegsGWqlOTJyAV7cuuVjmVPqxgvL8xBng4R85xqIQJRMjtYYktoPNuQ==", + "dependencies": { + "@babel/runtime": "^7.23.2", + "@mui/utils": "^5.14.15", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/styled-engine": { + "version": "5.14.15", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.14.15.tgz", + "integrity": "sha512-mbOjRf867BysNpexe5Z/P8s3bWzDPNowmKhi7gtNDP/LPEeqAfiDSuC4WPTXmtvse1dCl30Nl755OLUYuoi7Mw==", + "dependencies": { + "@babel/runtime": "^7.23.2", + "@emotion/cache": "^11.11.0", + "csstype": "^3.1.2", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui" + }, + "peerDependencies": { + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/system": { + "version": "5.14.15", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.14.15.tgz", + "integrity": "sha512-zr0Gdk1RgKiEk+tCMB900LaOpEC8NaGvxtkmMdL/CXgkqQZSVZOt2PQsxJWaw7kE4YVkIe4VukFVc43qcq9u3w==", + "dependencies": { + "@babel/runtime": "^7.23.2", + "@mui/private-theming": "^5.14.15", + "@mui/styled-engine": "^5.14.15", + "@mui/types": "^7.2.7", + "@mui/utils": "^5.14.15", + "clsx": "^2.0.0", + "csstype": "^3.1.2", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/system/node_modules/clsx": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", + "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@mui/types": { + "version": "7.2.7", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.7.tgz", + "integrity": "sha512-sofpWmcBqOlTzRbr1cLQuUDKaUYVZTw8ENQrtL39TECRNENEzwgnNPh6WMfqMZlMvf1Aj9DLg74XPjnLr0izUQ==", + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils": { + "version": "5.14.15", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.14.15.tgz", + "integrity": "sha512-QBfHovAvTa0J1jXuYDaXGk+Yyp7+Fm8GSqx6nK2JbezGqzCFfirNdop/+bL9Flh/OQ/64PeXcW4HGDdOge+n3A==", + "dependencies": { + "@babel/runtime": "^7.23.2", + "@types/prop-types": "^15.7.8", + "prop-types": "^15.8.1", + "react-is": "^18.2.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/x-charts": { + "version": "6.0.0-alpha.13", + "resolved": "https://registry.npmjs.org/@mui/x-charts/-/x-charts-6.0.0-alpha.13.tgz", + "integrity": "sha512-/FfH55kkhbP3IRbQczvcysp78iTMllqHC4RUDz4wskQVMVCep32slv77aTfgP+XWtMx9lEHPGse238OKwUKLEA==", + "dependencies": { + "@babel/runtime": "^7.22.15", + "@mui/base": "^5.0.0-beta.14", + "clsx": "^2.0.0", + "d3-color": "^3.1.0", + "d3-scale": "^4.0.2", + "d3-shape": "^3.2.0", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "@emotion/react": "^11.9.0", + "@emotion/styled": "^11.8.1", + "@mui/material": "^5.4.1", + "@mui/system": "^5.4.1", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/x-charts/node_modules/clsx": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", + "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@mui/x-data-grid": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-6.10.0.tgz", + "integrity": "sha512-x9h+Z4B2vu+ZKKwClBVs30Y9eZYdhqyV3toHH2E0zat7FIZxwiVfk6qz4Q98V1fV0Fe1nczPj9i0siUmduMEXg==", + "dependencies": { + "@babel/runtime": "^7.22.5", + "@mui/utils": "^5.13.6", + "clsx": "^1.2.1", + "prop-types": "^15.8.1", + "reselect": "^4.1.8" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui" + }, + "peerDependencies": { + "@mui/material": "^5.4.1", + "@mui/system": "^5.4.1", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + } + }, + "node_modules/@mui/x-date-pickers": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-6.10.0.tgz", + "integrity": "sha512-tp0i65JqZarIRyyTyQy5OjOPgjJv5cO7oQAbOrAePIHn7UEYPXe3k4ISiUzEAjBBXy1HhwQxGRJslVp4BXe3MA==", + "dependencies": { + "@babel/runtime": "^7.22.5", + "@mui/utils": "^5.13.6", + "@types/react-transition-group": "^4.4.6", + "clsx": "^1.2.1", + "prop-types": "^15.8.1", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui" + }, + "peerDependencies": { + "@emotion/react": "^11.9.0", + "@emotion/styled": "^11.8.1", + "@mui/base": "^5.0.0-alpha.87", + "@mui/material": "^5.8.6", + "@mui/system": "^5.8.0", + "date-fns": "^2.25.0", + "date-fns-jalali": "^2.13.0-0", + "dayjs": "^1.10.7", + "luxon": "^3.0.2", + "moment": "^2.29.4", + "moment-hijri": "^2.1.2", + "moment-jalaali": "^0.7.4 || ^0.8.0 || ^0.9.0 || ^0.10.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "date-fns": { + "optional": true + }, + "date-fns-jalali": { + "optional": true + }, + "dayjs": { + "optional": true + }, + "luxon": { + "optional": true + }, + "moment": { + "optional": true + }, + "moment-hijri": { + "optional": true + }, + "moment-jalaali": { + "optional": true + } + } + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "dependencies": { + "eslint-scope": "5.1.1" + } + }, + "node_modules/@nicolo-ribaudo/semver-v6": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/semver-v6/-/semver-v6-6.3.3.tgz", + "integrity": "sha512-3Yc1fUTs69MG/uZbJlLSI3JISMn2UV2rg+1D/vROUqZyh3l6iYHCs7GMp+M40ZD7yOdDbYjJcU1oTJhrc+dGKg==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@npmcli/fs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", + "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", + "dependencies": { + "@gar/promisify": "^1.1.3", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/move-file": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", + "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@pdf-lib/standard-fonts": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz", + "integrity": "sha512-hU30BK9IUN/su0Mn9VdlVKsWBS6GyhVfqjwl1FjZN4TxP6cCw0jP2w7V3Hf5uX7M0AZJ16vey9yE0ny7Sa59ZA==", + "dependencies": { + "pako": "^1.0.6" + } + }, + "node_modules/@pdf-lib/upng": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@pdf-lib/upng/-/upng-1.0.1.tgz", + "integrity": "sha512-dQK2FUMQtowVP00mtIksrlZhdFXQZPC+taih1q4CvPZ5vqdxR/LKBaFg0oAfzd1GlHZXXSPdQfzQnt+ViGvEIQ==", + "dependencies": { + "pako": "^1.0.10" + } + }, + "node_modules/@pdfme/common": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@pdfme/common/-/common-1.2.6.tgz", + "integrity": "sha512-ROmQ/iMUdmFS2QXD/kKDdcU5T6H3azDs2b1hE/OXs8531BPZ9ABbu9+1NRZQoNK4U/zP2F+Osb/B8ckr9lAmGg==", + "dependencies": { + "buffer": "^6.0.3", + "fontkit": "^2.0.2", + "zod": "^3.20.2" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pdfme/generator": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@pdfme/generator/-/generator-1.2.6.tgz", + "integrity": "sha512-rAkhr4vYa0OxVubAvLI/UIgD9+sCrcBG1SZpFCBVILgZjpqkUsscXdyukRtmHP6WaNAFGINch6PZVoshyQdGPw==", + "dependencies": { + "@pdfme/common": "latest", + "@pdfme/pdf-lib": "^1.17.3", + "atob": "^2.1.2", + "bwip-js": "^3.2.2", + "fontkit": "^2.0.2" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pdfme/pdf-lib": { + "version": "1.17.3", + "resolved": "https://registry.npmjs.org/@pdfme/pdf-lib/-/pdf-lib-1.17.3.tgz", + "integrity": "sha512-k3cyms42I7jVycwDuzZuLD7A9J/D8Ud1iGJ7BpAfF54QYKxG0mUG6jTDJnc+tHrpNrsoJ4iFqERy5XvMQ6SUsA==", + "dependencies": { + "@pdf-lib/standard-fonts": "^1.0.0", + "@pdf-lib/upng": "^1.0.1", + "pako": "^1.0.11", + "tslib": "^1.11.1" + } + }, + "node_modules/@pdfme/pdf-lib/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@pmmmwh/react-refresh-webpack-plugin": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.10.tgz", + "integrity": "sha512-j0Ya0hCFZPd4x40qLzbhGsh9TMtdb+CJQiso+WxLOPNasohq9cc5SNUcwsZaRH6++Xh91Xkm/xHCkuIiIu0LUA==", + "dependencies": { + "ansi-html-community": "^0.0.8", + "common-path-prefix": "^3.0.0", + "core-js-pure": "^3.23.3", + "error-stack-parser": "^2.0.6", + "find-up": "^5.0.0", + "html-entities": "^2.1.0", + "loader-utils": "^2.0.4", + "schema-utils": "^3.0.0", + "source-map": "^0.7.3" + }, + "engines": { + "node": ">= 10.13" + }, + "peerDependencies": { + "@types/webpack": "4.x || 5.x", + "react-refresh": ">=0.10.0 <1.0.0", + "sockjs-client": "^1.4.0", + "type-fest": ">=0.17.0 <4.0.0", + "webpack": ">=4.43.0 <6.0.0", + "webpack-dev-server": "3.x || 4.x", + "webpack-hot-middleware": "2.x", + "webpack-plugin-serve": "0.x || 1.x" + }, + "peerDependenciesMeta": { + "@types/webpack": { + "optional": true + }, + "sockjs-client": { + "optional": true + }, + "type-fest": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + }, + "webpack-hot-middleware": { + "optional": true + }, + "webpack-plugin-serve": { + "optional": true + } + } + }, + "node_modules/@pmmmwh/react-refresh-webpack-plugin/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@pmmmwh/react-refresh-webpack-plugin/node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/@pmmmwh/react-refresh-webpack-plugin/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@pmmmwh/react-refresh-webpack-plugin/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@pmmmwh/react-refresh-webpack-plugin/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@pmmmwh/react-refresh-webpack-plugin/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@polka/url": { + "version": "1.0.0-next.21", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz", + "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==", + "dev": true + }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@react-aria/ssr": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.7.0.tgz", + "integrity": "sha512-bfufjg4ESE5giN+Fxj1XIzS5f/YIhqcGc+Ve+vUUKU8xZ8t/Xtjlv8F3kjqDBQdk//n3mluFY7xG1wQVB9rMLQ==", + "dependencies": { + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/ssr/node_modules/@swc/helpers": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.1.tgz", + "integrity": "sha512-sJ902EfIzn1Fa+qYmjdQqh8tPsoxyBz+8yBKC2HKUxyezKJFwPGOn7pv4WY6QuQW//ySQi5lJjA/ZT9sNWWNTg==", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@restart/hooks": { + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.10.tgz", + "integrity": "sha512-HVZhYHb+9xnN6vDPyiTmw6N4V5wD9tatL3y0zpHFeeatP1ooOD1edzd3MnJCXYlb3OeleDg+Vv16EikGrH57eA==", + "dependencies": { + "dequal": "^2.0.3" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@restart/ui": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.6.6.tgz", + "integrity": "sha512-eC3puKuWE1SRYbojWHXnvCNHGgf3uzHCb6JOhnF4OXPibOIPEkR1sqDSkL643ydigxwh+ruCa1CmYHlzk7ikKA==", + "dependencies": { + "@babel/runtime": "^7.21.0", + "@popperjs/core": "^2.11.6", + "@react-aria/ssr": "^3.5.0", + "@restart/hooks": "^0.4.9", + "@types/warning": "^3.0.0", + "dequal": "^2.0.3", + "dom-helpers": "^5.2.0", + "uncontrollable": "^8.0.1", + "warning": "^4.0.3" + }, + "peerDependencies": { + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + } + }, + "node_modules/@restart/ui/node_modules/uncontrollable": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-8.0.2.tgz", + "integrity": "sha512-/GDx+K1STGtpgTsj5Dj3J51YaKxZDblbCQHTH1zHLuoBEWodj6MjtRVv3TUijj1JYLRLSFsFzN8NV4M3QV4d9w==", + "peerDependencies": { + "react": ">=16.14.0" + } + }, + "node_modules/@rollup/plugin-babel": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", + "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", + "dependencies": { + "@babel/helper-module-imports": "^7.10.4", + "@rollup/pluginutils": "^3.1.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "@types/babel__core": "^7.1.9", + "rollup": "^1.20.0||^2.0.0" + }, + "peerDependenciesMeta": { + "@types/babel__core": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", + "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==", + "dependencies": { + "@rollup/pluginutils": "^3.1.0", + "@types/resolve": "1.17.1", + "builtin-modules": "^3.1.0", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@rollup/plugin-replace": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz", + "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==", + "dependencies": { + "@rollup/pluginutils": "^3.1.0", + "magic-string": "^0.25.7" + }, + "peerDependencies": { + "rollup": "^1.20.0 || ^2.0.0" + } + }, + "node_modules/@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dependencies": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@rollup/pluginutils/node_modules/@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==" + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.3.2.tgz", + "integrity": "sha512-V+MvGwaHH03hYhY+k6Ef/xKd6RYlc4q8WBx+2ANmipHJcKuktNcI/NgEsJgdSUF6Lw32njT6OnrRsKYCdgHjYw==" + }, + "node_modules/@sinclair/typebox": { + "version": "0.24.51", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", + "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==" + }, + "node_modules/@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sinonjs/commons": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", + "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/@surma/rollup-plugin-off-main-thread": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", + "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==", + "dependencies": { + "ejs": "^3.1.6", + "json5": "^2.2.0", + "magic-string": "^0.25.0", + "string.prototype.matchall": "^4.0.6" + } + }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.5.1.tgz", + "integrity": "sha512-9PYGcXrAxitycIjRmZB+Q0JaN07GZIWaTBIGQzfaZv+qr1n8X1XUEJ5rZ/vx6OVD9RRYlrNnXWExQXcmZeD/BQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.5.1.tgz", + "integrity": "sha512-8DPaVVE3fd5JKuIC29dqyMB54sA6mfgki2H2+swh+zNJoynC8pMPzOkidqHOSc6Wj032fhl8Z0TVn1GiPpAiJg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.5.1.tgz", + "integrity": "sha512-FwOEi0Il72iAzlkaHrlemVurgSQRDFbk0OC8dSvD5fSBPHltNh7JtLsxmZUhjYBZo2PpcU/RJvvi6Q0l7O7ogw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.5.1.tgz", + "integrity": "sha512-gWGsiwjb4tw+ITOJ86ndY/DZZ6cuXMNE/SjcDRg+HLuCmwpcjOktwRF9WgAiycTqJD/QXqL2f8IzE2Rzh7aVXA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.5.1.tgz", + "integrity": "sha512-2jT3nTayyYP7kI6aGutkyfJ7UMGtuguD72OjeGLwVNyfPRBD8zQthlvL+fAbAKk5n9ZNcvFkp/b1lZ7VsYqVJg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.5.1.tgz", + "integrity": "sha512-a1p6LF5Jt33O3rZoVRBqdxL350oge54iZWHNI6LJB5tQ7EelvD/Mb1mfBiZNAan0dt4i3VArkFRjA4iObuNykQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-6.5.1.tgz", + "integrity": "sha512-6127fvO/FF2oi5EzSQOAjo1LE3OtNVh11R+/8FXa+mHx1ptAaS4cknIjnUA7e6j6fwGGJ17NzaTJFUwOV2zwCw==", + "dev": true, + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "^6.5.1", + "@svgr/babel-plugin-remove-jsx-attribute": "*", + "@svgr/babel-plugin-remove-jsx-empty-expression": "*", + "@svgr/babel-plugin-replace-jsx-attribute-value": "^6.5.1", + "@svgr/babel-plugin-svg-dynamic-title": "^6.5.1", + "@svgr/babel-plugin-svg-em-dimensions": "^6.5.1", + "@svgr/babel-plugin-transform-react-native-svg": "^6.5.1", + "@svgr/babel-plugin-transform-svg-component": "^6.5.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/core": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-6.5.1.tgz", + "integrity": "sha512-/xdLSWxK5QkqG524ONSjvg3V/FkNyCv538OIBdQqPNaAta3AsXj/Bd2FbvR87yMbXO2hFSWiAe/Q6IkVPDw+mw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.19.6", + "@svgr/babel-preset": "^6.5.1", + "@svgr/plugin-jsx": "^6.5.1", + "camelcase": "^6.2.0", + "cosmiconfig": "^7.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/core/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.5.1.tgz", + "integrity": "sha512-1hnUxxjd83EAxbL4a0JDJoD3Dao3hmjvyvyEV8PzWmLK3B9m9NPlW7GKjFyoWE8nM7HnXzPcmmSyOW8yOddSXw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.0", + "entities": "^4.4.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-6.5.1.tgz", + "integrity": "sha512-+UdQxI3jgtSjCykNSlEMuy1jSRQlGC7pqBCPvkG/2dATdWo082zHTTK3uhnAju2/6XpE6B5mZ3z4Z8Ns01S8Gw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.19.6", + "@svgr/babel-preset": "^6.5.1", + "@svgr/hast-util-to-babel-ast": "^6.5.1", + "svg-parser": "^2.0.4" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "^6.0.0" + } + }, + "node_modules/@svgr/plugin-svgo": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-5.5.0.tgz", + "integrity": "sha512-r5swKk46GuQl4RrVejVwpeeJaydoxkdwkM1mBKOgJLBUJPGaLci6ylg/IjhrRsREKDkr4kbMWdgOtbXEh0fyLQ==", + "dependencies": { + "cosmiconfig": "^7.0.0", + "deepmerge": "^4.2.2", + "svgo": "^1.2.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/webpack": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-5.5.0.tgz", + "integrity": "sha512-DOBOK255wfQxguUta2INKkzPj6AIS6iafZYiYmHn6W3pHlycSRRlvWKCfLDG10fXfLWqE3DJHgRUOyJYmARa7g==", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/plugin-transform-react-constant-elements": "^7.12.1", + "@babel/preset-env": "^7.12.1", + "@babel/preset-react": "^7.12.5", + "@svgr/core": "^5.5.0", + "@svgr/plugin-jsx": "^5.5.0", + "@svgr/plugin-svgo": "^5.5.0", + "loader-utils": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/webpack/node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz", + "integrity": "sha512-ZFf2gs/8/6B8PnSofI0inYXr2SDNTDScPXhN7k5EqD4aZ3gi6u+rbmZHVB8IM3wDyx8ntKACZbtXSm7oZGRqVg==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/webpack/node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-5.4.0.tgz", + "integrity": "sha512-yaS4o2PgUtwLFGTKbsiAy6D0o3ugcUhWK0Z45umJ66EPWunAz9fuFw2gJuje6wqQvQWOTJvIahUwndOXb7QCPg==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/webpack/node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-5.0.1.tgz", + "integrity": "sha512-LA72+88A11ND/yFIMzyuLRSMJ+tRKeYKeQ+mR3DcAZ5I4h5CPWN9AHyUzJbWSYp/u2u0xhmgOe0+E41+GjEueA==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/webpack/node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-5.0.1.tgz", + "integrity": "sha512-PoiE6ZD2Eiy5mK+fjHqwGOS+IXX0wq/YDtNyIgOrc6ejFnxN4b13pRpiIPbtPwHEc+NT2KCjteAcq33/F1Y9KQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/webpack/node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-5.4.0.tgz", + "integrity": "sha512-zSOZH8PdZOpuG1ZVx/cLVePB2ibo3WPpqo7gFIjLV9a0QsuQAzJiwwqmuEdTaW2pegyBE17Uu15mOgOcgabQZg==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/webpack/node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-5.4.0.tgz", + "integrity": "sha512-cPzDbDA5oT/sPXDCUYoVXEmm3VIoAWAPT6mSPTJNbQaBNUuEKVKyGH93oDY4e42PYHRW67N5alJx/eEol20abw==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/webpack/node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-5.4.0.tgz", + "integrity": "sha512-3eYP/SaopZ41GHwXma7Rmxcv9uRslRDTY1estspeB1w1ueZWd/tPlMfEOoccYpEMZU3jD4OU7YitnXcF5hLW2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/webpack/node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-5.5.0.tgz", + "integrity": "sha512-q4jSH1UUvbrsOtlo/tKcgSeiCHRSBdXoIoqX1pgcKK/aU3JD27wmMKwGtpB8qRYUYoyXvfGxUVKchLuR5pB3rQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/webpack/node_modules/@svgr/babel-preset": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-5.5.0.tgz", + "integrity": "sha512-4FiXBjvQ+z2j7yASeGPEi8VD/5rrGQk4Xrq3EdJmoZgz/tpqChpo5hgXDvmEauwtvOc52q8ghhZK4Oy7qph4ig==", + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "^5.4.0", + "@svgr/babel-plugin-remove-jsx-attribute": "^5.4.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "^5.0.1", + "@svgr/babel-plugin-replace-jsx-attribute-value": "^5.0.1", + "@svgr/babel-plugin-svg-dynamic-title": "^5.4.0", + "@svgr/babel-plugin-svg-em-dimensions": "^5.4.0", + "@svgr/babel-plugin-transform-react-native-svg": "^5.4.0", + "@svgr/babel-plugin-transform-svg-component": "^5.5.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/webpack/node_modules/@svgr/core": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-5.5.0.tgz", + "integrity": "sha512-q52VOcsJPvV3jO1wkPtzTuKlvX7Y3xIcWRpCMtBF3MrteZJtBfQw/+u0B1BHy5ColpQc1/YVTrPEtSYIMNZlrQ==", + "dependencies": { + "@svgr/plugin-jsx": "^5.5.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^7.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/webpack/node_modules/@svgr/hast-util-to-babel-ast": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-5.5.0.tgz", + "integrity": "sha512-cAaR/CAiZRB8GP32N+1jocovUtvlj0+e65TB50/6Lcime+EA49m/8l+P2ko+XPJ4dw3xaPS3jOL4F2X4KWxoeQ==", + "dependencies": { + "@babel/types": "^7.12.6" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/webpack/node_modules/@svgr/plugin-jsx": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-5.5.0.tgz", + "integrity": "sha512-V/wVh33j12hGh05IDg8GpIUXbjAPnTdPTKuP4VNLggnwaHMPNQNae2pRnyTAILWCQdz5GyMqtO488g7CKM8CBA==", + "dependencies": { + "@babel/core": "^7.12.3", + "@svgr/babel-preset": "^5.5.0", + "@svgr/hast-util-to-babel-ast": "^5.5.0", + "svg-parser": "^2.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/webpack/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@svgr/webpack/node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/@swc/helpers": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", + "integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "dependencies": { + "defer-to-connect": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@testing-library/dom": { + "version": "7.31.2", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.31.2.tgz", + "integrity": "sha512-3UqjCpey6HiTZT92vODYLPxTBWlM8ZOOjr3LX5F37/VRipW2M1kX6I/Cm4VXzteZqfGfagg8yXywpcOgQBlNsQ==", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^4.2.0", + "aria-query": "^4.2.2", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.6", + "lz-string": "^1.4.4", + "pretty-format": "^26.6.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@testing-library/dom/node_modules/aria-query": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", + "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", + "dependencies": { + "@babel/runtime": "^7.10.2", + "@babel/runtime-corejs3": "^7.10.2" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/@testing-library/dom/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/@testing-library/jest-dom": { + "version": "5.16.5", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz", + "integrity": "sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA==", + "dependencies": { + "@adobe/css-tools": "^4.0.1", + "@babel/runtime": "^7.9.2", + "@types/testing-library__jest-dom": "^5.9.1", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.5.6", + "lodash": "^4.17.15", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=8", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/@testing-library/react": { + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-11.2.7.tgz", + "integrity": "sha512-tzRNp7pzd5QmbtXNG/mhdcl7Awfu/Iz1RaVHY75zTdOkmHCuzMhRL83gWHSgOAcjS3CCbyfwUHMZgRJb4kAfpA==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^7.28.1" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/@testing-library/user-event": { + "version": "12.8.3", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-12.8.3.tgz", + "integrity": "sha512-IR0iWbFkgd56Bu5ZI/ej8yQwrkCv8Qydx6RzwbKz9faXazR/+5tvYKsZQgyXJiwgpcva127YO6JcWy7YlCfofQ==", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" + } + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@types/aria-query": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz", + "integrity": "sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==" + }, + "node_modules/@types/babel__core": { + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", + "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", + "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", + "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz", + "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.10", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz", + "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cheerio": { + "version": "0.22.31", + "resolved": "https://registry.npmjs.org/@types/cheerio/-/cheerio-0.22.31.tgz", + "integrity": "sha512-Kt7Cdjjdi2XWSfrZ53v4Of0wG3ZcmaegFXjMmz9tfNrZSkzzo36G0AL1YqSdcIA78Etjt6E609pt5h1xnQkPUw==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz", + "integrity": "sha512-4x5FkPpLipqwthjPsF7ZRbOv3uoLUFkTA9G9v583qi4pACvq0uTELrB8OLUzPWUI4IJIyvM85vzkV1nyiI2Lig==", + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/enzyme": { + "version": "3.10.13", + "resolved": "https://registry.npmjs.org/@types/enzyme/-/enzyme-3.10.13.tgz", + "integrity": "sha512-FCtoUhmFsud0Yx9fmZk179GkdZ4U9B0GFte64/Md+W/agx0L5SxsIIbhLBOxIb9y2UfBA4WQnaG1Od/UsUQs9Q==", + "dependencies": { + "@types/cheerio": "*", + "@types/react": "^16" + } + }, + "node_modules/@types/enzyme-adapter-react-16": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.0.6.tgz", + "integrity": "sha512-VonDkZ15jzqDWL8mPFIQnnLtjwebuL9YnDkqeCDYnB4IVgwUm0mwKkqhrxLL6mb05xm7qqa3IE95m8CZE9imCg==", + "dependencies": { + "@types/enzyme": "*" + } + }, + "node_modules/@types/enzyme/node_modules/@types/react": { + "version": "16.14.43", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.43.tgz", + "integrity": "sha512-7zdjv7jvoLLQg1tTvpQsm+hyNUMT2mPlNV1+d0I8fbGhkJl82spopMyBlu4wb1dviZAxpGdk5eHu/muacknnfw==", + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/eslint": { + "version": "8.44.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.0.tgz", + "integrity": "sha512-gsF+c/0XOguWgaOgvFs+xnnRqt9GwgTvIks36WpE6ueeI4KCEHHd8K/CKHqhOqrJKsYH8m27kRzQEvWXAwXUTw==", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", + "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", + "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==" + }, + "node_modules/@types/express": { + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", + "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.35", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", + "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", + "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/history": { + "version": "4.7.11", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", + "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==", + "dev": true + }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" + }, + "node_modules/@types/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==" + }, + "node_modules/@types/http-proxy": { + "version": "1.17.11", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.11.tgz", + "integrity": "sha512-HC8G7c1WmaF2ekqpnFq626xd3Zz0uvaqFmBJNRZCGEZCXkvSdJoNFn/8Ygbd9fKNQj8UzLdCETaI0UWPAjK7IA==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "26.0.24", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.24.tgz", + "integrity": "sha512-E/X5Vib8BWqZNRlDxj9vYXhsDwPYbPINqKF9BsnSoon4RQ0D9moEuLD8txgyypFLH7J4+Lho9Nr/c8H0Fi+17w==", + "dependencies": { + "jest-diff": "^26.0.0", + "pretty-format": "^26.0.0" + } + }, + "node_modules/@types/jquery": { + "version": "3.5.16", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.16.tgz", + "integrity": "sha512-bsI7y4ZgeMkmpG9OM710RRzDFp+w4P1RGiIt30C1mSBT+ExCleeh4HObwgArnDFELmRrOpXgSYN9VF1hj+f1lw==", + "dependencies": { + "@types/sizzle": "*" + } + }, + "node_modules/@types/js-cookie": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.3.tgz", + "integrity": "sha512-Xe7IImK09HP1sv2M/aI+48a20VX+TdRJucfq4vfRVy6nWN8PYPOEnlMRSgxJAgYQIXJVL8dZ4/ilAM7dWNaOww==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" + }, + "node_modules/@types/lodash": { + "version": "4.14.195", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.195.tgz", + "integrity": "sha512-Hwx9EUgdwf2GLarOjQp5ZH8ZmblzcbTBC2wtQWNKARBSxM9ezRIAUpeDTgoQRAFB0+8CNWXVA9+MaSOzOF3nPg==" + }, + "node_modules/@types/lodash.memoize": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/lodash.memoize/-/lodash.memoize-4.1.7.tgz", + "integrity": "sha512-lGN7WeO4vO6sICVpf041Q7BX/9k1Y24Zo3FY0aUezr1QlKznpjzsDk3T3wvH8ofYzoK0QupN9TWcFAFZlyPwQQ==", + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + }, + "node_modules/@types/minimist": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", + "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==" + }, + "node_modules/@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==" + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==" + }, + "node_modules/@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" + }, + "node_modules/@types/prettier": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.9", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.9.tgz", + "integrity": "sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g==" + }, + "node_modules/@types/q": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz", + "integrity": "sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ==" + }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "node_modules/@types/react": { + "version": "17.0.62", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.62.tgz", + "integrity": "sha512-eANCyz9DG8p/Vdhr0ZKST8JV12PhH2ACCDYlFw6DIO+D+ca+uP4jtEDEpVqXZrh/uZdXQGwk7whJa3ah5DtyLw==", + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-bootstrap": { + "version": "0.32.32", + "resolved": "https://registry.npmjs.org/@types/react-bootstrap/-/react-bootstrap-0.32.32.tgz", + "integrity": "sha512-GM9UtV7v+C2F0rbqgIpMWdCKBMdX3PQURoJQobPO4vDAeFadcExNtKffi13/MjaAks+riJKVGyiMe+6OmDYT2w==", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-datepicker": { + "version": "4.11.2", + "resolved": "https://registry.npmjs.org/@types/react-datepicker/-/react-datepicker-4.11.2.tgz", + "integrity": "sha512-ELYyX3lb3K1WltqdlF1hbnaDGgzlF6PIR5T4W38cSEcfrQDIrPE+Ioq5pwRe/KEJ+ihHMjvTVZQkwJx0pWMNHQ==", + "dependencies": { + "@popperjs/core": "^2.9.2", + "@types/react": "*", + "date-fns": "^2.0.1", + "react-popper": "^2.2.5" + } + }, + "node_modules/@types/react-dom": { + "version": "17.0.20", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.20.tgz", + "integrity": "sha512-4pzIjSxDueZZ90F52mU3aPoogkHIoSIDG+oQ+wQK7Cy2B9S+MvOqY0uEA/qawKz381qrEDkvpwyt8Bm31I8sbA==", + "dependencies": { + "@types/react": "^17" + } + }, + "node_modules/@types/react-google-recaptcha": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@types/react-google-recaptcha/-/react-google-recaptcha-2.1.5.tgz", + "integrity": "sha512-iWTjmVttlNgp0teyh7eBXqNOQzVq2RWNiFROWjraOptRnb1OcHJehQnji0sjqIRAk9K0z8stjyhU+OLpPb0N6w==", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-modal": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@types/react-modal/-/react-modal-3.16.0.tgz", + "integrity": "sha512-iphdqXAyUfByLbxJn5j6d+yh93dbMgshqGP0IuBeaKbZXx0aO+OXsvEkt6QctRdxjeM9/bR+Gp3h9F9djVWTQQ==", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-redux": { + "version": "7.1.25", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.25.tgz", + "integrity": "sha512-bAGh4e+w5D8dajd6InASVIyCo4pZLJ66oLb80F9OBLO1gKESbZcRCJpTT6uLXX+HAB57zw1WTdwJdAsewuTweg==", + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + } + }, + "node_modules/@types/react-router": { + "version": "5.1.20", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz", + "integrity": "sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==", + "dev": true, + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*" + } + }, + "node_modules/@types/react-router-dom": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz", + "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==", + "dev": true, + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "*" + } + }, + "node_modules/@types/react-transition-group": { + "version": "4.4.6", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.6.tgz", + "integrity": "sha512-VnCdSxfcm08KjsJVQcfBmhEQAPnLB8G08hAxn39azX1qYBQ/5RVQuoHuKIcfKOdncuaUvEpFKFzEvbtIMsfVew==", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/resolve": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", + "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" + }, + "node_modules/@types/scheduler": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", + "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==" + }, + "node_modules/@types/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==" + }, + "node_modules/@types/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", + "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", + "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", + "dependencies": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, + "node_modules/@types/sizzle": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", + "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==" + }, + "node_modules/@types/sockjs": { + "version": "0.3.33", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", + "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" + }, + "node_modules/@types/testing-library__jest-dom": { + "version": "5.14.8", + "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.8.tgz", + "integrity": "sha512-NRfJE9Cgpmu4fx716q9SYmU4jxxhYRU1BQo239Txt/9N3EC745XZX1Yl7h/SBIDlo1ANVOCRB4YDXjaQdoKCHQ==", + "dependencies": { + "@types/jest": "*" + } + }, + "node_modules/@types/trusted-types": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.3.tgz", + "integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==" + }, + "node_modules/@types/warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.0.tgz", + "integrity": "sha512-t/Tvs5qR47OLOr+4E9ckN8AmP2Tf16gWq+/qA4iUGS/OOyHVO8wv2vjJuX8SNOUTJyWb+2t7wJm6cXILFnOROA==" + }, + "node_modules/@types/ws": { + "version": "8.5.5", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz", + "integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yargs": { + "version": "16.0.5", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.5.tgz", + "integrity": "sha512-AxO/ADJOBFJScHbWhq2xAhlWP24rY4aCEG/NFaMvbT3X2MgRsLjhjQwsn0Zi5zn0LG9jUhCCZMeX9Dkuw6k+vQ==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/experimental-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.62.0.tgz", + "integrity": "sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==", + "dependencies": { + "@typescript-eslint/utils": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "dependencies": { + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "dependencies": { + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@wojtekmaj/date-utils": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@wojtekmaj/date-utils/-/date-utils-1.4.1.tgz", + "integrity": "sha512-Fjs0KJz0//0AmlJVFx9AQmWpmxOTw4foDo4DKoswWVVjHsna4rdu+fXwid5YHNgzv/wHi9AkZCRPmHWsf890lg==", + "funding": { + "url": "https://github.com/wojtekmaj/date-utils?sponsor=1" + } + }, + "node_modules/@wojtekmaj/enzyme-adapter-react-17": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wojtekmaj/enzyme-adapter-react-17/-/enzyme-adapter-react-17-0.8.0.tgz", + "integrity": "sha512-zeUGfQRziXW7R7skzNuJyi01ZwuKCH8WiBNnTgUJwdS/CURrJwAhWsfW7nG7E30ak8Pu3ZwD9PlK9skBfAoOBw==", + "dev": true, + "dependencies": { + "@wojtekmaj/enzyme-adapter-utils": "^0.2.0", + "enzyme-shallow-equal": "^1.0.0", + "has": "^1.0.0", + "prop-types": "^15.7.0", + "react-is": "^17.0.0", + "react-test-renderer": "^17.0.0" + }, + "funding": { + "url": "https://github.com/wojtekmaj/enzyme-adapter-react-17?sponsor=1" + }, + "peerDependencies": { + "enzyme": "^3.0.0", + "react": "^17.0.0-0", + "react-dom": "^17.0.0-0" + } + }, + "node_modules/@wojtekmaj/enzyme-adapter-react-17/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/@wojtekmaj/enzyme-adapter-utils": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@wojtekmaj/enzyme-adapter-utils/-/enzyme-adapter-utils-0.2.0.tgz", + "integrity": "sha512-ZvZm9kZxZEKAbw+M1/Q3iDuqQndVoN8uLnxZ8bzxm7KgGTBejrGRoJAp8f1EN8eoO3iAjBNEQnTDW/H4Ekb0FQ==", + "dev": true, + "dependencies": { + "function.prototype.name": "^1.1.0", + "has": "^1.0.0", + "object.fromentries": "^2.0.0", + "prop-types": "^15.7.0" + }, + "funding": { + "url": "https://github.com/wojtekmaj/enzyme-adapter-utils?sponsor=1" + }, + "peerDependencies": { + "react": "^17.0.0-0" + } + }, + "node_modules/@wry/context": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@wry/context/-/context-0.7.3.tgz", + "integrity": "sha512-Nl8WTesHp89RF803Se9X3IiHjdmLBrIvPMaJkl+rKVJAYyPsz1TEUbu89943HpvujtSJgDUx9W4vZw3K1Mr3sA==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@wry/equality": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@wry/equality/-/equality-0.5.6.tgz", + "integrity": "sha512-D46sfMTngaYlrH+OspKf8mIJETntFnf6Hsjb0V41jAXJ7Bx2kB8Rv8RCUujuVWYttFtHkUNp7g+FwxNQAr6mXA==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@wry/trie": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@wry/trie/-/trie-0.4.3.tgz", + "integrity": "sha512-I6bHwH0fSf6RqQcnnXLJKhkSXG45MFral3GxPaY4uAl0LYDZM+YDVDAiU9bYwjTuysy1S0IeecWtmq1SZA3M1w==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + }, + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==" + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "dependencies": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + } + }, + "node_modules/acorn-globals/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-assertions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "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/address": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", + "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/adjust-sourcemap-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz", + "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==", + "dependencies": { + "loader-utils": "^2.0.0", + "regex-parser": "^2.2.11" + }, + "engines": { + "node": ">=8.9" + } + }, + "node_modules/adjust-sourcemap-loader/node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agentkeepalive": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.3.0.tgz", + "integrity": "sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==", + "dependencies": { + "debug": "^4.1.0", + "depd": "^2.0.0", + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/airbnb-prop-types": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/airbnb-prop-types/-/airbnb-prop-types-2.16.0.tgz", + "integrity": "sha512-7WHOFolP/6cS96PhKNrslCLMYAI8yB1Pp6u6XmxozQOiZbsI5ycglZr5cHhBFfuRcQQjzCMith5ZPZdYiJCxUg==", + "dependencies": { + "array.prototype.find": "^2.1.1", + "function.prototype.name": "^1.1.2", + "is-regex": "^1.1.0", + "object-is": "^1.1.2", + "object.assign": "^4.1.0", + "object.entries": "^1.1.2", + "prop-types": "^15.7.2", + "prop-types-exact": "^1.2.0", + "react-is": "^16.13.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + }, + "peerDependencies": { + "react": "^0.14 || ^15.0.0 || ^16.0.0-alpha" + } + }, + "node_modules/airbnb-prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-sequence-parser": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz", + "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==" + }, + "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/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "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", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha512-H3LU5RLiSsGXPhN+Nipar0iR0IofH+8r89G2y1tBKxQ/agagKyAjhkAFDRBfodP2caPrNKHpAWNIM/c9yeL7uA==", + "dev": true + }, + "node_modules/array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" + }, + "node_modules/array-includes": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", + "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array.prototype.filter": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.2.tgz", + "integrity": "sha512-us+UrmGOilqttSOgoWZTpOvHu68vZT2YCjc/H4vhu56vzZpaDFBhB+Se2UwqWzMKbDv7Myq5M5pcZLAtUvTQdQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.find": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.2.1.tgz", + "integrity": "sha512-I2ri5Z9uMpMvnsNrHre9l3PaX+z9D0/z6F7Yt2u15q7wt0I62g5kX6xUKR1SJiefgG+u2/gJUmM8B47XRvQR6w==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", + "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", + "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.reduce": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz", + "integrity": "sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz", + "integrity": "sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.1.3" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dev": true, + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==" + }, + "node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + }, + "node_modules/async-foreach": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", + "integrity": "sha512-VUeSMD8nEGBWaZK4lizI1sf3yEC7pnAQ/mrI7pC2fBz2s/tq5jWWEngTwaf0Gruu/OoXRGLGg1XFqpYBiGTYJA==", + "engines": { + "node": "*" + } + }, + "node_modules/async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.14", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz", + "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + } + ], + "dependencies": { + "browserslist": "^4.21.5", + "caniuse-lite": "^1.0.30001464", + "fraction.js": "^4.2.0", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", + "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", + "dev": true + }, + "node_modules/axe-core": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.2.tgz", + "integrity": "sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", + "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/babel-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", + "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", + "dependencies": { + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-jest/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/babel-loader": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.3.0.tgz", + "integrity": "sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q==", + "dependencies": { + "find-cache-dir": "^3.3.1", + "loader-utils": "^2.0.0", + "make-dir": "^3.1.0", + "schema-utils": "^2.6.5" + }, + "engines": { + "node": ">= 8.9" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "webpack": ">=2" + } + }, + "node_modules/babel-loader/node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/babel-loader/node_modules/schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dependencies": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", + "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/babel-plugin-named-asset-import": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.8.tgz", + "integrity": "sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q==", + "peerDependencies": { + "@babel/core": "^7.1.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.4.tgz", + "integrity": "sha512-9WeK9snM1BfxB38goUEv2FLnA6ja07UMfazFHzCXUb3NyDZAwfXvQiURQ6guTTMeHcOsdknULm1PDhs4uWtKyA==", + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.4.1", + "@nicolo-ribaudo/semver-v6": "^6.3.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.2.tgz", + "integrity": "sha512-Cid+Jv1BrY9ReW9lIfNlNpsI53N+FN7gE+f73zLAUbr9C52W4gKLWSByx47pfDJsEysojKArqOtOKZSVIIUTuQ==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.4.1", + "core-js-compat": "^3.31.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.1.tgz", + "integrity": "sha512-L8OyySuI6OSQ5hFy9O+7zFjyr4WhAfRjLIOkhQGYl+emwJkd/S4XXT1JpfrgR1jrQ1NcGiOh+yAdGlF8pnC3Jw==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.4.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-transform-react-remove-prop-types": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz", + "integrity": "sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==" + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", + "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", + "dependencies": { + "babel-plugin-jest-hoist": "^27.5.1", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-react-app": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-react-app/-/babel-preset-react-app-10.0.1.tgz", + "integrity": "sha512-b0D9IZ1WhhCWkrTXyFuIIgqGzSkRIH5D5AmB0bXbzYAB1OBAwHcUeyWW2LorutLWF5btNo/N7r/cIdmvvKJlYg==", + "dependencies": { + "@babel/core": "^7.16.0", + "@babel/plugin-proposal-class-properties": "^7.16.0", + "@babel/plugin-proposal-decorators": "^7.16.4", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.0", + "@babel/plugin-proposal-numeric-separator": "^7.16.0", + "@babel/plugin-proposal-optional-chaining": "^7.16.0", + "@babel/plugin-proposal-private-methods": "^7.16.0", + "@babel/plugin-transform-flow-strip-types": "^7.16.0", + "@babel/plugin-transform-react-display-name": "^7.16.0", + "@babel/plugin-transform-runtime": "^7.16.4", + "@babel/preset-env": "^7.16.4", + "@babel/preset-react": "^7.16.0", + "@babel/preset-typescript": "^7.16.0", + "@babel/runtime": "^7.16.3", + "babel-plugin-macros": "^3.1.0", + "babel-plugin-transform-react-remove-prop-types": "^0.4.24" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "dependencies": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dev": true, + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/bfj": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/bfj/-/bfj-7.0.2.tgz", + "integrity": "sha512-+e/UqUzwmzJamNF50tBV6tZPTORow7gQ96iFow+8b562OdMpEK0BcJEq2OSPEDmAbSMBQ7PKZ87ubFkgxpYWgw==", + "dependencies": { + "bluebird": "^3.5.5", + "check-types": "^11.1.1", + "hoopy": "^0.1.4", + "tryer": "^1.0.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, + "node_modules/body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/body-parser/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/bonjour-service": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.1.1.tgz", + "integrity": "sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg==", + "dependencies": { + "array-flatten": "^2.1.2", + "dns-equal": "^1.0.0", + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "node_modules/bootstrap": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.0.tgz", + "integrity": "sha512-UnBV3E3v4STVNQdms6jSGO2CvOkjUMdDAVR2V5N4uCMdaIkaQjbcEAMqRimDHIs4uqBYzDAKCQwCB+97tJgHQw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], + "peerDependencies": { + "@popperjs/core": "^2.11.7" + } + }, + "node_modules/boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dev": true, + "dependencies": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "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/boxen/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/brotli": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz", + "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==", + "dependencies": { + "base64-js": "^1.1.2" + } + }, + "node_modules/browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==" + }, + "node_modules/browserslist": { + "version": "4.21.9", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz", + "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001503", + "electron-to-chromium": "^1.4.431", + "node-releases": "^2.0.12", + "update-browserslist-db": "^1.0.11" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bwip-js": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/bwip-js/-/bwip-js-3.4.3.tgz", + "integrity": "sha512-x+mQE/bq5V0Nlkn4Jd4cktNlEPH4zeIGSOEQNUtsV/cCJNiBba7u/S9PYR1pmD2WDeeZAIbYTjvGHjBQ21RXvw==", + "bin": { + "bwip-js": "bin/bwip-js.js" + } + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacache": { + "version": "16.1.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", + "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", + "dependencies": { + "@npmcli/fs": "^2.1.0", + "@npmcli/move-file": "^2.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "glob": "^8.0.1", + "infer-owner": "^1.0.4", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^9.0.0", + "tar": "^6.1.11", + "unique-filename": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/cacache/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/cacache/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/cacache/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "dependencies": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacheable-request/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacheable-request/node_modules/normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dependencies": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001516", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001516.tgz", + "integrity": "sha512-Wmec9pCBY8CWbmI4HsjBeQLqDTqV91nFVR83DnZpYyRnPI1wePDsTg0bGLPC5VU/3OIZV1fmxEea1b+tFKe86g==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/capture-exit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", + "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", + "dev": true, + "dependencies": { + "rsvp": "^4.8.4" + }, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/case-sensitive-paths-webpack-plugin": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", + "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "dev": true + }, + "node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/check-types": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/check-types/-/check-types-11.2.2.tgz", + "integrity": "sha512-HBiYvXvn9Z70Z88XKjz3AEKd4HJhBXsa3j7xFnITAzoS8+q6eIGi8qDB8FKPBAjtuxjI/zFpwuiCb8oDtKOYrA==" + }, + "node_modules/cheerio": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", + "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "htmlparser2": "^8.0.1", + "parse5": "^7.0.0", + "parse5-htmlparser2-tree-adapter": "^7.0.0" + }, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/ci-info": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", + "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/circular-json-es6": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/circular-json-es6/-/circular-json-es6-2.0.2.tgz", + "integrity": "sha512-ODYONMMNb3p658Zv+Pp+/XPa5s6q7afhz3Tzyvo+VRh9WIrJ64J76ZC4GQxnlye/NesTn09jvOiuE8+xxfpwhQ==", + "dev": true + }, + "node_modules/cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==" + }, + "node_modules/class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "dependencies": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + }, + "node_modules/clean-css": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.2.tgz", + "integrity": "sha512-JVJbM+f3d3Q704rF4bqQ5UUyTtuJ0JRKNbTKVEeujCCBoMdkEi+V+e8oktO9qGQNSvHrFTM6JZRXrUvGR1czww==", + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/clean-css/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/coa": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", + "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", + "dependencies": { + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/coa/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/coa/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/coa/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/coa/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/coa/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/coa/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/coa/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==" + }, + "node_modules/collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==", + "dev": true, + "dependencies": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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/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/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/common-path-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==" + }, + "node_modules/common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==" + }, + "node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/compression/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "dev": true, + "dependencies": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==" + }, + "node_modules/connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/connect/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/connect/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/core-js": { + "version": "3.31.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.31.1.tgz", + "integrity": "sha512-2sKLtfq1eFST7l7v62zaqXacPc7uG8ZAya8ogijLhTtaKNcpzpB4TMoTw2Si+8GYKRwFPMMtUT0263QFWFfqyQ==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat": { + "version": "3.31.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.31.1.tgz", + "integrity": "sha512-wIDWd2s5/5aJSdpOJHfSibxNODxoGoWOBHt8JSPB41NOE94M7kuTPZCYLOlTtuoXTsBPKobpJ6T+y0SSy5L9SA==", + "dependencies": { + "browserslist": "^4.21.9" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-pure": { + "version": "3.31.1", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.31.1.tgz", + "integrity": "sha512-w+C62kvWti0EPs4KPMCMVv9DriHSXfQOCQ94bGGBiEW5rrbtt/Rz8n5Krhfw9cpFyzXBjf3DB3QnPdEzGDY4Fw==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/cross-fetch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "dependencies": { + "node-fetch": "2.6.7" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/css-blank-pseudo": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz", + "integrity": "sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ==", + "dependencies": { + "postcss-selector-parser": "^6.0.9" + }, + "bin": { + "css-blank-pseudo": "dist/cli.cjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-declaration-sorter": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", + "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==", + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, + "node_modules/css-has-pseudo": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-3.0.4.tgz", + "integrity": "sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw==", + "dependencies": { + "postcss-selector-parser": "^6.0.9" + }, + "bin": { + "css-has-pseudo": "dist/cli.cjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-loader": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.8.1.tgz", + "integrity": "sha512-xDAXtEVGlD0gJ07iclwWVkLoZOpEvAWaSyf6W18S2pOC//K8+qUDIx8IIT3D+HjnmkJPQeesOPv5aiUaJsCM2g==", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.21", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.3", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.3.8" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/css-minimizer-webpack-plugin": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz", + "integrity": "sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==", + "dependencies": { + "cssnano": "^5.0.6", + "jest-worker": "^27.0.2", + "postcss": "^8.3.5", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@parcel/css": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/css-minimizer-webpack-plugin/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/css-minimizer-webpack-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/css-minimizer-webpack-plugin/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/css-minimizer-webpack-plugin/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/css-minimizer-webpack-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-prefers-color-scheme": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz", + "integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==", + "bin": { + "css-prefers-color-scheme": "dist/cli.cjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==" + }, + "node_modules/css-tree": { + "version": "1.0.0-alpha.37", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", + "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", + "dependencies": { + "mdn-data": "2.0.4", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/css-tree/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==" + }, + "node_modules/cssdb": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.6.0.tgz", + "integrity": "sha512-Nna7rph8V0jC6+JBY4Vk4ndErUmfJfV6NJCaZdurL0omggabiy+QB2HCQtu5c/ACLZ0I7REv7A4QyPIoYzZx0w==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + } + ] + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssnano": { + "version": "5.1.15", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.15.tgz", + "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==", + "dependencies": { + "cssnano-preset-default": "^5.2.14", + "lilconfig": "^2.0.3", + "yaml": "^1.10.2" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/cssnano" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano-preset-default": { + "version": "5.2.14", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz", + "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==", + "dependencies": { + "css-declaration-sorter": "^6.3.1", + "cssnano-utils": "^3.1.0", + "postcss-calc": "^8.2.3", + "postcss-colormin": "^5.3.1", + "postcss-convert-values": "^5.1.3", + "postcss-discard-comments": "^5.1.2", + "postcss-discard-duplicates": "^5.1.0", + "postcss-discard-empty": "^5.1.1", + "postcss-discard-overridden": "^5.1.0", + "postcss-merge-longhand": "^5.1.7", + "postcss-merge-rules": "^5.1.4", + "postcss-minify-font-values": "^5.1.0", + "postcss-minify-gradients": "^5.1.1", + "postcss-minify-params": "^5.1.4", + "postcss-minify-selectors": "^5.2.1", + "postcss-normalize-charset": "^5.1.0", + "postcss-normalize-display-values": "^5.1.0", + "postcss-normalize-positions": "^5.1.1", + "postcss-normalize-repeat-style": "^5.1.1", + "postcss-normalize-string": "^5.1.0", + "postcss-normalize-timing-functions": "^5.1.0", + "postcss-normalize-unicode": "^5.1.1", + "postcss-normalize-url": "^5.1.0", + "postcss-normalize-whitespace": "^5.1.1", + "postcss-ordered-values": "^5.1.3", + "postcss-reduce-initial": "^5.1.2", + "postcss-reduce-transforms": "^5.1.0", + "postcss-svgo": "^5.1.0", + "postcss-unique-selectors": "^5.1.1" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", + "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "dependencies": { + "css-tree": "^1.1.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "node_modules/csso/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==" + }, + "node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dependencies": { + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" + }, + "node_modules/csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==" + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/data-urls": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "dependencies": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, + "node_modules/dayjs": { + "version": "1.11.9", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.9.tgz", + "integrity": "sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==" + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" + }, + "node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==" + }, + "node_modules/deep-equal-ident": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal-ident/-/deep-equal-ident-1.1.1.tgz", + "integrity": "sha512-aWv7VhTl/Lju1zenOD3E1w8PpUVrTDbwXCHtbSNr+p/uadr49Y1P1ld0W3Pl6gbvIbiRjoCVsqw70UupCNGh6g==", + "dev": true, + "dependencies": { + "lodash.isequal": "^3.0" + } + }, + "node_modules/deep-equal-ident/node_modules/lodash.isequal": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-3.0.4.tgz", + "integrity": "sha512-Bsu5fP9Omd+HBk2Dz8qp4BHbC+83DBykZ87Lz1JmPKTVNy4Q0XQVtUrbfXVAK/udQrWNcGStcKSA9yj/Zkm3TQ==", + "dev": true, + "dependencies": { + "lodash._baseisequal": "^3.0.0", + "lodash._bindcallback": "^3.0.0" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/detect-newline": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-4.0.0.tgz", + "integrity": "sha512-1aXUEPdfGdzVPFpzGJJNgq9o81bGg1s09uxTWsqBlo9PI332uyJRQq13+LK/UN4JfxJbFdCXonUFQ9R/p7yCtw==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" + }, + "node_modules/detect-port-alt": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", + "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", + "dependencies": { + "address": "^1.0.1", + "debug": "^2.6.0" + }, + "bin": { + "detect": "bin/detect-port", + "detect-port": "bin/detect-port" + }, + "engines": { + "node": ">= 4.2.1" + } + }, + "node_modules/detect-port-alt/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/detect-port-alt/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/dfa": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz", + "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==" + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" + }, + "node_modules/diff-sequences": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.6.2.tgz", + "integrity": "sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==", + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/discontinuous-range": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", + "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" + }, + "node_modules/dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==" + }, + "node_modules/dns-packet": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.0.tgz", + "integrity": "sha512-rza3UH1LwdHh9qyPXp8lkwpjSNk/AMD3dPytUoRoqnypDUhY0xvbdmVhWOfxO68frEfV9BU8V12Ez7ZsHGZpCQ==", + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==" + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dependencies": { + "utila": "~0.4" + } + }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domexception": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "dependencies": { + "webidl-conversions": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/domexception/node_modules/webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dotenv": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", + "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", + "engines": { + "node": ">=10" + } + }, + "node_modules/dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==" + }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" + }, + "node_modules/duplexer3": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", + "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==", + "dev": true + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dev": true, + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/ejs": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz", + "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.461", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.461.tgz", + "integrity": "sha512-1JkvV2sgEGTDXjdsaQCeSwYYuhLRphRpc+g6EHTFELJXEiznLt3/0pZ9JuAOQ5p2rI3YxKTbivtvajirIfhrEQ==" + }, + "node_modules/emittery": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", + "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/enzyme": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.11.0.tgz", + "integrity": "sha512-Dw8/Gs4vRjxY6/6i9wU0V+utmQO9kvh9XLnz3LIudviOnVYDEe2ec+0k+NQoMamn1VrjKgCUOWj5jG/5M5M0Qw==", + "dependencies": { + "array.prototype.flat": "^1.2.3", + "cheerio": "^1.0.0-rc.3", + "enzyme-shallow-equal": "^1.0.1", + "function.prototype.name": "^1.1.2", + "has": "^1.0.3", + "html-element-map": "^1.2.0", + "is-boolean-object": "^1.0.1", + "is-callable": "^1.1.5", + "is-number-object": "^1.0.4", + "is-regex": "^1.0.5", + "is-string": "^1.0.5", + "is-subset": "^0.1.1", + "lodash.escape": "^4.0.1", + "lodash.isequal": "^4.5.0", + "object-inspect": "^1.7.0", + "object-is": "^1.0.2", + "object.assign": "^4.1.0", + "object.entries": "^1.1.1", + "object.values": "^1.1.1", + "raf": "^3.4.1", + "rst-selector-parser": "^2.2.3", + "string.prototype.trim": "^1.2.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/enzyme-adapter-react-16": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.15.7.tgz", + "integrity": "sha512-LtjKgvlTc/H7adyQcj+aq0P0H07LDL480WQl1gU512IUyaDo/sbOaNDdZsJXYW2XaoPqrLLE9KbZS+X2z6BASw==", + "dependencies": { + "enzyme-adapter-utils": "^1.14.1", + "enzyme-shallow-equal": "^1.0.5", + "has": "^1.0.3", + "object.assign": "^4.1.4", + "object.values": "^1.1.5", + "prop-types": "^15.8.1", + "react-is": "^16.13.1", + "react-test-renderer": "^16.0.0-0", + "semver": "^5.7.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + }, + "peerDependencies": { + "enzyme": "^3.0.0", + "react": "^16.0.0-0", + "react-dom": "^16.0.0-0" + } + }, + "node_modules/enzyme-adapter-react-16/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/enzyme-adapter-react-16/node_modules/react-test-renderer": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.14.0.tgz", + "integrity": "sha512-L8yPjqPE5CZO6rKsKXRO/rVPiaCOy0tQQJbC+UjPNlobl5mad59lvPjwFsQHTvL03caVDIVr9x9/OSgDe6I5Eg==", + "dependencies": { + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "react-is": "^16.8.6", + "scheduler": "^0.19.1" + }, + "peerDependencies": { + "react": "^16.14.0" + } + }, + "node_modules/enzyme-adapter-react-16/node_modules/scheduler": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", + "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "node_modules/enzyme-adapter-react-16/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/enzyme-adapter-utils": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/enzyme-adapter-utils/-/enzyme-adapter-utils-1.14.1.tgz", + "integrity": "sha512-JZgMPF1QOI7IzBj24EZoDpaeG/p8Os7WeBZWTJydpsH7JRStc7jYbHE4CmNQaLqazaGFyLM8ALWA3IIZvxW3PQ==", + "dependencies": { + "airbnb-prop-types": "^2.16.0", + "function.prototype.name": "^1.1.5", + "has": "^1.0.3", + "object.assign": "^4.1.4", + "object.fromentries": "^2.0.5", + "prop-types": "^15.8.1", + "semver": "^5.7.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + }, + "peerDependencies": { + "react": "0.13.x || 0.14.x || ^15.0.0-0 || ^16.0.0-0" + } + }, + "node_modules/enzyme-adapter-utils/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/enzyme-matchers": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/enzyme-matchers/-/enzyme-matchers-7.1.2.tgz", + "integrity": "sha512-03WqAg2XDl7id9rARIO97HQ1JIw9F2heJ3R4meGu/13hx0ULTDEgl0E67MGl2Uq1jq1DyRnJfto1/VSzskdV5A==", + "dev": true, + "dependencies": { + "circular-json-es6": "^2.0.1", + "deep-equal-ident": "^1.1.1" + }, + "peerDependencies": { + "enzyme": ">=3.4.0" + } + }, + "node_modules/enzyme-shallow-equal": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.5.tgz", + "integrity": "sha512-i6cwm7hN630JXenxxJFBKzgLC3hMTafFQXflvzHgPmDhOBhxUWDe8AeRv1qp2/uWJ2Y8z5yLWMzmAfkTOiOCZg==", + "dependencies": { + "has": "^1.0.3", + "object-is": "^1.1.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/enzyme-to-json": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/enzyme-to-json/-/enzyme-to-json-3.6.2.tgz", + "integrity": "sha512-Ynm6Z6R6iwQ0g2g1YToz6DWhxVnt8Dy1ijR2zynRKxTyBGA8rCDXU3rs2Qc4OKvUvc2Qoe1bcFK6bnPs20TrTg==", + "dev": true, + "dependencies": { + "@types/cheerio": "^0.22.22", + "lodash": "^4.17.21", + "react-is": "^16.12.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "peerDependencies": { + "enzyme": "^3.4.0" + } + }, + "node_modules/enzyme-to-json/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==" + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "dependencies": { + "stackframe": "^1.3.4" + } + }, + "node_modules/es-abstract": { + "version": "1.21.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.3.tgz", + "integrity": "sha512-ZU4miiY1j3sGPFLJ34VJXEqhpmL+HGByCinGHv4HC+Fxl2fI2Z4yR6tl0mORnDr6PA8eihWo4LmSWDbvhALckg==", + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.2.1", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.0", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" + }, + "node_modules/es-module-lexer": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.0.tgz", + "integrity": "sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==" + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dependencies": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dependencies": { + "has": "^1.0.3" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/escodegen/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint": { + "version": "8.45.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.45.0.tgz", + "integrity": "sha512-pd8KSxiQpdYRfYa9Wufvdoct3ZPQQuVuU5O6scNgMuOMYuxvH0IGaYK0wUFjo4UYYQQCUndlXiMbnxopwvvTiw==", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.1.0", + "@eslint/js": "8.44.0", + "@humanwhocodes/config-array": "^0.11.10", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.0", + "eslint-visitor-keys": "^3.4.1", + "espree": "^9.6.0", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", + "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-config-react-app": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-7.0.1.tgz", + "integrity": "sha512-K6rNzvkIeHaTd8m/QEh1Zko0KI7BACWkkneSs6s9cKZC/J27X3eZR6Upt1jkmZ/4FK+XUOPPxMEN7+lbUXfSlA==", + "dependencies": { + "@babel/core": "^7.16.0", + "@babel/eslint-parser": "^7.16.3", + "@rushstack/eslint-patch": "^1.1.0", + "@typescript-eslint/eslint-plugin": "^5.5.0", + "@typescript-eslint/parser": "^5.5.0", + "babel-preset-react-app": "^10.0.1", + "confusing-browser-globals": "^1.0.11", + "eslint-plugin-flowtype": "^8.0.3", + "eslint-plugin-import": "^2.25.3", + "eslint-plugin-jest": "^25.3.0", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-react": "^7.27.1", + "eslint-plugin-react-hooks": "^4.3.0", + "eslint-plugin-testing-library": "^5.0.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "eslint": "^8.0.0" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", + "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.11.0", + "resolve": "^1.22.1" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", + "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-flowtype": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-8.0.3.tgz", + "integrity": "sha512-dX8l6qUL6O+fYPtpNRideCFSpmWOUVx5QcaGLVqe/vlDiBSe4vYljDWDETwnyFzpl7By/WVIu6rcrniCgH9BqQ==", + "dependencies": { + "lodash": "^4.17.21", + "string-natural-compare": "^3.0.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@babel/plugin-syntax-flow": "^7.14.5", + "@babel/plugin-transform-react-jsx": "^7.14.9", + "eslint": "^8.1.0" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.27.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", + "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "array.prototype.flatmap": "^1.3.1", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.7", + "eslint-module-utils": "^2.7.4", + "has": "^1.0.3", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.values": "^1.1.6", + "resolve": "^1.22.1", + "semver": "^6.3.0", + "tsconfig-paths": "^3.14.1" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-jest": { + "version": "25.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-25.7.0.tgz", + "integrity": "sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==", + "dependencies": { + "@typescript-eslint/experimental-utils": "^5.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^4.0.0 || ^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz", + "integrity": "sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==", + "dependencies": { + "@babel/runtime": "^7.20.7", + "aria-query": "^5.1.3", + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", + "ast-types-flow": "^0.0.7", + "axe-core": "^4.6.2", + "axobject-query": "^3.1.1", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "has": "^1.0.3", + "jsx-ast-utils": "^3.3.3", + "language-tags": "=1.0.5", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz", + "integrity": "sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==", + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "peerDependencies": { + "eslint": ">=5.0.0", + "prettier": ">=1.13.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.32.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz", + "integrity": "sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", + "array.prototype.tosorted": "^1.1.1", + "doctrine": "^2.1.0", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "object.hasown": "^1.1.2", + "object.values": "^1.1.6", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.4", + "semver": "^6.3.0", + "string.prototype.matchall": "^4.0.8" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", + "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", + "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-testing-library": { + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.11.0.tgz", + "integrity": "sha512-ELY7Gefo+61OfXKlQeXNIDVVLPcvKTeiQOoMZG9TeuWa7Ln4dUNRv8JdRWBQI9Mbb427XGlVB1aa1QPZxBJM8Q==", + "dependencies": { + "@typescript-eslint/utils": "^5.58.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0", + "npm": ">=6" + }, + "peerDependencies": { + "eslint": "^7.5.0 || ^8.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", + "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-webpack-plugin": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-3.2.0.tgz", + "integrity": "sha512-avrKcGncpPbPSUHX6B3stNGzkKFto3eL+DKM4+VyMrVnhPc3vRczVlCq3uhuFOdRvDHTVXuzwk1ZKUrqDQHQ9w==", + "dependencies": { + "@types/eslint": "^7.29.0 || ^8.4.1", + "jest-worker": "^28.0.2", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0", + "webpack": "^5.0.0" + } + }, + "node_modules/eslint-webpack-plugin/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint-webpack-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/eslint-webpack-plugin/node_modules/jest-worker": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.1.3.tgz", + "integrity": "sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g==", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/eslint-webpack-plugin/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/eslint-webpack-plugin/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/eslint-webpack-plugin/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/eslint/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/eslint/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/eslint/node_modules/eslint-scope": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.1.tgz", + "integrity": "sha512-CvefSOsDdaYYvxChovdrPo/ZGt8d5lrJWleAc1diXRKhHGiTYEI26cvo8Kle/wGnsizoCJjK73FMg1/IkIwiNA==", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/exec-sh": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.6.tgz", + "integrity": "sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w==", + "dev": true + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", + "dev": true, + "dependencies": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/expand-brackets/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expect": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", + "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "dependencies": { + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/express/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express/node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/express/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "dependencies": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "dev": true, + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==" + }, + "node_modules/fast-glob": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", + "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/file-loader/node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/filesize": { + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", + "integrity": "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/find-node-modules": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/find-node-modules/-/find-node-modules-2.1.3.tgz", + "integrity": "sha512-UC2I2+nx1ZuOBclWVNdcnbDR5dlrOdVb7xNjmT/lHE+LsgztWks3dG7boJ37yTS/venXw84B/mAW9uHVoC5QRg==", + "dev": true, + "dependencies": { + "findup-sync": "^4.0.0", + "merge": "^2.1.1" + } + }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/findup-sync": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-4.0.0.tgz", + "integrity": "sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==", + "dev": true, + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^4.0.2", + "resolve-dir": "^1.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/flag-icons": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/flag-icons/-/flag-icons-6.7.0.tgz", + "integrity": "sha512-+KXrrrXN2jiETFxisFl+3f83Bq7tj5nuIWnbv9fX59k05lvldEXRCOffybb5hAIjMWt4nmG0E8OfKt7Flm99Eg==" + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" + }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/fontkit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-2.0.2.tgz", + "integrity": "sha512-jc4k5Yr8iov8QfS6u8w2CnHWVmbOGtdBtOXMze5Y+QD966Rx6PEVWXSEGwXlsDlKtu1G12cJjcsybnqhSk/+LA==", + "dependencies": { + "@swc/helpers": "^0.4.2", + "brotli": "^1.3.2", + "clone": "^2.1.2", + "dfa": "^1.2.0", + "fast-deep-equal": "^3.1.3", + "restructure": "^3.0.0", + "tiny-inflate": "^1.0.3", + "unicode-properties": "^1.4.0", + "unicode-trie": "^2.0.0" + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/fork-ts-checker-webpack-plugin": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz", + "integrity": "sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==", + "dependencies": { + "@babel/code-frame": "^7.8.3", + "@types/json-schema": "^7.0.5", + "chalk": "^4.1.0", + "chokidar": "^3.4.2", + "cosmiconfig": "^6.0.0", + "deepmerge": "^4.2.2", + "fs-extra": "^9.0.0", + "glob": "^7.1.6", + "memfs": "^3.1.2", + "minimatch": "^3.0.4", + "schema-utils": "2.7.0", + "semver": "^7.3.2", + "tapable": "^1.0.0" + }, + "engines": { + "node": ">=10", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "eslint": ">= 6", + "typescript": ">= 2.7", + "vue-template-compiler": "*", + "webpack": ">= 4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + }, + "vue-template-compiler": { + "optional": true + } + } + }, + "node_modules/fork-ts-checker-webpack-plugin/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/fork-ts-checker-webpack-plugin/node_modules/cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "dependencies": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fraction.js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", + "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/infusion" + } + }, + "node_modules/fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==", + "dev": true, + "dependencies": { + "map-cache": "^0.2.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-monkey": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.4.tgz", + "integrity": "sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ==" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/gaze": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", + "dependencies": { + "globule": "^1.0.0" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/generic-names": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/generic-names/-/generic-names-4.0.0.tgz", + "integrity": "sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A==", + "dev": true, + "dependencies": { + "loader-utils": "^3.2.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-user-locale": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/get-user-locale/-/get-user-locale-2.3.0.tgz", + "integrity": "sha512-I3rQvAUwu2nauRD9YyQBSXVFJZixNouwA+eZld51Sn4Pn0N1qFbgcgOi/nPigJPQlNY519mT95fiSPRgflQiTA==", + "dependencies": { + "@types/lodash.memoize": "^4.1.7", + "lodash.memoize": "^4.1.1" + }, + "funding": { + "url": "https://github.com/wojtekmaj/get-user-locale?sponsor=1" + } + }, + "node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + }, + "node_modules/global-dirs": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "dev": true, + "dependencies": { + "ini": "2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/global-dirs/node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globule": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.4.tgz", + "integrity": "sha512-OPTIfhMBh7JbBYDpa5b+Q5ptmMWKwcNcFSR/0c6t8V4f3ZAVBEsKNY37QdVqmLRYSMhOUGYrY0QhSoEpzGr/Eg==", + "dependencies": { + "glob": "~7.1.1", + "lodash": "^4.17.21", + "minimatch": "~3.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/globule/node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globule/node_modules/minimatch": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", + "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/got/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" + }, + "node_modules/graphql": { + "version": "15.8.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.8.0.tgz", + "integrity": "sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw==", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/graphql-tag": { + "version": "2.12.6", + "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz", + "integrity": "sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/graphql-ws": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.14.0.tgz", + "integrity": "sha512-itrUTQZP/TgswR4GSSYuwWUzrE/w5GhbwM2GX3ic2U7aw33jgEsayfIlvaj7/GcIvZgNMzsPTrE5hqPuFUiE5g==", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "graphql": ">=0.11 <=16" + } + }, + "node_modules/gzip-size": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", + "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "dependencies": { + "duplexer": "^0.1.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/handlebars/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "dev": true, + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/harmony-reflect": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", + "integrity": "sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==" + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==", + "dev": true, + "dependencies": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "bin": { + "he": "bin/he" + } + }, + "node_modules/history": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", + "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "dependencies": { + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^3.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^1.0.1" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "dependencies": { + "parse-passwd": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hoopy": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", + "integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==", + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hosted-git-info/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hpack.js/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/hpack.js/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hpack.js/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/hpack.js/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/html-element-map": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/html-element-map/-/html-element-map-1.3.1.tgz", + "integrity": "sha512-6XMlxrAFX4UEEGxctfFnmrFaaZFNf9i5fNuV5wZ3WWQ4FVaNP1aX1LkX9j2mfEx1NpjeE/rL3nmgEn23GdFmrg==", + "dependencies": { + "array.prototype.filter": "^1.0.0", + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "dependencies": { + "whatwg-encoding": "^1.0.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/html-entities": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz", + "integrity": "sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ] + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==" + }, + "node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/html-minifier-terser/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/html-parse-stringify": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", + "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==", + "dependencies": { + "void-elements": "3.1.0" + } + }, + "node_modules/html-webpack-plugin": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.3.tgz", + "integrity": "sha512-6YrDKTuqaP/TquFH7h4srYWsZx+x6k6+FbsTm0ziCwGHDP78Unr1r9F/H4+sGmMbX08GQcJ+K64x55b+7VM/jg==", + "dependencies": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "webpack": "^5.20.0" + } + }, + "node_modules/htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==" + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/http-proxy-middleware/node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/husky": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", + "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", + "dev": true, + "bin": { + "husky": "lib/bin.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/i18next": { + "version": "21.10.0", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-21.10.0.tgz", + "integrity": "sha512-YeuIBmFsGjUfO3qBmMOc0rQaun4mIpGKET5WDwvu8lU7gvwpcariZLNtL0Fzj+zazcHUrlXHiptcFhBMFaxzfg==", + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "dependencies": { + "@babel/runtime": "^7.17.2" + } + }, + "node_modules/i18next-browser-languagedetector": { + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-6.1.8.tgz", + "integrity": "sha512-Svm+MduCElO0Meqpj1kJAriTC6OhI41VhlT/A0UPjGoPZBhAHIaGE5EfsHlTpgdH09UVX7rcc72pSDDBeKSQQA==", + "dependencies": { + "@babel/runtime": "^7.19.0" + } + }, + "node_modules/i18next-http-backend": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-1.4.5.tgz", + "integrity": "sha512-tLuHWuLWl6CmS07o+UB6EcQCaUjrZ1yhdseIN7sfq0u7phsMePJ8pqlGhIAdRDPF/q7ooyo5MID5DRFBCH+x5w==", + "dependencies": { + "cross-fetch": "3.1.5" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/idb": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", + "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==" + }, + "node_modules/identity-obj-proxy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz", + "integrity": "sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA==", + "dependencies": { + "harmony-reflect": "^1.4.6" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/immer": { + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "dependencies": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + }, + "node_modules/ipaddr.js": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", + "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "dependencies": { + "ci-info": "^2.0.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-ci/node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "node_modules/is-core-module": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", + "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "dev": true, + "dependencies": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==" + }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==" + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-npm": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", + "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-root": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", + "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-subset": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", + "integrity": "sha512-6Ybun0IkarhmEqxXCNw/C0bna6Zb/TkfUX9UbwJtK6ObwAVCxmAP308WWTHviM/zAqXk05cdhYsUsZeGQh99iw==" + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", + "dev": true + }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", + "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jake": { + "version": "10.8.7", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", + "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==", + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jake/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": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", + "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", + "dependencies": { + "@jest/core": "^27.5.1", + "import-local": "^3.0.2", + "jest-cli": "^27.5.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", + "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", + "dependencies": { + "@jest/types": "^27.5.1", + "execa": "^5.0.0", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-circus": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", + "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^0.7.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-circus/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-circus/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-circus/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-circus/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "node_modules/jest-cli": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", + "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", + "dependencies": { + "@jest/core": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "import-local": "^3.0.2", + "jest-config": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "prompts": "^2.0.1", + "yargs": "^16.2.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-cli/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": { + "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-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/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-config/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "node_modules/jest-diff": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.6.2.tgz", + "integrity": "sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^26.6.2", + "jest-get-type": "^26.3.0", + "pretty-format": "^26.6.2" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/jest-diff/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-diff/node_modules/jest-get-type": { + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.3.0.tgz", + "integrity": "sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==", + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/jest-docblock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", + "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-docblock/node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-each": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", + "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", + "dependencies": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-each/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-each/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-each/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-each/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "node_modules/jest-environment-enzyme": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/jest-environment-enzyme/-/jest-environment-enzyme-7.1.2.tgz", + "integrity": "sha512-3tfaYAzO7qZSRrv+srQnfK16Vu5XwH/pHi8FpoqSHjKKngbHzXf7aBCBuWh8y3w0OtknHRfDMFrC60Khj+g1hA==", + "dev": true, + "dependencies": { + "jest-environment-jsdom": "^24.0.0" + }, + "peerDependencies": { + "enzyme": "3.x", + "jest": ">=22.0.0", + "react": "^0.13.0 || ^0.14.0 || ^15.0.0 || >=16.x" + } + }, + "node_modules/jest-environment-enzyme/node_modules/@jest/console": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", + "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", + "dev": true, + "dependencies": { + "@jest/source-map": "^24.9.0", + "chalk": "^2.0.1", + "slash": "^2.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jest-environment-enzyme/node_modules/@jest/environment": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.9.0.tgz", + "integrity": "sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ==", + "dev": true, + "dependencies": { + "@jest/fake-timers": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jest-environment-enzyme/node_modules/@jest/fake-timers": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", + "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", + "dev": true, + "dependencies": { + "@jest/types": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-mock": "^24.9.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jest-environment-enzyme/node_modules/@jest/source-map": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", + "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0", + "graceful-fs": "^4.1.15", + "source-map": "^0.6.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jest-environment-enzyme/node_modules/@jest/test-result": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", + "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", + "dev": true, + "dependencies": { + "@jest/console": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/istanbul-lib-coverage": "^2.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jest-environment-enzyme/node_modules/@jest/transform": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.9.0.tgz", + "integrity": "sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.1.0", + "@jest/types": "^24.9.0", + "babel-plugin-istanbul": "^5.1.0", + "chalk": "^2.0.1", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.1.15", + "jest-haste-map": "^24.9.0", + "jest-regex-util": "^24.9.0", + "jest-util": "^24.9.0", + "micromatch": "^3.1.10", + "pirates": "^4.0.1", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "2.4.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jest-environment-enzyme/node_modules/@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jest-environment-enzyme/node_modules/@types/istanbul-reports": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz", + "integrity": "sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*", + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/jest-environment-enzyme/node_modules/@types/stack-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", + "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==", + "dev": true + }, + "node_modules/jest-environment-enzyme/node_modules/@types/yargs": { + "version": "13.0.12", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.12.tgz", + "integrity": "sha512-qCxJE1qgz2y0hA4pIxjBR+PelCH0U5CK1XJXFwCNqfmliatKp47UCXXE9Dyk1OXBDLvsCF57TqQEJaeLfDYEOQ==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-environment-enzyme/node_modules/acorn": { + "version": "5.7.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", + "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/jest-environment-enzyme/node_modules/acorn-globals": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz", + "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==", + "dev": true, + "dependencies": { + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" + } + }, + "node_modules/jest-environment-enzyme/node_modules/acorn-globals/node_modules/acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/jest-environment-enzyme/node_modules/acorn-walk": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", + "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/jest-environment-enzyme/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/jest-environment-enzyme/node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "node_modules/jest-environment-enzyme/node_modules/babel-plugin-istanbul": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz", + "integrity": "sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "find-up": "^3.0.0", + "istanbul-lib-instrument": "^3.3.0", + "test-exclude": "^5.2.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jest-environment-enzyme/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-environment-enzyme/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-environment-enzyme/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/jest-environment-enzyme/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/jest-environment-enzyme/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/jest-environment-enzyme/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "node_modules/jest-environment-enzyme/node_modules/cssstyle": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", + "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", + "dev": true, + "dependencies": { + "cssom": "0.3.x" + } + }, + "node_modules/jest-environment-enzyme/node_modules/data-urls": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", + "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", + "dev": true, + "dependencies": { + "abab": "^2.0.0", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0" + } + }, + "node_modules/jest-environment-enzyme/node_modules/data-urls/node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "node_modules/jest-environment-enzyme/node_modules/domexception": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", + "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "dev": true, + "dependencies": { + "webidl-conversions": "^4.0.2" + } + }, + "node_modules/jest-environment-enzyme/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/jest-environment-enzyme/node_modules/escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "dev": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=4.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/jest-environment-enzyme/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-environment-enzyme/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-environment-enzyme/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jest-environment-enzyme/node_modules/fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "deprecated": "The v1 package contains DANGEROUS / INSECURE binaries. Upgrade to safe fsevents v2", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/jest-environment-enzyme/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/jest-environment-enzyme/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/jest-environment-enzyme/node_modules/html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "dev": true, + "dependencies": { + "whatwg-encoding": "^1.0.1" + } + }, + "node_modules/jest-environment-enzyme/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-environment-enzyme/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-environment-enzyme/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-environment-enzyme/node_modules/istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/jest-environment-enzyme/node_modules/istanbul-lib-instrument": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", + "dev": true, + "dependencies": { + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", + "semver": "^6.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jest-environment-enzyme/node_modules/jest-environment-jsdom": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-24.9.0.tgz", + "integrity": "sha512-Zv9FV9NBRzLuALXjvRijO2351DRQeLYXtpD4xNvfoVFw21IOKNhZAEUKcbiEtjTkm2GsJ3boMVgkaR7rN8qetA==", + "dev": true, + "dependencies": { + "@jest/environment": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-util": "^24.9.0", + "jsdom": "^11.5.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jest-environment-enzyme/node_modules/jest-haste-map": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.9.0.tgz", + "integrity": "sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==", + "dev": true, + "dependencies": { + "@jest/types": "^24.9.0", + "anymatch": "^2.0.0", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.1.15", + "invariant": "^2.2.4", + "jest-serializer": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.9.0", + "micromatch": "^3.1.10", + "sane": "^4.0.3", + "walker": "^1.0.7" + }, + "engines": { + "node": ">= 6" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" + } + }, + "node_modules/jest-environment-enzyme/node_modules/jest-message-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", + "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^2.0.1", + "micromatch": "^3.1.10", + "slash": "^2.0.0", + "stack-utils": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jest-environment-enzyme/node_modules/jest-mock": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", + "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", + "dev": true, + "dependencies": { + "@jest/types": "^24.9.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jest-environment-enzyme/node_modules/jest-regex-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", + "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jest-environment-enzyme/node_modules/jest-serializer": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.9.0.tgz", + "integrity": "sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jest-environment-enzyme/node_modules/jest-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", + "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", + "dev": true, + "dependencies": { + "@jest/console": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/source-map": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "callsites": "^3.0.0", + "chalk": "^2.0.1", + "graceful-fs": "^4.1.15", + "is-ci": "^2.0.0", + "mkdirp": "^0.5.1", + "slash": "^2.0.0", + "source-map": "^0.6.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jest-environment-enzyme/node_modules/jest-worker": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", + "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "dev": true, + "dependencies": { + "merge-stream": "^2.0.0", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jest-environment-enzyme/node_modules/jest-worker/node_modules/supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jest-environment-enzyme/node_modules/jsdom": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", + "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", + "dev": true, + "dependencies": { + "abab": "^2.0.0", + "acorn": "^5.5.3", + "acorn-globals": "^4.1.0", + "array-equal": "^1.0.0", + "cssom": ">= 0.3.2 < 0.4.0", + "cssstyle": "^1.0.0", + "data-urls": "^1.0.0", + "domexception": "^1.0.1", + "escodegen": "^1.9.1", + "html-encoding-sniffer": "^1.0.2", + "left-pad": "^1.3.0", + "nwsapi": "^2.0.7", + "parse5": "4.0.0", + "pn": "^1.1.0", + "request": "^2.87.0", + "request-promise-native": "^1.0.5", + "sax": "^1.2.4", + "symbol-tree": "^3.2.2", + "tough-cookie": "^2.3.4", + "w3c-hr-time": "^1.0.1", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.3", + "whatwg-mimetype": "^2.1.0", + "whatwg-url": "^6.4.1", + "ws": "^5.2.0", + "xml-name-validator": "^3.0.0" + } + }, + "node_modules/jest-environment-enzyme/node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/jest-environment-enzyme/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jest-environment-enzyme/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-environment-enzyme/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/jest-environment-enzyme/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/jest-environment-enzyme/node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/jest-environment-enzyme/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-environment-enzyme/node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/jest-environment-enzyme/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jest-environment-enzyme/node_modules/parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", + "dev": true + }, + "node_modules/jest-environment-enzyme/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==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/jest-environment-enzyme/node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/jest-environment-enzyme/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/jest-environment-enzyme/node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/jest-environment-enzyme/node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "dev": true, + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/jest-environment-enzyme/node_modules/read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jest-environment-enzyme/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/jest-environment-enzyme/node_modules/slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/jest-environment-enzyme/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-environment-enzyme/node_modules/stack-utils": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.5.tgz", + "integrity": "sha512-KZiTzuV3CnSnSvgMRrARVCj+Ht7rMbauGDK0LdVFRGyenwdylpajAp4Q0i6SX8rEmbTpMMf6ryq2gb8pPq2WgQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-environment-enzyme/node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-environment-enzyme/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/jest-environment-enzyme/node_modules/test-exclude": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", + "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", + "dev": true, + "dependencies": { + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jest-environment-enzyme/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-environment-enzyme/node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/jest-environment-enzyme/node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/jest-environment-enzyme/node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/jest-environment-enzyme/node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "node_modules/jest-environment-enzyme/node_modules/whatwg-url": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", + "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", + "dev": true, + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "node_modules/jest-environment-enzyme/node_modules/write-file-atomic": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz", + "integrity": "sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "node_modules/jest-environment-enzyme/node_modules/ws": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.3.tgz", + "integrity": "sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA==", + "dev": true, + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/jest-environment-jsdom": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", + "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1", + "jsdom": "^16.6.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", + "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-enzyme": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/jest-enzyme/-/jest-enzyme-7.1.2.tgz", + "integrity": "sha512-j+jkph3t5hGBS12eOldpfsnERYRCHi4c/0KWPMnqRPoJJXvCpLIc5th1MHl0xDznQDXVU0AHUXg3rqMrf8vGpA==", + "dev": true, + "dependencies": { + "enzyme-matchers": "^7.1.2", + "enzyme-to-json": "^3.3.0", + "jest-environment-enzyme": "^7.1.2" + }, + "peerDependencies": { + "enzyme": ">=3.4.0", + "jest": ">=22.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-jasmine2": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", + "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-jasmine2/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-jasmine2/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-jasmine2/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-jasmine2/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "node_modules/jest-leak-detector": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", + "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", + "dependencies": { + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-leak-detector/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-leak-detector/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-leak-detector/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "node_modules/jest-localstorage-mock": { + "version": "2.4.26", + "resolved": "https://registry.npmjs.org/jest-localstorage-mock/-/jest-localstorage-mock-2.4.26.tgz", + "integrity": "sha512-owAJrYnjulVlMIXOYQIPRCCn3MmqI3GzgfZCXdD3/pmwrIvFMXcKVWZ+aMc44IzaASapg0Z4SEFxR+v5qxDA2w==", + "dev": true, + "engines": { + "node": ">=6.16.0" + } + }, + "node_modules/jest-location-mock": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/jest-location-mock/-/jest-location-mock-1.0.10.tgz", + "integrity": "sha512-g5u0rDOaj1I/lWuPOOP6xfpY+O958IcOanwPKnHdfWm0l4Y2sdVmwXMPY9fT5s8D9nX44Zl/Ypmk6B88mDoqZQ==", + "dev": true, + "dependencies": { + "@jedmao/location": "^3.0.0", + "jest-diff": "^27.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/jest-location-mock/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "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-location-mock/node_modules/diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "dev": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-location-mock/node_modules/jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-location-mock/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-location-mock/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-location-mock/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-matcher-utils/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-matcher-utils/node_modules/diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-matcher-utils/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "node_modules/jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-message-util/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-message-util/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-message-util/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "node_modules/jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-preview": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/jest-preview/-/jest-preview-0.3.1.tgz", + "integrity": "sha512-gRR4shnXFSh8tdNaIncJC98d1zXD7w7LA52HQC0bu0DsPb+FXVEg+NQh9GTbO+n6/SCgcZNQAVt4MeCfsIkBPA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@svgr/core": "^6.2.1", + "camelcase": "^6.3.0", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "commander": "^9.2.0", + "connect": "^3.7.0", + "find-node-modules": "^2.1.3", + "open": "^8.4.0", + "postcss-import": "^14.1.0", + "postcss-load-config": "^4.0.1", + "sirv": "^2.0.2", + "slash": "^3.0.0", + "string-hash": "^1.1.3", + "update-notifier": "^5.1.0", + "ws": "^8.5.0" + }, + "bin": { + "jest-preview": "cli/index.js" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/jest-preview" + } + }, + "node_modules/jest-preview/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-preview/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "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-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", + "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", + "dependencies": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", + "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", + "dependencies": { + "@jest/types": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-snapshot": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve/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-runner": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", + "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-leak-detector": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "source-map-support": "^0.5.6", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runner/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-runtime": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", + "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/globals": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "execa": "^5.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runtime/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-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dependencies": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", + "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", + "dependencies": { + "@babel/core": "^7.7.2", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/traverse": "^7.7.2", + "@babel/types": "^7.0.0", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__traverse": "^7.0.4", + "@types/prettier": "^2.1.5", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^27.5.1", + "semver": "^7.3.2" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/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-snapshot/node_modules/diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-snapshot/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-util/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-validate": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", + "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", + "dependencies": { + "@jest/types": "^27.5.1", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "leven": "^3.1.0", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-validate/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-validate/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-validate/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-validate/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "node_modules/jest-watch-typeahead": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-1.1.0.tgz", + "integrity": "sha512-Va5nLSJTN7YFtC2jd+7wsoe1pNe5K4ShLux/E5iHEwlB9AxaxmggY7to9KUqKojhaJw3aXqt5WAb4jGPOolpEw==", + "dependencies": { + "ansi-escapes": "^4.3.1", + "chalk": "^4.0.0", + "jest-regex-util": "^28.0.0", + "jest-watcher": "^28.0.0", + "slash": "^4.0.0", + "string-length": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "jest": "^27.0.0 || ^28.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/@jest/console": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.3.tgz", + "integrity": "sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==", + "dependencies": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^28.1.3", + "jest-util": "^28.1.3", + "slash": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/@jest/console/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watch-typeahead/node_modules/@jest/test-result": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-28.1.3.tgz", + "integrity": "sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg==", + "dependencies": { + "@jest/console": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/@jest/types": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", + "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", + "dependencies": { + "@jest/schemas": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/@types/yargs": { + "version": "17.0.24", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", + "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-watch-typeahead/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-watch-typeahead/node_modules/emittery": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", + "integrity": "sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-message-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", + "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^28.1.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^28.1.3", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-message-util/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-regex-util": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", + "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", + "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", + "dependencies": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-watcher": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-28.1.3.tgz", + "integrity": "sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g==", + "dependencies": { + "@jest/test-result": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.10.2", + "jest-util": "^28.1.3", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-watcher/node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-watcher/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watch-typeahead/node_modules/pretty-format": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", + "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "dependencies": { + "@jest/schemas": "^28.1.3", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-watch-typeahead/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watch-typeahead/node_modules/string-length": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-5.0.1.tgz", + "integrity": "sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==", + "dependencies": { + "char-regex": "^2.0.0", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watch-typeahead/node_modules/string-length/node_modules/char-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-2.0.1.tgz", + "integrity": "sha512-oSvEeo6ZUD7NepqAat3RqoucZ5SeqLJgOvVIwkafu6IP3V0pO38s/ypdVUmDDK6qIIHNlYHJAKX9E7R7HoKElw==", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/jest-watch-typeahead/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/jest-watch-typeahead/node_modules/strip-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/jest-watcher": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", + "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", + "dependencies": { + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "jest-util": "^27.5.1", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-watcher/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-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jiti": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.1.tgz", + "integrity": "sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg==", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/jquery": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.0.tgz", + "integrity": "sha512-umpJ0/k8X0MvD1ds0P9SfowREz2LenHsQaxSohMZ5OMNEU2r0tf8pdeEFTHMFxWVxKNyU9rTtK3CWzUCTKJUeQ==", + "dev": true + }, + "node_modules/js-base64": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", + "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==" + }, + "node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "engines": { + "node": ">=14" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true + }, + "node_modules/jsdom": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "dependencies": { + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, + "node_modules/jsdom/node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", + "dev": true + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==" + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "dev": true, + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.4.tgz", + "integrity": "sha512-fX2TVdCViod6HwKEtSWGHs57oFhVfCMwieb9PuRDgjDPh5XeqJiHFFFJCHxU5cnTc3Bu/GRL+kPiFmw8XWOfKw==", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.0" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "engines": { + "node": ">=6" + } + }, + "node_modules/klona": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", + "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==" + }, + "node_modules/language-tags": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", + "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", + "dependencies": { + "language-subtag-registry": "~0.3.2" + } + }, + "node_modules/latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "dev": true, + "dependencies": { + "package-json": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/launch-editor": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz", + "integrity": "sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==", + "dependencies": { + "picocolors": "^1.0.0", + "shell-quote": "^1.7.3" + } + }, + "node_modules/left-pad": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", + "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==", + "deprecated": "use String.prototype.padStart()", + "dev": true + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", + "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==", + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash._baseisequal": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/lodash._baseisequal/-/lodash._baseisequal-3.0.7.tgz", + "integrity": "sha512-U+3GsNEZj9ebI03ncLC2pLmYVjgtYZEwdkAPO7UGgtGvAz36JVFPAQUufpSaVL93Cz5arc6JGRKZRhaOhyVJYA==", + "dev": true, + "dependencies": { + "lodash.isarray": "^3.0.0", + "lodash.istypedarray": "^3.0.0", + "lodash.keys": "^3.0.0" + } + }, + "node_modules/lodash._bindcallback": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", + "integrity": "sha512-2wlI0JRAGX8WEf4Gm1p/mv/SZ+jLijpj0jyaE/AXeuQphzCgD8ZQW4oSpoN8JAopujOFGU3KMuq7qfHBWlGpjQ==", + "dev": true + }, + "node_modules/lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha512-RrL9VxMEPyDMHOd9uFbvMe8X55X16/cGM5IgOKgRElQZutpX89iS6vwl64duTV1/16w5JY7tuFNXqoekmh1EmA==", + "dev": true + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "dev": true + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, + "node_modules/lodash.escape": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz", + "integrity": "sha512-nXEOnb/jK9g0DYMr1/Xvq6l5xMD7GDG55+GSYIYmS0G4tBk/hURD4JR9WCavs04t33WmJx9kCyp9vJ+mr4BOUw==" + }, + "node_modules/lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==" + }, + "node_modules/lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==", + "dev": true + }, + "node_modules/lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha512-JwObCrNJuT0Nnbuecmqr5DgtuBppuCvGD9lxjFpAzwnVtdGoDQ1zig+5W8k5/6Gcn0gZ3936HDAlGd28i7sOGQ==", + "dev": true + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" + }, + "node_modules/lodash.istypedarray": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/lodash.istypedarray/-/lodash.istypedarray-3.0.6.tgz", + "integrity": "sha512-lGWJ6N8AA3KSv+ZZxlTdn4f6A7kMfpJboeyvbFdE7IU9YAgweODqmOgdUHOA+c6lVWeVLysdaxciFXi+foVsWw==", + "dev": true + }, + "node_modules/lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha512-CuBsapFjcubOGMn3VD+24HOAPxM79tH+V6ivJL3CHYjtrawauDJHUk//Yew9Hvc6e9rbCrURGk8z6PC+8WJBfQ==", + "dev": true, + "dependencies": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==" + }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dependencies": { + "sourcemap-codec": "^1.4.8" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/make-fetch-happen": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", + "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^16.1.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^2.0.3", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^9.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/make-fetch-happen/node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/make-fetch-happen/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==", + "dev": true, + "dependencies": { + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/meow": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", + "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", + "dependencies": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize": "^1.2.0", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/merge/-/merge-2.1.1.tgz", + "integrity": "sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==", + "dev": true + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "engines": { + "node": ">=4" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "2.7.6", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.6.tgz", + "integrity": "sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw==", + "dependencies": { + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/mini-css-extract-plugin/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-fetch": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", + "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "dependencies": { + "minipass": "^3.1.6", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "dependencies": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/moo": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", + "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==" + }, + "node_modules/mrmime": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", + "integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nan": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", + "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==" + }, + "node_modules/nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==" + }, + "node_modules/nearley": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", + "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", + "dependencies": { + "commander": "^2.19.0", + "moo": "^0.5.0", + "railroad-diagrams": "^1.0.0", + "randexp": "0.4.6" + }, + "bin": { + "nearley-railroad": "bin/nearley-railroad.js", + "nearley-test": "bin/nearley-test.js", + "nearley-unparse": "bin/nearley-unparse.js", + "nearleyc": "bin/nearleyc.js" + }, + "funding": { + "type": "individual", + "url": "https://nearley.js.org/#give-to-nearley" + } + }, + "node_modules/nearley/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-gyp": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", + "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/node-gyp/node_modules/@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "dependencies": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "node_modules/node-gyp/node_modules/@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-gyp/node_modules/cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "dependencies": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/node-gyp/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-gyp/node_modules/make-fetch-happen": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "dependencies": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/node-gyp/node_modules/minipass-fetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "dependencies": { + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "optionalDependencies": { + "encoding": "^0.1.12" + } + }, + "node_modules/node-gyp/node_modules/socks-proxy-agent": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", + "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/node-gyp/node_modules/ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/node-gyp/node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/node-gyp/node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, + "node_modules/node-gyp/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" + }, + "node_modules/node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==" + }, + "node_modules/node-sass": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-9.0.0.tgz", + "integrity": "sha512-yltEuuLrfH6M7Pq2gAj5B6Zm7m+gdZoG66wTqG6mIZV/zijq3M2OO2HswtT6oBspPyFhHDcaxWpsBm0fRNDHPg==", + "hasInstallScript": true, + "dependencies": { + "async-foreach": "^0.1.3", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "gaze": "^1.0.0", + "get-stdin": "^4.0.1", + "glob": "^7.0.3", + "lodash": "^4.17.15", + "make-fetch-happen": "^10.0.4", + "meow": "^9.0.0", + "nan": "^2.17.0", + "node-gyp": "^8.4.1", + "sass-graph": "^4.0.1", + "stdout-stream": "^1.4.0", + "true-case-path": "^2.2.1" + }, + "bin": { + "node-sass": "bin/node-sass" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/node-sass/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/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nwsapi": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", + "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==" + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==", + "dev": true, + "dependencies": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==", + "dev": true, + "dependencies": { + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.assign": { + "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", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", + "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", + "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.getownpropertydescriptors": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.6.tgz", + "integrity": "sha512-lq+61g26E/BgHv0ZTFgRvi7NMEPuAxLkFU7rukXjc/AlwH4Am5xXVnIXy3un1bg/JPbXHrixRkK1itUzzPiIjQ==", + "dependencies": { + "array.prototype.reduce": "^1.0.5", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.21.2", + "safe-array-concat": "^1.0.0" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.hasown": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", + "integrity": "sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==", + "dependencies": { + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.values": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", + "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optimism": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.16.2.tgz", + "integrity": "sha512-zWNbgWj+3vLEjZNIh/okkY2EUfX+vB9TJopzIZwT1xxaMqC5hRLLraePod4c5n4He08xuXNH+zhKFFCu390wiQ==", + "dependencies": { + "@wry/context": "^0.7.0", + "@wry/trie": "^0.3.0" + } + }, + "node_modules/optimism/node_modules/@wry/trie": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@wry/trie/-/trie-0.3.2.tgz", + "integrity": "sha512-yRTyhWSls2OY/pYLfwff867r8ekooZ4UI+/gxot5Wj8EFwSf2rG+n+Mo/6LoLQm1TKA4GRj2+LCpbfS937dClQ==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-retry/node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "dev": true, + "dependencies": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", + "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", + "dependencies": { + "domhandler": "^5.0.2", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dependencies": { + "isarray": "0.0.1" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-up/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/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/pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", + "dev": true + }, + "node_modules/posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss": { + "version": "8.4.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.26.tgz", + "integrity": "sha512-jrXHFF8iTloAenySjM/ob3gSj7pCu0Ji49hnjqzsgSRa50hkWCKD0HQ+gMNJkW38jBI68MpAAg7ZWwHwX8NMMw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-attribute-case-insensitive": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.2.tgz", + "integrity": "sha512-XIidXV8fDr0kKt28vqki84fRK8VW8eTuIa4PChv2MqKuT6C9UjmSKzen6KaWhWEoYvwxFCa7n/tC1SZ3tyq4SQ==", + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-browser-comments": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-browser-comments/-/postcss-browser-comments-4.0.0.tgz", + "integrity": "sha512-X9X9/WN3KIvY9+hNERUqX9gncsgBA25XaeR+jshHz2j8+sYyHktHw1JdKuMjeLpGktXidqDhA7b/qm1mrBDmgg==", + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "browserslist": ">=4", + "postcss": ">=8" + } + }, + "node_modules/postcss-calc": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", + "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", + "dependencies": { + "postcss-selector-parser": "^6.0.9", + "postcss-value-parser": "^4.2.0" + }, + "peerDependencies": { + "postcss": "^8.2.2" + } + }, + "node_modules/postcss-clamp": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz", + "integrity": "sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=7.6.0" + }, + "peerDependencies": { + "postcss": "^8.4.6" + } + }, + "node_modules/postcss-color-functional-notation": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-4.2.4.tgz", + "integrity": "sha512-2yrTAUZUab9s6CpxkxC4rVgFEVaR6/2Pipvi6qcgvnYiVqZcbDHEoBDhrXzyb7Efh2CCfHQNtcqWcIruDTIUeg==", + "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/postcss-color-hex-alpha": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-8.0.4.tgz", + "integrity": "sha512-nLo2DCRC9eE4w2JmuKgVA3fGL3d01kGq752pVALF68qpGLmx2Qrk91QTKkdUqqp45T1K1XV8IhQpcu1hoAQflQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-color-rebeccapurple": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-7.1.1.tgz", + "integrity": "sha512-pGxkuVEInwLHgkNxUc4sdg4g3py7zUeCQ9sMfwyHAT+Ezk8a4OaaVZ8lIY5+oNqA/BXXgLyXv0+5wHP68R79hg==", + "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/postcss-colormin": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.1.tgz", + "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==", + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "colord": "^2.9.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-convert-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", + "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", + "dependencies": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-custom-media": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-8.0.2.tgz", + "integrity": "sha512-7yi25vDAoHAkbhAzX9dHx2yc6ntS4jQvejrNcC+csQJAXjj15e7VcWfMgLqBNAbOvqi5uIa9huOVwdHbf+sKqg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-custom-properties": { + "version": "12.1.11", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-12.1.11.tgz", + "integrity": "sha512-0IDJYhgU8xDv1KY6+VgUwuQkVtmYzRwu+dMjnmdMafXYv86SWqfxkc7qdDvWS38vsjaEtv8e0vGOUQrAiMBLpQ==", + "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/postcss-custom-selectors": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-6.0.3.tgz", + "integrity": "sha512-fgVkmyiWDwmD3JbpCmB45SvvlCD6z9CG6Ie6Iere22W5aHea6oWa7EM2bpnv2Fj3I94L3VbtvX9KqwSi5aFzSg==", + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-dir-pseudo-class": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-6.0.5.tgz", + "integrity": "sha512-eqn4m70P031PF7ZQIvSgy9RSJ5uI2171O/OO/zcRNYpJbvaeKFUlar1aJ7rmgiQtbm0FSPsRewjpdS0Oew7MPA==", + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-discard-comments": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", + "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-duplicates": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", + "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-empty": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", + "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-overridden": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", + "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-double-position-gradients": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-3.1.2.tgz", + "integrity": "sha512-GX+FuE/uBR6eskOK+4vkXgT6pDkexLokPaz/AbJna9s5Kzp/yl488pKPjhy0obB475ovfT1Wv8ho7U/cHNaRgQ==", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "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/postcss-env-function": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-4.0.6.tgz", + "integrity": "sha512-kpA6FsLra+NqcFnL81TnsU+Z7orGtDTxcOhl6pwXeEq1yFPpRMkCDpHhrz8CFQDr/Wfm0jLiNQ1OsGGPjlqPwA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-flexbugs-fixes": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz", + "integrity": "sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==", + "peerDependencies": { + "postcss": "^8.1.4" + } + }, + "node_modules/postcss-focus-visible": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-6.0.4.tgz", + "integrity": "sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw==", + "dependencies": { + "postcss-selector-parser": "^6.0.9" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-focus-within": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz", + "integrity": "sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ==", + "dependencies": { + "postcss-selector-parser": "^6.0.9" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-font-variant": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", + "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-gap-properties": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-3.0.5.tgz", + "integrity": "sha512-IuE6gKSdoUNcvkGIqdtjtcMtZIFyXZhmFd5RUlg97iVEvp1BZKV5ngsAjCjrVy+14uhGBQl9tzmi1Qwq4kqVOg==", + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-image-set-function": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-4.0.7.tgz", + "integrity": "sha512-9T2r9rsvYzm5ndsBE8WgtrMlIT7VbtTfE7b3BQnudUqnBcBo7L758oc+o+pdj/dUV0l5wjwSdjeOH2DZtfv8qw==", + "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/postcss-import": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz", + "integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-initial": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz", + "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==", + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-lab-function": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-4.2.1.tgz", + "integrity": "sha512-xuXll4isR03CrQsmxyz92LJB2xX9n+pZJ5jE9JgcnmsCammLyKdlzrBin+25dy6wIjfhJpKBAN80gsTlCgRk2w==", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "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/postcss-load-config": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.1.tgz", + "integrity": "sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==", + "dependencies": { + "lilconfig": "^2.0.5", + "yaml": "^2.1.1" + }, + "engines": { + "node": ">= 14" + }, + "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-load-config/node_modules/yaml": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", + "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", + "engines": { + "node": ">= 14" + } + }, + "node_modules/postcss-loader": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", + "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", + "dependencies": { + "cosmiconfig": "^7.0.0", + "klona": "^2.0.5", + "semver": "^7.3.5" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" + } + }, + "node_modules/postcss-logical": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-5.0.4.tgz", + "integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==", + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-media-minmax": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz", + "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-merge-longhand": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", + "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "stylehacks": "^5.1.1" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-merge-rules": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz", + "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==", + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^3.1.0", + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-font-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", + "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-gradients": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", + "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", + "dependencies": { + "colord": "^2.9.1", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-params": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", + "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", + "dependencies": { + "browserslist": "^4.21.4", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-selectors": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", + "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", + "dependencies": { + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-modules": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules/-/postcss-modules-6.0.0.tgz", + "integrity": "sha512-7DGfnlyi/ju82BRzTIjWS5C4Tafmzl3R79YP/PASiocj+aa6yYphHhhKUOEoXQToId5rgyFgJ88+ccOUydjBXQ==", + "dev": true, + "dependencies": { + "generic-names": "^4.0.0", + "icss-utils": "^5.1.0", + "lodash.camelcase": "^4.3.0", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "string-hash": "^1.1.1" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz", + "integrity": "sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==", + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-nested": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", + "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", + "dependencies": { + "postcss-selector-parser": "^6.0.11" + }, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-nesting": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-10.2.0.tgz", + "integrity": "sha512-EwMkYchxiDiKUhlJGzWsD9b2zvq/r2SSubcRrgP+jujMXFzqvANLt16lJANC+5uZ6hjI7lpRmI6O8JIl+8l1KA==", + "dependencies": { + "@csstools/selector-specificity": "^2.0.0", + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-normalize": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize/-/postcss-normalize-10.0.1.tgz", + "integrity": "sha512-+5w18/rDev5mqERcG3W5GZNMJa1eoYYNGo8gB7tEwaos0ajk3ZXAI4mHGcNT47NE+ZnZD1pEpUOFLvltIwmeJA==", + "dependencies": { + "@csstools/normalize.css": "*", + "postcss-browser-comments": "^4", + "sanitize.css": "*" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "browserslist": ">= 4", + "postcss": ">= 8" + } + }, + "node_modules/postcss-normalize-charset": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", + "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-display-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", + "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-positions": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", + "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-repeat-style": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", + "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-string": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", + "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-timing-functions": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", + "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-unicode": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", + "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", + "dependencies": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", + "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", + "dependencies": { + "normalize-url": "^6.0.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-whitespace": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", + "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-opacity-percentage": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.3.tgz", + "integrity": "sha512-An6Ba4pHBiDtyVpSLymUUERMo2cU7s+Obz6BTrS+gxkbnSBNKSuD0AVUc+CpBMrpVPKKfoVz0WQCX+Tnst0i4A==", + "funding": [ + { + "type": "kofi", + "url": "https://ko-fi.com/mrcgrtz" + }, + { + "type": "liberapay", + "url": "https://liberapay.com/mrcgrtz" + } + ], + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-ordered-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", + "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", + "dependencies": { + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-overflow-shorthand": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.4.tgz", + "integrity": "sha512-otYl/ylHK8Y9bcBnPLo3foYFLL6a6Ak+3EQBPOTR7luMYCOsiVTUk1iLvNf6tVPNGXcoL9Hoz37kpfriRIFb4A==", + "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/postcss-page-break": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", + "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", + "peerDependencies": { + "postcss": "^8" + } + }, + "node_modules/postcss-place": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-7.0.5.tgz", + "integrity": "sha512-wR8igaZROA6Z4pv0d+bvVrvGY4GVHihBCBQieXFY3kuSuMyOmEnnfFzHl/tQuqHZkfkIVBEbDvYcFfHmpSet9g==", + "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/postcss-preset-env": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-7.8.3.tgz", + "integrity": "sha512-T1LgRm5uEVFSEF83vHZJV2z19lHg4yJuZ6gXZZkqVsqv63nlr6zabMH3l4Pc01FQCyfWVrh2GaUeCVy9Po+Aag==", + "dependencies": { + "@csstools/postcss-cascade-layers": "^1.1.1", + "@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.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.13", + "browserslist": "^4.21.4", + "css-blank-pseudo": "^3.0.3", + "css-has-pseudo": "^3.0.4", + "css-prefers-color-scheme": "^6.0.3", + "cssdb": "^7.1.0", + "postcss-attribute-case-insensitive": "^5.0.2", + "postcss-clamp": "^4.1.0", + "postcss-color-functional-notation": "^4.2.4", + "postcss-color-hex-alpha": "^8.0.4", + "postcss-color-rebeccapurple": "^7.1.1", + "postcss-custom-media": "^8.0.2", + "postcss-custom-properties": "^12.1.10", + "postcss-custom-selectors": "^6.0.3", + "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.5", + "postcss-image-set-function": "^4.0.7", + "postcss-initial": "^4.0.1", + "postcss-lab-function": "^4.2.1", + "postcss-logical": "^5.0.4", + "postcss-media-minmax": "^5.0.0", + "postcss-nesting": "^10.2.0", + "postcss-opacity-percentage": "^1.1.2", + "postcss-overflow-shorthand": "^3.0.4", + "postcss-page-break": "^3.0.4", + "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.1", + "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/postcss-pseudo-class-any-link": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.6.tgz", + "integrity": "sha512-9sCtZkO6f/5ML9WcTLcIyV1yz9D1rf0tWc+ulKcvV30s0iZKS/ONyETvoWsr6vnrmW+X+KmuK3gV/w5EWnT37w==", + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-reduce-initial": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz", + "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==", + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-reduce-transforms": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", + "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-replace-overflow-wrap": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", + "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", + "peerDependencies": { + "postcss": "^8.0.3" + } + }, + "node_modules/postcss-selector-not": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-6.0.1.tgz", + "integrity": "sha512-1i9affjAe9xu/y9uqWH+tD4r6/hDaXJruk8xn2x1vzxC2U3J3LKO3zJW4CyxlNhA56pADJ/djpEwpH1RClI2rQ==", + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", + "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-svgo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", + "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "svgo": "^2.7.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/postcss-svgo/node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/postcss-svgo/node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/postcss-svgo/node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/postcss-svgo/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/postcss-svgo/node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/postcss-svgo/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/postcss-svgo/node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "node_modules/postcss-svgo/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-svgo/node_modules/svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/postcss-unique-selectors": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", + "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", + "dependencies": { + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "node_modules/pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "dependencies": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/pretty-format/node_modules/@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/pretty-format/node_modules/@types/yargs": { + "version": "15.0.15", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.15.tgz", + "integrity": "sha512-IziEYMU9XoVj8hWg7k+UJrXALkGFjWJhn5QFEv9q4p+v40oZhSuC135M38st8XPjICL7Ey4TV64ferBGUoJhBg==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/pretty-format/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/pretty-format/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/promise": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", + "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", + "dependencies": { + "asap": "~2.0.6" + } + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==" + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types-exact": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/prop-types-exact/-/prop-types-exact-1.2.0.tgz", + "integrity": "sha512-K+Tk3Kd9V0odiXFP9fwDHUYRyvK3Nun3GVyPapSIs5OBkITAm15W0CPFD/YKTkMUAbc0b9CUwRQp2ybiBIq+eA==", + "dependencies": { + "has": "^1.0.3", + "object.assign": "^4.1.0", + "reflect.ownkeys": "^0.2.0" + } + }, + "node_modules/prop-types-extra": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz", + "integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==", + "dependencies": { + "react-is": "^16.3.2", + "warning": "^4.0.0" + }, + "peerDependencies": { + "react": ">=0.14.0" + } + }, + "node_modules/prop-types-extra/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/pupa": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "dev": true, + "dependencies": { + "escape-goat": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "engines": { + "node": ">=8" + } + }, + "node_modules/raf": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", + "dependencies": { + "performance-now": "^2.1.0" + } + }, + "node_modules/railroad-diagrams": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", + "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==" + }, + "node_modules/randexp": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", + "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", + "dependencies": { + "discontinuous-range": "1.0.0", + "ret": "~0.1.10" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", + "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-app-polyfill": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-3.0.0.tgz", + "integrity": "sha512-sZ41cxiU5llIB003yxxQBYrARBqe0repqPTTYBTmMqTz9szeBbE37BehCE891NZsmdZqqP+xWKdT3eo3vOzN8w==", + "dependencies": { + "core-js": "^3.19.2", + "object-assign": "^4.1.1", + "promise": "^8.1.0", + "raf": "^3.4.1", + "regenerator-runtime": "^0.13.9", + "whatwg-fetch": "^3.6.2" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/react-async-script": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/react-async-script/-/react-async-script-1.2.0.tgz", + "integrity": "sha512-bCpkbm9JiAuMGhkqoAiC0lLkb40DJ0HOEJIku+9JDjxX3Rcs+ztEOG13wbrOskt3n2DTrjshhaQ/iay+SnGg5Q==", + "dependencies": { + "hoist-non-react-statics": "^3.3.0", + "prop-types": "^15.5.0" + }, + "peerDependencies": { + "react": ">=16.4.1" + } + }, + "node_modules/react-bootstrap": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.8.0.tgz", + "integrity": "sha512-e/aNtxl0Z2ozrIaR82jr6Zz7ss9GSoaXpQaxmvtDUsTZIq/XalkduR/ZXP6vbQHz2T4syvjA+4FbtwELxxmpww==", + "dependencies": { + "@babel/runtime": "^7.21.0", + "@restart/hooks": "^0.4.9", + "@restart/ui": "^1.6.3", + "@types/react-transition-group": "^4.4.5", + "classnames": "^2.3.2", + "dom-helpers": "^5.2.1", + "invariant": "^2.2.4", + "prop-types": "^15.8.1", + "prop-types-extra": "^1.1.0", + "react-transition-group": "^4.4.5", + "uncontrollable": "^7.2.1", + "warning": "^4.0.3" + }, + "peerDependencies": { + "@types/react": ">=16.14.8", + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-calendar": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/react-calendar/-/react-calendar-4.3.0.tgz", + "integrity": "sha512-TyCv8NbXnqXADyXNtMG0szkGvJNH3NG/WMTEE2q6g3RqAsFNyHwYbQD5Kvb6jRV/CqO0WB+oMCtkxblprdeT5A==", + "dependencies": { + "@types/react": "*", + "@wojtekmaj/date-utils": "^1.1.3", + "clsx": "^1.2.1", + "get-user-locale": "^2.2.1", + "prop-types": "^15.6.0" + }, + "funding": { + "url": "https://github.com/wojtekmaj/react-calendar?sponsor=1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-datepicker": { + "version": "4.16.0", + "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.16.0.tgz", + "integrity": "sha512-hNQ0PAg/LQoVbDUO/RWAdm/RYmPhN3cz7LuQ3hqbs24OSp69QCiKOJRrQ4jk1gv1jNR5oYu8SjjgfDh8q6Q1yw==", + "dependencies": { + "@popperjs/core": "^2.11.8", + "classnames": "^2.2.6", + "date-fns": "^2.30.0", + "prop-types": "^15.7.2", + "react-onclickoutside": "^6.12.2", + "react-popper": "^2.3.0" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17 || ^18", + "react-dom": "^16.9.0 || ^17 || ^18" + } + }, + "node_modules/react-dev-utils": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", + "integrity": "sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==", + "dependencies": { + "@babel/code-frame": "^7.16.0", + "address": "^1.1.2", + "browserslist": "^4.18.1", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "detect-port-alt": "^1.1.6", + "escape-string-regexp": "^4.0.0", + "filesize": "^8.0.6", + "find-up": "^5.0.0", + "fork-ts-checker-webpack-plugin": "^6.5.0", + "global-modules": "^2.0.0", + "globby": "^11.0.4", + "gzip-size": "^6.0.0", + "immer": "^9.0.7", + "is-root": "^2.1.0", + "loader-utils": "^3.2.0", + "open": "^8.4.0", + "pkg-up": "^3.1.0", + "prompts": "^2.4.2", + "react-error-overlay": "^6.0.11", + "recursive-readdir": "^2.2.2", + "shell-quote": "^1.7.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/react-dev-utils/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/react-dev-utils/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dom": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", + "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "scheduler": "^0.20.2" + }, + "peerDependencies": { + "react": "17.0.2" + } + }, + "node_modules/react-error-overlay": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", + "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" + }, + "node_modules/react-fast-compare": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" + }, + "node_modules/react-google-recaptcha": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/react-google-recaptcha/-/react-google-recaptcha-2.1.0.tgz", + "integrity": "sha512-K9jr7e0CWFigi8KxC3WPvNqZZ47df2RrMAta6KmRoE4RUi7Ys6NmNjytpXpg4HI/svmQJLKR+PncEPaNJ98DqQ==", + "dependencies": { + "prop-types": "^15.5.0", + "react-async-script": "^1.1.1" + }, + "peerDependencies": { + "react": ">=16.4.1" + } + }, + "node_modules/react-i18next": { + "version": "11.18.6", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.18.6.tgz", + "integrity": "sha512-yHb2F9BiT0lqoQDt8loZ5gWP331GwctHz9tYQ8A2EIEUu+CcEdjBLQWli1USG3RdWQt3W+jqQLg/d4rrQR96LA==", + "dependencies": { + "@babel/runtime": "^7.14.5", + "html-parse-stringify": "^3.0.1" + }, + "peerDependencies": { + "i18next": ">= 19.0.0", + "react": ">= 16.8.0" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, + "node_modules/react-infinite-scroll-component": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/react-infinite-scroll-component/-/react-infinite-scroll-component-6.1.0.tgz", + "integrity": "sha512-SQu5nCqy8DxQWpnUVLx7V7b7LcA37aM7tvoWjTLZp1dk6EJibM5/4EJKzOnl07/BsM1Y40sKLuqjCwwH/xV0TQ==", + "dependencies": { + "throttle-debounce": "^2.1.0" + }, + "peerDependencies": { + "react": ">=16.0.0" + } + }, + "node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, + "node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, + "node_modules/react-onclickoutside": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.13.0.tgz", + "integrity": "sha512-ty8So6tcUpIb+ZE+1HAhbLROvAIJYyJe/1vRrrcmW+jLsaM+/powDRqxzo6hSh9CuRZGSL1Q8mvcF5WRD93a0A==", + "funding": { + "type": "individual", + "url": "https://github.com/Pomax/react-onclickoutside/blob/master/FUNDING.md" + }, + "peerDependencies": { + "react": "^15.5.x || ^16.x || ^17.x || ^18.x", + "react-dom": "^15.5.x || ^16.x || ^17.x || ^18.x" + } + }, + "node_modules/react-popper": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz", + "integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==", + "dependencies": { + "react-fast-compare": "^3.0.1", + "warning": "^4.0.2" + }, + "peerDependencies": { + "@popperjs/core": "^2.0.0", + "react": "^16.8.0 || ^17 || ^18", + "react-dom": "^16.8.0 || ^17 || ^18" + } + }, + "node_modules/react-redux": { + "version": "7.2.9", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz", + "integrity": "sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==", + "dependencies": { + "@babel/runtime": "^7.15.4", + "@types/react-redux": "^7.1.20", + "hoist-non-react-statics": "^3.3.2", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^17.0.2" + }, + "peerDependencies": { + "react": "^16.8.3 || ^17 || ^18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, + "node_modules/react-redux/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "node_modules/react-refresh": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", + "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-router": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", + "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", + "dependencies": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.2", + "react-is": "^16.6.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "peerDependencies": { + "react": ">=15" + } + }, + "node_modules/react-router-dom": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.4.tgz", + "integrity": "sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ==", + "dependencies": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.3.4", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "peerDependencies": { + "react": ">=15" + } + }, + "node_modules/react-router/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/react-scripts": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", + "integrity": "sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==", + "dependencies": { + "@babel/core": "^7.16.0", + "@pmmmwh/react-refresh-webpack-plugin": "^0.5.3", + "@svgr/webpack": "^5.5.0", + "babel-jest": "^27.4.2", + "babel-loader": "^8.2.3", + "babel-plugin-named-asset-import": "^0.3.8", + "babel-preset-react-app": "^10.0.1", + "bfj": "^7.0.2", + "browserslist": "^4.18.1", + "camelcase": "^6.2.1", + "case-sensitive-paths-webpack-plugin": "^2.4.0", + "css-loader": "^6.5.1", + "css-minimizer-webpack-plugin": "^3.2.0", + "dotenv": "^10.0.0", + "dotenv-expand": "^5.1.0", + "eslint": "^8.3.0", + "eslint-config-react-app": "^7.0.1", + "eslint-webpack-plugin": "^3.1.1", + "file-loader": "^6.2.0", + "fs-extra": "^10.0.0", + "html-webpack-plugin": "^5.5.0", + "identity-obj-proxy": "^3.0.0", + "jest": "^27.4.3", + "jest-resolve": "^27.4.2", + "jest-watch-typeahead": "^1.0.0", + "mini-css-extract-plugin": "^2.4.5", + "postcss": "^8.4.4", + "postcss-flexbugs-fixes": "^5.0.2", + "postcss-loader": "^6.2.1", + "postcss-normalize": "^10.0.1", + "postcss-preset-env": "^7.0.1", + "prompts": "^2.4.2", + "react-app-polyfill": "^3.0.0", + "react-dev-utils": "^12.0.1", + "react-refresh": "^0.11.0", + "resolve": "^1.20.0", + "resolve-url-loader": "^4.0.0", + "sass-loader": "^12.3.0", + "semver": "^7.3.5", + "source-map-loader": "^3.0.0", + "style-loader": "^3.3.1", + "tailwindcss": "^3.0.2", + "terser-webpack-plugin": "^5.2.5", + "webpack": "^5.64.4", + "webpack-dev-server": "^4.6.0", + "webpack-manifest-plugin": "^4.0.2", + "workbox-webpack-plugin": "^6.4.1" + }, + "bin": { + "react-scripts": "bin/react-scripts.js" + }, + "engines": { + "node": ">=14.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + }, + "peerDependencies": { + "react": ">= 16", + "typescript": "^3.2.1 || ^4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/react-scripts/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-shallow-renderer": { + "version": "16.15.0", + "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz", + "integrity": "sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==", + "dev": true, + "dependencies": { + "object-assign": "^4.1.1", + "react-is": "^16.12.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-test-renderer": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-17.0.2.tgz", + "integrity": "sha512-yaQ9cB89c17PUb0x6UfWRs7kQCorVdHlutU1boVPEsB8IDZH6n9tHxMacc3y0JoXOJUsZb/t/Mb8FUWMKaM7iQ==", + "dev": true, + "dependencies": { + "object-assign": "^4.1.1", + "react-is": "^17.0.2", + "react-shallow-renderer": "^16.13.1", + "scheduler": "^0.20.2" + }, + "peerDependencies": { + "react": "17.0.2" + } + }, + "node_modules/react-test-renderer/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/react-toastify": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.1.3.tgz", + "integrity": "sha512-fPfb8ghtn/XMxw3LkxQBk3IyagNpF/LIKjOBflbexr2AWxAH1MJgvnESwEwBn9liLFXgTKWgBSdZpw9m4OTHTg==", + "dependencies": { + "clsx": "^1.1.1" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" + }, + "node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/read-pkg/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/realpath-native": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", + "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", + "dev": true, + "dependencies": { + "util.promisify": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/recursive-readdir": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", + "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", + "dependencies": { + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "dependencies": { + "@babel/runtime": "^7.9.2" + } + }, + "node_modules/redux-thunk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz", + "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==", + "peerDependencies": { + "redux": "^4" + } + }, + "node_modules/reflect.ownkeys": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz", + "integrity": "sha512-qOLsBKHCpSOFKK1NUOCGC5VyeufB6lEsFe92AL2bhIJsacZS1qdoOZSbPk3MYKuT2cFlRDnulKXuuElIrMjGUg==" + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz", + "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + }, + "node_modules/regenerator-transform": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.1.tgz", + "integrity": "sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==", + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "dependencies": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regex-parser": { + "version": "2.2.11", + "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.11.tgz", + "integrity": "sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q==" + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", + "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/registry-auth-token": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz", + "integrity": "sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==", + "dev": true, + "dependencies": { + "rc": "1.2.8" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dev": true, + "dependencies": { + "rc": "^1.2.8" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", + "dev": true + }, + "node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "node_modules/renderkid/node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/renderkid/node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/repeat-element": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", + "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dev": true, + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/request-promise-core": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", + "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.19" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "request": "^2.34" + } + }, + "node_modules/request-promise-native": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz", + "integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==", + "deprecated": "request-promise-native has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142", + "dev": true, + "dependencies": { + "request-promise-core": "1.1.4", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + }, + "engines": { + "node": ">=0.12.0" + }, + "peerDependencies": { + "request": "^2.34" + } + }, + "node_modules/request-promise-native/node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/request/node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/request/node_modules/qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/request/node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/request/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + }, + "node_modules/reselect": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", + "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==" + }, + "node_modules/resolve": { + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", + "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "dependencies": { + "is-core-module": "^2.11.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-dir/node_modules/global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "dependencies": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-dir/node_modules/global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-dir/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pathname": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", + "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" + }, + "node_modules/resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", + "deprecated": "https://github.com/lydell/resolve-url#deprecated", + "dev": true + }, + "node_modules/resolve-url-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-4.0.0.tgz", + "integrity": "sha512-05VEMczVREcbtT7Bz+C+96eUO5HDNvdthIiMB34t7FcF8ehcu4wC0sSgPUubs3XW2Q3CNLJk/BJrCU9wVRymiA==", + "dependencies": { + "adjust-sourcemap-loader": "^4.0.0", + "convert-source-map": "^1.7.0", + "loader-utils": "^2.0.0", + "postcss": "^7.0.35", + "source-map": "0.6.1" + }, + "engines": { + "node": ">=8.9" + }, + "peerDependencies": { + "rework": "1.0.1", + "rework-visit": "1.0.0" + }, + "peerDependenciesMeta": { + "rework": { + "optional": true + }, + "rework-visit": { + "optional": true + } + } + }, + "node_modules/resolve-url-loader/node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/resolve-url-loader/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/resolve-url-loader/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/resolve-url-loader/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve.exports": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.1.tgz", + "integrity": "sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/response-iterator": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/response-iterator/-/response-iterator-0.2.6.tgz", + "integrity": "sha512-pVzEEzrsg23Sh053rmDUvLSkGXluZio0qu8VT6ukrYuvtjVfCbDZH9d6PGXb8HZfzdNZt8feXv/jvUzlhRgLnw==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", + "dev": true, + "dependencies": { + "lowercase-keys": "^1.0.0" + } + }, + "node_modules/restructure": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/restructure/-/restructure-3.0.0.tgz", + "integrity": "sha512-Xj8/MEIhhfj9X2rmD9iJ4Gga9EFqVlpMj3vfLnV2r/Mh5jRMryNV+6lWh9GdJtDBcBSPIqzRdfBQ3wDtNFv/uw==" + }, + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "engines": { + "node": ">=0.12" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "2.79.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", + "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup-plugin-terser": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", + "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", + "deprecated": "This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "jest-worker": "^26.2.1", + "serialize-javascript": "^4.0.0", + "terser": "^5.0.0" + }, + "peerDependencies": { + "rollup": "^2.0.0" + } + }, + "node_modules/rollup-plugin-terser/node_modules/jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/rollup-plugin-terser/node_modules/serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/rst-selector-parser": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz", + "integrity": "sha512-nDG1rZeP6oFTLN6yNDV/uiAvs1+FS/KlrEwh7+y7dpuApDBy6bI2HTBcc0/V8lv9OTqfyD34eF7au2pm8aBbhA==", + "dependencies": { + "lodash.flattendeep": "^4.4.0", + "nearley": "^2.7.10" + } + }, + "node_modules/rsvp": { + "version": "4.8.5", + "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", + "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==", + "dev": true, + "engines": { + "node": "6.* || >= 7.*" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", + "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==", + "dev": true, + "dependencies": { + "ret": "~0.1.10" + } + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sane": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz", + "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", + "deprecated": "some dependency vulnerabilities fixed, support for node < 10 dropped, and newer ECMAScript syntax/features added", + "dev": true, + "dependencies": { + "@cnakazawa/watch": "^1.0.3", + "anymatch": "^2.0.0", + "capture-exit": "^2.0.0", + "exec-sh": "^0.3.2", + "execa": "^1.0.0", + "fb-watchman": "^2.0.0", + "micromatch": "^3.1.4", + "minimist": "^1.1.1", + "walker": "~1.0.5" + }, + "bin": { + "sane": "src/cli.js" + }, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/sane/node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "node_modules/sane/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sane/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sane/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/sane/node_modules/execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "dependencies": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/sane/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sane/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sane/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/sane/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sane/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sane/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sane/node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sane/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sane/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sane/node_modules/npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", + "dev": true, + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/sane/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/sane/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/sane/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sane/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sane/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sane/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/sanitize.css": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-13.0.0.tgz", + "integrity": "sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA==" + }, + "node_modules/sass-graph": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-4.0.1.tgz", + "integrity": "sha512-5YCfmGBmxoIRYHnKK2AKzrAkCoQ8ozO+iumT8K4tXJXRVCPf+7s1/9KxTSW3Rbvf+7Y7b4FR3mWyLnQr3PHocA==", + "dependencies": { + "glob": "^7.0.0", + "lodash": "^4.17.11", + "scss-tokenizer": "^0.4.3", + "yargs": "^17.2.1" + }, + "bin": { + "sassgraph": "bin/sassgraph" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/sass-graph/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/sass-graph/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/sass-graph/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/sass-loader": { + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.6.0.tgz", + "integrity": "sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA==", + "dependencies": { + "klona": "^2.0.4", + "neo-async": "^2.6.2" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "fibers": ">= 3.1.0", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0", + "sass": "^1.3.0", + "sass-embedded": "*", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "fibers": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + } + } + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "node_modules/saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/scheduler": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/scss-tokenizer": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.4.3.tgz", + "integrity": "sha512-raKLgf1LI5QMQnG+RxHz6oK0sL3x3I4FN2UDLqgLOGO8hodECNnNh5BXn7fAyBxrA8zVzdQizQ6XjNJQ+uBwMw==", + "dependencies": { + "js-base64": "^2.4.9", + "source-map": "^0.7.3" + } + }, + "node_modules/scss-tokenizer/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==" + }, + "node_modules/selfsigned": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz", + "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==", + "dependencies": { + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "dev": true, + "dependencies": { + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/semver-diff/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/send/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" + }, + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, + "node_modules/set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/set-value/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/set-value/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/shiki": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.3.tgz", + "integrity": "sha512-U3S/a+b0KS+UkTyMjoNojvTgrBHjgp7L6ovhFVZsXmBGnVdQ4K4U9oK0z63w538S91ATngv1vXigHCSWOwnr+g==", + "dependencies": { + "ansi-sequence-parser": "^1.1.0", + "jsonc-parser": "^3.2.0", + "vscode-oniguruma": "^1.7.0", + "vscode-textmate": "^8.0.0" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/sirv": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.3.tgz", + "integrity": "sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA==", + "dev": true, + "dependencies": { + "@polka/url": "^1.0.0-next.20", + "mrmime": "^1.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "dependencies": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "dependencies": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "dependencies": { + "kind-of": "^3.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/snapdragon/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", + "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" + }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-loader": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-3.0.2.tgz", + "integrity": "sha512-BokxPoLjyl3iOrgkWaakaxqnelAJSS+0V+De0kKIq6lyWrXuiPgYTGp6z3iHmqljKAaLXwZa+ctD8GccRJeVvg==", + "dependencies": { + "abab": "^2.0.5", + "iconv-lite": "^0.6.3", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", + "dev": true, + "dependencies": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-url": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", + "deprecated": "See https://github.com/lydell/source-map-url#deprecated", + "dev": true + }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "deprecated": "Please use @jridgewell/sourcemap-codec instead" + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==" + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "dependencies": { + "extend-shallow": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "node_modules/sshpk": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "dev": true, + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ssri": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", + "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility" + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==" + }, + "node_modules/static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==", + "dev": true, + "dependencies": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/stdout-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", + "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", + "dependencies": { + "readable-stream": "^2.0.1" + } + }, + "node_modules/stdout-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/stdout-stream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/stdout-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/stdout-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", + "integrity": "sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==", + "dev": true + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-natural-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/string-natural-compare/-/string-natural-compare-3.0.1.tgz", + "integrity": "sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==" + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", + "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.4.3", + "side-channel": "^1.0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "dependencies": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/stringify-object/node_modules/is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", + "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-loader": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.3.tgz", + "integrity": "sha512-53BiGLXAcll9maCYtZi2RCQZKa8NQQai5C4horqKyRmHj9H7QmcUyucrH+4KW/gBQbXM2AsB0axoEcFZPlfPcw==", + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/stylehacks": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", + "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", + "dependencies": { + "browserslist": "^4.21.4", + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + }, + "node_modules/sucrase": { + "version": "3.33.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.33.0.tgz", + "integrity": "sha512-ARGC7vbufOHfpvyGcZZXFaXCMZ9A4fffOGC5ucOW7+WHDGlAe8LJdf3Jts1sWhDeiI1RSWrKy5Hodl+JWGdW2A==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "7.1.6", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sucrase/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/sucrase/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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/supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" + }, + "node_modules/svgo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", + "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", + "deprecated": "This SVGO version is no longer supported. Upgrade to v2.x.x.", + "dependencies": { + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", + "css-tree": "1.0.0-alpha.37", + "csso": "^4.0.2", + "js-yaml": "^3.13.1", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/svgo/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/svgo/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/svgo/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/svgo/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/svgo/node_modules/css-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "node_modules/svgo/node_modules/css-what": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", + "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/svgo/node_modules/dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dependencies": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + } + }, + "node_modules/svgo/node_modules/domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dependencies": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "node_modules/svgo/node_modules/domutils/node_modules/domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, + "node_modules/svgo/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/svgo/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/svgo/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/svgo/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/svgo/node_modules/nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dependencies": { + "boolbase": "~1.0.0" + } + }, + "node_modules/svgo/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/symbol-observable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", + "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" + }, + "node_modules/tailwindcss": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz", + "integrity": "sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.2.12", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.18.2", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/tailwindcss/node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/tar": { + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", + "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/tempy": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz", + "integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==", + "dependencies": { + "is-stream": "^2.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^0.16.0", + "unique-string": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "dependencies": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terser": { + "version": "5.19.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.19.0.tgz", + "integrity": "sha512-JpcpGOQLOXm2jsomozdMDpd5f8ZHh1rR48OFgWUH3QsyZcfPgv2qDCYbcDEAYNd4OZRj2bWYKpwdll/udZCk/Q==", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", + "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.17", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.16.8" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/throat": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz", + "integrity": "sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==" + }, + "node_modules/throttle-debounce": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-2.3.0.tgz", + "integrity": "sha512-H7oLPV0P7+jgvrk+6mwwwBDmxTaxnu9HMXmloNLXwnNO0ZxZ31Orah2n8lU1eMPvsaowP2CX+USCgyovXfdOFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" + }, + "node_modules/tiny-inflate": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==" + }, + "node_modules/tiny-invariant": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz", + "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==" + }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==" + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-object-path/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "dependencies": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/tough-cookie": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", + "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tough-cookie/node_modules/universalify": { + "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" + } + }, + "node_modules/tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/true-case-path": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-2.2.1.tgz", + "integrity": "sha512-0z3j8R7MCjy10kc/g+qg7Ln3alJTodw9aDuVWZa3uiWqfuBMKeAeP2ocWcxoyM3D73yz3Jt/Pu4qPr4wHSdB/Q==" + }, + "node_modules/tryer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", + "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==" + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" + }, + "node_modules/ts-invariant": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.10.3.tgz", + "integrity": "sha512-uivwYcQaxAucv1CzRp2n/QdYPo4ILf9VXgH19zEIjFx2EJufV16P0JtJVpYHy89DItG6Kwj2oIUjrcK5au+4tQ==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", + "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/tslib": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typedoc": { + "version": "0.24.8", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.24.8.tgz", + "integrity": "sha512-ahJ6Cpcvxwaxfu4KtjA8qZNqS43wYt6JL27wYiIgl1vd38WW/KWX11YuAeZhuz9v+ttrutSsgK+XO1CjL1kA3w==", + "dependencies": { + "lunr": "^2.3.9", + "marked": "^4.3.0", + "minimatch": "^9.0.0", + "shiki": "^0.14.1" + }, + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 14.14" + }, + "peerDependencies": { + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x" + } + }, + "node_modules/typedoc-plugin-markdown": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-3.16.0.tgz", + "integrity": "sha512-eeiC78fDNGFwemPIHiwRC+mEC7W5jwt3fceUev2gJ2nFnXpVHo8eRrpC9BLWZDee6ehnz/sPmNjizbXwpfaTBw==", + "dependencies": { + "handlebars": "^4.7.7" + }, + "peerDependencies": { + "typedoc": ">=0.24.0" + } + }, + "node_modules/typedoc/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/typedoc/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/uglify-js": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/uncontrollable": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz", + "integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==", + "dependencies": { + "@babel/runtime": "^7.6.3", + "@types/react": ">=16.9.11", + "invariant": "^2.2.4", + "react-lifecycles-compat": "^3.0.4" + }, + "peerDependencies": { + "react": ">=15.0.0" + } + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-properties": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz", + "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==", + "dependencies": { + "base64-js": "^1.3.0", + "unicode-trie": "^2.0.0" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-trie": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz", + "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==", + "dependencies": { + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" + } + }, + "node_modules/unicode-trie/node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==" + }, + "node_modules/union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "dependencies": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/union-value/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unique-filename": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", + "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", + "dependencies": { + "unique-slug": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/unique-slug": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", + "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unquote": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", + "integrity": "sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg==" + }, + "node_modules/unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==", + "dev": true, + "dependencies": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==", + "dev": true, + "dependencies": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", + "dev": true, + "dependencies": { + "isarray": "1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", + "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/update-notifier": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", + "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", + "dev": true, + "dependencies": { + "boxen": "^5.0.0", + "chalk": "^4.1.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.4.0", + "is-npm": "^5.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.1.0", + "pupa": "^2.1.1", + "semver": "^7.3.4", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/yeoman/update-notifier?sponsor=1" + } + }, + "node_modules/update-notifier/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "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/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", + "deprecated": "Please see https://github.com/lydell/urix#deprecated", + "dev": true + }, + "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-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", + "dev": true, + "dependencies": { + "prepend-http": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-to-istanbul": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", + "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0", + "source-map": "^0.7.3" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/value-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", + "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/verror/node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true + }, + "node_modules/void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/vscode-oniguruma": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==" + }, + "node_modules/vscode-textmate": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==" + }, + "node_modules/w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "deprecated": "Use your platform's native performance.now() and performance.timeOrigin.", + "dependencies": { + "browser-process-hrtime": "^1.0.0" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "dependencies": { + "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/web-vitals": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-1.1.2.tgz", + "integrity": "sha512-PFMKIY+bRSXlMxVAQ+m2aw9c/ioUYfDgrYot0YUa+/xa0sakubWhSDyxAKwzymvXVdF4CZI71g06W+mqhzu6ig==" + }, + "node_modules/webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "engines": { + "node": ">=10.4" + } + }, + "node_modules/webpack": { + "version": "5.88.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.1.tgz", + "integrity": "sha512-FROX3TxQnC/ox4N+3xQoWZzvGXSuscxR32rbzjpXgEzWudJFEJBpdlkkob2ylrv5yzzufD1zph1OoFsLtm6stQ==", + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.9.0", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.7", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-middleware": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", + "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.3", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/webpack-dev-middleware/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack-dev-middleware/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/webpack-dev-middleware/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack-dev-server": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz", + "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==", + "dependencies": { + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/serve-static": "^1.13.10", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.5.5", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.0.11", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.0.1", + "launch-editor": "^2.6.0", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "rimraf": "^3.0.2", + "schema-utils": "^4.0.0", + "selfsigned": "^2.1.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^5.3.1", + "ws": "^8.13.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack-dev-server/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack-dev-server/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/webpack-dev-server/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack-manifest-plugin": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/webpack-manifest-plugin/-/webpack-manifest-plugin-4.1.1.tgz", + "integrity": "sha512-YXUAwxtfKIJIKkhg03MKuiFAD72PlrqCiwdwO4VEXdRO5V0ORCNwaOwAZawPZalCbmH9kBDmXnNeQOw+BIEiow==", + "dependencies": { + "tapable": "^2.0.0", + "webpack-sources": "^2.2.0" + }, + "engines": { + "node": ">=12.22.0" + }, + "peerDependencies": { + "webpack": "^4.44.2 || ^5.47.0" + } + }, + "node_modules/webpack-manifest-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-manifest-plugin/node_modules/webpack-sources": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", + "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", + "dependencies": { + "source-list-map": "^2.0.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dependencies": { + "iconv-lite": "0.4.24" + } + }, + "node_modules/whatwg-encoding/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/whatwg-fetch": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", + "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==" + }, + "node_modules/whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==" + }, + "node_modules/whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "dependencies": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.10.tgz", + "integrity": "sha512-uxoA5vLUfRPdjCuJ1h5LlYdmTLbYfums398v3WLkM+i/Wltl2/XyZpQWKbN++ck5L64SR/grOHqtXCUKmlZPNA==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" + }, + "node_modules/workbox-background-sync": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-6.6.0.tgz", + "integrity": "sha512-jkf4ZdgOJxC9u2vztxLuPT/UjlH7m/nWRQ/MgGL0v8BJHoZdVGJd18Kck+a0e55wGXdqyHO+4IQTk0685g4MUw==", + "dependencies": { + "idb": "^7.0.1", + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-broadcast-update": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-6.6.0.tgz", + "integrity": "sha512-nm+v6QmrIFaB/yokJmQ/93qIJ7n72NICxIwQwe5xsZiV2aI93MGGyEyzOzDPVz5THEr5rC3FJSsO3346cId64Q==", + "dependencies": { + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-build": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-6.6.0.tgz", + "integrity": "sha512-Tjf+gBwOTuGyZwMz2Nk/B13Fuyeo0Q84W++bebbVsfr9iLkDSo6j6PST8tET9HYA58mlRXwlMGpyWO8ETJiXdQ==", + "dependencies": { + "@apideck/better-ajv-errors": "^0.3.1", + "@babel/core": "^7.11.1", + "@babel/preset-env": "^7.11.0", + "@babel/runtime": "^7.11.2", + "@rollup/plugin-babel": "^5.2.0", + "@rollup/plugin-node-resolve": "^11.2.1", + "@rollup/plugin-replace": "^2.4.1", + "@surma/rollup-plugin-off-main-thread": "^2.2.3", + "ajv": "^8.6.0", + "common-tags": "^1.8.0", + "fast-json-stable-stringify": "^2.1.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", + "lodash": "^4.17.20", + "pretty-bytes": "^5.3.0", + "rollup": "^2.43.1", + "rollup-plugin-terser": "^7.0.0", + "source-map": "^0.8.0-beta.0", + "stringify-object": "^3.3.0", + "strip-comments": "^2.0.1", + "tempy": "^0.6.0", + "upath": "^1.2.0", + "workbox-background-sync": "6.6.0", + "workbox-broadcast-update": "6.6.0", + "workbox-cacheable-response": "6.6.0", + "workbox-core": "6.6.0", + "workbox-expiration": "6.6.0", + "workbox-google-analytics": "6.6.0", + "workbox-navigation-preload": "6.6.0", + "workbox-precaching": "6.6.0", + "workbox-range-requests": "6.6.0", + "workbox-recipes": "6.6.0", + "workbox-routing": "6.6.0", + "workbox-strategies": "6.6.0", + "workbox-streams": "6.6.0", + "workbox-sw": "6.6.0", + "workbox-window": "6.6.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/workbox-build/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/workbox-build/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/workbox-build/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/workbox-build/node_modules/source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "dependencies": { + "whatwg-url": "^7.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/workbox-build/node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/workbox-build/node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" + }, + "node_modules/workbox-build/node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "node_modules/workbox-cacheable-response": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-6.6.0.tgz", + "integrity": "sha512-JfhJUSQDwsF1Xv3EV1vWzSsCOZn4mQ38bWEBR3LdvOxSPgB65gAM6cS2CX8rkkKHRgiLrN7Wxoyu+TuH67kHrw==", + "deprecated": "workbox-background-sync@6.6.0", + "dependencies": { + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-core": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.6.0.tgz", + "integrity": "sha512-GDtFRF7Yg3DD859PMbPAYPeJyg5gJYXuBQAC+wyrWuuXgpfoOrIQIvFRZnQ7+czTIQjIr1DhLEGFzZanAT/3bQ==" + }, + "node_modules/workbox-expiration": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.6.0.tgz", + "integrity": "sha512-baplYXcDHbe8vAo7GYvyAmlS4f6998Jff513L4XvlzAOxcl8F620O91guoJ5EOf5qeXG4cGdNZHkkVAPouFCpw==", + "dependencies": { + "idb": "^7.0.1", + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-google-analytics": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-6.6.0.tgz", + "integrity": "sha512-p4DJa6OldXWd6M9zRl0H6vB9lkrmqYFkRQ2xEiNdBFp9U0LhsGO7hsBscVEyH9H2/3eZZt8c97NB2FD9U2NJ+Q==", + "dependencies": { + "workbox-background-sync": "6.6.0", + "workbox-core": "6.6.0", + "workbox-routing": "6.6.0", + "workbox-strategies": "6.6.0" + } + }, + "node_modules/workbox-navigation-preload": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-6.6.0.tgz", + "integrity": "sha512-utNEWG+uOfXdaZmvhshrh7KzhDu/1iMHyQOV6Aqup8Mm78D286ugu5k9MFD9SzBT5TcwgwSORVvInaXWbvKz9Q==", + "dependencies": { + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-precaching": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.6.0.tgz", + "integrity": "sha512-eYu/7MqtRZN1IDttl/UQcSZFkHP7dnvr/X3Vn6Iw6OsPMruQHiVjjomDFCNtd8k2RdjLs0xiz9nq+t3YVBcWPw==", + "dependencies": { + "workbox-core": "6.6.0", + "workbox-routing": "6.6.0", + "workbox-strategies": "6.6.0" + } + }, + "node_modules/workbox-range-requests": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-6.6.0.tgz", + "integrity": "sha512-V3aICz5fLGq5DpSYEU8LxeXvsT//mRWzKrfBOIxzIdQnV/Wj7R+LyJVTczi4CQ4NwKhAaBVaSujI1cEjXW+hTw==", + "dependencies": { + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-recipes": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-6.6.0.tgz", + "integrity": "sha512-TFi3kTgYw73t5tg73yPVqQC8QQjxJSeqjXRO4ouE/CeypmP2O/xqmB/ZFBBQazLTPxILUQ0b8aeh0IuxVn9a6A==", + "dependencies": { + "workbox-cacheable-response": "6.6.0", + "workbox-core": "6.6.0", + "workbox-expiration": "6.6.0", + "workbox-precaching": "6.6.0", + "workbox-routing": "6.6.0", + "workbox-strategies": "6.6.0" + } + }, + "node_modules/workbox-routing": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.6.0.tgz", + "integrity": "sha512-x8gdN7VDBiLC03izAZRfU+WKUXJnbqt6PG9Uh0XuPRzJPpZGLKce/FkOX95dWHRpOHWLEq8RXzjW0O+POSkKvw==", + "dependencies": { + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-strategies": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.6.0.tgz", + "integrity": "sha512-eC07XGuINAKUWDnZeIPdRdVja4JQtTuc35TZ8SwMb1ztjp7Ddq2CJ4yqLvWzFWGlYI7CG/YGqaETntTxBGdKgQ==", + "dependencies": { + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-streams": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-6.6.0.tgz", + "integrity": "sha512-rfMJLVvwuED09CnH1RnIep7L9+mj4ufkTyDPVaXPKlhi9+0czCu+SJggWCIFbPpJaAZmp2iyVGLqS3RUmY3fxg==", + "dependencies": { + "workbox-core": "6.6.0", + "workbox-routing": "6.6.0" + } + }, + "node_modules/workbox-sw": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-6.6.0.tgz", + "integrity": "sha512-R2IkwDokbtHUE4Kus8pKO5+VkPHD2oqTgl+XJwh4zbF1HyjAbgNmK/FneZHVU7p03XUt9ICfuGDYISWG9qV/CQ==" + }, + "node_modules/workbox-webpack-plugin": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-webpack-plugin/-/workbox-webpack-plugin-6.6.0.tgz", + "integrity": "sha512-xNZIZHalboZU66Wa7x1YkjIqEy1gTR+zPM+kjrYJzqN7iurYZBctBLISyScjhkJKYuRrZUP0iqViZTh8rS0+3A==", + "dependencies": { + "fast-json-stable-stringify": "^2.1.0", + "pretty-bytes": "^5.4.1", + "upath": "^1.2.0", + "webpack-sources": "^1.4.3", + "workbox-build": "6.6.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "webpack": "^4.4.0 || ^5.9.0" + } + }, + "node_modules/workbox-webpack-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/workbox-webpack-plugin/node_modules/webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dependencies": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "node_modules/workbox-window": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-6.6.0.tgz", + "integrity": "sha512-L4N9+vka17d16geaJXXRjENLFldvkWy7JyGxElRD0JvBxvFEd8LOhr+uXCcar/NzAmIBRv9EZ+M+Qr4mOoBITw==", + "dependencies": { + "@types/trusted-types": "^2.0.2", + "workbox-core": "6.6.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/ws": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==" + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yarn": { + "version": "1.22.19", + "resolved": "https://registry.npmjs.org/yarn/-/yarn-1.22.19.tgz", + "integrity": "sha512-/0V5q0WbslqnwP91tirOvldvYISzaqhClxzyUKXYxs07yUILIs5jx/k6CFe8bvKSkds5w+eiOqta39Wk3WxdcQ==", + "hasInstallScript": true, + "bin": { + "yarn": "bin/yarn.js", + "yarnpkg": "bin/yarn.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zen-observable": { + "version": "0.8.15", + "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", + "integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==" + }, + "node_modules/zen-observable-ts": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-1.2.5.tgz", + "integrity": "sha512-QZWQekv6iB72Naeake9hS1KxHlotfRpe+WGNbNx5/ta+R3DNjVO2bswf63gXlWDcs+EMd7XY8HfVQyP1X6T4Zg==", + "dependencies": { + "zen-observable": "0.8.15" + } + }, + "node_modules/zod": { + "version": "3.21.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz", + "integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/package.json b/package.json index 6526d77a59..1fbc68abf3 100644 --- a/package.json +++ b/package.json @@ -1,34 +1,85 @@ { - "name": "my-app", - "version": "0.1.0", + "name": "talawa-admin", + "version": "3.0.0", "private": true, + "type": "module", "dependencies": { - "@testing-library/jest-dom": "^5.11.4", + "@apollo/client": "^3.4.0-beta.19", + "@apollo/link-error": "^2.0.0-beta.3", + "@apollo/react-testing": "^4.0.0", + "@emotion/react": "^11.11.1", + "@emotion/styled": "^11.11.0", + "@mui/icons-material": "^5.8.3", + "@mui/material": "^5.14.1", + "@mui/private-theming": "^5.14.13", + "@mui/system": "^5.14.12", + "@mui/x-charts": "^6.0.0-alpha.13", + "@mui/x-data-grid": "^6.8.0", + "@mui/x-date-pickers": "^6.6.0", + "@pdfme/generator": "^1.2.6", + "@testing-library/jest-dom": "^5.14.1", "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", - "@types/jest": "^26.0.15", - "@types/node": "^12.0.0", - "@types/react": "^17.0.0", - "@types/react-dom": "^17.0.0", + "@types/enzyme-adapter-react-16": "^1.0.6", + "@types/jest": "^26.0.24", + "@types/jquery": "^3.5.6", + "@types/node": "^12.20.16", + "@types/react-bootstrap": "^0.32.32", + "@types/react-datepicker": "^4.1.4", + "@types/react-dom": "^17.0.9", + "@types/react-google-recaptcha": "^2.1.5", + "@types/react-modal": "^3.12.1", + "bootstrap": "^5.3.0", + "dayjs": "^1.10.7", + "detect-newline": "^4.0.0", + "enzyme": "^3.11.0", + "enzyme-adapter-react-16": "^1.15.6", "eslint-config-prettier": "^8.3.0", + "eslint-plugin-jest": "^25.3.4", "eslint-plugin-prettier": "^3.4.0", - "prettier": "^2.3.0", + "flag-icons": "^6.6.6", + "graphql": "^15.5.1", + "graphql-tag": "^2.12.6", + "graphql-ws": "^5.14.0", + "i18next": "^21.8.14", + "i18next-browser-languagedetector": "^6.1.4", + "i18next-http-backend": "^1.4.1", + "jest-docblock": "^27.4.0", + "js-cookie": "^3.0.1", + "node-sass": "^9.0.0", + "prettier": "^2.3.2", "react": "^17.0.2", - "react-bootstrap": "^1.5.2", + "react-bootstrap": "^2.7.4", + "react-calendar": "^4.2.1", + "react-datepicker": "^4.2.0", "react-dom": "^17.0.2", + "react-google-recaptcha": "^2.1.0", + "react-i18next": "^11.18.1", + "react-infinite-scroll-component": "^6.1.0", + "react-redux": "^7.2.5", "react-router-dom": "^5.2.0", - "react-scripts": "4.0.3", - "typescript": "^4.2.4", - "web-vitals": "^1.0.1" + "react-scripts": "5.0.1", + "react-toastify": "^9.0.3", + "redux": "^4.1.1", + "redux-thunk": "^2.3.0", + "typedoc": "^0.24.8", + "typedoc-plugin-markdown": "^3.16.0", + "typescript": "^4.3.5", + "web-vitals": "^1.0.1", + "yarn": "^1.22.17" }, "scripts": { "serve": "react-scripts start", "build": "react-scripts build", - "test": "react-scripts test", + "test": "cross-env NODE_ENV=test node scripts/test.js --env=./scripts/custom-test-env.js --watchAll --coverage", "eject": "react-scripts eject", - "lint": "eslint 'src/*.{ts,tsx}'", - "lint-fix": "eslint 'src/*.{ts,tsx}' --fix", - "format": "prettier --write \"**/*.{ts,tsx,json,scss,css}\"" + "lint:check": "eslint \"**/*.{ts,tsx}\" --max-warnings=0", + "lint:fix": "eslint \"**/*.{ts,tsx}\" --fix", + "format:fix": "prettier --write \"**/*.{ts,tsx,json,scss,css}\"", + "format:check": "prettier --check \"**/*.{ts,tsx,json,scss,css}\"", + "typecheck": "tsc --project tsconfig.json --noEmit", + "prepare": "husky install", + "jest-preview": "jest-preview" }, "eslintConfig": { "extends": [ @@ -49,8 +100,32 @@ ] }, "devDependencies": { - "@typescript-eslint/eslint-plugin": "^4.24.0", - "@typescript-eslint/parser": "^4.24.0", - "eslint-plugin-react-hooks": "^4.2.0" + "@babel/plugin-proposal-private-property-in-object": "^7.21.11", + "@fortawesome/fontawesome-svg-core": "^1.2.35", + "@fortawesome/free-brands-svg-icons": "^5.15.3", + "@fortawesome/react-fontawesome": "^0.1.14", + "@types/enzyme": "^3.10.9", + "@types/js-cookie": "^3.0.2", + "@types/react": "^17.0.14", + "@types/react-router-dom": "^5.1.8", + "@typescript-eslint/eslint-plugin": "^5.9.0", + "@typescript-eslint/parser": "^5.9.0", + "@wojtekmaj/enzyme-adapter-react-17": "^0.8.0", + "cross-env": "^7.0.3", + "husky": "^8.0.3", + "identity-obj-proxy": "^3.0.0", + "jest": "^27.4.5", + "jest-enzyme": "^7.1.2", + "jest-localstorage-mock": "^2.4.19", + "jest-location-mock": "^1.0.9", + "jest-preview": "^0.3.1", + "jquery": "^3.2.1", + "postcss-modules": "^6.0.0" + }, + "resolutions": { + "@apollo/client": "^3.4.0-beta.19", + "@types/react": "17.0.2", + "@types/react-dom": "17.0.2", + "graphql": "^16.5.0" } } diff --git a/public/favicon.ico b/public/favicon.ico index a11777cc471a4344702741ab1c8a588998b1311a..0675af2934d8d350d002845f0fb9d223e1ccd06e 100644 GIT binary patch literal 870 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 baj7?x%VD!5Cxk2YbYLNVeiXvvpMCWYo=by@ diff --git a/public/favicon_palisadoes.ico b/public/favicon_palisadoes.ico new file mode 100644 index 0000000000000000000000000000000000000000..0675af2934d8d350d002845f0fb9d223e1ccd06e GIT binary patch literal 870 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 q~76bbQU*Gku3{R!`d+?8U~=i8_2od>&*E|FJ< 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 T{a5e1r3K*mfd5`K0r>v~Nti{( literal 0 HcmV?d00001 diff --git a/public/logo512.png b/public/images/logo512.png similarity index 100% rename from public/logo512.png rename to public/images/logo512.png diff --git a/public/index.html b/public/index.html index 72527d8e95..e17b0de972 100644 --- a/public/index.html +++ b/public/index.html @@ -2,11 +2,12 @@ - + - + + Talawa Admin diff --git a/public/locales/en.json b/public/locales/en.json new file mode 100644 index 0000000000..bfefeec253 --- /dev/null +++ b/public/locales/en.json @@ -0,0 +1,690 @@ +{ + "loginPage": { + "title": "Talawa Admin", + "fromPalisadoes": "An open source application by Palisadoes Foundation volunteers", + "talawa_portal": "Talawa Admin Portal", + "login": "Login", + "register": "Register", + "firstName": "First Name", + "lastName": "Last Name", + "email": "Email", + "password": "Password", + "atleast_8_char_long": "Atleast 8 Character long", + "Password_and_Confirm_password_mismatches.": "Password and Confirm password mismatches.", + "confirmPassword": "Confirm Password", + "forgotPassword": "Forgot Password ?", + "enterEmail": "Enter Email", + "enterPassword": "Enter Password", + "doNotOwnAnAccount": "Do not own an account?", + "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too.", + "captchaError": "Captcha Error!", + "Please_check_the_captcha": "Please, check the captcha.", + "Something_went_wrong": "Something went wrong, Please try after sometime.", + "passwordMismatches": "Password and Confirm password mismatches.", + "fillCorrectly": "Fill all the Details Correctly.", + "notAuthorised": "Sorry! you are not Authorised!", + "notFound": "User not found!", + "successfullyRegistered": "Successfully Registered. Please wait until you will be approved.", + "login_to_admin_portal": "Admin Portal Login", + "OR": "OR" + }, + "latestEvents": { + "eventCardTitle": "Upcoming Events", + "eventCardSeeAll": "See All", + "noEvents": "No Upcoming Events" + }, + "latestPosts": { + "latestPostsTitle": "Latest Posts", + "seeAllLink": "See All", + "noPostsCreated": "No Posts Created" + }, + "listNavbar": { + "talawa_portal": "Talawa Admin Portal", + "roles": "Roles", + "requests": "Requests", + "logout": "Logout" + }, + "leftDrawer": { + "talawaAdminPortal": "Talawa Admin Portal", + "menu": "Menu", + "organizations": "Organizations", + "requests": "Requests", + "users": "Users", + "logout": "Logout" + }, + "leftDrawerOrg": { + "talawaAdminPortal": "Talawa Admin Portal", + "menu": "Menu", + "logout": "Logout", + "talawa_portal": "Talawa Admin Portal", + "Dashboard": "Dashboard", + "People": "People", + "Events": "Events", + "Contributions": "Contributions", + "Posts": "Posts", + "Block/Unblock": "Block/Unblock", + "Plugins": "Plugins", + "Plugin Store": "Plugin Store", + "Advertisement": "Advertisements", + "allOrganizations": "All Organizations", + "yourOrganization": "Your Organization", + "notification": "Notification", + "settings": "Settings", + "language": "Language", + "notifications": "Notifications", + "spamsThe": "spams the", + "group": "group", + "noNotifications": "No Notifications", + "close": "Close" + }, + "orgList": { + "title": "Talawa Organizations", + "you": "You", + "name": "Name", + "designation": "Designation", + "email": "Email", + "searchByName": "Search By Name", + "organizations": "Organizations", + "createOrganization": "Create Organization", + "createSampleOrganization": "Create Sample Organization", + "description": "Description", + "location": "Location", + "isPublic": "Is Public", + "visibleInSearch": "Visible In Search", + "displayImage": "Display Image", + "enterName": "Enter Name", + "sort": "Sort", + "filter": "Filter", + "cancel": "Cancel", + "noOrgErrorTitle": "Organizations Not Found", + "sampleOrgDuplicate": "Only one sample organization allowed", + "noOrgErrorDescription": "Please create an organization through dashboard", + "endOfResults": "End of results", + "manageFeatures": "Manage Features", + "manageFeaturesInfo": "Creation Successful ! Please select features that you want to enale for this organization from the plugin store.", + "goToStore": "Go to Plugin Store", + "enableEverything": "Enable Everything", + "noResultsFoundFor": "No results found for", + "OR": "OR", + "sampleOrgSuccess": "Sample Organization Successfully Created" + }, + "orgListCard": { + "admins": "Admins", + "members": "Members", + "manage": "Manage", + "sampleOrganization": "Sample Organization" + }, + "paginationList": { + "rowsPerPage": "rows per page", + "all": "All" + }, + "users": { + "title": "Talawa Roles", + "searchByName": "Search By Name", + "users": "Users", + "name": "Name", + "email": "Email", + "roles_userType": "Role/User-Type", + "joined_organizations": "Joined Organizations", + "blocked_organizations": "Blocked Organizations", + "orgJoinedBy": "Organizations Joined By", + "orgThatBlocked": "Organizations That Blocked", + "endOfResults": "End of results", + "hasNotJoinedAnyOrg": "has not joined any organization", + "isNotBlockedByAnyOrg": "is not blocked by any organization", + "searchByOrgName": "Search By Organization Name", + "view": "View", + "admin": "ADMIN", + "superAdmin": "SUPERADMIN", + "user": "USER", + "enterName": "Enter Name", + "loadingUsers": "Loading Users...", + "noUserFound": "No User Found", + "sort": "Sort", + "Newest": "Newest First", + "Oldest": "Oldest First", + "filter": "Filter", + "noOrgError": "Organizations not found, please create an organization through dashboard", + "roleUpdated": "Role Updated.", + "noResultsFoundFor": "No results found for ", + "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too." + }, + "requests": { + "title": "Talawa Requests", + "searchByName": "Search By Name", + "requests": "Requests", + "name": "Name", + "email": "Email", + "accept": "Accept", + "reject": "Reject", + "enterName": "Enter Name", + "endOfResults": "End of results", + "loadingRequests": "Loading Requests...", + "noRequestFound": "No Request Found", + "sort": "Sort", + "filter": "Filter", + "noOrgError": "Organizations not found, please create an organization through dashboard", + "userApproved": "User Approved", + "userRejected": "User Rejected", + "noResultsFoundFor": "No results found for ", + "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too." + }, + "dashboard": { + "title": "Dashboard", + "location": "Location", + "about": "About", + "deleteThisOrganization": "Delete This Organization", + "statistics": "Statistics", + "members": "Members", + "admins": "Admins", + "posts": "Posts", + "events": "Events", + "blockedUsers": "Blocked Users", + "requests": "Requests", + "viewAll": "View All", + "upcomingEvents": "Upcoming Events", + "noUpcomingEvents": "No Upcoming Events", + "latestPosts": "Latest Posts", + "noPostsPresent": "No Posts Present", + "membershipRequests": "Membership requests", + "noMembershipRequests": "No Membership requests present", + "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too." + }, + "organizationPeople": { + "title": "Talawa Members", + "filterByName": "Filter by Name", + "filterByLocation": "Filter by Location", + "filterByEvent": "Filter by Event", + "members": "Members", + "admins": "Admins", + "users": "Users", + "searchName": "Enter Name", + "searchevent": "Enter Event", + "searchFirstName": "Enter First Name", + "searchLastName": "Enter Last Name" + }, + "userListCard": { + "joined": "Joined", + "addAdmin": "Add Admin", + "addedAsAdmin": "User is added as admin.", + "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too." + }, + "orgAdminListCard": { + "joined": "Joined", + "remove": "Remove", + "removeAdmin": "Remove Admin", + "removeAdminMsg": "Do you want to remove this admin?", + "no": "No", + "yes": "Yes", + "adminRemoved": "The admin is removed.", + "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too." + }, + "orgPeopleListCard": { + "joined": "Joined", + "remove": "Remove", + "removeMember": "Remove Member", + "removeMemberMsg": "Do you want to remove this member?", + "no": "No", + "yes": "Yes", + "memberRemoved": "The Member is removed", + "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too." + }, + "organizationEvents": { + "title": "Talawa Events", + "filterByTitle": "Filter by Title", + "filterByLocation": "Filter by Location", + "filterByDescription": "Filter by Description", + "events": "Events", + "addEvent": "Add Event", + "eventDetails": "Event Details", + "eventTitle": "Title", + "description": "Description", + "location": "Location", + "startDate": "Start Date", + "endDate": "End Date", + "startTime": "Start Time", + "endTime": "End Time", + "allDay": "All Day", + "recurringEvent": "Recurring Event", + "isPublic": "Is Public", + "isRegistrable": "Is Registrable", + "createEvent": "Create Event", + "enterFilter": "Enter Filter", + "enterTitle": "Enter Title", + "enterDescrip": "Enter Description", + "eventLocation": "Enter Location", + "eventCreated": "Congratulations! The Event is created.", + "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too." + }, + "eventListCard": { + "location": "Location", + "on": "On", + "end": "End", + "deleteEvent": "Delete Event", + "deleteEventMsg": "Do you want to remove this event?", + "no": "No", + "yes": "Yes", + "editEvent": "Edit Event", + "eventTitle": "Title", + "description": "Description", + "startTime": "Start Time", + "endTime": "End Time", + "allDay": "All Day", + "recurringEvent": "Recurring Event", + "isPublic": "Is Public", + "isRegistrable": "Is Registrable", + "close": "Close", + "updatePost": "Update Post", + "eventDetails": "Event Details", + "eventDeleted": "Event deleted successfully.", + "eventUpdated": "Event updated successfully.", + "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too." + }, + "orgPost": { + "title": "Talawa Posts", + "searchPost": "Search Post", + "posts": "Posts", + "createPost": "Create Post", + "postDetails": "Post Details", + "postTitle1": "Write title of the post", + "postTitle": "Title", + "information": "Information", + "information1": "Write information of the post", + "image": "Post Image", + "video": "Post Video", + "addPost": "Add Post", + "searchTitle": "Search By Title", + "searchText": "Search By Text", + "ptitle": "Post Title", + "postDes": "What do you to talk about?", + "Title": "Title", + "Text": "Text", + "cancel": "Cancel", + "searchBy": "Search By", + "Oldest": "Oldest First", + "Latest": "Latest First", + "sortPost": "Sort Post", + "tag": " Your browser does not support the video tag" + }, + "postNotFound": { + "post": "Post", + "not found!": "Not Found!", + "organization": "Organization", + "post not found!": "Post Not Found!", + "organization not found!": "Organization Not Found!" + }, + "userNotFound": { + "user": "User", + "not found!": "Not Found!", + "roles": "Roles", + "user not found!": "User Not Found!", + "member not found!": "Member Not Found!", + "admin not found!": "Admin Not Found!", + "roles not found!": "Roles Not Found!" + }, + "orgPostCard": { + "author": "Author", + "imageURL": "Image URL", + "videoURL": "Video URL", + "edit": "Edit Post", + "deletePost": "Delete Post", + "deletePostMsg": "Do you want to remove this post?", + "no": "No", + "yes": "Yes", + "editPost": "Edit Post", + "postTitle": "Title", + "information": "Information", + "image": "Image", + "video": "Video", + "close": "Close", + "updatePost": "Update Post", + "postDeleted": "Post deleted successfully.", + "postUpdated": "Post Updated successfully.", + "tag": " Your browser does not support the video tag", + "pin": "Pin Post", + "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too." + }, + "blockUnblockUser": { + "title": "Talawa Block/Unblock User", + "pageName": "Block/Unblock", + "searchByName": "Search By Name", + "listOfUsers": "List of Users who spammed", + "name": "Name", + "email": "Email", + "block_unblock": "Block/Unblock", + "unblock": "UnBlock", + "block": "Block", + "orgName": "Enter Name", + "blockedSuccessfully": "User blocked successfully", + "Un-BlockedSuccessfully": "User Un-Blocked successfully", + "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too.", + "allMembers": "All Members", + "blockedUsers": "Blocked Users", + "searchByFirstName": "Search By First Name", + "searchByLastName": "Search By Last Name", + "noResultsFoundFor": "No results found for", + "noSpammerFound": "No spammer found" + }, + "forgotPassword": { + "title": "Talawa Forgot Password", + "forgotPassword": "Forgot Password", + "registeredEmail": "Registered Email", + "getOtp": "Get OTP", + "enterOtp": "Enter OTP", + "enterNewPassword": "Enter New Password", + "cofirmNewPassword": "Confirm New Password", + "changePassword": "Change Password", + "backToLogin": "Back to Login", + "userOtp": "e.g. 12345", + "password": "Password", + "emailNotRegistered": "Email is not registered.", + "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too.", + "errorSendingMail": "Error in sending mail.", + "passwordMismatches": "Password and Confirm password mismatches.", + "passwordChanges": "Password changes successfully.", + "OTPsent": "OTP is sent to your registered email." + }, + "pageNotFound": { + "title": "404 Not Found", + "talawaAdmin": "Talawa Admin", + "404": "404", + "notFoundMsg": "Oops! The Page you requested was not found!", + "backToHome": "Back to Home" + }, + "orgContribution": { + "title": "Talawa Contributions", + "filterByName": "Filter by Name", + "filterByTransId": "Filter by Trans. ID", + "recentStats": "Recent Stats", + "contribution": "Contribution", + "orgname": "Enter Name", + "searchtransaction": "Enter Transaction ID" + }, + "contriStats": { + "recentContribution": "Recent Contribution", + "highestContribution": "Highest Contribution", + "totalContribution": "Total Contribution" + }, + "orgContriCards": { + "date": "Date", + "transactionId": "Transaction ID", + "amount": "Amount" + }, + "orgSettings": { + "title": "Talawa Setting", + "pageName": "Settings", + "updateOrganization": "Update Organization", + "seeRequest": "See Request", + "settings": "Settings", + "noData": "No data", + "otherSettings": "Other Settings", + "changeLanguage": "Change Language" + }, + "deleteOrg": { + "deleteOrganization": "Delete Organization", + "deleteSampleOrganization": "Delete Sample Organization", + "deleteMsg": "Do you want to delete this organization?", + "cancel": "Cancel", + "confirmDelete": "Confirm Delete", + "longDelOrgMsg": "By clicking on Delete Organization button the organization will be permanently deleted along with its events, tags and all related data." + }, + "userUpdate": { + "firstName": "First Name", + "lastName": "Last Name", + "email": "Email", + "password": "Password", + "appLanguageCode": "Default Language", + "userType": "User Type", + "admin": "Admin", + "superAdmin": "Superadmin", + "displayImage": "Display Image", + "saveChanges": "Save Changes", + "cancel": "Cancel" + }, + "userPasswordUpdate": { + "previousPassword": "Previous Password", + "newPassword": "New Password", + "confirmNewPassword": "Confirm New Password", + "saveChanges": "Save Changes", + "cancel": "Cancel" + }, + "orgDelete": { + "deleteOrg": "Delete Org" + }, + "membershipRequest": { + "joined": "Joined", + "accept": "Accept", + "reject": "Reject", + "memberAdded": "it is accepted", + "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too." + }, + "orgUpdate": { + "name": "Name", + "description": "Description", + "location": "Location", + "displayImage": "Display Image", + "isPublic": "Public", + "isVisibleInSearch": "Visible in Search", + "saveChanges": "Save Changes", + "enterNameOrganization": "Enter Organization Name", + "successfulUpdated": "Organization updated successfully", + "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too." + }, + "addOnRegister": { + "addNew": "Add New", + "addPlugin": "Add Plugin", + "pluginName": "Plugin Name", + "creatorName": "Creator Name", + "pluginDesc": "Plugin Description", + "close": "Close", + "register": "Register", + "pName": "Ex: Donations", + "cName": "Ex: john Doe", + "pDesc": "This Plugin enables UI for" + }, + "addOnStore": { + "title": "Add On Store", + "searchName": "Ex: Donations", + "enable": "Enabled", + "disable": "Disabled", + "pHeading": "Plugins", + "install": "Installed", + "available": "Available", + "pMessage": "Plugin does not exists", + "filter": "Filters", + "search": "Search" + }, + "addOnEntry": { + "enable": "Enabled", + "install": "Install", + "uninstall": "Uninstall", + "uninstallMsg": "This feature is now removed from your organization", + "installMsg": "This feature is now enabled in your organization" + }, + "memberDetail": { + "title": "User Details", + "addAdmin": "Add Admin", + "organizations": "Organizations", + "events": "Events", + "role": "Role", + "email": "Email", + "createdOn": "Created on", + "main": "Main", + "firstName": "First name", + "lastName": "Last name", + "memberOfOrganization": "Member of Organization", + "language": "Language", + "adminApproved": "Admin approved", + "pluginCreationAllowed": "Plugin creation allowed", + "joined": "Joined", + "created": "Created", + "adminForOrganizations": "Admin for organizations", + "membershipRequests": "Membership requests", + "adminForEvents": "Admin for events", + "addedAsAdmin": "User is added as admin.", + "talawaApiUnavailable": "Talawa-API service is unavailable. Kindly check your network connection and wait for a while." + }, + "userLogin": { + "login": "Login", + "forgotPassword": "Forgot Password?", + "loginIntoYourAccount": "Login into your account", + "emailAddress": "Email Address", + "enterEmail": "Enter your email address", + "password": "Password", + "enterPassword": "Enter your password", + "register": "Register", + "invalidDetailsMessage": "Please enter a valid email and password.", + "notAuthorised": "Sorry! you are not Authorised!", + "invalidCredentials": "Entered credentials are incorrect. Please enter valid credentials.", + "talawaApiUnavailable": "Talawa-API service is unavailable. Kindly check your network connection and wait for a while." + }, + "userRegister": { + "register": "Register", + "firstName": "First Name", + "enterFirstName": "Enter your first name", + "lastName": "Last Name", + "enterLastName": "Enter your last name", + "emailAddress": "Email Address", + "enterEmail": "Enter your email address", + "password": "Password", + "enterPassword": "Enter your password", + "confirmPassword": "Confirm Password", + "enterConfirmPassword": "Enter your password to confirm", + "alreadyhaveAnAccount": "Already have an account?", + "login": "Login", + "afterRegister": "Successfully registered. Please wait for admin to approve your request.", + "passwordNotMatch": "Password doesn't match. Confirm Password and try again.", + "invalidDetailsMessage": "Please enter valid details.", + "talawaApiUnavailable": "Talawa-API service is unavailable. Kindly check your network connection and wait for a while." + }, + "userNavbar": { + "talawa": "Talawa", + "home": "Home", + "people": "People", + "events": "Events", + "chat": "Chat", + "donate": "Donate", + "myTasks": "My Tasks", + "settings": "Settings", + "language": "Language", + "logout": "Logout", + "close": "Close" + }, + "userOrganizations": { + "allOrganizations": "All Organizations", + "joinedOrganizations": "Joined Organizations", + "createdOrganizations": "Created Organizations", + "search": "Search", + "nothingToShow": "Nothing to show here.", + "selectOrganization": "Select Organization" + }, + "userSidebar": { + "yourOrganizations": "Your Organizations", + "noOrganizations": "You haven't joined any organization yet.", + "viewAll": "View all" + }, + "organizationSidebar": { + "viewAll": "View all", + "events": "Events", + "members": "Members", + "noEvents": "No Events to show", + "noMembers": "No Members to show" + }, + "postCard": { + "likes": "Likes", + "comments": "Comments" + }, + "home": { + "feed": "Feed", + "pinnedPosts": "View Pinned Posts", + "somethingOnYourMind": "Something on your mind?" + }, + "settings": { + "profileSettings": "Profile Settings", + "firstName": "First Name", + "lastName": "Last Name", + "emailAddress": "Email Address", + "updateImage": "Update Image", + "save": "Save" + }, + "donate": { + "donateTo": "Donate to", + "amount": "Amount", + "yourPreviousDonations": "Your Previous Donations", + "donate": "Donate", + "nothingToShow": "Nothing to show here." + }, + "userEvents": { + "nothingToShow": "Nothing to show here.", + "search": "Search", + "createEvent": "Create Event", + "eventTitle": "Event Title", + "eventDescription": "Event Description", + "eventLocation": "Event Location", + "startDate": "Select Start Date", + "endDate": "Select End Date", + "publicEvent": "Public Event", + "registerable": "Registerable", + "recurring": "Recurring", + "startTime": "Start Time", + "endTime": "End Time", + "cancel": "Cancel", + "create": "Create", + "listView": "List View", + "calendarView": "Calendar View", + "allDay": "All Day", + "eventCreated": "Event created and posted successfully." + }, + "userEventCard": { + "location": "Location", + "starts": "Starts", + "ends": "Ends", + "creator": "Creator", + "alreadyRegistered": "Already registered", + "register": "Register" + }, + "userTasks": { + "yourAssignedTasks": "Your assigned tasks", + "nothingToShow": "Nothing to show here." + }, + "userTaskCard": { + "description": "Description", + "deadline": "Deadline", + "created": "Created", + "assignees": "Assignees", + "completed": "Completed", + "incomplete": "Incomplete", + "taskCompleted": "The task has been completed", + "taskNotCompleted": "The task has not been completed yet", + "event": "Event", + "organization": "Organization" + }, + "advertisement": { + "title": "Advertisements", + "pHeading": "Manage Ads", + "activeAds": "Active Campaigns", + "archievedAds": "Completed Campaigns", + "pMessage": "Ads not present for this campaign.", + "delete": "Delete", + "Rname": "Enter name of Advertisement", + "Rtype": "Select type of Advertisement", + "Rlink": "Provide a link for content to be displayed", + "RstartDate": "Select Start Date", + "RendDate": "Select End Date", + "RClose": "Close the window", + "addNew": "Create new advertisement", + "EXname": "Ex. Cookie Shop", + "EXlink": "Ex. http://yourwebsite.com/photo", + "register": "Create Advertisement", + "close": "Close " + }, + "userChat": { + "chat": "Chat", + "search": "Search", + "contacts": "Contacts" + }, + "userChatRoom": { + "selectContact": "Select a contact to start conversation", + "sendMessage": "Send Message" + } +} diff --git a/public/locales/fr.json b/public/locales/fr.json new file mode 100644 index 0000000000..818ffd6fcd --- /dev/null +++ b/public/locales/fr.json @@ -0,0 +1,668 @@ +{ + "loginPage": { + "title": "Administrateur Talawa", + "talawa_portal": "Portail D'Administrateur Talawa", + "fromPalisadoes": "Une application open source par les volontaires de la Fondation Palissades", + "login": "Connexion", + "register": "S'inscrire", + "firstName": "Prénom", + "lastName": "Nom de famille", + "email": "E-mail", + "password": "Mot de passe", + "atleast_8_char_long": "Au moins 8 caractères", + "Password_and_Confirm_password_mismatches.": "Le mot de passe et la confirmation du mot de passe ne correspondent pas.", + "confirmPassword": "Confirmez le mot de passe", + "forgotPassword": "Mot de passe oublié ?", + "enterEmail": "entrez l'e-mail", + "enterPassword": "Entrer le mot de passe", + "doNotOwnAnAccount": "Vous n'avez pas de compte ?", + "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau.", + "captchaError": "Erreur de captcha !", + "Please_check_the_captcha": "Veuillez vérifier le captcha.", + "Something_went_wrong": "Quelque chose s'est mal passé, veuillez réessayer plus tard.", + "passwordMismatches": "Le mot de passe et la confirmation du mot de passe ne correspondent pas.", + "fillCorrectly": "Remplissez tous les détails correctement.", + "notAuthorised": "Désolé ! vous n'êtes pas autorisé !", + "notFound": "Utilisateur introuvable !", + "successfullyRegistered": "Enregistré avec succès. Veuillez patienter jusqu'à ce que vous soyez approuvé.", + "login_to_admin_portal": "Connexion à l'administration du portail", + "OR": "OU" + }, + "latestEvents": { + "eventCardTitle": "Événements à venir", + "eventCardSeeAll": "Voir Tout", + "noEvents": "Aucun événement à venir" + }, + "listNavbar": { + "talawa_portal": "Portail D'Administrateur Talawa", + "roles": "Les rôles", + "requests": "Demandes", + "logout": "Se déconnecter" + }, + "leftDrawer": { + "talawaAdminPortal": "Portail d'administration Talawa", + "menu": "Menu", + "organizations": "Organisations", + "requests": "Demandes", + "users": "Utilisateurs", + "logout": "Déconnexion" + }, + "leftDrawerOrg": { + "talawaAdminPortal": "Portail d'administration Talawa", + "menu": "Menu", + "talawa_portal": "Portail D'Administrateur Talawa", + "Dashboard": "Tableau de bord", + "People": "Personnes", + "Events": "Événements", + "Contributions": "Contributions", + "Posts": "Des postes", + "Block/Unblock": "Bloquer/Débloquer", + "Plugins": "Plugins", + "Plugin Store": "Magasin de plugins", + "allOrganizations": "Toutes les organisations", + "yourOrganization": "Votre organisation", + "notification": "Notification", + "settings": "Réglages", + "language": "Langue", + "logout": "Se déconnecter", + "notifications": "Notifications", + "spamsThe": "spam le", + "group": "groupe", + "noNotifications": "Aucune notification", + "close": "Proche" + }, + "orgList": { + "title": "Organisations Talawa", + "you": "Tu", + "name": "Nom", + "designation": "La désignation", + "email": "E-mail", + "searchByName": "Rechercher par nom", + "organizations": "Organisations", + "createOrganization": "Créer une organisation", + "createSampleOrganization": "Créer une organisation d'exemple", + "description": "La description", + "location": "Emplacement", + "isPublic": "Est publique", + "visibleInSearch": "Visible dans la recherche", + "displayImage": "Afficher l'image", + "enterName": "Entrez le nom", + "sort": "Trier", + "filter": "Filtre", + "cancel": "Annuler", + "endOfResults": "Fin des résultats", + "noOrgErrorTitle": "Organisations non trouvées", + "sampleOrgDuplicate": "Seule une organisation d'exemple est autorisée.", + "noOrgErrorDescription": "Veuillez créer une organisation via le tableau de bord", + "noResultsFoundFor": "Aucun résultat trouvé pour ", + "OR": "OU", + "sampleOrgSuccess": "Organisation d'exemple créée avec succès" + }, + "orgListCard": { + "admins": "Administrateurs", + "members": "Membres", + "manage": "Faire en sorte", + "sampleOrganization": "Organisation d'exemple" + }, + + "paginationList": { + "rowsPerPage": "lignes par page", + "all": "Tout" + }, + "users": { + "title": "Rôles Talawa", + "searchByName": "Recherche par nom", + "users": "Utilisateurs", + "name": "Nom", + "email": "E-mail", + "roles_userType": "Rôle/Type d'utilisateur", + "joined_organizations": "Organisations rejointes", + "blocked_organizations": "Organisations bloquées", + "endOfResults": "Fin des résultats", + "orgJoinedBy": "Organisation rejointe par", + "orgThatBlocked": "Organisation bloquée par", + "hasNotJoinedAnyOrg": "n'a rejoint aucune organisation", + "isNotBlockedByAnyOrg": "n'est bloqué par aucune organisation", + "searchByOrgName": "Rechercher par nom d'organisation", + "view": "Vue", + "admin": "ADMIN", + "superAdmin": "SUPERADMIN", + "user": "UTILISATEUR", + "enterName": "Entrez le nom", + "loadingUsers": "Chargement des utilisateurs...", + "noUserFound": "Aucun utilisateur trouvé", + "sort": "Trier", + "Oldest": "Les plus anciennes d'abord", + "Newest": "Les plus récentes d'abord", + "filter": "Filtre", + "roleUpdated": "Rôle mis à jour.", + "noResultsFoundFor": "Aucun résultat trouvé pour ", + "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau." + }, + "requests": { + "title": "Demandes Talawa", + "searchByName": "Recherche par nom", + "requests": "Demandes", + "name": "Nom", + "email": "E-mail", + "accept": "Accepter", + "reject": "Rejeter", + "enterName": "Entrez le nom", + "endOfResults": "Fin des résultats", + "loadingRequests": "Chargement des demandes...", + "noRequestFound": "Aucune demande trouvée", + "sort": "Trier", + "filter": "Filtre", + "userApproved": "Approuvé par l'utilisateur", + "userRejected": "Utilisateur rejeté", + "noResultsFoundFor": "Aucun résultat trouvé pour ", + "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau." + }, + "dashboard": { + "title": "Tableau de bord", + "location": "Emplacement", + "about": "À propos de", + "deleteThisOrganization": "Supprimer cette organisation", + "statistics": "Statistiques", + "members": "Membres", + "admins": "Administrateurs", + "posts": "Des postes", + "events": "Événements", + "blockedUsers": "Utilisateurs bloqués", + "requests": "Demandes", + "viewAll": "Voir tout", + "upcomingEvents": "Événements à venir", + "noUpcomingEvents": "Aucun événement à venir", + "latestPosts": "Derniers messages", + "noPostsPresent": "Aucune publication présente", + "membershipRequests": "Demandes d'adhésion", + "noMembershipRequests": "Aucune demande d'adhésion", + "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau." + }, + "organizationPeople": { + "title": "Membres Talawa", + "filterByName": "Filtrer par nom", + "filterByLocation": "Filtrer par lieu", + "filterByEvent": "Filtrer par événement", + "members": "Membres", + "admins": "Administrateurs", + "users": "Utilisateurs", + "searchName": "Entrez le nom", + "searchevent": "Entrez l'événement", + "searchFirstName": "Entrez votre prénom", + "searchLastName": "Entrer le nom de famille" + }, + "userListCard": { + "joined": "Inscrit", + "addAdmin": "Ajouter un administrateur", + "addedAsAdmin": "L'utilisateur est ajouté en tant qu'administrateur.", + "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau." + }, + "orgAdminListCard": { + "joined": "Inscrit", + "remove": "Retirer", + "removeAdmin": "Supprimer l'administrateur", + "removeAdminMsg": "Voulez-vous supprimer cet administrateur ?", + "no": "Non", + "yes": "Oui", + "adminRemoved": "L'administrateur est supprimé.", + "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau." + }, + "orgPeopleListCard": { + "joined": "Inscrit", + "remove": "Retirer", + "removeMember": "Supprimer le membre", + "removeMemberMsg": "Voulez-vous supprimer ce membre ?", + "no": "Non", + "yes": "Oui", + "memberRemoved": "Le membre est supprimé", + "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau." + }, + "organizationEvents": { + "title": "Événements Talawa", + "filterByTitle": "Filtrer par titre", + "filterByLocation": "Filtrer par l'emplacement", + "filterByDescription": "Filtrer par Description", + "events": "Événements", + "addEvent": "Ajouter un évènement", + "eventDetails": "Détails de l'évènement", + "eventTitle": "Titre", + "description": "La description", + "location": "Emplacement", + "startDate": "Date de début", + "endDate": "Date de fin", + "startTime": "Heure de début", + "endTime": "Heure de fin", + "allDay": "Toute la journée", + "recurringEvent": "Événement récurrent", + "isPublic": "Est publique", + "isRegistrable": "Est enregistrable", + "createEvent": "Créer un évènement", + "enterFilter": "Entrez le filtre", + "enterTitle": "Entrez le titre", + "enterDescrip": "Entrez la description", + "eventLocation": "Entrez l'emplacement", + "eventCreated": "Toutes nos félicitations! L'événement est créé.", + "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau." + }, + "eventListCard": { + "location": "Emplacement", + "on": "Sur", + "end": "Fin", + "deleteEvent": "Supprimer l'événement", + "deleteEventMsg": "Voulez-vous supprimer cet événement ?", + "no": "Non", + "yes": "Oui", + "editEvent": "Modifier l'événement", + "eventTitle": "Titre", + "description": "La description", + "startTime": "Heure de début", + "endTime": "Heure de fin", + "allDay": "Toute la journée", + "recurringEvent": "Événement récurrent", + "isPublic": "Est publique", + "isRegistrable": "Est enregistrable", + "close": "Proche", + "updatePost": "Mettre à jour le message", + "eventDetails": "Détails de l'évènement", + "eventDeleted": "Événement supprimé avec succès.", + "eventUpdated": "Événement mis à jour avec succès.", + "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau." + }, + "orgPost": { + "title": "Talawa Publications", + "searchPost": "Rechercher une publication", + "posts": "Publications", + "createPost": "Créer une publication", + "postDetails": "Détails de la publication", + "postTitle1": "Écrire le titre de la publication", + "postTitle": "Titre", + "information": "Informations", + "information1": "Écrire les informations de la publication", + "image": "Image de la publication", + "video": "Vidéo de la publication", + "addPost": "Ajouter une publication", + "searchTitle": "Rechercher par titre", + "searchText": "Rechercher par texte", + "ptitle": "Titre de la publication", + "postDes": "De quoi voulez-vous parler?", + "Title": "Titre", + "Text": "Texte", + "cancel": "Annuler", + "searchBy": "Rechercher par", + "Oldest": "Les plus anciennes d'abord", + "Latest": "Les plus récentes d'abord", + "sortPost": "Trier les publications", + "tag": "Votre navigateur ne prend pas en charge la balise vidéo" + }, + "postNotFound": { + "post": "Poste", + "not found!": "Pas Trouvé!", + "organization": "Organization", + "post not found!": "Poste Pas Trouvé!", + "organization not found!": "Organization Pas Trouvé!" + }, + "userNotFound": { + "user": "utilisateur", + "not found!": "pas trouvé!", + "roles": "les rôles", + "user not found!": "utilisateur non trouvé!", + "member not found!": "Membre introuvable!", + "admin not found!": "Administrateur introuvable!", + "roles not found!": "utilisateur non trouvé!" + }, + "orgPostCard": { + "author": "Auteur", + "imageURL": "URL de l'image", + "videoURL": "URL de la vidéo", + "edit": "Modifier la publication", + "deletePost": "Supprimer la publication", + "deletePostMsg": "Voulez-vous supprimer cette publication ?", + "no": "Non", + "yes": "Oui", + "editPost": "Modifier la publication", + "postTitle": "Titre", + "information": "Informations", + "image": "Image", + "video": "Vidéo", + "close": "Fermer", + "pin": "Épingler la publication", + "updatePost": "Mettre à jour la publication", + "postDeleted": "Publication supprimée avec succès.", + "postUpdated": "Publication mise à jour avec succès.", + "tag": "Votre navigateur ne prend pas en charge la balise vidéo", + "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau." + }, + "blockUnblockUser": { + "title": "Talawa Bloquer/Débloquer l'utilisateur", + "pageName": "Bloquer/Débloquer'", + "searchByName": "Recherche par nom", + "listOfUsers": "Liste des utilisateurs qui ont spammé", + "name": "Nom", + "email": "E-mail", + "block_unblock": "Bloquer/Débloquer", + "unblock": "Débloquer", + "block": "Bloquer", + "orgName": "Entrez le nom", + "blockedSuccessfully": "Utilisateur bloqué avec succès", + "Un-BlockedSuccessfully": "Utilisateur débloqué avec succès", + "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau.", + "allMembers": "Tous les membres", + "blockedUsers": "Utilisateurs bloqués", + "searchByFirstName": "Rechercher par prénom", + "searchByLastName": "Rechercher par nom de famille", + "noResultsFoundFor": "Aucun résultat trouvé pour ", + "noSpammerFound": "Aucun spammeur trouvé" + }, + "forgotPassword": { + "title": "Mot de passe oublié Talawa", + "forgotPassword": "Mot de passe oublié", + "registeredEmail": "Email enregistré", + "getOtp": "Obtenir OTP", + "enterOtp": "Entrez OTP", + "enterNewPassword": "Entrez un nouveau mot de passe", + "cofirmNewPassword": "Confirmer le nouveau mot de passe", + "changePassword": "Changer le mot de passe", + "backToLogin": "Retour à la connexion", + "userOtp": "par exemple. 12345", + "password": "Mot de passe", + "emailNotRegistered": "L'e-mail n'est pas enregistré.", + "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau.", + "errorSendingMail": "Erreur lors de l'envoi du courrier.", + "passwordMismatches": "Le mot de passe et la confirmation du mot de passe ne correspondent pas.", + "passwordChanges": "Mot de passe modifié avec succès.", + "OTPsent": "OTP est envoyé à votre adresse e-mail enregistrée." + }, + "pageNotFound": { + "title": "404 introuvable", + "talawaAdmin": "Administrateur Talawa", + "404": "404", + "notFoundMsg": "Oups ! La page demandée est introuvable !", + "backToHome": "De retour à la maison" + }, + "orgContribution": { + "title": "Cotisations Talawa", + "filterByName": "Filtrer par nom", + "filterByTransId": "Filtrer par Trans. ID", + "recentStats": "Statistiques récentes", + "contribution": "Contribution", + "orgname": "Entrez le nom", + "searchtransaction": "Saisir l'identifiant de la transaction" + }, + "contriStats": { + "recentContribution": "Contribution récente", + "highestContribution": "Contribution la plus élevée", + "totalContribution": "Contribution totale" + }, + "orgContriCards": { + "date": "Date", + "transactionId": "Identifiant de transaction", + "amount": "Montant" + }, + "orgSettings": { + "title": "Paramètre Talawa", + "pageName": "Paramètres", + "updateYourDetails": "Mettre à jour vos informations", + "updateYourPassword": "Mettez à jour votre mot de passe", + "updateOrganization": "Mettre à jour l'organisation", + "seeRequest": "Voir demande", + "settings": "Réglages", + "noData": "Pas de données", + "otherSettings": "Autres paramètres", + "changeLanguage": "Changer la langue" + }, + "deleteOrg": { + "deleteOrganization": "Supprimer l'organisation", + "deleteSampleOrganization": "Supprimer l'organisation d'exemple", + "deleteMsg": "Voulez-vous supprimer cette organisation ?", + "cancel": "Annuler", + "confirmDelete": "Confirmer la suppression", + "longDelOrgMsg": "En cliquant sur le bouton Supprimer l'organisation, l'organisation sera définitivement supprimée ainsi que ses événements, balises et toutes les données associées." + }, + "userUpdate": { + "firstName": "Prénom", + "lastName": "Nom de famille", + "email": "E-mail", + "password": "Mot de passe", + "appLanguageCode": "Langue par défaut", + "userType": "Type d'utilisateur", + "admin": "Administrateur", + "superAdmin": "Super administrateur", + "displayImage": "Afficher l'image", + "saveChanges": "Sauvegarder les modifications", + "cancel": "Annuler" + }, + "userPasswordUpdate": { + "previousPassword": "mot de passe précédent", + "newPassword": "Nouveau mot de passe", + "confirmNewPassword": "Confirmer le nouveau mot de passe", + "saveChanges": "Sauvegarder les modifications", + "cancel": "Annuler" + }, + "orgDelete": { + "deleteOrg": "Supprimer l'organisation" + }, + "membershipRequest": { + "joined": "Inscrit", + "accept": "Accepter", + "reject": "Rejeter", + "memberAdded": "c'est accepté", + "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau." + }, + "orgUpdate": { + "name": "Nom", + "description": "La description", + "location": "emplacement", + "displayImage": "Afficher l'image", + "isPublic": "Public", + "isVisibleInSearch": "Visible dans la recherche", + "saveChanges": "Sauvegarder les modifications", + "enterNameOrganization": "Entrez le nom de l'organisation", + "successfulUpdated": "Mise à jour réussie", + "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau." + }, + "addOnRegister": { + "addNew": "Ajouter nouveau", + "addPlugin": "Ajouter un plug-in", + "pluginName": "Nom du plug-in", + "creatorName": "Creator Name", + "pluginDesc": "Description du plug-in", + "close": "Fermer", + "register": "Enregistrer", + "pName": "Ex : Dons", + "cName": "Ex: Jean Doe", + "pDesc": "Ce plugin active l'interface utilisateur pour" + }, + "addOnStore": { + "title": "Add-On Store", + "searchName": "Ex:Des dons ", + "enable": "Activé", + "disable": "Désactivé", + "pHeading": "Plugins", + "install": "Installée", + "available": "Disponible", + "pMessage": "Le plugin n'existe pas", + "filter": "Filtres", + "search": "recherche" + }, + "addOnEntry": { + "enable": "Activé", + "install": "Installer", + "uninstall": "désinstaller" + }, + "memberDetail": { + "title": "Détails de l'utilisateur", + "addAdmin": "Ajouter un administrateur", + "organizations": "Organisations", + "events": "Événements", + "role": "Rôle", + "email": "Email", + "createdOn": "Créé le", + "main": "Principal", + "firstName": "Prénom", + "lastName": "Nom de famille", + "memberOfOrganization": "Membre de l'organisation", + "language": "Langue", + "adminApproved": "Approuvé par l'administrateur", + "pluginCreationAllowed": "Autorisation de création de plugin", + "joined": "Rejoint", + "created": "Créé", + "adminForOrganizations": "Administrateur pour les organisations", + "membershipRequests": "Demandes d'adhésion", + "adminForEvents": "Administrateur pour les événements", + "addedAsAdmin": "L'utilisateur est ajouté en tant qu'administrateur.", + "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Veuillez vérifier votre connexion réseau et attendre un moment." + }, + "userLogin": { + "login": "Connexion", + "forgotPassword": "Mot de passe oublié?", + "loginIntoYourAccount": "Connectez-vous à votre compte", + "emailAddress": "Email Address", + "enterEmail": "Entrez votre adresse email", + "password": "Mot de passe", + "enterPassword": "Tapez votre mot de passe", + "register": "Enregistrer", + "invalidDetailsMessage": "Veuillez saisir un e-mail et un mot de passe valides.", + "notAuthorised": "Désolé! vous n'êtes pas autorisé !", + "invalidCredentials": "Les informations d'identification saisies sont incorrectes. Veuillez entrer des informations d'identification valides.", + "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Veuillez vérifier votre connexion réseau et attendre un moment." + }, + "userRegister": { + "register": "Enregistrer", + "firstName": "Prénom", + "enterFirstName": "Entrez votre prénom", + "lastName": "Nom de famille", + "enterLastName": "Entrez votre nom de famille", + "emailAddress": "Email Address", + "enterEmail": "Entrez votre adresse email", + "password": "Mot de passe", + "enterPassword": "Tapez votre mot de passe", + "confirmPassword": "Confirmez le mot de passe", + "enterConfirmPassword": "Entrez votre mot de passe pour confirmer", + "alreadyhaveAnAccount": "Vous avez déjà un compte?", + "login": "Connexion", + "afterRegister": "Enregistré avec succès. Veuillez attendre que l'administrateur approuve votre demande.", + "passwordNotMatch": "Le mot de passe ne correspond pas. Confirmez le mot de passe et réessayez.", + "invalidDetailsMessage": "Veuillez entrer des détails valides.", + "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Veuillez vérifier votre connexion réseau et attendre un moment." + }, + "userNavbar": { + "talawa": "Talawa", + "home": "Maison", + "people": "Personnes", + "events": "Événements", + "chat": "Discuter", + "donate": "Donner", + "myTasks": "Mes tâches", + "settings": "Paramètres", + "language": "Langue", + "logout": "Se déconnecter", + "close": "Fermer" + }, + "userOrganizations": { + "allOrganizations": "Toutes les organisations", + "joinedOrganizations": "Organisations jointes", + "createdOrganizations": "Organisations créées", + "search": "Recherche", + "nothingToShow": "Rien à montrer ici.", + "selectOrganization": "Sélectionnez une organisation" + }, + "userSidebar": { + "yourOrganizations": "Vos organisations", + "noOrganizations": "Vous n'avez encore rejoint aucune organisation.", + "viewAll": "Voir tout" + }, + "organizationSidebar": { + "viewAll": "Voir tout", + "events": "Événements", + "members": "Membres", + "noEvents": "Aucun événement à afficher", + "noMembers": "Aucun membre à afficher" + }, + "postCard": { + "likes": "Aime", + "comments": "commentaires" + }, + "home": { + "feed": "Alimentation", + "pinnedPosts": "Afficher les publications épinglées", + "somethingOnYourMind": "Quelque chose dans votre esprit?" + }, + "settings": { + "profileSettings": "Paramètres de profil", + "firstName": "Prénom", + "lastName": "Nom de famille", + "emailAddress": "Adresse e-mail", + "updateImage": "Mettre à jour l'image", + "save": "Sauvegarder" + }, + "donate": { + "donateTo": "Faire un don à", + "amount": "Montante", + "yourPreviousDonations": "Vos dons précédents", + "donate": "Donner", + "nothingToShow": "Rien à montrer ici." + }, + "userEvents": { + "nothingToShow": "Rien à montrer ici.", + "search": "Recherche", + "createEvent": "Créer un évènement", + "eventTitle": "Titre de l'événement", + "eventDescription": "Description de l'évenement", + "eventLocation": "Lieu de l'événement", + "startDate": "Sélectionnez la date de début", + "endDate": "Sélectionnez la date de fin", + "publicEvent": "Évennement publique", + "registerable": "Enregistrable", + "recurring": "Récurrente", + "startTime": "Heure de début", + "endTime": "Heure de fin", + "cancel": "Annuler", + "create": "Créer", + "listView": "Vue en liste", + "calendarView": "Vue du calendrier", + "allDay": "Toute la journée", + "eventCreated": "Événement créé et publié avec succès." + }, + "userEventCard": { + "location": "Emplacement", + "starts": "Départs", + "ends": "Prend fin", + "creator": "Créatrice", + "alreadyRegistered": "Déjà enregistré", + "register": "Registre" + }, + "userTasks": { + "yourAssignedTasks": "Vos tâches assignées", + "nothingToShow": "Rien à montrer ici." + }, + "userTaskCard": { + "description": "Description", + "deadline": "Date limite", + "created": "Créé", + "assignees": "Destinataires", + "completed": "Complété", + "incomplete": "Incomplète", + "taskCompleted": "La tâche est terminée", + "taskNotCompleted": "La tâche n'est pas encore terminée", + "event": "Événement", + "organization": "Organisation" + }, + "advertisement": { + "title": "Publicités", + "pHeading": "Gérer les publicités", + "activeAds": "Campagnes actives", + "archievedAds": "Campagnes terminées", + "pMessage": "Aucune publicité n'est présente pour cette campagne.", + "delete": "Supprimer" + }, + "userChat": { + "chat": "Chat", + "search": "Recherche", + "contacts": "Contacts" + }, + "userChatRoom": { + "selectContact": "Sélectionnez un contact pour démarrer la conversation", + "sendMessage": "Envoyer le message" + } +} diff --git a/public/locales/hi.json b/public/locales/hi.json new file mode 100644 index 0000000000..fb9ae1ab23 --- /dev/null +++ b/public/locales/hi.json @@ -0,0 +1,668 @@ +{ + "loginPage": { + "title": "तलवा व्यवस्थापक", + "fromPalisadoes": "पलिसाडो के स्वयंसेवकों द्वारा एक खुला स्रोत अनुप्रयोग", + "talawa_portal": "तलावा प्रशासन पोर्टल", + "login": "लॉग इन करें", + "register": "पंजीकरण करवाना", + "firstName": "पहला नाम", + "lastName": "उपनाम", + "email": "ईमेल", + "password": "पासवर्ड", + "atleast_8_char_long": "कम से कम 8 कैरेक्टर लंबा", + "Password_and_Confirm_password_mismatches.": "पासवर्ड और पुष्टि पासवर्ड बेमेल।", + "confirmPassword": "पासवर्ड की पुष्टि कीजिये", + "forgotPassword": "पासवर्ड भूल गए ?", + "enterEmail": "ईमेल दर्ज करें", + "enterPassword": "पास वर्ड दर्ज करें", + "doNotOwnAnAccount": "क्या आपके पास खाता नहीं है?", + "talawaApiUnavailable": "तलावा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रही है? अपनी नेटवर्क कनेक्टिविटी की भी जाँच करें।", + "captchaError": "कैप्चा त्रुटि!", + "Please_check_the_captcha": "कृपया, कैप्चा जांचें।", + "Something_went_wrong": "कुछ गलत हुआ, कृपया कुछ समय बाद प्रयास करें।", + "passwordMismatches": "पासवर्ड और पुष्टि पासवर्ड मेल नहीं खाते।", + "fillCorrectly": "सभी विवरण सही ढंग से भरें।", + "notAuthorised": "क्षमा करें! आप अधिकृत नहीं हैं!", + "notFound": "उपयोगकर्ता नहीं मिला!", + "successfullyRegistered": "सफलतापूर्वक पंजीकृत। कृपया स्वीकृत होने तक प्रतीक्षा करें।", + "login_to_admin_portal": "एडमिन पोर्टल लॉगिन", + "OR": "या" + }, + "latestEvents": { + "eventCardTitle": "आगामी घटनाएँ", + "eventCardSeeAll": "सभी देखें", + "noEvents": "कोई आगामी घटनाएँ नहीं" + }, + "listNavbar": { + "talawa_portal": "तलावा प्रशासन पोर्टल", + "roles": "भूमिकाएँ", + "requests": "अनुरोध", + "logout": "लॉग आउट" + }, + "leftDrawer": { + "talawaAdminPortal": "तलावा व्यवस्थापक पोर्टल", + "menu": "मेन्यू", + "organizations": "संगठन", + "requests": "अनुरोध", + "users": "उपयोगकर्ता", + "logout": "लॉग आउट" + }, + "leftDrawerOrg": { + "talawaAdminPortal": "तलावा व्यवस्थापक पोर्टल", + "menu": "मेन्यू", + "talawa_portal": "तलावा प्रशासन पोर्टल", + "Dashboard": "डैशबोर्ड", + "People": "लोग", + "Events": "आयोजन", + "Contributions": "योगदान", + "Posts": "पोस्ट", + "Block/Unblock": "ब्लॉक/अनब्लॉक करें", + "Plugins": "प्लगइन्स", + "Plugin Store": "प्लगइन स्टोर", + "allOrganizations": "सभी संगठन", + "yourOrganization": "आपका संगठन", + "notification": "अधिसूचना", + "settings": "समायोजन", + "language": "भाषा", + "logout": "लॉग आउट", + "notifications": "सूचनाएं", + "spamsThe": "स्पैम द", + "group": "समूह", + "noNotifications": "कोई सूचनाएं नहीं", + "close": "बंद करना" + }, + "orgList": { + "title": "तलवा संगठन", + "you": "आप", + "name": "नाम", + "designation": "पद", + "email": "ईमेल", + "searchByName": "नाम से खोजें", + "organizations": "संगठन", + "createOrganization": "संगठन बनाएं", + "createSampleOrganization": " सैंपल संगठन बनाएं", + "description": "विवरण", + "location": "स्थान", + "isPublic": "सार्वजनिक है", + "visibleInSearch": "खोज में दृश्यमान", + "displayImage": "प्रदर्शन छवि", + "enterName": "नाम दर्ज करें", + "sort": "छांटें", + "filter": "फ़िल्टर", + "cancel": "रद्द करना", + "endOfResults": "परिणामों का अंत", + "noOrgErrorTitle": "संगठन नहीं मिला", + "sampleOrgDuplicate": "केवल एक नमूना संगठन को अनुमति दी गई", + "noOrgErrorDescription": "कृपया डैशबोर्ड के माध्यम से एक संगठन बनाएं", + "noResultsFoundFor": "के लिए कोई परिणाम नहीं मिला ", + "OR": "या", + "sampleOrgSuccess": "सैंपल संगठन सफलतापूर्वक बनाया गया" + }, + "orgListCard": { + "admins": "व्यवस्थापक", + "members": "सदस्य", + "manage": "प्रबंधित करना", + "sampleOrganization": "सैंपल संगठन" + }, + "paginationList": { + "rowsPerPage": "प्रति पृष्ठ पंक्तियाँ", + "all": "सभी" + }, + "users": { + "title": "तलावा भूमिकाएं", + "searchByName": "नाम से खोजें", + "users": "उपयोगकर्ता", + "name": "नाम", + "email": "ईमेल", + "roles_userType": "भूमिका/उपयोगकर्ता-प्रकार", + "joined_organizations": "संगठनों में शामिल हुए", + "blocked_organizations": "अवरोधित संगठन", + "endOfResults": "परिणामों का अंत", + "orgJoinedBy": "द्वारा शामिल हुए संगठन", + "orgThatBlocked": "जिन संगठनों ने अवरोधित किया", + "hasNotJoinedAnyOrg": "किसी भी संगठन में शामिल नहीं है", + "isNotBlockedByAnyOrg": "किसी भी संगठन द्वारा अवरोधित नहीं है", + "searchByOrgName": "संगठन के नाम से खोजें", + "view": "देखें", + "admin": "व्यवस्थापक", + "superAdmin": "सुपरएडमिन", + "user": "उपयोगकर्ता", + "enterName": "नाम दर्ज करें", + "loadingUsers": "उपयोगकर्ता लोड हो रहा है ...", + "noUserFound": "कोई उपयोगकर्ता नहीं मिला।", + "sort": "छांटें", + "Oldest": "सबसे पुराना पहले", + "Newest": "सबसे नवीनतम पहले", + "filter": "फ़िल्टर", + "roleUpdated": "भूमिका अपडेट की गई।", + "noResultsFoundFor": "के लिए कोई परिणाम नहीं मिला ", + "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।" + }, + "requests": { + "title": "तलवा अनुरोध", + "searchByName": "नाम से खोजें", + "requests": "अनुरोध", + "name": "नाम", + "email": "ईमेल", + "accept": "स्वीकार करना", + "reject": "अस्वीकार", + "enterName": "नाम दर्ज करें", + "endOfResults": "परिणामों का अंत", + "loadingRequests": "अनुरोध लोड हो रहा है ...", + "noRequestFound": "कोई अनुरोध नहीं मिला।", + "sort": "छांटें", + "filter": "फ़िल्टर", + "userApproved": "उपयोगकर्ता स्वीकृत", + "userRejected": "उपयोगकर्ता अस्वीकृत", + "noResultsFoundFor": "के लिए कोई परिणाम नहीं मिला ", + "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।" + }, + "dashboard": { + "title": "डैशबोर्ड", + "location": "स्थान", + "about": "के बारे में", + "deleteThisOrganization": "इस संगठन को हटाएं", + "statistics": "सांख्यिकी", + "members": "सदस्य", + "admins": "व्यवस्थापक", + "posts": "पोस्ट", + "events": "आयोजन", + "blockedUsers": "रोके गए उपयोगकर्ता", + "requests": "अनुरोध", + "viewAll": "सभी देखें", + "upcomingEvents": "आगामी घटनाएँ", + "noUpcomingEvents": "कोई आगामी घटनाएँ नहीं", + "latestPosts": "नवीनतम पोस्ट", + "noPostsPresent": "कोई पोस्ट नहीं है", + "membershipRequests": "सदस्यता अनुरोध", + "noMembershipRequests": "कोई सदस्यता अनुरोध नहीं", + "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।" + }, + "organizationPeople": { + "title": "तलावा सदस्य", + "filterByName": "नाम से फ़िल्टर करें", + "filterByLocation": "स्थान के अनुसार फ़िल्टर करें", + "filterByEvent": "इवेंट द्वारा फ़िल्टर करें", + "members": "सदस्य", + "admins": "व्यवस्थापक", + "users": "उपयोगकर्ता", + "searchName": "नाम दर्ज करें", + "searchevent": "घटना दर्ज करें", + "searchFirstName": "प्रथम नाम दर्ज करें", + "searchLastName": "अंतिम नाम दर्ज करो" + }, + "userListCard": { + "joined": "में शामिल हो गए", + "addAdmin": "व्यवस्थापक जोड़ें", + "addedAsAdmin": "उपयोगकर्ता को व्यवस्थापक के रूप में जोड़ा गया है।", + "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।" + }, + "orgAdminListCard": { + "joined": "में शामिल हो गए", + "remove": "हटाना", + "removeAdmin": "व्यवस्थापक हटाएं", + "removeAdminMsg": "क्या आप इस व्यवस्थापक को हटाना चाहते हैं?", + "no": "नहीं", + "yes": "हाँ", + "adminRemoved": "व्यवस्थापक को हटा दिया गया है।", + "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।" + }, + "orgPeopleListCard": { + "joined": "में शामिल हो गए", + "remove": "हटाना", + "removeMember": "सदस्य निकालें", + "removeMemberMsg": "क्या आप इस सदस्य को हटाना चाहते हैं?", + "no": "नहीं", + "yes": "हाँ", + "memberRemoved": "सदस्य को हटा दिया गया है", + "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।" + }, + "organizationEvents": { + "title": "तलावा इवेंट्स", + "filterByTitle": "शीर्षक द्वारा फ़िल्टर करें", + "filterByLocation": "स्थान के अनुसार फ़िल्टर करें", + "filterByDescription": "विवरण द्वारा फ़िल्टर करें", + "events": "आयोजन", + "addEvent": "कार्यक्रम जोड़ें", + "eventDetails": "घटना की जानकारी", + "eventTitle": "शीर्षक", + "description": "विवरण", + "location": "स्थान", + "startDate": "आरंभ करने की तिथि", + "endDate": "अंतिम तिथि", + "startTime": "समय शुरू", + "endTime": "अंत समय", + "allDay": "पूरे दिन", + "recurringEvent": "पुनरावर्ती ईवेंट", + "isPublic": "सार्वजनिक है", + "isRegistrable": "पंजीकरण योग्य है", + "createEvent": "कार्यक्रम बनाएँ", + "enterFilter": "फ़िल्टर दर्ज करें", + "enterTitle": "शीर्षक दर्ज करें", + "enterDescrip": "विवरण दर्ज करें", + "eventLocation": "स्थान दर्ज करें", + "eventCreated": "बधाई हो! इवेंट बनाया गया है।", + "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।" + }, + "eventListCard": { + "location": "स्थान", + "on": "पर", + "end": "समाप्त", + "deleteEvent": "घटना हटाएं", + "deleteEventMsg": "क्या आप इस इवेंट को हटाना चाहते हैं?", + "no": "नहीं", + "yes": "हाँ", + "editEvent": "घटना संपादित करें", + "eventTitle": "शीर्षक", + "description": "विवरण", + "startTime": "समय शुरू", + "endTime": "अंत समय", + "allDay": "पूरे दिन", + "recurringEvent": "पुनरावर्ती ईवेंट", + "isPublic": "सार्वजनिक है", + "isRegistrable": "पंजीकरण योग्य है", + "close": "बंद करना", + "updatePost": "अपडेट पोस्ट", + "eventDetails": "घटना की जानकारी", + "eventDeleted": "इवेंट सफलतापूर्वक मिटाया गया.", + "eventUpdated": "इवेंट सफलतापूर्वक अपडेट किया गया।", + "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।" + }, + "orgPost": { + "title": "तलवा पोस्ट्स", + "searchPost": "पोस्ट खोजें", + "posts": "पोस्ट्स", + "createPost": "पोस्ट बनाएँ", + "postDetails": "पोस्ट विवरण", + "postTitle1": "पोस्ट का शीर्षक लिखें", + "postTitle": "शीर्षक", + "information": "जानकारी", + "information1": "पोस्ट की जानकारी लिखें", + "image": "पोस्ट छवि", + "video": "पोस्ट वीडियो", + "addPost": "पोस्ट जोड़ें", + "searchTitle": "शीर्षक से खोजें", + "searchText": "टेक्स्ट से खोजें", + "ptitle": "पोस्ट का शीर्षक", + "postDes": "आप किस बारे में बात करना चाहते हैं?", + "Title": "शीर्षक", + "Text": "टेक्स्ट", + "cancel": "रद्द करें", + "searchBy": "इसके द्वारा खोजें", + "Oldest": "सबसे पुराना पहले", + "Latest": "सबसे नवीनतम पहले", + "sortPost": "पोस्ट को क्रमित करें", + "tag": "आपका ब्राउज़र वीडियो टैग का समर्थन नहीं करता" + }, + "postNotFound": { + "post": "पोस्ट", + "not found!": "नहीं मिला!", + "organization": "संगठन", + "post not found!": "पोस्ट नहीं मिला!", + "organization not found!": "संगठन नहीं मिला!" + }, + "userNotFound": { + "user": "उपयोगकर्ता", + "not found!": "नहीं मिला!", + "roles": "भूमिका", + "user not found!": "उपयोगकर्ता नहीं मिले!", + "member not found!": "सदस्य अनुपस्थित!", + "admin not found!": "व्यवस्थापक नहीं मिला!", + "roles not found!": "भूमिकाएँ नहीं मिलीं!" + }, + "orgPostCard": { + "author": "लेखक", + "imageURL": "छवि URL", + "videoURL": "वीडियो URL", + "edit": "पोस्ट संपादित करें", + "deletePost": "पोस्ट हटाएं", + "deletePostMsg": "क्या आप इस पोस्ट को हटाना चाहते हैं?", + "no": "नहीं", + "yes": "हाँ", + "editPost": "पोस्ट संपादित करें", + "postTitle": "शीर्षक", + "information": "जानकारी", + "image": "छवि", + "video": "वीडियो", + "close": "बंद करें", + "updatePost": "पोस्ट अपडेट करें", + "postDeleted": "पोस्ट सफलतापूर्वक हटा दी गई है।", + "pin": "पोस्ट पिन करें", + "postUpdated": "पोस्ट सफलतापूर्वक अपडेट की गई है।", + "tag": "आपका ब्राउज़र वीडियो टैग का समर्थन नहीं करता", + "talawaApiUnavailable": "Talawa-API सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जाँचें।" + }, + "blockUnblockUser": { + "title": "तलावा ब्लॉक/अनब्लॉक यूजर", + "pageName": "ब्लॉक/अनब्लॉक", + "searchByName": "नाम से खोजें", + "listOfUsers": "स्पैम करने वाले उपयोगकर्ताओं की सूची", + "name": "नाम", + "email": "ईमेल", + "block_unblock": "ब्लॉक/अनब्लॉक करें", + "unblock": "अनब्लॉक करें", + "block": "अवरोध पैदा करना", + "orgName": "नाम दर्ज करें", + "blockedSuccessfully": "उपयोगकर्ता को सफलतापूर्वक अवरोधित किया गया", + "Un-BlockedSuccessfully": "उपयोगकर्ता अन-ब्लॉक किया गया सफलतापूर्वक", + "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।", + "allMembers": "सभी सदस्य", + "blockedUsers": "रोके गए उपयोगकर्ता", + "searchByFirstName": "पहले नाम से खोजें", + "searchByLastName": "उपनाम से खोजें", + "noResultsFoundFor": "के लिए कोई परिणाम नहीं मिला ", + "noSpammerFound": "कोई स्पैमर नहीं मिला" + }, + "forgotPassword": { + "title": "तलवा पासवर्ड भूल गए", + "forgotPassword": "पासवर्ड भूल गए", + "registeredEmail": "पंजीकृत ईमेल", + "getOtp": "ओटीपी प्राप्त करें", + "enterOtp": "ओटीपी दर्ज करें", + "enterNewPassword": "नया पासवर्ड दर्ज करें", + "cofirmNewPassword": "नए पासवर्ड की पुष्टि करें", + "changePassword": "पासवर्ड बदलें", + "backToLogin": "लॉगिन पर वापस जाएं", + "userOtp": "उदाहरण के लिए 12345", + "password": "पासवर्ड", + "emailNotRegistered": "ईमेल पंजीकृत नहीं है।", + "talawaApiUnavailable": "तलावा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रही है? अपनी नेटवर्क कनेक्टिविटी की भी जाँच करें।", + "errorSendingMail": "मेल भेजने में त्रुटि।", + "passwordMismatches": "पासवर्ड और पुष्टि पासवर्ड मेल नहीं खाते।", + "passwordChanges": "पासवर्ड सफलतापूर्वक बदल गया है।", + "OTPsent": "OTP आपके पंजीकृत ईमेल पर भेजा गया है।" + }, + "pageNotFound": { + "title": "404 नहीं मिला", + "talawaAdmin": "तलावा एडमिन", + "404": "404", + "notFoundMsg": "ओह! आपके द्वारा अनुरोधित पृष्ठ नहीं मिला!", + "backToHome": "घर वापिस जा रहा हूँ" + }, + "orgContribution": { + "title": "तलवा योगदान", + "filterByName": "नाम से फ़िल्टर करें", + "filterByTransId": "ट्रांस आईडी द्वारा फ़िल्टर करें", + "recentStats": "हाल के आँकड़े", + "contribution": "योगदान", + "orgname": "नाम दर्ज करें", + "searchtransaction": "लेन-देन आईडी दर्ज करें" + }, + "contriStats": { + "recentContribution": "हाल ही में योगदान", + "highestContribution": "उच्चतम योगदान", + "totalContribution": "कुल योगदान" + }, + "orgContriCards": { + "date": "दिनांक", + "transactionId": "लेनदेन आईडी", + "amount": "राशि" + }, + "orgSettings": { + "title": "तलावा सेटिंग", + "pageName": "सेटिंग्स", + "updateYourDetails": "अपना विवरण अपडेट करें", + "updateYourPassword": "अपना पासवर्ड अपडेट करें", + "updateOrganization": "अद्यतन संगठन", + "seeRequest": "अनुरोध देखें", + "settings": "समायोजन", + "noData": "कोई डेटा नहीं", + "otherSettings": "अन्य सेटिंग्स", + "changeLanguage": "भाषा बदलें" + }, + "deleteOrg": { + "deleteOrganization": "संगठन हटाएं", + "deleteSampleOrganization": "सैंपल संगठन को हटाएं", + "deleteMsg": "क्या आप इस संगठन को हटाना चाहते हैं?", + "cancel": "रद्द करना", + "confirmDelete": "हटाने की पुष्टि करें", + "longDelOrgMsg": "संगठन को हमेशा के लिए हटा देने के लिए संगठन हटाने के बटन पर क्लिक करके, उसके इवेंट्स, टैग्स और सभी संबंधित डेटा सहित सभी जानकारी हटा दी जाएगी।" + }, + "userUpdate": { + "firstName": "पहला नाम", + "lastName": "उपनाम", + "email": "ईमेल", + "password": "पासवर्ड", + "appLanguageCode": "डिफ़ॉल्ट भाषा", + "userType": "उपयोगकर्ता का प्रकार", + "admin": "व्यवस्थापक", + "superAdmin": "सुपरएडमिन", + "displayImage": "प्रदर्शन छवि", + "saveChanges": "परिवर्तनों को सुरक्षित करें", + "cancel": "रद्द करना" + }, + "userPasswordUpdate": { + "previousPassword": "पिछला पासवर्ड", + "newPassword": "नया पासवर्ड", + "confirmNewPassword": "नए पासवर्ड की पुष्टि करें", + "saveChanges": "परिवर्तनों को सुरक्षित करें", + "cancel": "रद्द करना" + }, + "orgDelete": { + "deleteOrg": "संगठन हटाएं" + }, + "membershipRequest": { + "joined": "में शामिल हो गए", + "accept": "स्वीकार करना", + "reject": "अस्वीकार", + "memberAdded": "यह स्वीकार किया जाता है", + "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।" + }, + "orgUpdate": { + "name": "नाम", + "description": "विवरण", + "location": "जगह", + "displayImage": "प्रदर्शन छवि", + "isPublic": "सार्वजनिक", + "isVisibleInSearch": "खोज में दिखाए जा सकते हैं", + "saveChanges": "परिवर्तनों को सुरक्षित करें", + "cancel": "रद्द करना", + "enterNameOrganization": "संगठन का नाम दर्ज करें", + "successfulUpdated": "सफल अपडेट किया गया", + "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।" + }, + "addOnRegister": { + "addNew": "नया जोड़ो", + "addPlugin": "प्लगइन जोड़ें", + "pluginName": "प्लगइन का नाम", + "creatorName": "निर्माता का नाम", + "pluginDesc": "प्लगइन विवरण", + "close": "बंद करना", + "register": "पंजीकरण करवाना", + "pName": "जैसे: दान", + "cName": "जैसे: जॉन डो", + "pDesc": "यह प्लगइन यूआई को सक्षम बनाता है" + }, + "addOnStore": { + "title": "प्लगइन स्टोर", + "searchName": "जैसे: दान", + "enable": "सक्रिय", + "disable": "अक्षम", + "pHeading": "प्लग-इन", + "install": "स्थापित", + "available": "उपलब्ध", + "pMessage": "प्लगइन मौजूद नहीं है", + "filter": "फिल्टर", + "search": "खोज" + }, + "addOnEntry": { + "enable": "सक्रिय", + "install": "स्थापित करना", + "uninstall": "स्थापना रद्द करें" + }, + "memberDetail": { + "title": "उपयोगकर्ता विवरण", + "addAdmin": "व्यवस्थापक जोड़ें", + "organizations": "संगठन", + "events": "घटनाएं", + "role": "भूमिका", + "email": "ईमेल", + "createdOn": "पर बनाया गया", + "main": "मुख्य", + "firstName": "पहला नाम", + "lastName": "अंतिम नाम", + "memberOfOrganization": "संगठन का सदस्य", + "language": "भाषा", + "adminApproved": "व्यवस्थापक द्वारा स्वीकृत", + "pluginCreationAllowed": "प्लगइन निर्माण अनुमति दी गई", + "joined": "शामिल हुए", + "created": "बनाया गया", + "adminForOrganizations": "संगठनों के लिए व्यवस्थापक", + "membershipRequests": "सदस्यता अनुरोध", + "adminForEvents": "घटनाओं के लिए व्यवस्थापक", + "addedAsAdmin": "उपयोगकर्ता को व्यवस्थापक के रूप में जोड़ा गया है।", + "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। कृपया अपना नेटवर्क कनेक्शन जांचें और कुछ देर प्रतीक्षा करें।" + }, + "userLogin": { + "login": "लॉगिन", + "forgotPassword": "पासवर्ड भूल गए ?", + "loginIntoYourAccount": "अपने खाते में प्रवेश करें", + "emailAddress": "ईमेल एड्रेस", + "enterEmail": "अपना ईमेल पता दर्ज करें", + "password": "पासवर्ड", + "enterPassword": "अपना पासवर्ड डालें", + "register": "रजिस्टर करें", + "invalidDetailsMessage": "कृपया एक वैध ईमेल और पासवर्ड दर्ज करें।", + "notAuthorised": "क्षमा मांगना! आप अधिकृत नहीं हैं!", + "invalidCredentials": "दर्ज क्रेडेंशियल्स गलत हैं। कृपया मान्य क्रेडेंशियल दर्ज करें।", + "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। कृपया अपना नेटवर्क कनेक्शन जांचें और कुछ देर प्रतीक्षा करें।" + }, + "userRegister": { + "register": "रजिस्टर करें", + "firstName": "पहला नाम", + "enterFirstName": "अपना पहला नाम दर्ज करें", + "lastName": "अंतिम नाम", + "enterLastName": "अपना अंतिम नाम दर्ज करें", + "emailAddress": "ईमेल एड्रेस", + "enterEmail": "अपना ईमेल पता दर्ज करें", + "password": "पासवर्ड", + "enterPassword": "अपना पासवर्ड डालें", + "confirmPassword": "पासवर्ड की पुष्टि कीजिये", + "enterConfirmPassword": "पुष्टि करने के लिए अपना पासवर्ड दर्ज करें", + "alreadyhaveAnAccount": "क्या आपके पास पहले से एक खाता मौजूद है?", + "login": "लॉगिन", + "afterRegister": "पंजीकरण सफलतापूर्वक हो गया है। कृपया आपके अनुरोध को स्वीकार करने के लिए व्यवस्थापक की प्रतीक्षा करें।", + "passwordNotMatch": "पासवर्ड मेल नहीं खाता. पासवर्ड की पुष्टि करें और पुनः प्रयास करें।", + "invalidDetailsMessage": "कृपया मान्य विवरण दर्ज करें।", + "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। कृपया अपना नेटवर्क कनेक्शन जांचें और कुछ देर प्रतीक्षा करें।" + }, + "userNavbar": { + "talawa": "तलावा", + "home": "घर", + "people": "लोग", + "events": "आयोजन", + "chat": "बातचीत", + "donate": "दान देना", + "myTasks": "मेरा काम", + "settings": "समायोजन", + "language": "भाषा", + "logout": "लॉग आउट", + "close": "बंद करना" + }, + "userOrganizations": { + "allOrganizations": "सभी संगठन", + "joinedOrganizations": "संगठन शामिल हुए", + "createdOrganizations": "संगठन बनाये गये", + "search": "खोज", + "nothingToShow": "यहां दिखाने के लिए कुछ भी नहीं है.", + "selectOrganization": "संगठन का चयन करें" + }, + "userSidebar": { + "yourOrganizations": "आपके संगठन", + "noOrganizations": "आप अभी तक किसी संगठन में शामिल नहीं हुए हैं.", + "viewAll": "सभी को देखें" + }, + "organizationSidebar": { + "viewAll": "सभी को देखें", + "events": "आयोजन", + "members": "सदस्य", + "noEvents": "दिखाने के लिए कोई ईवेंट नहीं", + "noMembers": "दिखाने के लिए कोई सदस्य नहीं" + }, + "postCard": { + "likes": "पसंद", + "comments": "टिप्पणियाँ" + }, + "home": { + "feed": "फ़ीड", + "pinnedPosts": "पिन किए गए पोस्ट देखें", + "somethingOnYourMind": "आपके मन में कुछ है?" + }, + "settings": { + "profileSettings": "पार्श्वचित्र समायोजन", + "firstName": "पहला नाम", + "lastName": "उपनाम", + "emailAddress": "मेल पता", + "updateImage": "छवि अद्यतन करें", + "save": "बचाना" + }, + "donate": { + "donateTo": "दान दें", + "amount": "मात्रा", + "yourPreviousDonations": "आपका पिछला दान", + "donate": "दान", + "nothingToShow": "यहां दिखाने के लिए कुछ भी नहीं है." + }, + "userEvents": { + "nothingToShow": "यहां दिखाने के लिए कुछ भी नहीं है.", + "search": "खोज", + "createEvent": "कार्यक्रम बनाएँ", + "eventTitle": "कार्यक्रम का शीर्षक", + "eventDescription": "घटना विवरण", + "eventLocation": "घटना स्थान", + "startDate": "आरंभ तिथि चुनें", + "endDate": "अंतिम तिथि चुनें", + "publicEvent": "सार्वजनिक समारोह", + "registerable": "पंजीकरण योग्य", + "recurring": "पुनरावर्ती", + "startTime": "समय शुरू", + "endTime": "अंत समय", + "cancel": "रद्द करना", + "create": "बनाएं", + "listView": "लिस्ट व्यू", + "calendarView": "कैलेंडर दृश्य", + "allDay": "पूरे दिन", + "eventCreated": "ईवेंट सफलतापूर्वक बनाया और पोस्ट किया गया." + }, + "userEventCard": { + "location": "जगह", + "starts": "प्रारंभ होगा", + "ends": "समाप्त होगा", + "creator": "निर्माता", + "alreadyRegistered": "पहले से ही पंजीकृत", + "register": "पंजीकरण करवाना" + }, + "userTasks": { + "yourAssignedTasks": "आपके असाइन किए गए कार्य", + "nothingToShow": "यहां दिखाने के लिए कुछ भी नहीं है." + }, + "userTaskCard": { + "description": "विवरण", + "deadline": "अंतिम तारीख", + "created": "बनाया", + "assignees": "असाइनी", + "completed": "पुरा", + "incomplete": "अधूरा", + "taskCompleted": "काम पूरा हो गया", + "taskNotCompleted": "कार्य अभी तक पूरा नहीं हुआ है", + "event": "आयोजन", + "organization": "संगठन" + }, + "advertisement": { + "title": "विज्ञापन", + "pHeading": "विज्ञापन प्रबंधन", + "activeAds": "सक्रिय अभियान", + "archievedAds": "संपन्न अभियान", + "pMessage": "इस अभियान के लिए कोई विज्ञापन नहीं हैं।", + "delete": "हटाएँ" + }, + "userChat": { + "chat": "बात", + "search": "खोज", + "contacts": "संपर्क" + }, + "userChatRoom": { + "selectContact": "बातचीत शुरू करने के लिए एक संपर्क चुनें", + "sendMessage": "मेसेज भेजें" + } +} diff --git a/public/locales/sp.json b/public/locales/sp.json new file mode 100644 index 0000000000..09d6472753 --- /dev/null +++ b/public/locales/sp.json @@ -0,0 +1,668 @@ +{ + "loginPage": { + "title": "Administrador Talawa", + "fromPalisadoes": "Una aplicación de código abierto de los voluntarios de la Fundación palisados", + "talawa_portal": "Portal De Administración Talawa", + "login": "Acceso", + "register": "Registro", + "firstName": "Primer nombre", + "lastName": "Apellido", + "email": "Correo electrónico", + "password": "Clave", + "atleast_8_char_long": "Al menos 8 caracteres de largo", + "Password_and_Confirm_password_mismatches.": "Contraseña y Confirmar contraseña no coinciden.", + "confirmPassword": "Confirmar contraseña", + "forgotPassword": "Has olvidado tu contraseña ?", + "enterEmail": "ingrese correo electrónico", + "enterPassword": "introducir la contraseña", + "doNotOwnAnAccount": "¿No tienes una cuenta?", + "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está funcionando? Verifica también la conectividad de tu red.", + "captchaError": "¡Error de captcha!", + "Please_check_the_captcha": "Por favor, revisa el captcha.", + "Something_went_wrong": "Algo salió mal. Inténtalo después de un tiempo", + "passwordMismatches": "Contraseña y Confirmar contraseña no coinciden.", + "fillCorrectly": "Complete todos los detalles correctamente.", + "notAuthorised": "¡Lo siento! ¡No estás autorizado!", + "notFound": "¡Usuario no encontrado!", + "successfullyRegistered": "Registrado con éxito. Espere hasta que sea aprobado", + "login_to_admin_portal": "Inicio de sesión en el portal de administración", + "OR": "O" + }, + "latestEvents": { + "eventCardTitle": "Próximos Eventos", + "eventCardSeeAll": "Ver Todos", + "noEvents": "No Hay Eventos Próximos" + }, + "listNavbar": { + "talawa_portal": "Portal De Administración Talawa", + "roles": "Roles", + "requests": "Peticiones", + "logout": "Cerrar sesión" + }, + "leftDrawer": { + "talawaAdminPortal": "Portal de administración de Talawa", + "menu": "Menú", + "organizations": "Organizaciones", + "requests": "Solicitudes", + "users": "Usuarios", + "logout": "Cerrar sesión" + }, + "leftDrawerOrg": { + "talawaAdminPortal": "Portal de administración de Talawa", + "menu": "Menú", + "talawa_portal": "Portal De Administración Talawa", + "Dashboard": "Tablero", + "People": "Gente", + "Events": "Eventos", + "Contributions": "Contribuciones", + "Posts": "Publicaciones", + "Block/Unblock": "Bloquear/Desbloquear", + "Plugins": "Complementos", + "Plugin Store": "Tienda de complementos", + "allOrganizations": "Todas las organizaciones", + "yourOrganization": "Tu organización", + "notification": "Notificación", + "settings": "Ajustes", + "language": "Idioma", + "logout": "Cerrar sesión", + "notifications": "Notificaciones", + "spamsThe": "envía correo no deseado", + "group": "grupo", + "noNotifications": "No Notificaciones", + "close": "Cerca" + }, + "orgList": { + "title": "Organizaciones Talawa", + "you": "Tú", + "name": "Nombre", + "designation": "Designacion", + "email": "Correo electrónico", + "searchByName": "Buscar por nombre", + "organizations": "Organizaciones", + "createOrganization": "Crear organización", + "createSampleOrganization": "Crear organización de muestra", + "description": "Descripción", + "location": "Ubicación", + "isPublic": "Es público", + "visibleInSearch": "Visible en la búsqueda", + "displayImage": "Mostrar imagen", + "enterName": "Ingrese su nombre", + "sort": "Ordenar", + "filter": "Filtrar", + "cancel": "Cancelar", + "endOfResults": "Fin de los resultados", + "noOrgErrorTitle": "Organizaciones no encontradas", + "sampleOrgDuplicate": "Solo se permite una organización de muestra", + "noOrgErrorDescription": "Por favor, crea una organización a través del panel de control", + "noResultsFoundFor": "No se encontraron resultados para ", + "OR": "O", + "sampleOrgSuccess": "Organización de ejemplo creada exitosamente" + }, + "orgListCard": { + "admins": "Administradores", + "members": "Miembros", + "manage": "Administrar", + "sampleOrganization": "Organización de muestra" + }, + "paginationList": { + "rowsPerPage": "filas por página", + "all": "Todos" + }, + "users": { + "title": "Roles Talawa", + "searchByName": "Buscar por nombre", + "users": "Usuarios", + "name": "Nombre", + "email": "Correo electrónico", + "roles_userType": "Rol/Tipo de usuario", + "joined_organizations": "Organizaciones unidas", + "blocked_organizations": "Organizaciones bloqueadas", + "endOfResults": "Fin de los resultados", + "orgJoinedBy": "Organizaciones unidas por", + "orgThatBlocked": "Organizaciones bloqueadas por", + "hasNotJoinedAnyOrg": "No se ha unido a ninguna organización.", + "isNotBlockedByAnyOrg": "No está bloqueado por ninguna organización.", + "searchByOrgName": "Buscar por nombre de organización", + "view": "Ver", + "admin": "ADMINISTRACIÓN", + "superAdmin": "SUPERADMIN", + "user": "USUARIO", + "enterName": "Ingrese su nombre", + "loadingUsers": "Cargando usuarios ...", + "noUserFound": "No se encontró ningún usuario.", + "sort": "Ordenar", + "Oldest": "Más Antiguas Primero", + "Newest": "Más Recientes Primero", + "filter": "Filtrar", + "roleUpdated": "Rol actualizado.", + "noResultsFoundFor": "No se encontraron resultados para ", + "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está funcionando? Compruebe también la conectividad de su red." + }, + "requests": { + "title": "Solicitudes Talawa", + "searchByName": "Buscar por nombre", + "requests": "Peticiones", + "name": "Nombre", + "email": "Correo electrónico", + "accept": "Aceptar", + "reject": "Rechazar", + "enterName": "Ingrese su nombre", + "endOfResults": "Fin de los resultados", + "loadingRequests": "Cargando solicitudes ...", + "noRequestFound": "No se encontró ninguna solicitud.", + "sort": "Ordenar", + "filter": "Filtrar", + "userApproved": "Aprobado por el usuario", + "userRejected": "Usuario rechazado", + "noResultsFoundFor": "No se encontraron resultados para ", + "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está funcionando? Compruebe también la conectividad de su red." + }, + "dashboard": { + "title": "Panel de", + "location": "Ubicación", + "about": "Sobre", + "deleteThisOrganization": "Eliminar esta organización", + "statistics": "Estadísticas", + "members": "Miembros", + "admins": "Administradores", + "posts": "Publicaciones", + "events": "Eventos", + "blockedUsers": "Usuarios bloqueados", + "requests": "Solicitudes", + "viewAll": "Ver Todo", + "upcomingEvents": "Próximos Eventos", + "noUpcomingEvents": "No Hay Próximos Eventos", + "latestPosts": "Últimas Publicaciones", + "noPostsPresent": "No Hay Publicaciones Presentes", + "membershipRequests": "Solicitudes de Membresía", + "noMembershipRequests": "No Hay Solicitudes de Membresía", + "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está funcionando? Compruebe también la conectividad de su red." + }, + "organizationPeople": { + "title": "Miembros Talawa", + "filterByName": "Filtrar por nombre", + "filterByLocation": "Filtrar por Ubicación", + "filterByEvent": "Filtrar por Evento", + "members": "Miembros", + "admins": "Administradores", + "users": "Usuarios", + "searchName": "Ingrese su nombre", + "searchevent": "Ingresar evento", + "searchFirstName": "Ingrese el nombre", + "searchLastName": "Introduzca el apellido" + }, + "userListCard": { + "joined": "Unido", + "addAdmin": "Agregar administrador", + "addedAsAdmin": "El usuario se agrega como administrador.", + "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está funcionando? Compruebe también la conectividad de su red." + }, + "orgAdminListCard": { + "joined": "Unido", + "remove": "Remover", + "removeAdmin": "Eliminar administrador", + "removeAdminMsg": "¿Quieres eliminar a este administrador?", + "no": "No", + "yes": "Sí", + "adminRemoved": "Se elimina el administrador.", + "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está funcionando? Compruebe también la conectividad de su red." + }, + "orgPeopleListCard": { + "joined": "Unido", + "remove": "Remover", + "removeMember": "Eliminar miembro", + "removeMemberMsg": "¿Quieres eliminar a este miembro?", + "no": "No", + "yes": "Sí", + "memberRemoved": "El miembro es eliminado", + "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está funcionando? Compruebe también la conectividad de su red." + }, + "organizationEvents": { + "title": "Eventos Talawa", + "filterByTitle": "Filtrar por Título", + "filterByLocation": "Filtrar por Ubicación", + "filterByDescription": "Filtrar por descripción", + "events": "Eventos", + "addEvent": "Añadir evento", + "eventDetails": "Detalles del evento", + "eventTitle": "Título", + "description": "Descripción", + "location": "Ubicación", + "startDate": "Fecha de inicio", + "endDate": "Fecha final", + "startTime": "Hora de inicio", + "endTime": "Hora de finalización", + "allDay": "Todo el dia", + "recurringEvent": "Evento recurrente", + "isPublic": "Es público", + "isRegistrable": "Es registrable", + "createEvent": "Crear evento", + "enterFilter": "Introducir filtro", + "enterTitle": "Ingrese el título", + "enterDescrip": "Introduce la descripción", + "eventLocation": "Introducir ubicación", + "eventCreated": "¡Felicidades! Se crea el Evento.", + "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está funcionando? Compruebe también la conectividad de su red." + }, + "eventListCard": { + "location": "Ubicación", + "on": "En", + "end": "Final", + "deleteEvent": "Eliminar evento", + "deleteEventMsg": "¿Quieres eliminar este evento?", + "no": "No", + "yes": "Sí", + "editEvent": "Editar evento", + "eventTitle": "Título", + "description": "Descripción", + "startTime": "Hora de inicio", + "endTime": "Hora de finalización", + "allDay": "Todo el dia", + "recurringEvent": "Evento recurrente", + "isPublic": "Es público", + "isRegistrable": "Es registrable", + "close": "Cerca", + "updatePost": "Actualizar publicación", + "eventDetails": "Detalles del evento", + "eventDeleted": "Evento eliminado con éxito.", + "eventUpdated": "Evento actualizado con éxito.", + "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está funcionando? Compruebe también la conectividad de su red." + }, + "orgPost": { + "title": "Publicaciones de Talawa", + "searchPost": "Buscar Publicación", + "posts": "Publicaciones", + "createPost": "Crear Publicación", + "postDetails": "Detalles de la Publicación", + "postTitle1": "Escribir título de la publicación", + "postTitle": "Título", + "information": "Información", + "information1": "Escribir información de la publicación", + "image": "Imagen de la Publicación", + "video": "Video de la Publicación", + "addPost": "Agregar Publicación", + "searchTitle": "Buscar por Título", + "searchText": "Buscar por Texto", + "ptitle": "Título de la Publicación", + "postDes": "¿De qué quieres hablar?", + "Title": "Título", + "Text": "Texto", + "cancel": "Cancelar", + "searchBy": "Buscar por", + "Oldest": "Más Antiguas Primero", + "Latest": "Más Recientes Primero", + "sortPost": "Ordenar Publicaciones", + "tag": "Su navegador no admite la etiqueta de video" + }, + "postNotFound": { + "post": "Publicaciones", + "not found!": "Extraviado!", + "organization": "Organización", + "post not found!": "Publicaciones Extraviado!", + "organization not found!": "Organización Extraviado!" + }, + "userNotFound": { + "user": "usuari(a/o)", + "not found!": "extraviado!", + "roles": "papeles", + "user not found!": "usuario no encontrado!", + "member not found!": "Miembro no encontrado!", + "admin not found!": "Administrador no encontrado!", + "roles not found!": "roles no encontrados!" + }, + + "orgPostCard": { + "author": "Autor", + "imageURL": "URL de la Imagen", + "videoURL": "URL del Video", + "edit": "Editar Publicación", + "deletePost": "Eliminar Publicación", + "deletePostMsg": "¿Desea eliminar esta publicación?", + "no": "No", + "yes": "Sí", + "editPost": "Editar Publicación", + "postTitle": "Título", + "information": "Información", + "image": "Imagen", + "video": "Video", + "close": "Cerrar", + "updatePost": "Actualizar Publicación", + "postDeleted": "Publicación eliminada exitosamente.", + "postUpdated": "Publicación actualizada exitosamente.", + "tag": "Su navegador no admite la etiqueta de video", + "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está en funcionamiento? Compruebe también su conectividad de red." + }, + "blockUnblockUser": { + "title": "Usuario de bloqueo/desbloqueo de Talawa", + "pageName": "Bloqueo/desbloqueo", + "searchByName": "Buscar por nombre", + "listOfUsers": "Lista de Usuarios que enviaron spam", + "name": "Nombre", + "email": "Correo electrónico", + "block_unblock": "Bloquear/Desbloquear", + "unblock": "Desatascar", + "block": "Bloquear", + "orgName": "Ingrese su nombre", + "blockedSuccessfully": "Usuario bloqueado con éxito", + "Un-BlockedSuccessfully": "Usuario desbloqueado con éxito", + "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está funcionando? Compruebe también la conectividad de su red.", + "allMembers": "Todos los miembros", + "blockedUsers": "Usuarios bloqueados", + "searchByFirstName": "Buscar por nombre de pila", + "searchByLastName": "Buscar por apellido", + "noResultsFoundFor": "No se encontraron resultados para ", + "noSpammerFound": "No se encontró ningún spammer" + }, + "forgotPassword": { + "title": "Talawa olvidó su contraseña", + "forgotPassword": "Has olvidado tu contraseña", + "registeredEmail": "Email registrado", + "getOtp": "Obtener OTP", + "enterOtp": "Ingresar OTP", + "enterNewPassword": "Ingrese nueva clave", + "cofirmNewPassword": "Confirmar nueva contraseña", + "changePassword": "Cambia la contraseña", + "backToLogin": "Volver al inicio de sesión", + "userOtp": "por ejemplo 12345", + "password": "Contraseña", + "emailNotRegistered": "El correo electrónico no está registrado.", + "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está funcionando? Verifica también la conectividad de tu red.", + "errorSendingMail": "Error al enviar correo.", + "passwordMismatches": "Contraseña y Confirmar contraseña no coinciden.", + "passwordChanges": "La contraseña cambia correctamente.", + "OTPsent": "OTP se envía a su correo electrónico registrado" + }, + "pageNotFound": { + "title": "404 No encontrado", + "talawaAdmin": "Administrador de Talawa", + "404": "404", + "notFoundMsg": "¡Ups! ¡No se encontró la página que solicitaste!", + "backToHome": "De vuelta a casa" + }, + "orgContribution": { + "title": "Contribuciones Talawa", + "filterByName": "Filtrar por nombre", + "filterByTransId": "Filtrar por ID de transacción", + "recentStats": "Estadísticas recientes", + "contribution": "Contribución", + "orgname": "Ingrese su nombre", + "searchtransaction": "Ingrese la identificación de la transacción" + }, + "contriStats": { + "recentContribution": "Contribución reciente", + "highestContribution": "Contribución más alta", + "totalContribution": "Contribución total" + }, + "orgContriCards": { + "date": "Fecha", + "transactionId": "ID de transacción", + "amount": "Monto" + }, + "orgSettings": { + "title": "Configuración Talawa", + "pageName": "Configuración", + "updateYourDetails": "Actualiza tus datos", + "updateYourPassword": "Actualice su contraseña", + "updateOrganization": "Actualizar Organización", + "seeRequest": "Ver Solicitud", + "settings": "Ajustes", + "noData": "Sin datos", + "otherSettings": "Otras Configuraciones", + "changeLanguage": "Cambiar Idioma" + }, + "deleteOrg": { + "deleteOrganization": "Eliminar organización", + "deleteSampleOrganization": "Eliminar organización de muestra", + "deleteMsg": "¿Desea eliminar esta organización?", + "cancel": "Cancelar", + "confirmDelete": "Confirmar eliminación", + "longDelOrgMsg": "Al hacer clic en el botón Eliminar organización, la organización se eliminará permanentemente junto con sus eventos, etiquetas y todos los datos relacionados." + }, + "userUpdate": { + "firstName": "Primer nombre", + "lastName": "Apellido", + "email": "Correo electrónico", + "password": "Clave", + "appLanguageCode": "Idioma predeterminado", + "userType": "Tipo de usuario", + "admin": "Administración", + "superAdmin": "Superadministrador", + "displayImage": "Mostrar imagen", + "saveChanges": "Guardar cambios", + "cancel": "Cancelar" + }, + "userPasswordUpdate": { + "previousPassword": "Contraseña anterior", + "newPassword": "Nueva contraseña", + "confirmNewPassword": "Confirmar nueva contraseña", + "saveChanges": "Guardar cambios", + "cancel": "Cancelar" + }, + "orgDelete": { + "deleteOrg": "Eliminar organización" + }, + "membershipRequest": { + "joined": "Unido", + "accept": "Aceptar", + "reject": "Rechazar", + "memberAdded": "es aceptado", + "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está funcionando? Compruebe también la conectividad de su red." + }, + "orgUpdate": { + "name": "Nombre", + "description": "Descripción", + "location": "ubicación", + "displayImage": "Mostrar imagen", + "isPublic": "Público", + "isVisibleInSearch": "Visible en la búsqueda", + "saveChanges": "Guardar cambios", + "cancel": "Cancelar", + "enterNameOrganization": "Ingrese el nombre de la organización", + "successfulUpdated": "Exitoso actualizado", + "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está funcionando? Compruebe también la conectividad de su red." + }, + "addOnRegister": { + "addNew": "Agregar nueva", + "addPlugin": "Agregar complemento", + "pluginName": "Nombre del complemento", + "creatorName": "Nombre del creadora", + "pluginDesc": "Descripción del complemento", + "close": "Cerca", + "register": "Registro", + "pName": "Ej: Donaciones", + "cName": "Ej: John Doe", + "pDesc": "Este complemento habilita la interfaz de usuario para" + }, + "addOnStore": { + "title": "Tienda de complementos", + "searchName": "Ej: Donaciones", + "enable": "Activada", + "disable": "Desactivada", + "pHeading": "Complementos", + "install": "Instalada", + "available": "Disponible", + "pMessage": "El complemento no existe", + "filter": "filtros", + "search": "Buscar" + }, + "addOnEntry": { + "enable": "Activada", + "install": "Instalar", + "uninstall": "Desinstalar" + }, + "memberDetail": { + "title": "Detalles del usuario", + "addAdmin": "Agregar administrador", + "organizations": "Organizaciones", + "events": "Eventos", + "role": "Rol", + "email": "Correo electrónico", + "createdOn": "Creado en", + "main": "Principal", + "firstName": "Nombre", + "lastName": "Apellido", + "memberOfOrganization": "Miembro de la organización", + "language": "Idioma", + "adminApproved": "Aprobado por el administrador", + "pluginCreationAllowed": "Permitir creación de complementos", + "joined": "Unido", + "created": "Creado", + "adminForOrganizations": "Administrador de organizaciones", + "membershipRequests": "Solicitudes de membresía", + "adminForEvents": "Administrador de eventos", + "addedAsAdmin": "El usuario se agrega como administrador.", + "talawaApiUnavailable": "El servicio Talawa-API no está disponible. Compruebe amablemente su conexión de red y espere un momento." + }, + "userLogin": { + "login": "Acceso", + "forgotPassword": "Has olvidado tu contraseña ?", + "loginIntoYourAccount": "Inicie sesión en su cuenta", + "emailAddress": "correo electrónico", + "enterEmail": "Ingrese su dirección de correo electrónico", + "password": "Contraseña", + "enterPassword": "Ingresa tu contraseña", + "register": "Registro", + "invalidDetailsMessage": "Por favor, introduzca un correo electrónico y una contraseña válidos.", + "notAuthorised": "¡Lo siento! usted no está autorizado!", + "invalidCredentials": "Las credenciales ingresadas son incorrectas. Ingrese credenciales válidas.", + "talawaApiUnavailable": "El servicio Talawa-API no está disponible. Compruebe amablemente su conexión de red y espere un momento." + }, + "userRegister": { + "register": "Registro", + "firstName": "Nombre de pila", + "enterFirstName": "Ponga su primer nombre", + "lastName": "Apellido", + "enterLastName": "Ingresa tu apellido", + "emailAddress": "correo electrónico", + "enterEmail": "Ingrese su dirección de correo electrónico", + "password": "Contraseña", + "enterPassword": "Ingresa tu contraseña", + "confirmPassword": "confirmar Contraseña", + "enterConfirmPassword": "Ingrese su contraseña para confirmar", + "alreadyhaveAnAccount": "¿Ya tienes una cuenta?", + "login": "Acceso", + "afterRegister": "Registrado exitosamente. Espere a que el administrador apruebe su solicitud.", + "passwordNotMatch": "La contraseña no coincide. Confirme la contraseña y vuelva a intentarlo.", + "invalidDetailsMessage": "Ingrese detalles válidos.", + "talawaApiUnavailable": "El servicio Talawa-API no está disponible. Compruebe amablemente su conexión de red y espere un momento." + }, + "userNavbar": { + "talawa": "Talawa", + "home": "Hogar", + "people": "Gente", + "events": "Eventos", + "chat": "Charlar", + "donate": "Donar", + "myTasks": "Mis tareas", + "settings": "Ajustes", + "language": "Idioma", + "logout": "Cerrar sesión", + "close": "Cerca" + }, + "userOrganizations": { + "allOrganizations": "Todas las organizaciones", + "joinedOrganizations": "Organizaciones unidas", + "createdOrganizations": "Organizaciones creadas", + "search": "Buscar", + "nothingToShow": "Nada que mostrar aquí.", + "selectOrganization": "Seleccionar organización" + }, + "userSidebar": { + "yourOrganizations": "Tus Organizaciones", + "noOrganizations": "Aún no te has unido a ninguna organización.", + "viewAll": "Ver todo" + }, + "organizationSidebar": { + "viewAll": "Ver todo", + "events": "Eventos", + "members": "Miembros", + "noEvents": "No hay eventos para mostrar", + "noMembers": "No hay miembros para mostrar" + }, + "postCard": { + "likes": "Gustos", + "comments": "Comentarios" + }, + "home": { + "feed": "Alimentar", + "pinnedPosts": "Ver publicaciones fijadas", + "somethingOnYourMind": "¿Algo en tu mente?" + }, + "settings": { + "profileSettings": "Configuración de perfil", + "firstName": "Nombre de pila", + "lastName": "Apellido", + "emailAddress": "dirección de correo electrónico", + "updateImage": "Actualizar imagen", + "save": "Ahorrar" + }, + "donate": { + "donateTo": "Donar a", + "amount": "Cantidad", + "yourPreviousDonations": "Tus donaciones anteriores", + "donate": "Donar", + "nothingToShow": "Nada que mostrar aquí." + }, + "userEvents": { + "nothingToShow": "No hay nada que mostrar aquí.", + "search": "Buscar", + "createEvent": "Crear evento", + "eventTitle": "Título del evento", + "eventDescription": "Descripción del evento", + "eventLocation": "Lugar del evento", + "startDate": "Seleccione la fecha de inicio", + "endDate": "Seleccionar fecha de finalización", + "publicEvent": "Evento público", + "registerable": "Registrable", + "recurring": "Periódica", + "startTime": "Hora de inicio", + "endTime": "Hora de finalización", + "cancel": "Cancelar", + "create": "Crear", + "listView": "Vista de la lista", + "calendarView": "Vista de calendario", + "allDay": "Todo el dia", + "eventCreated": "Evento creado y publicado exitosamente." + }, + "userEventCard": { + "location": "Ubicación", + "starts": "Empieza", + "ends": "Termina", + "creator": "Creadora", + "alreadyRegistered": "Ya registrado", + "register": "Registro" + }, + "userTasks": { + "yourAssignedTasks": "Tus tareas asignadas", + "nothingToShow": "No hay nada que mostrar aquí." + }, + "userTaskCard": { + "description": "Descripción", + "deadline": "Fecha límite", + "created": "Creado", + "assignees": "Cesionarias", + "completed": "Terminada", + "incomplete": "Incompleta", + "taskCompleted": "La tarea ha sido completada", + "taskNotCompleted": "La tarea aún no se ha completado", + "event": "Evento", + "organization": "Organización" + }, + "advertisement": { + "title": "Anuncios", + "pHeading": "Gestionar anuncios", + "activeAds": "Campañas activas", + "archievedAds": "Campañas completadas", + "pMessage": "No hay anuncios disponibles para esta campaña.", + "delete": "Eliminar" + }, + "userChat": { + "chat": "Charlar", + "search": "Buscar", + "contacts": "Contactos" + }, + "userChatRoom": { + "selectContact": "Seleccione un contacto para iniciar una conversación", + "sendMessage": "Enviar mensaje" + } +} diff --git a/public/locales/zh.json b/public/locales/zh.json new file mode 100644 index 0000000000..138a345206 --- /dev/null +++ b/public/locales/zh.json @@ -0,0 +1,668 @@ +{ + "loginPage": { + "title": "塔拉瓦管理員", + "fromPalisadoes": "柵欄 基金会志愿者的开源应用程序", + "talawa_portal": "塔拉瓦管理門戶", + "login": "登錄", + "register": "登記", + "firstName": "名", + "lastName": "姓", + "email": "電子郵件", + "password": "密碼", + "atleast_8_char_long": "至少 8 個字符長", + "Password_and_Confirm_password_mismatches.": "密碼和確認密碼不匹配。", + "confirmPassword": "確認密碼", + "forgotPassword": "忘記密碼 ?", + "enterEmail": "输入电子邮件", + "enterPassword": "输入密码", + "doNotOwnAnAccount": "沒有帳戶嗎?", + "talawaApiUnavailable": "服務不可用。它正在運行嗎?還要檢查您的網絡連接。", + "captchaError": "驗證碼錯誤!", + "Please_check_the_captcha": "請檢查驗證碼。", + "Something_went_wrong": "出了點問題,請稍後再試。", + "passwordMismatches": "密碼和確認密碼不匹配。", + "fillCorrectly": "正確填寫所有細節。", + "notAuthorised": "抱歉!你沒有被授權!", + "notFound": "找不到用戶!", + "successfullyRegistered": "註冊成功,請等待審核通過。", + "login_to_admin_portal": " 管理员门户登录 ", + "OR": "或者" + }, + "latestEvents": { + "eventCardTitle": "即将举行的活动", + "eventCardSeeAll": "查看全部", + "noEvents": "暂无即将举行的活动" + }, + "listNavbar": { + "talawa_portal": "塔拉瓦管理門戶", + "roles": "角色", + "requests": "要求", + "logout": "登出" + }, + "leftDrawer": { + "talawaAdminPortal": "塔拉瓦管理门户", + "menu": "菜单", + "organizations": "组织", + "requests": "请求", + "users": "用户", + "logout": "退出登录" + }, + "leftDrawerOrg": { + "talawaAdminPortal": "塔拉瓦管理门户", + "menu": "菜单", + "talawa_portal": "塔拉瓦管理門戶", + "Dashboard": "儀表板", + "People": "人們", + "Events": "事件", + "Contributions": "貢獻", + "Posts": "帖子", + "Block/Unblock": "阻止/解除阻止", + "Plugins": "插件", + "Plugin Store": "插件商店", + "allOrganizations": "所有组织", + "yourOrganization": "您的组织", + "notification": "通知", + "settings": "設置", + "language": "語", + "logout": "登出", + "notifications": "通知", + "spamsThe": "垃圾郵件", + "group": "團體", + "noNotifications": "沒有通知", + "close": "關" + }, + "orgList": { + "title": "塔拉瓦組織", + "you": "你", + "name": "姓名", + "designation": "指定", + "email": "電子郵件", + "searchByName": "按名稱搜索", + "organizations": "组织", + "createOrganization": "創建組織", + "createSampleOrganization": "创建示范组织", + "description": "描述", + "location": "地點", + "isPublic": "是否公開", + "visibleInSearch": "在搜索中可見", + "displayImage": "顯示圖像", + "enterName": "输入名字", + "sort": "排序", + "filter": "過濾", + "cancel": "取消", + "endOfResults": "結果結束", + "noOrgErrorTitle": "找不到组织", + "sampleOrgDuplicate": "只允许一个样本组织", + "noOrgErrorDescription": "请通过仪表板创建一个组织", + "noResultsFoundFor": "未找到结果 ", + "OR": "或者", + "sampleOrgSuccess": "示例组织成功创建" + }, + "orgListCard": { + "admins": "管理員", + "members": "成員", + "manage": "管理", + "sampleOrganization": "示例组织" + }, + "paginationList": { + "rowsPerPage": "每頁行數", + "all": "全部" + }, + "users": { + "title": "塔拉瓦角色", + "searchByName": "按名稱搜索", + "users": "用户", + "name": "姓名", + "email": "電子郵件", + "roles_userType": "角色/用戶類型", + "joined_organizations": "加入的組織", + "blocked_organizations": "阻止的組織", + "endOfResults": "結果結束", + "orgJoinedBy": "加入組織", + "orgThatBlocked": "阻止組織", + "hasNotJoinedAnyOrg": "尚未加入任何組織", + "isNotBlockedByAnyOrg": "沒有被任何組織阻止", + "searchByOrgName": "按組織名稱搜索", + "view": "視圖", + "admin": "行政", + "superAdmin": "超級管理員", + "user": "用戶", + "enterName": "输入名字", + "loadingUsers": "正在加載用戶...", + "noUserFound": "找不到用戶。", + "sort": "排序", + "Oldest": "最旧的优先", + "Newest": "最新的优先", + "filter": "過濾", + "roleUpdated": "角色已更新。", + "noResultsFoundFor": "未找到结果 ", + "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。" + }, + "requests": { + "title": "塔拉瓦請求", + "searchByName": "按名稱搜索", + "requests": "要求", + "name": "姓名", + "email": "電子郵件", + "accept": "接受", + "reject": "拒絕", + "enterName": "输入名字", + "endOfResults": "結果結束", + "loadingRequests": "正在加載請求...", + "noRequestFound": "找不到請求。", + "sort": "排序", + "filter": "過濾", + "userApproved": "用戶批准", + "userRejected": "用戶被拒絕", + "noResultsFoundFor": "未找到结果 ", + "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。" + }, + "dashboard": { + "title": "儀表板", + "location": "地點", + "about": "關於", + "deleteThisOrganization": "刪除此組織", + "statistics": "統計數據", + "members": "成員", + "admins": "管理員", + "posts": "帖子", + "events": "事件", + "blockedUsers": "被阻止的用戶", + "requests": "请求", + "viewAll": "查看全部", + "upcomingEvents": "即将举办的活动", + "noUpcomingEvents": "没有即将举办的活动", + "latestPosts": "最新帖子", + "noPostsPresent": "没有帖子", + "membershipRequests": "会员申请", + "noMembershipRequests": "没有会员申请", + "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。" + }, + "organizationPeople": { + "title": "塔拉瓦成員", + "filterByName": "按名稱過濾", + "filterByLocation": "按位置過濾", + "filterByEvent": "按事件過濾", + "members": "成員", + "admins": "管理員", + "users": "用戶", + "searchName": "輸入名字", + "searchevent": "輸入事件", + "searchFirstName": "输入名字", + "searchLastName": "输入姓氏" + }, + "userListCard": { + "joined": "加入", + "addAdmin": "添加管理員", + "addedAsAdmin": "用戶被添加為管理員。", + "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。" + }, + "orgAdminListCard": { + "joined": "加入", + "remove": "消除", + "removeAdmin": "刪除管理員", + "removeAdminMsg": "您要刪除此管理員嗎?", + "no": "不", + "yes": "是的", + "adminRemoved": "管理員被刪除。", + "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。" + }, + "orgPeopleListCard": { + "joined": "加入", + "remove": "消除", + "removeMember": "刪除成員", + "removeMemberMsg": "您要刪除此成員嗎?", + "no": "不", + "yes": "是的", + "memberRemoved": "該會員已被刪除", + "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。" + }, + "organizationEvents": { + "title": "塔拉瓦事件", + "filterByTitle": "按標題過濾", + "filterByLocation": "按位置過濾", + "filterByDescription": "按描述過濾", + "events": "事件", + "addEvent": "添加事件", + "eventDetails": "活動詳情", + "eventTitle": "標題", + "description": "描述", + "location": "地點", + "startDate": "開始日期", + "endDate": "結束日期", + "startTime": "開始時間", + "endTime": "時間結束", + "allDay": "一整天", + "recurringEvent": "重複事件", + "isPublic": "是公開的", + "isRegistrable": "可註冊", + "createEvent": "創建事件", + "enterFilter": "輸入過濾器", + "enterTitle": "輸入標題", + "enterDescrip": "輸入說明", + "eventLocation": "輸入位置", + "eventCreated": "恭喜!事件已創建。", + "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。" + }, + "eventListCard": { + "location": "地點", + "on": "上", + "end": "結尾", + "deleteEvent": "刪除事件", + "deleteEventMsg": "您要刪除此活動嗎?", + "no": "不", + "yes": "是的", + "editEvent": "編輯事件", + "eventTitle": "標題", + "description": "描述", + "startTime": "開始時間", + "endTime": "時間結束", + "allDay": "一整天", + "recurringEvent": "重複事件", + "isPublic": "是公開的", + "isRegistrable": "可註冊", + "close": "關", + "updatePost": "更新帖子", + "eventDetails": "活動詳情", + "eventDeleted": "活动删除成功。", + "eventUpdated": "活動更新成功。", + "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。" + }, + "orgPost": { + "title": "塔拉瓦帖子", + "searchPost": "搜索帖子", + "posts": "帖子", + "createPost": "创建帖子", + "postDetails": "帖子详情", + "postTitle1": "填写帖子标题", + "postTitle": "标题", + "information": "信息", + "information1": "填写帖子信息", + "image": "帖子图片", + "video": "帖子视频", + "addPost": "添加帖子", + "searchTitle": "按标题搜索", + "searchText": "按文本搜索", + "ptitle": "帖子标题", + "postDes": "您想讨论什么?", + "Title": "标题", + "Text": "文本", + "cancel": "取消", + "searchBy": "按方式搜索", + "Oldest": "最旧的优先", + "Latest": "最新的优先", + "sortPost": "排序帖子", + "tag": "您的浏览器不支持视频标签" + }, + "postNotFound": { + "post": "郵政", + "not found!": "未找到!", + "organization": "組織", + "post not found!": "郵政 未找到!", + "organization not found!": "組織 未找到!" + }, + "userNotFound": { + "user": "用户", + "not found!": "未找到!", + "roles": "角色", + "user not found!": "找不到用户!", + "member not found!": "找不到会员!", + "admin not found!": "找不到管理员!", + "roles not found!": "找不到角色!" + }, + "orgPostCard": { + "author": "作者", + "imageURL": "图像链接", + "videoURL": "视频链接", + "edit": "编辑帖子", + "deletePost": "删除帖子", + "deletePostMsg": "您确定要删除此帖子吗?", + "no": "否", + "yes": "是", + "editPost": "编辑帖子", + "postTitle": "标题", + "information": "信息", + "image": "图片", + "video": "视频", + "close": "关闭", + "pin": "置顶帖子", + "updatePost": "更新帖子", + "postDeleted": "帖子成功删除。", + "postUpdated": "帖子成功更新。", + "tag": "您的浏览器不支持视频标签", + "talawaApiUnavailable": "Talawa-API 服务不可用。是否正在运行?还请检查您的网络连接。" + }, + "blockUnblockUser": { + "title": "塔拉瓦封鎖/解除封鎖用戶", + "pageName": "封锁/解封", + "searchByName": "按名稱搜索", + "listOfUsers": "發送垃圾郵件的用戶列表", + "name": "姓名", + "email": "電子郵件", + "block_unblock": "阻止/解除阻止", + "unblock": "解除封鎖", + "block": "堵塞", + "orgName": "輸入名字", + "blockedSuccessfully": "用戶被成功阻止", + "Un-BlockedSuccessfully": "用戶解封成功", + "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。", + "allMembers": "所有成员", + "blockedUsers": "被阻止的用户", + "searchByFirstName": "按名字搜索", + "searchByLastName": "按姓氏搜索", + "noResultsFoundFor": "未找到结果 ", + "noSpammerFound": "未发现垃圾邮件发送者" + }, + "forgotPassword": { + "title": "塔拉瓦忘記密碼", + "forgotPassword": "忘記密碼", + "registeredEmail": "註冊的電子郵件", + "getOtp": "獲取一次性密碼", + "enterOtp": "輸入一次性密碼", + "enterNewPassword": "輸入新密碼", + "cofirmNewPassword": "確認新密碼", + "changePassword": "更改密碼", + "backToLogin": "回到登錄", + "userOtp": "舉個例子。 12345", + "password": "密碼", + "emailNotRegistered": "電子郵件未註冊。", + "talawaApiUnavailable": "服務不可用。它正在運行嗎?還要檢查您的網絡連接。", + "errorSendingMail": "發送郵件時出錯。", + "passwordMismatches": "密碼和確認密碼不匹配。", + "passwordChanges": "密碼修改成功。", + "OTPsent": "已發送到您的註冊郵箱。" + }, + "pageNotFound": { + "title": "404 未找到", + "talawaAdmin": "塔拉瓦管理員", + "404": "404", + "notFoundMsg": "糟糕!找不到您請求的頁面!", + "backToHome": "回到家" + }, + "orgContribution": { + "title": "塔拉瓦貢獻", + "filterByName": "按名稱過濾", + "filterByTransId": "按 Trans.ID 過濾", + "recentStats": "最近的統計", + "contribution": "貢獻", + "orgname": "輸入名字", + "searchtransaction": "輸入交易編號" + }, + "contriStats": { + "recentContribution": "最近的貢獻", + "highestContribution": "最高貢獻", + "totalContribution": "總貢獻" + }, + "orgContriCards": { + "date": "日期", + "transactionId": "交易 ID", + "amount": "數量" + }, + "orgSettings": { + "title": "塔拉瓦設置", + "pageName": "设置", + "updateYourDetails": "更新您的詳細信息", + "updateYourPassword": "更新您的密碼", + "updateOrganization": "更新組織", + "seeRequest": "查看請求", + "settings": "設置", + "noData": "沒有數據", + "otherSettings": "其他设置", + "changeLanguage": "更改语言" + }, + "deleteOrg": { + "deleteOrganization": "删除组织", + "deleteSampleOrganization": "删除示范组织", + "deleteMsg": "您是否要删除此组织?", + "cancel": "取消", + "confirmDelete": "确认删除", + "longDelOrgMsg": "点击删除组织按钮,组织将被永久删除,包括其事件、标签和所有相关数据。" + }, + "userUpdate": { + "firstName": "名", + "lastName": "姓", + "email": "電子郵件", + "password": "密碼", + "appLanguageCode": "默认语言", + "userType": "用戶類型", + "admin": "行政", + "superAdmin": "超級管理員", + "displayImage": "顯示圖像", + "saveChanges": "保存更改", + "cancel": "取消" + }, + "userPasswordUpdate": { + "previousPassword": "以前的密碼", + "newPassword": "新密碼", + "confirmNewPassword": "確認新密碼", + "saveChanges": "保存更改", + "cancel": "取消" + }, + "orgDelete": { + "deleteOrg": "刪除組織" + }, + "membershipRequest": { + "joined": "加入", + "accept": "接受", + "reject": "拒絕", + "memberAdded": "它被接受", + "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。" + }, + "orgUpdate": { + "name": "姓名", + "description": "描述", + "location": "地點", + "displayImage": "顯示圖像", + "isPublic": "公开", + "isVisibleInSearch": "在搜索中可见", + "saveChanges": "保存更改", + "cancel": "取消", + "enterNameOrganization": "輸入組織名稱", + "successfulUpdated": "更新成功", + "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。" + }, + "addOnRegister": { + "addNew": "添新", + "addPlugin": "添加插件", + "pluginName": "插件名称", + "creatorName": "创建者姓名", + "pluginDesc": "插件说明", + "close": "关闭", + "register": "登记", + "pName": "例如:捐赠", + "cName": "例如:约翰·多伊", + "pDesc": "此插件启用 UI" + }, + "addOnStore": { + "title": "插件商店", + "searchName": "例如:捐赠", + "enable": "启用", + "disable": "残疾人", + "pHeading": "插件", + "install": "已安装", + "available": "可用的", + "pMessage": "插件不存在”", + "filter": "过滤器", + "search": "搜索" + }, + "addOnEntry": { + "enable": "启用", + "install": "安装", + "uninstall": "卸载" + }, + "memberDetail": { + "title": "用户详细信息", + "addAdmin": "添加管理员", + "organizations": "组织", + "events": "事件", + "role": "角色", + "email": "电子邮件", + "createdOn": "创建于", + "main": "主要的", + "firstName": "名字", + "lastName": "姓氏", + "memberOfOrganization": "组织成员", + "language": "语言", + "adminApproved": "管理员已批准", + "pluginCreationAllowed": "允许创建插件", + "joined": "加入", + "created": "创建", + "adminForOrganizations": "组织管理员", + "membershipRequests": "会员申请", + "adminForEvents": "事件管理员", + "addedAsAdmin": "用戶被添加為管理員。", + "talawaApiUnavailable": "Talawa-API 服務不可用。 請檢查您的網絡連接並稍等片刻。" + }, + "userLogin": { + "login": "登錄", + "forgotPassword": "忘記密碼 ?", + "loginIntoYourAccount": "登錄您的賬戶", + "emailAddress": "電子郵件地址", + "enterEmail": "輸入你的電子郵箱地址", + "password": "密碼", + "enterPassword": "輸入您的密碼", + "register": "登記", + "invalidDetailsMessage": "請輸入有效的電子郵件和密碼", + "notAuthorised": "對不起! 你沒有被授權!", + "invalidCredentials": "輸入的憑據不正確。 請輸入有效憑據。", + "talawaApiUnavailable": "Talawa-API 服務不可用。 請檢查您的網絡連接並稍等片刻。" + }, + "userRegister": { + "register": "登記", + "firstName": "名", + "enterFirstName": "輸入您的名字", + "lastName": "姓", + "enterLastName": "輸入您的姓氏", + "emailAddress": "電子郵件地址", + "enterEmail": "輸入你的電子郵箱地址", + "password": "密碼", + "enterPassword": "輸入您的密碼", + "confirmPassword": "確認密碼", + "enterConfirmPassword": "輸入您的密碼以確認", + "alreadyhaveAnAccount": "已有帳戶?", + "login": "登錄", + "afterRegister": "註冊成功。 請等待管理員批准您的請求。", + "passwordNotMatch": "密碼不匹配。 確認密碼並重試。", + "invalidDetailsMessage": "請輸入有效的詳細信息。", + "talawaApiUnavailable": "Talawa-API 服務不可用。 請檢查您的網絡連接並稍等片刻。" + }, + "userNavbar": { + "talawa": "塔拉瓦", + "home": "家", + "people": "人們", + "events": "活動", + "chat": "聊天", + "donate": "捐", + "myTasks": "我的任務", + "settings": "設置", + "language": "語言", + "logout": "登出", + "close": "關閉" + }, + "userOrganizations": { + "allOrganizations": "所有組織", + "joinedOrganizations": "加入組織", + "createdOrganizations": "創建的組織", + "search": "搜索", + "nothingToShow": "這裡沒有什麼可展示的。", + "selectOrganization": "選擇組織" + }, + "userSidebar": { + "yourOrganizations": "您的組織", + "noOrganizations": "您還沒有加入任何組織。", + "viewAll": "查看全部" + }, + "organizationSidebar": { + "viewAll": "查看全部", + "events": "事件", + "members": "成员", + "noEvents": "沒有可顯示的活動", + "noMembers": "沒有可顯示的會員" + }, + "postCard": { + "likes": "喜歡", + "comments": "評論" + }, + "home": { + "feed": "餵養", + "pinnedPosts": "查看固定帖子", + "somethingOnYourMind": "你有什麼心事嗎?" + }, + "settings": { + "profileSettings": "配置文件設置", + "firstName": "名", + "lastName": "姓", + "emailAddress": "電子郵件地址", + "updateImage": "更新圖片", + "save": "節省" + }, + "donate": { + "donateTo": "捐贈給", + "amount": "數量", + "yourPreviousDonations": "您之前的捐款", + "donate": "捐", + "nothingToShow": "這裡沒有什麼可顯示的。" + }, + "userEvents": { + "nothingToShow": "這裡沒有什麼可顯示的。", + "search": "搜索", + "createEvent": "創建事件", + "eventTitle": "活動標題", + "eventDescription": "活動說明", + "eventLocation": "活動地點", + "startDate": "選擇開始日期", + "endDate": "選擇結束日期", + "publicEvent": "公共活動", + "registerable": "可註冊", + "recurring": "再次發生的", + "startTime": "開始時間", + "endTime": "時間結束", + "cancel": "取消", + "create": "創造", + "listView": "列表顯示", + "calendarView": "日曆視圖", + "allDay": "整天", + "eventCreated": "活動已成功創建並發布。" + }, + "userEventCard": { + "location": "地點", + "starts": "開始", + "ends": "結束", + "creator": "創作者", + "alreadyRegistered": "已經註冊", + "register": "登記" + }, + "userTasks": { + "yourAssignedTasks": "您指派的任務", + "nothingToShow": "這裡沒有什麼可顯示的。" + }, + "userTaskCard": { + "description": "描述", + "deadline": "最後期限", + "created": "已創建", + "assignees": "受讓人", + "completed": "完全的", + "incomplete": "不完整", + "taskCompleted": "任務已完成", + "taskNotCompleted": "任務還沒完成", + "event": "事件", + "organization": "組織" + }, + "advertisement": { + "title": "广告", + "pHeading": "管理广告", + "activeAds": "活动广告", + "archievedAds": "已完成的广告活动", + "pMessage": "此广告活动没有相关广告。", + "delete": "删除" + }, + "userChat": { + "chat": "聊天", + "search": "搜尋", + "contacts": "聯絡方式" + }, + "userChatRoom": { + "selectContact": "選擇聯絡人開始對話", + "sendMessage": "傳訊息" + } +} diff --git a/public/logo192.png b/public/logo192.png deleted file mode 100644 index fc44b0a3796c0e0a64c3d858ca038bd4570465d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5347 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 X@eDJUQo;Ye2mwlRs { + throw err; +}); + +// Ensure environment variables are read. +import 'react-scripts/config/env.js'; + +// eslint-disable-next-line jest/no-jest-import +import jest from 'jest'; +import { execSync } from 'child_process'; + +const argv = process.argv.slice(2); + +function isInGitRepository() { + try { + execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' }); + return true; + } catch (e) { + return false; + } +} + +function isInMercurialRepository() { + try { + execSync('hg --cwd . root', { stdio: 'ignore' }); + return true; + } catch (e) { + return false; + } +} + +// Watch unless on CI or explicitly running all tests +if ( + !process.env.CI && + argv.indexOf('--watchAll') === -1 && + argv.indexOf('--watchAll=false') === -1 +) { + // https://github.com/facebook/create-react-app/issues/5210 + const hasSourceControl = isInGitRepository() || isInMercurialRepository(); + argv.push(hasSourceControl ? '--watch' : '--watchAll'); +} + +jest.run(argv); diff --git a/src/App.test.tsx b/src/App.test.tsx index 2a68616d98..f8db73a210 100644 --- a/src/App.test.tsx +++ b/src/App.test.tsx @@ -1,9 +1,94 @@ import React from 'react'; -import { render, screen } from '@testing-library/react'; +import { act, render, screen } from '@testing-library/react'; +import { Provider } from 'react-redux'; +import { MockedProvider } from '@apollo/react-testing'; +import { BrowserRouter } from 'react-router-dom'; +import { I18nextProvider } from 'react-i18next'; +import 'jest-location-mock'; import App from './App'; +import { store } from 'state/store'; +import { CHECK_AUTH } from 'GraphQl/Queries/Queries'; +import i18nForTest from './utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; -test('renders learn react link', () => { - render(); - const linkElement = screen.getByText(/learn react/i); - expect(linkElement).toBeInTheDocument(); +// Mock the modules for PieChart rendering as they require a trasformer being used (which is not done by Jest) +// These modules are used by the Feedback components +jest.mock('@mui/x-charts/PieChart', () => ({ + pieArcLabelClasses: jest.fn(), + PieChart: jest.fn().mockImplementation(() => <>Test), + pieArcClasses: jest.fn(), +})); + +const MOCKS = [ + { + request: { + query: CHECK_AUTH, + }, + result: { + data: { + checkAuth: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: 'john.jpg', + email: 'johndoe@gmail.com', + userType: 'SUPERADMIN', + }, + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); +const link2 = new StaticMockLink([], true); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Testing the App Component', () => { + test('Component should be rendered properly and user is loggedin', async () => { + render( + + + + + + + + + + ); + + await wait(); + + window.location.assign('/orglist'); + await wait(); + expect(window.location).toBeAt('/orglist'); + expect( + screen.getByText( + 'An open source application by Palisadoes Foundation volunteers' + ) + ).toBeTruthy(); + }); + + test('Component should be rendered properly and user is loggedout', async () => { + render( + + + + + + + + + + ); + + await wait(); + }); }); diff --git a/src/App.tsx b/src/App.tsx index c31b4f754d..3daf57b09c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,27 +1,140 @@ -import React from 'react'; -import './App.css'; +import React, { useEffect } from 'react'; +import { Route, Switch } from 'react-router-dom'; +import { useQuery } from '@apollo/client'; +import * as installedPlugins from 'components/plugins/index'; +import { CHECK_AUTH } from 'GraphQl/Queries/Queries'; +import SecuredRoute from 'components/SecuredRoute/SecuredRoute'; +import SecuredRouteForUser from 'components/UserPortal/SecuredRouteForUser/SecuredRouteForUser'; +import LoginPage from 'screens/LoginPage/LoginPage'; +import OrganizationEvents from 'screens/OrganizationEvents/OrganizationEvents'; +import OrganizationPeople from 'screens/OrganizationPeople/OrganizationPeople'; +import OrganizationDashboard from 'screens/OrganizationDashboard/OrganizationDashboard'; +import OrgContribution from 'screens/OrgContribution/OrgContribution'; +import OrgList from 'screens/OrgList/OrgList'; +import OrgPost from 'screens/OrgPost/OrgPost'; +import OrgSettings from 'screens/OrgSettings/OrgSettings'; +import PageNotFound from 'screens/PageNotFound/PageNotFound'; +import AddOnStore from 'components/AddOn/core/AddOnStore/AddOnStore'; +import ForgotPassword from 'screens/ForgotPassword/ForgotPassword'; +import Users from 'screens/Users/Users'; +import Requests from 'screens/Requests/Requests'; +import BlockUser from 'screens/BlockUser/BlockUser'; +import EventDashboard from 'screens/EventDashboard/EventDashboard'; +import MemberDetail from 'screens/MemberDetail/MemberDetail'; +import Loader from 'components/Loader/Loader'; -function App(): JSX.Element { - return ( - + } + ); + + if (loading) { + return ; + } + return ( + <> + + + + + + + + + + + + + + + + + {extraRoutes} + + + {/* User Portal Routes */} + + + + + + + + + {/* */} + + + + ); } -export default App; +export default app; diff --git a/src/Constant/constant.spec.ts b/src/Constant/constant.spec.ts new file mode 100644 index 0000000000..c194f51a10 --- /dev/null +++ b/src/Constant/constant.spec.ts @@ -0,0 +1,29 @@ +import { + AUTH_TOKEN, + BACKEND_URL, + RECAPTCHA_SITE_KEY, + REACT_APP_USE_RECAPTCHA, +} from './constant'; + +describe('constants', () => { + it('AUTH_TOKEN should be an empty string', () => { + expect(typeof AUTH_TOKEN).toEqual('string'); + expect(AUTH_TOKEN).toEqual(''); + }); + + it('BACKEND_URL should be equal to REACT_APP_TALAWA_URL environment variable', () => { + expect(BACKEND_URL).toEqual(process.env.REACT_APP_TALAWA_URL); + }); + + it('RECAPTCHA_SITE_KEY should be equal to REACT_APP_RECAPTCHA_SITE_KEY environment variable', () => { + expect(RECAPTCHA_SITE_KEY).toEqual( + process.env.REACT_APP_RECAPTCHA_SITE_KEY + ); + }); + + it('REACT_APP_USE_RECAPTCHA should be equal to REACT_APP_USE_RECAPTCHA environment variable', () => { + expect(REACT_APP_USE_RECAPTCHA).toEqual( + process.env.REACT_APP_USE_RECAPTCHA + ); + }); +}); diff --git a/src/Constant/constant.ts b/src/Constant/constant.ts new file mode 100644 index 0000000000..6582342ecd --- /dev/null +++ b/src/Constant/constant.ts @@ -0,0 +1,6 @@ +export const AUTH_TOKEN = ''; +export const BACKEND_URL = process.env.REACT_APP_TALAWA_URL; +export const RECAPTCHA_SITE_KEY = process.env.REACT_APP_RECAPTCHA_SITE_KEY; +export const REACT_APP_USE_RECAPTCHA = process.env.REACT_APP_USE_RECAPTCHA; +export const REACT_APP_BACKEND_WEBSOCKET_URL: string = + process.env.REACT_APP_BACKEND_WEBSOCKET_URL || ''; diff --git a/src/GraphQl/Mutations/mutations.ts b/src/GraphQl/Mutations/mutations.ts new file mode 100644 index 0000000000..720d655b53 --- /dev/null +++ b/src/GraphQl/Mutations/mutations.ts @@ -0,0 +1,742 @@ +import gql from 'graphql-tag'; + +// List of the mutations used in the code + +// to unblock the user + +export const UNBLOCK_USER_MUTATION = gql` + mutation UnblockUser($userId: ID!, $orgId: ID!) { + unblockUser(organizationId: $orgId, userId: $userId) { + _id + } + } +`; + +// to block the user + +export const BLOCK_USER_MUTATION = gql` + mutation BlockUser($userId: ID!, $orgId: ID!) { + blockUser(organizationId: $orgId, userId: $userId) { + _id + } + } +`; + +// to reject the organization request + +export const REJECT_ORGANIZATION_REQUEST_MUTATION = gql` + mutation RejectMembershipRequest($id: ID!) { + rejectMembershipRequest(membershipRequestId: $id) { + _id + } + } +`; + +// to accept the organization request + +export const ACCEPT_ORGANIZATION_REQUEST_MUTATION = gql` + mutation AcceptMembershipRequest($id: ID!) { + acceptMembershipRequest(membershipRequestId: $id) { + _id + } + } +`; + +// to update the organization details + +export const UPDATE_ORGANIZATION_MUTATION = gql` + mutation UpdateOrganization( + $id: ID! + $name: String + $description: String + $location: String + $isPublic: Boolean + $visibleInSearch: Boolean + $file: String + ) { + updateOrganization( + id: $id + data: { + name: $name + description: $description + isPublic: $isPublic + visibleInSearch: $visibleInSearch + location: $location + } + file: $file + ) { + _id + } + } +`; + +// to update the details of the user + +export const UPDATE_USER_MUTATION = gql` + mutation UpdateUserProfile( + $firstName: String + $lastName: String + $email: EmailAddress + $file: String + ) { + updateUserProfile( + data: { firstName: $firstName, lastName: $lastName, email: $email } + file: $file + ) { + _id + } + } +`; + +// to update the password of user + +export const UPDATE_USER_PASSWORD_MUTATION = gql` + mutation UpdateUserPassword( + $previousPassword: String! + $newPassword: String! + $confirmNewPassword: String! + ) { + updateUserPassword( + data: { + previousPassword: $previousPassword + newPassword: $newPassword + confirmNewPassword: $confirmNewPassword + } + ) { + _id + } + } +`; + +// to sign up in the talawa admin + +export const SIGNUP_MUTATION = gql` + mutation SignUp( + $firstName: String! + $lastName: String! + $email: EmailAddress! + $password: String! + ) { + signUp( + data: { + firstName: $firstName + lastName: $lastName + email: $email + password: $password + } + ) { + user { + _id + } + accessToken + refreshToken + } + } +`; + +// to login in the talawa admin + +export const LOGIN_MUTATION = gql` + mutation Login($email: EmailAddress!, $password: String!) { + login(data: { email: $email, password: $password }) { + user { + _id + userType + adminApproved + } + accessToken + refreshToken + } + } +`; + +// to get the refresh token + +export const REFRESH_TOKEN_MUTATION = gql` + mutation RefreshToken($refreshToken: String!) { + refreshToken(refreshToken: $refreshToken) { + refreshToken + accessToken + } + } +`; + +// to revoke a refresh token + +export const REVOKE_REFRESH_TOKEN = gql` + mutation RevokeRefreshTokenForUser { + revokeRefreshTokenForUser + } +`; + +// To verify the google recaptcha + +export const RECAPTCHA_MUTATION = gql` + mutation Recaptcha($recaptchaToken: String!) { + recaptcha(data: { recaptchaToken: $recaptchaToken }) + } +`; + +// to create the organization + +export const CREATE_ORGANIZATION_MUTATION = gql` + mutation CreateOrganization( + $description: String! + $location: String! + $name: String! + $visibleInSearch: Boolean! + $isPublic: Boolean! + $image: String + ) { + createOrganization( + data: { + description: $description + location: $location + name: $name + visibleInSearch: $visibleInSearch + isPublic: $isPublic + } + file: $image + ) { + _id + } + } +`; + +// to delete the organization + +export const DELETE_ORGANIZATION_MUTATION = gql` + mutation RemoveOrganization($id: ID!) { + removeOrganization(id: $id) { + _id + } + } +`; + +// to create the event by any organization + +export const CREATE_EVENT_MUTATION = gql` + mutation CreateEvent( + $title: String! + $description: String! + $recurring: Boolean! + $isPublic: Boolean! + $isRegisterable: Boolean! + $organizationId: ID! + $startDate: Date! + $endDate: Date + $allDay: Boolean! + $startTime: Time + $endTime: Time + $location: String + ) { + createEvent( + data: { + title: $title + description: $description + recurring: $recurring + isPublic: $isPublic + isRegisterable: $isRegisterable + organizationId: $organizationId + startDate: $startDate + endDate: $endDate + allDay: $allDay + startTime: $startTime + endTime: $endTime + location: $location + } + ) { + _id + } + } +`; + +// to delete any event by any organization + +export const DELETE_EVENT_MUTATION = gql` + mutation RemoveEvent($id: ID!) { + removeEvent(id: $id) { + _id + } + } +`; + +// to remove an admin from an organization + +export const REMOVE_ADMIN_MUTATION = gql` + mutation RemoveAdmin($orgid: ID!, $userid: ID!) { + removeAdmin(data: { organizationId: $orgid, userId: $userid }) { + _id + } + } +`; + +// to Remove member from an organization + +export const REMOVE_MEMBER_MUTATION = gql` + mutation RemoveMember($orgid: ID!, $userid: ID!) { + removeMember(data: { organizationId: $orgid, userId: $userid }) { + _id + } + } +`; + +// to add the admin + +export const ADD_ADMIN_MUTATION = gql` + mutation CreateAdmin($orgid: ID!, $userid: ID!) { + createAdmin(data: { organizationId: $orgid, userId: $userid }) { + _id + } + } +`; + +export const CREATE_POST_MUTATION = gql` + mutation CreatePost( + $text: String! + $title: String! + $imageUrl: URL + $videoUrl: URL + $organizationId: ID! + $file: String + ) { + createPost( + data: { + text: $text + title: $title + imageUrl: $imageUrl + videoUrl: $videoUrl + organizationId: $organizationId + } + file: $file + ) { + _id + } + } +`; + +export const DELETE_POST_MUTATION = gql` + mutation RemovePost($id: ID!) { + removePost(id: $id) { + _id + } + } +`; + +export const GENERATE_OTP_MUTATION = gql` + mutation Otp($email: EmailAddress!) { + otp(data: { email: $email }) { + otpToken + } + } +`; + +export const FORGOT_PASSWORD_MUTATION = gql` + mutation ForgotPassword( + $userOtp: String! + $newPassword: String! + $otpToken: String! + ) { + forgotPassword( + data: { + userOtp: $userOtp + newPassword: $newPassword + otpToken: $otpToken + } + ) + } +`; + +export const UPDATE_USERTYPE_MUTATION = gql` + mutation UpdateUserType($id: ID!, $userType: String!) { + updateUserType(data: { id: $id, userType: $userType }) + } +`; + +export const ACCEPT_ADMIN_MUTATION = gql` + mutation AcceptAdmin($id: ID!) { + acceptAdmin(id: $id) + } +`; + +export const REJECT_ADMIN_MUTATION = gql` + mutation RejectAdmin($id: ID!) { + rejectAdmin(id: $id) + } +`; + +/** + * @name UPDATE_INSTALL_STATUS_PLUGIN_MUTATION + * @description used to toggle `installStatus` (boolean value) of a Plugin + */ +export const UPDATE_INSTALL_STATUS_PLUGIN_MUTATION = gql` + mutation ($id: ID!, $orgId: ID!) { + updatePluginStatus(id: $id, orgId: $orgId) { + _id + pluginName + pluginCreatedBy + pluginDesc + uninstalledOrgs + } + } +`; + +/** + * @name UPDATE_ORG_STATUS_PLUGIN_MUTATION + * @description used `updatePluginStatus`to add or remove the current Organization the in the plugin list `uninstalledOrgs` + */ +export const UPDATE_ORG_STATUS_PLUGIN_MUTATION = gql` + mutation update_install_status_plugin_mutation($id: ID!, $orgId: ID!) { + updatePluginStatus(id: $id, orgId: $orgId) { + _id + pluginName + pluginCreatedBy + pluginDesc + uninstalledOrgs + } + } +`; + +/** + * @name ADD_PLUGIN_MUTATION + * @description used `createPlugin` to add new Plugin in database + */ +export const ADD_PLUGIN_MUTATION = gql` + mutation add_plugin_mutation( + $pluginName: String! + $pluginCreatedBy: String! + $pluginDesc: String! + ) { + createPlugin( + pluginName: $pluginName + pluginCreatedBy: $pluginCreatedBy + pluginDesc: $pluginDesc + ) { + _id + pluginName + pluginCreatedBy + pluginDesc + } + } +`; +export const ADD_ADVERTISEMENT_MUTATION = gql` + mutation ( + $orgId: ID! + $name: String! + $link: String! + $type: String! + $startDate: Date! + $endDate: Date! + ) { + createAdvertisement( + orgId: $orgId + name: $name + link: $link + type: $type + startDate: $startDate + endDate: $endDate + ) { + _id + } + } +`; +export const DELETE_ADVERTISEMENT_BY_ID = gql` + mutation ($id: ID!) { + deleteAdvertisementById(id: $id) { + success + } + } +`; +export const UPDATE_POST_MUTATION = gql` + mutation UpdatePost( + $id: ID! + $title: String + $text: String + $imageUrl: String + $videoUrl: String + ) { + updatePost( + id: $id + data: { + title: $title + text: $text + imageUrl: $imageUrl + videoUrl: $videoUrl + } + ) { + _id + } + } +`; + +export const UPDATE_EVENT_MUTATION = gql` + mutation UpdateEvent( + $id: ID! + $title: String! + $description: String! + $recurring: Boolean! + $isPublic: Boolean! + $isRegisterable: Boolean! + $allDay: Boolean! + $startTime: Time + $endTime: Time + $location: String + ) { + updateEvent( + id: $id + data: { + title: $title + description: $description + recurring: $recurring + isPublic: $isPublic + isRegisterable: $isRegisterable + allDay: $allDay + startTime: $startTime + endTime: $endTime + location: $location + } + ) { + _id + } + } +`; + +export const LIKE_POST = gql` + mutation likePost($postId: ID!) { + likePost(id: $postId) { + _id + } + } +`; + +export const UNLIKE_POST = gql` + mutation unlikePost($postId: ID!) { + unlikePost(id: $postId) { + _id + } + } +`; + +export const REGISTER_EVENT = gql` + mutation registerForEvent($eventId: ID!) { + registerForEvent(id: $eventId) { + _id + } + } +`; + +export const ADD_EVENT_PROJECT_MUTATION = gql` + mutation AddEventProject( + $title: String! + $description: String! + $eventId: ID! + ) { + createEventProject( + data: { title: $title, description: $description, eventId: $eventId } + ) { + _id + } + } +`; + +export const UPDATE_EVENT_PROJECT_MUTATION = gql` + mutation UpdateEventProject($title: String, $description: String, $id: ID!) { + updateEventProject( + id: $id + data: { title: $title, description: $description } + ) { + _id + } + } +`; + +export const DELETE_EVENT_PROJECT_MUTATION = gql` + mutation DeleteEventProject($id: ID!) { + removeEventProject(id: $id) { + _id + } + } +`; + +export const ADD_EVENT_PROJECT_TASK_MUTATION = gql` + mutation AddEventTask( + $title: String! + $description: String! + $projectId: ID! + $deadline: DateTime! + ) { + createTask( + eventProjectId: $projectId + data: { title: $title, description: $description, deadline: $deadline } + ) { + _id + } + } +`; + +export const UPDATE_EVENT_PROJECT_TASK_MUTATION = gql` + mutation UpdateEventTask( + $title: String! + $description: String! + $taskId: ID! + $deadline: DateTime! + $completed: Boolean! + ) { + updateTask( + id: $taskId + data: { + title: $title + description: $description + deadline: $deadline + completed: $completed + } + ) { + _id + } + } +`; + +export const DELETE_EVENT_TASK_MUTATION = gql` + mutation DeleteTask($id: ID!) { + removeTask(id: $id) { + _id + } + } +`; + +export const SET_TASK_VOLUNTEERS_MUTATION = gql` + mutation SetTaskVolunteers($id: ID!, $volunteers: [ID]!) { + setTaskVolunteers(id: $id, volunteers: $volunteers) { + _id + } + } +`; + +export const ADD_EVENT_ATTENDEE = gql` + mutation addEventAttendee($userId: ID!, $eventId: ID!) { + addEventAttendee(data: { userId: $userId, eventId: $eventId }) { + _id + } + } +`; + +export const REMOVE_EVENT_ATTENDEE = gql` + mutation removeEventAttendee($userId: ID!, $eventId: ID!) { + removeEventAttendee(data: { userId: $userId, eventId: $eventId }) { + _id + } + } +`; + +export const MARK_CHECKIN = gql` + mutation checkIn( + $userId: ID! + $eventId: ID! + $allotedRoom: String + $allotedSeat: String + ) { + checkIn( + data: { + userId: $userId + eventId: $eventId + allotedRoom: $allotedRoom + allotedSeat: $allotedSeat + } + ) { + _id + } + } +`; + +export const CREATE_COMMENT_POST = gql` + mutation createComment($comment: String!, $postId: ID!) { + createComment(data: { text: $comment }, postId: $postId) { + _id + creator { + _id + firstName + lastName + email + } + likeCount + likedBy { + _id + } + text + } + } +`; + +export const LIKE_COMMENT = gql` + mutation likeComment($commentId: ID!) { + likeComment(id: $commentId) { + _id + } + } +`; + +export const UNLIKE_COMMENT = gql` + mutation unlikeComment($commentId: ID!) { + unlikeComment(id: $commentId) { + _id + } + } +`; + +// Changes the role of a user in an organization +export const UPDATE_USER_ROLE_IN_ORG_MUTATION = gql` + mutation updateUserRoleInOrganization( + $organizationId: ID! + $userId: ID! + $role: String! + ) { + updateUserRoleInOrganization( + organizationId: $organizationId + userId: $userId + role: $role + ) { + _id + } + } +`; + +export const CREATE_SAMPLE_ORGANIZATION_MUTATION = gql` + mutation { + createSampleOrganization + } +`; + +export const REMOVE_SAMPLE_ORGANIZATION_MUTATION = gql` + mutation { + removeSampleOrganization + } +`; + +export const CREATE_DIRECT_CHAT = gql` + mutation createDirectChat($userIds: [ID!]!, $organizationId: ID!) { + createDirectChat( + data: { userIds: $userIds, organizationId: $organizationId } + ) { + _id + } + } +`; + +//Plugin WebSocket listner +export const PLUGIN_SUBSCRIPTION = gql` + subscription onPluginUpdate { + onPluginUpdate { + pluginName + _id + pluginDesc + uninstalledOrgs + } + } +`; +export const TOGGLE_PINNED_POST = gql` + mutation TogglePostPin($id: ID!) { + togglePostPin(id: $id) { + _id + } + } +`; diff --git a/src/GraphQl/Queries/Queries.ts b/src/GraphQl/Queries/Queries.ts new file mode 100644 index 0000000000..7bf99d48ee --- /dev/null +++ b/src/GraphQl/Queries/Queries.ts @@ -0,0 +1,845 @@ +import gql from 'graphql-tag'; + +//Query List + +// Check Auth + +export const CHECK_AUTH = gql` + query { + checkAuth { + _id + firstName + lastName + image + email + userType + } + } +`; + +// Query to take the Organization list +export const ORGANIZATION_LIST = gql` + query { + organizations { + _id + image + creator { + firstName + lastName + } + name + members { + _id + } + admins { + _id + } + createdAt + location + } + } +`; + +// Query to take the Organization list with filter option +export const ORGANIZATION_CONNECTION_LIST = gql` + query OrganizationsConnection($filter: String, $first: Int, $skip: Int) { + organizationsConnection( + where: { name_contains: $filter } + first: $first + skip: $skip + ) { + _id + image + creator { + firstName + lastName + } + name + members { + _id + } + admins { + _id + } + createdAt + location + } + } +`; + +// Query to take the User list +export const USER_LIST = gql` + query Users( + $firstName_contains: String + $lastName_contains: String + $skip: Int + $first: Int + ) { + users( + where: { + firstName_contains: $firstName_contains + lastName_contains: $lastName_contains + } + skip: $skip + first: $first + ) { + firstName + lastName + image + _id + email + userType + adminApproved + adminFor { + _id + } + createdAt + organizationsBlockedBy { + _id + name + image + location + createdAt + creator { + _id + firstName + lastName + image + email + createdAt + } + } + joinedOrganizations { + _id + name + image + location + createdAt + creator { + _id + firstName + lastName + image + email + createdAt + } + } + } + } +`; + +export const USER_LIST_REQUEST = gql` + query Users( + $firstName_contains: String + $lastName_contains: String + $first: Int + $skip: Int + $userType: String + $adminApproved: Boolean + ) { + users( + where: { + firstName_contains: $firstName_contains + lastName_contains: $lastName_contains + } + skip: $skip + first: $first + userType: $userType + adminApproved: $adminApproved + ) { + firstName + lastName + image + _id + email + userType + adminApproved + createdAt + } + } +`; + +export const EVENT_DETAILS = gql` + query Event($id: ID!) { + event(id: $id) { + _id + title + description + startDate + endDate + startTime + endTime + allDay + location + organization { + _id + members { + _id + firstName + lastName + } + } + attendees { + _id + } + projects { + _id + title + description + tasks { + _id + title + description + deadline + completed + volunteers { + _id + firstName + lastName + } + } + } + } + } +`; + +export const EVENT_ATTENDEES = gql` + query Event($id: ID!) { + event(id: $id) { + attendees { + _id + firstName + lastName + } + } + } +`; + +export const EVENT_CHECKINS = gql` + query eventCheckIns($id: ID!) { + event(id: $id) { + _id + attendeesCheckInStatus { + _id + user { + _id + firstName + lastName + } + checkIn { + _id + time + allotedRoom + allotedSeat + } + } + } + } +`; + +export const EVENT_FEEDBACKS = gql` + query eventFeedback($id: ID!) { + event(id: $id) { + _id + feedback { + _id + rating + review + } + averageFeedbackScore + } + } +`; + +// Query to take the Organization with data +export const ORGANIZATIONS_LIST = gql` + query Organizations($id: ID!) { + organizations(id: $id) { + _id + image + creator { + firstName + lastName + email + } + name + description + location + isPublic + visibleInSearch + members { + _id + firstName + lastName + email + } + admins { + _id + firstName + lastName + email + } + membershipRequests { + _id + user { + firstName + lastName + email + } + } + blockedUsers { + _id + firstName + lastName + email + } + } + } +`; + +// Query to take the Members of a particular organization + +export const MEMBERS_LIST = gql` + query Organizations($id: ID!) { + organizations(id: $id) { + _id + members { + _id + firstName + lastName + image + email + createdAt + organizationsBlockedBy { + _id + } + } + } + } +`; + +export const BLOCK_PAGE_MEMBER_LIST = gql` + query Organizations( + $orgId: ID! + $firstName_contains: String + $lastName_contains: String + ) { + organizationsMemberConnection( + orgId: $orgId + where: { + firstName_contains: $firstName_contains + lastName_contains: $lastName_contains + } + ) { + edges { + _id + firstName + lastName + email + organizationsBlockedBy { + _id + } + } + } + } +`; + +// Query to filter out all the members with the macthing query and a particular OrgId +export const ORGANIZATIONS_MEMBER_CONNECTION_LIST = gql` + query Organizations( + $orgId: ID! + $firstName_contains: String + $lastName_contains: String + $admin_for: ID + $event_title_contains: String + $first: Int + $skip: Int + ) { + organizationsMemberConnection( + orgId: $orgId + first: $first + skip: $skip + where: { + firstName_contains: $firstName_contains + lastName_contains: $lastName_contains + admin_for: $admin_for + event_title_contains: $event_title_contains + } + ) { + edges { + _id + firstName + lastName + image + email + createdAt + } + } + } +`; + +// To take the list of the oranization joined by a user +export const USER_ORGANIZATION_LIST = gql` + query User($id: ID!) { + user(id: $id) { + firstName + lastName + image + email + userType + adminFor { + _id + name + image + } + } + } +`; + +// To take the details of a user +export const USER_DETAILS = gql` + query User($id: ID!) { + user(id: $id) { + image + firstName + lastName + email + appLanguageCode + userType + pluginCreationAllowed + adminApproved + createdAt + adminFor { + _id + } + createdOrganizations { + _id + } + joinedOrganizations { + _id + } + organizationUserBelongsTo { + _id + } + organizationsBlockedBy { + _id + } + createdEvents { + _id + } + registeredEvents { + _id + } + eventAdmin { + _id + } + membershipRequests { + _id + } + } + } +`; + +// to take the organization event list +export const ORGANIZATION_EVENT_LIST = gql` + query EventsByOrganization($id: ID!) { + eventsByOrganization(id: $id) { + _id + title + description + startDate + endDate + location + startTime + endTime + allDay + recurring + isPublic + isRegisterable + } + } +`; + +export const ORGANIZATION_EVENT_CONNECTION_LIST = gql` + query EventsByOrganizationConnection( + $organization_id: ID! + $title_contains: String + $description_contains: String + $location_contains: String + $first: Int + $skip: Int + ) { + eventsByOrganizationConnection( + where: { + organization_id: $organization_id + title_contains: $title_contains + description_contains: $description_contains + location_contains: $location_contains + } + first: $first + skip: $skip + ) { + _id + title + description + startDate + endDate + location + startTime + endTime + allDay + recurring + isPublic + isRegisterable + } + } +`; + +export const ORGANIZATION_DONATION_CONNECTION_LIST = gql` + query GetDonationByOrgIdConnection( + $orgId: ID! + $id: ID + $name_of_user_contains: String + ) { + getDonationByOrgIdConnection( + orgId: $orgId + where: { id: $id, name_of_user_contains: $name_of_user_contains } + ) { + _id + nameOfUser + amount + userId + payPalId + } + } +`; + +// to take the list of the admins of a particular + +export const ADMIN_LIST = gql` + query Organizations($id: ID!) { + organizations(id: $id) { + _id + admins { + _id + firstName + lastName + image + email + createdAt + } + } + } +`; + +// to take the membership request + +export const MEMBERSHIP_REQUEST = gql` + query Organizations($id: ID!) { + organizations(id: $id) { + _id + membershipRequests { + _id + user { + _id + firstName + lastName + email + } + } + } + } +`; + +// display posts + +export const ORGANIZATION_POST_LIST = gql` + query PostsByOrganization($id: ID!) { + postsByOrganization(id: $id) { + _id + title + text + imageUrl + videoUrl + creator { + _id + firstName + lastName + email + } + createdAt + } + } +`; + +export const ORGANIZATION_POST_CONNECTION_LIST = gql` + query PostsByOrganizationConnection( + $id: ID! + $title_contains: String + $text_contains: String + ) { + postsByOrganizationConnection( + id: $id + where: { title_contains: $title_contains, text_contains: $text_contains } + orderBy: createdAt_DESC + ) { + edges { + _id + title + text + imageUrl + videoUrl + creator { + _id + firstName + lastName + email + } + createdAt + likeCount + commentCount + comments { + _id + creator { + _id + firstName + lastName + email + } + likeCount + likedBy { + _id + } + text + } + likedBy { + _id + firstName + lastName + } + } + } + } +`; + +export const USER_ORGANIZATION_CONNECTION = gql` + query organizationsConnection( + $first: Int + $skip: Int + $filter: String + $id: ID + ) { + organizationsConnection( + first: $first + skip: $skip + where: { name_contains: $filter, id: $id } + orderBy: name_ASC + ) { + _id + name + image + description + isPublic + creator { + firstName + lastName + } + } + } +`; + +export const USER_JOINED_ORGANIZATIONS = gql` + query UserJoinedOrganizations($id: ID!) { + users(where: { id: $id }) { + joinedOrganizations { + _id + name + description + image + } + } + } +`; + +export const USER_CREATED_ORGANIZATIONS = gql` + query UserJoinedOrganizations($id: ID!) { + users(where: { id: $id }) { + createdOrganizations { + _id + name + description + image + } + } + } +`; + +export const ORGANIZATION_ADMINS_LIST = gql` + query Organizations($id: ID!) { + organizations(id: $id) { + _id + admins { + _id + image + firstName + lastName + email + } + } + } +`; + +/** + * @name PLUGIN_GET + * @description used to fetch list of plugins + */ +export const PLUGIN_GET = gql` + query getPluginList { + getPlugins { + _id + pluginName + pluginCreatedBy + pluginDesc + uninstalledOrgs + } + } +`; +export const ADVERTISEMENTS_GET = gql` + query getAdvertisement { + getAdvertisements { + _id + name + type + orgId + link + endDate + startDate + } + } +`; +export const ORGANIZATION_EVENTS_CONNECTION = gql` + query EventsByOrganizationConnection( + $organization_id: ID! + $title_contains: String + $description_contains: String + $location_contains: String + $first: Int + $skip: Int + ) { + eventsByOrganizationConnection( + where: { + organization_id: $organization_id + title_contains: $title_contains + description_contains: $description_contains + location_contains: $location_contains + } + first: $first + skip: $skip + ) { + _id + title + description + startDate + endDate + location + startTime + endTime + allDay + recurring + isPublic + isRegisterable + creator { + _id + firstName + lastName + } + attendees { + _id + } + } + } +`; + +export const USER_TASKS_LIST = gql` + query User($id: ID!) { + user(id: $id) { + _id + assignedTasks { + _id + title + description + deadline + volunteers { + _id + firstName + lastName + email + } + createdAt + completed + event { + _id + title + organization { + _id + name + image + } + } + creator { + _id + firstName + lastName + } + } + } + } +`; + +export const DIRECT_CHATS_LIST = gql` + query DirectChatsByUserID($id: ID!) { + directChatsByUserID(id: $id) { + _id + creator { + _id + firstName + lastName + email + } + messages { + _id + createdAt + messageContent + receiver { + _id + firstName + lastName + email + } + sender { + _id + firstName + lastName + email + } + } + organization { + _id + name + } + users { + _id + firstName + lastName + email + image + } + } + } +`; + +export const IS_SAMPLE_ORGANIZATION_QUERY = gql` + query ($isSampleOrganizationId: ID!) { + isSampleOrganization(id: $isSampleOrganizationId) + } +`; diff --git a/src/assets/css/app.css b/src/assets/css/app.css new file mode 100644 index 0000000000..ae21cf9cb0 --- /dev/null +++ b/src/assets/css/app.css @@ -0,0 +1,12589 @@ +/*! + * Bootstrap v5.3.0 (https://getbootstrap.com/) + * Copyright 2011-2023 The Bootstrap Authors + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ +:root, +[data-bs-theme='light'] { + --bs-blue: #0d6efd; + --bs-indigo: #6610f2; + --bs-purple: #6f42c1; + --bs-pink: #d63384; + --bs-red: #dc3545; + --bs-orange: #fd7e14; + --bs-yellow: #ffc107; + --bs-green: #198754; + --bs-teal: #20c997; + --bs-cyan: #0dcaf0; + --bs-black: #000; + --bs-white: #fff; + --bs-gray: #6c757d; + --bs-gray-dark: #343a40; + --bs-gray-100: #f8f9fa; + --bs-gray-200: #e9ecef; + --bs-gray-300: #dee2e6; + --bs-gray-400: #ced4da; + --bs-gray-500: #adb5bd; + --bs-gray-600: #6c757d; + --bs-gray-700: #495057; + --bs-gray-800: #343a40; + --bs-gray-900: #212529; + --bs-primary: #31bb6b; + --bs-secondary: #707070; + --bs-success: #31bb6b; + --bs-info: #0dcaf0; + --bs-warning: #febc59; + --bs-danger: #dc3545; + --bs-light: #f8f9fa; + --bs-dark: #212529; + --bs-primary-rgb: 49, 187, 107; + --bs-secondary-rgb: 112, 112, 112; + --bs-success-rgb: 49, 187, 107; + --bs-info-rgb: 13, 202, 240; + --bs-warning-rgb: 254, 188, 89; + --bs-danger-rgb: 220, 53, 69; + --bs-light-rgb: 248, 249, 250; + --bs-dark-rgb: 33, 37, 41; + --bs-primary-text-emphasis: #144b2b; + --bs-secondary-text-emphasis: #2d2d2d; + --bs-success-text-emphasis: #144b2b; + --bs-info-text-emphasis: #055160; + --bs-warning-text-emphasis: #664b24; + --bs-danger-text-emphasis: #58151c; + --bs-light-text-emphasis: #495057; + --bs-dark-text-emphasis: #495057; + --bs-primary-bg-subtle: #d6f1e1; + --bs-secondary-bg-subtle: #e2e2e2; + --bs-success-bg-subtle: #d6f1e1; + --bs-info-bg-subtle: #cff4fc; + --bs-warning-bg-subtle: #fff2de; + --bs-danger-bg-subtle: #f8d7da; + --bs-light-bg-subtle: #fcfcfd; + --bs-dark-bg-subtle: #ced4da; + --bs-primary-border-subtle: #ade4c4; + --bs-secondary-border-subtle: #c6c6c6; + --bs-success-border-subtle: #ade4c4; + --bs-info-border-subtle: #9eeaf9; + --bs-warning-border-subtle: #ffe4bd; + --bs-danger-border-subtle: #f1aeb5; + --bs-light-border-subtle: #e9ecef; + --bs-dark-border-subtle: #adb5bd; + --bs-white-rgb: 255, 255, 255; + --bs-black-rgb: 0, 0, 0; + --bs-font-sans-serif: system-ui, -apple-system, 'Segoe UI', Roboto, + 'Helvetica Neue', 'Noto Sans', 'Liberation Sans', Arial, sans-serif, + 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + --bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, + 'Liberation Mono', 'Courier New', monospace; + --bs-gradient: linear-gradient( + 180deg, + rgba(255, 255, 255, 0.15), + rgba(255, 255, 255, 0) + ); + --bs-body-font-family: var(--bs-font-sans-serif); + --bs-body-font-size: 1rem; + --bs-body-font-weight: 400; + --bs-body-line-height: 1.5; + --bs-body-color: #212529; + --bs-body-color-rgb: 33, 37, 41; + --bs-body-bg: #fff; + --bs-body-bg-rgb: 255, 255, 255; + --bs-emphasis-color: #000; + --bs-emphasis-color-rgb: 0, 0, 0; + --bs-secondary-color: rgba(33, 37, 41, 0.75); + --bs-secondary-color-rgb: 33, 37, 41; + --bs-secondary-bg: #e9ecef; + --bs-secondary-bg-rgb: 233, 236, 239; + --bs-tertiary-color: rgba(33, 37, 41, 0.5); + --bs-tertiary-color-rgb: 33, 37, 41; + --bs-tertiary-bg: #f8f9fa; + --bs-tertiary-bg-rgb: 248, 249, 250; + --bs-heading-color: inherit; + --bs-link-color: #0d6efd; + --bs-link-color-rgb: 13, 110, 253; + --bs-link-decoration: none; + --bs-link-hover-color: #0a58ca; + --bs-link-hover-color-rgb: 10, 88, 202; + --bs-code-color: #d63384; + --bs-highlight-bg: #fff3cd; + --bs-border-width: 1px; + --bs-border-style: solid; + --bs-border-color: #dee2e6; + --bs-border-color-translucent: rgba(0, 0, 0, 0.175); + --bs-border-radius: 0.375rem; + --bs-border-radius-sm: 0.25rem; + --bs-border-radius-lg: 0.5rem; + --bs-border-radius-xl: 1rem; + --bs-border-radius-xxl: 2rem; + --bs-border-radius-2xl: var(--bs-border-radius-xxl); + --bs-border-radius-pill: 50rem; + --bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); + --bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075); + --bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175); + --bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075); + --bs-focus-ring-width: 0.25rem; + --bs-focus-ring-opacity: 0.25; + --bs-focus-ring-color: rgba(49, 187, 107, 0.25); + --bs-form-valid-color: #31bb6b; + --bs-form-valid-border-color: #31bb6b; + --bs-form-invalid-color: #dc3545; + --bs-form-invalid-border-color: #dc3545; +} + +[data-bs-theme='dark'] { + color-scheme: dark; + --bs-body-color: #adb5bd; + --bs-body-color-rgb: 173, 181, 189; + --bs-body-bg: #212529; + --bs-body-bg-rgb: 33, 37, 41; + --bs-emphasis-color: #fff; + --bs-emphasis-color-rgb: 255, 255, 255; + --bs-secondary-color: rgba(173, 181, 189, 0.75); + --bs-secondary-color-rgb: 173, 181, 189; + --bs-secondary-bg: #343a40; + --bs-secondary-bg-rgb: 52, 58, 64; + --bs-tertiary-color: rgba(173, 181, 189, 0.5); + --bs-tertiary-color-rgb: 173, 181, 189; + --bs-tertiary-bg: #2b3035; + --bs-tertiary-bg-rgb: 43, 48, 53; + --bs-primary-text-emphasis: #83d6a6; + --bs-secondary-text-emphasis: darkgray; + --bs-success-text-emphasis: #83d6a6; + --bs-info-text-emphasis: #6edff6; + --bs-warning-text-emphasis: #fed79b; + --bs-danger-text-emphasis: #ea868f; + --bs-light-text-emphasis: #f8f9fa; + --bs-dark-text-emphasis: #dee2e6; + --bs-primary-bg-subtle: #0a2515; + --bs-secondary-bg-subtle: #161616; + --bs-success-bg-subtle: #0a2515; + --bs-info-bg-subtle: #032830; + --bs-warning-bg-subtle: #332612; + --bs-danger-bg-subtle: #2c0b0e; + --bs-light-bg-subtle: #343a40; + --bs-dark-bg-subtle: #1a1d20; + --bs-primary-border-subtle: #1d7040; + --bs-secondary-border-subtle: #434343; + --bs-success-border-subtle: #1d7040; + --bs-info-border-subtle: #087990; + --bs-warning-border-subtle: #987135; + --bs-danger-border-subtle: #842029; + --bs-light-border-subtle: #495057; + --bs-dark-border-subtle: #343a40; + --bs-heading-color: inherit; + --bs-link-color: #83d6a6; + --bs-link-hover-color: #9cdeb8; + --bs-link-color-rgb: 131, 214, 166; + --bs-link-hover-color-rgb: 156, 222, 184; + --bs-code-color: #e685b5; + --bs-border-color: #495057; + --bs-border-color-translucent: rgba(255, 255, 255, 0.15); + --bs-form-valid-color: #75b798; + --bs-form-valid-border-color: #75b798; + --bs-form-invalid-color: #ea868f; + --bs-form-invalid-border-color: #ea868f; +} + +*, +*::before, +*::after { + box-sizing: border-box; +} + +@media (prefers-reduced-motion: no-preference) { + :root { + scroll-behavior: smooth; + } +} + +body { + margin: 0; + font-family: var(--bs-body-font-family); + font-size: var(--bs-body-font-size); + font-weight: var(--bs-body-font-weight); + line-height: var(--bs-body-line-height); + color: var(--bs-body-color); + text-align: var(--bs-body-text-align); + background-color: var(--bs-body-bg); + -webkit-text-size-adjust: 100%; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} + +hr { + margin: 1rem 0; + color: inherit; + border: 0; + border-top: var(--bs-border-width) solid; + opacity: 0.25; +} + +h1, +.h1, +h2, +.h2, +h3, +.h3, +h4, +.h4, +h5, +.h5, +h6, +.h6 { + margin-top: 0; + margin-bottom: 0.5rem; + font-weight: 500; + line-height: 1.2; + color: var(--bs-heading-color); +} + +h1, +.h1 { + font-size: calc(1.375rem + 1.5vw); +} +@media (min-width: 1200px) { + h1, + .h1 { + font-size: 2.5rem; + } +} + +h2, +.h2 { + font-size: calc(1.325rem + 0.9vw); +} +@media (min-width: 1200px) { + h2, + .h2 { + font-size: 2rem; + } +} + +h3, +.h3 { + font-size: calc(1.3rem + 0.6vw); +} +@media (min-width: 1200px) { + h3, + .h3 { + font-size: 1.75rem; + } +} + +h4, +.h4 { + font-size: calc(1.275rem + 0.3vw); +} +@media (min-width: 1200px) { + h4, + .h4 { + font-size: 1.5rem; + } +} + +h5, +.h5 { + font-size: 1.25rem; +} + +h6, +.h6 { + font-size: 1rem; +} + +p { + margin-top: 0; + margin-bottom: 1rem; +} + +abbr[title] { + text-decoration: underline dotted; + cursor: help; + text-decoration-skip-ink: none; +} + +address { + margin-bottom: 1rem; + font-style: normal; + line-height: inherit; +} + +ol, +ul { + padding-left: 2rem; +} + +ol, +ul, +dl { + margin-top: 0; + margin-bottom: 1rem; +} + +ol ol, +ul ul, +ol ul, +ul ol { + margin-bottom: 0; +} + +dt { + font-weight: 700; +} + +dd { + margin-bottom: 0.5rem; + margin-left: 0; +} + +blockquote { + margin: 0 0 1rem; +} + +b, +strong { + font-weight: bolder; +} + +small, +.small { + font-size: 0.875em; +} + +mark, +.mark { + padding: 0.1875em; + background-color: var(--bs-highlight-bg); +} + +sub, +sup { + position: relative; + font-size: 0.75em; + line-height: 0; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +a { + color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1)); + text-decoration: none; +} +a:hover { + --bs-link-color-rgb: var(--bs-link-hover-color-rgb); +} + +a:not([href]):not([class]), +a:not([href]):not([class]):hover { + color: inherit; + text-decoration: none; +} + +pre, +code, +kbd, +samp { + font-family: var(--bs-font-monospace); + font-size: 1em; +} + +pre { + display: block; + margin-top: 0; + margin-bottom: 1rem; + overflow: auto; + font-size: 0.875em; +} +pre code { + font-size: inherit; + color: inherit; + word-break: normal; +} + +code { + font-size: 0.875em; + color: var(--bs-code-color); + word-wrap: break-word; +} +a > code { + color: inherit; +} + +kbd { + padding: 0.1875rem 0.375rem; + font-size: 0.875em; + color: var(--bs-body-bg); + background-color: var(--bs-body-color); + border-radius: 0.25rem; +} +kbd kbd { + padding: 0; + font-size: 1em; +} + +figure { + margin: 0 0 1rem; +} + +img, +svg { + vertical-align: middle; +} + +table { + caption-side: bottom; + border-collapse: collapse; +} + +caption { + padding-top: 0.5rem; + padding-bottom: 0.5rem; + color: var(--bs-secondary-color); + text-align: left; +} + +th { + text-align: inherit; + text-align: -webkit-match-parent; +} + +thead, +tbody, +tfoot, +tr, +td, +th { + border-color: inherit; + border-style: solid; + border-width: 0; +} + +label { + display: inline-block; +} + +button { + border-radius: 0; +} + +button:focus:not(:focus-visible) { + outline: 0; +} + +input, +button, +select, +optgroup, +textarea { + margin: 0; + font-family: inherit; + font-size: inherit; + line-height: inherit; +} + +button, +select { + text-transform: none; +} + +[role='button'] { + cursor: pointer; +} + +select { + word-wrap: normal; +} +select:disabled { + opacity: 1; +} + +[list]:not([type='date']):not([type='datetime-local']):not([type='month']):not( + [type='week'] + ):not([type='time'])::-webkit-calendar-picker-indicator { + display: none !important; +} + +button, +[type='button'], +[type='reset'], +[type='submit'] { + -webkit-appearance: button; +} +button:not(:disabled), +[type='button']:not(:disabled), +[type='reset']:not(:disabled), +[type='submit']:not(:disabled) { + cursor: pointer; +} + +::-moz-focus-inner { + padding: 0; + border-style: none; +} + +textarea { + resize: vertical; +} + +fieldset { + min-width: 0; + padding: 0; + margin: 0; + border: 0; +} + +legend { + float: left; + width: 100%; + padding: 0; + margin-bottom: 0.5rem; + font-size: calc(1.275rem + 0.3vw); + line-height: inherit; +} +@media (min-width: 1200px) { + legend { + font-size: 1.5rem; + } +} +legend + * { + clear: left; +} + +::-webkit-datetime-edit-fields-wrapper, +::-webkit-datetime-edit-text, +::-webkit-datetime-edit-minute, +::-webkit-datetime-edit-hour-field, +::-webkit-datetime-edit-day-field, +::-webkit-datetime-edit-month-field, +::-webkit-datetime-edit-year-field { + padding: 0; +} + +::-webkit-inner-spin-button { + height: auto; +} + +[type='search'] { + outline-offset: -2px; + -webkit-appearance: textfield; +} + +/* rtl:raw: +[type="tel"], +[type="url"], +[type="email"], +[type="number"] { + direction: ltr; +} +*/ +::-webkit-search-decoration { + -webkit-appearance: none; +} + +::-webkit-color-swatch-wrapper { + padding: 0; +} + +::file-selector-button { + font: inherit; + -webkit-appearance: button; +} + +output { + display: inline-block; +} + +iframe { + border: 0; +} + +summary { + display: list-item; + cursor: pointer; +} + +progress { + vertical-align: baseline; +} + +[hidden] { + display: none !important; +} + +.lead { + font-size: 1.25rem; + font-weight: 300; +} + +.display-1 { + font-size: calc(1.625rem + 4.5vw); + font-weight: 300; + line-height: 1.2; +} +@media (min-width: 1200px) { + .display-1 { + font-size: 5rem; + } +} + +.display-2 { + font-size: calc(1.575rem + 3.9vw); + font-weight: 300; + line-height: 1.2; +} +@media (min-width: 1200px) { + .display-2 { + font-size: 4.5rem; + } +} + +.display-3 { + font-size: calc(1.525rem + 3.3vw); + font-weight: 300; + line-height: 1.2; +} +@media (min-width: 1200px) { + .display-3 { + font-size: 4rem; + } +} + +.display-4 { + font-size: calc(1.475rem + 2.7vw); + font-weight: 300; + line-height: 1.2; +} +@media (min-width: 1200px) { + .display-4 { + font-size: 3.5rem; + } +} + +.display-5 { + font-size: calc(1.425rem + 2.1vw); + font-weight: 300; + line-height: 1.2; +} +@media (min-width: 1200px) { + .display-5 { + font-size: 3rem; + } +} + +.display-6 { + font-size: calc(1.375rem + 1.5vw); + font-weight: 300; + line-height: 1.2; +} +@media (min-width: 1200px) { + .display-6 { + font-size: 2.5rem; + } +} + +.list-unstyled { + padding-left: 0; + list-style: none; +} + +.list-inline { + padding-left: 0; + list-style: none; +} + +.list-inline-item { + display: inline-block; +} +.list-inline-item:not(:last-child) { + margin-right: 0.5rem; +} + +.initialism { + font-size: 0.875em; + text-transform: uppercase; +} + +.blockquote { + margin-bottom: 1rem; + font-size: 1.25rem; +} +.blockquote > :last-child { + margin-bottom: 0; +} + +.blockquote-footer { + margin-top: -1rem; + margin-bottom: 1rem; + font-size: 0.875em; + color: #6c757d; +} +.blockquote-footer::before { + content: '\2014\00A0'; +} + +.img-fluid { + max-width: 100%; + height: auto; +} + +.img-thumbnail { + padding: 0.25rem; + background-color: var(--bs-body-bg); + border: var(--bs-border-width) solid var(--bs-border-color); + border-radius: var(--bs-border-radius); + max-width: 100%; + height: auto; +} + +.figure { + display: inline-block; +} + +.figure-img { + margin-bottom: 0.5rem; + line-height: 1; +} + +.figure-caption { + font-size: 0.875em; + color: var(--bs-secondary-color); +} + +.container, +.container-fluid, +.container-sm, +.container-md, +.container-lg, +.container-xl, +.container-xxl { + --bs-gutter-x: 1.5rem; + --bs-gutter-y: 0; + width: 100%; + padding-right: calc(var(--bs-gutter-x) * 0.5); + padding-left: calc(var(--bs-gutter-x) * 0.5); + margin-right: auto; + margin-left: auto; +} + +@media (min-width: 576px) { + .container, + .container-sm { + max-width: 540px; + } +} + +@media (min-width: 768px) { + .container, + .container-sm, + .container-md { + max-width: 720px; + } +} + +@media (min-width: 992px) { + .container, + .container-sm, + .container-md, + .container-lg { + max-width: 960px; + } +} + +@media (min-width: 1200px) { + .container, + .container-sm, + .container-md, + .container-lg, + .container-xl { + max-width: 1140px; + } +} + +@media (min-width: 1400px) { + .container, + .container-sm, + .container-md, + .container-lg, + .container-xl, + .container-xxl { + max-width: 1320px; + } +} + +:root { + --bs-breakpoint-xs: 0; + --bs-breakpoint-sm: 576px; + --bs-breakpoint-md: 768px; + --bs-breakpoint-lg: 992px; + --bs-breakpoint-xl: 1200px; + --bs-breakpoint-xxl: 1400px; +} + +.row { + --bs-gutter-x: 1.5rem; + --bs-gutter-y: 0; + display: flex; + flex-wrap: wrap; + margin-top: calc(-1 * var(--bs-gutter-y)); + margin-right: calc(-0.5 * var(--bs-gutter-x)); + margin-left: calc(-0.5 * var(--bs-gutter-x)); +} +.row > * { + flex-shrink: 0; + width: 100%; + max-width: 100%; + padding-right: calc(var(--bs-gutter-x) * 0.5); + padding-left: calc(var(--bs-gutter-x) * 0.5); + margin-top: var(--bs-gutter-y); +} + +.col { + flex: 1 0 0%; +} + +.row-cols-auto > * { + flex: 0 0 auto; + width: auto; +} + +.row-cols-1 > * { + flex: 0 0 auto; + width: 100%; +} + +.row-cols-2 > * { + flex: 0 0 auto; + width: 50%; +} + +.row-cols-3 > * { + flex: 0 0 auto; + width: 33.33333%; +} + +.row-cols-4 > * { + flex: 0 0 auto; + width: 25%; +} + +.row-cols-5 > * { + flex: 0 0 auto; + width: 20%; +} + +.row-cols-6 > * { + flex: 0 0 auto; + width: 16.66667%; +} + +.col-auto { + flex: 0 0 auto; + width: auto; +} + +.col-1 { + flex: 0 0 auto; + width: 8.33333%; +} + +.col-2 { + flex: 0 0 auto; + width: 16.66667%; +} + +.col-3 { + flex: 0 0 auto; + width: 25%; +} + +.col-4 { + flex: 0 0 auto; + width: 33.33333%; +} + +.col-5 { + flex: 0 0 auto; + width: 41.66667%; +} + +.col-6 { + flex: 0 0 auto; + width: 50%; +} + +.col-7 { + flex: 0 0 auto; + width: 58.33333%; +} + +.col-8 { + flex: 0 0 auto; + width: 66.66667%; +} + +.col-9 { + flex: 0 0 auto; + width: 75%; +} + +.col-10 { + flex: 0 0 auto; + width: 83.33333%; +} + +.col-11 { + flex: 0 0 auto; + width: 91.66667%; +} + +.col-12 { + flex: 0 0 auto; + width: 100%; +} + +.offset-1 { + margin-left: 8.33333%; +} + +.offset-2 { + margin-left: 16.66667%; +} + +.offset-3 { + margin-left: 25%; +} + +.offset-4 { + margin-left: 33.33333%; +} + +.offset-5 { + margin-left: 41.66667%; +} + +.offset-6 { + margin-left: 50%; +} + +.offset-7 { + margin-left: 58.33333%; +} + +.offset-8 { + margin-left: 66.66667%; +} + +.offset-9 { + margin-left: 75%; +} + +.offset-10 { + margin-left: 83.33333%; +} + +.offset-11 { + margin-left: 91.66667%; +} + +.g-0, +.gx-0 { + --bs-gutter-x: 0; +} + +.g-0, +.gy-0 { + --bs-gutter-y: 0; +} + +.g-1, +.gx-1 { + --bs-gutter-x: 0.25rem; +} + +.g-1, +.gy-1 { + --bs-gutter-y: 0.25rem; +} + +.g-2, +.gx-2 { + --bs-gutter-x: 0.5rem; +} + +.g-2, +.gy-2 { + --bs-gutter-y: 0.5rem; +} + +.g-3, +.gx-3 { + --bs-gutter-x: 1rem; +} + +.g-3, +.gy-3 { + --bs-gutter-y: 1rem; +} + +.g-4, +.gx-4 { + --bs-gutter-x: 1.5rem; +} + +.g-4, +.gy-4 { + --bs-gutter-y: 1.5rem; +} + +.g-5, +.gx-5 { + --bs-gutter-x: 3rem; +} + +.g-5, +.gy-5 { + --bs-gutter-y: 3rem; +} + +@media (min-width: 576px) { + .col-sm { + flex: 1 0 0%; + } + .row-cols-sm-auto > * { + flex: 0 0 auto; + width: auto; + } + .row-cols-sm-1 > * { + flex: 0 0 auto; + width: 100%; + } + .row-cols-sm-2 > * { + flex: 0 0 auto; + width: 50%; + } + .row-cols-sm-3 > * { + flex: 0 0 auto; + width: 33.33333%; + } + .row-cols-sm-4 > * { + flex: 0 0 auto; + width: 25%; + } + .row-cols-sm-5 > * { + flex: 0 0 auto; + width: 20%; + } + .row-cols-sm-6 > * { + flex: 0 0 auto; + width: 16.66667%; + } + .col-sm-auto { + flex: 0 0 auto; + width: auto; + } + .col-sm-1 { + flex: 0 0 auto; + width: 8.33333%; + } + .col-sm-2 { + flex: 0 0 auto; + width: 16.66667%; + } + .col-sm-3 { + flex: 0 0 auto; + width: 25%; + } + .col-sm-4 { + flex: 0 0 auto; + width: 33.33333%; + } + .col-sm-5 { + flex: 0 0 auto; + width: 41.66667%; + } + .col-sm-6 { + flex: 0 0 auto; + width: 50%; + } + .col-sm-7 { + flex: 0 0 auto; + width: 58.33333%; + } + .col-sm-8 { + flex: 0 0 auto; + width: 66.66667%; + } + .col-sm-9 { + flex: 0 0 auto; + width: 75%; + } + .col-sm-10 { + flex: 0 0 auto; + width: 83.33333%; + } + .col-sm-11 { + flex: 0 0 auto; + width: 91.66667%; + } + .col-sm-12 { + flex: 0 0 auto; + width: 100%; + } + .offset-sm-0 { + margin-left: 0; + } + .offset-sm-1 { + margin-left: 8.33333%; + } + .offset-sm-2 { + margin-left: 16.66667%; + } + .offset-sm-3 { + margin-left: 25%; + } + .offset-sm-4 { + margin-left: 33.33333%; + } + .offset-sm-5 { + margin-left: 41.66667%; + } + .offset-sm-6 { + margin-left: 50%; + } + .offset-sm-7 { + margin-left: 58.33333%; + } + .offset-sm-8 { + margin-left: 66.66667%; + } + .offset-sm-9 { + margin-left: 75%; + } + .offset-sm-10 { + margin-left: 83.33333%; + } + .offset-sm-11 { + margin-left: 91.66667%; + } + .g-sm-0, + .gx-sm-0 { + --bs-gutter-x: 0; + } + .g-sm-0, + .gy-sm-0 { + --bs-gutter-y: 0; + } + .g-sm-1, + .gx-sm-1 { + --bs-gutter-x: 0.25rem; + } + .g-sm-1, + .gy-sm-1 { + --bs-gutter-y: 0.25rem; + } + .g-sm-2, + .gx-sm-2 { + --bs-gutter-x: 0.5rem; + } + .g-sm-2, + .gy-sm-2 { + --bs-gutter-y: 0.5rem; + } + .g-sm-3, + .gx-sm-3 { + --bs-gutter-x: 1rem; + } + .g-sm-3, + .gy-sm-3 { + --bs-gutter-y: 1rem; + } + .g-sm-4, + .gx-sm-4 { + --bs-gutter-x: 1.5rem; + } + .g-sm-4, + .gy-sm-4 { + --bs-gutter-y: 1.5rem; + } + .g-sm-5, + .gx-sm-5 { + --bs-gutter-x: 3rem; + } + .g-sm-5, + .gy-sm-5 { + --bs-gutter-y: 3rem; + } +} + +@media (min-width: 768px) { + .col-md { + flex: 1 0 0%; + } + .row-cols-md-auto > * { + flex: 0 0 auto; + width: auto; + } + .row-cols-md-1 > * { + flex: 0 0 auto; + width: 100%; + } + .row-cols-md-2 > * { + flex: 0 0 auto; + width: 50%; + } + .row-cols-md-3 > * { + flex: 0 0 auto; + width: 33.33333%; + } + .row-cols-md-4 > * { + flex: 0 0 auto; + width: 25%; + } + .row-cols-md-5 > * { + flex: 0 0 auto; + width: 20%; + } + .row-cols-md-6 > * { + flex: 0 0 auto; + width: 16.66667%; + } + .col-md-auto { + flex: 0 0 auto; + width: auto; + } + .col-md-1 { + flex: 0 0 auto; + width: 8.33333%; + } + .col-md-2 { + flex: 0 0 auto; + width: 16.66667%; + } + .col-md-3 { + flex: 0 0 auto; + width: 25%; + } + .col-md-4 { + flex: 0 0 auto; + width: 33.33333%; + } + .col-md-5 { + flex: 0 0 auto; + width: 41.66667%; + } + .col-md-6 { + flex: 0 0 auto; + width: 50%; + } + .col-md-7 { + flex: 0 0 auto; + width: 58.33333%; + } + .col-md-8 { + flex: 0 0 auto; + width: 66.66667%; + } + .col-md-9 { + flex: 0 0 auto; + width: 75%; + } + .col-md-10 { + flex: 0 0 auto; + width: 83.33333%; + } + .col-md-11 { + flex: 0 0 auto; + width: 91.66667%; + } + .col-md-12 { + flex: 0 0 auto; + width: 100%; + } + .offset-md-0 { + margin-left: 0; + } + .offset-md-1 { + margin-left: 8.33333%; + } + .offset-md-2 { + margin-left: 16.66667%; + } + .offset-md-3 { + margin-left: 25%; + } + .offset-md-4 { + margin-left: 33.33333%; + } + .offset-md-5 { + margin-left: 41.66667%; + } + .offset-md-6 { + margin-left: 50%; + } + .offset-md-7 { + margin-left: 58.33333%; + } + .offset-md-8 { + margin-left: 66.66667%; + } + .offset-md-9 { + margin-left: 75%; + } + .offset-md-10 { + margin-left: 83.33333%; + } + .offset-md-11 { + margin-left: 91.66667%; + } + .g-md-0, + .gx-md-0 { + --bs-gutter-x: 0; + } + .g-md-0, + .gy-md-0 { + --bs-gutter-y: 0; + } + .g-md-1, + .gx-md-1 { + --bs-gutter-x: 0.25rem; + } + .g-md-1, + .gy-md-1 { + --bs-gutter-y: 0.25rem; + } + .g-md-2, + .gx-md-2 { + --bs-gutter-x: 0.5rem; + } + .g-md-2, + .gy-md-2 { + --bs-gutter-y: 0.5rem; + } + .g-md-3, + .gx-md-3 { + --bs-gutter-x: 1rem; + } + .g-md-3, + .gy-md-3 { + --bs-gutter-y: 1rem; + } + .g-md-4, + .gx-md-4 { + --bs-gutter-x: 1.5rem; + } + .g-md-4, + .gy-md-4 { + --bs-gutter-y: 1.5rem; + } + .g-md-5, + .gx-md-5 { + --bs-gutter-x: 3rem; + } + .g-md-5, + .gy-md-5 { + --bs-gutter-y: 3rem; + } +} + +@media (min-width: 992px) { + .col-lg { + flex: 1 0 0%; + } + .row-cols-lg-auto > * { + flex: 0 0 auto; + width: auto; + } + .row-cols-lg-1 > * { + flex: 0 0 auto; + width: 100%; + } + .row-cols-lg-2 > * { + flex: 0 0 auto; + width: 50%; + } + .row-cols-lg-3 > * { + flex: 0 0 auto; + width: 33.33333%; + } + .row-cols-lg-4 > * { + flex: 0 0 auto; + width: 25%; + } + .row-cols-lg-5 > * { + flex: 0 0 auto; + width: 20%; + } + .row-cols-lg-6 > * { + flex: 0 0 auto; + width: 16.66667%; + } + .col-lg-auto { + flex: 0 0 auto; + width: auto; + } + .col-lg-1 { + flex: 0 0 auto; + width: 8.33333%; + } + .col-lg-2 { + flex: 0 0 auto; + width: 16.66667%; + } + .col-lg-3 { + flex: 0 0 auto; + width: 25%; + } + .col-lg-4 { + flex: 0 0 auto; + width: 33.33333%; + } + .col-lg-5 { + flex: 0 0 auto; + width: 41.66667%; + } + .col-lg-6 { + flex: 0 0 auto; + width: 50%; + } + .col-lg-7 { + flex: 0 0 auto; + width: 58.33333%; + } + .col-lg-8 { + flex: 0 0 auto; + width: 66.66667%; + } + .col-lg-9 { + flex: 0 0 auto; + width: 75%; + } + .col-lg-10 { + flex: 0 0 auto; + width: 83.33333%; + } + .col-lg-11 { + flex: 0 0 auto; + width: 91.66667%; + } + .col-lg-12 { + flex: 0 0 auto; + width: 100%; + } + .offset-lg-0 { + margin-left: 0; + } + .offset-lg-1 { + margin-left: 8.33333%; + } + .offset-lg-2 { + margin-left: 16.66667%; + } + .offset-lg-3 { + margin-left: 25%; + } + .offset-lg-4 { + margin-left: 33.33333%; + } + .offset-lg-5 { + margin-left: 41.66667%; + } + .offset-lg-6 { + margin-left: 50%; + } + .offset-lg-7 { + margin-left: 58.33333%; + } + .offset-lg-8 { + margin-left: 66.66667%; + } + .offset-lg-9 { + margin-left: 75%; + } + .offset-lg-10 { + margin-left: 83.33333%; + } + .offset-lg-11 { + margin-left: 91.66667%; + } + .g-lg-0, + .gx-lg-0 { + --bs-gutter-x: 0; + } + .g-lg-0, + .gy-lg-0 { + --bs-gutter-y: 0; + } + .g-lg-1, + .gx-lg-1 { + --bs-gutter-x: 0.25rem; + } + .g-lg-1, + .gy-lg-1 { + --bs-gutter-y: 0.25rem; + } + .g-lg-2, + .gx-lg-2 { + --bs-gutter-x: 0.5rem; + } + .g-lg-2, + .gy-lg-2 { + --bs-gutter-y: 0.5rem; + } + .g-lg-3, + .gx-lg-3 { + --bs-gutter-x: 1rem; + } + .g-lg-3, + .gy-lg-3 { + --bs-gutter-y: 1rem; + } + .g-lg-4, + .gx-lg-4 { + --bs-gutter-x: 1.5rem; + } + .g-lg-4, + .gy-lg-4 { + --bs-gutter-y: 1.5rem; + } + .g-lg-5, + .gx-lg-5 { + --bs-gutter-x: 3rem; + } + .g-lg-5, + .gy-lg-5 { + --bs-gutter-y: 3rem; + } +} + +@media (min-width: 1200px) { + .col-xl { + flex: 1 0 0%; + } + .row-cols-xl-auto > * { + flex: 0 0 auto; + width: auto; + } + .row-cols-xl-1 > * { + flex: 0 0 auto; + width: 100%; + } + .row-cols-xl-2 > * { + flex: 0 0 auto; + width: 50%; + } + .row-cols-xl-3 > * { + flex: 0 0 auto; + width: 33.33333%; + } + .row-cols-xl-4 > * { + flex: 0 0 auto; + width: 25%; + } + .row-cols-xl-5 > * { + flex: 0 0 auto; + width: 20%; + } + .row-cols-xl-6 > * { + flex: 0 0 auto; + width: 16.66667%; + } + .col-xl-auto { + flex: 0 0 auto; + width: auto; + } + .col-xl-1 { + flex: 0 0 auto; + width: 8.33333%; + } + .col-xl-2 { + flex: 0 0 auto; + width: 16.66667%; + } + .col-xl-3 { + flex: 0 0 auto; + width: 25%; + } + .col-xl-4 { + flex: 0 0 auto; + width: 33.33333%; + } + .col-xl-5 { + flex: 0 0 auto; + width: 41.66667%; + } + .col-xl-6 { + flex: 0 0 auto; + width: 50%; + } + .col-xl-7 { + flex: 0 0 auto; + width: 58.33333%; + } + .col-xl-8 { + flex: 0 0 auto; + width: 66.66667%; + } + .col-xl-9 { + flex: 0 0 auto; + width: 75%; + } + .col-xl-10 { + flex: 0 0 auto; + width: 83.33333%; + } + .col-xl-11 { + flex: 0 0 auto; + width: 91.66667%; + } + .col-xl-12 { + flex: 0 0 auto; + width: 100%; + } + .offset-xl-0 { + margin-left: 0; + } + .offset-xl-1 { + margin-left: 8.33333%; + } + .offset-xl-2 { + margin-left: 16.66667%; + } + .offset-xl-3 { + margin-left: 25%; + } + .offset-xl-4 { + margin-left: 33.33333%; + } + .offset-xl-5 { + margin-left: 41.66667%; + } + .offset-xl-6 { + margin-left: 50%; + } + .offset-xl-7 { + margin-left: 58.33333%; + } + .offset-xl-8 { + margin-left: 66.66667%; + } + .offset-xl-9 { + margin-left: 75%; + } + .offset-xl-10 { + margin-left: 83.33333%; + } + .offset-xl-11 { + margin-left: 91.66667%; + } + .g-xl-0, + .gx-xl-0 { + --bs-gutter-x: 0; + } + .g-xl-0, + .gy-xl-0 { + --bs-gutter-y: 0; + } + .g-xl-1, + .gx-xl-1 { + --bs-gutter-x: 0.25rem; + } + .g-xl-1, + .gy-xl-1 { + --bs-gutter-y: 0.25rem; + } + .g-xl-2, + .gx-xl-2 { + --bs-gutter-x: 0.5rem; + } + .g-xl-2, + .gy-xl-2 { + --bs-gutter-y: 0.5rem; + } + .g-xl-3, + .gx-xl-3 { + --bs-gutter-x: 1rem; + } + .g-xl-3, + .gy-xl-3 { + --bs-gutter-y: 1rem; + } + .g-xl-4, + .gx-xl-4 { + --bs-gutter-x: 1.5rem; + } + .g-xl-4, + .gy-xl-4 { + --bs-gutter-y: 1.5rem; + } + .g-xl-5, + .gx-xl-5 { + --bs-gutter-x: 3rem; + } + .g-xl-5, + .gy-xl-5 { + --bs-gutter-y: 3rem; + } +} + +@media (min-width: 1400px) { + .col-xxl { + flex: 1 0 0%; + } + .row-cols-xxl-auto > * { + flex: 0 0 auto; + width: auto; + } + .row-cols-xxl-1 > * { + flex: 0 0 auto; + width: 100%; + } + .row-cols-xxl-2 > * { + flex: 0 0 auto; + width: 50%; + } + .row-cols-xxl-3 > * { + flex: 0 0 auto; + width: 33.33333%; + } + .row-cols-xxl-4 > * { + flex: 0 0 auto; + width: 25%; + } + .row-cols-xxl-5 > * { + flex: 0 0 auto; + width: 20%; + } + .row-cols-xxl-6 > * { + flex: 0 0 auto; + width: 16.66667%; + } + .col-xxl-auto { + flex: 0 0 auto; + width: auto; + } + .col-xxl-1 { + flex: 0 0 auto; + width: 8.33333%; + } + .col-xxl-2 { + flex: 0 0 auto; + width: 16.66667%; + } + .col-xxl-3 { + flex: 0 0 auto; + width: 25%; + } + .col-xxl-4 { + flex: 0 0 auto; + width: 33.33333%; + } + .col-xxl-5 { + flex: 0 0 auto; + width: 41.66667%; + } + .col-xxl-6 { + flex: 0 0 auto; + width: 50%; + } + .col-xxl-7 { + flex: 0 0 auto; + width: 58.33333%; + } + .col-xxl-8 { + flex: 0 0 auto; + width: 66.66667%; + } + .col-xxl-9 { + flex: 0 0 auto; + width: 75%; + } + .col-xxl-10 { + flex: 0 0 auto; + width: 83.33333%; + } + .col-xxl-11 { + flex: 0 0 auto; + width: 91.66667%; + } + .col-xxl-12 { + flex: 0 0 auto; + width: 100%; + } + .offset-xxl-0 { + margin-left: 0; + } + .offset-xxl-1 { + margin-left: 8.33333%; + } + .offset-xxl-2 { + margin-left: 16.66667%; + } + .offset-xxl-3 { + margin-left: 25%; + } + .offset-xxl-4 { + margin-left: 33.33333%; + } + .offset-xxl-5 { + margin-left: 41.66667%; + } + .offset-xxl-6 { + margin-left: 50%; + } + .offset-xxl-7 { + margin-left: 58.33333%; + } + .offset-xxl-8 { + margin-left: 66.66667%; + } + .offset-xxl-9 { + margin-left: 75%; + } + .offset-xxl-10 { + margin-left: 83.33333%; + } + .offset-xxl-11 { + margin-left: 91.66667%; + } + .g-xxl-0, + .gx-xxl-0 { + --bs-gutter-x: 0; + } + .g-xxl-0, + .gy-xxl-0 { + --bs-gutter-y: 0; + } + .g-xxl-1, + .gx-xxl-1 { + --bs-gutter-x: 0.25rem; + } + .g-xxl-1, + .gy-xxl-1 { + --bs-gutter-y: 0.25rem; + } + .g-xxl-2, + .gx-xxl-2 { + --bs-gutter-x: 0.5rem; + } + .g-xxl-2, + .gy-xxl-2 { + --bs-gutter-y: 0.5rem; + } + .g-xxl-3, + .gx-xxl-3 { + --bs-gutter-x: 1rem; + } + .g-xxl-3, + .gy-xxl-3 { + --bs-gutter-y: 1rem; + } + .g-xxl-4, + .gx-xxl-4 { + --bs-gutter-x: 1.5rem; + } + .g-xxl-4, + .gy-xxl-4 { + --bs-gutter-y: 1.5rem; + } + .g-xxl-5, + .gx-xxl-5 { + --bs-gutter-x: 3rem; + } + .g-xxl-5, + .gy-xxl-5 { + --bs-gutter-y: 3rem; + } +} + +.table { + --bs-table-color-type: initial; + --bs-table-bg-type: initial; + --bs-table-color-state: initial; + --bs-table-bg-state: initial; + --bs-table-color: var(--bs-body-color); + --bs-table-bg: var(--bs-body-bg); + --bs-table-border-color: var(--bs-border-color); + --bs-table-accent-bg: transparent; + --bs-table-striped-color: var(--bs-body-color); + --bs-table-striped-bg: rgba(0, 0, 0, 0.05); + --bs-table-active-color: var(--bs-body-color); + --bs-table-active-bg: rgba(0, 0, 0, 0.1); + --bs-table-hover-color: var(--bs-body-color); + --bs-table-hover-bg: rgba(0, 0, 0, 0.075); + width: 100%; + margin-bottom: 1rem; + vertical-align: top; + border-color: var(--bs-table-border-color); +} +.table > :not(caption) > * > * { + padding: 0.5rem 0.5rem; + color: var( + --bs-table-color-state, + var(--bs-table-color-type, var(--bs-table-color)) + ); + background-color: var(--bs-table-bg); + border-bottom-width: var(--bs-border-width); + box-shadow: inset 0 0 0 9999px + var(--bs-table-bg-state, var(--bs-table-bg-type, var(--bs-table-accent-bg))); +} +.table > tbody { + vertical-align: inherit; +} +.table > thead { + vertical-align: bottom; +} + +.table-group-divider { + border-top: calc(var(--bs-border-width) * 2) solid currentcolor; +} + +.caption-top { + caption-side: top; +} + +.table-sm > :not(caption) > * > * { + padding: 0.25rem 0.25rem; +} + +.table-bordered > :not(caption) > * { + border-width: var(--bs-border-width) 0; +} +.table-bordered > :not(caption) > * > * { + border-width: 0 var(--bs-border-width); +} + +.table-borderless > :not(caption) > * > * { + border-bottom-width: 0; +} + +.table-borderless > :not(:first-child) { + border-top-width: 0; +} + +.table-striped > tbody > tr:nth-of-type(odd) > * { + --bs-table-color-type: var(--bs-table-striped-color); + --bs-table-bg-type: var(--bs-table-striped-bg); +} + +.table-striped-columns > :not(caption) > tr > :nth-child(even) { + --bs-table-color-type: var(--bs-table-striped-color); + --bs-table-bg-type: var(--bs-table-striped-bg); +} + +.table-active { + --bs-table-color-state: var(--bs-table-active-color); + --bs-table-bg-state: var(--bs-table-active-bg); +} + +.table-hover > tbody > tr:hover > * { + --bs-table-color-state: var(--bs-table-hover-color); + --bs-table-bg-state: var(--bs-table-hover-bg); +} + +.table-primary { + --bs-table-color: #000; + --bs-table-bg: #d6f1e1; + --bs-table-border-color: #c1d9cb; + --bs-table-striped-bg: #cbe5d6; + --bs-table-striped-color: #000; + --bs-table-active-bg: #c1d9cb; + --bs-table-active-color: #000; + --bs-table-hover-bg: #c6dfd0; + --bs-table-hover-color: #000; + color: var(--bs-table-color); + border-color: var(--bs-table-border-color); +} + +.table-secondary { + --bs-table-color: #000; + --bs-table-bg: #e2e2e2; + --bs-table-border-color: #cbcbcb; + --bs-table-striped-bg: #d7d7d7; + --bs-table-striped-color: #000; + --bs-table-active-bg: #cbcbcb; + --bs-table-active-color: #000; + --bs-table-hover-bg: #d1d1d1; + --bs-table-hover-color: #000; + color: var(--bs-table-color); + border-color: var(--bs-table-border-color); +} + +.table-success { + --bs-table-color: #000; + --bs-table-bg: #d6f1e1; + --bs-table-border-color: #c1d9cb; + --bs-table-striped-bg: #cbe5d6; + --bs-table-striped-color: #000; + --bs-table-active-bg: #c1d9cb; + --bs-table-active-color: #000; + --bs-table-hover-bg: #c6dfd0; + --bs-table-hover-color: #000; + color: var(--bs-table-color); + border-color: var(--bs-table-border-color); +} + +.table-info { + --bs-table-color: #000; + --bs-table-bg: #cff4fc; + --bs-table-border-color: #badce3; + --bs-table-striped-bg: #c5e8ef; + --bs-table-striped-color: #000; + --bs-table-active-bg: #badce3; + --bs-table-active-color: #000; + --bs-table-hover-bg: #bfe2e9; + --bs-table-hover-color: #000; + color: var(--bs-table-color); + border-color: var(--bs-table-border-color); +} + +.table-warning { + --bs-table-color: #000; + --bs-table-bg: #fff2de; + --bs-table-border-color: #e6dac8; + --bs-table-striped-bg: #f2e6d3; + --bs-table-striped-color: #000; + --bs-table-active-bg: #e6dac8; + --bs-table-active-color: #000; + --bs-table-hover-bg: #ece0cd; + --bs-table-hover-color: #000; + color: var(--bs-table-color); + border-color: var(--bs-table-border-color); +} + +.table-danger { + --bs-table-color: #000; + --bs-table-bg: #f8d7da; + --bs-table-border-color: #dfc2c4; + --bs-table-striped-bg: #eccccf; + --bs-table-striped-color: #000; + --bs-table-active-bg: #dfc2c4; + --bs-table-active-color: #000; + --bs-table-hover-bg: #e5c7ca; + --bs-table-hover-color: #000; + color: var(--bs-table-color); + border-color: var(--bs-table-border-color); +} + +.table-light { + --bs-table-color: #000; + --bs-table-bg: #f8f9fa; + --bs-table-border-color: #dfe0e1; + --bs-table-striped-bg: #ecedee; + --bs-table-striped-color: #000; + --bs-table-active-bg: #dfe0e1; + --bs-table-active-color: #000; + --bs-table-hover-bg: #e5e6e7; + --bs-table-hover-color: #000; + color: var(--bs-table-color); + border-color: var(--bs-table-border-color); +} + +.table-dark { + --bs-table-color: #fff; + --bs-table-bg: #212529; + --bs-table-border-color: #373b3e; + --bs-table-striped-bg: #2c3034; + --bs-table-striped-color: #fff; + --bs-table-active-bg: #373b3e; + --bs-table-active-color: #fff; + --bs-table-hover-bg: #323539; + --bs-table-hover-color: #fff; + color: var(--bs-table-color); + border-color: var(--bs-table-border-color); +} + +.table-responsive { + overflow-x: auto; + -webkit-overflow-scrolling: touch; +} + +@media (max-width: 575.98px) { + .table-responsive-sm { + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } +} + +@media (max-width: 767.98px) { + .table-responsive-md { + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } +} + +@media (max-width: 991.98px) { + .table-responsive-lg { + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } +} + +@media (max-width: 1199.98px) { + .table-responsive-xl { + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } +} + +@media (max-width: 1399.98px) { + .table-responsive-xxl { + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } +} + +.form-label { + margin-bottom: 0.5rem; +} + +.col-form-label { + padding-top: 0.7rem; + padding-bottom: 0.7rem; + margin-bottom: 0; + font-size: inherit; + line-height: 1.5; +} + +.col-form-label-lg { + padding-top: 0.5rem; + padding-bottom: 0.5rem; + font-size: 1.25rem; +} + +.col-form-label-sm { + padding-top: 0.25rem; + padding-bottom: 0.25rem; + font-size: 0.875rem; +} + +.form-text { + margin-top: 0.25rem; + font-size: 0.875em; + color: var(--bs-secondary-color); +} + +.form-control { + display: block; + width: 100%; + padding: 0.7rem 1rem; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: var(--bs-body-color); + background-color: #f2f2f2; + background-clip: padding-box; + border: 0 solid var(--bs-border-color); + appearance: none; + border-radius: var(--bs-border-radius); + transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .form-control { + transition: none; + } +} +.form-control[type='file'] { + overflow: hidden; +} +.form-control[type='file']:not(:disabled):not([readonly]) { + cursor: pointer; +} +.form-control:focus { + color: var(--bs-body-color); + background-color: #f2f2f2; + border-color: #98ddb5; + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(49, 187, 107, 0.25); +} +.form-control::-webkit-date-and-time-value { + min-width: 85px; + height: 1.5em; + margin: 0; +} +.form-control::-webkit-datetime-edit { + display: block; + padding: 0; +} +.form-control::placeholder { + color: var(--bs-secondary-color); + opacity: 1; +} +.form-control:disabled { + background-color: var(--bs-secondary-bg); + opacity: 1; +} +.form-control::file-selector-button { + padding: 0.7rem 1rem; + margin: -0.7rem -1rem; + margin-inline-end: 1rem; + color: var(--bs-body-color); + background-color: var(--bs-tertiary-bg); + pointer-events: none; + border-color: inherit; + border-style: solid; + border-width: 0; + border-inline-end-width: 0; + border-radius: 0; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, + border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .form-control::file-selector-button { + transition: none; + } +} +.form-control:hover:not(:disabled):not([readonly])::file-selector-button { + background-color: var(--bs-secondary-bg); +} + +.form-control-plaintext { + display: block; + width: 100%; + padding: 0.7rem 0; + margin-bottom: 0; + line-height: 1.5; + color: var(--bs-body-color); + background-color: transparent; + border: solid transparent; + border-width: 0 0; +} +.form-control-plaintext:focus { + outline: 0; +} +.form-control-plaintext.form-control-sm, +.form-control-plaintext.form-control-lg { + padding-right: 0; + padding-left: 0; +} + +.form-control-sm { + min-height: calc(1.5em + 0.5rem + calc(0 * 2)); + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + border-radius: var(--bs-border-radius-sm); +} +.form-control-sm::file-selector-button { + padding: 0.25rem 0.5rem; + margin: -0.25rem -0.5rem; + margin-inline-end: 0.5rem; +} + +.form-control-lg { + min-height: calc(1.5em + 1rem + calc(0 * 2)); + padding: 0.5rem 1rem; + font-size: 1.25rem; + border-radius: var(--bs-border-radius-lg); +} +.form-control-lg::file-selector-button { + padding: 0.5rem 1rem; + margin: -0.5rem -1rem; + margin-inline-end: 1rem; +} + +textarea.form-control { + min-height: calc(1.5em + 1.4rem + calc(0 * 2)); +} + +textarea.form-control-sm { + min-height: calc(1.5em + 0.5rem + calc(0 * 2)); +} + +textarea.form-control-lg { + min-height: calc(1.5em + 1rem + calc(0 * 2)); +} + +.form-control-color { + width: 3rem; + height: calc(1.5em + 1.4rem + calc(0 * 2)); + padding: 0.7rem; +} +.form-control-color:not(:disabled):not([readonly]) { + cursor: pointer; +} +.form-control-color::-moz-color-swatch { + border: 0 !important; + border-radius: var(--bs-border-radius); +} +.form-control-color::-webkit-color-swatch { + border: 0 !important; + border-radius: var(--bs-border-radius); +} +.form-control-color.form-control-sm { + height: calc(1.5em + 0.5rem + calc(0 * 2)); +} +.form-control-color.form-control-lg { + height: calc(1.5em + 1rem + calc(0 * 2)); +} + +.form-select { + --bs-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"); + display: block; + width: 100%; + padding: 0.7rem 3rem 0.7rem 1rem; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: var(--bs-body-color); + background-color: #f2f2f2; + background-image: var(--bs-form-select-bg-img), + var(--bs-form-select-bg-icon, none); + background-repeat: no-repeat; + background-position: right 1rem center; + background-size: 16px 12px; + border: 0 solid var(--bs-border-color); + border-radius: var(--bs-border-radius); + transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + appearance: none; +} +@media (prefers-reduced-motion: reduce) { + .form-select { + transition: none; + } +} +.form-select:focus { + border-color: #98ddb5; + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(49, 187, 107, 0.25); +} +.form-select[multiple], +.form-select[size]:not([size='1']) { + padding-right: 1rem; + background-image: none; +} +.form-select:disabled { + background-color: var(--bs-secondary-bg); +} +.form-select:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 var(--bs-body-color); +} + +.form-select-sm { + padding-top: 0.25rem; + padding-bottom: 0.25rem; + padding-left: 0.5rem; + font-size: 0.875rem; + border-radius: var(--bs-border-radius-sm); +} + +.form-select-lg { + padding-top: 0.5rem; + padding-bottom: 0.5rem; + padding-left: 1rem; + font-size: 1.25rem; + border-radius: var(--bs-border-radius-lg); +} + +[data-bs-theme='dark'] .form-select { + --bs-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23adb5bd' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"); +} + +.form-check { + display: block; + min-height: 1.5rem; + padding-left: 1.5em; + margin-bottom: 0.125rem; +} +.form-check .form-check-input { + float: left; + margin-left: -1.5em; +} + +.form-check-reverse { + padding-right: 1.5em; + padding-left: 0; + text-align: right; +} +.form-check-reverse .form-check-input { + float: right; + margin-right: -1.5em; + margin-left: 0; +} + +.form-check-input { + --bs-form-check-bg: #f2f2f2; + width: 1em; + height: 1em; + margin-top: 0.25em; + vertical-align: top; + background-color: var(--bs-form-check-bg); + background-image: var(--bs-form-check-bg-image); + background-repeat: no-repeat; + background-position: center; + background-size: contain; + border: var(--bs-border-width) solid var(--bs-border-color); + appearance: none; + print-color-adjust: exact; +} +.form-check-input[type='checkbox'] { + border-radius: 0.25em; +} +.form-check-input[type='radio'] { + border-radius: 50%; +} +.form-check-input:active { + filter: brightness(90%); +} +.form-check-input:focus { + border-color: #98ddb5; + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(49, 187, 107, 0.25); +} +.form-check-input:checked { + background-color: #31bb6b; + border-color: #31bb6b; +} +.form-check-input:checked[type='checkbox'] { + --bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e"); +} +.form-check-input:checked[type='radio'] { + --bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e"); +} +.form-check-input[type='checkbox']:indeterminate { + background-color: #31bb6b; + border-color: #31bb6b; + --bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e"); +} +.form-check-input:disabled { + pointer-events: none; + filter: none; + opacity: 0.5; +} +.form-check-input[disabled] ~ .form-check-label, +.form-check-input:disabled ~ .form-check-label { + cursor: default; + opacity: 0.5; +} + +.form-switch { + padding-left: 2.5em; +} +.form-switch .form-check-input { + --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e"); + width: 2em; + margin-left: -2.5em; + background-image: var(--bs-form-switch-bg); + background-position: left center; + border-radius: 2em; + transition: background-position 0.15s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .form-switch .form-check-input { + transition: none; + } +} +.form-switch .form-check-input:focus { + --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2398ddb5'/%3e%3c/svg%3e"); +} +.form-switch .form-check-input:checked { + background-position: right center; + --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e"); +} +.form-switch.form-check-reverse { + padding-right: 2.5em; + padding-left: 0; +} +.form-switch.form-check-reverse .form-check-input { + margin-right: -2.5em; + margin-left: 0; +} + +.form-check-inline { + display: inline-block; + margin-right: 1rem; +} + +.btn-check { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} +.btn-check[disabled] + .btn, +.btn-check:disabled + .btn { + pointer-events: none; + filter: none; + opacity: 0.65; +} + +[data-bs-theme='dark'] + .form-switch + .form-check-input:not(:checked):not(:focus) { + --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%28255, 255, 255, 0.25%29'/%3e%3c/svg%3e"); +} + +.form-range { + width: 100%; + height: 1.5rem; + padding: 0; + background-color: transparent; + appearance: none; +} +.form-range:focus { + outline: 0; +} +.form-range:focus::-webkit-slider-thumb { + box-shadow: 0 0 0 1px #fff, 0 0 0 0.25rem rgba(49, 187, 107, 0.25); +} +.form-range:focus::-moz-range-thumb { + box-shadow: 0 0 0 1px #fff, 0 0 0 0.25rem rgba(49, 187, 107, 0.25); +} +.form-range::-moz-focus-outer { + border: 0; +} +.form-range::-webkit-slider-thumb { + width: 1rem; + height: 1rem; + margin-top: -0.25rem; + background-color: #31bb6b; + border: 0; + border-radius: 1rem; + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, + box-shadow 0.15s ease-in-out; + appearance: none; +} +@media (prefers-reduced-motion: reduce) { + .form-range::-webkit-slider-thumb { + transition: none; + } +} +.form-range::-webkit-slider-thumb:active { + background-color: #c1ebd3; +} +.form-range::-webkit-slider-runnable-track { + width: 100%; + height: 0.5rem; + color: transparent; + cursor: pointer; + background-color: var(--bs-tertiary-bg); + border-color: transparent; + border-radius: 1rem; +} +.form-range::-moz-range-thumb { + width: 1rem; + height: 1rem; + background-color: #31bb6b; + border: 0; + border-radius: 1rem; + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, + box-shadow 0.15s ease-in-out; + appearance: none; +} +@media (prefers-reduced-motion: reduce) { + .form-range::-moz-range-thumb { + transition: none; + } +} +.form-range::-moz-range-thumb:active { + background-color: #c1ebd3; +} +.form-range::-moz-range-track { + width: 100%; + height: 0.5rem; + color: transparent; + cursor: pointer; + background-color: var(--bs-tertiary-bg); + border-color: transparent; + border-radius: 1rem; +} +.form-range:disabled { + pointer-events: none; +} +.form-range:disabled::-webkit-slider-thumb { + background-color: var(--bs-secondary-color); +} +.form-range:disabled::-moz-range-thumb { + background-color: var(--bs-secondary-color); +} + +.form-floating { + position: relative; +} +.form-floating > .form-control, +.form-floating > .form-control-plaintext, +.form-floating > .form-select { + height: calc(3.5rem + calc(0 * 2)); + min-height: calc(3.5rem + calc(0 * 2)); + line-height: 1.25; +} +.form-floating > label { + position: absolute; + top: 0; + left: 0; + z-index: 2; + height: 100%; + padding: 1rem 1rem; + overflow: hidden; + text-align: start; + text-overflow: ellipsis; + white-space: nowrap; + pointer-events: none; + border: 0 solid transparent; + transform-origin: 0 0; + transition: opacity 0.1s ease-in-out, transform 0.1s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .form-floating > label { + transition: none; + } +} +.form-floating > .form-control, +.form-floating > .form-control-plaintext { + padding: 1rem 1rem; +} +.form-floating > .form-control::placeholder, +.form-floating > .form-control-plaintext::placeholder { + color: transparent; +} +.form-floating > .form-control:focus, +.form-floating > .form-control:not(:placeholder-shown), +.form-floating > .form-control-plaintext:focus, +.form-floating > .form-control-plaintext:not(:placeholder-shown) { + padding-top: 1.625rem; + padding-bottom: 0.625rem; +} +.form-floating > .form-control:-webkit-autofill, +.form-floating > .form-control-plaintext:-webkit-autofill { + padding-top: 1.625rem; + padding-bottom: 0.625rem; +} +.form-floating > .form-select { + padding-top: 1.625rem; + padding-bottom: 0.625rem; +} +.form-floating > .form-control:focus ~ label, +.form-floating > .form-control:not(:placeholder-shown) ~ label, +.form-floating > .form-control-plaintext ~ label, +.form-floating > .form-select ~ label { + color: rgba(var(--bs-body-color-rgb), 0.65); + transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem); +} +.form-floating > .form-control:focus ~ label::after, +.form-floating > .form-control:not(:placeholder-shown) ~ label::after, +.form-floating > .form-control-plaintext ~ label::after, +.form-floating > .form-select ~ label::after { + position: absolute; + inset: 1rem 0.5rem; + z-index: -1; + height: 1.5em; + content: ''; + background-color: #f2f2f2; + border-radius: var(--bs-border-radius); +} +.form-floating > .form-control:-webkit-autofill ~ label { + color: rgba(var(--bs-body-color-rgb), 0.65); + transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem); +} +.form-floating > .form-control-plaintext ~ label { + border-width: 0 0; +} +.form-floating > :disabled ~ label { + color: #6c757d; +} +.form-floating > :disabled ~ label::after { + background-color: var(--bs-secondary-bg); +} + +.input-group { + position: relative; + display: flex; + flex-wrap: wrap; + align-items: stretch; + width: 100%; +} +.input-group > .form-control, +.input-group > .form-select, +.input-group > .form-floating { + position: relative; + flex: 1 1 auto; + width: 1%; + min-width: 0; +} +.input-group > .form-control:focus, +.input-group > .form-select:focus, +.input-group > .form-floating:focus-within { + z-index: 5; +} +.input-group .btn { + position: relative; + z-index: 2; +} +.input-group .btn:focus { + z-index: 5; +} + +.input-group-text { + display: flex; + align-items: center; + padding: 0.7rem 1rem; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: var(--bs-body-color); + text-align: center; + white-space: nowrap; + background-color: var(--bs-tertiary-bg); + border: 0 solid var(--bs-border-color); + border-radius: var(--bs-border-radius); +} + +.input-group-lg > .form-control, +.input-group-lg > .form-select, +.input-group-lg > .input-group-text, +.input-group-lg > .btn { + padding: 0.5rem 1rem; + font-size: 1.25rem; + border-radius: var(--bs-border-radius-lg); +} + +.input-group-sm > .form-control, +.input-group-sm > .form-select, +.input-group-sm > .input-group-text, +.input-group-sm > .btn { + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + border-radius: var(--bs-border-radius-sm); +} + +.input-group-lg > .form-select, +.input-group-sm > .form-select { + padding-right: 4rem; +} + +.input-group:not(.has-validation) + > :not(:last-child):not(.dropdown-toggle):not(.dropdown-menu):not( + .form-floating + ), +.input-group:not(.has-validation) > .dropdown-toggle:nth-last-child(n + 3), +.input-group:not(.has-validation) + > .form-floating:not(:last-child) + > .form-control, +.input-group:not(.has-validation) + > .form-floating:not(:last-child) + > .form-select { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.input-group.has-validation + > :nth-last-child(n + 3):not(.dropdown-toggle):not(.dropdown-menu):not( + .form-floating + ), +.input-group.has-validation > .dropdown-toggle:nth-last-child(n + 4), +.input-group.has-validation + > .form-floating:nth-last-child(n + 3) + > .form-control, +.input-group.has-validation + > .form-floating:nth-last-child(n + 3) + > .form-select { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.input-group + > :not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not( + .valid-feedback + ):not(.invalid-tooltip):not(.invalid-feedback) { + margin-left: calc(0 * -1); + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.input-group > .form-floating:not(:first-child) > .form-control, +.input-group > .form-floating:not(:first-child) > .form-select { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.valid-feedback { + display: none; + width: 100%; + margin-top: 0.25rem; + font-size: 0.875em; + color: var(--bs-form-valid-color); +} + +.valid-tooltip { + position: absolute; + top: 100%; + z-index: 5; + display: none; + max-width: 100%; + padding: 0.25rem 0.5rem; + margin-top: 0.1rem; + font-size: 0.875rem; + color: #fff; + background-color: var(--bs-success); + border-radius: var(--bs-border-radius); +} + +.was-validated :valid ~ .valid-feedback, +.was-validated :valid ~ .valid-tooltip, +.is-valid ~ .valid-feedback, +.is-valid ~ .valid-tooltip { + display: block; +} + +.was-validated .form-control:valid, +.form-control.is-valid { + border-color: var(--bs-form-valid-border-color); + padding-right: calc(1.5em + 1.4rem); + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2331bb6b' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-position: right calc(0.375em + 0.35rem) center; + background-size: calc(0.75em + 0.7rem) calc(0.75em + 0.7rem); +} +.was-validated .form-control:valid:focus, +.form-control.is-valid:focus { + border-color: var(--bs-form-valid-border-color); + box-shadow: 0 0 0 0.25rem rgba(var(--bs-success-rgb), 0.25); +} + +.was-validated textarea.form-control:valid, +textarea.form-control.is-valid { + padding-right: calc(1.5em + 1.4rem); + background-position: top calc(0.375em + 0.35rem) right calc(0.375em + 0.35rem); +} + +.was-validated .form-select:valid, +.form-select.is-valid { + border-color: var(--bs-form-valid-border-color); +} +.was-validated .form-select:valid:not([multiple]):not([size]), +.was-validated .form-select:valid:not([multiple])[size='1'], +.form-select.is-valid:not([multiple]):not([size]), +.form-select.is-valid:not([multiple])[size='1'] { + --bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2331bb6b' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); + padding-right: 5.5rem; + background-position: right 1rem center, center right 3rem; + background-size: 16px 12px, calc(0.75em + 0.7rem) calc(0.75em + 0.7rem); +} +.was-validated .form-select:valid:focus, +.form-select.is-valid:focus { + border-color: var(--bs-form-valid-border-color); + box-shadow: 0 0 0 0.25rem rgba(var(--bs-success-rgb), 0.25); +} + +.was-validated .form-control-color:valid, +.form-control-color.is-valid { + width: calc(3rem + calc(1.5em + 1.4rem)); +} + +.was-validated .form-check-input:valid, +.form-check-input.is-valid { + border-color: var(--bs-form-valid-border-color); +} +.was-validated .form-check-input:valid:checked, +.form-check-input.is-valid:checked { + background-color: var(--bs-form-valid-color); +} +.was-validated .form-check-input:valid:focus, +.form-check-input.is-valid:focus { + box-shadow: 0 0 0 0.25rem rgba(var(--bs-success-rgb), 0.25); +} +.was-validated .form-check-input:valid ~ .form-check-label, +.form-check-input.is-valid ~ .form-check-label { + color: var(--bs-form-valid-color); +} + +.form-check-inline .form-check-input ~ .valid-feedback { + margin-left: 0.5em; +} + +.was-validated .input-group > .form-control:not(:focus):valid, +.input-group > .form-control:not(:focus).is-valid, +.was-validated .input-group > .form-select:not(:focus):valid, +.input-group > .form-select:not(:focus).is-valid, +.was-validated .input-group > .form-floating:not(:focus-within):valid, +.input-group > .form-floating:not(:focus-within).is-valid { + z-index: 3; +} + +.invalid-feedback { + display: none; + width: 100%; + margin-top: 0.25rem; + font-size: 0.875em; + color: var(--bs-form-invalid-color); +} + +.invalid-tooltip { + position: absolute; + top: 100%; + z-index: 5; + display: none; + max-width: 100%; + padding: 0.25rem 0.5rem; + margin-top: 0.1rem; + font-size: 0.875rem; + color: #fff; + background-color: var(--bs-danger); + border-radius: var(--bs-border-radius); +} + +.was-validated :invalid ~ .invalid-feedback, +.was-validated :invalid ~ .invalid-tooltip, +.is-invalid ~ .invalid-feedback, +.is-invalid ~ .invalid-tooltip { + display: block; +} + +.was-validated .form-control:invalid, +.form-control.is-invalid { + border-color: var(--bs-form-invalid-border-color); + padding-right: calc(1.5em + 1.4rem); + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-position: right calc(0.375em + 0.35rem) center; + background-size: calc(0.75em + 0.7rem) calc(0.75em + 0.7rem); +} +.was-validated .form-control:invalid:focus, +.form-control.is-invalid:focus { + border-color: var(--bs-form-invalid-border-color); + box-shadow: 0 0 0 0.25rem rgba(var(--bs-danger-rgb), 0.25); +} + +.was-validated textarea.form-control:invalid, +textarea.form-control.is-invalid { + padding-right: calc(1.5em + 1.4rem); + background-position: top calc(0.375em + 0.35rem) right calc(0.375em + 0.35rem); +} + +.was-validated .form-select:invalid, +.form-select.is-invalid { + border-color: var(--bs-form-invalid-border-color); +} +.was-validated .form-select:invalid:not([multiple]):not([size]), +.was-validated .form-select:invalid:not([multiple])[size='1'], +.form-select.is-invalid:not([multiple]):not([size]), +.form-select.is-invalid:not([multiple])[size='1'] { + --bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); + padding-right: 5.5rem; + background-position: right 1rem center, center right 3rem; + background-size: 16px 12px, calc(0.75em + 0.7rem) calc(0.75em + 0.7rem); +} +.was-validated .form-select:invalid:focus, +.form-select.is-invalid:focus { + border-color: var(--bs-form-invalid-border-color); + box-shadow: 0 0 0 0.25rem rgba(var(--bs-danger-rgb), 0.25); +} + +.was-validated .form-control-color:invalid, +.form-control-color.is-invalid { + width: calc(3rem + calc(1.5em + 1.4rem)); +} + +.was-validated .form-check-input:invalid, +.form-check-input.is-invalid { + border-color: var(--bs-form-invalid-border-color); +} +.was-validated .form-check-input:invalid:checked, +.form-check-input.is-invalid:checked { + background-color: var(--bs-form-invalid-color); +} +.was-validated .form-check-input:invalid:focus, +.form-check-input.is-invalid:focus { + box-shadow: 0 0 0 0.25rem rgba(var(--bs-danger-rgb), 0.25); +} +.was-validated .form-check-input:invalid ~ .form-check-label, +.form-check-input.is-invalid ~ .form-check-label { + color: var(--bs-form-invalid-color); +} + +.form-check-inline .form-check-input ~ .invalid-feedback { + margin-left: 0.5em; +} + +.was-validated .input-group > .form-control:not(:focus):invalid, +.input-group > .form-control:not(:focus).is-invalid, +.was-validated .input-group > .form-select:not(:focus):invalid, +.input-group > .form-select:not(:focus).is-invalid, +.was-validated .input-group > .form-floating:not(:focus-within):invalid, +.input-group > .form-floating:not(:focus-within).is-invalid { + z-index: 4; +} + +.btn { + --bs-btn-padding-x: 1rem; + --bs-btn-padding-y: 0.7rem; + --bs-btn-font-family: ; + --bs-btn-font-size: 1rem; + --bs-btn-font-weight: 400; + --bs-btn-line-height: 1.5; + --bs-btn-color: var(--bs-body-color); + --bs-btn-bg: transparent; + --bs-btn-border-width: var(--bs-border-width); + --bs-btn-border-color: transparent; + --bs-btn-border-radius: var(--bs-border-radius); + --bs-btn-hover-border-color: transparent; + --bs-btn-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), + 0 1px 1px rgba(0, 0, 0, 0.075); + --bs-btn-disabled-opacity: 0.65; + --bs-btn-focus-box-shadow: 0 0 0 0.25rem + rgba(var(--bs-btn-focus-shadow-rgb), 0.5); + display: inline-block; + padding: var(--bs-btn-padding-y) var(--bs-btn-padding-x); + font-family: var(--bs-btn-font-family); + font-size: var(--bs-btn-font-size); + font-weight: var(--bs-btn-font-weight); + line-height: var(--bs-btn-line-height); + color: var(--bs-btn-color); + text-align: center; + vertical-align: middle; + cursor: pointer; + user-select: none; + border: var(--bs-btn-border-width) solid var(--bs-btn-border-color); + border-radius: var(--bs-btn-border-radius); + background-color: var(--bs-btn-bg); + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, + border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .btn { + transition: none; + } +} +.btn:hover { + color: var(--bs-btn-hover-color); + background-color: var(--bs-btn-hover-bg); + border-color: var(--bs-btn-hover-border-color); +} +.btn-check + .btn:hover { + color: var(--bs-btn-color); + background-color: var(--bs-btn-bg); + border-color: var(--bs-btn-border-color); +} +.btn:focus-visible { + color: var(--bs-btn-hover-color); + background-color: var(--bs-btn-hover-bg); + border-color: var(--bs-btn-hover-border-color); + outline: 0; + box-shadow: var(--bs-btn-focus-box-shadow); +} +.btn-check:focus-visible + .btn { + border-color: var(--bs-btn-hover-border-color); + outline: 0; + box-shadow: var(--bs-btn-focus-box-shadow); +} +.btn-check:checked + .btn, +:not(.btn-check) + .btn:active, +.btn:first-child:active, +.btn.active, +.btn.show { + color: var(--bs-btn-active-color); + background-color: var(--bs-btn-active-bg); + border-color: var(--bs-btn-active-border-color); +} +.btn-check:checked + .btn:focus-visible, +:not(.btn-check) + .btn:active:focus-visible, +.btn:first-child:active:focus-visible, +.btn.active:focus-visible, +.btn.show:focus-visible { + box-shadow: var(--bs-btn-focus-box-shadow); +} +.btn:disabled, +.btn.disabled, +fieldset:disabled .btn { + color: var(--bs-btn-disabled-color); + pointer-events: none; + background-color: var(--bs-btn-disabled-bg); + border-color: var(--bs-btn-disabled-border-color); + opacity: var(--bs-btn-disabled-opacity); +} + +.btn-primary { + --bs-btn-color: #000; + --bs-btn-bg: #31bb6b; + --bs-btn-border-color: #31bb6b; + --bs-btn-hover-color: #000; + --bs-btn-hover-bg: #50c581; + --bs-btn-hover-border-color: #46c27a; + --bs-btn-focus-shadow-rgb: 42, 159, 91; + --bs-btn-active-color: #000; + --bs-btn-active-bg: #5ac989; + --bs-btn-active-border-color: #46c27a; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #000; + --bs-btn-disabled-bg: #31bb6b; + --bs-btn-disabled-border-color: #31bb6b; +} + +.btn-secondary { + --bs-btn-color: #fff; + --bs-btn-bg: #707070; + --bs-btn-border-color: #707070; + --bs-btn-hover-color: #fff; + --bs-btn-hover-bg: #5f5f5f; + --bs-btn-hover-border-color: #5a5a5a; + --bs-btn-focus-shadow-rgb: 133, 133, 133; + --bs-btn-active-color: #fff; + --bs-btn-active-bg: #5a5a5a; + --bs-btn-active-border-color: #545454; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #fff; + --bs-btn-disabled-bg: #707070; + --bs-btn-disabled-border-color: #707070; +} + +.btn-success { + --bs-btn-color: #000; + --bs-btn-bg: #31bb6b; + --bs-btn-border-color: #31bb6b; + --bs-btn-hover-color: #000; + --bs-btn-hover-bg: #50c581; + --bs-btn-hover-border-color: #46c27a; + --bs-btn-focus-shadow-rgb: 42, 159, 91; + --bs-btn-active-color: #000; + --bs-btn-active-bg: #5ac989; + --bs-btn-active-border-color: #46c27a; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #000; + --bs-btn-disabled-bg: #31bb6b; + --bs-btn-disabled-border-color: #31bb6b; +} + +.btn-info { + --bs-btn-color: #000; + --bs-btn-bg: #0dcaf0; + --bs-btn-border-color: #0dcaf0; + --bs-btn-hover-color: #000; + --bs-btn-hover-bg: #31d2f2; + --bs-btn-hover-border-color: #25cff2; + --bs-btn-focus-shadow-rgb: 11, 172, 204; + --bs-btn-active-color: #000; + --bs-btn-active-bg: #3dd5f3; + --bs-btn-active-border-color: #25cff2; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #000; + --bs-btn-disabled-bg: #0dcaf0; + --bs-btn-disabled-border-color: #0dcaf0; +} + +.btn-warning { + --bs-btn-color: #000; + --bs-btn-bg: #febc59; + --bs-btn-border-color: #febc59; + --bs-btn-hover-color: #000; + --bs-btn-hover-bg: #fec672; + --bs-btn-hover-border-color: #fec36a; + --bs-btn-focus-shadow-rgb: 216, 160, 76; + --bs-btn-active-color: #000; + --bs-btn-active-bg: #fec97a; + --bs-btn-active-border-color: #fec36a; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #000; + --bs-btn-disabled-bg: #febc59; + --bs-btn-disabled-border-color: #febc59; +} + +.btn-danger { + --bs-btn-color: #fff; + --bs-btn-bg: #dc3545; + --bs-btn-border-color: #dc3545; + --bs-btn-hover-color: #fff; + --bs-btn-hover-bg: #bb2d3b; + --bs-btn-hover-border-color: #b02a37; + --bs-btn-focus-shadow-rgb: 225, 83, 97; + --bs-btn-active-color: #fff; + --bs-btn-active-bg: #b02a37; + --bs-btn-active-border-color: #a52834; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #fff; + --bs-btn-disabled-bg: #dc3545; + --bs-btn-disabled-border-color: #dc3545; +} + +.btn-light { + --bs-btn-color: #000; + --bs-btn-bg: #f8f9fa; + --bs-btn-border-color: #f8f9fa; + --bs-btn-hover-color: #000; + --bs-btn-hover-bg: #d3d4d5; + --bs-btn-hover-border-color: #c6c7c8; + --bs-btn-focus-shadow-rgb: 211, 212, 213; + --bs-btn-active-color: #000; + --bs-btn-active-bg: #c6c7c8; + --bs-btn-active-border-color: #babbbc; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #000; + --bs-btn-disabled-bg: #f8f9fa; + --bs-btn-disabled-border-color: #f8f9fa; +} + +.btn-dark { + --bs-btn-color: #fff; + --bs-btn-bg: #212529; + --bs-btn-border-color: #212529; + --bs-btn-hover-color: #fff; + --bs-btn-hover-bg: #424649; + --bs-btn-hover-border-color: #373b3e; + --bs-btn-focus-shadow-rgb: 66, 70, 73; + --bs-btn-active-color: #fff; + --bs-btn-active-bg: #4d5154; + --bs-btn-active-border-color: #373b3e; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #fff; + --bs-btn-disabled-bg: #212529; + --bs-btn-disabled-border-color: #212529; +} + +.btn-outline-primary { + --bs-btn-color: #31bb6b; + --bs-btn-border-color: #31bb6b; + --bs-btn-hover-color: #000; + --bs-btn-hover-bg: #31bb6b; + --bs-btn-hover-border-color: #31bb6b; + --bs-btn-focus-shadow-rgb: 49, 187, 107; + --bs-btn-active-color: #000; + --bs-btn-active-bg: #31bb6b; + --bs-btn-active-border-color: #31bb6b; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #31bb6b; + --bs-btn-disabled-bg: transparent; + --bs-btn-disabled-border-color: #31bb6b; + --bs-gradient: none; +} + +.btn-outline-secondary { + --bs-btn-color: #707070; + --bs-btn-border-color: #707070; + --bs-btn-hover-color: #fff; + --bs-btn-hover-bg: #707070; + --bs-btn-hover-border-color: #707070; + --bs-btn-focus-shadow-rgb: 112, 112, 112; + --bs-btn-active-color: #fff; + --bs-btn-active-bg: #707070; + --bs-btn-active-border-color: #707070; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #707070; + --bs-btn-disabled-bg: transparent; + --bs-btn-disabled-border-color: #707070; + --bs-gradient: none; +} + +.btn-outline-success { + --bs-btn-color: #31bb6b; + --bs-btn-border-color: #31bb6b; + --bs-btn-hover-color: #000; + --bs-btn-hover-bg: #31bb6b; + --bs-btn-hover-border-color: #31bb6b; + --bs-btn-focus-shadow-rgb: 49, 187, 107; + --bs-btn-active-color: #000; + --bs-btn-active-bg: #31bb6b; + --bs-btn-active-border-color: #31bb6b; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #31bb6b; + --bs-btn-disabled-bg: transparent; + --bs-btn-disabled-border-color: #31bb6b; + --bs-gradient: none; +} + +.btn-outline-info { + --bs-btn-color: #0dcaf0; + --bs-btn-border-color: #0dcaf0; + --bs-btn-hover-color: #000; + --bs-btn-hover-bg: #0dcaf0; + --bs-btn-hover-border-color: #0dcaf0; + --bs-btn-focus-shadow-rgb: 13, 202, 240; + --bs-btn-active-color: #000; + --bs-btn-active-bg: #0dcaf0; + --bs-btn-active-border-color: #0dcaf0; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #0dcaf0; + --bs-btn-disabled-bg: transparent; + --bs-btn-disabled-border-color: #0dcaf0; + --bs-gradient: none; +} + +.btn-outline-warning { + --bs-btn-color: #febc59; + --bs-btn-border-color: #febc59; + --bs-btn-hover-color: #000; + --bs-btn-hover-bg: #febc59; + --bs-btn-hover-border-color: #febc59; + --bs-btn-focus-shadow-rgb: 254, 188, 89; + --bs-btn-active-color: #000; + --bs-btn-active-bg: #febc59; + --bs-btn-active-border-color: #febc59; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #febc59; + --bs-btn-disabled-bg: transparent; + --bs-btn-disabled-border-color: #febc59; + --bs-gradient: none; +} + +.btn-outline-danger { + --bs-btn-color: #dc3545; + --bs-btn-border-color: #dc3545; + --bs-btn-hover-color: #fff; + --bs-btn-hover-bg: #dc3545; + --bs-btn-hover-border-color: #dc3545; + --bs-btn-focus-shadow-rgb: 220, 53, 69; + --bs-btn-active-color: #fff; + --bs-btn-active-bg: #dc3545; + --bs-btn-active-border-color: #dc3545; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #dc3545; + --bs-btn-disabled-bg: transparent; + --bs-btn-disabled-border-color: #dc3545; + --bs-gradient: none; +} + +.btn-outline-light { + --bs-btn-color: #f8f9fa; + --bs-btn-border-color: #f8f9fa; + --bs-btn-hover-color: #000; + --bs-btn-hover-bg: #f8f9fa; + --bs-btn-hover-border-color: #f8f9fa; + --bs-btn-focus-shadow-rgb: 248, 249, 250; + --bs-btn-active-color: #000; + --bs-btn-active-bg: #f8f9fa; + --bs-btn-active-border-color: #f8f9fa; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #f8f9fa; + --bs-btn-disabled-bg: transparent; + --bs-btn-disabled-border-color: #f8f9fa; + --bs-gradient: none; +} + +.btn-outline-dark { + --bs-btn-color: #212529; + --bs-btn-border-color: #212529; + --bs-btn-hover-color: #fff; + --bs-btn-hover-bg: #212529; + --bs-btn-hover-border-color: #212529; + --bs-btn-focus-shadow-rgb: 33, 37, 41; + --bs-btn-active-color: #fff; + --bs-btn-active-bg: #212529; + --bs-btn-active-border-color: #212529; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #212529; + --bs-btn-disabled-bg: transparent; + --bs-btn-disabled-border-color: #212529; + --bs-gradient: none; +} + +.btn-link { + --bs-btn-font-weight: 400; + --bs-btn-color: var(--bs-link-color); + --bs-btn-bg: transparent; + --bs-btn-border-color: transparent; + --bs-btn-hover-color: var(--bs-link-hover-color); + --bs-btn-hover-border-color: transparent; + --bs-btn-active-color: var(--bs-link-hover-color); + --bs-btn-active-border-color: transparent; + --bs-btn-disabled-color: #6c757d; + --bs-btn-disabled-border-color: transparent; + --bs-btn-box-shadow: 0 0 0 #000; + --bs-btn-focus-shadow-rgb: 49, 132, 253; + text-decoration: none; +} +.btn-link:focus-visible { + color: var(--bs-btn-color); +} +.btn-link:hover { + color: var(--bs-btn-hover-color); +} + +.btn-lg, +.btn-group-lg > .btn { + --bs-btn-padding-y: 0.5rem; + --bs-btn-padding-x: 1rem; + --bs-btn-font-size: 1.25rem; + --bs-btn-border-radius: var(--bs-border-radius-lg); +} + +.btn-sm, +.btn-group-sm > .btn { + --bs-btn-padding-y: 0.25rem; + --bs-btn-padding-x: 0.5rem; + --bs-btn-font-size: 0.875rem; + --bs-btn-border-radius: var(--bs-border-radius-sm); +} + +.fade { + transition: opacity 0.15s linear; +} +@media (prefers-reduced-motion: reduce) { + .fade { + transition: none; + } +} +.fade:not(.show) { + opacity: 0; +} + +.collapse:not(.show) { + display: none; +} + +.collapsing { + height: 0; + overflow: hidden; + transition: height 0.35s ease; +} +@media (prefers-reduced-motion: reduce) { + .collapsing { + transition: none; + } +} +.collapsing.collapse-horizontal { + width: 0; + height: auto; + transition: width 0.35s ease; +} +@media (prefers-reduced-motion: reduce) { + .collapsing.collapse-horizontal { + transition: none; + } +} + +.dropup, +.dropend, +.dropdown, +.dropstart, +.dropup-center, +.dropdown-center { + position: relative; +} + +.dropdown-toggle { + white-space: nowrap; +} +.dropdown-toggle::after { + display: inline-block; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ''; + border-top: 0.3em solid; + border-right: 0.3em solid transparent; + border-bottom: 0; + border-left: 0.3em solid transparent; +} +.dropdown-toggle:empty::after { + margin-left: 0; +} + +.dropdown-menu { + --bs-dropdown-zindex: 1000; + --bs-dropdown-min-width: 10rem; + --bs-dropdown-padding-x: 0; + --bs-dropdown-padding-y: 0.5rem; + --bs-dropdown-spacer: 0.125rem; + --bs-dropdown-font-size: 1rem; + --bs-dropdown-color: var(--bs-body-color); + --bs-dropdown-bg: var(--bs-body-bg); + --bs-dropdown-border-color: var(--bs-border-color-translucent); + --bs-dropdown-border-radius: var(--bs-border-radius); + --bs-dropdown-border-width: var(--bs-border-width); + --bs-dropdown-inner-border-radius: calc( + var(--bs-border-radius) - var(--bs-border-width) + ); + --bs-dropdown-divider-bg: var(--bs-border-color-translucent); + --bs-dropdown-divider-margin-y: 0.5rem; + --bs-dropdown-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); + --bs-dropdown-link-color: var(--bs-body-color); + --bs-dropdown-link-hover-color: var(--bs-body-color); + --bs-dropdown-link-hover-bg: var(--bs-tertiary-bg); + --bs-dropdown-link-active-color: #fff; + --bs-dropdown-link-active-bg: #31bb6b; + --bs-dropdown-link-disabled-color: var(--bs-tertiary-color); + --bs-dropdown-item-padding-x: 1rem; + --bs-dropdown-item-padding-y: 0.25rem; + --bs-dropdown-header-color: #6c757d; + --bs-dropdown-header-padding-x: 1rem; + --bs-dropdown-header-padding-y: 0.5rem; + position: absolute; + z-index: var(--bs-dropdown-zindex); + display: none; + min-width: var(--bs-dropdown-min-width); + padding: var(--bs-dropdown-padding-y) var(--bs-dropdown-padding-x); + margin: 0; + font-size: var(--bs-dropdown-font-size); + color: var(--bs-dropdown-color); + text-align: left; + list-style: none; + background-color: var(--bs-dropdown-bg); + background-clip: padding-box; + border: var(--bs-dropdown-border-width) solid var(--bs-dropdown-border-color); + border-radius: var(--bs-dropdown-border-radius); +} +.dropdown-menu[data-bs-popper] { + top: 100%; + left: 0; + margin-top: var(--bs-dropdown-spacer); +} + +.dropdown-menu-start { + --bs-position: start; +} +.dropdown-menu-start[data-bs-popper] { + right: auto; + left: 0; +} + +.dropdown-menu-end { + --bs-position: end; +} +.dropdown-menu-end[data-bs-popper] { + right: 0; + left: auto; +} + +@media (min-width: 576px) { + .dropdown-menu-sm-start { + --bs-position: start; + } + .dropdown-menu-sm-start[data-bs-popper] { + right: auto; + left: 0; + } + .dropdown-menu-sm-end { + --bs-position: end; + } + .dropdown-menu-sm-end[data-bs-popper] { + right: 0; + left: auto; + } +} + +@media (min-width: 768px) { + .dropdown-menu-md-start { + --bs-position: start; + } + .dropdown-menu-md-start[data-bs-popper] { + right: auto; + left: 0; + } + .dropdown-menu-md-end { + --bs-position: end; + } + .dropdown-menu-md-end[data-bs-popper] { + right: 0; + left: auto; + } +} + +@media (min-width: 992px) { + .dropdown-menu-lg-start { + --bs-position: start; + } + .dropdown-menu-lg-start[data-bs-popper] { + right: auto; + left: 0; + } + .dropdown-menu-lg-end { + --bs-position: end; + } + .dropdown-menu-lg-end[data-bs-popper] { + right: 0; + left: auto; + } +} + +@media (min-width: 1200px) { + .dropdown-menu-xl-start { + --bs-position: start; + } + .dropdown-menu-xl-start[data-bs-popper] { + right: auto; + left: 0; + } + .dropdown-menu-xl-end { + --bs-position: end; + } + .dropdown-menu-xl-end[data-bs-popper] { + right: 0; + left: auto; + } +} + +@media (min-width: 1400px) { + .dropdown-menu-xxl-start { + --bs-position: start; + } + .dropdown-menu-xxl-start[data-bs-popper] { + right: auto; + left: 0; + } + .dropdown-menu-xxl-end { + --bs-position: end; + } + .dropdown-menu-xxl-end[data-bs-popper] { + right: 0; + left: auto; + } +} + +.dropup .dropdown-menu[data-bs-popper] { + top: auto; + bottom: 100%; + margin-top: 0; + margin-bottom: var(--bs-dropdown-spacer); +} + +.dropup .dropdown-toggle::after { + display: inline-block; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ''; + border-top: 0; + border-right: 0.3em solid transparent; + border-bottom: 0.3em solid; + border-left: 0.3em solid transparent; +} + +.dropup .dropdown-toggle:empty::after { + margin-left: 0; +} + +.dropend .dropdown-menu[data-bs-popper] { + top: 0; + right: auto; + left: 100%; + margin-top: 0; + margin-left: var(--bs-dropdown-spacer); +} + +.dropend .dropdown-toggle::after { + display: inline-block; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ''; + border-top: 0.3em solid transparent; + border-right: 0; + border-bottom: 0.3em solid transparent; + border-left: 0.3em solid; +} + +.dropend .dropdown-toggle:empty::after { + margin-left: 0; +} + +.dropend .dropdown-toggle::after { + vertical-align: 0; +} + +.dropstart .dropdown-menu[data-bs-popper] { + top: 0; + right: 100%; + left: auto; + margin-top: 0; + margin-right: var(--bs-dropdown-spacer); +} + +.dropstart .dropdown-toggle::after { + display: inline-block; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ''; +} + +.dropstart .dropdown-toggle::after { + display: none; +} + +.dropstart .dropdown-toggle::before { + display: inline-block; + margin-right: 0.255em; + vertical-align: 0.255em; + content: ''; + border-top: 0.3em solid transparent; + border-right: 0.3em solid; + border-bottom: 0.3em solid transparent; +} + +.dropstart .dropdown-toggle:empty::after { + margin-left: 0; +} + +.dropstart .dropdown-toggle::before { + vertical-align: 0; +} + +.dropdown-divider { + height: 0; + margin: var(--bs-dropdown-divider-margin-y) 0; + overflow: hidden; + border-top: 1px solid var(--bs-dropdown-divider-bg); + opacity: 1; +} + +.dropdown-item { + display: block; + width: 100%; + padding: var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x); + clear: both; + font-weight: 400; + color: var(--bs-dropdown-link-color); + text-align: inherit; + white-space: nowrap; + background-color: transparent; + border: 0; + border-radius: var(--bs-dropdown-item-border-radius, 0); +} +.dropdown-item:hover, +.dropdown-item:focus { + color: var(--bs-dropdown-link-hover-color); + background-color: var(--bs-dropdown-link-hover-bg); +} +.dropdown-item.active, +.dropdown-item:active { + color: var(--bs-dropdown-link-active-color); + text-decoration: none; + background-color: var(--bs-dropdown-link-active-bg); +} +.dropdown-item.disabled, +.dropdown-item:disabled { + color: var(--bs-dropdown-link-disabled-color); + pointer-events: none; + background-color: transparent; +} + +.dropdown-menu.show { + display: block; +} + +.dropdown-header { + display: block; + padding: var(--bs-dropdown-header-padding-y) + var(--bs-dropdown-header-padding-x); + margin-bottom: 0; + font-size: 0.875rem; + color: var(--bs-dropdown-header-color); + white-space: nowrap; +} + +.dropdown-item-text { + display: block; + padding: var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x); + color: var(--bs-dropdown-link-color); +} + +.dropdown-menu-dark { + --bs-dropdown-color: #dee2e6; + --bs-dropdown-bg: #343a40; + --bs-dropdown-border-color: var(--bs-border-color-translucent); + --bs-dropdown-box-shadow: ; + --bs-dropdown-link-color: #dee2e6; + --bs-dropdown-link-hover-color: #fff; + --bs-dropdown-divider-bg: var(--bs-border-color-translucent); + --bs-dropdown-link-hover-bg: rgba(255, 255, 255, 0.15); + --bs-dropdown-link-active-color: #fff; + --bs-dropdown-link-active-bg: #31bb6b; + --bs-dropdown-link-disabled-color: #adb5bd; + --bs-dropdown-header-color: #adb5bd; +} + +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-flex; + vertical-align: middle; +} +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + flex: 1 1 auto; +} +.btn-group > .btn-check:checked + .btn, +.btn-group > .btn-check:focus + .btn, +.btn-group > .btn:hover, +.btn-group > .btn:focus, +.btn-group > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn-check:checked + .btn, +.btn-group-vertical > .btn-check:focus + .btn, +.btn-group-vertical > .btn:hover, +.btn-group-vertical > .btn:focus, +.btn-group-vertical > .btn:active, +.btn-group-vertical > .btn.active { + z-index: 1; +} + +.btn-toolbar { + display: flex; + flex-wrap: wrap; + justify-content: flex-start; +} +.btn-toolbar .input-group { + width: auto; +} + +.btn-group { + border-radius: var(--bs-border-radius); +} +.btn-group > :not(.btn-check:first-child) + .btn, +.btn-group > .btn-group:not(:first-child) { + margin-left: calc(var(--bs-border-width) * -1); +} +.btn-group > .btn:not(:last-child):not(.dropdown-toggle), +.btn-group > .btn.dropdown-toggle-split:first-child, +.btn-group > .btn-group:not(:last-child) > .btn { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.btn-group > .btn:nth-child(n + 3), +.btn-group > :not(.btn-check) + .btn, +.btn-group > .btn-group:not(:first-child) > .btn { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.dropdown-toggle-split { + padding-right: 0.75rem; + padding-left: 0.75rem; +} +.dropdown-toggle-split::after, +.dropup .dropdown-toggle-split::after, +.dropend .dropdown-toggle-split::after { + margin-left: 0; +} +.dropstart .dropdown-toggle-split::before { + margin-right: 0; +} + +.btn-sm + .dropdown-toggle-split, +.btn-group-sm > .btn + .dropdown-toggle-split { + padding-right: 0.375rem; + padding-left: 0.375rem; +} + +.btn-lg + .dropdown-toggle-split, +.btn-group-lg > .btn + .dropdown-toggle-split { + padding-right: 0.75rem; + padding-left: 0.75rem; +} + +.btn-group-vertical { + flex-direction: column; + align-items: flex-start; + justify-content: center; +} +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group { + width: 100%; +} +.btn-group-vertical > .btn:not(:first-child), +.btn-group-vertical > .btn-group:not(:first-child) { + margin-top: calc(var(--bs-border-width) * -1); +} +.btn-group-vertical > .btn:not(:last-child):not(.dropdown-toggle), +.btn-group-vertical > .btn-group:not(:last-child) > .btn { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn ~ .btn, +.btn-group-vertical > .btn-group:not(:first-child) > .btn { + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.nav { + --bs-nav-link-padding-x: 1rem; + --bs-nav-link-padding-y: 0.5rem; + --bs-nav-link-font-weight: ; + --bs-nav-link-color: var(--bs-link-color); + --bs-nav-link-hover-color: var(--bs-link-hover-color); + --bs-nav-link-disabled-color: var(--bs-secondary-color); + display: flex; + flex-wrap: wrap; + padding-left: 0; + margin-bottom: 0; + list-style: none; +} + +.nav-link { + display: block; + padding: var(--bs-nav-link-padding-y) var(--bs-nav-link-padding-x); + font-size: var(--bs-nav-link-font-size); + font-weight: var(--bs-nav-link-font-weight); + color: var(--bs-nav-link-color); + background: none; + border: 0; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, + border-color 0.15s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .nav-link { + transition: none; + } +} +.nav-link:hover, +.nav-link:focus { + color: var(--bs-nav-link-hover-color); +} +.nav-link:focus-visible { + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(49, 187, 107, 0.25); +} +.nav-link.disabled { + color: var(--bs-nav-link-disabled-color); + pointer-events: none; + cursor: default; +} + +.nav-tabs { + --bs-nav-tabs-border-width: var(--bs-border-width); + --bs-nav-tabs-border-color: var(--bs-border-color); + --bs-nav-tabs-border-radius: var(--bs-border-radius); + --bs-nav-tabs-link-hover-border-color: var(--bs-secondary-bg) + var(--bs-secondary-bg) var(--bs-border-color); + --bs-nav-tabs-link-active-color: var(--bs-emphasis-color); + --bs-nav-tabs-link-active-bg: var(--bs-body-bg); + --bs-nav-tabs-link-active-border-color: var(--bs-border-color) + var(--bs-border-color) var(--bs-body-bg); + border-bottom: var(--bs-nav-tabs-border-width) solid + var(--bs-nav-tabs-border-color); +} +.nav-tabs .nav-link { + margin-bottom: calc(-1 * var(--bs-nav-tabs-border-width)); + border: var(--bs-nav-tabs-border-width) solid transparent; + border-top-left-radius: var(--bs-nav-tabs-border-radius); + border-top-right-radius: var(--bs-nav-tabs-border-radius); +} +.nav-tabs .nav-link:hover, +.nav-tabs .nav-link:focus { + isolation: isolate; + border-color: var(--bs-nav-tabs-link-hover-border-color); +} +.nav-tabs .nav-link.disabled, +.nav-tabs .nav-link:disabled { + color: var(--bs-nav-link-disabled-color); + background-color: transparent; + border-color: transparent; +} +.nav-tabs .nav-link.active, +.nav-tabs .nav-item.show .nav-link { + color: var(--bs-nav-tabs-link-active-color); + background-color: var(--bs-nav-tabs-link-active-bg); + border-color: var(--bs-nav-tabs-link-active-border-color); +} +.nav-tabs .dropdown-menu { + margin-top: calc(-1 * var(--bs-nav-tabs-border-width)); + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.nav-pills { + --bs-nav-pills-border-radius: var(--bs-border-radius); + --bs-nav-pills-link-active-color: #fff; + --bs-nav-pills-link-active-bg: #31bb6b; +} +.nav-pills .nav-link { + border-radius: var(--bs-nav-pills-border-radius); +} +.nav-pills .nav-link:disabled { + color: var(--bs-nav-link-disabled-color); + background-color: transparent; + border-color: transparent; +} +.nav-pills .nav-link.active, +.nav-pills .show > .nav-link { + color: var(--bs-nav-pills-link-active-color); + background-color: var(--bs-nav-pills-link-active-bg); +} + +.nav-underline { + --bs-nav-underline-gap: 1rem; + --bs-nav-underline-border-width: 0.125rem; + --bs-nav-underline-link-active-color: var(--bs-emphasis-color); + gap: var(--bs-nav-underline-gap); +} +.nav-underline .nav-link { + padding-right: 0; + padding-left: 0; + border-bottom: var(--bs-nav-underline-border-width) solid transparent; +} +.nav-underline .nav-link:hover, +.nav-underline .nav-link:focus { + border-bottom-color: currentcolor; +} +.nav-underline .nav-link.active, +.nav-underline .show > .nav-link { + font-weight: 700; + color: var(--bs-nav-underline-link-active-color); + border-bottom-color: currentcolor; +} + +.nav-fill > .nav-link, +.nav-fill .nav-item { + flex: 1 1 auto; + text-align: center; +} + +.nav-justified > .nav-link, +.nav-justified .nav-item { + flex-basis: 0; + flex-grow: 1; + text-align: center; +} + +.nav-fill .nav-item .nav-link, +.nav-justified .nav-item .nav-link { + width: 100%; +} + +.tab-content > .tab-pane { + display: none; +} + +.tab-content > .active { + display: block; +} + +.navbar { + --bs-navbar-padding-x: 0; + --bs-navbar-padding-y: 0.5rem; + --bs-navbar-color: rgba(var(--bs-emphasis-color-rgb), 0.65); + --bs-navbar-hover-color: rgba(var(--bs-emphasis-color-rgb), 0.8); + --bs-navbar-disabled-color: rgba(var(--bs-emphasis-color-rgb), 0.3); + --bs-navbar-active-color: rgba(var(--bs-emphasis-color-rgb), 1); + --bs-navbar-brand-padding-y: 0.3125rem; + --bs-navbar-brand-margin-end: 1rem; + --bs-navbar-brand-font-size: 1.25rem; + --bs-navbar-brand-color: rgba(var(--bs-emphasis-color-rgb), 1); + --bs-navbar-brand-hover-color: rgba(var(--bs-emphasis-color-rgb), 1); + --bs-navbar-nav-link-padding-x: 0.5rem; + --bs-navbar-toggler-padding-y: 0.25rem; + --bs-navbar-toggler-padding-x: 0.75rem; + --bs-navbar-toggler-font-size: 1.25rem; + --bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%2833, 37, 41, 0.75%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); + --bs-navbar-toggler-border-color: rgba(var(--bs-emphasis-color-rgb), 0.15); + --bs-navbar-toggler-border-radius: var(--bs-border-radius); + --bs-navbar-toggler-focus-width: 0.25rem; + --bs-navbar-toggler-transition: box-shadow 0.15s ease-in-out; + position: relative; + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: space-between; + padding: var(--bs-navbar-padding-y) var(--bs-navbar-padding-x); +} +.navbar > .container, +.navbar > .container-fluid, +.navbar > .container-sm, +.navbar > .container-md, +.navbar > .container-lg, +.navbar > .container-xl, +.navbar > .container-xxl { + display: flex; + flex-wrap: inherit; + align-items: center; + justify-content: space-between; +} + +.navbar-brand { + padding-top: var(--bs-navbar-brand-padding-y); + padding-bottom: var(--bs-navbar-brand-padding-y); + margin-right: var(--bs-navbar-brand-margin-end); + font-size: var(--bs-navbar-brand-font-size); + color: var(--bs-navbar-brand-color); + white-space: nowrap; +} +.navbar-brand:hover, +.navbar-brand:focus { + color: var(--bs-navbar-brand-hover-color); +} + +.navbar-nav { + --bs-nav-link-padding-x: 0; + --bs-nav-link-padding-y: 0.5rem; + --bs-nav-link-font-weight: ; + --bs-nav-link-color: var(--bs-navbar-color); + --bs-nav-link-hover-color: var(--bs-navbar-hover-color); + --bs-nav-link-disabled-color: var(--bs-navbar-disabled-color); + display: flex; + flex-direction: column; + padding-left: 0; + margin-bottom: 0; + list-style: none; +} +.navbar-nav .nav-link.active, +.navbar-nav .nav-link.show { + color: var(--bs-navbar-active-color); +} +.navbar-nav .dropdown-menu { + position: static; +} + +.navbar-text { + padding-top: 0.5rem; + padding-bottom: 0.5rem; + color: var(--bs-navbar-color); +} +.navbar-text a, +.navbar-text a:hover, +.navbar-text a:focus { + color: var(--bs-navbar-active-color); +} + +.navbar-collapse { + flex-basis: 100%; + flex-grow: 1; + align-items: center; +} + +.navbar-toggler { + padding: var(--bs-navbar-toggler-padding-y) var(--bs-navbar-toggler-padding-x); + font-size: var(--bs-navbar-toggler-font-size); + line-height: 1; + color: var(--bs-navbar-color); + background-color: transparent; + border: var(--bs-border-width) solid var(--bs-navbar-toggler-border-color); + border-radius: var(--bs-navbar-toggler-border-radius); + transition: var(--bs-navbar-toggler-transition); +} +@media (prefers-reduced-motion: reduce) { + .navbar-toggler { + transition: none; + } +} +.navbar-toggler:hover { + text-decoration: none; +} +.navbar-toggler:focus { + text-decoration: none; + outline: 0; + box-shadow: 0 0 0 var(--bs-navbar-toggler-focus-width); +} + +.navbar-toggler-icon { + display: inline-block; + width: 1.5em; + height: 1.5em; + vertical-align: middle; + background-image: var(--bs-navbar-toggler-icon-bg); + background-repeat: no-repeat; + background-position: center; + background-size: 100%; +} + +.navbar-nav-scroll { + max-height: var(--bs-scroll-height, 75vh); + overflow-y: auto; +} + +@media (min-width: 576px) { + .navbar-expand-sm { + flex-wrap: nowrap; + justify-content: flex-start; + } + .navbar-expand-sm .navbar-nav { + flex-direction: row; + } + .navbar-expand-sm .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-sm .navbar-nav .nav-link { + padding-right: var(--bs-navbar-nav-link-padding-x); + padding-left: var(--bs-navbar-nav-link-padding-x); + } + .navbar-expand-sm .navbar-nav-scroll { + overflow: visible; + } + .navbar-expand-sm .navbar-collapse { + display: flex !important; + flex-basis: auto; + } + .navbar-expand-sm .navbar-toggler { + display: none; + } + .navbar-expand-sm .offcanvas { + position: static; + z-index: auto; + flex-grow: 1; + width: auto !important; + height: auto !important; + visibility: visible !important; + background-color: transparent !important; + border: 0 !important; + transform: none !important; + transition: none; + } + .navbar-expand-sm .offcanvas .offcanvas-header { + display: none; + } + .navbar-expand-sm .offcanvas .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible; + } +} + +@media (min-width: 768px) { + .navbar-expand-md { + flex-wrap: nowrap; + justify-content: flex-start; + } + .navbar-expand-md .navbar-nav { + flex-direction: row; + } + .navbar-expand-md .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-md .navbar-nav .nav-link { + padding-right: var(--bs-navbar-nav-link-padding-x); + padding-left: var(--bs-navbar-nav-link-padding-x); + } + .navbar-expand-md .navbar-nav-scroll { + overflow: visible; + } + .navbar-expand-md .navbar-collapse { + display: flex !important; + flex-basis: auto; + } + .navbar-expand-md .navbar-toggler { + display: none; + } + .navbar-expand-md .offcanvas { + position: static; + z-index: auto; + flex-grow: 1; + width: auto !important; + height: auto !important; + visibility: visible !important; + background-color: transparent !important; + border: 0 !important; + transform: none !important; + transition: none; + } + .navbar-expand-md .offcanvas .offcanvas-header { + display: none; + } + .navbar-expand-md .offcanvas .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible; + } +} + +@media (min-width: 992px) { + .navbar-expand-lg { + flex-wrap: nowrap; + justify-content: flex-start; + } + .navbar-expand-lg .navbar-nav { + flex-direction: row; + } + .navbar-expand-lg .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-lg .navbar-nav .nav-link { + padding-right: var(--bs-navbar-nav-link-padding-x); + padding-left: var(--bs-navbar-nav-link-padding-x); + } + .navbar-expand-lg .navbar-nav-scroll { + overflow: visible; + } + .navbar-expand-lg .navbar-collapse { + display: flex !important; + flex-basis: auto; + } + .navbar-expand-lg .navbar-toggler { + display: none; + } + .navbar-expand-lg .offcanvas { + position: static; + z-index: auto; + flex-grow: 1; + width: auto !important; + height: auto !important; + visibility: visible !important; + background-color: transparent !important; + border: 0 !important; + transform: none !important; + transition: none; + } + .navbar-expand-lg .offcanvas .offcanvas-header { + display: none; + } + .navbar-expand-lg .offcanvas .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible; + } +} + +@media (min-width: 1200px) { + .navbar-expand-xl { + flex-wrap: nowrap; + justify-content: flex-start; + } + .navbar-expand-xl .navbar-nav { + flex-direction: row; + } + .navbar-expand-xl .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-xl .navbar-nav .nav-link { + padding-right: var(--bs-navbar-nav-link-padding-x); + padding-left: var(--bs-navbar-nav-link-padding-x); + } + .navbar-expand-xl .navbar-nav-scroll { + overflow: visible; + } + .navbar-expand-xl .navbar-collapse { + display: flex !important; + flex-basis: auto; + } + .navbar-expand-xl .navbar-toggler { + display: none; + } + .navbar-expand-xl .offcanvas { + position: static; + z-index: auto; + flex-grow: 1; + width: auto !important; + height: auto !important; + visibility: visible !important; + background-color: transparent !important; + border: 0 !important; + transform: none !important; + transition: none; + } + .navbar-expand-xl .offcanvas .offcanvas-header { + display: none; + } + .navbar-expand-xl .offcanvas .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible; + } +} + +@media (min-width: 1400px) { + .navbar-expand-xxl { + flex-wrap: nowrap; + justify-content: flex-start; + } + .navbar-expand-xxl .navbar-nav { + flex-direction: row; + } + .navbar-expand-xxl .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-xxl .navbar-nav .nav-link { + padding-right: var(--bs-navbar-nav-link-padding-x); + padding-left: var(--bs-navbar-nav-link-padding-x); + } + .navbar-expand-xxl .navbar-nav-scroll { + overflow: visible; + } + .navbar-expand-xxl .navbar-collapse { + display: flex !important; + flex-basis: auto; + } + .navbar-expand-xxl .navbar-toggler { + display: none; + } + .navbar-expand-xxl .offcanvas { + position: static; + z-index: auto; + flex-grow: 1; + width: auto !important; + height: auto !important; + visibility: visible !important; + background-color: transparent !important; + border: 0 !important; + transform: none !important; + transition: none; + } + .navbar-expand-xxl .offcanvas .offcanvas-header { + display: none; + } + .navbar-expand-xxl .offcanvas .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible; + } +} + +.navbar-expand { + flex-wrap: nowrap; + justify-content: flex-start; +} +.navbar-expand .navbar-nav { + flex-direction: row; +} +.navbar-expand .navbar-nav .dropdown-menu { + position: absolute; +} +.navbar-expand .navbar-nav .nav-link { + padding-right: var(--bs-navbar-nav-link-padding-x); + padding-left: var(--bs-navbar-nav-link-padding-x); +} +.navbar-expand .navbar-nav-scroll { + overflow: visible; +} +.navbar-expand .navbar-collapse { + display: flex !important; + flex-basis: auto; +} +.navbar-expand .navbar-toggler { + display: none; +} +.navbar-expand .offcanvas { + position: static; + z-index: auto; + flex-grow: 1; + width: auto !important; + height: auto !important; + visibility: visible !important; + background-color: transparent !important; + border: 0 !important; + transform: none !important; + transition: none; +} +.navbar-expand .offcanvas .offcanvas-header { + display: none; +} +.navbar-expand .offcanvas .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible; +} + +.navbar-dark, +.navbar[data-bs-theme='dark'] { + --bs-navbar-color: rgba(255, 255, 255, 0.55); + --bs-navbar-hover-color: rgba(255, 255, 255, 0.75); + --bs-navbar-disabled-color: rgba(255, 255, 255, 0.25); + --bs-navbar-active-color: #fff; + --bs-navbar-brand-color: #fff; + --bs-navbar-brand-hover-color: #fff; + --bs-navbar-toggler-border-color: rgba(255, 255, 255, 0.1); + --bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); +} + +[data-bs-theme='dark'] .navbar-toggler-icon { + --bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); +} + +.card { + --bs-card-spacer-y: 1rem; + --bs-card-spacer-x: 1rem; + --bs-card-title-spacer-y: 0.5rem; + --bs-card-title-color: ; + --bs-card-subtitle-color: ; + --bs-card-border-width: var(--bs-border-width); + --bs-card-border-color: var(--bs-border-color-translucent); + --bs-card-border-radius: var(--bs-border-radius); + --bs-card-box-shadow: ; + --bs-card-inner-border-radius: calc( + var(--bs-border-radius) - (var(--bs-border-width)) + ); + --bs-card-cap-padding-y: 0.5rem; + --bs-card-cap-padding-x: 1rem; + --bs-card-cap-bg: rgba(var(--bs-body-color-rgb), 0.03); + --bs-card-cap-color: ; + --bs-card-height: ; + --bs-card-color: ; + --bs-card-bg: var(--bs-body-bg); + --bs-card-img-overlay-padding: 1rem; + --bs-card-group-margin: 0.75rem; + position: relative; + display: flex; + flex-direction: column; + min-width: 0; + height: var(--bs-card-height); + color: var(--bs-body-color); + word-wrap: break-word; + background-color: var(--bs-card-bg); + background-clip: border-box; + border: var(--bs-card-border-width) solid var(--bs-card-border-color); + border-radius: var(--bs-card-border-radius); +} +.card > hr { + margin-right: 0; + margin-left: 0; +} +.card > .list-group { + border-top: inherit; + border-bottom: inherit; +} +.card > .list-group:first-child { + border-top-width: 0; + border-top-left-radius: var(--bs-card-inner-border-radius); + border-top-right-radius: var(--bs-card-inner-border-radius); +} +.card > .list-group:last-child { + border-bottom-width: 0; + border-bottom-right-radius: var(--bs-card-inner-border-radius); + border-bottom-left-radius: var(--bs-card-inner-border-radius); +} +.card > .card-header + .list-group, +.card > .list-group + .card-footer { + border-top: 0; +} + +.card-body { + flex: 1 1 auto; + padding: var(--bs-card-spacer-y) var(--bs-card-spacer-x); + color: var(--bs-card-color); +} + +.card-title { + margin-bottom: var(--bs-card-title-spacer-y); + color: var(--bs-card-title-color); +} + +.card-subtitle { + margin-top: calc(-0.5 * var(--bs-card-title-spacer-y)); + margin-bottom: 0; + color: var(--bs-card-subtitle-color); +} + +.card-text:last-child { + margin-bottom: 0; +} + +.card-link + .card-link { + margin-left: var(--bs-card-spacer-x); +} + +.card-header { + padding: var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x); + margin-bottom: 0; + color: var(--bs-card-cap-color); + background-color: var(--bs-card-cap-bg); + border-bottom: var(--bs-card-border-width) solid var(--bs-card-border-color); +} +.card-header:first-child { + border-radius: var(--bs-card-inner-border-radius) + var(--bs-card-inner-border-radius) 0 0; +} + +.card-footer { + padding: var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x); + color: var(--bs-card-cap-color); + background-color: var(--bs-card-cap-bg); + border-top: var(--bs-card-border-width) solid var(--bs-card-border-color); +} +.card-footer:last-child { + border-radius: 0 0 var(--bs-card-inner-border-radius) + var(--bs-card-inner-border-radius); +} + +.card-header-tabs { + margin-right: calc(-0.5 * var(--bs-card-cap-padding-x)); + margin-bottom: calc(-1 * var(--bs-card-cap-padding-y)); + margin-left: calc(-0.5 * var(--bs-card-cap-padding-x)); + border-bottom: 0; +} +.card-header-tabs .nav-link.active { + background-color: var(--bs-card-bg); + border-bottom-color: var(--bs-card-bg); +} + +.card-header-pills { + margin-right: calc(-0.5 * var(--bs-card-cap-padding-x)); + margin-left: calc(-0.5 * var(--bs-card-cap-padding-x)); +} + +.card-img-overlay { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + padding: var(--bs-card-img-overlay-padding); + border-radius: var(--bs-card-inner-border-radius); +} + +.card-img, +.card-img-top, +.card-img-bottom { + width: 100%; +} + +.card-img, +.card-img-top { + border-top-left-radius: var(--bs-card-inner-border-radius); + border-top-right-radius: var(--bs-card-inner-border-radius); +} + +.card-img, +.card-img-bottom { + border-bottom-right-radius: var(--bs-card-inner-border-radius); + border-bottom-left-radius: var(--bs-card-inner-border-radius); +} + +.card-group > .card { + margin-bottom: var(--bs-card-group-margin); +} + +@media (min-width: 576px) { + .card-group { + display: flex; + flex-flow: row wrap; + } + .card-group > .card { + flex: 1 0 0%; + margin-bottom: 0; + } + .card-group > .card + .card { + margin-left: 0; + border-left: 0; + } + .card-group > .card:not(:last-child) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } + .card-group > .card:not(:last-child) .card-img-top, + .card-group > .card:not(:last-child) .card-header { + border-top-right-radius: 0; + } + .card-group > .card:not(:last-child) .card-img-bottom, + .card-group > .card:not(:last-child) .card-footer { + border-bottom-right-radius: 0; + } + .card-group > .card:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + .card-group > .card:not(:first-child) .card-img-top, + .card-group > .card:not(:first-child) .card-header { + border-top-left-radius: 0; + } + .card-group > .card:not(:first-child) .card-img-bottom, + .card-group > .card:not(:first-child) .card-footer { + border-bottom-left-radius: 0; + } +} + +.accordion { + --bs-accordion-color: var(--bs-body-color); + --bs-accordion-bg: var(--bs-body-bg); + --bs-accordion-transition: color 0.15s ease-in-out, + background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, + box-shadow 0.15s ease-in-out, border-radius 0.15s ease; + --bs-accordion-border-color: var(--bs-border-color); + --bs-accordion-border-width: var(--bs-border-width); + --bs-accordion-border-radius: var(--bs-border-radius); + --bs-accordion-inner-border-radius: calc( + var(--bs-border-radius) - (var(--bs-border-width)) + ); + --bs-accordion-btn-padding-x: 1.25rem; + --bs-accordion-btn-padding-y: 1rem; + --bs-accordion-btn-color: var(--bs-body-color); + --bs-accordion-btn-bg: var(--bs-accordion-bg); + --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23212529'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); + --bs-accordion-btn-icon-width: 1.25rem; + --bs-accordion-btn-icon-transform: rotate(-180deg); + --bs-accordion-btn-icon-transition: transform 0.2s ease-in-out; + --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23144b2b'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); + --bs-accordion-btn-focus-border-color: #98ddb5; + --bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(49, 187, 107, 0.25); + --bs-accordion-body-padding-x: 1.25rem; + --bs-accordion-body-padding-y: 1rem; + --bs-accordion-active-color: var(--bs-primary-text-emphasis); + --bs-accordion-active-bg: var(--bs-primary-bg-subtle); +} + +.accordion-button { + position: relative; + display: flex; + align-items: center; + width: 100%; + padding: var(--bs-accordion-btn-padding-y) var(--bs-accordion-btn-padding-x); + font-size: 1rem; + color: var(--bs-accordion-btn-color); + text-align: left; + background-color: var(--bs-accordion-btn-bg); + border: 0; + border-radius: 0; + overflow-anchor: none; + transition: var(--bs-accordion-transition); +} +@media (prefers-reduced-motion: reduce) { + .accordion-button { + transition: none; + } +} +.accordion-button:not(.collapsed) { + color: var(--bs-accordion-active-color); + background-color: var(--bs-accordion-active-bg); + box-shadow: inset 0 calc(-1 * var(--bs-accordion-border-width)) 0 + var(--bs-accordion-border-color); +} +.accordion-button:not(.collapsed)::after { + background-image: var(--bs-accordion-btn-active-icon); + transform: var(--bs-accordion-btn-icon-transform); +} +.accordion-button::after { + flex-shrink: 0; + width: var(--bs-accordion-btn-icon-width); + height: var(--bs-accordion-btn-icon-width); + margin-left: auto; + content: ''; + background-image: var(--bs-accordion-btn-icon); + background-repeat: no-repeat; + background-size: var(--bs-accordion-btn-icon-width); + transition: var(--bs-accordion-btn-icon-transition); +} +@media (prefers-reduced-motion: reduce) { + .accordion-button::after { + transition: none; + } +} +.accordion-button:hover { + z-index: 2; +} +.accordion-button:focus { + z-index: 3; + border-color: var(--bs-accordion-btn-focus-border-color); + outline: 0; + box-shadow: var(--bs-accordion-btn-focus-box-shadow); +} + +.accordion-header { + margin-bottom: 0; +} + +.accordion-item { + color: var(--bs-accordion-color); + background-color: var(--bs-accordion-bg); + border: var(--bs-accordion-border-width) solid + var(--bs-accordion-border-color); +} +.accordion-item:first-of-type { + border-top-left-radius: var(--bs-accordion-border-radius); + border-top-right-radius: var(--bs-accordion-border-radius); +} +.accordion-item:first-of-type .accordion-button { + border-top-left-radius: var(--bs-accordion-inner-border-radius); + border-top-right-radius: var(--bs-accordion-inner-border-radius); +} +.accordion-item:not(:first-of-type) { + border-top: 0; +} +.accordion-item:last-of-type { + border-bottom-right-radius: var(--bs-accordion-border-radius); + border-bottom-left-radius: var(--bs-accordion-border-radius); +} +.accordion-item:last-of-type .accordion-button.collapsed { + border-bottom-right-radius: var(--bs-accordion-inner-border-radius); + border-bottom-left-radius: var(--bs-accordion-inner-border-radius); +} +.accordion-item:last-of-type .accordion-collapse { + border-bottom-right-radius: var(--bs-accordion-border-radius); + border-bottom-left-radius: var(--bs-accordion-border-radius); +} + +.accordion-body { + padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x); +} + +.accordion-flush .accordion-collapse { + border-width: 0; +} + +.accordion-flush .accordion-item { + border-right: 0; + border-left: 0; + border-radius: 0; +} +.accordion-flush .accordion-item:first-child { + border-top: 0; +} +.accordion-flush .accordion-item:last-child { + border-bottom: 0; +} +.accordion-flush .accordion-item .accordion-button, +.accordion-flush .accordion-item .accordion-button.collapsed { + border-radius: 0; +} + +[data-bs-theme='dark'] .accordion-button::after { + --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%2383d6a6'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); + --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%2383d6a6'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); +} + +.breadcrumb { + --bs-breadcrumb-padding-x: 0; + --bs-breadcrumb-padding-y: 0; + --bs-breadcrumb-margin-bottom: 1rem; + --bs-breadcrumb-bg: ; + --bs-breadcrumb-border-radius: ; + --bs-breadcrumb-divider-color: var(--bs-secondary-color); + --bs-breadcrumb-item-padding-x: 0.5rem; + --bs-breadcrumb-item-active-color: var(--bs-secondary-color); + display: flex; + flex-wrap: wrap; + padding: var(--bs-breadcrumb-padding-y) var(--bs-breadcrumb-padding-x); + margin-bottom: var(--bs-breadcrumb-margin-bottom); + font-size: var(--bs-breadcrumb-font-size); + list-style: none; + background-color: var(--bs-breadcrumb-bg); + border-radius: var(--bs-breadcrumb-border-radius); +} + +.breadcrumb-item + .breadcrumb-item { + padding-left: var(--bs-breadcrumb-item-padding-x); +} +.breadcrumb-item + .breadcrumb-item::before { + float: left; + padding-right: var(--bs-breadcrumb-item-padding-x); + color: var(--bs-breadcrumb-divider-color); + content: var(--bs-breadcrumb-divider, '/') + /* rtl: var(--bs-breadcrumb-divider, "/") */; +} + +.breadcrumb-item.active { + color: var(--bs-breadcrumb-item-active-color); +} + +.pagination { + --bs-pagination-padding-x: 0.75rem; + --bs-pagination-padding-y: 0.375rem; + --bs-pagination-font-size: 1rem; + --bs-pagination-color: var(--bs-link-color); + --bs-pagination-bg: var(--bs-body-bg); + --bs-pagination-border-width: var(--bs-border-width); + --bs-pagination-border-color: var(--bs-border-color); + --bs-pagination-border-radius: var(--bs-border-radius); + --bs-pagination-hover-color: var(--bs-link-hover-color); + --bs-pagination-hover-bg: var(--bs-tertiary-bg); + --bs-pagination-hover-border-color: var(--bs-border-color); + --bs-pagination-focus-color: var(--bs-link-hover-color); + --bs-pagination-focus-bg: var(--bs-secondary-bg); + --bs-pagination-focus-box-shadow: 0 0 0 0.25rem rgba(49, 187, 107, 0.25); + --bs-pagination-active-color: #fff; + --bs-pagination-active-bg: #31bb6b; + --bs-pagination-active-border-color: #31bb6b; + --bs-pagination-disabled-color: var(--bs-secondary-color); + --bs-pagination-disabled-bg: var(--bs-secondary-bg); + --bs-pagination-disabled-border-color: var(--bs-border-color); + display: flex; + padding-left: 0; + list-style: none; +} + +.page-link { + position: relative; + display: block; + padding: var(--bs-pagination-padding-y) var(--bs-pagination-padding-x); + font-size: var(--bs-pagination-font-size); + color: var(--bs-pagination-color); + background-color: var(--bs-pagination-bg); + border: var(--bs-pagination-border-width) solid + var(--bs-pagination-border-color); + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, + border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .page-link { + transition: none; + } +} +.page-link:hover { + z-index: 2; + color: var(--bs-pagination-hover-color); + background-color: var(--bs-pagination-hover-bg); + border-color: var(--bs-pagination-hover-border-color); +} +.page-link:focus { + z-index: 3; + color: var(--bs-pagination-focus-color); + background-color: var(--bs-pagination-focus-bg); + outline: 0; + box-shadow: var(--bs-pagination-focus-box-shadow); +} +.page-link.active, +.active > .page-link { + z-index: 3; + color: var(--bs-pagination-active-color); + background-color: var(--bs-pagination-active-bg); + border-color: var(--bs-pagination-active-border-color); +} +.page-link.disabled, +.disabled > .page-link { + color: var(--bs-pagination-disabled-color); + pointer-events: none; + background-color: var(--bs-pagination-disabled-bg); + border-color: var(--bs-pagination-disabled-border-color); +} + +.page-item:not(:first-child) .page-link { + margin-left: calc(var(--bs-border-width) * -1); +} + +.page-item:first-child .page-link { + border-top-left-radius: var(--bs-pagination-border-radius); + border-bottom-left-radius: var(--bs-pagination-border-radius); +} + +.page-item:last-child .page-link { + border-top-right-radius: var(--bs-pagination-border-radius); + border-bottom-right-radius: var(--bs-pagination-border-radius); +} + +.pagination-lg { + --bs-pagination-padding-x: 1.5rem; + --bs-pagination-padding-y: 0.75rem; + --bs-pagination-font-size: 1.25rem; + --bs-pagination-border-radius: var(--bs-border-radius-lg); +} + +.pagination-sm { + --bs-pagination-padding-x: 0.5rem; + --bs-pagination-padding-y: 0.25rem; + --bs-pagination-font-size: 0.875rem; + --bs-pagination-border-radius: var(--bs-border-radius-sm); +} + +.badge { + --bs-badge-padding-x: 0.65em; + --bs-badge-padding-y: 0.35em; + --bs-badge-font-size: 0.75em; + --bs-badge-font-weight: 700; + --bs-badge-color: #fff; + --bs-badge-border-radius: var(--bs-border-radius); + display: inline-block; + padding: var(--bs-badge-padding-y) var(--bs-badge-padding-x); + font-size: var(--bs-badge-font-size); + font-weight: var(--bs-badge-font-weight); + line-height: 1; + color: var(--bs-badge-color); + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: var(--bs-badge-border-radius); +} +.badge:empty { + display: none; +} + +.btn .badge { + position: relative; + top: -1px; +} + +.alert { + --bs-alert-bg: transparent; + --bs-alert-padding-x: 1rem; + --bs-alert-padding-y: 1rem; + --bs-alert-margin-bottom: 1rem; + --bs-alert-color: inherit; + --bs-alert-border-color: transparent; + --bs-alert-border: var(--bs-border-width) solid var(--bs-alert-border-color); + --bs-alert-border-radius: var(--bs-border-radius); + --bs-alert-link-color: inherit; + position: relative; + padding: var(--bs-alert-padding-y) var(--bs-alert-padding-x); + margin-bottom: var(--bs-alert-margin-bottom); + color: var(--bs-alert-color); + background-color: var(--bs-alert-bg); + border: var(--bs-alert-border); + border-radius: var(--bs-alert-border-radius); +} + +.alert-heading { + color: inherit; +} + +.alert-link { + font-weight: 700; + color: var(--bs-alert-link-color); +} + +.alert-dismissible { + padding-right: 3rem; +} +.alert-dismissible .btn-close { + position: absolute; + top: 0; + right: 0; + z-index: 2; + padding: 1.25rem 1rem; +} + +.alert-primary { + --bs-alert-color: var(--bs-primary-text-emphasis); + --bs-alert-bg: var(--bs-primary-bg-subtle); + --bs-alert-border-color: var(--bs-primary-border-subtle); + --bs-alert-link-color: var(--bs-primary-text-emphasis); +} + +.alert-secondary { + --bs-alert-color: var(--bs-secondary-text-emphasis); + --bs-alert-bg: var(--bs-secondary-bg-subtle); + --bs-alert-border-color: var(--bs-secondary-border-subtle); + --bs-alert-link-color: var(--bs-secondary-text-emphasis); +} + +.alert-success { + --bs-alert-color: var(--bs-success-text-emphasis); + --bs-alert-bg: var(--bs-success-bg-subtle); + --bs-alert-border-color: var(--bs-success-border-subtle); + --bs-alert-link-color: var(--bs-success-text-emphasis); +} + +.alert-info { + --bs-alert-color: var(--bs-info-text-emphasis); + --bs-alert-bg: var(--bs-info-bg-subtle); + --bs-alert-border-color: var(--bs-info-border-subtle); + --bs-alert-link-color: var(--bs-info-text-emphasis); +} + +.alert-warning { + --bs-alert-color: var(--bs-warning-text-emphasis); + --bs-alert-bg: var(--bs-warning-bg-subtle); + --bs-alert-border-color: var(--bs-warning-border-subtle); + --bs-alert-link-color: var(--bs-warning-text-emphasis); +} + +.alert-danger { + --bs-alert-color: var(--bs-danger-text-emphasis); + --bs-alert-bg: var(--bs-danger-bg-subtle); + --bs-alert-border-color: var(--bs-danger-border-subtle); + --bs-alert-link-color: var(--bs-danger-text-emphasis); +} + +.alert-light { + --bs-alert-color: var(--bs-light-text-emphasis); + --bs-alert-bg: var(--bs-light-bg-subtle); + --bs-alert-border-color: var(--bs-light-border-subtle); + --bs-alert-link-color: var(--bs-light-text-emphasis); +} + +.alert-dark { + --bs-alert-color: var(--bs-dark-text-emphasis); + --bs-alert-bg: var(--bs-dark-bg-subtle); + --bs-alert-border-color: var(--bs-dark-border-subtle); + --bs-alert-link-color: var(--bs-dark-text-emphasis); +} + +@keyframes progress-bar-stripes { + 0% { + background-position-x: 1rem; + } +} + +.progress, +.progress-stacked { + --bs-progress-height: 1rem; + --bs-progress-font-size: 0.75rem; + --bs-progress-bg: var(--bs-secondary-bg); + --bs-progress-border-radius: var(--bs-border-radius); + --bs-progress-box-shadow: var(--bs-box-shadow-inset); + --bs-progress-bar-color: #fff; + --bs-progress-bar-bg: #31bb6b; + --bs-progress-bar-transition: width 0.6s ease; + display: flex; + height: var(--bs-progress-height); + overflow: hidden; + font-size: var(--bs-progress-font-size); + background-color: var(--bs-progress-bg); + border-radius: var(--bs-progress-border-radius); +} + +.progress-bar { + display: flex; + flex-direction: column; + justify-content: center; + overflow: hidden; + color: var(--bs-progress-bar-color); + text-align: center; + white-space: nowrap; + background-color: var(--bs-progress-bar-bg); + transition: var(--bs-progress-bar-transition); +} +@media (prefers-reduced-motion: reduce) { + .progress-bar { + transition: none; + } +} + +.progress-bar-striped { + background-image: linear-gradient( + 45deg, + rgba(255, 255, 255, 0.15) 25%, + transparent 25%, + transparent 50%, + rgba(255, 255, 255, 0.15) 50%, + rgba(255, 255, 255, 0.15) 75%, + transparent 75%, + transparent + ); + background-size: var(--bs-progress-height) var(--bs-progress-height); +} + +.progress-stacked > .progress { + overflow: visible; +} + +.progress-stacked > .progress > .progress-bar { + width: 100%; +} + +.progress-bar-animated { + animation: 1s linear infinite progress-bar-stripes; +} +@media (prefers-reduced-motion: reduce) { + .progress-bar-animated { + animation: none; + } +} + +.list-group { + --bs-list-group-color: var(--bs-body-color); + --bs-list-group-bg: var(--bs-body-bg); + --bs-list-group-border-color: var(--bs-border-color); + --bs-list-group-border-width: var(--bs-border-width); + --bs-list-group-border-radius: var(--bs-border-radius); + --bs-list-group-item-padding-x: 1rem; + --bs-list-group-item-padding-y: 0.5rem; + --bs-list-group-action-color: var(--bs-secondary-color); + --bs-list-group-action-hover-color: var(--bs-emphasis-color); + --bs-list-group-action-hover-bg: var(--bs-tertiary-bg); + --bs-list-group-action-active-color: var(--bs-body-color); + --bs-list-group-action-active-bg: var(--bs-secondary-bg); + --bs-list-group-disabled-color: var(--bs-secondary-color); + --bs-list-group-disabled-bg: var(--bs-body-bg); + --bs-list-group-active-color: #fff; + --bs-list-group-active-bg: #31bb6b; + --bs-list-group-active-border-color: #31bb6b; + display: flex; + flex-direction: column; + padding-left: 0; + margin-bottom: 0; + border-radius: var(--bs-list-group-border-radius); +} + +.list-group-numbered { + list-style-type: none; + counter-reset: section; +} +.list-group-numbered > .list-group-item::before { + content: counters(section, '.') '. '; + counter-increment: section; +} + +.list-group-item-action { + width: 100%; + color: var(--bs-list-group-action-color); + text-align: inherit; +} +.list-group-item-action:hover, +.list-group-item-action:focus { + z-index: 1; + color: var(--bs-list-group-action-hover-color); + text-decoration: none; + background-color: var(--bs-list-group-action-hover-bg); +} +.list-group-item-action:active { + color: var(--bs-list-group-action-active-color); + background-color: var(--bs-list-group-action-active-bg); +} + +.list-group-item { + position: relative; + display: block; + padding: var(--bs-list-group-item-padding-y) + var(--bs-list-group-item-padding-x); + color: var(--bs-list-group-color); + background-color: var(--bs-list-group-bg); + border: var(--bs-list-group-border-width) solid + var(--bs-list-group-border-color); +} +.list-group-item:first-child { + border-top-left-radius: inherit; + border-top-right-radius: inherit; +} +.list-group-item:last-child { + border-bottom-right-radius: inherit; + border-bottom-left-radius: inherit; +} +.list-group-item.disabled, +.list-group-item:disabled { + color: var(--bs-list-group-disabled-color); + pointer-events: none; + background-color: var(--bs-list-group-disabled-bg); +} +.list-group-item.active { + z-index: 2; + color: var(--bs-list-group-active-color); + background-color: var(--bs-list-group-active-bg); + border-color: var(--bs-list-group-active-border-color); +} +.list-group-item + .list-group-item { + border-top-width: 0; +} +.list-group-item + .list-group-item.active { + margin-top: calc(-1 * var(--bs-list-group-border-width)); + border-top-width: var(--bs-list-group-border-width); +} + +.list-group-horizontal { + flex-direction: row; +} +.list-group-horizontal > .list-group-item:first-child:not(:last-child) { + border-bottom-left-radius: var(--bs-list-group-border-radius); + border-top-right-radius: 0; +} +.list-group-horizontal > .list-group-item:last-child:not(:first-child) { + border-top-right-radius: var(--bs-list-group-border-radius); + border-bottom-left-radius: 0; +} +.list-group-horizontal > .list-group-item.active { + margin-top: 0; +} +.list-group-horizontal > .list-group-item + .list-group-item { + border-top-width: var(--bs-list-group-border-width); + border-left-width: 0; +} +.list-group-horizontal > .list-group-item + .list-group-item.active { + margin-left: calc(-1 * var(--bs-list-group-border-width)); + border-left-width: var(--bs-list-group-border-width); +} + +@media (min-width: 576px) { + .list-group-horizontal-sm { + flex-direction: row; + } + .list-group-horizontal-sm > .list-group-item:first-child:not(:last-child) { + border-bottom-left-radius: var(--bs-list-group-border-radius); + border-top-right-radius: 0; + } + .list-group-horizontal-sm > .list-group-item:last-child:not(:first-child) { + border-top-right-radius: var(--bs-list-group-border-radius); + border-bottom-left-radius: 0; + } + .list-group-horizontal-sm > .list-group-item.active { + margin-top: 0; + } + .list-group-horizontal-sm > .list-group-item + .list-group-item { + border-top-width: var(--bs-list-group-border-width); + border-left-width: 0; + } + .list-group-horizontal-sm > .list-group-item + .list-group-item.active { + margin-left: calc(-1 * var(--bs-list-group-border-width)); + border-left-width: var(--bs-list-group-border-width); + } +} + +@media (min-width: 768px) { + .list-group-horizontal-md { + flex-direction: row; + } + .list-group-horizontal-md > .list-group-item:first-child:not(:last-child) { + border-bottom-left-radius: var(--bs-list-group-border-radius); + border-top-right-radius: 0; + } + .list-group-horizontal-md > .list-group-item:last-child:not(:first-child) { + border-top-right-radius: var(--bs-list-group-border-radius); + border-bottom-left-radius: 0; + } + .list-group-horizontal-md > .list-group-item.active { + margin-top: 0; + } + .list-group-horizontal-md > .list-group-item + .list-group-item { + border-top-width: var(--bs-list-group-border-width); + border-left-width: 0; + } + .list-group-horizontal-md > .list-group-item + .list-group-item.active { + margin-left: calc(-1 * var(--bs-list-group-border-width)); + border-left-width: var(--bs-list-group-border-width); + } +} + +@media (min-width: 992px) { + .list-group-horizontal-lg { + flex-direction: row; + } + .list-group-horizontal-lg > .list-group-item:first-child:not(:last-child) { + border-bottom-left-radius: var(--bs-list-group-border-radius); + border-top-right-radius: 0; + } + .list-group-horizontal-lg > .list-group-item:last-child:not(:first-child) { + border-top-right-radius: var(--bs-list-group-border-radius); + border-bottom-left-radius: 0; + } + .list-group-horizontal-lg > .list-group-item.active { + margin-top: 0; + } + .list-group-horizontal-lg > .list-group-item + .list-group-item { + border-top-width: var(--bs-list-group-border-width); + border-left-width: 0; + } + .list-group-horizontal-lg > .list-group-item + .list-group-item.active { + margin-left: calc(-1 * var(--bs-list-group-border-width)); + border-left-width: var(--bs-list-group-border-width); + } +} + +@media (min-width: 1200px) { + .list-group-horizontal-xl { + flex-direction: row; + } + .list-group-horizontal-xl > .list-group-item:first-child:not(:last-child) { + border-bottom-left-radius: var(--bs-list-group-border-radius); + border-top-right-radius: 0; + } + .list-group-horizontal-xl > .list-group-item:last-child:not(:first-child) { + border-top-right-radius: var(--bs-list-group-border-radius); + border-bottom-left-radius: 0; + } + .list-group-horizontal-xl > .list-group-item.active { + margin-top: 0; + } + .list-group-horizontal-xl > .list-group-item + .list-group-item { + border-top-width: var(--bs-list-group-border-width); + border-left-width: 0; + } + .list-group-horizontal-xl > .list-group-item + .list-group-item.active { + margin-left: calc(-1 * var(--bs-list-group-border-width)); + border-left-width: var(--bs-list-group-border-width); + } +} + +@media (min-width: 1400px) { + .list-group-horizontal-xxl { + flex-direction: row; + } + .list-group-horizontal-xxl > .list-group-item:first-child:not(:last-child) { + border-bottom-left-radius: var(--bs-list-group-border-radius); + border-top-right-radius: 0; + } + .list-group-horizontal-xxl > .list-group-item:last-child:not(:first-child) { + border-top-right-radius: var(--bs-list-group-border-radius); + border-bottom-left-radius: 0; + } + .list-group-horizontal-xxl > .list-group-item.active { + margin-top: 0; + } + .list-group-horizontal-xxl > .list-group-item + .list-group-item { + border-top-width: var(--bs-list-group-border-width); + border-left-width: 0; + } + .list-group-horizontal-xxl > .list-group-item + .list-group-item.active { + margin-left: calc(-1 * var(--bs-list-group-border-width)); + border-left-width: var(--bs-list-group-border-width); + } +} + +.list-group-flush { + border-radius: 0; +} +.list-group-flush > .list-group-item { + border-width: 0 0 var(--bs-list-group-border-width); +} +.list-group-flush > .list-group-item:last-child { + border-bottom-width: 0; +} + +.list-group-item-primary { + --bs-list-group-color: var(--bs-primary-text-emphasis); + --bs-list-group-bg: var(--bs-primary-bg-subtle); + --bs-list-group-border-color: var(--bs-primary-border-subtle); + --bs-list-group-action-hover-color: var(--bs-emphasis-color); + --bs-list-group-action-hover-bg: var(--bs-primary-border-subtle); + --bs-list-group-action-active-color: var(--bs-emphasis-color); + --bs-list-group-action-active-bg: var(--bs-primary-border-subtle); + --bs-list-group-active-color: var(--bs-primary-bg-subtle); + --bs-list-group-active-bg: var(--bs-primary-text-emphasis); + --bs-list-group-active-border-color: var(--bs-primary-text-emphasis); +} + +.list-group-item-secondary { + --bs-list-group-color: var(--bs-secondary-text-emphasis); + --bs-list-group-bg: var(--bs-secondary-bg-subtle); + --bs-list-group-border-color: var(--bs-secondary-border-subtle); + --bs-list-group-action-hover-color: var(--bs-emphasis-color); + --bs-list-group-action-hover-bg: var(--bs-secondary-border-subtle); + --bs-list-group-action-active-color: var(--bs-emphasis-color); + --bs-list-group-action-active-bg: var(--bs-secondary-border-subtle); + --bs-list-group-active-color: var(--bs-secondary-bg-subtle); + --bs-list-group-active-bg: var(--bs-secondary-text-emphasis); + --bs-list-group-active-border-color: var(--bs-secondary-text-emphasis); +} + +.list-group-item-success { + --bs-list-group-color: var(--bs-success-text-emphasis); + --bs-list-group-bg: var(--bs-success-bg-subtle); + --bs-list-group-border-color: var(--bs-success-border-subtle); + --bs-list-group-action-hover-color: var(--bs-emphasis-color); + --bs-list-group-action-hover-bg: var(--bs-success-border-subtle); + --bs-list-group-action-active-color: var(--bs-emphasis-color); + --bs-list-group-action-active-bg: var(--bs-success-border-subtle); + --bs-list-group-active-color: var(--bs-success-bg-subtle); + --bs-list-group-active-bg: var(--bs-success-text-emphasis); + --bs-list-group-active-border-color: var(--bs-success-text-emphasis); +} + +.list-group-item-info { + --bs-list-group-color: var(--bs-info-text-emphasis); + --bs-list-group-bg: var(--bs-info-bg-subtle); + --bs-list-group-border-color: var(--bs-info-border-subtle); + --bs-list-group-action-hover-color: var(--bs-emphasis-color); + --bs-list-group-action-hover-bg: var(--bs-info-border-subtle); + --bs-list-group-action-active-color: var(--bs-emphasis-color); + --bs-list-group-action-active-bg: var(--bs-info-border-subtle); + --bs-list-group-active-color: var(--bs-info-bg-subtle); + --bs-list-group-active-bg: var(--bs-info-text-emphasis); + --bs-list-group-active-border-color: var(--bs-info-text-emphasis); +} + +.list-group-item-warning { + --bs-list-group-color: var(--bs-warning-text-emphasis); + --bs-list-group-bg: var(--bs-warning-bg-subtle); + --bs-list-group-border-color: var(--bs-warning-border-subtle); + --bs-list-group-action-hover-color: var(--bs-emphasis-color); + --bs-list-group-action-hover-bg: var(--bs-warning-border-subtle); + --bs-list-group-action-active-color: var(--bs-emphasis-color); + --bs-list-group-action-active-bg: var(--bs-warning-border-subtle); + --bs-list-group-active-color: var(--bs-warning-bg-subtle); + --bs-list-group-active-bg: var(--bs-warning-text-emphasis); + --bs-list-group-active-border-color: var(--bs-warning-text-emphasis); +} + +.list-group-item-danger { + --bs-list-group-color: var(--bs-danger-text-emphasis); + --bs-list-group-bg: var(--bs-danger-bg-subtle); + --bs-list-group-border-color: var(--bs-danger-border-subtle); + --bs-list-group-action-hover-color: var(--bs-emphasis-color); + --bs-list-group-action-hover-bg: var(--bs-danger-border-subtle); + --bs-list-group-action-active-color: var(--bs-emphasis-color); + --bs-list-group-action-active-bg: var(--bs-danger-border-subtle); + --bs-list-group-active-color: var(--bs-danger-bg-subtle); + --bs-list-group-active-bg: var(--bs-danger-text-emphasis); + --bs-list-group-active-border-color: var(--bs-danger-text-emphasis); +} + +.list-group-item-light { + --bs-list-group-color: var(--bs-light-text-emphasis); + --bs-list-group-bg: var(--bs-light-bg-subtle); + --bs-list-group-border-color: var(--bs-light-border-subtle); + --bs-list-group-action-hover-color: var(--bs-emphasis-color); + --bs-list-group-action-hover-bg: var(--bs-light-border-subtle); + --bs-list-group-action-active-color: var(--bs-emphasis-color); + --bs-list-group-action-active-bg: var(--bs-light-border-subtle); + --bs-list-group-active-color: var(--bs-light-bg-subtle); + --bs-list-group-active-bg: var(--bs-light-text-emphasis); + --bs-list-group-active-border-color: var(--bs-light-text-emphasis); +} + +.list-group-item-dark { + --bs-list-group-color: var(--bs-dark-text-emphasis); + --bs-list-group-bg: var(--bs-dark-bg-subtle); + --bs-list-group-border-color: var(--bs-dark-border-subtle); + --bs-list-group-action-hover-color: var(--bs-emphasis-color); + --bs-list-group-action-hover-bg: var(--bs-dark-border-subtle); + --bs-list-group-action-active-color: var(--bs-emphasis-color); + --bs-list-group-action-active-bg: var(--bs-dark-border-subtle); + --bs-list-group-active-color: var(--bs-dark-bg-subtle); + --bs-list-group-active-bg: var(--bs-dark-text-emphasis); + --bs-list-group-active-border-color: var(--bs-dark-text-emphasis); +} + +.btn-close { + --bs-btn-close-color: #000; + --bs-btn-close-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414z'/%3e%3c/svg%3e"); + --bs-btn-close-opacity: 0.5; + --bs-btn-close-hover-opacity: 0.75; + --bs-btn-close-focus-shadow: 0 0 0 0.25rem rgba(49, 187, 107, 0.25); + --bs-btn-close-focus-opacity: 1; + --bs-btn-close-disabled-opacity: 0.25; + --bs-btn-close-white-filter: invert(1) grayscale(100%) brightness(200%); + box-sizing: content-box; + width: 1em; + height: 1em; + padding: 0.25em 0.25em; + color: var(--bs-btn-close-color); + background: transparent var(--bs-btn-close-bg) center/1em auto no-repeat; + border: 0; + border-radius: 0.375rem; + opacity: var(--bs-btn-close-opacity); +} +.btn-close:hover { + color: var(--bs-btn-close-color); + text-decoration: none; + opacity: var(--bs-btn-close-hover-opacity); +} +.btn-close:focus { + outline: 0; + box-shadow: var(--bs-btn-close-focus-shadow); + opacity: var(--bs-btn-close-focus-opacity); +} +.btn-close:disabled, +.btn-close.disabled { + pointer-events: none; + user-select: none; + opacity: var(--bs-btn-close-disabled-opacity); +} + +.btn-close-white { + filter: var(--bs-btn-close-white-filter); +} + +[data-bs-theme='dark'] .btn-close { + filter: var(--bs-btn-close-white-filter); +} + +.toast { + --bs-toast-zindex: 1090; + --bs-toast-padding-x: 0.75rem; + --bs-toast-padding-y: 0.5rem; + --bs-toast-spacing: 1.5rem; + --bs-toast-max-width: 350px; + --bs-toast-font-size: 0.875rem; + --bs-toast-color: ; + --bs-toast-bg: rgba(var(--bs-body-bg-rgb), 0.85); + --bs-toast-border-width: var(--bs-border-width); + --bs-toast-border-color: var(--bs-border-color-translucent); + --bs-toast-border-radius: var(--bs-border-radius); + --bs-toast-box-shadow: var(--bs-box-shadow); + --bs-toast-header-color: var(--bs-secondary-color); + --bs-toast-header-bg: rgba(var(--bs-body-bg-rgb), 0.85); + --bs-toast-header-border-color: var(--bs-border-color-translucent); + width: var(--bs-toast-max-width); + max-width: 100%; + font-size: var(--bs-toast-font-size); + color: var(--bs-toast-color); + pointer-events: auto; + background-color: var(--bs-toast-bg); + background-clip: padding-box; + border: var(--bs-toast-border-width) solid var(--bs-toast-border-color); + box-shadow: var(--bs-toast-box-shadow); + border-radius: var(--bs-toast-border-radius); +} +.showing { + opacity: 0; +} +.toast:not(.show) { + display: none; +} + +.toast-container { + --bs-toast-zindex: 1090; + position: absolute; + z-index: var(--bs-toast-zindex); + width: max-content; + max-width: 100%; + pointer-events: none; +} +.toast-container > :not(:last-child) { + margin-bottom: var(--bs-toast-spacing); +} + +.toast-header { + display: flex; + align-items: center; + padding: var(--bs-toast-padding-y) var(--bs-toast-padding-x); + color: var(--bs-toast-header-color); + background-color: var(--bs-toast-header-bg); + background-clip: padding-box; + border-bottom: var(--bs-toast-border-width) solid + var(--bs-toast-header-border-color); + border-top-left-radius: calc( + var(--bs-toast-border-radius) - var(--bs-toast-border-width) + ); + border-top-right-radius: calc( + var(--bs-toast-border-radius) - var(--bs-toast-border-width) + ); +} +.toast-header .btn-close { + margin-right: calc(-0.5 * var(--bs-toast-padding-x)); + margin-left: var(--bs-toast-padding-x); +} + +.toast-body { + padding: var(--bs-toast-padding-x); + word-wrap: break-word; +} + +.modal { + --bs-modal-zindex: 1055; + --bs-modal-width: 500px; + --bs-modal-padding: 1rem; + --bs-modal-margin: 0.5rem; + --bs-modal-color: ; + --bs-modal-bg: var(--bs-body-bg); + --bs-modal-border-color: var(--bs-border-color-translucent); + --bs-modal-border-width: var(--bs-border-width); + --bs-modal-border-radius: var(--bs-border-radius-lg); + --bs-modal-box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075); + --bs-modal-inner-border-radius: calc( + var(--bs-border-radius-lg) - (var(--bs-border-width)) + ); + --bs-modal-header-padding-x: 1rem; + --bs-modal-header-padding-y: 1rem; + --bs-modal-header-padding: 1rem 1rem; + --bs-modal-header-border-color: var(--bs-border-color); + --bs-modal-header-border-width: var(--bs-border-width); + --bs-modal-title-line-height: 1.5; + --bs-modal-footer-gap: 0.5rem; + --bs-modal-footer-bg: ; + --bs-modal-footer-border-color: var(--bs-border-color); + --bs-modal-footer-border-width: var(--bs-border-width); + position: fixed; + top: 0; + left: 0; + z-index: var(--bs-modal-zindex); + display: none; + width: 100%; + height: 100%; + overflow-x: hidden; + overflow-y: auto; + outline: 0; +} + +.modal-dialog { + position: relative; + width: auto; + margin: var(--bs-modal-margin); + pointer-events: none; +} +.modal.fade .modal-dialog { + transition: transform 0.3s ease-out; + transform: translate(0, -50px); +} +@media (prefers-reduced-motion: reduce) { + .modal.fade .modal-dialog { + transition: none; + } +} +.modal.show .modal-dialog { + transform: none; +} +.modal.modal-static .modal-dialog { + transform: scale(1.02); +} + +.modal-dialog-scrollable { + height: calc(100% - var(--bs-modal-margin) * 2); +} +.modal-dialog-scrollable .modal-content { + max-height: 100%; + overflow: hidden; +} +.modal-dialog-scrollable .modal-body { + overflow-y: auto; +} + +.modal-dialog-centered { + display: flex; + align-items: center; + min-height: calc(100% - var(--bs-modal-margin) * 2); +} + +.modal-content { + position: relative; + display: flex; + flex-direction: column; + width: 100%; + color: var(--bs-modal-color); + pointer-events: auto; + background-color: var(--bs-modal-bg); + background-clip: padding-box; + border: var(--bs-modal-border-width) solid var(--bs-modal-border-color); + border-radius: var(--bs-modal-border-radius); + outline: 0; +} + +.modal-backdrop { + --bs-backdrop-zindex: 1050; + --bs-backdrop-bg: #000; + --bs-backdrop-opacity: 0.5; + position: fixed; + top: 0; + left: 0; + z-index: var(--bs-backdrop-zindex); + width: 100vw; + height: 100vh; + background-color: var(--bs-backdrop-bg); +} +.modal-backdrop.fade { + opacity: 0; +} +.modal-backdrop.show { + opacity: var(--bs-backdrop-opacity); +} + +.modal-header { + display: flex; + flex-shrink: 0; + align-items: center; + justify-content: space-between; + padding: var(--bs-modal-header-padding); + border-bottom: var(--bs-modal-header-border-width) solid + var(--bs-modal-header-border-color); + border-top-left-radius: var(--bs-modal-inner-border-radius); + border-top-right-radius: var(--bs-modal-inner-border-radius); +} +.modal-header .btn-close { + padding: calc(var(--bs-modal-header-padding-y) * 0.5) + calc(var(--bs-modal-header-padding-x) * 0.5); + margin: calc(-0.5 * var(--bs-modal-header-padding-y)) + calc(-0.5 * var(--bs-modal-header-padding-x)) + calc(-0.5 * var(--bs-modal-header-padding-y)) auto; +} + +.modal-title { + margin-bottom: 0; + line-height: var(--bs-modal-title-line-height); +} + +.modal-body { + position: relative; + flex: 1 1 auto; + padding: var(--bs-modal-padding); +} + +.modal-footer { + display: flex; + flex-shrink: 0; + flex-wrap: wrap; + align-items: center; + justify-content: flex-end; + padding: calc(var(--bs-modal-padding) - var(--bs-modal-footer-gap) * 0.5); + background-color: var(--bs-modal-footer-bg); + border-top: var(--bs-modal-footer-border-width) solid + var(--bs-modal-footer-border-color); + border-bottom-right-radius: var(--bs-modal-inner-border-radius); + border-bottom-left-radius: var(--bs-modal-inner-border-radius); +} +.modal-footer > * { + margin: calc(var(--bs-modal-footer-gap) * 0.5); +} + +@media (min-width: 576px) { + .modal { + --bs-modal-margin: 1.75rem; + --bs-modal-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); + } + .modal-dialog { + max-width: var(--bs-modal-width); + margin-right: auto; + margin-left: auto; + } + .modal-sm { + --bs-modal-width: 300px; + } +} + +@media (min-width: 992px) { + .modal-lg, + .modal-xl { + --bs-modal-width: 800px; + } +} + +@media (min-width: 1200px) { + .modal-xl { + --bs-modal-width: 1140px; + } +} + +.modal-fullscreen { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; +} +.modal-fullscreen .modal-content { + height: 100%; + border: 0; + border-radius: 0; +} +.modal-fullscreen .modal-header, +.modal-fullscreen .modal-footer { + border-radius: 0; +} +.modal-fullscreen .modal-body { + overflow-y: auto; +} + +@media (max-width: 575.98px) { + .modal-fullscreen-sm-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; + } + .modal-fullscreen-sm-down .modal-content { + height: 100%; + border: 0; + border-radius: 0; + } + .modal-fullscreen-sm-down .modal-header, + .modal-fullscreen-sm-down .modal-footer { + border-radius: 0; + } + .modal-fullscreen-sm-down .modal-body { + overflow-y: auto; + } +} + +@media (max-width: 767.98px) { + .modal-fullscreen-md-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; + } + .modal-fullscreen-md-down .modal-content { + height: 100%; + border: 0; + border-radius: 0; + } + .modal-fullscreen-md-down .modal-header, + .modal-fullscreen-md-down .modal-footer { + border-radius: 0; + } + .modal-fullscreen-md-down .modal-body { + overflow-y: auto; + } +} + +@media (max-width: 991.98px) { + .modal-fullscreen-lg-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; + } + .modal-fullscreen-lg-down .modal-content { + height: 100%; + border: 0; + border-radius: 0; + } + .modal-fullscreen-lg-down .modal-header, + .modal-fullscreen-lg-down .modal-footer { + border-radius: 0; + } + .modal-fullscreen-lg-down .modal-body { + overflow-y: auto; + } +} + +@media (max-width: 1199.98px) { + .modal-fullscreen-xl-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; + } + .modal-fullscreen-xl-down .modal-content { + height: 100%; + border: 0; + border-radius: 0; + } + .modal-fullscreen-xl-down .modal-header, + .modal-fullscreen-xl-down .modal-footer { + border-radius: 0; + } + .modal-fullscreen-xl-down .modal-body { + overflow-y: auto; + } +} + +@media (max-width: 1399.98px) { + .modal-fullscreen-xxl-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; + } + .modal-fullscreen-xxl-down .modal-content { + height: 100%; + border: 0; + border-radius: 0; + } + .modal-fullscreen-xxl-down .modal-header, + .modal-fullscreen-xxl-down .modal-footer { + border-radius: 0; + } + .modal-fullscreen-xxl-down .modal-body { + overflow-y: auto; + } +} + +.tooltip { + --bs-tooltip-zindex: 1080; + --bs-tooltip-max-width: 200px; + --bs-tooltip-padding-x: 0.5rem; + --bs-tooltip-padding-y: 0.25rem; + --bs-tooltip-margin: ; + --bs-tooltip-font-size: 0.875rem; + --bs-tooltip-color: var(--bs-body-bg); + --bs-tooltip-bg: var(--bs-emphasis-color); + --bs-tooltip-border-radius: var(--bs-border-radius); + --bs-tooltip-opacity: 0.9; + --bs-tooltip-arrow-width: 0.8rem; + --bs-tooltip-arrow-height: 0.4rem; + z-index: var(--bs-tooltip-zindex); + display: block; + margin: var(--bs-tooltip-margin); + font-family: var(--bs-font-sans-serif); + font-style: normal; + font-weight: 400; + line-height: 1.5; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + white-space: normal; + word-spacing: normal; + line-break: auto; + font-size: var(--bs-tooltip-font-size); + word-wrap: break-word; + opacity: 0; +} +.tooltip.show { + opacity: var(--bs-tooltip-opacity); +} +.tooltip .tooltip-arrow { + display: block; + width: var(--bs-tooltip-arrow-width); + height: var(--bs-tooltip-arrow-height); +} +.tooltip .tooltip-arrow::before { + position: absolute; + content: ''; + border-color: transparent; + border-style: solid; +} + +.bs-tooltip-top .tooltip-arrow, +.bs-tooltip-auto[data-popper-placement^='top'] .tooltip-arrow { + bottom: calc(-1 * var(--bs-tooltip-arrow-height)); +} +.bs-tooltip-top .tooltip-arrow::before, +.bs-tooltip-auto[data-popper-placement^='top'] .tooltip-arrow::before { + top: -1px; + border-width: var(--bs-tooltip-arrow-height) + calc(var(--bs-tooltip-arrow-width) * 0.5) 0; + border-top-color: var(--bs-tooltip-bg); +} + +/* rtl:begin:ignore */ +.bs-tooltip-end .tooltip-arrow, +.bs-tooltip-auto[data-popper-placement^='right'] .tooltip-arrow { + left: calc(-1 * var(--bs-tooltip-arrow-height)); + width: var(--bs-tooltip-arrow-height); + height: var(--bs-tooltip-arrow-width); +} +.bs-tooltip-end .tooltip-arrow::before, +.bs-tooltip-auto[data-popper-placement^='right'] .tooltip-arrow::before { + right: -1px; + border-width: calc(var(--bs-tooltip-arrow-width) * 0.5) + var(--bs-tooltip-arrow-height) calc(var(--bs-tooltip-arrow-width) * 0.5) 0; + border-right-color: var(--bs-tooltip-bg); +} + +/* rtl:end:ignore */ +.bs-tooltip-bottom .tooltip-arrow, +.bs-tooltip-auto[data-popper-placement^='bottom'] .tooltip-arrow { + top: calc(-1 * var(--bs-tooltip-arrow-height)); +} +.bs-tooltip-bottom .tooltip-arrow::before, +.bs-tooltip-auto[data-popper-placement^='bottom'] .tooltip-arrow::before { + bottom: -1px; + border-width: 0 calc(var(--bs-tooltip-arrow-width) * 0.5) + var(--bs-tooltip-arrow-height); + border-bottom-color: var(--bs-tooltip-bg); +} + +/* rtl:begin:ignore */ +.bs-tooltip-start .tooltip-arrow, +.bs-tooltip-auto[data-popper-placement^='left'] .tooltip-arrow { + right: calc(-1 * var(--bs-tooltip-arrow-height)); + width: var(--bs-tooltip-arrow-height); + height: var(--bs-tooltip-arrow-width); +} +.bs-tooltip-start .tooltip-arrow::before, +.bs-tooltip-auto[data-popper-placement^='left'] .tooltip-arrow::before { + left: -1px; + border-width: calc(var(--bs-tooltip-arrow-width) * 0.5) 0 + calc(var(--bs-tooltip-arrow-width) * 0.5) var(--bs-tooltip-arrow-height); + border-left-color: var(--bs-tooltip-bg); +} + +/* rtl:end:ignore */ +.tooltip-inner { + max-width: var(--bs-tooltip-max-width); + padding: var(--bs-tooltip-padding-y) var(--bs-tooltip-padding-x); + color: var(--bs-tooltip-color); + text-align: center; + background-color: var(--bs-tooltip-bg); + border-radius: var(--bs-tooltip-border-radius); +} + +.popover { + --bs-popover-zindex: 1070; + --bs-popover-max-width: 276px; + --bs-popover-font-size: 0.875rem; + --bs-popover-bg: var(--bs-body-bg); + --bs-popover-border-width: var(--bs-border-width); + --bs-popover-border-color: var(--bs-border-color-translucent); + --bs-popover-border-radius: var(--bs-border-radius-lg); + --bs-popover-inner-border-radius: calc( + var(--bs-border-radius-lg) - var(--bs-border-width) + ); + --bs-popover-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); + --bs-popover-header-padding-x: 1rem; + --bs-popover-header-padding-y: 0.5rem; + --bs-popover-header-font-size: 1rem; + --bs-popover-header-color: inherit; + --bs-popover-header-bg: var(--bs-secondary-bg); + --bs-popover-body-padding-x: 1rem; + --bs-popover-body-padding-y: 1rem; + --bs-popover-body-color: var(--bs-body-color); + --bs-popover-arrow-width: 1rem; + --bs-popover-arrow-height: 0.5rem; + --bs-popover-arrow-border: var(--bs-popover-border-color); + z-index: var(--bs-popover-zindex); + display: block; + max-width: var(--bs-popover-max-width); + font-family: var(--bs-font-sans-serif); + font-style: normal; + font-weight: 400; + line-height: 1.5; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + white-space: normal; + word-spacing: normal; + line-break: auto; + font-size: var(--bs-popover-font-size); + word-wrap: break-word; + background-color: var(--bs-popover-bg); + background-clip: padding-box; + border: var(--bs-popover-border-width) solid var(--bs-popover-border-color); + border-radius: var(--bs-popover-border-radius); +} +.popover .popover-arrow { + display: block; + width: var(--bs-popover-arrow-width); + height: var(--bs-popover-arrow-height); +} +.popover .popover-arrow::before, +.popover .popover-arrow::after { + position: absolute; + display: block; + content: ''; + border-color: transparent; + border-style: solid; + border-width: 0; +} + +.bs-popover-top > .popover-arrow, +.bs-popover-auto[data-popper-placement^='top'] > .popover-arrow { + bottom: calc( + -1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width) + ); +} +.bs-popover-top > .popover-arrow::before, +.bs-popover-auto[data-popper-placement^='top'] > .popover-arrow::before, +.bs-popover-top > .popover-arrow::after, +.bs-popover-auto[data-popper-placement^='top'] > .popover-arrow::after { + border-width: var(--bs-popover-arrow-height) + calc(var(--bs-popover-arrow-width) * 0.5) 0; +} +.bs-popover-top > .popover-arrow::before, +.bs-popover-auto[data-popper-placement^='top'] > .popover-arrow::before { + bottom: 0; + border-top-color: var(--bs-popover-arrow-border); +} +.bs-popover-top > .popover-arrow::after, +.bs-popover-auto[data-popper-placement^='top'] > .popover-arrow::after { + bottom: var(--bs-popover-border-width); + border-top-color: var(--bs-popover-bg); +} + +/* rtl:begin:ignore */ +.bs-popover-end > .popover-arrow, +.bs-popover-auto[data-popper-placement^='right'] > .popover-arrow { + left: calc( + -1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width) + ); + width: var(--bs-popover-arrow-height); + height: var(--bs-popover-arrow-width); +} +.bs-popover-end > .popover-arrow::before, +.bs-popover-auto[data-popper-placement^='right'] > .popover-arrow::before, +.bs-popover-end > .popover-arrow::after, +.bs-popover-auto[data-popper-placement^='right'] > .popover-arrow::after { + border-width: calc(var(--bs-popover-arrow-width) * 0.5) + var(--bs-popover-arrow-height) calc(var(--bs-popover-arrow-width) * 0.5) 0; +} +.bs-popover-end > .popover-arrow::before, +.bs-popover-auto[data-popper-placement^='right'] > .popover-arrow::before { + left: 0; + border-right-color: var(--bs-popover-arrow-border); +} +.bs-popover-end > .popover-arrow::after, +.bs-popover-auto[data-popper-placement^='right'] > .popover-arrow::after { + left: var(--bs-popover-border-width); + border-right-color: var(--bs-popover-bg); +} + +/* rtl:end:ignore */ +.bs-popover-bottom > .popover-arrow, +.bs-popover-auto[data-popper-placement^='bottom'] > .popover-arrow { + top: calc( + -1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width) + ); +} +.bs-popover-bottom > .popover-arrow::before, +.bs-popover-auto[data-popper-placement^='bottom'] > .popover-arrow::before, +.bs-popover-bottom > .popover-arrow::after, +.bs-popover-auto[data-popper-placement^='bottom'] > .popover-arrow::after { + border-width: 0 calc(var(--bs-popover-arrow-width) * 0.5) + var(--bs-popover-arrow-height); +} +.bs-popover-bottom > .popover-arrow::before, +.bs-popover-auto[data-popper-placement^='bottom'] > .popover-arrow::before { + top: 0; + border-bottom-color: var(--bs-popover-arrow-border); +} +.bs-popover-bottom > .popover-arrow::after, +.bs-popover-auto[data-popper-placement^='bottom'] > .popover-arrow::after { + top: var(--bs-popover-border-width); + border-bottom-color: var(--bs-popover-bg); +} + +.bs-popover-bottom .popover-header::before, +.bs-popover-auto[data-popper-placement^='bottom'] .popover-header::before { + position: absolute; + top: 0; + left: 50%; + display: block; + width: var(--bs-popover-arrow-width); + margin-left: calc(-0.5 * var(--bs-popover-arrow-width)); + content: ''; + border-bottom: var(--bs-popover-border-width) solid + var(--bs-popover-header-bg); +} + +/* rtl:begin:ignore */ +.bs-popover-start > .popover-arrow, +.bs-popover-auto[data-popper-placement^='left'] > .popover-arrow { + right: calc( + -1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width) + ); + width: var(--bs-popover-arrow-height); + height: var(--bs-popover-arrow-width); +} +.bs-popover-start > .popover-arrow::before, +.bs-popover-auto[data-popper-placement^='left'] > .popover-arrow::before, +.bs-popover-start > .popover-arrow::after, +.bs-popover-auto[data-popper-placement^='left'] > .popover-arrow::after { + border-width: calc(var(--bs-popover-arrow-width) * 0.5) 0 + calc(var(--bs-popover-arrow-width) * 0.5) var(--bs-popover-arrow-height); +} +.bs-popover-start > .popover-arrow::before, +.bs-popover-auto[data-popper-placement^='left'] > .popover-arrow::before { + right: 0; + border-left-color: var(--bs-popover-arrow-border); +} +.bs-popover-start > .popover-arrow::after, +.bs-popover-auto[data-popper-placement^='left'] > .popover-arrow::after { + right: var(--bs-popover-border-width); + border-left-color: var(--bs-popover-bg); +} + +/* rtl:end:ignore */ +.popover-header { + padding: var(--bs-popover-header-padding-y) var(--bs-popover-header-padding-x); + margin-bottom: 0; + font-size: var(--bs-popover-header-font-size); + color: var(--bs-popover-header-color); + background-color: var(--bs-popover-header-bg); + border-bottom: var(--bs-popover-border-width) solid + var(--bs-popover-border-color); + border-top-left-radius: var(--bs-popover-inner-border-radius); + border-top-right-radius: var(--bs-popover-inner-border-radius); +} +.popover-header:empty { + display: none; +} + +.popover-body { + padding: var(--bs-popover-body-padding-y) var(--bs-popover-body-padding-x); + color: var(--bs-popover-body-color); +} + +.carousel { + position: relative; +} + +.carousel.pointer-event { + touch-action: pan-y; +} + +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} +.carousel-inner::after { + display: block; + clear: both; + content: ''; +} + +.carousel-item { + position: relative; + display: none; + float: left; + width: 100%; + margin-right: -100%; + backface-visibility: hidden; + transition: transform 0.6s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .carousel-item { + transition: none; + } +} + +.carousel-item.active, +.carousel-item-next, +.carousel-item-prev { + display: block; +} + +.carousel-item-next:not(.carousel-item-start), +.active.carousel-item-end { + transform: translateX(100%); +} + +.carousel-item-prev:not(.carousel-item-end), +.active.carousel-item-start { + transform: translateX(-100%); +} + +.carousel-fade .carousel-item { + opacity: 0; + transition-property: opacity; + transform: none; +} + +.carousel-fade .carousel-item.active, +.carousel-fade .carousel-item-next.carousel-item-start, +.carousel-fade .carousel-item-prev.carousel-item-end { + z-index: 1; + opacity: 1; +} + +.carousel-fade .active.carousel-item-start, +.carousel-fade .active.carousel-item-end { + z-index: 0; + opacity: 0; + transition: opacity 0s 0.6s; +} +@media (prefers-reduced-motion: reduce) { + .carousel-fade .active.carousel-item-start, + .carousel-fade .active.carousel-item-end { + transition: none; + } +} + +.carousel-control-prev, +.carousel-control-next { + position: absolute; + top: 0; + bottom: 0; + z-index: 1; + display: flex; + align-items: center; + justify-content: center; + width: 15%; + padding: 0; + color: #fff; + text-align: center; + background: none; + border: 0; + opacity: 0.5; + transition: opacity 0.15s ease; +} +@media (prefers-reduced-motion: reduce) { + .carousel-control-prev, + .carousel-control-next { + transition: none; + } +} +.carousel-control-prev:hover, +.carousel-control-prev:focus, +.carousel-control-next:hover, +.carousel-control-next:focus { + color: #fff; + text-decoration: none; + outline: 0; + opacity: 0.9; +} + +.carousel-control-prev { + left: 0; +} + +.carousel-control-next { + right: 0; +} + +.carousel-control-prev-icon, +.carousel-control-next-icon { + display: inline-block; + width: 2rem; + height: 2rem; + background-repeat: no-repeat; + background-position: 50%; + background-size: 100% 100%; +} + +/* rtl:options: { + "autoRename": true, + "stringMap":[ { + "name" : "prev-next", + "search" : "prev", + "replace" : "next" + } ] +} */ +.carousel-control-prev-icon { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e"); +} + +.carousel-control-next-icon { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); +} + +.carousel-indicators { + position: absolute; + right: 0; + bottom: 0; + left: 0; + z-index: 2; + display: flex; + justify-content: center; + padding: 0; + margin-right: 15%; + margin-bottom: 1rem; + margin-left: 15%; +} +.carousel-indicators [data-bs-target] { + box-sizing: content-box; + flex: 0 1 auto; + width: 30px; + height: 3px; + padding: 0; + margin-right: 3px; + margin-left: 3px; + text-indent: -999px; + cursor: pointer; + background-color: #fff; + background-clip: padding-box; + border: 0; + border-top: 10px solid transparent; + border-bottom: 10px solid transparent; + opacity: 0.5; + transition: opacity 0.6s ease; +} +@media (prefers-reduced-motion: reduce) { + .carousel-indicators [data-bs-target] { + transition: none; + } +} +.carousel-indicators .active { + opacity: 1; +} + +.carousel-caption { + position: absolute; + right: 15%; + bottom: 1.25rem; + left: 15%; + padding-top: 1.25rem; + padding-bottom: 1.25rem; + color: #fff; + text-align: center; +} + +.carousel-dark .carousel-control-prev-icon, +.carousel-dark .carousel-control-next-icon { + filter: invert(1) grayscale(100); +} + +.carousel-dark .carousel-indicators [data-bs-target] { + background-color: #000; +} + +.carousel-dark .carousel-caption { + color: #000; +} + +[data-bs-theme='dark'] .carousel .carousel-control-prev-icon, +[data-bs-theme='dark'] .carousel .carousel-control-next-icon, +[data-bs-theme='dark'].carousel .carousel-control-prev-icon, +[data-bs-theme='dark'].carousel .carousel-control-next-icon { + filter: invert(1) grayscale(100); +} + +[data-bs-theme='dark'] .carousel .carousel-indicators [data-bs-target], +[data-bs-theme='dark'].carousel .carousel-indicators [data-bs-target] { + background-color: #000; +} + +[data-bs-theme='dark'] .carousel .carousel-caption, +[data-bs-theme='dark'].carousel .carousel-caption { + color: #000; +} + +.spinner-grow, +.spinner-border { + display: inline-block; + width: var(--bs-spinner-width); + height: var(--bs-spinner-height); + vertical-align: var(--bs-spinner-vertical-align); + border-radius: 50%; + animation: var(--bs-spinner-animation-speed) linear infinite + var(--bs-spinner-animation-name); +} + +@keyframes spinner-border { + to { + transform: rotate(360deg) /* rtl:ignore */; + } +} + +.spinner-border { + --bs-spinner-width: 2rem; + --bs-spinner-height: 2rem; + --bs-spinner-vertical-align: -0.125em; + --bs-spinner-border-width: 0.25em; + --bs-spinner-animation-speed: 0.75s; + --bs-spinner-animation-name: spinner-border; + border: var(--bs-spinner-border-width) solid currentcolor; + border-right-color: transparent; +} + +.spinner-border-sm { + --bs-spinner-width: 1rem; + --bs-spinner-height: 1rem; + --bs-spinner-border-width: 0.2em; +} + +@keyframes spinner-grow { + 0% { + transform: scale(0); + } + 50% { + opacity: 1; + transform: none; + } +} + +.spinner-grow { + --bs-spinner-width: 2rem; + --bs-spinner-height: 2rem; + --bs-spinner-vertical-align: -0.125em; + --bs-spinner-animation-speed: 0.75s; + --bs-spinner-animation-name: spinner-grow; + background-color: currentcolor; + opacity: 0; +} + +.spinner-grow-sm { + --bs-spinner-width: 1rem; + --bs-spinner-height: 1rem; +} + +@media (prefers-reduced-motion: reduce) { + .spinner-border, + .spinner-grow { + --bs-spinner-animation-speed: 1.5s; + } +} + +.offcanvas-sm, +.offcanvas-md, +.offcanvas-lg, +.offcanvas-xl, +.offcanvas-xxl, +.offcanvas { + --bs-offcanvas-zindex: 1045; + --bs-offcanvas-width: 400px; + --bs-offcanvas-height: 30vh; + --bs-offcanvas-padding-x: 1rem; + --bs-offcanvas-padding-y: 1rem; + --bs-offcanvas-color: var(--bs-body-color); + --bs-offcanvas-bg: var(--bs-body-bg); + --bs-offcanvas-border-width: var(--bs-border-width); + --bs-offcanvas-border-color: var(--bs-border-color-translucent); + --bs-offcanvas-box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075); + --bs-offcanvas-transition: transform 0.3s ease-in-out; + --bs-offcanvas-title-line-height: 1.5; +} + +@media (max-width: 575.98px) { + .offcanvas-sm { + position: fixed; + bottom: 0; + z-index: var(--bs-offcanvas-zindex); + display: flex; + flex-direction: column; + max-width: 100%; + color: var(--bs-offcanvas-color); + visibility: hidden; + background-color: var(--bs-offcanvas-bg); + background-clip: padding-box; + outline: 0; + transition: var(--bs-offcanvas-transition); + } +} +@media (max-width: 575.98px) and (prefers-reduced-motion: reduce) { + .offcanvas-sm { + transition: none; + } +} + +@media (max-width: 575.98px) { + .offcanvas-sm.offcanvas-start { + top: 0; + left: 0; + width: var(--bs-offcanvas-width); + border-right: var(--bs-offcanvas-border-width) solid + var(--bs-offcanvas-border-color); + transform: translateX(-100%); + } + .offcanvas-sm.offcanvas-end { + top: 0; + right: 0; + width: var(--bs-offcanvas-width); + border-left: var(--bs-offcanvas-border-width) solid + var(--bs-offcanvas-border-color); + transform: translateX(100%); + } + .offcanvas-sm.offcanvas-top { + top: 0; + right: 0; + left: 0; + height: var(--bs-offcanvas-height); + max-height: 100%; + border-bottom: var(--bs-offcanvas-border-width) solid + var(--bs-offcanvas-border-color); + transform: translateY(-100%); + } + .offcanvas-sm.offcanvas-bottom { + right: 0; + left: 0; + height: var(--bs-offcanvas-height); + max-height: 100%; + border-top: var(--bs-offcanvas-border-width) solid + var(--bs-offcanvas-border-color); + transform: translateY(100%); + } + .offcanvas-sm.showing, + .offcanvas-sm.show:not(.hiding) { + transform: none; + } + .offcanvas-sm.showing, + .offcanvas-sm.hiding, + .offcanvas-sm.show { + visibility: visible; + } +} + +@media (min-width: 576px) { + .offcanvas-sm { + --bs-offcanvas-height: auto; + --bs-offcanvas-border-width: 0; + background-color: transparent !important; + } + .offcanvas-sm .offcanvas-header { + display: none; + } + .offcanvas-sm .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible; + background-color: transparent !important; + } +} + +@media (max-width: 767.98px) { + .offcanvas-md { + position: fixed; + bottom: 0; + z-index: var(--bs-offcanvas-zindex); + display: flex; + flex-direction: column; + max-width: 100%; + color: var(--bs-offcanvas-color); + visibility: hidden; + background-color: var(--bs-offcanvas-bg); + background-clip: padding-box; + outline: 0; + transition: var(--bs-offcanvas-transition); + } +} +@media (max-width: 767.98px) and (prefers-reduced-motion: reduce) { + .offcanvas-md { + transition: none; + } +} + +@media (max-width: 767.98px) { + .offcanvas-md.offcanvas-start { + top: 0; + left: 0; + width: var(--bs-offcanvas-width); + border-right: var(--bs-offcanvas-border-width) solid + var(--bs-offcanvas-border-color); + transform: translateX(-100%); + } + .offcanvas-md.offcanvas-end { + top: 0; + right: 0; + width: var(--bs-offcanvas-width); + border-left: var(--bs-offcanvas-border-width) solid + var(--bs-offcanvas-border-color); + transform: translateX(100%); + } + .offcanvas-md.offcanvas-top { + top: 0; + right: 0; + left: 0; + height: var(--bs-offcanvas-height); + max-height: 100%; + border-bottom: var(--bs-offcanvas-border-width) solid + var(--bs-offcanvas-border-color); + transform: translateY(-100%); + } + .offcanvas-md.offcanvas-bottom { + right: 0; + left: 0; + height: var(--bs-offcanvas-height); + max-height: 100%; + border-top: var(--bs-offcanvas-border-width) solid + var(--bs-offcanvas-border-color); + transform: translateY(100%); + } + .offcanvas-md.showing, + .offcanvas-md.show:not(.hiding) { + transform: none; + } + .offcanvas-md.showing, + .offcanvas-md.hiding, + .offcanvas-md.show { + visibility: visible; + } +} + +@media (min-width: 768px) { + .offcanvas-md { + --bs-offcanvas-height: auto; + --bs-offcanvas-border-width: 0; + background-color: transparent !important; + } + .offcanvas-md .offcanvas-header { + display: none; + } + .offcanvas-md .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible; + background-color: transparent !important; + } +} + +@media (max-width: 991.98px) { + .offcanvas-lg { + position: fixed; + bottom: 0; + z-index: var(--bs-offcanvas-zindex); + display: flex; + flex-direction: column; + max-width: 100%; + color: var(--bs-offcanvas-color); + visibility: hidden; + background-color: var(--bs-offcanvas-bg); + background-clip: padding-box; + outline: 0; + transition: var(--bs-offcanvas-transition); + } +} +@media (max-width: 991.98px) and (prefers-reduced-motion: reduce) { + .offcanvas-lg { + transition: none; + } +} + +@media (max-width: 991.98px) { + .offcanvas-lg.offcanvas-start { + top: 0; + left: 0; + width: var(--bs-offcanvas-width); + border-right: var(--bs-offcanvas-border-width) solid + var(--bs-offcanvas-border-color); + transform: translateX(-100%); + } + .offcanvas-lg.offcanvas-end { + top: 0; + right: 0; + width: var(--bs-offcanvas-width); + border-left: var(--bs-offcanvas-border-width) solid + var(--bs-offcanvas-border-color); + transform: translateX(100%); + } + .offcanvas-lg.offcanvas-top { + top: 0; + right: 0; + left: 0; + height: var(--bs-offcanvas-height); + max-height: 100%; + border-bottom: var(--bs-offcanvas-border-width) solid + var(--bs-offcanvas-border-color); + transform: translateY(-100%); + } + .offcanvas-lg.offcanvas-bottom { + right: 0; + left: 0; + height: var(--bs-offcanvas-height); + max-height: 100%; + border-top: var(--bs-offcanvas-border-width) solid + var(--bs-offcanvas-border-color); + transform: translateY(100%); + } + .offcanvas-lg.showing, + .offcanvas-lg.show:not(.hiding) { + transform: none; + } + .offcanvas-lg.showing, + .offcanvas-lg.hiding, + .offcanvas-lg.show { + visibility: visible; + } +} + +@media (min-width: 992px) { + .offcanvas-lg { + --bs-offcanvas-height: auto; + --bs-offcanvas-border-width: 0; + background-color: transparent !important; + } + .offcanvas-lg .offcanvas-header { + display: none; + } + .offcanvas-lg .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible; + background-color: transparent !important; + } +} + +@media (max-width: 1199.98px) { + .offcanvas-xl { + position: fixed; + bottom: 0; + z-index: var(--bs-offcanvas-zindex); + display: flex; + flex-direction: column; + max-width: 100%; + color: var(--bs-offcanvas-color); + visibility: hidden; + background-color: var(--bs-offcanvas-bg); + background-clip: padding-box; + outline: 0; + transition: var(--bs-offcanvas-transition); + } +} +@media (max-width: 1199.98px) and (prefers-reduced-motion: reduce) { + .offcanvas-xl { + transition: none; + } +} + +@media (max-width: 1199.98px) { + .offcanvas-xl.offcanvas-start { + top: 0; + left: 0; + width: var(--bs-offcanvas-width); + border-right: var(--bs-offcanvas-border-width) solid + var(--bs-offcanvas-border-color); + transform: translateX(-100%); + } + .offcanvas-xl.offcanvas-end { + top: 0; + right: 0; + width: var(--bs-offcanvas-width); + border-left: var(--bs-offcanvas-border-width) solid + var(--bs-offcanvas-border-color); + transform: translateX(100%); + } + .offcanvas-xl.offcanvas-top { + top: 0; + right: 0; + left: 0; + height: var(--bs-offcanvas-height); + max-height: 100%; + border-bottom: var(--bs-offcanvas-border-width) solid + var(--bs-offcanvas-border-color); + transform: translateY(-100%); + } + .offcanvas-xl.offcanvas-bottom { + right: 0; + left: 0; + height: var(--bs-offcanvas-height); + max-height: 100%; + border-top: var(--bs-offcanvas-border-width) solid + var(--bs-offcanvas-border-color); + transform: translateY(100%); + } + .offcanvas-xl.showing, + .offcanvas-xl.show:not(.hiding) { + transform: none; + } + .offcanvas-xl.showing, + .offcanvas-xl.hiding, + .offcanvas-xl.show { + visibility: visible; + } +} + +@media (min-width: 1200px) { + .offcanvas-xl { + --bs-offcanvas-height: auto; + --bs-offcanvas-border-width: 0; + background-color: transparent !important; + } + .offcanvas-xl .offcanvas-header { + display: none; + } + .offcanvas-xl .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible; + background-color: transparent !important; + } +} + +@media (max-width: 1399.98px) { + .offcanvas-xxl { + position: fixed; + bottom: 0; + z-index: var(--bs-offcanvas-zindex); + display: flex; + flex-direction: column; + max-width: 100%; + color: var(--bs-offcanvas-color); + visibility: hidden; + background-color: var(--bs-offcanvas-bg); + background-clip: padding-box; + outline: 0; + transition: var(--bs-offcanvas-transition); + } +} +@media (max-width: 1399.98px) and (prefers-reduced-motion: reduce) { + .offcanvas-xxl { + transition: none; + } +} + +@media (max-width: 1399.98px) { + .offcanvas-xxl.offcanvas-start { + top: 0; + left: 0; + width: var(--bs-offcanvas-width); + border-right: var(--bs-offcanvas-border-width) solid + var(--bs-offcanvas-border-color); + transform: translateX(-100%); + } + .offcanvas-xxl.offcanvas-end { + top: 0; + right: 0; + width: var(--bs-offcanvas-width); + border-left: var(--bs-offcanvas-border-width) solid + var(--bs-offcanvas-border-color); + transform: translateX(100%); + } + .offcanvas-xxl.offcanvas-top { + top: 0; + right: 0; + left: 0; + height: var(--bs-offcanvas-height); + max-height: 100%; + border-bottom: var(--bs-offcanvas-border-width) solid + var(--bs-offcanvas-border-color); + transform: translateY(-100%); + } + .offcanvas-xxl.offcanvas-bottom { + right: 0; + left: 0; + height: var(--bs-offcanvas-height); + max-height: 100%; + border-top: var(--bs-offcanvas-border-width) solid + var(--bs-offcanvas-border-color); + transform: translateY(100%); + } + .offcanvas-xxl.showing, + .offcanvas-xxl.show:not(.hiding) { + transform: none; + } + .offcanvas-xxl.showing, + .offcanvas-xxl.hiding, + .offcanvas-xxl.show { + visibility: visible; + } +} + +@media (min-width: 1400px) { + .offcanvas-xxl { + --bs-offcanvas-height: auto; + --bs-offcanvas-border-width: 0; + background-color: transparent !important; + } + .offcanvas-xxl .offcanvas-header { + display: none; + } + .offcanvas-xxl .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible; + background-color: transparent !important; + } +} + +.offcanvas { + position: fixed; + bottom: 0; + z-index: var(--bs-offcanvas-zindex); + display: flex; + flex-direction: column; + max-width: 100%; + color: var(--bs-offcanvas-color); + visibility: hidden; + background-color: var(--bs-offcanvas-bg); + background-clip: padding-box; + outline: 0; + transition: var(--bs-offcanvas-transition); +} +@media (prefers-reduced-motion: reduce) { + .offcanvas { + transition: none; + } +} +.offcanvas.offcanvas-start { + top: 0; + left: 0; + width: var(--bs-offcanvas-width); + border-right: var(--bs-offcanvas-border-width) solid + var(--bs-offcanvas-border-color); + transform: translateX(-100%); +} +.offcanvas.offcanvas-end { + top: 0; + right: 0; + width: var(--bs-offcanvas-width); + border-left: var(--bs-offcanvas-border-width) solid + var(--bs-offcanvas-border-color); + transform: translateX(100%); +} +.offcanvas.offcanvas-top { + top: 0; + right: 0; + left: 0; + height: var(--bs-offcanvas-height); + max-height: 100%; + border-bottom: var(--bs-offcanvas-border-width) solid + var(--bs-offcanvas-border-color); + transform: translateY(-100%); +} +.offcanvas.offcanvas-bottom { + right: 0; + left: 0; + height: var(--bs-offcanvas-height); + max-height: 100%; + border-top: var(--bs-offcanvas-border-width) solid + var(--bs-offcanvas-border-color); + transform: translateY(100%); +} +.offcanvas.showing, +.offcanvas.show:not(.hiding) { + transform: none; +} +.offcanvas.showing, +.offcanvas.hiding, +.offcanvas.show { + visibility: visible; +} + +.offcanvas-backdrop { + position: fixed; + top: 0; + left: 0; + z-index: 1040; + width: 100vw; + height: 100vh; + background-color: #000; +} +.offcanvas-backdrop.fade { + opacity: 0; +} +.offcanvas-backdrop.show { + opacity: 0.5; +} + +.offcanvas-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x); +} +.offcanvas-header .btn-close { + padding: calc(var(--bs-offcanvas-padding-y) * 0.5) + calc(var(--bs-offcanvas-padding-x) * 0.5); + margin-top: calc(-0.5 * var(--bs-offcanvas-padding-y)); + margin-right: calc(-0.5 * var(--bs-offcanvas-padding-x)); + margin-bottom: calc(-0.5 * var(--bs-offcanvas-padding-y)); +} + +.offcanvas-title { + margin-bottom: 0; + line-height: var(--bs-offcanvas-title-line-height); +} + +.offcanvas-body { + flex-grow: 1; + padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x); + overflow-y: auto; +} + +.placeholder { + display: inline-block; + min-height: 1em; + vertical-align: middle; + cursor: wait; + background-color: currentcolor; + opacity: 0.5; +} +.placeholder.btn::before { + display: inline-block; + content: ''; +} + +.placeholder-xs { + min-height: 0.6em; +} + +.placeholder-sm { + min-height: 0.8em; +} + +.placeholder-lg { + min-height: 1.2em; +} + +.placeholder-glow .placeholder { + animation: placeholder-glow 2s ease-in-out infinite; +} + +@keyframes placeholder-glow { + 50% { + opacity: 0.2; + } +} + +.placeholder-wave { + mask-image: linear-gradient( + 130deg, + #000 55%, + rgba(0, 0, 0, 0.8) 75%, + #000 95% + ); + mask-size: 200% 100%; + animation: placeholder-wave 2s linear infinite; +} + +@keyframes placeholder-wave { + 100% { + mask-position: -200% 0%; + } +} + +.clearfix::after { + display: block; + clear: both; + content: ''; +} + +.text-bg-primary { + color: #000 !important; + background-color: RGBA(49, 187, 107, var(--bs-bg-opacity, 1)) !important; +} + +.text-bg-secondary { + color: #fff !important; + background-color: RGBA(112, 112, 112, var(--bs-bg-opacity, 1)) !important; +} + +.text-bg-success { + color: #000 !important; + background-color: RGBA(49, 187, 107, var(--bs-bg-opacity, 1)) !important; +} + +.text-bg-info { + color: #000 !important; + background-color: RGBA(13, 202, 240, var(--bs-bg-opacity, 1)) !important; +} + +.text-bg-warning { + color: #000 !important; + background-color: RGBA(254, 188, 89, var(--bs-bg-opacity, 1)) !important; +} + +.text-bg-danger { + color: #fff !important; + background-color: RGBA(220, 53, 69, var(--bs-bg-opacity, 1)) !important; +} + +.text-bg-light { + color: #000 !important; + background-color: RGBA(248, 249, 250, var(--bs-bg-opacity, 1)) !important; +} + +.text-bg-dark { + color: #fff !important; + background-color: RGBA(33, 37, 41, var(--bs-bg-opacity, 1)) !important; +} + +.link-primary { + color: RGBA(var(--bs-primary-rgb), var(--bs-link-opacity, 1)) !important; + text-decoration-color: RGBA( + var(--bs-primary-rgb), + var(--bs-link-underline-opacity, 1) + ) !important; +} +.link-primary:hover, +.link-primary:focus { + color: RGBA(90, 201, 137, var(--bs-link-opacity, 1)) !important; + text-decoration-color: RGBA( + 90, + 201, + 137, + var(--bs-link-underline-opacity, 1) + ) !important; +} + +.link-secondary { + color: RGBA(var(--bs-secondary-rgb), var(--bs-link-opacity, 1)) !important; + text-decoration-color: RGBA( + var(--bs-secondary-rgb), + var(--bs-link-underline-opacity, 1) + ) !important; +} +.link-secondary:hover, +.link-secondary:focus { + color: RGBA(90, 90, 90, var(--bs-link-opacity, 1)) !important; + text-decoration-color: RGBA( + 90, + 90, + 90, + var(--bs-link-underline-opacity, 1) + ) !important; +} + +.link-success { + color: RGBA(var(--bs-success-rgb), var(--bs-link-opacity, 1)) !important; + text-decoration-color: RGBA( + var(--bs-success-rgb), + var(--bs-link-underline-opacity, 1) + ) !important; +} +.link-success:hover, +.link-success:focus { + color: RGBA(90, 201, 137, var(--bs-link-opacity, 1)) !important; + text-decoration-color: RGBA( + 90, + 201, + 137, + var(--bs-link-underline-opacity, 1) + ) !important; +} + +.link-info { + color: RGBA(var(--bs-info-rgb), var(--bs-link-opacity, 1)) !important; + text-decoration-color: RGBA( + var(--bs-info-rgb), + var(--bs-link-underline-opacity, 1) + ) !important; +} +.link-info:hover, +.link-info:focus { + color: RGBA(61, 213, 243, var(--bs-link-opacity, 1)) !important; + text-decoration-color: RGBA( + 61, + 213, + 243, + var(--bs-link-underline-opacity, 1) + ) !important; +} + +.link-warning { + color: RGBA(var(--bs-warning-rgb), var(--bs-link-opacity, 1)) !important; + text-decoration-color: RGBA( + var(--bs-warning-rgb), + var(--bs-link-underline-opacity, 1) + ) !important; +} +.link-warning:hover, +.link-warning:focus { + color: RGBA(254, 201, 122, var(--bs-link-opacity, 1)) !important; + text-decoration-color: RGBA( + 254, + 201, + 122, + var(--bs-link-underline-opacity, 1) + ) !important; +} + +.link-danger { + color: RGBA(var(--bs-danger-rgb), var(--bs-link-opacity, 1)) !important; + text-decoration-color: RGBA( + var(--bs-danger-rgb), + var(--bs-link-underline-opacity, 1) + ) !important; +} +.link-danger:hover, +.link-danger:focus { + color: RGBA(176, 42, 55, var(--bs-link-opacity, 1)) !important; + text-decoration-color: RGBA( + 176, + 42, + 55, + var(--bs-link-underline-opacity, 1) + ) !important; +} + +.link-light { + color: RGBA(var(--bs-light-rgb), var(--bs-link-opacity, 1)) !important; + text-decoration-color: RGBA( + var(--bs-light-rgb), + var(--bs-link-underline-opacity, 1) + ) !important; +} +.link-light:hover, +.link-light:focus { + color: RGBA(249, 250, 251, var(--bs-link-opacity, 1)) !important; + text-decoration-color: RGBA( + 249, + 250, + 251, + var(--bs-link-underline-opacity, 1) + ) !important; +} + +.link-dark { + color: RGBA(var(--bs-dark-rgb), var(--bs-link-opacity, 1)) !important; + text-decoration-color: RGBA( + var(--bs-dark-rgb), + var(--bs-link-underline-opacity, 1) + ) !important; +} +.link-dark:hover, +.link-dark:focus { + color: RGBA(26, 30, 33, var(--bs-link-opacity, 1)) !important; + text-decoration-color: RGBA( + 26, + 30, + 33, + var(--bs-link-underline-opacity, 1) + ) !important; +} + +.link-body-emphasis { + color: RGBA( + var(--bs-emphasis-color-rgb), + var(--bs-link-opacity, 1) + ) !important; + text-decoration-color: RGBA( + var(--bs-emphasis-color-rgb), + var(--bs-link-underline-opacity, 1) + ) !important; +} +.link-body-emphasis:hover, +.link-body-emphasis:focus { + color: RGBA( + var(--bs-emphasis-color-rgb), + var(--bs-link-opacity, 0.75) + ) !important; + text-decoration-color: RGBA( + var(--bs-emphasis-color-rgb), + var(--bs-link-underline-opacity, 0.75) + ) !important; +} + +.focus-ring:focus { + outline: 0; + box-shadow: var(--bs-focus-ring-x, 0) var(--bs-focus-ring-y, 0) + var(--bs-focus-ring-blur, 0) var(--bs-focus-ring-width) + var(--bs-focus-ring-color); +} + +.icon-link { + display: inline-flex; + gap: 0.375rem; + align-items: center; + text-decoration-color: rgba( + var(--bs-link-color-rgb), + var(--bs-link-opacity, 0.5) + ); + text-underline-offset: 0.25em; + backface-visibility: hidden; +} +.icon-link > .bi { + flex-shrink: 0; + width: 1em; + height: 1em; + fill: currentcolor; + transition: 0.2s ease-in-out transform; +} +@media (prefers-reduced-motion: reduce) { + .icon-link > .bi { + transition: none; + } +} + +.icon-link-hover:hover > .bi, +.icon-link-hover:focus-visible > .bi { + transform: var(--bs-icon-link-transform, translate3d(0.25em, 0, 0)); +} + +.ratio { + position: relative; + width: 100%; +} +.ratio::before { + display: block; + padding-top: var(--bs-aspect-ratio); + content: ''; +} +.ratio > * { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.ratio-1x1 { + --bs-aspect-ratio: 100%; +} + +.ratio-4x3 { + --bs-aspect-ratio: calc(3 / 4 * 100%); +} + +.ratio-16x9 { + --bs-aspect-ratio: calc(9 / 16 * 100%); +} + +.ratio-21x9 { + --bs-aspect-ratio: calc(9 / 21 * 100%); +} + +.fixed-top { + position: fixed; + top: 0; + right: 0; + left: 0; + z-index: 1030; +} + +.fixed-bottom { + position: fixed; + right: 0; + bottom: 0; + left: 0; + z-index: 1030; +} + +.sticky-top { + position: sticky; + top: 0; + z-index: 1020; +} + +.sticky-bottom { + position: sticky; + bottom: 0; + z-index: 1020; +} + +@media (min-width: 576px) { + .sticky-sm-top { + position: sticky; + top: 0; + z-index: 1020; + } + .sticky-sm-bottom { + position: sticky; + bottom: 0; + z-index: 1020; + } +} + +@media (min-width: 768px) { + .sticky-md-top { + position: sticky; + top: 0; + z-index: 1020; + } + .sticky-md-bottom { + position: sticky; + bottom: 0; + z-index: 1020; + } +} + +@media (min-width: 992px) { + .sticky-lg-top { + position: sticky; + top: 0; + z-index: 1020; + } + .sticky-lg-bottom { + position: sticky; + bottom: 0; + z-index: 1020; + } +} + +@media (min-width: 1200px) { + .sticky-xl-top { + position: sticky; + top: 0; + z-index: 1020; + } + .sticky-xl-bottom { + position: sticky; + bottom: 0; + z-index: 1020; + } +} + +@media (min-width: 1400px) { + .sticky-xxl-top { + position: sticky; + top: 0; + z-index: 1020; + } + .sticky-xxl-bottom { + position: sticky; + bottom: 0; + z-index: 1020; + } +} + +.hstack { + display: flex; + flex-direction: row; + align-items: center; + align-self: stretch; +} + +.vstack { + display: flex; + flex: 1 1 auto; + flex-direction: column; + align-self: stretch; +} + +.visually-hidden, +.visually-hidden-focusable:not(:focus):not(:focus-within) { + width: 1px !important; + height: 1px !important; + padding: 0 !important; + margin: -1px !important; + overflow: hidden !important; + clip: rect(0, 0, 0, 0) !important; + white-space: nowrap !important; + border: 0 !important; +} +.visually-hidden:not(caption), +.visually-hidden-focusable:not(:focus):not(:focus-within):not(caption) { + position: absolute !important; +} + +.stretched-link::after { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1; + content: ''; +} + +.text-truncate { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.vr { + display: inline-block; + align-self: stretch; + width: 1px; + min-height: 1em; + background-color: currentcolor; + opacity: 0.25; +} + +.align-baseline { + vertical-align: baseline !important; +} + +.align-top { + vertical-align: top !important; +} + +.align-middle { + vertical-align: middle !important; +} + +.align-bottom { + vertical-align: bottom !important; +} + +.align-text-bottom { + vertical-align: text-bottom !important; +} + +.align-text-top { + vertical-align: text-top !important; +} + +.float-start { + float: left !important; +} + +.float-end { + float: right !important; +} + +.float-none { + float: none !important; +} + +.object-fit-contain { + object-fit: contain !important; +} + +.object-fit-cover { + object-fit: cover !important; +} + +.object-fit-fill { + object-fit: fill !important; +} + +.object-fit-scale { + object-fit: scale-down !important; +} + +.object-fit-none { + object-fit: none !important; +} + +.opacity-0 { + opacity: 0 !important; +} + +.opacity-25 { + opacity: 0.25 !important; +} + +.opacity-50 { + opacity: 0.5 !important; +} + +.opacity-75 { + opacity: 0.75 !important; +} + +.opacity-100 { + opacity: 1 !important; +} + +.overflow-auto { + overflow: auto !important; +} + +.overflow-hidden { + overflow: hidden !important; +} + +.overflow-visible { + overflow: visible !important; +} + +.overflow-scroll { + overflow: scroll !important; +} + +.overflow-x-auto { + overflow-x: auto !important; +} + +.overflow-x-hidden { + overflow-x: hidden !important; +} + +.overflow-x-visible { + overflow-x: visible !important; +} + +.overflow-x-scroll { + overflow-x: scroll !important; +} + +.overflow-y-auto { + overflow-y: auto !important; +} + +.overflow-y-hidden { + overflow-y: hidden !important; +} + +.overflow-y-visible { + overflow-y: visible !important; +} + +.overflow-y-scroll { + overflow-y: scroll !important; +} + +.d-inline { + display: inline !important; +} + +.d-inline-block { + display: inline-block !important; +} + +.d-block { + display: block !important; +} + +.d-grid { + display: grid !important; +} + +.d-inline-grid { + display: inline-grid !important; +} + +.d-table { + display: table !important; +} + +.d-table-row { + display: table-row !important; +} + +.d-table-cell { + display: table-cell !important; +} + +.d-flex { + display: flex !important; +} + +.d-inline-flex { + display: inline-flex !important; +} + +.d-none { + display: none !important; +} + +.shadow { + box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important; +} + +.shadow-sm { + box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; +} + +.shadow-lg { + box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important; +} + +.shadow-none { + box-shadow: none !important; +} + +.focus-ring-primary { + --bs-focus-ring-color: rgba( + var(--bs-primary-rgb), + var(--bs-focus-ring-opacity) + ); +} + +.focus-ring-secondary { + --bs-focus-ring-color: rgba( + var(--bs-secondary-rgb), + var(--bs-focus-ring-opacity) + ); +} + +.focus-ring-success { + --bs-focus-ring-color: rgba( + var(--bs-success-rgb), + var(--bs-focus-ring-opacity) + ); +} + +.focus-ring-info { + --bs-focus-ring-color: rgba(var(--bs-info-rgb), var(--bs-focus-ring-opacity)); +} + +.focus-ring-warning { + --bs-focus-ring-color: rgba( + var(--bs-warning-rgb), + var(--bs-focus-ring-opacity) + ); +} + +.focus-ring-danger { + --bs-focus-ring-color: rgba( + var(--bs-danger-rgb), + var(--bs-focus-ring-opacity) + ); +} + +.focus-ring-light { + --bs-focus-ring-color: rgba( + var(--bs-light-rgb), + var(--bs-focus-ring-opacity) + ); +} + +.focus-ring-dark { + --bs-focus-ring-color: rgba(var(--bs-dark-rgb), var(--bs-focus-ring-opacity)); +} + +.position-static { + position: static !important; +} + +.position-relative { + position: relative !important; +} + +.position-absolute { + position: absolute !important; +} + +.position-fixed { + position: fixed !important; +} + +.position-sticky { + position: sticky !important; +} + +.top-0 { + top: 0 !important; +} + +.top-50 { + top: 50% !important; +} + +.top-100 { + top: 100% !important; +} + +.bottom-0 { + bottom: 0 !important; +} + +.bottom-50 { + bottom: 50% !important; +} + +.bottom-100 { + bottom: 100% !important; +} + +.start-0 { + left: 0 !important; +} + +.start-50 { + left: 50% !important; +} + +.start-100 { + left: 100% !important; +} + +.end-0 { + right: 0 !important; +} + +.end-50 { + right: 50% !important; +} + +.end-100 { + right: 100% !important; +} + +.translate-middle { + transform: translate(-50%, -50%) !important; +} + +.translate-middle-x { + transform: translateX(-50%) !important; +} + +.translate-middle-y { + transform: translateY(-50%) !important; +} + +.border { + border: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; +} + +.border-0 { + border: 0 !important; +} + +.border-top { + border-top: var(--bs-border-width) var(--bs-border-style) + var(--bs-border-color) !important; +} + +.border-top-0 { + border-top: 0 !important; +} + +.border-end { + border-right: var(--bs-border-width) var(--bs-border-style) + var(--bs-border-color) !important; +} + +.border-end-0 { + border-right: 0 !important; +} + +.border-bottom { + border-bottom: var(--bs-border-width) var(--bs-border-style) + var(--bs-border-color) !important; +} + +.border-bottom-0 { + border-bottom: 0 !important; +} + +.border-start { + border-left: var(--bs-border-width) var(--bs-border-style) + var(--bs-border-color) !important; +} + +.border-start-0 { + border-left: 0 !important; +} + +.border-primary { + --bs-border-opacity: 1; + border-color: rgba( + var(--bs-primary-rgb), + var(--bs-border-opacity) + ) !important; +} + +.border-secondary { + --bs-border-opacity: 1; + border-color: rgba( + var(--bs-secondary-rgb), + var(--bs-border-opacity) + ) !important; +} + +.border-success { + --bs-border-opacity: 1; + border-color: rgba( + var(--bs-success-rgb), + var(--bs-border-opacity) + ) !important; +} + +.border-info { + --bs-border-opacity: 1; + border-color: rgba(var(--bs-info-rgb), var(--bs-border-opacity)) !important; +} + +.border-warning { + --bs-border-opacity: 1; + border-color: rgba( + var(--bs-warning-rgb), + var(--bs-border-opacity) + ) !important; +} + +.border-danger { + --bs-border-opacity: 1; + border-color: rgba(var(--bs-danger-rgb), var(--bs-border-opacity)) !important; +} + +.border-light { + --bs-border-opacity: 1; + border-color: rgba(var(--bs-light-rgb), var(--bs-border-opacity)) !important; +} + +.border-dark { + --bs-border-opacity: 1; + border-color: rgba(var(--bs-dark-rgb), var(--bs-border-opacity)) !important; +} + +.border-black { + --bs-border-opacity: 1; + border-color: rgba(var(--bs-black-rgb), var(--bs-border-opacity)) !important; +} + +.border-white { + --bs-border-opacity: 1; + border-color: rgba(var(--bs-white-rgb), var(--bs-border-opacity)) !important; +} + +.border-primary-subtle { + border-color: var(--bs-primary-border-subtle) !important; +} + +.border-secondary-subtle { + border-color: var(--bs-secondary-border-subtle) !important; +} + +.border-success-subtle { + border-color: var(--bs-success-border-subtle) !important; +} + +.border-info-subtle { + border-color: var(--bs-info-border-subtle) !important; +} + +.border-warning-subtle { + border-color: var(--bs-warning-border-subtle) !important; +} + +.border-danger-subtle { + border-color: var(--bs-danger-border-subtle) !important; +} + +.border-light-subtle { + border-color: var(--bs-light-border-subtle) !important; +} + +.border-dark-subtle { + border-color: var(--bs-dark-border-subtle) !important; +} + +.border-1 { + border-width: 1px !important; +} + +.border-2 { + border-width: 2px !important; +} + +.border-3 { + border-width: 3px !important; +} + +.border-4 { + border-width: 4px !important; +} + +.border-5 { + border-width: 5px !important; +} + +.border-opacity-10 { + --bs-border-opacity: 0.1; +} + +.border-opacity-25 { + --bs-border-opacity: 0.25; +} + +.border-opacity-50 { + --bs-border-opacity: 0.5; +} + +.border-opacity-75 { + --bs-border-opacity: 0.75; +} + +.border-opacity-100 { + --bs-border-opacity: 1; +} + +.w-25 { + width: 25% !important; +} + +.w-50 { + width: 50% !important; +} + +.w-75 { + width: 75% !important; +} + +.w-100 { + width: 100% !important; +} + +.w-auto { + width: auto !important; +} + +.mw-100 { + max-width: 100% !important; +} + +.vw-100 { + width: 100vw !important; +} + +.min-vw-100 { + min-width: 100vw !important; +} + +.h-25 { + height: 25% !important; +} + +.h-50 { + height: 50% !important; +} + +.h-75 { + height: 75% !important; +} + +.h-100 { + height: 100% !important; +} + +.h-auto { + height: auto !important; +} + +.mh-100 { + max-height: 100% !important; +} + +.vh-100 { + height: 100vh !important; +} + +.min-vh-100 { + min-height: 100vh !important; +} + +.flex-fill { + flex: 1 1 auto !important; +} + +.flex-row { + flex-direction: row !important; +} + +.flex-column { + flex-direction: column !important; +} + +.flex-row-reverse { + flex-direction: row-reverse !important; +} + +.flex-column-reverse { + flex-direction: column-reverse !important; +} + +.flex-grow-0 { + flex-grow: 0 !important; +} + +.flex-grow-1 { + flex-grow: 1 !important; +} + +.flex-shrink-0 { + flex-shrink: 0 !important; +} + +.flex-shrink-1 { + flex-shrink: 1 !important; +} + +.flex-wrap { + flex-wrap: wrap !important; +} + +.flex-nowrap { + flex-wrap: nowrap !important; +} + +.flex-wrap-reverse { + flex-wrap: wrap-reverse !important; +} + +.justify-content-start { + justify-content: flex-start !important; +} + +.justify-content-end { + justify-content: flex-end !important; +} + +.justify-content-center { + justify-content: center !important; +} + +.justify-content-between { + justify-content: space-between !important; +} + +.justify-content-around { + justify-content: space-around !important; +} + +.justify-content-evenly { + justify-content: space-evenly !important; +} + +.align-items-start { + align-items: flex-start !important; +} + +.align-items-end { + align-items: flex-end !important; +} + +.align-items-center { + align-items: center !important; +} + +.align-items-baseline { + align-items: baseline !important; +} + +.align-items-stretch { + align-items: stretch !important; +} + +.align-content-start { + align-content: flex-start !important; +} + +.align-content-end { + align-content: flex-end !important; +} + +.align-content-center { + align-content: center !important; +} + +.align-content-between { + align-content: space-between !important; +} + +.align-content-around { + align-content: space-around !important; +} + +.align-content-stretch { + align-content: stretch !important; +} + +.align-self-auto { + align-self: auto !important; +} + +.align-self-start { + align-self: flex-start !important; +} + +.align-self-end { + align-self: flex-end !important; +} + +.align-self-center { + align-self: center !important; +} + +.align-self-baseline { + align-self: baseline !important; +} + +.align-self-stretch { + align-self: stretch !important; +} + +.order-first { + order: -1 !important; +} + +.order-0 { + order: 0 !important; +} + +.order-1 { + order: 1 !important; +} + +.order-2 { + order: 2 !important; +} + +.order-3 { + order: 3 !important; +} + +.order-4 { + order: 4 !important; +} + +.order-5 { + order: 5 !important; +} + +.order-last { + order: 6 !important; +} + +.m-0 { + margin: 0 !important; +} + +.m-1 { + margin: 0.25rem !important; +} + +.m-2 { + margin: 0.5rem !important; +} + +.m-3 { + margin: 1rem !important; +} + +.m-4 { + margin: 1.5rem !important; +} + +.m-5 { + margin: 3rem !important; +} + +.m-auto { + margin: auto !important; +} + +.mx-0 { + margin-right: 0 !important; + margin-left: 0 !important; +} + +.mx-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; +} + +.mx-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; +} + +.mx-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; +} + +.mx-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; +} + +.mx-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; +} + +.mx-auto { + margin-right: auto !important; + margin-left: auto !important; +} + +.my-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; +} + +.my-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; +} + +.my-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; +} + +.my-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; +} + +.my-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; +} + +.my-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; +} + +.my-auto { + margin-top: auto !important; + margin-bottom: auto !important; +} + +.mt-0 { + margin-top: 0 !important; +} + +.mt-1 { + margin-top: 0.25rem !important; +} + +.mt-2 { + margin-top: 0.5rem !important; +} + +.mt-3 { + margin-top: 1rem !important; +} + +.mt-4 { + margin-top: 1.5rem !important; +} + +.mt-5 { + margin-top: 3rem !important; +} + +.mt-auto { + margin-top: auto !important; +} + +.me-0 { + margin-right: 0 !important; +} + +.me-1 { + margin-right: 0.25rem !important; +} + +.me-2 { + margin-right: 0.5rem !important; +} + +.me-3 { + margin-right: 1rem !important; +} + +.me-4 { + margin-right: 1.5rem !important; +} + +.me-5 { + margin-right: 3rem !important; +} + +.me-auto { + margin-right: auto !important; +} + +.mb-0 { + margin-bottom: 0 !important; +} + +.mb-1 { + margin-bottom: 0.25rem !important; +} + +.mb-2 { + margin-bottom: 0.5rem !important; +} + +.mb-3 { + margin-bottom: 1rem !important; +} + +.mb-4 { + margin-bottom: 1.5rem !important; +} + +.mb-5 { + margin-bottom: 3rem !important; +} + +.mb-auto { + margin-bottom: auto !important; +} + +.ms-0 { + margin-left: 0 !important; +} + +.ms-1 { + margin-left: 0.25rem !important; +} + +.ms-2 { + margin-left: 0.5rem !important; +} + +.ms-3 { + margin-left: 1rem !important; +} + +.ms-4 { + margin-left: 1.5rem !important; +} + +.ms-5 { + margin-left: 3rem !important; +} + +.ms-auto { + margin-left: auto !important; +} + +.p-0 { + padding: 0 !important; +} + +.p-1 { + padding: 0.25rem !important; +} + +.p-2 { + padding: 0.5rem !important; +} + +.p-3 { + padding: 1rem !important; +} + +.p-4 { + padding: 1.5rem !important; +} + +.p-5 { + padding: 3rem !important; +} + +.px-0 { + padding-right: 0 !important; + padding-left: 0 !important; +} + +.px-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; +} + +.px-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; +} + +.px-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; +} + +.px-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; +} + +.px-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; +} + +.py-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; +} + +.py-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; +} + +.py-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; +} + +.py-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; +} + +.py-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; +} + +.py-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; +} + +.pt-0 { + padding-top: 0 !important; +} + +.pt-1 { + padding-top: 0.25rem !important; +} + +.pt-2 { + padding-top: 0.5rem !important; +} + +.pt-3 { + padding-top: 1rem !important; +} + +.pt-4 { + padding-top: 1.5rem !important; +} + +.pt-5 { + padding-top: 3rem !important; +} + +.pe-0 { + padding-right: 0 !important; +} + +.pe-1 { + padding-right: 0.25rem !important; +} + +.pe-2 { + padding-right: 0.5rem !important; +} + +.pe-3 { + padding-right: 1rem !important; +} + +.pe-4 { + padding-right: 1.5rem !important; +} + +.pe-5 { + padding-right: 3rem !important; +} + +.pb-0 { + padding-bottom: 0 !important; +} + +.pb-1 { + padding-bottom: 0.25rem !important; +} + +.pb-2 { + padding-bottom: 0.5rem !important; +} + +.pb-3 { + padding-bottom: 1rem !important; +} + +.pb-4 { + padding-bottom: 1.5rem !important; +} + +.pb-5 { + padding-bottom: 3rem !important; +} + +.ps-0 { + padding-left: 0 !important; +} + +.ps-1 { + padding-left: 0.25rem !important; +} + +.ps-2 { + padding-left: 0.5rem !important; +} + +.ps-3 { + padding-left: 1rem !important; +} + +.ps-4 { + padding-left: 1.5rem !important; +} + +.ps-5 { + padding-left: 3rem !important; +} + +.gap-0 { + gap: 0 !important; +} + +.gap-1 { + gap: 0.25rem !important; +} + +.gap-2 { + gap: 0.5rem !important; +} + +.gap-3 { + gap: 1rem !important; +} + +.gap-4 { + gap: 1.5rem !important; +} + +.gap-5 { + gap: 3rem !important; +} + +.row-gap-0 { + row-gap: 0 !important; +} + +.row-gap-1 { + row-gap: 0.25rem !important; +} + +.row-gap-2 { + row-gap: 0.5rem !important; +} + +.row-gap-3 { + row-gap: 1rem !important; +} + +.row-gap-4 { + row-gap: 1.5rem !important; +} + +.row-gap-5 { + row-gap: 3rem !important; +} + +.column-gap-0 { + column-gap: 0 !important; +} + +.column-gap-1 { + column-gap: 0.25rem !important; +} + +.column-gap-2 { + column-gap: 0.5rem !important; +} + +.column-gap-3 { + column-gap: 1rem !important; +} + +.column-gap-4 { + column-gap: 1.5rem !important; +} + +.column-gap-5 { + column-gap: 3rem !important; +} + +.font-monospace { + font-family: var(--bs-font-monospace) !important; +} + +.fs-1 { + font-size: calc(1.375rem + 1.5vw) !important; +} + +.fs-2 { + font-size: calc(1.325rem + 0.9vw) !important; +} + +.fs-3 { + font-size: calc(1.3rem + 0.6vw) !important; +} + +.fs-4 { + font-size: calc(1.275rem + 0.3vw) !important; +} + +.fs-5 { + font-size: 1.25rem !important; +} + +.fs-6 { + font-size: 1rem !important; +} + +.fst-italic { + font-style: italic !important; +} + +.fst-normal { + font-style: normal !important; +} + +.fw-lighter { + font-weight: lighter !important; +} + +.fw-light { + font-weight: 300 !important; +} + +.fw-normal { + font-weight: 400 !important; +} + +.fw-medium { + font-weight: 500 !important; +} + +.fw-semibold { + font-weight: 600 !important; +} + +.fw-bold { + font-weight: 700 !important; +} + +.fw-bolder { + font-weight: bolder !important; +} + +.lh-1 { + line-height: 1 !important; +} + +.lh-sm { + line-height: 1.25 !important; +} + +.lh-base { + line-height: 1.5 !important; +} + +.lh-lg { + line-height: 2 !important; +} + +.text-start { + text-align: left !important; +} + +.text-end { + text-align: right !important; +} + +.text-center { + text-align: center !important; +} + +.text-decoration-none { + text-decoration: none !important; +} + +.text-decoration-underline { + text-decoration: underline !important; +} + +.text-decoration-line-through { + text-decoration: line-through !important; +} + +.text-lowercase { + text-transform: lowercase !important; +} + +.text-uppercase { + text-transform: uppercase !important; +} + +.text-capitalize { + text-transform: capitalize !important; +} + +.text-wrap { + white-space: normal !important; +} + +.text-nowrap { + white-space: nowrap !important; +} + +/* rtl:begin:remove */ +.text-break { + word-wrap: break-word !important; + word-break: break-word !important; +} + +/* rtl:end:remove */ +.text-primary { + --bs-text-opacity: 1; + color: rgba(var(--bs-primary-rgb), var(--bs-text-opacity)) !important; +} + +.text-secondary { + --bs-text-opacity: 1; + color: rgba(var(--bs-secondary-rgb), var(--bs-text-opacity)) !important; +} + +.text-success { + --bs-text-opacity: 1; + color: rgba(var(--bs-success-rgb), var(--bs-text-opacity)) !important; +} + +.text-info { + --bs-text-opacity: 1; + color: rgba(var(--bs-info-rgb), var(--bs-text-opacity)) !important; +} + +.text-warning { + --bs-text-opacity: 1; + color: rgba(var(--bs-warning-rgb), var(--bs-text-opacity)) !important; +} + +.text-danger { + --bs-text-opacity: 1; + color: rgba(var(--bs-danger-rgb), var(--bs-text-opacity)) !important; +} + +.text-light { + --bs-text-opacity: 1; + color: rgba(var(--bs-light-rgb), var(--bs-text-opacity)) !important; +} + +.text-dark { + --bs-text-opacity: 1; + color: rgba(var(--bs-dark-rgb), var(--bs-text-opacity)) !important; +} + +.text-black { + --bs-text-opacity: 1; + color: rgba(var(--bs-black-rgb), var(--bs-text-opacity)) !important; +} + +.text-white { + --bs-text-opacity: 1; + color: rgba(var(--bs-white-rgb), var(--bs-text-opacity)) !important; +} + +.text-body { + --bs-text-opacity: 1; + color: rgba(var(--bs-body-color-rgb), var(--bs-text-opacity)) !important; +} + +.text-muted { + --bs-text-opacity: 1; + color: var(--bs-secondary-color) !important; +} + +.text-black-50 { + --bs-text-opacity: 1; + color: rgba(0, 0, 0, 0.5) !important; +} + +.text-white-50 { + --bs-text-opacity: 1; + color: rgba(255, 255, 255, 0.5) !important; +} + +.text-body-secondary { + --bs-text-opacity: 1; + color: var(--bs-secondary-color) !important; +} + +.text-body-tertiary { + --bs-text-opacity: 1; + color: var(--bs-tertiary-color) !important; +} + +.text-body-emphasis { + --bs-text-opacity: 1; + color: var(--bs-emphasis-color) !important; +} + +.text-reset { + --bs-text-opacity: 1; + color: inherit !important; +} + +.text-opacity-25 { + --bs-text-opacity: 0.25; +} + +.text-opacity-50 { + --bs-text-opacity: 0.5; +} + +.text-opacity-75 { + --bs-text-opacity: 0.75; +} + +.text-opacity-100 { + --bs-text-opacity: 1; +} + +.text-primary-emphasis { + color: var(--bs-primary-text-emphasis) !important; +} + +.text-secondary-emphasis { + color: var(--bs-secondary-text-emphasis) !important; +} + +.text-success-emphasis { + color: var(--bs-success-text-emphasis) !important; +} + +.text-info-emphasis { + color: var(--bs-info-text-emphasis) !important; +} + +.text-warning-emphasis { + color: var(--bs-warning-text-emphasis) !important; +} + +.text-danger-emphasis { + color: var(--bs-danger-text-emphasis) !important; +} + +.text-light-emphasis { + color: var(--bs-light-text-emphasis) !important; +} + +.text-dark-emphasis { + color: var(--bs-dark-text-emphasis) !important; +} + +.link-opacity-10 { + --bs-link-opacity: 0.1; +} + +.link-opacity-10-hover:hover { + --bs-link-opacity: 0.1; +} + +.link-opacity-25 { + --bs-link-opacity: 0.25; +} + +.link-opacity-25-hover:hover { + --bs-link-opacity: 0.25; +} + +.link-opacity-50 { + --bs-link-opacity: 0.5; +} + +.link-opacity-50-hover:hover { + --bs-link-opacity: 0.5; +} + +.link-opacity-75 { + --bs-link-opacity: 0.75; +} + +.link-opacity-75-hover:hover { + --bs-link-opacity: 0.75; +} + +.link-opacity-100 { + --bs-link-opacity: 1; +} + +.link-opacity-100-hover:hover { + --bs-link-opacity: 1; +} + +.link-offset-1 { + text-underline-offset: 0.125em !important; +} + +.link-offset-1-hover:hover { + text-underline-offset: 0.125em !important; +} + +.link-offset-2 { + text-underline-offset: 0.25em !important; +} + +.link-offset-2-hover:hover { + text-underline-offset: 0.25em !important; +} + +.link-offset-3 { + text-underline-offset: 0.375em !important; +} + +.link-offset-3-hover:hover { + text-underline-offset: 0.375em !important; +} + +.link-underline-primary { + --bs-link-underline-opacity: 1; + text-decoration-color: rgba( + var(--bs-primary-rgb), + var(--bs-link-underline-opacity) + ) !important; +} + +.link-underline-secondary { + --bs-link-underline-opacity: 1; + text-decoration-color: rgba( + var(--bs-secondary-rgb), + var(--bs-link-underline-opacity) + ) !important; +} + +.link-underline-success { + --bs-link-underline-opacity: 1; + text-decoration-color: rgba( + var(--bs-success-rgb), + var(--bs-link-underline-opacity) + ) !important; +} + +.link-underline-info { + --bs-link-underline-opacity: 1; + text-decoration-color: rgba( + var(--bs-info-rgb), + var(--bs-link-underline-opacity) + ) !important; +} + +.link-underline-warning { + --bs-link-underline-opacity: 1; + text-decoration-color: rgba( + var(--bs-warning-rgb), + var(--bs-link-underline-opacity) + ) !important; +} + +.link-underline-danger { + --bs-link-underline-opacity: 1; + text-decoration-color: rgba( + var(--bs-danger-rgb), + var(--bs-link-underline-opacity) + ) !important; +} + +.link-underline-light { + --bs-link-underline-opacity: 1; + text-decoration-color: rgba( + var(--bs-light-rgb), + var(--bs-link-underline-opacity) + ) !important; +} + +.link-underline-dark { + --bs-link-underline-opacity: 1; + text-decoration-color: rgba( + var(--bs-dark-rgb), + var(--bs-link-underline-opacity) + ) !important; +} + +.link-underline { + --bs-link-underline-opacity: 1; + text-decoration-color: rgba( + var(--bs-link-color-rgb), + var(--bs-link-underline-opacity, 1) + ) !important; +} + +.link-underline-opacity-0 { + --bs-link-underline-opacity: 0; +} + +.link-underline-opacity-0-hover:hover { + --bs-link-underline-opacity: 0; +} + +.link-underline-opacity-10 { + --bs-link-underline-opacity: 0.1; +} + +.link-underline-opacity-10-hover:hover { + --bs-link-underline-opacity: 0.1; +} + +.link-underline-opacity-25 { + --bs-link-underline-opacity: 0.25; +} + +.link-underline-opacity-25-hover:hover { + --bs-link-underline-opacity: 0.25; +} + +.link-underline-opacity-50 { + --bs-link-underline-opacity: 0.5; +} + +.link-underline-opacity-50-hover:hover { + --bs-link-underline-opacity: 0.5; +} + +.link-underline-opacity-75 { + --bs-link-underline-opacity: 0.75; +} + +.link-underline-opacity-75-hover:hover { + --bs-link-underline-opacity: 0.75; +} + +.link-underline-opacity-100 { + --bs-link-underline-opacity: 1; +} + +.link-underline-opacity-100-hover:hover { + --bs-link-underline-opacity: 1; +} + +.bg-primary { + --bs-bg-opacity: 1; + background-color: rgba( + var(--bs-primary-rgb), + var(--bs-bg-opacity) + ) !important; +} + +.bg-secondary { + --bs-bg-opacity: 1; + background-color: rgba( + var(--bs-secondary-rgb), + var(--bs-bg-opacity) + ) !important; +} + +.bg-success { + --bs-bg-opacity: 1; + background-color: rgba( + var(--bs-success-rgb), + var(--bs-bg-opacity) + ) !important; +} + +.bg-info { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-info-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-warning { + --bs-bg-opacity: 1; + background-color: rgba( + var(--bs-warning-rgb), + var(--bs-bg-opacity) + ) !important; +} + +.bg-danger { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-danger-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-light { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-light-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-dark { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-dark-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-black { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-black-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-white { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-white-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-body { + --bs-bg-opacity: 1; + background-color: rgba( + var(--bs-body-bg-rgb), + var(--bs-bg-opacity) + ) !important; +} + +.bg-transparent { + --bs-bg-opacity: 1; + background-color: transparent !important; +} + +.bg-body-secondary { + --bs-bg-opacity: 1; + background-color: rgba( + var(--bs-secondary-bg-rgb), + var(--bs-bg-opacity) + ) !important; +} + +.bg-body-tertiary { + --bs-bg-opacity: 1; + background-color: rgba( + var(--bs-tertiary-bg-rgb), + var(--bs-bg-opacity) + ) !important; +} + +.bg-opacity-10 { + --bs-bg-opacity: 0.1; +} + +.bg-opacity-25 { + --bs-bg-opacity: 0.25; +} + +.bg-opacity-50 { + --bs-bg-opacity: 0.5; +} + +.bg-opacity-75 { + --bs-bg-opacity: 0.75; +} + +.bg-opacity-100 { + --bs-bg-opacity: 1; +} + +.bg-primary-subtle { + background-color: var(--bs-primary-bg-subtle) !important; +} + +.bg-secondary-subtle { + background-color: var(--bs-secondary-bg-subtle) !important; +} + +.bg-success-subtle { + background-color: var(--bs-success-bg-subtle) !important; +} + +.bg-info-subtle { + background-color: var(--bs-info-bg-subtle) !important; +} + +.bg-warning-subtle { + background-color: var(--bs-warning-bg-subtle) !important; +} + +.bg-danger-subtle { + background-color: var(--bs-danger-bg-subtle) !important; +} + +.bg-light-subtle { + background-color: var(--bs-light-bg-subtle) !important; +} + +.bg-dark-subtle { + background-color: var(--bs-dark-bg-subtle) !important; +} + +.bg-gradient { + background-image: var(--bs-gradient) !important; +} + +.user-select-all { + user-select: all !important; +} + +.user-select-auto { + user-select: auto !important; +} + +.user-select-none { + user-select: none !important; +} + +.pe-none { + pointer-events: none !important; +} + +.pe-auto { + pointer-events: auto !important; +} + +.rounded { + border-radius: var(--bs-border-radius) !important; +} + +.rounded-0 { + border-radius: 0 !important; +} + +.rounded-1 { + border-radius: var(--bs-border-radius-sm) !important; +} + +.rounded-2 { + border-radius: var(--bs-border-radius) !important; +} + +.rounded-3 { + border-radius: var(--bs-border-radius-lg) !important; +} + +.rounded-4 { + border-radius: var(--bs-border-radius-xl) !important; +} + +.rounded-5 { + border-radius: var(--bs-border-radius-xxl) !important; +} + +.rounded-circle { + border-radius: 50% !important; +} + +.rounded-pill { + border-radius: var(--bs-border-radius-pill) !important; +} + +.rounded-top { + border-top-left-radius: var(--bs-border-radius) !important; + border-top-right-radius: var(--bs-border-radius) !important; +} + +.rounded-top-0 { + border-top-left-radius: 0 !important; + border-top-right-radius: 0 !important; +} + +.rounded-top-1 { + border-top-left-radius: var(--bs-border-radius-sm) !important; + border-top-right-radius: var(--bs-border-radius-sm) !important; +} + +.rounded-top-2 { + border-top-left-radius: var(--bs-border-radius) !important; + border-top-right-radius: var(--bs-border-radius) !important; +} + +.rounded-top-3 { + border-top-left-radius: var(--bs-border-radius-lg) !important; + border-top-right-radius: var(--bs-border-radius-lg) !important; +} + +.rounded-top-4 { + border-top-left-radius: var(--bs-border-radius-xl) !important; + border-top-right-radius: var(--bs-border-radius-xl) !important; +} + +.rounded-top-5 { + border-top-left-radius: var(--bs-border-radius-xxl) !important; + border-top-right-radius: var(--bs-border-radius-xxl) !important; +} + +.rounded-top-circle { + border-top-left-radius: 50% !important; + border-top-right-radius: 50% !important; +} + +.rounded-top-pill { + border-top-left-radius: var(--bs-border-radius-pill) !important; + border-top-right-radius: var(--bs-border-radius-pill) !important; +} + +.rounded-end { + border-top-right-radius: var(--bs-border-radius) !important; + border-bottom-right-radius: var(--bs-border-radius) !important; +} + +.rounded-end-0 { + border-top-right-radius: 0 !important; + border-bottom-right-radius: 0 !important; +} + +.rounded-end-1 { + border-top-right-radius: var(--bs-border-radius-sm) !important; + border-bottom-right-radius: var(--bs-border-radius-sm) !important; +} + +.rounded-end-2 { + border-top-right-radius: var(--bs-border-radius) !important; + border-bottom-right-radius: var(--bs-border-radius) !important; +} + +.rounded-end-3 { + border-top-right-radius: var(--bs-border-radius-lg) !important; + border-bottom-right-radius: var(--bs-border-radius-lg) !important; +} + +.rounded-end-4 { + border-top-right-radius: var(--bs-border-radius-xl) !important; + border-bottom-right-radius: var(--bs-border-radius-xl) !important; +} + +.rounded-end-5 { + border-top-right-radius: var(--bs-border-radius-xxl) !important; + border-bottom-right-radius: var(--bs-border-radius-xxl) !important; +} + +.rounded-end-circle { + border-top-right-radius: 50% !important; + border-bottom-right-radius: 50% !important; +} + +.rounded-end-pill { + border-top-right-radius: var(--bs-border-radius-pill) !important; + border-bottom-right-radius: var(--bs-border-radius-pill) !important; +} + +.rounded-bottom { + border-bottom-right-radius: var(--bs-border-radius) !important; + border-bottom-left-radius: var(--bs-border-radius) !important; +} + +.rounded-bottom-0 { + border-bottom-right-radius: 0 !important; + border-bottom-left-radius: 0 !important; +} + +.rounded-bottom-1 { + border-bottom-right-radius: var(--bs-border-radius-sm) !important; + border-bottom-left-radius: var(--bs-border-radius-sm) !important; +} + +.rounded-bottom-2 { + border-bottom-right-radius: var(--bs-border-radius) !important; + border-bottom-left-radius: var(--bs-border-radius) !important; +} + +.rounded-bottom-3 { + border-bottom-right-radius: var(--bs-border-radius-lg) !important; + border-bottom-left-radius: var(--bs-border-radius-lg) !important; +} + +.rounded-bottom-4 { + border-bottom-right-radius: var(--bs-border-radius-xl) !important; + border-bottom-left-radius: var(--bs-border-radius-xl) !important; +} + +.rounded-bottom-5 { + border-bottom-right-radius: var(--bs-border-radius-xxl) !important; + border-bottom-left-radius: var(--bs-border-radius-xxl) !important; +} + +.rounded-bottom-circle { + border-bottom-right-radius: 50% !important; + border-bottom-left-radius: 50% !important; +} + +.rounded-bottom-pill { + border-bottom-right-radius: var(--bs-border-radius-pill) !important; + border-bottom-left-radius: var(--bs-border-radius-pill) !important; +} + +.rounded-start { + border-bottom-left-radius: var(--bs-border-radius) !important; + border-top-left-radius: var(--bs-border-radius) !important; +} + +.rounded-start-0 { + border-bottom-left-radius: 0 !important; + border-top-left-radius: 0 !important; +} + +.rounded-start-1 { + border-bottom-left-radius: var(--bs-border-radius-sm) !important; + border-top-left-radius: var(--bs-border-radius-sm) !important; +} + +.rounded-start-2 { + border-bottom-left-radius: var(--bs-border-radius) !important; + border-top-left-radius: var(--bs-border-radius) !important; +} + +.rounded-start-3 { + border-bottom-left-radius: var(--bs-border-radius-lg) !important; + border-top-left-radius: var(--bs-border-radius-lg) !important; +} + +.rounded-start-4 { + border-bottom-left-radius: var(--bs-border-radius-xl) !important; + border-top-left-radius: var(--bs-border-radius-xl) !important; +} + +.rounded-start-5 { + border-bottom-left-radius: var(--bs-border-radius-xxl) !important; + border-top-left-radius: var(--bs-border-radius-xxl) !important; +} + +.rounded-start-circle { + border-bottom-left-radius: 50% !important; + border-top-left-radius: 50% !important; +} + +.rounded-start-pill { + border-bottom-left-radius: var(--bs-border-radius-pill) !important; + border-top-left-radius: var(--bs-border-radius-pill) !important; +} + +.visible { + visibility: visible !important; +} + +.invisible { + visibility: hidden !important; +} + +.z-n1 { + z-index: -1 !important; +} + +.z-0 { + z-index: 0 !important; +} + +.z-1 { + z-index: 1 !important; +} + +.z-2 { + z-index: 2 !important; +} + +.z-3 { + z-index: 3 !important; +} + +@media (min-width: 576px) { + .float-sm-start { + float: left !important; + } + .float-sm-end { + float: right !important; + } + .float-sm-none { + float: none !important; + } + .object-fit-sm-contain { + object-fit: contain !important; + } + .object-fit-sm-cover { + object-fit: cover !important; + } + .object-fit-sm-fill { + object-fit: fill !important; + } + .object-fit-sm-scale { + object-fit: scale-down !important; + } + .object-fit-sm-none { + object-fit: none !important; + } + .d-sm-inline { + display: inline !important; + } + .d-sm-inline-block { + display: inline-block !important; + } + .d-sm-block { + display: block !important; + } + .d-sm-grid { + display: grid !important; + } + .d-sm-inline-grid { + display: inline-grid !important; + } + .d-sm-table { + display: table !important; + } + .d-sm-table-row { + display: table-row !important; + } + .d-sm-table-cell { + display: table-cell !important; + } + .d-sm-flex { + display: flex !important; + } + .d-sm-inline-flex { + display: inline-flex !important; + } + .d-sm-none { + display: none !important; + } + .flex-sm-fill { + flex: 1 1 auto !important; + } + .flex-sm-row { + flex-direction: row !important; + } + .flex-sm-column { + flex-direction: column !important; + } + .flex-sm-row-reverse { + flex-direction: row-reverse !important; + } + .flex-sm-column-reverse { + flex-direction: column-reverse !important; + } + .flex-sm-grow-0 { + flex-grow: 0 !important; + } + .flex-sm-grow-1 { + flex-grow: 1 !important; + } + .flex-sm-shrink-0 { + flex-shrink: 0 !important; + } + .flex-sm-shrink-1 { + flex-shrink: 1 !important; + } + .flex-sm-wrap { + flex-wrap: wrap !important; + } + .flex-sm-nowrap { + flex-wrap: nowrap !important; + } + .flex-sm-wrap-reverse { + flex-wrap: wrap-reverse !important; + } + .justify-content-sm-start { + justify-content: flex-start !important; + } + .justify-content-sm-end { + justify-content: flex-end !important; + } + .justify-content-sm-center { + justify-content: center !important; + } + .justify-content-sm-between { + justify-content: space-between !important; + } + .justify-content-sm-around { + justify-content: space-around !important; + } + .justify-content-sm-evenly { + justify-content: space-evenly !important; + } + .align-items-sm-start { + align-items: flex-start !important; + } + .align-items-sm-end { + align-items: flex-end !important; + } + .align-items-sm-center { + align-items: center !important; + } + .align-items-sm-baseline { + align-items: baseline !important; + } + .align-items-sm-stretch { + align-items: stretch !important; + } + .align-content-sm-start { + align-content: flex-start !important; + } + .align-content-sm-end { + align-content: flex-end !important; + } + .align-content-sm-center { + align-content: center !important; + } + .align-content-sm-between { + align-content: space-between !important; + } + .align-content-sm-around { + align-content: space-around !important; + } + .align-content-sm-stretch { + align-content: stretch !important; + } + .align-self-sm-auto { + align-self: auto !important; + } + .align-self-sm-start { + align-self: flex-start !important; + } + .align-self-sm-end { + align-self: flex-end !important; + } + .align-self-sm-center { + align-self: center !important; + } + .align-self-sm-baseline { + align-self: baseline !important; + } + .align-self-sm-stretch { + align-self: stretch !important; + } + .order-sm-first { + order: -1 !important; + } + .order-sm-0 { + order: 0 !important; + } + .order-sm-1 { + order: 1 !important; + } + .order-sm-2 { + order: 2 !important; + } + .order-sm-3 { + order: 3 !important; + } + .order-sm-4 { + order: 4 !important; + } + .order-sm-5 { + order: 5 !important; + } + .order-sm-last { + order: 6 !important; + } + .m-sm-0 { + margin: 0 !important; + } + .m-sm-1 { + margin: 0.25rem !important; + } + .m-sm-2 { + margin: 0.5rem !important; + } + .m-sm-3 { + margin: 1rem !important; + } + .m-sm-4 { + margin: 1.5rem !important; + } + .m-sm-5 { + margin: 3rem !important; + } + .m-sm-auto { + margin: auto !important; + } + .mx-sm-0 { + margin-right: 0 !important; + margin-left: 0 !important; + } + .mx-sm-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; + } + .mx-sm-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; + } + .mx-sm-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; + } + .mx-sm-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; + } + .mx-sm-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; + } + .mx-sm-auto { + margin-right: auto !important; + margin-left: auto !important; + } + .my-sm-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; + } + .my-sm-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; + } + .my-sm-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; + } + .my-sm-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; + } + .my-sm-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; + } + .my-sm-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; + } + .my-sm-auto { + margin-top: auto !important; + margin-bottom: auto !important; + } + .mt-sm-0 { + margin-top: 0 !important; + } + .mt-sm-1 { + margin-top: 0.25rem !important; + } + .mt-sm-2 { + margin-top: 0.5rem !important; + } + .mt-sm-3 { + margin-top: 1rem !important; + } + .mt-sm-4 { + margin-top: 1.5rem !important; + } + .mt-sm-5 { + margin-top: 3rem !important; + } + .mt-sm-auto { + margin-top: auto !important; + } + .me-sm-0 { + margin-right: 0 !important; + } + .me-sm-1 { + margin-right: 0.25rem !important; + } + .me-sm-2 { + margin-right: 0.5rem !important; + } + .me-sm-3 { + margin-right: 1rem !important; + } + .me-sm-4 { + margin-right: 1.5rem !important; + } + .me-sm-5 { + margin-right: 3rem !important; + } + .me-sm-auto { + margin-right: auto !important; + } + .mb-sm-0 { + margin-bottom: 0 !important; + } + .mb-sm-1 { + margin-bottom: 0.25rem !important; + } + .mb-sm-2 { + margin-bottom: 0.5rem !important; + } + .mb-sm-3 { + margin-bottom: 1rem !important; + } + .mb-sm-4 { + margin-bottom: 1.5rem !important; + } + .mb-sm-5 { + margin-bottom: 3rem !important; + } + .mb-sm-auto { + margin-bottom: auto !important; + } + .ms-sm-0 { + margin-left: 0 !important; + } + .ms-sm-1 { + margin-left: 0.25rem !important; + } + .ms-sm-2 { + margin-left: 0.5rem !important; + } + .ms-sm-3 { + margin-left: 1rem !important; + } + .ms-sm-4 { + margin-left: 1.5rem !important; + } + .ms-sm-5 { + margin-left: 3rem !important; + } + .ms-sm-auto { + margin-left: auto !important; + } + .p-sm-0 { + padding: 0 !important; + } + .p-sm-1 { + padding: 0.25rem !important; + } + .p-sm-2 { + padding: 0.5rem !important; + } + .p-sm-3 { + padding: 1rem !important; + } + .p-sm-4 { + padding: 1.5rem !important; + } + .p-sm-5 { + padding: 3rem !important; + } + .px-sm-0 { + padding-right: 0 !important; + padding-left: 0 !important; + } + .px-sm-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; + } + .px-sm-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; + } + .px-sm-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; + } + .px-sm-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; + } + .px-sm-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; + } + .py-sm-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; + } + .py-sm-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; + } + .py-sm-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; + } + .py-sm-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; + } + .py-sm-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; + } + .py-sm-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; + } + .pt-sm-0 { + padding-top: 0 !important; + } + .pt-sm-1 { + padding-top: 0.25rem !important; + } + .pt-sm-2 { + padding-top: 0.5rem !important; + } + .pt-sm-3 { + padding-top: 1rem !important; + } + .pt-sm-4 { + padding-top: 1.5rem !important; + } + .pt-sm-5 { + padding-top: 3rem !important; + } + .pe-sm-0 { + padding-right: 0 !important; + } + .pe-sm-1 { + padding-right: 0.25rem !important; + } + .pe-sm-2 { + padding-right: 0.5rem !important; + } + .pe-sm-3 { + padding-right: 1rem !important; + } + .pe-sm-4 { + padding-right: 1.5rem !important; + } + .pe-sm-5 { + padding-right: 3rem !important; + } + .pb-sm-0 { + padding-bottom: 0 !important; + } + .pb-sm-1 { + padding-bottom: 0.25rem !important; + } + .pb-sm-2 { + padding-bottom: 0.5rem !important; + } + .pb-sm-3 { + padding-bottom: 1rem !important; + } + .pb-sm-4 { + padding-bottom: 1.5rem !important; + } + .pb-sm-5 { + padding-bottom: 3rem !important; + } + .ps-sm-0 { + padding-left: 0 !important; + } + .ps-sm-1 { + padding-left: 0.25rem !important; + } + .ps-sm-2 { + padding-left: 0.5rem !important; + } + .ps-sm-3 { + padding-left: 1rem !important; + } + .ps-sm-4 { + padding-left: 1.5rem !important; + } + .ps-sm-5 { + padding-left: 3rem !important; + } + .gap-sm-0 { + gap: 0 !important; + } + .gap-sm-1 { + gap: 0.25rem !important; + } + .gap-sm-2 { + gap: 0.5rem !important; + } + .gap-sm-3 { + gap: 1rem !important; + } + .gap-sm-4 { + gap: 1.5rem !important; + } + .gap-sm-5 { + gap: 3rem !important; + } + .row-gap-sm-0 { + row-gap: 0 !important; + } + .row-gap-sm-1 { + row-gap: 0.25rem !important; + } + .row-gap-sm-2 { + row-gap: 0.5rem !important; + } + .row-gap-sm-3 { + row-gap: 1rem !important; + } + .row-gap-sm-4 { + row-gap: 1.5rem !important; + } + .row-gap-sm-5 { + row-gap: 3rem !important; + } + .column-gap-sm-0 { + column-gap: 0 !important; + } + .column-gap-sm-1 { + column-gap: 0.25rem !important; + } + .column-gap-sm-2 { + column-gap: 0.5rem !important; + } + .column-gap-sm-3 { + column-gap: 1rem !important; + } + .column-gap-sm-4 { + column-gap: 1.5rem !important; + } + .column-gap-sm-5 { + column-gap: 3rem !important; + } + .text-sm-start { + text-align: left !important; + } + .text-sm-end { + text-align: right !important; + } + .text-sm-center { + text-align: center !important; + } +} + +@media (min-width: 768px) { + .float-md-start { + float: left !important; + } + .float-md-end { + float: right !important; + } + .float-md-none { + float: none !important; + } + .object-fit-md-contain { + object-fit: contain !important; + } + .object-fit-md-cover { + object-fit: cover !important; + } + .object-fit-md-fill { + object-fit: fill !important; + } + .object-fit-md-scale { + object-fit: scale-down !important; + } + .object-fit-md-none { + object-fit: none !important; + } + .d-md-inline { + display: inline !important; + } + .d-md-inline-block { + display: inline-block !important; + } + .d-md-block { + display: block !important; + } + .d-md-grid { + display: grid !important; + } + .d-md-inline-grid { + display: inline-grid !important; + } + .d-md-table { + display: table !important; + } + .d-md-table-row { + display: table-row !important; + } + .d-md-table-cell { + display: table-cell !important; + } + .d-md-flex { + display: flex !important; + } + .d-md-inline-flex { + display: inline-flex !important; + } + .d-md-none { + display: none !important; + } + .flex-md-fill { + flex: 1 1 auto !important; + } + .flex-md-row { + flex-direction: row !important; + } + .flex-md-column { + flex-direction: column !important; + } + .flex-md-row-reverse { + flex-direction: row-reverse !important; + } + .flex-md-column-reverse { + flex-direction: column-reverse !important; + } + .flex-md-grow-0 { + flex-grow: 0 !important; + } + .flex-md-grow-1 { + flex-grow: 1 !important; + } + .flex-md-shrink-0 { + flex-shrink: 0 !important; + } + .flex-md-shrink-1 { + flex-shrink: 1 !important; + } + .flex-md-wrap { + flex-wrap: wrap !important; + } + .flex-md-nowrap { + flex-wrap: nowrap !important; + } + .flex-md-wrap-reverse { + flex-wrap: wrap-reverse !important; + } + .justify-content-md-start { + justify-content: flex-start !important; + } + .justify-content-md-end { + justify-content: flex-end !important; + } + .justify-content-md-center { + justify-content: center !important; + } + .justify-content-md-between { + justify-content: space-between !important; + } + .justify-content-md-around { + justify-content: space-around !important; + } + .justify-content-md-evenly { + justify-content: space-evenly !important; + } + .align-items-md-start { + align-items: flex-start !important; + } + .align-items-md-end { + align-items: flex-end !important; + } + .align-items-md-center { + align-items: center !important; + } + .align-items-md-baseline { + align-items: baseline !important; + } + .align-items-md-stretch { + align-items: stretch !important; + } + .align-content-md-start { + align-content: flex-start !important; + } + .align-content-md-end { + align-content: flex-end !important; + } + .align-content-md-center { + align-content: center !important; + } + .align-content-md-between { + align-content: space-between !important; + } + .align-content-md-around { + align-content: space-around !important; + } + .align-content-md-stretch { + align-content: stretch !important; + } + .align-self-md-auto { + align-self: auto !important; + } + .align-self-md-start { + align-self: flex-start !important; + } + .align-self-md-end { + align-self: flex-end !important; + } + .align-self-md-center { + align-self: center !important; + } + .align-self-md-baseline { + align-self: baseline !important; + } + .align-self-md-stretch { + align-self: stretch !important; + } + .order-md-first { + order: -1 !important; + } + .order-md-0 { + order: 0 !important; + } + .order-md-1 { + order: 1 !important; + } + .order-md-2 { + order: 2 !important; + } + .order-md-3 { + order: 3 !important; + } + .order-md-4 { + order: 4 !important; + } + .order-md-5 { + order: 5 !important; + } + .order-md-last { + order: 6 !important; + } + .m-md-0 { + margin: 0 !important; + } + .m-md-1 { + margin: 0.25rem !important; + } + .m-md-2 { + margin: 0.5rem !important; + } + .m-md-3 { + margin: 1rem !important; + } + .m-md-4 { + margin: 1.5rem !important; + } + .m-md-5 { + margin: 3rem !important; + } + .m-md-auto { + margin: auto !important; + } + .mx-md-0 { + margin-right: 0 !important; + margin-left: 0 !important; + } + .mx-md-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; + } + .mx-md-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; + } + .mx-md-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; + } + .mx-md-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; + } + .mx-md-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; + } + .mx-md-auto { + margin-right: auto !important; + margin-left: auto !important; + } + .my-md-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; + } + .my-md-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; + } + .my-md-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; + } + .my-md-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; + } + .my-md-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; + } + .my-md-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; + } + .my-md-auto { + margin-top: auto !important; + margin-bottom: auto !important; + } + .mt-md-0 { + margin-top: 0 !important; + } + .mt-md-1 { + margin-top: 0.25rem !important; + } + .mt-md-2 { + margin-top: 0.5rem !important; + } + .mt-md-3 { + margin-top: 1rem !important; + } + .mt-md-4 { + margin-top: 1.5rem !important; + } + .mt-md-5 { + margin-top: 3rem !important; + } + .mt-md-auto { + margin-top: auto !important; + } + .me-md-0 { + margin-right: 0 !important; + } + .me-md-1 { + margin-right: 0.25rem !important; + } + .me-md-2 { + margin-right: 0.5rem !important; + } + .me-md-3 { + margin-right: 1rem !important; + } + .me-md-4 { + margin-right: 1.5rem !important; + } + .me-md-5 { + margin-right: 3rem !important; + } + .me-md-auto { + margin-right: auto !important; + } + .mb-md-0 { + margin-bottom: 0 !important; + } + .mb-md-1 { + margin-bottom: 0.25rem !important; + } + .mb-md-2 { + margin-bottom: 0.5rem !important; + } + .mb-md-3 { + margin-bottom: 1rem !important; + } + .mb-md-4 { + margin-bottom: 1.5rem !important; + } + .mb-md-5 { + margin-bottom: 3rem !important; + } + .mb-md-auto { + margin-bottom: auto !important; + } + .ms-md-0 { + margin-left: 0 !important; + } + .ms-md-1 { + margin-left: 0.25rem !important; + } + .ms-md-2 { + margin-left: 0.5rem !important; + } + .ms-md-3 { + margin-left: 1rem !important; + } + .ms-md-4 { + margin-left: 1.5rem !important; + } + .ms-md-5 { + margin-left: 3rem !important; + } + .ms-md-auto { + margin-left: auto !important; + } + .p-md-0 { + padding: 0 !important; + } + .p-md-1 { + padding: 0.25rem !important; + } + .p-md-2 { + padding: 0.5rem !important; + } + .p-md-3 { + padding: 1rem !important; + } + .p-md-4 { + padding: 1.5rem !important; + } + .p-md-5 { + padding: 3rem !important; + } + .px-md-0 { + padding-right: 0 !important; + padding-left: 0 !important; + } + .px-md-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; + } + .px-md-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; + } + .px-md-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; + } + .px-md-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; + } + .px-md-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; + } + .py-md-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; + } + .py-md-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; + } + .py-md-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; + } + .py-md-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; + } + .py-md-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; + } + .py-md-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; + } + .pt-md-0 { + padding-top: 0 !important; + } + .pt-md-1 { + padding-top: 0.25rem !important; + } + .pt-md-2 { + padding-top: 0.5rem !important; + } + .pt-md-3 { + padding-top: 1rem !important; + } + .pt-md-4 { + padding-top: 1.5rem !important; + } + .pt-md-5 { + padding-top: 3rem !important; + } + .pe-md-0 { + padding-right: 0 !important; + } + .pe-md-1 { + padding-right: 0.25rem !important; + } + .pe-md-2 { + padding-right: 0.5rem !important; + } + .pe-md-3 { + padding-right: 1rem !important; + } + .pe-md-4 { + padding-right: 1.5rem !important; + } + .pe-md-5 { + padding-right: 3rem !important; + } + .pb-md-0 { + padding-bottom: 0 !important; + } + .pb-md-1 { + padding-bottom: 0.25rem !important; + } + .pb-md-2 { + padding-bottom: 0.5rem !important; + } + .pb-md-3 { + padding-bottom: 1rem !important; + } + .pb-md-4 { + padding-bottom: 1.5rem !important; + } + .pb-md-5 { + padding-bottom: 3rem !important; + } + .ps-md-0 { + padding-left: 0 !important; + } + .ps-md-1 { + padding-left: 0.25rem !important; + } + .ps-md-2 { + padding-left: 0.5rem !important; + } + .ps-md-3 { + padding-left: 1rem !important; + } + .ps-md-4 { + padding-left: 1.5rem !important; + } + .ps-md-5 { + padding-left: 3rem !important; + } + .gap-md-0 { + gap: 0 !important; + } + .gap-md-1 { + gap: 0.25rem !important; + } + .gap-md-2 { + gap: 0.5rem !important; + } + .gap-md-3 { + gap: 1rem !important; + } + .gap-md-4 { + gap: 1.5rem !important; + } + .gap-md-5 { + gap: 3rem !important; + } + .row-gap-md-0 { + row-gap: 0 !important; + } + .row-gap-md-1 { + row-gap: 0.25rem !important; + } + .row-gap-md-2 { + row-gap: 0.5rem !important; + } + .row-gap-md-3 { + row-gap: 1rem !important; + } + .row-gap-md-4 { + row-gap: 1.5rem !important; + } + .row-gap-md-5 { + row-gap: 3rem !important; + } + .column-gap-md-0 { + column-gap: 0 !important; + } + .column-gap-md-1 { + column-gap: 0.25rem !important; + } + .column-gap-md-2 { + column-gap: 0.5rem !important; + } + .column-gap-md-3 { + column-gap: 1rem !important; + } + .column-gap-md-4 { + column-gap: 1.5rem !important; + } + .column-gap-md-5 { + column-gap: 3rem !important; + } + .text-md-start { + text-align: left !important; + } + .text-md-end { + text-align: right !important; + } + .text-md-center { + text-align: center !important; + } +} + +@media (min-width: 992px) { + .float-lg-start { + float: left !important; + } + .float-lg-end { + float: right !important; + } + .float-lg-none { + float: none !important; + } + .object-fit-lg-contain { + object-fit: contain !important; + } + .object-fit-lg-cover { + object-fit: cover !important; + } + .object-fit-lg-fill { + object-fit: fill !important; + } + .object-fit-lg-scale { + object-fit: scale-down !important; + } + .object-fit-lg-none { + object-fit: none !important; + } + .d-lg-inline { + display: inline !important; + } + .d-lg-inline-block { + display: inline-block !important; + } + .d-lg-block { + display: block !important; + } + .d-lg-grid { + display: grid !important; + } + .d-lg-inline-grid { + display: inline-grid !important; + } + .d-lg-table { + display: table !important; + } + .d-lg-table-row { + display: table-row !important; + } + .d-lg-table-cell { + display: table-cell !important; + } + .d-lg-flex { + display: flex !important; + } + .d-lg-inline-flex { + display: inline-flex !important; + } + .d-lg-none { + display: none !important; + } + .flex-lg-fill { + flex: 1 1 auto !important; + } + .flex-lg-row { + flex-direction: row !important; + } + .flex-lg-column { + flex-direction: column !important; + } + .flex-lg-row-reverse { + flex-direction: row-reverse !important; + } + .flex-lg-column-reverse { + flex-direction: column-reverse !important; + } + .flex-lg-grow-0 { + flex-grow: 0 !important; + } + .flex-lg-grow-1 { + flex-grow: 1 !important; + } + .flex-lg-shrink-0 { + flex-shrink: 0 !important; + } + .flex-lg-shrink-1 { + flex-shrink: 1 !important; + } + .flex-lg-wrap { + flex-wrap: wrap !important; + } + .flex-lg-nowrap { + flex-wrap: nowrap !important; + } + .flex-lg-wrap-reverse { + flex-wrap: wrap-reverse !important; + } + .justify-content-lg-start { + justify-content: flex-start !important; + } + .justify-content-lg-end { + justify-content: flex-end !important; + } + .justify-content-lg-center { + justify-content: center !important; + } + .justify-content-lg-between { + justify-content: space-between !important; + } + .justify-content-lg-around { + justify-content: space-around !important; + } + .justify-content-lg-evenly { + justify-content: space-evenly !important; + } + .align-items-lg-start { + align-items: flex-start !important; + } + .align-items-lg-end { + align-items: flex-end !important; + } + .align-items-lg-center { + align-items: center !important; + } + .align-items-lg-baseline { + align-items: baseline !important; + } + .align-items-lg-stretch { + align-items: stretch !important; + } + .align-content-lg-start { + align-content: flex-start !important; + } + .align-content-lg-end { + align-content: flex-end !important; + } + .align-content-lg-center { + align-content: center !important; + } + .align-content-lg-between { + align-content: space-between !important; + } + .align-content-lg-around { + align-content: space-around !important; + } + .align-content-lg-stretch { + align-content: stretch !important; + } + .align-self-lg-auto { + align-self: auto !important; + } + .align-self-lg-start { + align-self: flex-start !important; + } + .align-self-lg-end { + align-self: flex-end !important; + } + .align-self-lg-center { + align-self: center !important; + } + .align-self-lg-baseline { + align-self: baseline !important; + } + .align-self-lg-stretch { + align-self: stretch !important; + } + .order-lg-first { + order: -1 !important; + } + .order-lg-0 { + order: 0 !important; + } + .order-lg-1 { + order: 1 !important; + } + .order-lg-2 { + order: 2 !important; + } + .order-lg-3 { + order: 3 !important; + } + .order-lg-4 { + order: 4 !important; + } + .order-lg-5 { + order: 5 !important; + } + .order-lg-last { + order: 6 !important; + } + .m-lg-0 { + margin: 0 !important; + } + .m-lg-1 { + margin: 0.25rem !important; + } + .m-lg-2 { + margin: 0.5rem !important; + } + .m-lg-3 { + margin: 1rem !important; + } + .m-lg-4 { + margin: 1.5rem !important; + } + .m-lg-5 { + margin: 3rem !important; + } + .m-lg-auto { + margin: auto !important; + } + .mx-lg-0 { + margin-right: 0 !important; + margin-left: 0 !important; + } + .mx-lg-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; + } + .mx-lg-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; + } + .mx-lg-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; + } + .mx-lg-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; + } + .mx-lg-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; + } + .mx-lg-auto { + margin-right: auto !important; + margin-left: auto !important; + } + .my-lg-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; + } + .my-lg-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; + } + .my-lg-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; + } + .my-lg-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; + } + .my-lg-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; + } + .my-lg-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; + } + .my-lg-auto { + margin-top: auto !important; + margin-bottom: auto !important; + } + .mt-lg-0 { + margin-top: 0 !important; + } + .mt-lg-1 { + margin-top: 0.25rem !important; + } + .mt-lg-2 { + margin-top: 0.5rem !important; + } + .mt-lg-3 { + margin-top: 1rem !important; + } + .mt-lg-4 { + margin-top: 1.5rem !important; + } + .mt-lg-5 { + margin-top: 3rem !important; + } + .mt-lg-auto { + margin-top: auto !important; + } + .me-lg-0 { + margin-right: 0 !important; + } + .me-lg-1 { + margin-right: 0.25rem !important; + } + .me-lg-2 { + margin-right: 0.5rem !important; + } + .me-lg-3 { + margin-right: 1rem !important; + } + .me-lg-4 { + margin-right: 1.5rem !important; + } + .me-lg-5 { + margin-right: 3rem !important; + } + .me-lg-auto { + margin-right: auto !important; + } + .mb-lg-0 { + margin-bottom: 0 !important; + } + .mb-lg-1 { + margin-bottom: 0.25rem !important; + } + .mb-lg-2 { + margin-bottom: 0.5rem !important; + } + .mb-lg-3 { + margin-bottom: 1rem !important; + } + .mb-lg-4 { + margin-bottom: 1.5rem !important; + } + .mb-lg-5 { + margin-bottom: 3rem !important; + } + .mb-lg-auto { + margin-bottom: auto !important; + } + .ms-lg-0 { + margin-left: 0 !important; + } + .ms-lg-1 { + margin-left: 0.25rem !important; + } + .ms-lg-2 { + margin-left: 0.5rem !important; + } + .ms-lg-3 { + margin-left: 1rem !important; + } + .ms-lg-4 { + margin-left: 1.5rem !important; + } + .ms-lg-5 { + margin-left: 3rem !important; + } + .ms-lg-auto { + margin-left: auto !important; + } + .p-lg-0 { + padding: 0 !important; + } + .p-lg-1 { + padding: 0.25rem !important; + } + .p-lg-2 { + padding: 0.5rem !important; + } + .p-lg-3 { + padding: 1rem !important; + } + .p-lg-4 { + padding: 1.5rem !important; + } + .p-lg-5 { + padding: 3rem !important; + } + .px-lg-0 { + padding-right: 0 !important; + padding-left: 0 !important; + } + .px-lg-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; + } + .px-lg-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; + } + .px-lg-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; + } + .px-lg-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; + } + .px-lg-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; + } + .py-lg-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; + } + .py-lg-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; + } + .py-lg-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; + } + .py-lg-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; + } + .py-lg-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; + } + .py-lg-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; + } + .pt-lg-0 { + padding-top: 0 !important; + } + .pt-lg-1 { + padding-top: 0.25rem !important; + } + .pt-lg-2 { + padding-top: 0.5rem !important; + } + .pt-lg-3 { + padding-top: 1rem !important; + } + .pt-lg-4 { + padding-top: 1.5rem !important; + } + .pt-lg-5 { + padding-top: 3rem !important; + } + .pe-lg-0 { + padding-right: 0 !important; + } + .pe-lg-1 { + padding-right: 0.25rem !important; + } + .pe-lg-2 { + padding-right: 0.5rem !important; + } + .pe-lg-3 { + padding-right: 1rem !important; + } + .pe-lg-4 { + padding-right: 1.5rem !important; + } + .pe-lg-5 { + padding-right: 3rem !important; + } + .pb-lg-0 { + padding-bottom: 0 !important; + } + .pb-lg-1 { + padding-bottom: 0.25rem !important; + } + .pb-lg-2 { + padding-bottom: 0.5rem !important; + } + .pb-lg-3 { + padding-bottom: 1rem !important; + } + .pb-lg-4 { + padding-bottom: 1.5rem !important; + } + .pb-lg-5 { + padding-bottom: 3rem !important; + } + .ps-lg-0 { + padding-left: 0 !important; + } + .ps-lg-1 { + padding-left: 0.25rem !important; + } + .ps-lg-2 { + padding-left: 0.5rem !important; + } + .ps-lg-3 { + padding-left: 1rem !important; + } + .ps-lg-4 { + padding-left: 1.5rem !important; + } + .ps-lg-5 { + padding-left: 3rem !important; + } + .gap-lg-0 { + gap: 0 !important; + } + .gap-lg-1 { + gap: 0.25rem !important; + } + .gap-lg-2 { + gap: 0.5rem !important; + } + .gap-lg-3 { + gap: 1rem !important; + } + .gap-lg-4 { + gap: 1.5rem !important; + } + .gap-lg-5 { + gap: 3rem !important; + } + .row-gap-lg-0 { + row-gap: 0 !important; + } + .row-gap-lg-1 { + row-gap: 0.25rem !important; + } + .row-gap-lg-2 { + row-gap: 0.5rem !important; + } + .row-gap-lg-3 { + row-gap: 1rem !important; + } + .row-gap-lg-4 { + row-gap: 1.5rem !important; + } + .row-gap-lg-5 { + row-gap: 3rem !important; + } + .column-gap-lg-0 { + column-gap: 0 !important; + } + .column-gap-lg-1 { + column-gap: 0.25rem !important; + } + .column-gap-lg-2 { + column-gap: 0.5rem !important; + } + .column-gap-lg-3 { + column-gap: 1rem !important; + } + .column-gap-lg-4 { + column-gap: 1.5rem !important; + } + .column-gap-lg-5 { + column-gap: 3rem !important; + } + .text-lg-start { + text-align: left !important; + } + .text-lg-end { + text-align: right !important; + } + .text-lg-center { + text-align: center !important; + } +} + +@media (min-width: 1200px) { + .float-xl-start { + float: left !important; + } + .float-xl-end { + float: right !important; + } + .float-xl-none { + float: none !important; + } + .object-fit-xl-contain { + object-fit: contain !important; + } + .object-fit-xl-cover { + object-fit: cover !important; + } + .object-fit-xl-fill { + object-fit: fill !important; + } + .object-fit-xl-scale { + object-fit: scale-down !important; + } + .object-fit-xl-none { + object-fit: none !important; + } + .d-xl-inline { + display: inline !important; + } + .d-xl-inline-block { + display: inline-block !important; + } + .d-xl-block { + display: block !important; + } + .d-xl-grid { + display: grid !important; + } + .d-xl-inline-grid { + display: inline-grid !important; + } + .d-xl-table { + display: table !important; + } + .d-xl-table-row { + display: table-row !important; + } + .d-xl-table-cell { + display: table-cell !important; + } + .d-xl-flex { + display: flex !important; + } + .d-xl-inline-flex { + display: inline-flex !important; + } + .d-xl-none { + display: none !important; + } + .flex-xl-fill { + flex: 1 1 auto !important; + } + .flex-xl-row { + flex-direction: row !important; + } + .flex-xl-column { + flex-direction: column !important; + } + .flex-xl-row-reverse { + flex-direction: row-reverse !important; + } + .flex-xl-column-reverse { + flex-direction: column-reverse !important; + } + .flex-xl-grow-0 { + flex-grow: 0 !important; + } + .flex-xl-grow-1 { + flex-grow: 1 !important; + } + .flex-xl-shrink-0 { + flex-shrink: 0 !important; + } + .flex-xl-shrink-1 { + flex-shrink: 1 !important; + } + .flex-xl-wrap { + flex-wrap: wrap !important; + } + .flex-xl-nowrap { + flex-wrap: nowrap !important; + } + .flex-xl-wrap-reverse { + flex-wrap: wrap-reverse !important; + } + .justify-content-xl-start { + justify-content: flex-start !important; + } + .justify-content-xl-end { + justify-content: flex-end !important; + } + .justify-content-xl-center { + justify-content: center !important; + } + .justify-content-xl-between { + justify-content: space-between !important; + } + .justify-content-xl-around { + justify-content: space-around !important; + } + .justify-content-xl-evenly { + justify-content: space-evenly !important; + } + .align-items-xl-start { + align-items: flex-start !important; + } + .align-items-xl-end { + align-items: flex-end !important; + } + .align-items-xl-center { + align-items: center !important; + } + .align-items-xl-baseline { + align-items: baseline !important; + } + .align-items-xl-stretch { + align-items: stretch !important; + } + .align-content-xl-start { + align-content: flex-start !important; + } + .align-content-xl-end { + align-content: flex-end !important; + } + .align-content-xl-center { + align-content: center !important; + } + .align-content-xl-between { + align-content: space-between !important; + } + .align-content-xl-around { + align-content: space-around !important; + } + .align-content-xl-stretch { + align-content: stretch !important; + } + .align-self-xl-auto { + align-self: auto !important; + } + .align-self-xl-start { + align-self: flex-start !important; + } + .align-self-xl-end { + align-self: flex-end !important; + } + .align-self-xl-center { + align-self: center !important; + } + .align-self-xl-baseline { + align-self: baseline !important; + } + .align-self-xl-stretch { + align-self: stretch !important; + } + .order-xl-first { + order: -1 !important; + } + .order-xl-0 { + order: 0 !important; + } + .order-xl-1 { + order: 1 !important; + } + .order-xl-2 { + order: 2 !important; + } + .order-xl-3 { + order: 3 !important; + } + .order-xl-4 { + order: 4 !important; + } + .order-xl-5 { + order: 5 !important; + } + .order-xl-last { + order: 6 !important; + } + .m-xl-0 { + margin: 0 !important; + } + .m-xl-1 { + margin: 0.25rem !important; + } + .m-xl-2 { + margin: 0.5rem !important; + } + .m-xl-3 { + margin: 1rem !important; + } + .m-xl-4 { + margin: 1.5rem !important; + } + .m-xl-5 { + margin: 3rem !important; + } + .m-xl-auto { + margin: auto !important; + } + .mx-xl-0 { + margin-right: 0 !important; + margin-left: 0 !important; + } + .mx-xl-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; + } + .mx-xl-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; + } + .mx-xl-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; + } + .mx-xl-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; + } + .mx-xl-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; + } + .mx-xl-auto { + margin-right: auto !important; + margin-left: auto !important; + } + .my-xl-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; + } + .my-xl-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; + } + .my-xl-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; + } + .my-xl-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; + } + .my-xl-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; + } + .my-xl-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; + } + .my-xl-auto { + margin-top: auto !important; + margin-bottom: auto !important; + } + .mt-xl-0 { + margin-top: 0 !important; + } + .mt-xl-1 { + margin-top: 0.25rem !important; + } + .mt-xl-2 { + margin-top: 0.5rem !important; + } + .mt-xl-3 { + margin-top: 1rem !important; + } + .mt-xl-4 { + margin-top: 1.5rem !important; + } + .mt-xl-5 { + margin-top: 3rem !important; + } + .mt-xl-auto { + margin-top: auto !important; + } + .me-xl-0 { + margin-right: 0 !important; + } + .me-xl-1 { + margin-right: 0.25rem !important; + } + .me-xl-2 { + margin-right: 0.5rem !important; + } + .me-xl-3 { + margin-right: 1rem !important; + } + .me-xl-4 { + margin-right: 1.5rem !important; + } + .me-xl-5 { + margin-right: 3rem !important; + } + .me-xl-auto { + margin-right: auto !important; + } + .mb-xl-0 { + margin-bottom: 0 !important; + } + .mb-xl-1 { + margin-bottom: 0.25rem !important; + } + .mb-xl-2 { + margin-bottom: 0.5rem !important; + } + .mb-xl-3 { + margin-bottom: 1rem !important; + } + .mb-xl-4 { + margin-bottom: 1.5rem !important; + } + .mb-xl-5 { + margin-bottom: 3rem !important; + } + .mb-xl-auto { + margin-bottom: auto !important; + } + .ms-xl-0 { + margin-left: 0 !important; + } + .ms-xl-1 { + margin-left: 0.25rem !important; + } + .ms-xl-2 { + margin-left: 0.5rem !important; + } + .ms-xl-3 { + margin-left: 1rem !important; + } + .ms-xl-4 { + margin-left: 1.5rem !important; + } + .ms-xl-5 { + margin-left: 3rem !important; + } + .ms-xl-auto { + margin-left: auto !important; + } + .p-xl-0 { + padding: 0 !important; + } + .p-xl-1 { + padding: 0.25rem !important; + } + .p-xl-2 { + padding: 0.5rem !important; + } + .p-xl-3 { + padding: 1rem !important; + } + .p-xl-4 { + padding: 1.5rem !important; + } + .p-xl-5 { + padding: 3rem !important; + } + .px-xl-0 { + padding-right: 0 !important; + padding-left: 0 !important; + } + .px-xl-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; + } + .px-xl-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; + } + .px-xl-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; + } + .px-xl-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; + } + .px-xl-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; + } + .py-xl-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; + } + .py-xl-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; + } + .py-xl-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; + } + .py-xl-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; + } + .py-xl-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; + } + .py-xl-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; + } + .pt-xl-0 { + padding-top: 0 !important; + } + .pt-xl-1 { + padding-top: 0.25rem !important; + } + .pt-xl-2 { + padding-top: 0.5rem !important; + } + .pt-xl-3 { + padding-top: 1rem !important; + } + .pt-xl-4 { + padding-top: 1.5rem !important; + } + .pt-xl-5 { + padding-top: 3rem !important; + } + .pe-xl-0 { + padding-right: 0 !important; + } + .pe-xl-1 { + padding-right: 0.25rem !important; + } + .pe-xl-2 { + padding-right: 0.5rem !important; + } + .pe-xl-3 { + padding-right: 1rem !important; + } + .pe-xl-4 { + padding-right: 1.5rem !important; + } + .pe-xl-5 { + padding-right: 3rem !important; + } + .pb-xl-0 { + padding-bottom: 0 !important; + } + .pb-xl-1 { + padding-bottom: 0.25rem !important; + } + .pb-xl-2 { + padding-bottom: 0.5rem !important; + } + .pb-xl-3 { + padding-bottom: 1rem !important; + } + .pb-xl-4 { + padding-bottom: 1.5rem !important; + } + .pb-xl-5 { + padding-bottom: 3rem !important; + } + .ps-xl-0 { + padding-left: 0 !important; + } + .ps-xl-1 { + padding-left: 0.25rem !important; + } + .ps-xl-2 { + padding-left: 0.5rem !important; + } + .ps-xl-3 { + padding-left: 1rem !important; + } + .ps-xl-4 { + padding-left: 1.5rem !important; + } + .ps-xl-5 { + padding-left: 3rem !important; + } + .gap-xl-0 { + gap: 0 !important; + } + .gap-xl-1 { + gap: 0.25rem !important; + } + .gap-xl-2 { + gap: 0.5rem !important; + } + .gap-xl-3 { + gap: 1rem !important; + } + .gap-xl-4 { + gap: 1.5rem !important; + } + .gap-xl-5 { + gap: 3rem !important; + } + .row-gap-xl-0 { + row-gap: 0 !important; + } + .row-gap-xl-1 { + row-gap: 0.25rem !important; + } + .row-gap-xl-2 { + row-gap: 0.5rem !important; + } + .row-gap-xl-3 { + row-gap: 1rem !important; + } + .row-gap-xl-4 { + row-gap: 1.5rem !important; + } + .row-gap-xl-5 { + row-gap: 3rem !important; + } + .column-gap-xl-0 { + column-gap: 0 !important; + } + .column-gap-xl-1 { + column-gap: 0.25rem !important; + } + .column-gap-xl-2 { + column-gap: 0.5rem !important; + } + .column-gap-xl-3 { + column-gap: 1rem !important; + } + .column-gap-xl-4 { + column-gap: 1.5rem !important; + } + .column-gap-xl-5 { + column-gap: 3rem !important; + } + .text-xl-start { + text-align: left !important; + } + .text-xl-end { + text-align: right !important; + } + .text-xl-center { + text-align: center !important; + } +} + +@media (min-width: 1400px) { + .float-xxl-start { + float: left !important; + } + .float-xxl-end { + float: right !important; + } + .float-xxl-none { + float: none !important; + } + .object-fit-xxl-contain { + object-fit: contain !important; + } + .object-fit-xxl-cover { + object-fit: cover !important; + } + .object-fit-xxl-fill { + object-fit: fill !important; + } + .object-fit-xxl-scale { + object-fit: scale-down !important; + } + .object-fit-xxl-none { + object-fit: none !important; + } + .d-xxl-inline { + display: inline !important; + } + .d-xxl-inline-block { + display: inline-block !important; + } + .d-xxl-block { + display: block !important; + } + .d-xxl-grid { + display: grid !important; + } + .d-xxl-inline-grid { + display: inline-grid !important; + } + .d-xxl-table { + display: table !important; + } + .d-xxl-table-row { + display: table-row !important; + } + .d-xxl-table-cell { + display: table-cell !important; + } + .d-xxl-flex { + display: flex !important; + } + .d-xxl-inline-flex { + display: inline-flex !important; + } + .d-xxl-none { + display: none !important; + } + .flex-xxl-fill { + flex: 1 1 auto !important; + } + .flex-xxl-row { + flex-direction: row !important; + } + .flex-xxl-column { + flex-direction: column !important; + } + .flex-xxl-row-reverse { + flex-direction: row-reverse !important; + } + .flex-xxl-column-reverse { + flex-direction: column-reverse !important; + } + .flex-xxl-grow-0 { + flex-grow: 0 !important; + } + .flex-xxl-grow-1 { + flex-grow: 1 !important; + } + .flex-xxl-shrink-0 { + flex-shrink: 0 !important; + } + .flex-xxl-shrink-1 { + flex-shrink: 1 !important; + } + .flex-xxl-wrap { + flex-wrap: wrap !important; + } + .flex-xxl-nowrap { + flex-wrap: nowrap !important; + } + .flex-xxl-wrap-reverse { + flex-wrap: wrap-reverse !important; + } + .justify-content-xxl-start { + justify-content: flex-start !important; + } + .justify-content-xxl-end { + justify-content: flex-end !important; + } + .justify-content-xxl-center { + justify-content: center !important; + } + .justify-content-xxl-between { + justify-content: space-between !important; + } + .justify-content-xxl-around { + justify-content: space-around !important; + } + .justify-content-xxl-evenly { + justify-content: space-evenly !important; + } + .align-items-xxl-start { + align-items: flex-start !important; + } + .align-items-xxl-end { + align-items: flex-end !important; + } + .align-items-xxl-center { + align-items: center !important; + } + .align-items-xxl-baseline { + align-items: baseline !important; + } + .align-items-xxl-stretch { + align-items: stretch !important; + } + .align-content-xxl-start { + align-content: flex-start !important; + } + .align-content-xxl-end { + align-content: flex-end !important; + } + .align-content-xxl-center { + align-content: center !important; + } + .align-content-xxl-between { + align-content: space-between !important; + } + .align-content-xxl-around { + align-content: space-around !important; + } + .align-content-xxl-stretch { + align-content: stretch !important; + } + .align-self-xxl-auto { + align-self: auto !important; + } + .align-self-xxl-start { + align-self: flex-start !important; + } + .align-self-xxl-end { + align-self: flex-end !important; + } + .align-self-xxl-center { + align-self: center !important; + } + .align-self-xxl-baseline { + align-self: baseline !important; + } + .align-self-xxl-stretch { + align-self: stretch !important; + } + .order-xxl-first { + order: -1 !important; + } + .order-xxl-0 { + order: 0 !important; + } + .order-xxl-1 { + order: 1 !important; + } + .order-xxl-2 { + order: 2 !important; + } + .order-xxl-3 { + order: 3 !important; + } + .order-xxl-4 { + order: 4 !important; + } + .order-xxl-5 { + order: 5 !important; + } + .order-xxl-last { + order: 6 !important; + } + .m-xxl-0 { + margin: 0 !important; + } + .m-xxl-1 { + margin: 0.25rem !important; + } + .m-xxl-2 { + margin: 0.5rem !important; + } + .m-xxl-3 { + margin: 1rem !important; + } + .m-xxl-4 { + margin: 1.5rem !important; + } + .m-xxl-5 { + margin: 3rem !important; + } + .m-xxl-auto { + margin: auto !important; + } + .mx-xxl-0 { + margin-right: 0 !important; + margin-left: 0 !important; + } + .mx-xxl-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; + } + .mx-xxl-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; + } + .mx-xxl-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; + } + .mx-xxl-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; + } + .mx-xxl-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; + } + .mx-xxl-auto { + margin-right: auto !important; + margin-left: auto !important; + } + .my-xxl-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; + } + .my-xxl-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; + } + .my-xxl-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; + } + .my-xxl-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; + } + .my-xxl-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; + } + .my-xxl-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; + } + .my-xxl-auto { + margin-top: auto !important; + margin-bottom: auto !important; + } + .mt-xxl-0 { + margin-top: 0 !important; + } + .mt-xxl-1 { + margin-top: 0.25rem !important; + } + .mt-xxl-2 { + margin-top: 0.5rem !important; + } + .mt-xxl-3 { + margin-top: 1rem !important; + } + .mt-xxl-4 { + margin-top: 1.5rem !important; + } + .mt-xxl-5 { + margin-top: 3rem !important; + } + .mt-xxl-auto { + margin-top: auto !important; + } + .me-xxl-0 { + margin-right: 0 !important; + } + .me-xxl-1 { + margin-right: 0.25rem !important; + } + .me-xxl-2 { + margin-right: 0.5rem !important; + } + .me-xxl-3 { + margin-right: 1rem !important; + } + .me-xxl-4 { + margin-right: 1.5rem !important; + } + .me-xxl-5 { + margin-right: 3rem !important; + } + .me-xxl-auto { + margin-right: auto !important; + } + .mb-xxl-0 { + margin-bottom: 0 !important; + } + .mb-xxl-1 { + margin-bottom: 0.25rem !important; + } + .mb-xxl-2 { + margin-bottom: 0.5rem !important; + } + .mb-xxl-3 { + margin-bottom: 1rem !important; + } + .mb-xxl-4 { + margin-bottom: 1.5rem !important; + } + .mb-xxl-5 { + margin-bottom: 3rem !important; + } + .mb-xxl-auto { + margin-bottom: auto !important; + } + .ms-xxl-0 { + margin-left: 0 !important; + } + .ms-xxl-1 { + margin-left: 0.25rem !important; + } + .ms-xxl-2 { + margin-left: 0.5rem !important; + } + .ms-xxl-3 { + margin-left: 1rem !important; + } + .ms-xxl-4 { + margin-left: 1.5rem !important; + } + .ms-xxl-5 { + margin-left: 3rem !important; + } + .ms-xxl-auto { + margin-left: auto !important; + } + .p-xxl-0 { + padding: 0 !important; + } + .p-xxl-1 { + padding: 0.25rem !important; + } + .p-xxl-2 { + padding: 0.5rem !important; + } + .p-xxl-3 { + padding: 1rem !important; + } + .p-xxl-4 { + padding: 1.5rem !important; + } + .p-xxl-5 { + padding: 3rem !important; + } + .px-xxl-0 { + padding-right: 0 !important; + padding-left: 0 !important; + } + .px-xxl-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; + } + .px-xxl-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; + } + .px-xxl-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; + } + .px-xxl-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; + } + .px-xxl-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; + } + .py-xxl-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; + } + .py-xxl-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; + } + .py-xxl-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; + } + .py-xxl-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; + } + .py-xxl-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; + } + .py-xxl-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; + } + .pt-xxl-0 { + padding-top: 0 !important; + } + .pt-xxl-1 { + padding-top: 0.25rem !important; + } + .pt-xxl-2 { + padding-top: 0.5rem !important; + } + .pt-xxl-3 { + padding-top: 1rem !important; + } + .pt-xxl-4 { + padding-top: 1.5rem !important; + } + .pt-xxl-5 { + padding-top: 3rem !important; + } + .pe-xxl-0 { + padding-right: 0 !important; + } + .pe-xxl-1 { + padding-right: 0.25rem !important; + } + .pe-xxl-2 { + padding-right: 0.5rem !important; + } + .pe-xxl-3 { + padding-right: 1rem !important; + } + .pe-xxl-4 { + padding-right: 1.5rem !important; + } + .pe-xxl-5 { + padding-right: 3rem !important; + } + .pb-xxl-0 { + padding-bottom: 0 !important; + } + .pb-xxl-1 { + padding-bottom: 0.25rem !important; + } + .pb-xxl-2 { + padding-bottom: 0.5rem !important; + } + .pb-xxl-3 { + padding-bottom: 1rem !important; + } + .pb-xxl-4 { + padding-bottom: 1.5rem !important; + } + .pb-xxl-5 { + padding-bottom: 3rem !important; + } + .ps-xxl-0 { + padding-left: 0 !important; + } + .ps-xxl-1 { + padding-left: 0.25rem !important; + } + .ps-xxl-2 { + padding-left: 0.5rem !important; + } + .ps-xxl-3 { + padding-left: 1rem !important; + } + .ps-xxl-4 { + padding-left: 1.5rem !important; + } + .ps-xxl-5 { + padding-left: 3rem !important; + } + .gap-xxl-0 { + gap: 0 !important; + } + .gap-xxl-1 { + gap: 0.25rem !important; + } + .gap-xxl-2 { + gap: 0.5rem !important; + } + .gap-xxl-3 { + gap: 1rem !important; + } + .gap-xxl-4 { + gap: 1.5rem !important; + } + .gap-xxl-5 { + gap: 3rem !important; + } + .row-gap-xxl-0 { + row-gap: 0 !important; + } + .row-gap-xxl-1 { + row-gap: 0.25rem !important; + } + .row-gap-xxl-2 { + row-gap: 0.5rem !important; + } + .row-gap-xxl-3 { + row-gap: 1rem !important; + } + .row-gap-xxl-4 { + row-gap: 1.5rem !important; + } + .row-gap-xxl-5 { + row-gap: 3rem !important; + } + .column-gap-xxl-0 { + column-gap: 0 !important; + } + .column-gap-xxl-1 { + column-gap: 0.25rem !important; + } + .column-gap-xxl-2 { + column-gap: 0.5rem !important; + } + .column-gap-xxl-3 { + column-gap: 1rem !important; + } + .column-gap-xxl-4 { + column-gap: 1.5rem !important; + } + .column-gap-xxl-5 { + column-gap: 3rem !important; + } + .text-xxl-start { + text-align: left !important; + } + .text-xxl-end { + text-align: right !important; + } + .text-xxl-center { + text-align: center !important; + } +} + +@media (min-width: 1200px) { + .fs-1 { + font-size: 2.5rem !important; + } + .fs-2 { + font-size: 2rem !important; + } + .fs-3 { + font-size: 1.75rem !important; + } + .fs-4 { + font-size: 1.5rem !important; + } +} + +@media print { + .d-print-inline { + display: inline !important; + } + .d-print-inline-block { + display: inline-block !important; + } + .d-print-block { + display: block !important; + } + .d-print-grid { + display: grid !important; + } + .d-print-inline-grid { + display: inline-grid !important; + } + .d-print-table { + display: table !important; + } + .d-print-table-row { + display: table-row !important; + } + .d-print-table-cell { + display: table-cell !important; + } + .d-print-flex { + display: flex !important; + } + .d-print-inline-flex { + display: inline-flex !important; + } + .d-print-none { + display: none !important; + } +} + +/* + TALAWA SCSS + ----------- + This file is used to import all partial scss files in the project. + It is used to compile the final CSS file to the CSS folder as main.css . + +========= Table of Contents ========= +1. Components +2. Content +3. Forms +4. Utilities +5. General +6. Colors + +*/ +/* + + 1. COMPONENTS + +*/ +.btn-primary, +.btn-secondary, +.btn-success, +.btn-warning, +.btn-info { + color: #fff; +} +.btn-primary:hover, +.btn-primary:active, +.btn-secondary:hover, +.btn-secondary:active, +.btn-success:hover, +.btn-success:active, +.btn-warning:hover, +.btn-warning:active, +.btn-info:hover, +.btn-info:active { + color: #fff !important; +} + +.btn-outline-primary:hover, +.btn-outline-primary:active, +.btn-outline-secondary:hover, +.btn-outline-secondary:active, +.btn-outline-success:hover, +.btn-outline-success:active, +.btn-outline-warning:hover, +.btn-outline-warning:active, +.btn-outline-info:hover, +.btn-outline-info:active { + color: #fff !important; +} + +@keyframes progress-bar-stripes { + 0% { + background-position-x: 1rem; + } +} + +@keyframes spinner-border { + to { + transform: rotate(360deg) /* rtl:ignore */; + } +} + +@keyframes spinner-grow { + 0% { + transform: scale(0); + } + 50% { + opacity: 1; + transform: none; + } +} + +/* + + 2. CONTENT + +*/ +/* + DISPLAY SASS VARIABLES +*/ +/* + DISPLAY SASS VARIABLES +*/ +/* + + 3. FORMS + +*/ +/* + + 4. UTILITIES + +*/ +/* + + 5. General + +*/ +:root { + --bs-body-font-family: Arial, Helvetica, sans-serif; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +html { + overflow-x: hidden; +} + +body { + background-color: var(--bs-body-bg); +} + +#root { + min-height: 100vh; + background-color: #f2f7ff; +} + +input[type='checkbox'] { + transform: scale(1.5); +} + +.form-switch { + padding-left: 3rem; +} + +input[type='file']::file-selector-button { + background: var(--bs-gray-400); +} + +.shimmer { + animation-duration: 2.2s; + animation-fill-mode: forwards; + animation-iteration-count: infinite; + animation-name: shimmer; + animation-timing-function: linear; + background: var(--bs-gray-200); + background: linear-gradient(to right, #f6f6f6 8%, #f0f0f0 18%, #f6f6f6 33%); + background-size: 1200px 100%; +} + +@-webkit-keyframes shimmer { + 0% { + background-position: -100% 0; + } + 100% { + background-position: 100% 0; + } +} + +@keyframes shimmer { + 0% { + background-position: -1200px 0; + } + 100% { + background-position: 1200px 0; + } +} + +/* + + 6. COLORS + +*/ diff --git a/src/assets/images/blank.png b/src/assets/images/blank.png new file mode 100644 index 0000000000000000000000000000000000000000..ae6f25f049eb4e8d8dfe479bd9dcd0dfc9d4f820 GIT binary patch literal 5911 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 literal 0 HcmV?d00001 diff --git a/src/assets/images/defaultImg.png b/src/assets/images/defaultImg.png new file mode 100644 index 0000000000000000000000000000000000000000..310a79c130f2b7e4cd791b12ca19388a89239f3b GIT binary patch literal 585990 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Ǿ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ÎJpp)j&CR6?Q`0F$2@lZa$i`pz!$wzd6B3J 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 &BBs21&)d$|5 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 literal 0 HcmV?d00001 diff --git a/src/assets/images/palisadoes_logo.png b/src/assets/images/palisadoes_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2e91c02233047309e5dd7bdf90a8958801472916 GIT binary patch literal 169634 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%0DFO#wdQReW5(~53l$t!Z? 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

    @B;cpz)B6D9z#)g3sXMY zaa+t!3HYuvB@O+u@4g)lef*d1D~Omxk-gd>S4(r}5P<}ooJ4LUYeJQ#SID{CgHb9M zQMGWsWig-ExK0BozpQMR?D#V6fopnKu({2D)k3q+nm9V$z=x2f*R5avJok&PEsKU9 zCS!P@a+WawLUe-O9YGi4q+i^w-IwI_Cj+6u2-)ppNQt!;@+%h$$4;G(pPl(%Ne-SB zHc5F@^Rz$4b$Ne?G(vrIm)>t|bl+e`UcGd_TiEl@X(%BTIc4+XTWfqel2Qf4PLNdP z?fA%$K6JpCOcC9)2&Y{$E$Z7}i2D!{fn#BHn83R|<{Kp*qq-hO=XhMWv=w2J;-`t-ch8LDqjaq{`Ocdr^Gy?SRSxBa7I$sq7y=vtH_6T1Lkk({*Jf{>?=IE}pM< z^S*grl|p-l>B>kCoR;)@G{U1G$>TmNB*0+juj_K~4CJws(N16mhxJ9K_Fcz5u?wlY zq~;IvE^PnPH@_$8sD$YF-jU*Hr&9fGP}A3c9sa~_>KPKEybOIDH@AFKK)-L`8{_4x z31`Lzw=xnrMW0aLN@6#~izMrjoBF2C5R}+CxN#?EQKP{Gy*FGc z2Tmp39dlyC^8M3crSNiKUvQB}U<-PiFH&DphZ<#_=OObM8QB(}FCHHk^f}VWv*{TV z<=|j9w1Zu&_-F6khKx(09y0_vP1=aU8Q&MIx&V6%`bjnT29ih><0zzep4k_cer{Ph zgi1%4;{8D4=aMDlMZbal$`CP@VYs{Zl-^JsLXXbP^onLMqNdxVEqzmcMgB93^papg zpukf90XGX_h|=1uUIMhdV61bj*g-clnXm@c?sCd%SEZT>DdR+8t(l6b$%Jq1i9X`i z{`zsus>9Uvt)^nt=>5eVJ?3xmZwH$Uk}3PL5=~r^5Ppf3UJ>J2mKA4)QXREk(<`28 zSmf*;7P)lTK!KdvXl2Fu;(k6m$paxyHh$9(+Oc&7y^I#+8_Mp z_XIvt%3LRcGLW=qylo}fOJ`N`_2|~a#8FJ{o&DhxyJSn{T8Sf@ufHY@ znhT{mTZhG+Ti@s#&s0#>Y^$sW>`hBsxBnED0t8?^r1G<&B+u5yGF za2~}L@W|?<_Q{&jYm455;M2{7sqr}y&AEZn2n*{`v#-%kHL72*&F~vjYt57G%*^}* zvs64DG_0Y{H(ibK_)@|C!LRX8>875tmcI?H?=y3TTDdhuYZ}anJ0TB;g6YU*O@oqt zxGv;C#!mxwbp!PGsSG|GatB-=t`Rl~v~(-jmq^7c!9(^YZ)WGalZcR7g#1Ug*Q^zFF5yT5M4Bm(X$m&`}&e(XcHZU;uYbC{@?uZGIz0*rKp(6}w!UT*Joc|RvLU5)Kk zl%gW3EFf%6&jNik>u=BvljnbSn1yLa6FRaO+xci?FP1tFQ$HDvNb%+ATOoO4IWduE zq=Kutn5&Fg3ERW@0iOzT+$90|CziNPaJ}98&0Ayn6#M~CT;Ho8edNgp|D95WYdz+^ z#yanGW6EQ*;{nqD^LS&@ZG_fr>PK^_60^ke-08w%EVE{1o}=-7|Fd+n1Thc$xEiW>$pi0&bROYXa$DP1OWQ9*2Xz6+^;6phS}h52^1(^9Gy z51Sh`)6Kl15p9s`eq*r?;U87(-82?54?IJy`&OKWOvGMz?sj}_Ae{-~M6w+Teh}=w zWFlKQtc1Y5@z!44Wf-iuZ&ow$`&}M`H+dNU-(7FW$ZY-5wxo3LRAs)J3F8jiz2Zx6 z^SLj_)WU6veYLkF0JIpsnb}{jy_}7~Y#L__O9zvJw+-GlUS8PA)!;eikyQTO-|bZs zJ@EoY@BMRU{qqf~B%5BR<1TE{|MyEq@M7#80Yw#$_Sc*-W9+RdKn1FyfRcL?_#fiP BdOrXF literal 0 HcmV?d00001 diff --git a/src/assets/talawa-logo-dark-200x200.png b/src/assets/images/talawa-logo-dark-200x200.png similarity index 100% rename from src/assets/talawa-logo-dark-200x200.png rename to src/assets/images/talawa-logo-dark-200x200.png diff --git a/src/assets/images/talawa-logo-lite-200x200.png b/src/assets/images/talawa-logo-lite-200x200.png new file mode 100644 index 0000000000000000000000000000000000000000..a8d0a8fa7b1e85c7fcdb3ca1c5b75663fdb39fb2 GIT binary patch literal 5061 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 literal 0 HcmV?d00001 diff --git a/src/App.css b/src/assets/scss/_colors.scss similarity index 100% rename from src/App.css rename to src/assets/scss/_colors.scss diff --git a/src/assets/scss/_general.scss b/src/assets/scss/_general.scss new file mode 100644 index 0000000000..f2309504ce --- /dev/null +++ b/src/assets/scss/_general.scss @@ -0,0 +1,63 @@ +:root { + --bs-body-font-family: Arial, Helvetica, sans-serif; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +html { + overflow-x: hidden; +} + +body { + background-color: var(--bs-body-bg); +} + +#root { + min-height: 100vh; + background-color: #f2f7ff; +} + +input[type='checkbox'] { + transform: scale(1.5); +} +.form-switch { + padding-left: 3rem; +} +input[type='file']::file-selector-button { + background: var(--bs-gray-400); +} + +.shimmer { + animation-duration: 2.2s; + animation-fill-mode: forwards; + animation-iteration-count: infinite; + animation-name: shimmer; + animation-timing-function: linear; + background: var(--bs-gray-200); + background: linear-gradient(to right, #f6f6f6 8%, #f0f0f0 18%, #f6f6f6 33%); + background-size: 1200px 100%; +} + +@-webkit-keyframes shimmer { + 0% { + background-position: -100% 0; + } + + 100% { + background-position: 100% 0; + } +} + +@keyframes shimmer { + 0% { + background-position: -1200px 0; + } + + 100% { + background-position: 1200px 0; + } +} diff --git a/src/assets/scss/_talawa.scss b/src/assets/scss/_talawa.scss new file mode 100644 index 0000000000..2537c2c682 --- /dev/null +++ b/src/assets/scss/_talawa.scss @@ -0,0 +1,136 @@ +/* + TALAWA SCSS + ----------- + This file is used to import all partial scss files in the project. + It is used to compile the final CSS file to the CSS folder as main.css . + +========= Table of Contents ========= +1. Components +2. Content +3. Forms +4. Utilities +5. General +6. Colors + +*/ + +/* + + 1. COMPONENTS + +*/ + +// 1.1. Accordion +@import './components/accordion'; + +// 1.2. Alert +@import './components/alert'; + +// 1.3. Badge +@import './components/badge'; + +// 1.4. Breadcrumb +@import './components/breadcrumb'; + +// 1.5. Button +@import './components/buttons'; + +// 1.6. Card +@import './components/card'; + +// 1.7. Carousel +@import './components/carousel'; + +// 1.8. Close +@import './components/close'; + +// 1.9. Dropdown +@import './components/dropdown'; + +// 1.10. List Group +@import './components/list-group'; + +// 1.11. Modal +@import './components/modal'; + +// 1.12. Navbar +@import './components/navbar'; + +// 1.13. Nav and Nav Tabs +@import './components/nav'; + +// 1.14 Offcanvas +@import './components/offcanvas'; + +// 1.15 Pagination +@import './components/pagination'; + +// 1.16 Placeholder +@import './components/placeholder'; + +// 1.17 Progress +@import './components/progress'; + +// 1.18 Spinners +@import './components/spinners'; + +/* + + 2. CONTENT + +*/ + +// 2.1. Table +@import './content/table'; + +// 2.2. Typography +@import './content/typography'; + +/* + + 3. FORMS + +*/ + +// 3.1. Checkbox & Radio +@import './forms/check-radios'; + +// 3.2. Floating Labels +@import './forms/floating-label'; + +// 3.3. Form Controls +@import './forms/form-control'; + +// 3.4. Input Group +@import './forms/input-group'; + +// 3.5. Range +@import './forms/range'; + +// 3.6. Select +@import './forms/select'; + +// 3.7. Validation +@import './forms/validation'; + +/* + + 4. UTILITIES + +*/ + +@import './utilities'; + +/* + + 5. General + +*/ +@import './general'; + +/* + + 6. COLORS + +*/ +@import './colors'; diff --git a/src/assets/scss/_utilities.scss b/src/assets/scss/_utilities.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/assets/scss/_variables.scss b/src/assets/scss/_variables.scss new file mode 100644 index 0000000000..2871cb9df2 --- /dev/null +++ b/src/assets/scss/_variables.scss @@ -0,0 +1,30 @@ +// Colors + +$primary: #31bb6b; +$secondary: #707070; +$success: #31bb6b; +$warning: #febc59; + +$blue: #0d6efd; +$indigo: #6610f2; +$purple: #6f42c1; +$pink: #d63384; +$red: #dc3545; +$orange: #fd7e14; +$yellow: #ffc107; +$green: #198754; +$teal: #20c997; +$cyan: #0dcaf0; +$placeholder-bg: #f2f2f2; +// Colors + +// Links +$link-color: $blue !default; +$link-decoration: none !default; + +// Inputs and buttons +$input-bg: $placeholder-bg; +$input-border-width: 0; + +$input-btn-padding-y: 0.7rem; +$input-btn-padding-x: 1rem; diff --git a/src/assets/scss/app.scss b/src/assets/scss/app.scss new file mode 100644 index 0000000000..8685a742db --- /dev/null +++ b/src/assets/scss/app.scss @@ -0,0 +1,14 @@ +// Importing Bootstrap SCSS Functions and Mixins +@import '../../../node_modules/bootstrap/scss/functions'; +@import '../../../node_modules/bootstrap/scss/mixins'; + +// Importing Our Bootstrap SCSS Variables +@import './variables'; + +// Importing Bootstrap Variables and SCSS +@import '../../../node_modules/bootstrap/scss/variables'; +@import '../../../node_modules/bootstrap/scss/variables-dark'; +@import '../../../node_modules/bootstrap/scss/bootstrap.scss'; + +// Importing Our Bootstrap SCSS Overrides +@import './talawa'; diff --git a/src/assets/scss/components/_accordion.scss b/src/assets/scss/components/_accordion.scss new file mode 100644 index 0000000000..96be1dbcfa --- /dev/null +++ b/src/assets/scss/components/_accordion.scss @@ -0,0 +1,34 @@ +$accordion-padding-y: 1.25rem; +$accordion-padding-x: 1.5rem; +$accordion-color: var(--#{$prefix}body-color); +$accordion-bg: var(--#{$prefix}body-bg); +$accordion-border-width: var(--#{$prefix}border-width); +$accordion-border-color: var(--#{$prefix}border-color); +$accordion-border-radius: var(--#{$prefix}border-radius); +$accordion-inner-border-radius: subtract( + $accordion-border-radius, + $accordion-border-width +); + +$accordion-body-padding-y: $accordion-padding-y; +$accordion-body-padding-x: $accordion-padding-x; + +$accordion-button-padding-y: $accordion-padding-y; +$accordion-button-padding-x: $accordion-padding-x; +$accordion-button-color: var(--#{$prefix}body-color); +$accordion-button-bg: var(--#{$prefix}accordion-bg); +$accordion-transition: $btn-transition, border-radius 0.15s ease; +$accordion-button-active-bg: var(--#{$prefix}primary-bg-subtle); +$accordion-button-active-color: var(--#{$prefix}primary-text-emphasis); + +$accordion-button-focus-border-color: $input-focus-border-color; +$accordion-button-focus-box-shadow: $btn-focus-box-shadow; + +$accordion-icon-width: 1.25rem; +$accordion-icon-color: $body-color; +$accordion-icon-active-color: $primary-text-emphasis; +$accordion-icon-transition: transform 0.2s ease-in-out; +$accordion-icon-transform: rotate(-180deg); + +$accordion-button-icon: url("data:image/svg+xml,"); +$accordion-button-active-icon: url("data:image/svg+xml,"); diff --git a/src/assets/scss/components/_alert.scss b/src/assets/scss/components/_alert.scss new file mode 100644 index 0000000000..64f29bf3c0 --- /dev/null +++ b/src/assets/scss/components/_alert.scss @@ -0,0 +1,10 @@ +$alert-padding-y: $spacer; +$alert-padding-x: $spacer; +$alert-margin-bottom: 1rem; +$alert-border-radius: var(--#{$prefix}border-radius); +$alert-link-font-weight: $font-weight-bold; +$alert-border-width: var(--#{$prefix}border-width); +$alert-bg-scale: -80%; +$alert-border-scale: -70%; +$alert-color-scale: 40%; +$alert-dismissible-padding-r: $alert-padding-x * 3; // 3x covers width of x plus default padding on either side diff --git a/src/assets/scss/components/_badge.scss b/src/assets/scss/components/_badge.scss new file mode 100644 index 0000000000..9b0c6a8a3a --- /dev/null +++ b/src/assets/scss/components/_badge.scss @@ -0,0 +1,6 @@ +$badge-font-size: 0.75em; +$badge-font-weight: $font-weight-bold; +$badge-color: $white; +$badge-padding-y: 0.35em; +$badge-padding-x: 0.65em; +$badge-border-radius: var(--#{$prefix}border-radius); diff --git a/src/assets/scss/components/_breadcrumb.scss b/src/assets/scss/components/_breadcrumb.scss new file mode 100644 index 0000000000..73fb6bd692 --- /dev/null +++ b/src/assets/scss/components/_breadcrumb.scss @@ -0,0 +1,11 @@ +$breadcrumb-font-size: null; +$breadcrumb-padding-y: 0; +$breadcrumb-padding-x: 0; +$breadcrumb-item-padding-x: 0.5rem; +$breadcrumb-margin-bottom: 1rem; +$breadcrumb-bg: null; +$breadcrumb-divider-color: var(--#{$prefix}secondary-color); +$breadcrumb-active-color: var(--#{$prefix}secondary-color); +$breadcrumb-divider: quote('/'); +$breadcrumb-divider-flipped: $breadcrumb-divider; +$breadcrumb-border-radius: null; diff --git a/src/assets/scss/components/_buttons.scss b/src/assets/scss/components/_buttons.scss new file mode 100644 index 0000000000..1301eaf5a8 --- /dev/null +++ b/src/assets/scss/components/_buttons.scss @@ -0,0 +1,68 @@ +$btn-color: $white; +$btn-padding-y: $input-btn-padding-y; +$btn-padding-x: $input-btn-padding-x; +$btn-font-family: $input-btn-font-family; +$btn-font-size: $input-btn-font-size; +$btn-line-height: $input-btn-line-height; +$btn-white-space: null; // Set to `nowrap` to prevent text wrapping + +$btn-padding-y-sm: $input-btn-padding-y-sm; +$btn-padding-x-sm: $input-btn-padding-x-sm; +$btn-font-size-sm: $input-btn-font-size-sm; + +$btn-padding-y-lg: $input-btn-padding-y-lg; +$btn-padding-x-lg: $input-btn-padding-x-lg; +$btn-font-size-lg: $input-btn-font-size-lg; + +$btn-border-width: $input-btn-border-width; + +$btn-font-weight: $font-weight-normal; +$btn-box-shadow: inset 0 1px 0 rgba($white, 0.15), 0 1px 1px rgba($black, 0.075); +$btn-focus-width: $input-btn-focus-width; +$btn-focus-box-shadow: $input-btn-focus-box-shadow; +$btn-disabled-opacity: 0.65; +$btn-active-box-shadow: inset 0 3px 5px rgba($black, 0.125); + +$btn-link-color: var(--#{$prefix}link-color); +$btn-link-hover-color: var(--#{$prefix}link-hover-color); +$btn-link-disabled-color: $gray-600; + +// Allows for customizing button radius independently from global border radius +$btn-border-radius: var(--#{$prefix}border-radius); +$btn-border-radius-sm: var(--#{$prefix}border-radius-sm); +$btn-border-radius-lg: var(--#{$prefix}border-radius-lg); + +$btn-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, + border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + +$btn-hover-bg-shade-amount: 15%; +$btn-hover-bg-tint-amount: 15%; +$btn-hover-border-shade-amount: 20%; +$btn-hover-border-tint-amount: 10%; +$btn-active-bg-shade-amount: 20%; +$btn-active-bg-tint-amount: 20%; +$btn-active-border-shade-amount: 25%; +$btn-active-border-tint-amount: 10%; + +.btn-primary, +.btn-secondary, +.btn-success, +.btn-warning, +.btn-info { + color: $white; + &:hover, + &:active { + color: $white !important; + } +} + +.btn-outline-primary, +.btn-outline-secondary, +.btn-outline-success, +.btn-outline-warning, +.btn-outline-info { + &:hover, + &:active { + color: $white !important; + } +} diff --git a/src/assets/scss/components/_card.scss b/src/assets/scss/components/_card.scss new file mode 100644 index 0000000000..5fa5abb4ee --- /dev/null +++ b/src/assets/scss/components/_card.scss @@ -0,0 +1,19 @@ +$card-spacer-y: $spacer; +$card-spacer-x: $spacer; +$card-title-spacer-y: $spacer * 0.5; +$card-title-color: null; +$card-subtitle-color: null; +$card-border-width: var(--#{$prefix}border-width); +$card-border-color: var(--#{$prefix}border-color-translucent); +$card-border-radius: var(--#{$prefix}border-radius); +$card-box-shadow: null; +$card-inner-border-radius: subtract($card-border-radius, $card-border-width); +$card-cap-padding-y: $card-spacer-y * 0.5; +$card-cap-padding-x: $card-spacer-x; +$card-cap-bg: rgba(var(--#{$prefix}body-color-rgb), 0.03); +$card-cap-color: null; +$card-height: null; +$card-color: null; +$card-bg: var(--#{$prefix}body-bg); +$card-img-overlay-padding: $spacer; +$card-group-margin: $grid-gutter-width * 0.5; diff --git a/src/assets/scss/components/_carousel.scss b/src/assets/scss/components/_carousel.scss new file mode 100644 index 0000000000..5f7d77e4c6 --- /dev/null +++ b/src/assets/scss/components/_carousel.scss @@ -0,0 +1,27 @@ +$carousel-control-color: $white; +$carousel-control-width: 15%; +$carousel-control-opacity: 0.5; +$carousel-control-hover-opacity: 0.9; +$carousel-control-transition: opacity 0.15s ease; + +$carousel-indicator-width: 30px; +$carousel-indicator-height: 3px; +$carousel-indicator-hit-area-height: 10px; +$carousel-indicator-spacer: 3px; +$carousel-indicator-opacity: 0.5; +$carousel-indicator-active-bg: $white; +$carousel-indicator-active-opacity: 1; +$carousel-indicator-transition: opacity 0.6s ease; + +$carousel-caption-width: 70%; +$carousel-caption-color: $white; +$carousel-caption-padding-y: 1.25rem; +$carousel-caption-spacer: 1.25rem; + +$carousel-control-icon-width: 2rem; + +$carousel-control-prev-icon-bg: url("data:image/svg+xml,"); +$carousel-control-next-icon-bg: url("data:image/svg+xml,"); + +$carousel-transition-duration: 0.6s; +$carousel-transition: transform $carousel-transition-duration ease-in-out; // Define transform transition first if using multiple transitions (e.g., `transform 2s ease, opacity .5s ease-out`) diff --git a/src/assets/scss/components/_close.scss b/src/assets/scss/components/_close.scss new file mode 100644 index 0000000000..2ae25d5353 --- /dev/null +++ b/src/assets/scss/components/_close.scss @@ -0,0 +1,12 @@ +$btn-close-width: 1em; +$btn-close-height: $btn-close-width; +$btn-close-padding-x: 0.25em; +$btn-close-padding-y: $btn-close-padding-x; +$btn-close-color: $black; +$btn-close-bg: url("data:image/svg+xml,"); +$btn-close-focus-shadow: $focus-ring-box-shadow; +$btn-close-opacity: 0.5; +$btn-close-hover-opacity: 0.75; +$btn-close-focus-opacity: 1; +$btn-close-disabled-opacity: 0.25; +$btn-close-white-filter: invert(1) grayscale(100%) brightness(200%); diff --git a/src/assets/scss/components/_dropdown.scss b/src/assets/scss/components/_dropdown.scss new file mode 100644 index 0000000000..1e1f1fa040 --- /dev/null +++ b/src/assets/scss/components/_dropdown.scss @@ -0,0 +1,35 @@ +$dropdown-min-width: 10rem; +$dropdown-padding-x: 0; +$dropdown-padding-y: 0.5rem; +$dropdown-spacer: 0.125rem; +$dropdown-font-size: $font-size-base; +$dropdown-color: var(--#{$prefix}body-color); +$dropdown-bg: var(--#{$prefix}body-bg); +$dropdown-border-color: var(--#{$prefix}border-color-translucent); +$dropdown-border-radius: var(--#{$prefix}border-radius); +$dropdown-border-width: var(--#{$prefix}border-width); +$dropdown-inner-border-radius: calc( + #{$dropdown-border-radius} - #{$dropdown-border-width} +); // stylelint-disable-line function-disallowed-list +$dropdown-divider-bg: $dropdown-border-color; +$dropdown-divider-margin-y: $spacer * 0.5; +$dropdown-box-shadow: $box-shadow; + +$dropdown-link-color: var(--#{$prefix}body-color); +$dropdown-link-hover-color: $dropdown-link-color; +$dropdown-link-hover-bg: var(--#{$prefix}tertiary-bg); + +$dropdown-link-active-color: $component-active-color; +$dropdown-link-active-bg: $component-active-bg; + +$dropdown-link-disabled-color: var(--#{$prefix}tertiary-color); + +$dropdown-item-padding-y: $spacer * 0.25; +$dropdown-item-padding-x: $spacer; + +$dropdown-header-color: $gray-600; +$dropdown-header-padding-x: $dropdown-item-padding-x; +$dropdown-header-padding-y: $dropdown-padding-y; +// fusv-disable +$dropdown-header-padding: $dropdown-header-padding-y $dropdown-header-padding-x; // Deprecated in v5.2.0 +// fusv-enable diff --git a/src/assets/scss/components/_list-group.scss b/src/assets/scss/components/_list-group.scss new file mode 100644 index 0000000000..2579f2e823 --- /dev/null +++ b/src/assets/scss/components/_list-group.scss @@ -0,0 +1,26 @@ +$list-group-color: var(--#{$prefix}body-color); +$list-group-bg: var(--#{$prefix}body-bg); +$list-group-border-color: var(--#{$prefix}border-color); +$list-group-border-width: var(--#{$prefix}border-width); +$list-group-border-radius: var(--#{$prefix}border-radius); + +$list-group-item-padding-y: $spacer * 0.5; +$list-group-item-padding-x: $spacer; +// fusv-disable +$list-group-item-bg-scale: -80%; // Deprecated in v5.3.0 +$list-group-item-color-scale: 40%; // Deprecated in v5.3.0 +// fusv-enable + +$list-group-hover-bg: var(--#{$prefix}tertiary-bg); +$list-group-active-color: $component-active-color; +$list-group-active-bg: $component-active-bg; +$list-group-active-border-color: $list-group-active-bg; + +$list-group-disabled-color: var(--#{$prefix}secondary-color); +$list-group-disabled-bg: $list-group-bg; + +$list-group-action-color: var(--#{$prefix}secondary-color); +$list-group-action-hover-color: var(--#{$prefix}emphasis-color); + +$list-group-action-active-color: var(--#{$prefix}body-color); +$list-group-action-active-bg: var(--#{$prefix}secondary-bg); diff --git a/src/assets/scss/components/_modal.scss b/src/assets/scss/components/_modal.scss new file mode 100644 index 0000000000..b491a19f1c --- /dev/null +++ b/src/assets/scss/components/_modal.scss @@ -0,0 +1,43 @@ +$modal-inner-padding: $spacer; + +$modal-footer-margin-between: 0.5rem; + +$modal-dialog-margin: 0.5rem; +$modal-dialog-margin-y-sm-up: 1.75rem; + +$modal-title-line-height: $line-height-base; + +$modal-content-color: null; +$modal-content-bg: var(--#{$prefix}body-bg); +$modal-content-border-color: var(--#{$prefix}border-color-translucent); +$modal-content-border-width: var(--#{$prefix}border-width); +$modal-content-border-radius: var(--#{$prefix}border-radius-lg); +$modal-content-inner-border-radius: subtract( + $modal-content-border-radius, + $modal-content-border-width +); +$modal-content-box-shadow-xs: $box-shadow-sm; +$modal-content-box-shadow-sm-up: $box-shadow; + +$modal-backdrop-bg: $black; +$modal-backdrop-opacity: 0.5; + +$modal-header-border-color: var(--#{$prefix}border-color); +$modal-header-border-width: 0; // We dont want border here +$modal-header-padding-y: $modal-inner-padding * 0.8; +$modal-header-padding-x: $modal-inner-padding; +$modal-header-padding: $modal-header-padding-y $modal-header-padding-x; // Keep this for backwards compatibility + +$modal-footer-bg: null; +$modal-footer-border-color: $modal-header-border-color; +$modal-footer-border-width: 0; // We don't want border here + +$modal-sm: 300px; +$modal-md: 500px; +$modal-lg: 800px; +$modal-xl: 1140px; + +$modal-fade-transform: translate(0, -50px); +$modal-show-transform: none; +$modal-transition: transform 0.3s ease-out; +$modal-scale-transform: scale(1.02); diff --git a/src/assets/scss/components/_nav.scss b/src/assets/scss/components/_nav.scss new file mode 100644 index 0000000000..1474454488 --- /dev/null +++ b/src/assets/scss/components/_nav.scss @@ -0,0 +1,28 @@ +$nav-link-padding-y: 0.5rem; +$nav-link-padding-x: 1rem; +$nav-link-font-size: null; +$nav-link-font-weight: null; +$nav-link-color: var(--#{$prefix}link-color); +$nav-link-hover-color: var(--#{$prefix}link-hover-color); +$nav-link-transition: color 0.15s ease-in-out, + background-color 0.15s ease-in-out, border-color 0.15s ease-in-out; +$nav-link-disabled-color: var(--#{$prefix}secondary-color); +$nav-link-focus-box-shadow: $focus-ring-box-shadow; + +$nav-tabs-border-color: var(--#{$prefix}border-color); +$nav-tabs-border-width: var(--#{$prefix}border-width); +$nav-tabs-border-radius: var(--#{$prefix}border-radius); +$nav-tabs-link-hover-border-color: var(--#{$prefix}secondary-bg) + var(--#{$prefix}secondary-bg) $nav-tabs-border-color; +$nav-tabs-link-active-color: var(--#{$prefix}emphasis-color); +$nav-tabs-link-active-bg: var(--#{$prefix}body-bg); +$nav-tabs-link-active-border-color: var(--#{$prefix}border-color) + var(--#{$prefix}border-color) $nav-tabs-link-active-bg; + +$nav-pills-border-radius: var(--#{$prefix}border-radius); +$nav-pills-link-active-color: $component-active-color; +$nav-pills-link-active-bg: $component-active-bg; + +$nav-underline-gap: 1rem; +$nav-underline-border-width: 0.125rem; +$nav-underline-link-active-color: var(--#{$prefix}emphasis-color); diff --git a/src/assets/scss/components/_navbar.scss b/src/assets/scss/components/_navbar.scss new file mode 100644 index 0000000000..aaf27bc8b2 --- /dev/null +++ b/src/assets/scss/components/_navbar.scss @@ -0,0 +1,31 @@ +$navbar-padding-y: $spacer * 0.5; +$navbar-padding-x: null; + +$navbar-nav-link-padding-x: 0.5rem; + +$navbar-brand-font-size: $font-size-lg; +// Compute the navbar-brand padding-y so the navbar-brand will have the same height as navbar-text and nav-link +$nav-link-height: $font-size-base * $line-height-base + $nav-link-padding-y * 2; +$navbar-brand-height: $navbar-brand-font-size * $line-height-base; +$navbar-brand-padding-y: ($nav-link-height - $navbar-brand-height) * 0.5; +$navbar-brand-margin-end: 1rem; + +$navbar-toggler-padding-y: 0.25rem; +$navbar-toggler-padding-x: 0.75rem; +$navbar-toggler-font-size: $font-size-lg; +$navbar-toggler-border-radius: $btn-border-radius; +$navbar-toggler-focus-width: $btn-focus-width; +$navbar-toggler-transition: box-shadow 0.15s ease-in-out; + +$navbar-light-color: rgba(var(--#{$prefix}emphasis-color-rgb), 0.65); +$navbar-light-hover-color: rgba(var(--#{$prefix}emphasis-color-rgb), 0.8); +$navbar-light-active-color: rgba(var(--#{$prefix}emphasis-color-rgb), 1); +$navbar-light-disabled-color: rgba(var(--#{$prefix}emphasis-color-rgb), 0.3); +$navbar-light-icon-color: rgba($body-color, 0.75); +$navbar-light-toggler-icon-bg: url("data:image/svg+xml,"); +$navbar-light-toggler-border-color: rgba( + var(--#{$prefix}emphasis-color-rgb), + 0.15 +); +$navbar-light-brand-color: $navbar-light-active-color; +$navbar-light-brand-hover-color: $navbar-light-active-color; diff --git a/src/assets/scss/components/_offcanvas.scss b/src/assets/scss/components/_offcanvas.scss new file mode 100644 index 0000000000..3226f970f4 --- /dev/null +++ b/src/assets/scss/components/_offcanvas.scss @@ -0,0 +1,13 @@ +$offcanvas-padding-y: $modal-inner-padding; +$offcanvas-padding-x: $modal-inner-padding; +$offcanvas-horizontal-width: 400px; +$offcanvas-vertical-height: 30vh; +$offcanvas-transition-duration: 0.3s; +$offcanvas-border-color: $modal-content-border-color; +$offcanvas-border-width: $modal-content-border-width; +$offcanvas-title-line-height: $modal-title-line-height; +$offcanvas-bg-color: var(--#{$prefix}body-bg); +$offcanvas-color: var(--#{$prefix}body-color); +$offcanvas-box-shadow: $modal-content-box-shadow-xs; +$offcanvas-backdrop-bg: $modal-backdrop-bg; +$offcanvas-backdrop-opacity: $modal-backdrop-opacity; diff --git a/src/assets/scss/components/_pagination.scss b/src/assets/scss/components/_pagination.scss new file mode 100644 index 0000000000..4bb3888854 --- /dev/null +++ b/src/assets/scss/components/_pagination.scss @@ -0,0 +1,43 @@ +$pagination-padding-y: 0.375rem; +$pagination-padding-x: 0.75rem; +$pagination-padding-y-sm: 0.25rem; +$pagination-padding-x-sm: 0.5rem; +$pagination-padding-y-lg: 0.75rem; +$pagination-padding-x-lg: 1.5rem; + +$pagination-font-size: $font-size-base; + +$pagination-color: var(--#{$prefix}link-color); +$pagination-bg: var(--#{$prefix}body-bg); +$pagination-border-radius: var(--#{$prefix}border-radius); +$pagination-border-width: var(--#{$prefix}border-width); +$pagination-margin-start: calc( + #{$pagination-border-width} * -1 +); // stylelint-disable-line function-disallowed-list +$pagination-border-color: var(--#{$prefix}border-color); + +$pagination-focus-color: var(--#{$prefix}link-hover-color); +$pagination-focus-bg: var(--#{$prefix}secondary-bg); +$pagination-focus-box-shadow: $focus-ring-box-shadow; +$pagination-focus-outline: 0; + +$pagination-hover-color: var(--#{$prefix}link-hover-color); +$pagination-hover-bg: var(--#{$prefix}tertiary-bg); +$pagination-hover-border-color: var( + --#{$prefix}border-color +); // Todo in v6: remove this? + +$pagination-active-color: $component-active-color; +$pagination-active-bg: $component-active-bg; +$pagination-active-border-color: $component-active-bg; + +$pagination-disabled-color: var(--#{$prefix}secondary-color); +$pagination-disabled-bg: var(--#{$prefix}secondary-bg); +$pagination-disabled-border-color: var(--#{$prefix}border-color); + +$pagination-transition: color 0.15s ease-in-out, + background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, + box-shadow 0.15s ease-in-out; + +$pagination-border-radius-sm: var(--#{$prefix}border-radius-sm); +$pagination-border-radius-lg: var(--#{$prefix}border-radius-lg); diff --git a/src/assets/scss/components/_placeholder.scss b/src/assets/scss/components/_placeholder.scss new file mode 100644 index 0000000000..8e7b77d0a4 --- /dev/null +++ b/src/assets/scss/components/_placeholder.scss @@ -0,0 +1,2 @@ +$placeholder-opacity-max: 0.5; +$placeholder-opacity-min: 0.2; diff --git a/src/assets/scss/components/_progress.scss b/src/assets/scss/components/_progress.scss new file mode 100644 index 0000000000..a40fa4676e --- /dev/null +++ b/src/assets/scss/components/_progress.scss @@ -0,0 +1,17 @@ +$progress-height: 1rem; +$progress-font-size: $font-size-base * 0.75; +$progress-bg: var(--#{$prefix}secondary-bg); +$progress-border-radius: var(--#{$prefix}border-radius); +$progress-box-shadow: var(--#{$prefix}box-shadow-inset); +$progress-bar-color: $white; +$progress-bar-bg: $primary; +$progress-bar-animation-timing: 1s linear infinite; +$progress-bar-transition: width 0.6s ease; + +@if $enable-transitions { + @keyframes progress-bar-stripes { + 0% { + background-position-x: $progress-height; + } + } +} diff --git a/src/assets/scss/components/_spinners.scss b/src/assets/scss/components/_spinners.scss new file mode 100644 index 0000000000..08f4c51c90 --- /dev/null +++ b/src/assets/scss/components/_spinners.scss @@ -0,0 +1,24 @@ +$spinner-width: 2rem; +$spinner-height: $spinner-width; +$spinner-vertical-align: -0.125em; +$spinner-border-width: 0.25em; +$spinner-animation-speed: 0.75s; + +$spinner-width-sm: 1rem; +$spinner-height-sm: $spinner-width-sm; +$spinner-border-width-sm: 0.2em; + +@keyframes spinner-border { + to { + transform: rotate(360deg) #{'/* rtl:ignore */'}; + } +} +@keyframes spinner-grow { + 0% { + transform: scale(0); + } + 50% { + opacity: 1; + transform: none; + } +} diff --git a/src/assets/scss/content/_table.scss b/src/assets/scss/content/_table.scss new file mode 100644 index 0000000000..f5c9c608fb --- /dev/null +++ b/src/assets/scss/content/_table.scss @@ -0,0 +1,37 @@ +$table-cell-padding-y: 0.5rem; +$table-cell-padding-x: 0.5rem; +$table-cell-padding-y-sm: 0.25rem; +$table-cell-padding-x-sm: 0.25rem; + +$table-cell-vertical-align: top; + +$table-color: var(--#{$prefix}body-color); +$table-bg: var(--#{$prefix}body-bg); +$table-accent-bg: transparent; + +$table-th-font-weight: null; + +$table-striped-color: $table-color; +$table-striped-bg-factor: 0.05; +$table-striped-bg: rgba($black, $table-striped-bg-factor); + +$table-active-color: $table-color; +$table-active-bg-factor: 0.1; +$table-active-bg: rgba($black, $table-active-bg-factor); + +$table-hover-color: $table-color; +$table-hover-bg-factor: 0.075; +$table-hover-bg: rgba($black, $table-hover-bg-factor); + +$table-border-factor: 0.1; +$table-border-width: var(--#{$prefix}border-width); +$table-border-color: var(--#{$prefix}border-color); + +$table-striped-order: odd; +$table-striped-columns-order: even; + +$table-group-separator-color: currentcolor; + +$table-caption-color: var(--#{$prefix}secondary-color); + +$table-bg-scale: -80%; diff --git a/src/assets/scss/content/_typography.scss b/src/assets/scss/content/_typography.scss new file mode 100644 index 0000000000..6336f8554e --- /dev/null +++ b/src/assets/scss/content/_typography.scss @@ -0,0 +1,69 @@ +/* + DISPLAY SASS VARIABLES +*/ + +$display-font-sizes: ( + 1: 5rem, + 2: 4.5rem, + 3: 4rem, + 4: 3.5rem, + 5: 3rem, + 6: 2.5rem, +); + +$display-font-family: null; +$display-font-style: null; +$display-font-weight: 300; +$display-line-height: $headings-line-height; + +/* + DISPLAY SASS VARIABLES +*/ + +$lead-font-size: $font-size-base * 1.25; +$lead-font-weight: 300; + +$small-font-size: 0.875em; + +$sub-sup-font-size: 0.75em; + +// fusv-disable +$text-muted: var(--#{$prefix}secondary-color); // Deprecated in 5.3.0 +// fusv-enable + +$headings-margin-bottom: $spacer * 0.5; +$headings-font-family: null; +$headings-font-style: null; +$headings-font-weight: 500; +$headings-line-height: 1.2; +$headings-color: inherit; + +$initialism-font-size: $small-font-size; + +$blockquote-margin-y: $spacer; +$blockquote-font-size: $font-size-base * 1.25; +$blockquote-footer-color: $gray-600; +$blockquote-footer-font-size: $small-font-size; + +$hr-margin-y: $spacer; +$hr-color: inherit; + +// fusv-disable +$hr-bg-color: null; // Deprecated in v5.2.0 +$hr-height: null; // Deprecated in v5.2.0 +// fusv-enable + +$hr-border-color: null; // Allows for inherited colors +$hr-border-width: var(--#{$prefix}border-width); +$hr-opacity: 0.25; + +$legend-margin-bottom: 0.5rem; +$legend-font-size: 1.5rem; +$legend-font-weight: null; + +$dt-font-weight: $font-weight-bold; + +$list-inline-padding: 0.5rem; + +$mark-padding: 0.1875em; +$mark-bg: $yellow-100; diff --git a/src/assets/scss/forms/_check-radios.scss b/src/assets/scss/forms/_check-radios.scss new file mode 100644 index 0000000000..1ed4d32fd0 --- /dev/null +++ b/src/assets/scss/forms/_check-radios.scss @@ -0,0 +1,34 @@ +$form-check-input-width: 1em; +$form-check-min-height: $font-size-base * $line-height-base; +$form-check-padding-start: $form-check-input-width + 0.5em; +$form-check-margin-bottom: 0.125rem; +$form-check-label-color: null; +$form-check-label-cursor: null; +$form-check-transition: null; + +$form-check-input-active-filter: brightness(90%); + +$form-check-input-bg: $input-bg; +$form-check-input-border: var(--#{$prefix}border-width) solid + var(--#{$prefix}border-color); +$form-check-input-border-radius: 0.25em; +$form-check-radio-border-radius: 50%; +$form-check-input-focus-border: $input-focus-border-color; +$form-check-input-focus-box-shadow: $focus-ring-box-shadow; + +$form-check-input-checked-color: $component-active-color; +$form-check-input-checked-bg-color: $component-active-bg; +$form-check-input-checked-border-color: $form-check-input-checked-bg-color; +$form-check-input-checked-bg-image: url("data:image/svg+xml,"); +$form-check-radio-checked-bg-image: url("data:image/svg+xml,"); + +$form-check-input-indeterminate-color: $component-active-color; +$form-check-input-indeterminate-bg-color: $component-active-bg; +$form-check-input-indeterminate-border-color: $form-check-input-indeterminate-bg-color; +$form-check-input-indeterminate-bg-image: url("data:image/svg+xml,"); + +$form-check-input-disabled-opacity: 0.5; +$form-check-label-disabled-opacity: $form-check-input-disabled-opacity; +$form-check-btn-check-disabled-opacity: $btn-disabled-opacity; + +$form-check-inline-margin-end: 1rem; diff --git a/src/assets/scss/forms/_floating-label.scss b/src/assets/scss/forms/_floating-label.scss new file mode 100644 index 0000000000..56198eaf48 --- /dev/null +++ b/src/assets/scss/forms/_floating-label.scss @@ -0,0 +1,12 @@ +$form-floating-height: add(3.5rem, $input-height-border); +$form-floating-line-height: 1.25; +$form-floating-padding-x: $input-padding-x; +$form-floating-padding-y: 1rem; +$form-floating-input-padding-t: 1.625rem; +$form-floating-input-padding-b: 0.625rem; +$form-floating-label-height: 1.5em; +$form-floating-label-opacity: 0.65; +$form-floating-label-transform: scale(0.85) translateY(-0.5rem) + translateX(0.15rem); +$form-floating-label-disabled-color: $gray-600; +$form-floating-transition: opacity 0.1s ease-in-out, transform 0.1s ease-in-out; diff --git a/src/assets/scss/forms/_form-control.scss b/src/assets/scss/forms/_form-control.scss new file mode 100644 index 0000000000..f4d570d278 --- /dev/null +++ b/src/assets/scss/forms/_form-control.scss @@ -0,0 +1,106 @@ +$input-btn-padding-y: 0.375rem; +$input-btn-padding-x: 0.75rem; +$input-btn-font-family: null; +$input-btn-font-size: $font-size-base; +$input-btn-line-height: $line-height-base; + +$input-btn-focus-width: $focus-ring-width; +$input-btn-focus-color-opacity: $focus-ring-opacity; +$input-btn-focus-color: $focus-ring-color; +$input-btn-focus-blur: $focus-ring-blur; +$input-btn-focus-box-shadow: $focus-ring-box-shadow; + +$input-btn-padding-y-sm: 0.25rem; +$input-btn-padding-x-sm: 0.5rem; +$input-btn-font-size-sm: $font-size-sm; + +$input-btn-padding-y-lg: 0.5rem; +$input-btn-padding-x-lg: 1rem; +$input-btn-font-size-lg: $font-size-lg; + +$input-btn-border-width: var(--#{$prefix}border-width); + +$input-padding-y: $input-btn-padding-y; +$input-padding-x: $input-btn-padding-x; +$input-font-family: $input-btn-font-family; +$input-font-size: $input-btn-font-size; +$input-font-weight: $font-weight-base; +$input-line-height: $input-btn-line-height; + +$input-padding-y-sm: $input-btn-padding-y-sm; +$input-padding-x-sm: $input-btn-padding-x-sm; +$input-font-size-sm: $input-btn-font-size-sm; + +$input-padding-y-lg: $input-btn-padding-y-lg; +$input-padding-x-lg: $input-btn-padding-x-lg; +$input-font-size-lg: $input-btn-font-size-lg; + +$input-bg: var(--#{$prefix}body-bg); +$input-disabled-color: null; +$input-disabled-bg: var(--#{$prefix}secondary-bg); +$input-disabled-border-color: null; + +$input-color: var(--#{$prefix}body-color); +$input-border-color: var(--#{$prefix}border-color); +$input-border-width: $input-btn-border-width; +$input-box-shadow: $box-shadow-inset; + +$input-border-radius: var(--#{$prefix}border-radius); +$input-border-radius-sm: var(--#{$prefix}border-radius-sm); +$input-border-radius-lg: var(--#{$prefix}border-radius-lg); + +$input-focus-bg: $input-bg; +$input-focus-border-color: tint-color($component-active-bg, 50%); +$input-focus-color: $input-color; +$input-focus-width: $input-btn-focus-width; +$input-focus-box-shadow: $input-btn-focus-box-shadow; + +$input-placeholder-color: var(--#{$prefix}secondary-color); +$input-plaintext-color: var(--#{$prefix}body-color); + +$input-height-border: calc( + #{$input-border-width} * 2 +); // stylelint-disable-line function-disallowed-list + +$input-height-inner: add($input-line-height * 1em, $input-padding-y * 2); +$input-height-inner-half: add($input-line-height * 0.5em, $input-padding-y); +$input-height-inner-quarter: add( + $input-line-height * 0.25em, + $input-padding-y * 0.5 +); + +$input-height: add( + $input-line-height * 1em, + add($input-padding-y * 2, $input-height-border, false) +); +$input-height-sm: add( + $input-line-height * 1em, + add($input-padding-y-sm * 2, $input-height-border, false) +); +$input-height-lg: add( + $input-line-height * 1em, + add($input-padding-y-lg * 2, $input-height-border, false) +); + +$input-transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + +$form-color-width: 3rem; + +// Form Label Text +$form-label-margin-bottom: 0.5rem; +$form-label-font-size: null; +$form-label-font-style: null; +$form-label-font-weight: null; +$form-label-color: null; + +// Form Text +$form-text-margin-top: 0.25rem; +$form-text-font-size: $small-font-size; +$form-text-font-style: null; +$form-text-font-weight: null; +$form-text-color: var(--#{$prefix}secondary-color); + +// Form File Button +$form-file-button-color: $input-color; +$form-file-button-bg: var(--#{$prefix}tertiary-bg); +$form-file-button-hover-bg: var(--#{$prefix}secondary-bg); diff --git a/src/assets/scss/forms/_input-group.scss b/src/assets/scss/forms/_input-group.scss new file mode 100644 index 0000000000..cd50a59126 --- /dev/null +++ b/src/assets/scss/forms/_input-group.scss @@ -0,0 +1,6 @@ +$input-group-addon-padding-y: $input-padding-y; +$input-group-addon-padding-x: $input-padding-x; +$input-group-addon-font-weight: $input-font-weight; +$input-group-addon-color: $input-color; +$input-group-addon-bg: var(--#{$prefix}tertiary-bg); +$input-group-addon-border-color: $input-border-color; diff --git a/src/assets/scss/forms/_range.scss b/src/assets/scss/forms/_range.scss new file mode 100644 index 0000000000..73be68f4f2 --- /dev/null +++ b/src/assets/scss/forms/_range.scss @@ -0,0 +1,19 @@ +$form-range-track-width: 100%; +$form-range-track-height: 0.5rem; +$form-range-track-cursor: pointer; +$form-range-track-bg: var(--#{$prefix}tertiary-bg); +$form-range-track-border-radius: 1rem; +$form-range-track-box-shadow: $box-shadow-inset; + +$form-range-thumb-width: 1rem; +$form-range-thumb-height: $form-range-thumb-width; +$form-range-thumb-bg: $component-active-bg; +$form-range-thumb-border: 0; +$form-range-thumb-border-radius: 1rem; +$form-range-thumb-box-shadow: 0 0.1rem 0.25rem rgba($black, 0.1); +$form-range-thumb-focus-box-shadow: 0 0 0 1px $body-bg, $input-focus-box-shadow; +$form-range-thumb-focus-box-shadow-width: $input-focus-width; // For focus box shadow issue in Edge +$form-range-thumb-active-bg: tint-color($component-active-bg, 70%); +$form-range-thumb-disabled-bg: var(--#{$prefix}secondary-color); +$form-range-thumb-transition: background-color 0.15s ease-in-out, + border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; diff --git a/src/assets/scss/forms/_select.scss b/src/assets/scss/forms/_select.scss new file mode 100644 index 0000000000..4d5c428636 --- /dev/null +++ b/src/assets/scss/forms/_select.scss @@ -0,0 +1,44 @@ +$form-select-padding-y: $input-padding-y; +$form-select-padding-x: $input-padding-x; +$form-select-font-family: $input-font-family; +$form-select-font-size: $input-font-size; +$form-select-indicator-padding: $form-select-padding-x * 3; // Extra padding for background-image +$form-select-font-weight: $input-font-weight; +$form-select-line-height: $input-line-height; +$form-select-color: $input-color; +$form-select-bg: $input-bg; +$form-select-disabled-color: null; +$form-select-disabled-bg: $input-disabled-bg; +$form-select-disabled-border-color: $input-disabled-border-color; +$form-select-bg-position: right $form-select-padding-x center; +$form-select-bg-size: 16px 12px; // In pixels because image dimensions +$form-select-indicator-color: $gray-800; +$form-select-indicator: url("data:image/svg+xml,"); + +$form-select-feedback-icon-padding-end: $form-select-padding-x * 2.5 + + $form-select-indicator-padding; +$form-select-feedback-icon-position: center right $form-select-indicator-padding; +$form-select-feedback-icon-size: $input-height-inner-half + $input-height-inner-half; + +$form-select-border-width: $input-border-width; +$form-select-border-color: $input-border-color; +$form-select-border-radius: $input-border-radius; +$form-select-box-shadow: $box-shadow-inset; + +$form-select-focus-border-color: $input-focus-border-color; +$form-select-focus-width: $input-focus-width; +$form-select-focus-box-shadow: 0 0 0 $form-select-focus-width + $input-btn-focus-color; + +$form-select-padding-y-sm: $input-padding-y-sm; +$form-select-padding-x-sm: $input-padding-x-sm; +$form-select-font-size-sm: $input-font-size-sm; +$form-select-border-radius-sm: $input-border-radius-sm; + +$form-select-padding-y-lg: $input-padding-y-lg; +$form-select-padding-x-lg: $input-padding-x-lg; +$form-select-font-size-lg: $input-font-size-lg; +$form-select-border-radius-lg: $input-border-radius-lg; + +$form-select-transition: $input-transition; diff --git a/src/assets/scss/forms/_validation.scss b/src/assets/scss/forms/_validation.scss new file mode 100644 index 0000000000..9877dfe327 --- /dev/null +++ b/src/assets/scss/forms/_validation.scss @@ -0,0 +1,20 @@ +$form-feedback-margin-top: $form-text-margin-top; +$form-feedback-font-size: $form-text-font-size; +$form-feedback-font-style: $form-text-font-style; +$form-feedback-valid-color: $success; +$form-feedback-invalid-color: $danger; + +$form-feedback-icon-valid-color: $form-feedback-valid-color; +$form-feedback-icon-valid: url("data:image/svg+xml,"); +$form-feedback-icon-invalid-color: $form-feedback-invalid-color; +$form-feedback-icon-invalid: url("data:image/svg+xml,"); + +$form-valid-color: $form-feedback-valid-color; +$form-valid-border-color: $form-feedback-valid-color; +$form-invalid-color: $form-feedback-invalid-color; +$form-invalid-border-color: $form-feedback-invalid-color; + +$form-valid-color-dark: $green-300; +$form-valid-border-color-dark: $green-300; +$form-invalid-color-dark: $red-300; +$form-invalid-border-color-dark: $red-300; diff --git a/src/assets/svgs/addEventProject.svg b/src/assets/svgs/addEventProject.svg new file mode 100644 index 0000000000..3c561d5ee8 --- /dev/null +++ b/src/assets/svgs/addEventProject.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/admin.svg b/src/assets/svgs/admin.svg new file mode 100644 index 0000000000..8ee42f611d --- /dev/null +++ b/src/assets/svgs/admin.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/svgs/angleRight.svg b/src/assets/svgs/angleRight.svg new file mode 100644 index 0000000000..4a3a498877 --- /dev/null +++ b/src/assets/svgs/angleRight.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/svgs/blockUser.svg b/src/assets/svgs/blockUser.svg new file mode 100644 index 0000000000..f9aef51775 --- /dev/null +++ b/src/assets/svgs/blockUser.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/svgs/blockedUser.svg b/src/assets/svgs/blockedUser.svg new file mode 100644 index 0000000000..bbe0a51f84 --- /dev/null +++ b/src/assets/svgs/blockedUser.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/svgs/checkInRegistrants.svg b/src/assets/svgs/checkInRegistrants.svg new file mode 100644 index 0000000000..0a663e3876 --- /dev/null +++ b/src/assets/svgs/checkInRegistrants.svg @@ -0,0 +1 @@ +check_inCreated with Sketch. \ No newline at end of file diff --git a/src/assets/svgs/dashboard.svg b/src/assets/svgs/dashboard.svg new file mode 100644 index 0000000000..12e8b0fe63 --- /dev/null +++ b/src/assets/svgs/dashboard.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/svgs/date.svg b/src/assets/svgs/date.svg new file mode 100644 index 0000000000..9baf0768c4 --- /dev/null +++ b/src/assets/svgs/date.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/event.svg b/src/assets/svgs/event.svg new file mode 100644 index 0000000000..3c73e7b04e --- /dev/null +++ b/src/assets/svgs/event.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/svgs/eventStats.svg b/src/assets/svgs/eventStats.svg new file mode 100644 index 0000000000..9503758f39 --- /dev/null +++ b/src/assets/svgs/eventStats.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/events.svg b/src/assets/svgs/events.svg new file mode 100644 index 0000000000..95b8a3b587 --- /dev/null +++ b/src/assets/svgs/events.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/svgs/flask.svg b/src/assets/svgs/flask.svg new file mode 100644 index 0000000000..599220a9d2 --- /dev/null +++ b/src/assets/svgs/flask.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/key.svg b/src/assets/svgs/key.svg new file mode 100644 index 0000000000..a1f47615e8 --- /dev/null +++ b/src/assets/svgs/key.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/svgs/listEventRegistrants.svg b/src/assets/svgs/listEventRegistrants.svg new file mode 100644 index 0000000000..4d2874d641 --- /dev/null +++ b/src/assets/svgs/listEventRegistrants.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/location.svg b/src/assets/svgs/location.svg new file mode 100644 index 0000000000..b75f616dd6 --- /dev/null +++ b/src/assets/svgs/location.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/logout.svg b/src/assets/svgs/logout.svg new file mode 100644 index 0000000000..e71a973f0d --- /dev/null +++ b/src/assets/svgs/logout.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/svgs/organizations.svg b/src/assets/svgs/organizations.svg new file mode 100644 index 0000000000..5c616655d2 --- /dev/null +++ b/src/assets/svgs/organizations.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/svgs/palisadoes.svg b/src/assets/svgs/palisadoes.svg new file mode 100644 index 0000000000..dc57b69a42 --- /dev/null +++ b/src/assets/svgs/palisadoes.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/assets/svgs/people.svg b/src/assets/svgs/people.svg new file mode 100644 index 0000000000..17c62eb14e --- /dev/null +++ b/src/assets/svgs/people.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/svgs/plugins.svg b/src/assets/svgs/plugins.svg new file mode 100644 index 0000000000..7da1701dc1 --- /dev/null +++ b/src/assets/svgs/plugins.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/assets/svgs/post.svg b/src/assets/svgs/post.svg new file mode 100644 index 0000000000..34e468523b --- /dev/null +++ b/src/assets/svgs/post.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/svgs/posts.svg b/src/assets/svgs/posts.svg new file mode 100644 index 0000000000..181e25855a --- /dev/null +++ b/src/assets/svgs/posts.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/svgs/requests.svg b/src/assets/svgs/requests.svg new file mode 100644 index 0000000000..8873bce1d7 --- /dev/null +++ b/src/assets/svgs/requests.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/assets/svgs/roles.svg b/src/assets/svgs/roles.svg new file mode 100644 index 0000000000..bc301784f9 --- /dev/null +++ b/src/assets/svgs/roles.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/svgs/settings.svg b/src/assets/svgs/settings.svg new file mode 100644 index 0000000000..064f6c9001 --- /dev/null +++ b/src/assets/svgs/settings.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/svgs/tags.svg b/src/assets/svgs/tags.svg new file mode 100644 index 0000000000..32cb76851a --- /dev/null +++ b/src/assets/svgs/tags.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/svgs/talawa.svg b/src/assets/svgs/talawa.svg new file mode 100644 index 0000000000..0c89afbcca --- /dev/null +++ b/src/assets/svgs/talawa.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/assets/svgs/user.svg b/src/assets/svgs/user.svg new file mode 100644 index 0000000000..b23b34481e --- /dev/null +++ b/src/assets/svgs/user.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/users.svg b/src/assets/svgs/users.svg new file mode 100644 index 0000000000..a1a474206d --- /dev/null +++ b/src/assets/svgs/users.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/talawa-logo-lite-200x200.png b/src/assets/talawa-logo-lite-200x200.png deleted file mode 100644 index 9d341376612c598c7e08af8bbd79d717abb15a6e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5133 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 { + const props = { + children: 'This is a dummy text', + }; + + test('should render props and text elements test for the page component', () => { + const { getByTestId, getByText } = render( + + + + + + + + + + ); + + expect(getByTestId('pluginContainer')).toBeInTheDocument(); + expect(getByText(props.children)).toBeInTheDocument(); + }); +}); diff --git a/src/components/AddOn/AddOn.tsx b/src/components/AddOn/AddOn.tsx new file mode 100644 index 0000000000..4e73c52b7c --- /dev/null +++ b/src/components/AddOn/AddOn.tsx @@ -0,0 +1,36 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +interface InterfaceAddOnProps { + extras: any; + name: string; + children: any; +} + +// Validate Extras +function addOn({ children }: InterfaceAddOnProps): JSX.Element { + return ( + <> +

    + {children} +
    + + ); +} + +addOn.defaultProps = { + extras: {}, + name: '', + children: null, +}; + +addOn.propTypes = { + extras: PropTypes.shape({ + components: PropTypes.shape({}), + actions: PropTypes.shape({}), + }), + name: PropTypes.string, + children: PropTypes.any, +}; + +export default addOn; diff --git a/src/components/AddOn/core/AddOnEntry/AddOnEntry.module.css b/src/components/AddOn/core/AddOnEntry/AddOnEntry.module.css new file mode 100644 index 0000000000..1f1ea89996 --- /dev/null +++ b/src/components/AddOn/core/AddOnEntry/AddOnEntry.module.css @@ -0,0 +1,20 @@ +.entrytoggle { + margin: 24px 24px 0 auto; + width: fit-content; +} + +.entryaction { + margin-left: auto; + display: flex !important; + align-items: center; +} + +.entryaction i { + margin-right: 8px; +} + +.entryaction .spinner-grow { + height: 1rem; + width: 1rem; + margin-right: 8px; +} diff --git a/src/components/AddOn/core/AddOnEntry/AddOnEntry.test.tsx b/src/components/AddOn/core/AddOnEntry/AddOnEntry.test.tsx new file mode 100644 index 0000000000..50e56adf1e --- /dev/null +++ b/src/components/AddOn/core/AddOnEntry/AddOnEntry.test.tsx @@ -0,0 +1,98 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import { BrowserRouter } from 'react-router-dom'; +import AddOnEntry from './AddOnEntry'; +import { + ApolloClient, + ApolloProvider, + InMemoryCache, + ApolloLink, + HttpLink, +} from '@apollo/client'; + +import type { NormalizedCacheObject } from '@apollo/client'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import { BACKEND_URL } from 'Constant/constant'; +import i18nForTest from 'utils/i18nForTest'; +import { I18nextProvider } from 'react-i18next'; + +const httpLink = new HttpLink({ + uri: BACKEND_URL, + headers: { + authorization: 'Bearer ' + localStorage.getItem('token') || '', + }, +}); +console.error = jest.fn(); +const client: ApolloClient = new ApolloClient({ + cache: new InMemoryCache(), + link: ApolloLink.from([httpLink]), +}); + +describe('Testing AddOnEntry', () => { + const props = { + id: 'string', + enabled: true, + title: 'string', + description: 'string', + createdBy: 'string', + component: 'string', + installed: true, + configurable: true, + modified: true, + isInstalled: true, + getInstalledPlugins: (): { sample: string } => { + return { sample: 'sample' }; + }, + }; + + test('should render modal and take info to add plugin for registered organization', () => { + const { getByTestId } = render( + + + + + {} + + + + + ); + expect(getByTestId('AddOnEntry')).toBeInTheDocument(); + }); + + it('renders correctly', () => { + const props = { + id: '1', + title: 'Test Addon', + description: 'Test addon description', + createdBy: 'Test User', + component: 'string', + installed: true, + configurable: true, + modified: true, + isInstalled: true, + uninstalledOrgs: [], + enabled: true, + getInstalledPlugins: (): { sample: string } => { + return { sample: 'sample' }; + }, + }; + + const { getByText } = render( + + + + + {} + + + + + ); + + expect(getByText('Test Addon')).toBeInTheDocument(); + expect(getByText('Test addon description')).toBeInTheDocument(); + expect(getByText('Test User')).toBeInTheDocument(); + }); +}); diff --git a/src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx b/src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx new file mode 100644 index 0000000000..7503d0667d --- /dev/null +++ b/src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx @@ -0,0 +1,126 @@ +import React, { useState } from 'react'; +import PropTypes from 'prop-types'; +import styles from './AddOnEntry.module.css'; +import { Button, Card, Spinner } from 'react-bootstrap'; +import { UPDATE_INSTALL_STATUS_PLUGIN_MUTATION } from 'GraphQl/Mutations/mutations'; +import { useMutation } from '@apollo/client'; +import { useTranslation } from 'react-i18next'; +import { toast } from 'react-toastify'; + +interface InterfaceAddOnEntryProps { + id: string; + enabled: boolean; + title: string; + description: string; + createdBy: string; + component: string; + modified: any; + uninstalledOrgs: string[]; + getInstalledPlugins: () => any; +} + +function addOnEntry({ + id, + title, + description, + createdBy, + uninstalledOrgs, + getInstalledPlugins, +}: InterfaceAddOnEntryProps): JSX.Element { + const { t } = useTranslation('translation', { keyPrefix: 'addOnEntry' }); + //getting orgId from URL + const currentOrg = window.location.href.split('/id=')[1] + ''; + const [buttonLoading, setButtonLoading] = useState(false); + const [isInstalledLocal, setIsInstalledLocal] = useState( + uninstalledOrgs.includes(currentOrg) + ); + // const [addOrgAsUninstalled] = useMutation(UPDATE_ORG_STATUS_PLUGIN_MUTATION); + const [addOrgAsUninstalled] = useMutation( + UPDATE_INSTALL_STATUS_PLUGIN_MUTATION + ); + + const togglePluginInstall = async (): Promise => { + setButtonLoading(true); + await addOrgAsUninstalled({ + variables: { + id: id.toString(), + orgId: currentOrg.toString(), + }, + }); + + setIsInstalledLocal(!isInstalledLocal); + setButtonLoading(false); + const dialog: string = isInstalledLocal + ? t('installMsg') + : t('uninstallMsg'); + toast.success(dialog); + }; + + return ( + <> + + {/* {uninstalledOrgs.includes(currentOrg) && ( + {}} + disabled={switchInProgress} + checked={enabled} + /> + )} */} + + {title} + + {createdBy} + + {description} + + + +
    + + ); +} + +addOnEntry.defaultProps = { + enabled: false, + configurable: true, + title: '', + description: '', + isInstalled: false, +}; + +addOnEntry.propTypes = { + enabled: PropTypes.bool, + configurable: PropTypes.bool, + title: PropTypes.string, + description: PropTypes.string, + isInstalled: PropTypes.bool, +}; + +export default addOnEntry; diff --git a/src/components/AddOn/core/AddOnRegister/AddOnRegister.module.css b/src/components/AddOn/core/AddOnRegister/AddOnRegister.module.css new file mode 100644 index 0000000000..c122d386fa --- /dev/null +++ b/src/components/AddOn/core/AddOnRegister/AddOnRegister.module.css @@ -0,0 +1,9 @@ +.modalbtn { + display: flex !important; + margin-left: auto; + align-items: center; +} + +.modalbtn i { + margin-right: 8px; +} diff --git a/src/components/AddOn/core/AddOnRegister/AddOnRegister.test.tsx b/src/components/AddOn/core/AddOnRegister/AddOnRegister.test.tsx new file mode 100644 index 0000000000..7caa1f9e3e --- /dev/null +++ b/src/components/AddOn/core/AddOnRegister/AddOnRegister.test.tsx @@ -0,0 +1,72 @@ +import React from 'react'; +import { act, render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import AddOnRegister from './AddOnRegister'; +import { + ApolloClient, + ApolloProvider, + InMemoryCache, + ApolloLink, + HttpLink, +} from '@apollo/client'; +import type { NormalizedCacheObject } from '@apollo/client'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import { BrowserRouter } from 'react-router-dom'; +import { BACKEND_URL } from 'Constant/constant'; +import i18nForTest from 'utils/i18nForTest'; +import { I18nextProvider } from 'react-i18next'; + +const httpLink = new HttpLink({ + uri: BACKEND_URL, + headers: { + authorization: 'Bearer ' + localStorage.getItem('token') || '', + }, +}); + +async function wait(ms = 500): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +const client: ApolloClient = new ApolloClient({ + cache: new InMemoryCache(), + link: ApolloLink.from([httpLink]), +}); +describe('Testing AddOnRegister', () => { + const props = { + id: '6234d8bf6ud937ddk70ecc5c9', + }; + + test('should render modal and take info to add plugin for registered organization', async () => { + await act(async () => { + render( + + + + + {} + + + + + ); + + await wait(100); + + userEvent.click(screen.getByRole('button', { name: /Add New/i })); + userEvent.type(screen.getByPlaceholderText(/Ex: Donations/i), 'myplugin'); + userEvent.type( + screen.getByPlaceholderText(/This Plugin enables UI for/i), + 'test description' + ); + userEvent.type( + screen.getByPlaceholderText(/Ex: john Doe/i), + 'test creator' + ); + }); + }); +}); diff --git a/src/components/AddOn/core/AddOnRegister/AddOnRegister.tsx b/src/components/AddOn/core/AddOnRegister/AddOnRegister.tsx new file mode 100644 index 0000000000..4f720b4fad --- /dev/null +++ b/src/components/AddOn/core/AddOnRegister/AddOnRegister.tsx @@ -0,0 +1,159 @@ +import React, { useState } from 'react'; +import PropTypes from 'prop-types'; +import styles from './AddOnRegister.module.css'; +import { Button, Form, Modal } from 'react-bootstrap'; +import { useMutation } from '@apollo/client'; +import { ADD_PLUGIN_MUTATION } from 'GraphQl/Mutations/mutations'; +import { useTranslation } from 'react-i18next'; +import { toast } from 'react-toastify'; + +interface InterfaceAddOnRegisterProps { + id?: string; // OrgId + createdBy?: string; // User +} +interface InterfaceFormStateTypes { + pluginName: string; + pluginCreatedBy: string; + pluginDesc: string; + pluginInstallStatus: boolean; + installedOrgs: [string] | []; +} + +const currentUrl = window.location.href.split('=')[1]; +// eslint-disable-next-line @typescript-eslint/no-unused-vars +function addOnRegister({ + // eslint-disable-next-line @typescript-eslint/no-unused-vars + createdBy, +}: InterfaceAddOnRegisterProps): JSX.Element { + const { t } = useTranslation('translation', { keyPrefix: 'addOnRegister' }); + + const [show, setShow] = useState(false); + + const handleClose = (): void => setShow(false); + const handleShow = (): void => setShow(true); + const [create] = useMutation(ADD_PLUGIN_MUTATION); + + const [formState, setFormState] = useState({ + pluginName: '', + pluginCreatedBy: '', + pluginDesc: '', + pluginInstallStatus: false, + installedOrgs: [currentUrl], + }); + + const handleRegister = async (): Promise => { + const { data } = await create({ + variables: { + $pluginName: formState.pluginName, + $pluginCreatedBy: formState.pluginCreatedBy, + $pluginDesc: formState.pluginDesc, + $pluginInstallStatus: formState.pluginInstallStatus, + $installedOrgs: formState.installedOrgs, + }, + }); + + if (data) { + toast.success('Plugin Added Successfully'); + setTimeout(() => { + window.location.reload(); + }, 2000); + } + }; + return ( + <> + + + + + {t('addPlugin')} + + +
    + + {t('pluginName')} + { + setFormState({ + ...formState, + pluginName: e.target.value, + }); + }} + /> + + + {t('creatorName')} + { + setFormState({ + ...formState, + pluginCreatedBy: e.target.value, + }); + }} + /> + + + {t('pluginDesc')} + { + setFormState({ + ...formState, + pluginDesc: e.target.value, + }); + }} + /> + +
    +
    + + + + +
    + + ); +} + +addOnRegister.defaultProps = { + createdBy: 'Admin', +}; + +addOnRegister.propTypes = { + createdBy: PropTypes.string, +}; + +export default addOnRegister; diff --git a/src/components/AddOn/core/AddOnStore/AddOnStore.module.css b/src/components/AddOn/core/AddOnStore/AddOnStore.module.css new file mode 100644 index 0000000000..8a34c03be5 --- /dev/null +++ b/src/components/AddOn/core/AddOnStore/AddOnStore.module.css @@ -0,0 +1,31 @@ +.container { + display: flex; +} + +.logintitle { + color: #707070; + font-weight: 600; + font-size: 20px; + margin-bottom: 30px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 15%; +} + +.actioninput { + text-decoration: none; + margin-bottom: 50px; + border-color: #e8e5e5; + width: 80%; + border-radius: 7px; + padding-top: 5px; + padding-bottom: 5px; + padding-right: 10px; + padding-left: 10px; + box-shadow: none; +} + +.actionradio input { + width: fit-content; + margin: inherit; +} diff --git a/src/components/AddOn/core/AddOnStore/AddOnStore.test.tsx b/src/components/AddOn/core/AddOnStore/AddOnStore.test.tsx new file mode 100644 index 0000000000..2fc5e61e92 --- /dev/null +++ b/src/components/AddOn/core/AddOnStore/AddOnStore.test.tsx @@ -0,0 +1,60 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +// import * as reactRedux from 'react-redux'; +// import { BrowserRouter } from 'react-router-dom'; +// import userEvent from '@testing-library/user-event'; + +// import AddOnStore from './AddOnStore'; +// import { store } from 'state/store'; +import { + ApolloClient, + ApolloProvider, + InMemoryCache, + ApolloLink, + HttpLink, +} from '@apollo/client'; + +import type { NormalizedCacheObject } from '@apollo/client'; +import { BrowserRouter } from 'react-router-dom'; +import AddOnStore from './AddOnStore'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import { BACKEND_URL } from 'Constant/constant'; +import i18nForTest from 'utils/i18nForTest'; +import { I18nextProvider } from 'react-i18next'; + +const httpLink = new HttpLink({ + uri: BACKEND_URL, + headers: { + authorization: 'Bearer ' + localStorage.getItem('token') || '', + }, +}); + +const client: ApolloClient = new ApolloClient({ + cache: new InMemoryCache(), + link: ApolloLink.from([httpLink]), +}); +describe('Testing AddOnStore Component', () => { + test('Temporary test for AddOnStore', () => { + expect(true).toBe(true); + const { getByTestId } = render( + + + + + {} + + + + + ); + expect(getByTestId('AddOnEntryStore')).toBeInTheDocument(); + }); + // const useSelectorMock = jest.spyOn(reactRedux, 'useSelector'); + // const useDispatchMock = jest.spyOn(reactRedux, 'useDispatch'); + + // beforeEach(() => { + // useSelectorMock.mockClear(); + // useDispatchMock.mockClear(); + // }); +}); diff --git a/src/components/AddOn/core/AddOnStore/AddOnStore.tsx b/src/components/AddOn/core/AddOnStore/AddOnStore.tsx new file mode 100644 index 0000000000..d81ce6fa4c --- /dev/null +++ b/src/components/AddOn/core/AddOnStore/AddOnStore.tsx @@ -0,0 +1,360 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import React, { useEffect, useState } from 'react'; +import PropTypes from 'react'; +import styles from './AddOnStore.module.css'; +import AddOnEntry from '../AddOnEntry/AddOnEntry'; +import Action from '../../support/components/Action/Action'; +import SidePanel from 'components/AddOn/support/components/SidePanel/SidePanel'; +import MainContent from 'components/AddOn/support/components/MainContent/MainContent'; +import { useQuery } from '@apollo/client'; +import { + ADMIN_LIST, + MEMBERS_LIST, + PLUGIN_GET, + USER_LIST, +} from 'GraphQl/Queries/Queries'; // PLUGIN_LIST +import { useSelector } from 'react-redux'; +import type { RootState } from '../../../../state/reducers'; +import { Col, Form, Row, Tab, Tabs } from 'react-bootstrap'; +import AddOnRegister from '../AddOnRegister/AddOnRegister'; +import PluginHelper from 'components/AddOn/support/services/Plugin.helper'; +import { store } from './../../../../state/store'; +import { useTranslation } from 'react-i18next'; +import Loader from 'components/Loader/Loader'; +import OrganizationScreen from 'components/OrganizationScreen/OrganizationScreen'; + +function addOnStore(): JSX.Element { + const { t } = useTranslation('translation', { keyPrefix: 'addOnStore' }); + document.title = t('title'); + + const [isStore, setIsStore] = useState(true); + const [showEnabled, setShowEnabled] = useState(true); + const [searchText, setSearchText] = useState(''); + const [dataList, setDataList] = useState([]); + + const [render, setRender] = useState(true); + const appRoutes = useSelector((state: RootState) => state.appRoutes); + const { targets, configUrl } = appRoutes; + + const plugins = useSelector((state: RootState) => state.plugins); + const { installed, addonStore } = plugins; + // type plugData = { pluginName: String, plug }; + const { data, loading, error } = useQuery(PLUGIN_GET); + /* istanbul ignore next */ + // eslint-disable-next-line @typescript-eslint/explicit-function-return-type + const getStorePlugins = async () => { + let plugins = await new PluginHelper().fetchStore(); + const installIds = (await new PluginHelper().fetchInstalled()).map( + (plugin: any) => plugin.id + ); + plugins = plugins.map((plugin: any) => { + plugin.installed = installIds.includes(plugin.id); + return plugin; + }); + store.dispatch({ type: 'UPDATE_STORE', payload: plugins }); + }; + + /* istanbul ignore next */ + const getInstalledPlugins: () => any = () => { + setDataList(data); + // setRender((current) => !current); + // const { + // data: newData, + // loading: newLoading, + // error: newError, + // } = useQuery(PLUGIN_GET); + // data = newData; + // loading = newLoading; + // error = newError; + // const plugins = await new PluginHelper().fetchInstalled(); + // store.dispatch({ type: 'UPDATE_INSTALLED', payload: plugins }); + // return plugins; + }; + + /* istanbul ignore next */ + const updateLinks = async (links: any[]): Promise => { + store.dispatch({ type: 'UPDATE_P_TARGETS', payload: links }); + }; + // /* istanbul ignore next */ + const pluginModified = (): void => { + return getInstalledPlugins(); + // .then((installedPlugins) => { + // getStorePlugins(); + // return installedPlugins; + // }); + }; + + // useEffect(() => { + // pluginModified(); + // }, []); + + const updateSelectedTab = (tab: any): void => { + setIsStore(tab === 'available'); + isStore ? getStorePlugins() : getInstalledPlugins(); + }; + + const filterChange = (ev: any): void => { + setShowEnabled(ev.target.value === 'enabled'); + }; + + /* istanbul ignore next */ + if (loading) { + return ( + <> +
    + + ); + } + return ( + <> + + + + + setSearchText(e.target.value)} + /> + + {!isStore && ( + +
    +
    + + +
    +
    +
    + )} + + +
    +

    {t('pHeading')}

    + {searchText ? ( +

    + Search results for {searchText} +

    + ) : null} + + + + {console.log( + data.getPlugins.filter( + (val: { + _id: string; + pluginName: string | undefined; + pluginDesc: string | undefined; + pluginCreatedBy: string; + pluginInstallStatus: boolean | undefined; + getInstalledPlugins: () => any; + }) => { + if (searchText == '') { + return val; + } else if ( + val.pluginName + ?.toLowerCase() + .includes(searchText.toLowerCase()) + ) { + return val; + } + } + ) + )} + {data.getPlugins.filter( + (val: { + _id: string; + pluginName: string | undefined; + pluginDesc: string | undefined; + pluginCreatedBy: string; + pluginInstallStatus: boolean | undefined; + getInstalledPlugins: () => any; + }) => { + if (searchText == '') { + return val; + } else if ( + val.pluginName + ?.toLowerCase() + .includes(searchText.toLowerCase()) + ) { + return val; + } + } + ).length === 0 ? ( +

    {t('pMessage')}

    + ) : ( + data.getPlugins + .filter( + (val: { + _id: string; + pluginName: string | undefined; + pluginDesc: string | undefined; + pluginCreatedBy: string; + pluginInstallStatus: boolean | undefined; + getInstalledPlugins: () => any; + }) => { + if (searchText == '') { + return val; + } else if ( + val.pluginName + ?.toLowerCase() + .includes(searchText.toLowerCase()) + ) { + return val; + } + } + ) + .map( + ( + plug: { + _id: string; + pluginName: string | undefined; + pluginDesc: string | undefined; + pluginCreatedBy: string; + uninstalledOrgs: string[]; + getInstalledPlugins: () => any; + }, + i: React.Key | null | undefined + ): JSX.Element => ( + { + console.log('Plugin is modified'); + }} + getInstalledPlugins={getInstalledPlugins} + uninstalledOrgs={plug.uninstalledOrgs} + /> + ) + ) + )} +
    + + {data.getPlugins + .filter((plugin: any) => plugin.pluginInstallStatus == true) + .filter( + (val: { + _id: string; + pluginName: string | undefined; + pluginDesc: string | undefined; + pluginCreatedBy: string; + pluginInstallStatus: boolean | undefined; + getInstalledPlugins: () => any; + }) => { + if (searchText == '') { + return val; + } else if ( + val.pluginName + ?.toLowerCase() + .includes(searchText.toLowerCase()) + ) { + return val; + } + } + ).length === 0 ? ( +

    {t('pMessage')}

    // eslint-disable-line + ) : ( + data.getPlugins + .filter( + (plugin: any) => plugin.pluginInstallStatus == true + ) + .filter( + (val: { + _id: string; + pluginName: string | undefined; + pluginDesc: string | undefined; + pluginCreatedBy: string; + pluginInstallStatus: boolean | undefined; + getInstalledPlugins: () => any; + }) => { + if (searchText == '') { + return val; + } else if ( + val.pluginName + ?.toLowerCase() + .includes(searchText.toLowerCase()) + ) { + return val; + } + } + ) + .map( + ( + plug: { + _id: string; + pluginName: string | undefined; + pluginDesc: string | undefined; + pluginCreatedBy: string; + uninstalledOrgs: string[]; + getInstalledPlugins: () => any; + }, + i: React.Key | null | undefined + ): JSX.Element => ( + { + console.log('Plugin is modified'); + }} + getInstalledPlugins={getInstalledPlugins} + uninstalledOrgs={plug.uninstalledOrgs} + /> + ) + ) + )} +
    +
    +
    + +
    +
    + + ); +} + +addOnStore.defaultProps = {}; + +addOnStore.propTypes = {}; + +export default addOnStore; diff --git a/src/components/AddOn/support/components/Action/Action.module.css b/src/components/AddOn/support/components/Action/Action.module.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/components/AddOn/support/components/Action/Action.test.tsx b/src/components/AddOn/support/components/Action/Action.test.tsx new file mode 100644 index 0000000000..9c9d37781d --- /dev/null +++ b/src/components/AddOn/support/components/Action/Action.test.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import { Provider } from 'react-redux'; + +import { store } from 'state/store'; +import Action from './Action'; + +describe('Testing Action Component', () => { + const props = { + children: 'dummy children', + label: 'dummy label', + }; + + test('should render props and text elements test for the page component', () => { + const { getByText } = render( + + + + ); + + expect(getByText(props.label)).toBeInTheDocument(); + expect(getByText(props.children)).toBeInTheDocument(); + }); +}); diff --git a/src/components/AddOn/support/components/Action/Action.tsx b/src/components/AddOn/support/components/Action/Action.tsx new file mode 100644 index 0000000000..50b6b10797 --- /dev/null +++ b/src/components/AddOn/support/components/Action/Action.tsx @@ -0,0 +1,21 @@ +import React, { useRef } from 'react'; + +// TODO: UI logic for embedded actions (hide label) +interface InterfaceActionProps { + children: any; + label: string; +} + +// TODO: props => Validate child element type, register functions from children for global use?, +function action(props: InterfaceActionProps): JSX.Element { + const actionRef = useRef(null); + + return ( +
    +
    {props.label}
    + {props.children} +
    + ); +} + +export default action; diff --git a/src/components/AddOn/support/components/MainContent/MainContent.module.css b/src/components/AddOn/support/components/MainContent/MainContent.module.css new file mode 100644 index 0000000000..3321cf6fd7 --- /dev/null +++ b/src/components/AddOn/support/components/MainContent/MainContent.module.css @@ -0,0 +1,4 @@ +.maincontainer { + width: 70vw; + margin-right: 2rem; +} diff --git a/src/components/AddOn/support/components/MainContent/MainContent.test.tsx b/src/components/AddOn/support/components/MainContent/MainContent.test.tsx new file mode 100644 index 0000000000..fe2914a277 --- /dev/null +++ b/src/components/AddOn/support/components/MainContent/MainContent.test.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; + +import { store } from 'state/store'; +import MainContent from './MainContent'; + +describe('Testing MainContent component', () => { + const props = { + children: 'This is a dummy text', + }; + + test('should render props and children for the Main Content', () => { + const { getByTestId, getByText } = render( + + + + + + ); + + expect(getByTestId('mainContentCheck')).toBeInTheDocument(); + expect(getByText(props.children)).toBeInTheDocument(); + }); +}); diff --git a/src/components/AddOn/support/components/MainContent/MainContent.tsx b/src/components/AddOn/support/components/MainContent/MainContent.tsx new file mode 100644 index 0000000000..7ca4dfc8c4 --- /dev/null +++ b/src/components/AddOn/support/components/MainContent/MainContent.tsx @@ -0,0 +1,18 @@ +import React from 'react'; +import styles from './MainContent.module.css'; +interface InterfaceMainContentProps { + children: any; +} + +// TODO: Implement extras plugins +// TODO: Implement additional styles +// id - [plugin/component-name]-main-content if is in plugin +function mainContent({ children }: InterfaceMainContentProps): JSX.Element { + return ( +
    + {children} +
    + ); +} + +export default mainContent; diff --git a/src/components/AddOn/support/components/SidePanel/SidePanel.module.css b/src/components/AddOn/support/components/SidePanel/SidePanel.module.css new file mode 100644 index 0000000000..f337eeea1b --- /dev/null +++ b/src/components/AddOn/support/components/SidePanel/SidePanel.module.css @@ -0,0 +1,12 @@ +.sidebarcontainer { + width: 30vw; + justify-content: center; + display: flex; + flex-direction: column; + padding: 2rem; + height: fit-content; +} + +.sidebarcollapsed { + display: none; +} diff --git a/src/components/AddOn/support/components/SidePanel/SidePanel.test.tsx b/src/components/AddOn/support/components/SidePanel/SidePanel.test.tsx new file mode 100644 index 0000000000..5590fa1786 --- /dev/null +++ b/src/components/AddOn/support/components/SidePanel/SidePanel.test.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import SidePanel from './SidePanel'; +import type { NormalizedCacheObject } from '@apollo/client'; +import { ApolloClient, ApolloProvider, InMemoryCache } from '@apollo/client'; +import { BACKEND_URL } from 'Constant/constant'; + +const client: ApolloClient = new ApolloClient({ + cache: new InMemoryCache(), + uri: BACKEND_URL, +}); + +describe('Testing Contribution Stats', () => { + const props = { + collapse: true, + children: '234', + }; + + test('should render props and text elements test for the SidePanel component', () => { + render( + + + + ); + expect(screen.getByTestId('SidePanel')).toBeInTheDocument(); + }); +}); diff --git a/src/components/AddOn/support/components/SidePanel/SidePanel.tsx b/src/components/AddOn/support/components/SidePanel/SidePanel.tsx new file mode 100644 index 0000000000..2eda5e7225 --- /dev/null +++ b/src/components/AddOn/support/components/SidePanel/SidePanel.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import styles from './SidePanel.module.css'; +interface InterfaceSidePanelProps { + collapse?: boolean; + children: any; +} + +// TODO: Implement Extras Plugin +// id - [plugin-name]-side-panel +function sidePanel({ + collapse, + children, +}: InterfaceSidePanelProps): JSX.Element { + return ( +
    + {children} +
    + ); +} + +export default sidePanel; diff --git a/src/components/AddOn/support/services/Plugin.helper.test.ts b/src/components/AddOn/support/services/Plugin.helper.test.ts new file mode 100644 index 0000000000..e024734247 --- /dev/null +++ b/src/components/AddOn/support/services/Plugin.helper.test.ts @@ -0,0 +1,46 @@ +import PluginHelper from './Plugin.helper'; + +describe('Testing src/components/AddOn/support/services/Plugin.helper.ts', () => { + test('Class should contain the required method definitions', () => { + const pluginHelper = new PluginHelper(); + expect(pluginHelper).toHaveProperty('fetchStore'); + expect(pluginHelper).toHaveProperty('fetchInstalled'); + expect(pluginHelper).toHaveProperty('generateLinks'); + expect(pluginHelper).toHaveProperty('generateLinks'); + }); + test('generateLinks should return proper objects', () => { + const obj = { enabled: true, name: 'demo', component: 'samplecomponent' }; + const objToMatch = { name: 'demo', url: '/plugin/samplecomponent' }; + const pluginHelper = new PluginHelper(); + const val = pluginHelper.generateLinks([obj]); + expect(val).toMatchObject([objToMatch]); + }); + it('fetchStore should return expected JSON', async () => { + const helper = new PluginHelper(); + const spy = jest.spyOn(global, 'fetch').mockImplementation(() => { + const response = new Response(); + response.json = jest + .fn() + .mockReturnValue(Promise.resolve({ data: 'mock data' })); + return Promise.resolve(response); + }); + + const result = await helper.fetchStore(); + expect(result).toEqual({ data: 'mock data' }); + spy.mockRestore(); + }); + it('fetchInstalled() should return expected JSON', async () => { + const pluginHelper = new PluginHelper(); + const mockResponse = [ + { name: 'plugin1', component: 'Component1', enabled: true }, + { name: 'plugin2', component: 'Component2', enabled: false }, + ]; + jest.spyOn(global, 'fetch').mockImplementation(() => { + const response = new Response(); + response.json = jest.fn().mockReturnValue(Promise.resolve(mockResponse)); + return Promise.resolve(response); + }) as jest.Mock; + const result = await pluginHelper.fetchInstalled(); + expect(result).toEqual(mockResponse); + }); +}); diff --git a/src/components/AddOn/support/services/Plugin.helper.ts b/src/components/AddOn/support/services/Plugin.helper.ts new file mode 100644 index 0000000000..358d4b3d7f --- /dev/null +++ b/src/components/AddOn/support/services/Plugin.helper.ts @@ -0,0 +1,24 @@ +class PluginHelper { + fetchStore = async (): Promise => { + const result = await fetch(`http://localhost:3005/store`); + return await result.json(); + }; + + fetchInstalled = async (): Promise => { + const result = await fetch(`http://localhost:3005/installed`); + return await result.json(); + }; + + generateLinks = (plugins: any[]): { name: string; url: string }[] => { + return plugins + .filter((plugin: any) => plugin.enabled) + .map((installedPlugin: any) => { + return { + name: installedPlugin.name, + url: `/plugin/${installedPlugin.component.toLowerCase()}`, + }; + }); + }; +} + +export default PluginHelper; diff --git a/src/components/AddOn/support/services/Render.helper.ts b/src/components/AddOn/support/services/Render.helper.ts new file mode 100644 index 0000000000..21202dc7af --- /dev/null +++ b/src/components/AddOn/support/services/Render.helper.ts @@ -0,0 +1,3 @@ +class RenderHelper {} + +export default RenderHelper; diff --git a/src/components/Advertisements/Advertisements.module.css b/src/components/Advertisements/Advertisements.module.css new file mode 100644 index 0000000000..8a34c03be5 --- /dev/null +++ b/src/components/Advertisements/Advertisements.module.css @@ -0,0 +1,31 @@ +.container { + display: flex; +} + +.logintitle { + color: #707070; + font-weight: 600; + font-size: 20px; + margin-bottom: 30px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 15%; +} + +.actioninput { + text-decoration: none; + margin-bottom: 50px; + border-color: #e8e5e5; + width: 80%; + border-radius: 7px; + padding-top: 5px; + padding-bottom: 5px; + padding-right: 10px; + padding-left: 10px; + box-shadow: none; +} + +.actionradio input { + width: fit-content; + margin: inherit; +} diff --git a/src/components/Advertisements/Advertisements.test.tsx b/src/components/Advertisements/Advertisements.test.tsx new file mode 100644 index 0000000000..bec43589b6 --- /dev/null +++ b/src/components/Advertisements/Advertisements.test.tsx @@ -0,0 +1,95 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import { MockedProvider } from '@apollo/client/testing'; +import { + ApolloClient, + ApolloProvider, + InMemoryCache, + ApolloLink, + HttpLink, +} from '@apollo/client'; + +import type { NormalizedCacheObject } from '@apollo/client'; +import { BrowserRouter } from 'react-router-dom'; +import Advertisement from './Advertisements'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import { BACKEND_URL } from 'Constant/constant'; +import i18nForTest from 'utils/i18nForTest'; +import { I18nextProvider } from 'react-i18next'; +import { ADVERTISEMENTS_GET } from 'GraphQl/Queries/Queries'; + +const httpLink = new HttpLink({ + uri: BACKEND_URL, + headers: { + authorization: 'Bearer ' + localStorage.getItem('token') || '', + }, +}); + +const client: ApolloClient = new ApolloClient({ + cache: new InMemoryCache(), + link: ApolloLink.from([httpLink]), +}); +describe('Testing Advertisement Component', () => { + test('Temporary test for Advertisement', () => { + expect(true).toBe(true); + const { getByTestId } = render( + + + + + {} + + + + + ); + expect(getByTestId('AdEntryStore')).toBeInTheDocument(); + }); + + test('renders advertisement data', async () => { + const mocks = [ + { + request: { + query: ADVERTISEMENTS_GET, + variables: { + name: 'Test', + }, + }, + result: { + data: { + getAdvertisements: [ + { + _id: '1', + name: 'Advertisement', + type: 'POPUP', + orgId: 'org1', + link: 'http://example.com', + endDate: new Date(), + startDate: new Date(), + }, + // Add more mock data if needed + ], + }, + loading: false, + }, + }, + ]; + + const { getByTestId } = render( + + + + + + + + + + + + ); + + expect(getByTestId('AdEntryStore')).toBeInTheDocument(); + }); +}); diff --git a/src/components/Advertisements/Advertisements.tsx b/src/components/Advertisements/Advertisements.tsx new file mode 100644 index 0000000000..7af6fd98c9 --- /dev/null +++ b/src/components/Advertisements/Advertisements.tsx @@ -0,0 +1,197 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import React, { useEffect, useState } from 'react'; +import PropTypes from 'react'; +import styles from './Advertisements.module.css'; +import { useQuery } from '@apollo/client'; +import { ADVERTISEMENTS_GET, PLUGIN_GET } from 'GraphQl/Queries/Queries'; // PLUGIN_LIST +import { useSelector } from 'react-redux'; +import type { RootState } from '../../state/reducers'; +import { Col, Form, Row, Tab, Tabs } from 'react-bootstrap'; +import PluginHelper from 'components/AddOn/support/services/Plugin.helper'; +import { store } from 'state/store'; +import { useTranslation } from 'react-i18next'; +import Loader from 'components/Loader/Loader'; +import OrganizationScreen from 'components/OrganizationScreen/OrganizationScreen'; +import AdvertisementEntry from './core/AdvertisementEntry/AdvertisementEntry'; +import AdvertisementRegister from './core/AdvertisementRegister/AdvertisementRegister'; +import AddOnRegister from 'components/AddOn/core/AddOnRegister/AddOnRegister'; +export default function advertisements(): JSX.Element { + const { + data: data2, + loading: loading2, + error: error2, + } = useQuery(ADVERTISEMENTS_GET); + const currentOrgId = window.location.href.split('/id=')[1] + ''; + const { t } = useTranslation('translation', { keyPrefix: 'advertisement' }); + document.title = t('title'); + + const [isStore, setIsStore] = useState(true); + const [showEnabled, setShowEnabled] = useState(true); + const [searchText, setSearchText] = useState(''); + const [dataList, setDataList] = useState([]); + + const [render, setRender] = useState(true); + const appRoutes = useSelector((state: RootState) => state.appRoutes); + const { targets, configUrl } = appRoutes; + + const plugins = useSelector((state: RootState) => state.plugins); + const { installed, addonStore } = plugins; + const { data, loading, error } = useQuery(PLUGIN_GET); + /* istanbul ignore next */ + // eslint-disable-next-line @typescript-eslint/explicit-function-return-type + const getStorePlugins = async () => { + let plugins = await new PluginHelper().fetchStore(); + const installIds = (await new PluginHelper().fetchInstalled()).map( + (plugin: any) => plugin.id + ); + plugins = plugins.map((plugin: any) => { + plugin.installed = installIds.includes(plugin.id); + return plugin; + }); + store.dispatch({ type: 'UPDATE_STORE', payload: plugins }); + }; + + /* istanbul ignore next */ + const getInstalledPlugins: () => any = () => { + setDataList(data); + }; + // const getAdvertisements: () => any = ()=> { + // return + // } + + /* istanbul ignore next */ + const updateLinks = async (links: any[]): Promise => { + store.dispatch({ type: 'UPDATE_P_TARGETS', payload: links }); + }; + // /* istanbul ignore next */ + const pluginModified = (): void => { + return getInstalledPlugins(); + // .then((installedPlugins) => { + // getStorePlugins(); + // return installedPlugins; + // }); + }; + + const updateSelectedTab = (tab: any): void => { + setIsStore(tab === 'activeAds'); + isStore ? getStorePlugins() : getInstalledPlugins(); + }; + + const filterChange = (ev: any): void => { + setShowEnabled(ev.target.value === 'enabled'); + }; + + /* istanbul ignore next */ + if (loading) { + return ( + <> +
    + + ); + } + + return ( + <> + + + +
    +

    {t('pHeading')}

    + + + + + {data2?.getAdvertisements + .filter((ad: any) => ad.orgId == currentOrgId) + .filter((ad: any) => new Date(ad.endDate) > new Date()) + .length == 0 ? ( +

    {t('pMessage')}

    // eslint-disable-line + ) : ( + data2?.getAdvertisements + .filter((ad: any) => ad.orgId == currentOrgId) + .filter((ad: any) => new Date(ad.endDate) > new Date()) + .map( + ( + ad: { + _id: string; + name: string | undefined; + type: string | undefined; + orgId: string; + link: string; + endDate: Date; + startDate: Date; + }, + i: React.Key | null | undefined + ): JSX.Element => ( + + ) + ) + )} +
    + + {data2?.getAdvertisements + .filter((ad: any) => ad.orgId == currentOrgId) + .filter((ad: any) => new Date(ad.endDate) < new Date()) + .length == 0 ? ( +

    {t('pMessage')}

    // eslint-disable-line + ) : ( + data2?.getAdvertisements + .filter((ad: any) => ad.orgId == currentOrgId) + .filter((ad: any) => new Date(ad.endDate) < new Date()) + .map( + ( + ad: { + _id: string; + name: string | undefined; + type: string | undefined; + orgId: string; + link: string; + endDate: Date; + startDate: Date; + }, + i: React.Key | null | undefined + ): JSX.Element => ( + + ) + ) + )} +
    +
    +
    + +
    +
    + + ); +} + +advertisements.defaultProps = {}; + +advertisements.propTypes = {}; diff --git a/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.module.css b/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.module.css new file mode 100644 index 0000000000..1f1ea89996 --- /dev/null +++ b/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.module.css @@ -0,0 +1,20 @@ +.entrytoggle { + margin: 24px 24px 0 auto; + width: fit-content; +} + +.entryaction { + margin-left: auto; + display: flex !important; + align-items: center; +} + +.entryaction i { + margin-right: 8px; +} + +.entryaction .spinner-grow { + height: 1rem; + width: 1rem; + margin-right: 8px; +} diff --git a/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.test.tsx b/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.test.tsx new file mode 100644 index 0000000000..896c61e5e1 --- /dev/null +++ b/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.test.tsx @@ -0,0 +1,60 @@ +import React from 'react'; +import { render } from '@testing-library/react'; + +import { + ApolloClient, + ApolloProvider, + InMemoryCache, + ApolloLink, + HttpLink, +} from '@apollo/client'; + +import type { NormalizedCacheObject } from '@apollo/client'; +import { BrowserRouter } from 'react-router-dom'; +import AdvertisementEntry from './AdvertisementEntry'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import { BACKEND_URL } from 'Constant/constant'; +import i18nForTest from 'utils/i18nForTest'; +import { I18nextProvider } from 'react-i18next'; + +const httpLink = new HttpLink({ + uri: BACKEND_URL, + headers: { + authorization: 'Bearer ' + localStorage.getItem('token') || '', + }, +}); + +const client: ApolloClient = new ApolloClient({ + cache: new InMemoryCache(), + link: ApolloLink.from([httpLink]), +}); +describe('Testing Advertisement Entry Component', () => { + test('Temporary test for Advertisement Entry', () => { + const { getByTestId, getAllByText } = render( + + + + + { + + } + + + + + ); + expect(getByTestId('AdEntry')).toBeInTheDocument(); + expect(getAllByText('POPUP')[0]).toBeInTheDocument(); + expect(getAllByText('Advert1')[0]).toBeInTheDocument(); + }); +}); diff --git a/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.tsx b/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.tsx new file mode 100644 index 0000000000..a98275e646 --- /dev/null +++ b/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.tsx @@ -0,0 +1,103 @@ +import React, { useState } from 'react'; +import PropTypes from 'prop-types'; +import styles from './AdvertisementEntry.module.css'; +import { Button, Card, Col, Row, Spinner } from 'react-bootstrap'; +import { DELETE_ADVERTISEMENT_BY_ID } from 'GraphQl/Mutations/mutations'; +import { useMutation } from '@apollo/client'; +import { useTranslation } from 'react-i18next'; +interface InterfaceAddOnEntryProps { + id: string; + name: string; + link: string; + type: string; + orgId: string; + startDate: Date; + endDate: Date; +} +function advertisementEntry({ + id, + name, + type, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + orgId, + link, + endDate, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + startDate, +}: InterfaceAddOnEntryProps): JSX.Element { + const { t } = useTranslation('translation', { keyPrefix: 'advertisement' }); + const [buttonLoading, setButtonLoading] = useState(false); + const [deleteAdById] = useMutation(DELETE_ADVERTISEMENT_BY_ID); + + const onDelete = async (): Promise => { + setButtonLoading(true); + await deleteAdById({ + variables: { + id: id.toString(), + }, + }); + setButtonLoading(false); + }; + return ( + <> + + {Array.from({ length: 1 }).map((_, idx) => ( + + + + + {name} + Ends on {endDate?.toDateString()} + + {type} + + {link} + + + + + ))} + +
    + + ); +} + +advertisementEntry.propTypes = { + name: PropTypes.string, + type: PropTypes.string, + orgId: PropTypes.string, + link: PropTypes.string, + endDate: PropTypes.instanceOf(Date), + startDate: PropTypes.instanceOf(Date), +}; + +advertisementEntry.defaultProps = { + name: '', + type: '', + orgId: '', + link: '', + endDate: new Date(), + startDate: new Date(), +}; +export default advertisementEntry; diff --git a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.module.css b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.module.css new file mode 100644 index 0000000000..c122d386fa --- /dev/null +++ b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.module.css @@ -0,0 +1,9 @@ +.modalbtn { + display: flex !important; + margin-left: auto; + align-items: center; +} + +.modalbtn i { + margin-right: 8px; +} diff --git a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.test.tsx b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.test.tsx new file mode 100644 index 0000000000..3bf5cb9792 --- /dev/null +++ b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.test.tsx @@ -0,0 +1,137 @@ +import React from 'react'; +import { render, fireEvent, waitFor } from '@testing-library/react'; + +import { + ApolloClient, + ApolloProvider, + InMemoryCache, + ApolloLink, + HttpLink, +} from '@apollo/client'; + +import type { NormalizedCacheObject } from '@apollo/client'; +import { BrowserRouter } from 'react-router-dom'; +import AdvertisementRegister from './AdvertisementRegister'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import { BACKEND_URL } from 'Constant/constant'; +import i18nForTest from 'utils/i18nForTest'; +import { I18nextProvider } from 'react-i18next'; +import i18n from 'utils/i18nForTest'; + +const httpLink = new HttpLink({ + uri: BACKEND_URL, + headers: { + authorization: 'Bearer ' + localStorage.getItem('token') || '', + }, +}); + +const client: ApolloClient = new ApolloClient({ + cache: new InMemoryCache(), + link: ApolloLink.from([httpLink]), +}); + +const translations = JSON.parse( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-non-null-asserted-optional-chain + JSON.stringify(i18n.getDataByLanguage('en')?.translation.advertisement!) +); + +describe('Testing Advertisement Register Component', () => { + test('AdvertismentRegister component loads correctly', async () => { + const { getByText } = render( + + + + + { + + } + + + + + ); + await waitFor(() => { + expect(getByText(translations.addNew)).toBeInTheDocument(); + }); + }); + test('opens and closes modals on button click', async () => { + const { getByText, queryByText } = render( + + + + + { + + } + + + + + ); + await waitFor(() => { + fireEvent.click(getByText(translations.addNew)); + expect(queryByText(translations.RClose)).toBeInTheDocument(); + + fireEvent.click(getByText(translations.RClose)); + expect(queryByText(translations.close)).not.toBeInTheDocument(); + }); + }); + test('submits the form and shows success toast on successful advertisement creation', async () => { + const { getByText, getByLabelText } = render( + + + + + { + + } + + + + + ); + await waitFor(() => { + fireEvent.click(getByText(translations.addNew)); + + fireEvent.change(getByLabelText(translations.Rname), { + target: { value: 'Test Advertisement' }, + }); + fireEvent.change(getByLabelText(translations.Rlink), { + target: { value: 'http://example.com' }, + }); + fireEvent.change(getByLabelText(translations.Rtype), { + target: { value: 'BANNER' }, + }); + fireEvent.change(getByLabelText(translations.RstartDate), { + target: { value: '2023-01-01' }, + }); + fireEvent.change(getByLabelText(translations.RendDate), { + target: { value: '2023-02-01' }, + }); + + fireEvent.click(getByText(translations.register)); + }); + }); +}); diff --git a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.tsx b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.tsx new file mode 100644 index 0000000000..e205d50598 --- /dev/null +++ b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.tsx @@ -0,0 +1,207 @@ +import React, { useState } from 'react'; +import PropTypes from 'prop-types'; +import styles from './AdvertisementRegister.module.css'; +import { Button, Form, Modal } from 'react-bootstrap'; +import { useMutation } from '@apollo/client'; +import { ADD_ADVERTISEMENT_MUTATION } from 'GraphQl/Mutations/mutations'; +import { useTranslation } from 'react-i18next'; +import { toast } from 'react-toastify'; +import dayjs from 'dayjs'; + +interface InterfaceAddOnRegisterProps { + id?: string; // OrgId + createdBy?: string; // User +} +interface InterfaceFormStateTypes { + name: string; + link: string; + type: string; + startDate: Date; + endDate: Date; + orgId: string; +} +// eslint-disable-next-line @typescript-eslint/no-unused-vars +function advertisementRegister({ + /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ + createdBy, +}: InterfaceAddOnRegisterProps): JSX.Element { + const { t } = useTranslation('translation', { keyPrefix: 'advertisement' }); + + const [show, setShow] = useState(false); + + const handleClose = (): void => setShow(false); + const handleShow = (): void => setShow(true); + const [create] = useMutation(ADD_ADVERTISEMENT_MUTATION); + + //getting orgId from URL + const currentOrg = window.location.href.split('/id=')[1] + ''; + const [formState, setFormState] = useState({ + name: '', + link: '', + type: 'BANNER', + startDate: new Date(), + endDate: new Date(), + orgId: currentOrg, + }); + const handleRegister = async (): Promise => { + try { + console.log('At handle register', formState); + const { data } = await create({ + variables: { + orgId: currentOrg, + name: formState.name as string, + link: formState.link as string, + type: formState.type as string, + startDate: dayjs(formState.startDate).format('YYYY-MM-DD'), + endDate: dayjs(formState.endDate).format('YYYY-MM-DD'), + }, + }); + + if (data) { + toast.success('Advertisement created successfully'); + setTimeout(() => { + window.location.reload(); + }, 2000); + } + } catch (error) { + console.log('error occured', error); + } + }; + return ( + <> + + + + + {t('RClose')} + + +
    + + {t('Rname')} + { + setFormState({ + ...formState, + name: e.target.value, + }); + }} + /> + + + {t('Rlink')} + { + setFormState({ + ...formState, + link: e.target.value, + }); + }} + /> + + + {t('Rtype')} + { + setFormState({ + ...formState, + type: e.target.value, + }); + console.log(e.target, e.target.value, typeof e.target.value); + }} + > + + + + + + + {t('RstartDate')} + { + setFormState({ + ...formState, + startDate: new Date(e.target.value), + }); + }} + /> + + + + {t('RendDate')} + { + setFormState({ + ...formState, + endDate: new Date(e.target.value), + }); + }} + /> + +
    +
    + + + + +
    + + ); +} + +advertisementRegister.defaultProps = { + name: '', + link: '', + type: 'BANNER', + startDate: new Date(), + endDate: new Date(), + orgId: '', +}; + +advertisementRegister.propTypes = { + name: PropTypes.string, + link: PropTypes.string, + type: PropTypes.string, + startDate: PropTypes.instanceOf(Date), + endDate: PropTypes.instanceOf(Date), + orgId: PropTypes.string, +}; + +export default advertisementRegister; diff --git a/src/components/ChangeLanguageDropdown/ChangeLanguageDropDown.tsx b/src/components/ChangeLanguageDropdown/ChangeLanguageDropDown.tsx new file mode 100644 index 0000000000..8f4fd945ed --- /dev/null +++ b/src/components/ChangeLanguageDropdown/ChangeLanguageDropDown.tsx @@ -0,0 +1,65 @@ +import React from 'react'; +import { Dropdown } from 'react-bootstrap'; +import i18next from 'i18next'; +import { languages } from 'utils/languages'; +import cookies from 'js-cookie'; + +interface InterfaceChangeLanguageDropDownProps { + parentContainerStyle?: string; + btnStyle?: string; + btnTextStyle?: string; +} + +export const changeLanguage = async (languageCode: string): Promise => { + await i18next.changeLanguage(languageCode); +}; + +const ChangeLanguageDropDown = ( + props: InterfaceChangeLanguageDropDownProps +): JSX.Element => { + const currentLanguageCode = cookies.get('i18next') || 'en'; + + return ( + + + {languages.map((language, index: number) => ( + + {currentLanguageCode === language.code ? ( + + + {language.name} + + ) : null} + + ))} + + + {languages.map((language, index: number) => ( + => changeLanguage(language.code)} + disabled={currentLanguageCode === language.code} + data-testid={`change-language-btn-${language.code}`} + > + + {language.name} + + ))} + + + ); +}; + +export default ChangeLanguageDropDown; diff --git a/src/components/ChangeLanguageDropdown/ChangeLanguageDropdown.test.tsx b/src/components/ChangeLanguageDropdown/ChangeLanguageDropdown.test.tsx new file mode 100644 index 0000000000..79209107fa --- /dev/null +++ b/src/components/ChangeLanguageDropdown/ChangeLanguageDropdown.test.tsx @@ -0,0 +1,106 @@ +import React from 'react'; +import { act, render } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; +import { BrowserRouter } from 'react-router-dom'; +import i18nForTest from 'utils/i18nForTest'; +import { languages } from 'utils/languages'; +import ChangeLanguageDropDown from './ChangeLanguageDropDown'; +import cookies from 'js-cookie'; + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Testing Change Language Dropdown', () => { + test('Component Should be rendered properly', async () => { + const { getByTestId } = render( + + + + + + ); + + expect(getByTestId('language-dropdown-container')).toBeInTheDocument(); + expect(getByTestId('language-dropdown-btn')).toBeInTheDocument(); + expect(getByTestId('dropdown-btn-0')).toBeInTheDocument(); + + getByTestId('language-dropdown-container').className.includes(''); + getByTestId('language-dropdown-btn').className.includes(''); + getByTestId('dropdown-btn-0').className.includes(''); + + userEvent.click(getByTestId('dropdown-btn-0')); + await wait(); + + languages.map((language) => { + expect( + getByTestId(`change-language-btn-${language.code}`) + ).toBeInTheDocument(); + }); + }); + + test('Component Should accept props properly', async () => { + const props = { + parentContainerStyle: 'parentContainerStyle', + btnStyle: 'btnStyle', + btnTextStyle: 'btnTextStyle', + }; + const { getByTestId } = render( + + + + + + ); + getByTestId('language-dropdown-container').className.includes( + props.parentContainerStyle + ); + getByTestId('language-dropdown-btn').className.includes(props.btnStyle); + getByTestId('dropdown-btn-0').className.includes(props.btnTextStyle); + }); + + test('Testing when language cookie is not set', async () => { + Object.defineProperty(window.document, 'cookie', { + writable: true, + value: 'i18next=', + }); + + render( + + + + ); + + await wait(); + expect(cookies.get('i18next')).toBe(''); + }); + + test('Testing change language functionality', async () => { + Object.defineProperty(window.document, 'cookie', { + writable: true, + value: 'i18next=en', + }); + + const { getByTestId } = render( + + + + ); + + userEvent.click(getByTestId('language-dropdown-btn')); + await wait(); + languages.map((language) => { + const changeLanguageBtn = getByTestId( + `change-language-btn-${language.code}` + ); + expect(changeLanguageBtn).toBeInTheDocument(); + userEvent.click(changeLanguageBtn); + expect(cookies.get('i18next')).toBe(language.code); + }); + }); +}); diff --git a/src/components/CheckIn/CheckInModal.module.css b/src/components/CheckIn/CheckInModal.module.css new file mode 100644 index 0000000000..0f78d81c01 --- /dev/null +++ b/src/components/CheckIn/CheckInModal.module.css @@ -0,0 +1,43 @@ +.loader, +.loader:after { + border-radius: 50%; + width: 10em; + height: 10em; +} +.loader { + margin: 60px auto; + margin-top: 35vh !important; + font-size: 10px; + position: relative; + text-indent: -9999em; + border-top: 1.1em solid rgba(255, 255, 255, 0.2); + border-right: 1.1em solid rgba(255, 255, 255, 0.2); + border-bottom: 1.1em solid rgba(255, 255, 255, 0.2); + border-left: 1.1em solid #febc59; + -webkit-transform: translateZ(0); + -ms-transform: translateZ(0); + transform: translateZ(0); + -webkit-animation: load8 1.1s infinite linear; + animation: load8 1.1s infinite linear; +} + +@-webkit-keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} +@keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} diff --git a/src/components/CheckIn/CheckInModal.test.tsx b/src/components/CheckIn/CheckInModal.test.tsx new file mode 100644 index 0000000000..80fe9dd918 --- /dev/null +++ b/src/components/CheckIn/CheckInModal.test.tsx @@ -0,0 +1,58 @@ +import React from 'react'; +import { fireEvent, render, waitFor } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { CheckInModal } from './CheckInModal'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; +import { ToastContainer } from 'react-toastify'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { checkInQueryMock } from './mocks'; +import { StaticMockLink } from 'utils/StaticMockLink'; + +const link = new StaticMockLink(checkInQueryMock, true); + +describe('Testing Check In Attendees Modal', () => { + const props = { + show: true, + eventId: 'event123', + handleClose: jest.fn(), + }; + + test('The modal should be rendered, and all the fetched users should be shown properly and user filtering should work', async () => { + const { queryByText, queryByLabelText } = render( + + + + + + + + + + + + + ); + + await waitFor(() => + expect(queryByText('Event Check In Management')).toBeInTheDocument() + ); + + await waitFor(() => expect(queryByText('John Doe')).toBeInTheDocument()); + await waitFor(() => expect(queryByText('John2 Doe2')).toBeInTheDocument()); + + // Tetst filtering of users + fireEvent.change(queryByLabelText('Search Attendees') as Element, { + target: { value: 'John Doe' }, + }); + + await waitFor(() => expect(queryByText('John Doe')).toBeInTheDocument()); + await waitFor(() => + expect(queryByText('John2 Doe2')).not.toBeInTheDocument() + ); + }); +}); diff --git a/src/components/CheckIn/CheckInModal.tsx b/src/components/CheckIn/CheckInModal.tsx new file mode 100644 index 0000000000..3f15824ecd --- /dev/null +++ b/src/components/CheckIn/CheckInModal.tsx @@ -0,0 +1,121 @@ +import React, { useState, useEffect } from 'react'; +import { Modal } from 'react-bootstrap'; +import { useQuery } from '@apollo/client'; +import { EVENT_CHECKINS } from 'GraphQl/Queries/Queries'; +import styles from 'components/CheckIn/CheckInModal.module.css'; +import { TableRow } from './TableRow'; +import type { + InterfaceAttendeeCheckIn, + InterfaceModalProp, + InterfaceTableData, +} from './types'; +import type { GridColDef, GridRowHeightReturnValue } from '@mui/x-data-grid'; +import { DataGrid } from '@mui/x-data-grid'; +import TextField from '@mui/material/TextField'; + +export const CheckInModal = (props: InterfaceModalProp): JSX.Element => { + const [tableData, setTableData] = useState([]); + + const [userFilterQuery, setUserFilterQuery] = useState(''); + const [filterQueryModel, setFilterQueryModel] = useState({ + items: [{ field: 'userName', operator: 'contains', value: '' }], + }); + + const { + data: checkInData, + loading: checkInLoading, + refetch: checkInRefetch, + } = useQuery(EVENT_CHECKINS, { + variables: { id: props.eventId }, + }); + + useEffect(() => { + checkInRefetch(); + if (checkInLoading) setTableData([]); + else + setTableData( + checkInData.event.attendeesCheckInStatus.map( + (checkIn: InterfaceAttendeeCheckIn) => ({ + userName: `${checkIn.user.firstName} ${checkIn.user.lastName}`, + id: checkIn._id, + checkInData: { + id: checkIn._id, + name: `${checkIn.user.firstName} ${checkIn.user.lastName}`, + userId: checkIn.user._id, + checkIn: checkIn.checkIn, + eventId: props.eventId, + }, + }) + ) + ); + }, [checkInData, props.eventId, checkInLoading]); + + const columns: GridColDef[] = [ + { field: 'userName', headerName: 'User', width: 300 }, + { + field: 'checkInData', + headerName: 'Check In Status', + width: 400, + renderCell: (props) => ( + + ), + }, + ]; + + // Render the loading screen + if (checkInLoading) { + return ( + <> +
    + + ); + } + return ( + <> + + + + Event Check In Management + + + +
    + { + setUserFilterQuery(e.target.value); + setFilterQueryModel({ + items: [ + { + field: 'userName', + operator: 'contains', + value: e.target.value, + }, + ], + }); + }} + fullWidth + /> +
    +
    + 'auto'} + columns={columns} + filterModel={filterQueryModel} + /> +
    +
    +
    + + ); +}; diff --git a/src/components/CheckIn/CheckInWrapper.module.css b/src/components/CheckIn/CheckInWrapper.module.css new file mode 100644 index 0000000000..f5f42546c3 --- /dev/null +++ b/src/components/CheckIn/CheckInWrapper.module.css @@ -0,0 +1,13 @@ +button .iconWrapper { + width: 32px; + padding-right: 4px; + margin-right: 4px; + transform: translateY(4px); +} + +button .iconWrapperSm { + width: 32px; + display: flex; + justify-content: center; + align-items: center; +} diff --git a/src/components/CheckIn/CheckInWrapper.test.tsx b/src/components/CheckIn/CheckInWrapper.test.tsx new file mode 100644 index 0000000000..9cb7fef4ba --- /dev/null +++ b/src/components/CheckIn/CheckInWrapper.test.tsx @@ -0,0 +1,58 @@ +import React from 'react'; +import { fireEvent, render, waitFor } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { CheckInWrapper } from './CheckInWrapper'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; +import { ToastContainer } from 'react-toastify'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { checkInQueryMock } from './mocks'; +import { StaticMockLink } from 'utils/StaticMockLink'; + +const link = new StaticMockLink(checkInQueryMock, true); + +describe('Testing CheckIn Wrapper', () => { + const props = { + eventId: 'event123', + }; + + test('The button to open and close the modal should work properly', async () => { + const { queryByText } = render( + + + + + + + + + + + + + ); + + // Open the modal + fireEvent.click(queryByText('Check In Registrants') as Element); + + await waitFor(() => + expect(queryByText('Event Check In Management')).toBeInTheDocument() + ); + + /* + TODO + The following test of closing the modal should be uncommented when the memory leak issue of MUI Data Grid is fixed. + + It will consequently ensure 100% coverage of the file. + */ + // Close the modal + // fireEvent.click(queryByRole('button', { name: /close/i }) as HTMLElement); + // await waitFor(() => + // expect(queryByText('Event Check In Management')).not.toBeInTheDocument() + // ); + }); +}); diff --git a/src/components/CheckIn/CheckInWrapper.tsx b/src/components/CheckIn/CheckInWrapper.tsx new file mode 100644 index 0000000000..9a87a12ed3 --- /dev/null +++ b/src/components/CheckIn/CheckInWrapper.tsx @@ -0,0 +1,41 @@ +import React, { useState } from 'react'; +import { CheckInModal } from './CheckInModal'; +import { Button } from 'react-bootstrap'; +import IconComponent from 'components/IconComponent/IconComponent'; +import styles from './CheckInWrapper.module.css'; + +type PropType = { + eventId: string; +}; + +export const CheckInWrapper = (props: PropType): JSX.Element => { + const [showModal, setShowModal] = useState(false); + + return ( + <> + + {showModal && ( + setShowModal(false)} + eventId={props.eventId} + /> + )} + + ); +}; diff --git a/src/components/CheckIn/TableRow.test.tsx b/src/components/CheckIn/TableRow.test.tsx new file mode 100644 index 0000000000..b8ab48f397 --- /dev/null +++ b/src/components/CheckIn/TableRow.test.tsx @@ -0,0 +1,141 @@ +import React from 'react'; +import { fireEvent, render, waitFor } from '@testing-library/react'; +import { TableRow } from './TableRow'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; +import { ToastContainer } from 'react-toastify'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { MockedProvider } from '@apollo/react-testing'; +import { checkInMutationSuccess, checkInMutationUnsuccess } from './mocks'; + +describe('Testing Table Row for CheckIn Table', () => { + test('If the user in not checked in, button to check in should be displayed, and the user should be able to check in succesfully', async () => { + const props = { + data: { + id: `123`, + name: `John Doe`, + userId: `user123`, + checkIn: null, + eventId: `event123`, + }, + refetch: jest.fn(), + }; + + const { queryByText } = render( + + + + + + + + + + + + + ); + + await waitFor(() => expect(queryByText('Check In')).toBeInTheDocument()); + + fireEvent.click(queryByText('Check In') as Element); + + await waitFor(() => + expect(queryByText('Checked in successfully!')).toBeInTheDocument() + ); + }); + + test('If the user in checked in, option to download tag should be shown', async () => { + const props = { + data: { + id: `123`, + name: `John Doe`, + userId: `user123`, + checkIn: { + _id: '123', + time: '12:00:00', + allotedRoom: '', + allotedSeat: '', + }, + eventId: `event123`, + }, + refetch: jest.fn(), + }; + + const { queryByText } = render( + + + + + + + + + + + + + ); + + // Stubbing functions required by the @pdfme to show pdfs + global.URL.createObjectURL = jest.fn(); + global.window.open = jest.fn(); + + await waitFor(() => expect(queryByText('Checked In')).toBeInTheDocument()); + await waitFor(() => + expect(queryByText('Download Tag')).toBeInTheDocument() + ); + + fireEvent.click(queryByText('Download Tag') as Element); + + await waitFor(() => + expect(queryByText('Generating pdf...')).toBeInTheDocument() + ); + await waitFor(() => { + expect(queryByText('PDF generated successfully!')).toBeInTheDocument(); + }); + }); + + test('Upon failing of check in mutation, the appropiate error message should be shown', async () => { + const props = { + data: { + id: `123`, + name: `John Doe`, + userId: `user123`, + checkIn: null, + eventId: `event123`, + }, + refetch: jest.fn(), + }; + + const { queryByText } = render( + + + + + + + + + + + + + ); + + await waitFor(() => expect(queryByText('Check In')).toBeInTheDocument()); + + fireEvent.click(queryByText('Check In') as Element); + + await waitFor(() => + expect( + queryByText('There was an error in checking in!') + ).toBeInTheDocument() + ); + await waitFor(() => expect(queryByText('Oops')).toBeInTheDocument()); + }); +}); diff --git a/src/components/CheckIn/TableRow.tsx b/src/components/CheckIn/TableRow.tsx new file mode 100644 index 0000000000..90e22deff0 --- /dev/null +++ b/src/components/CheckIn/TableRow.tsx @@ -0,0 +1,76 @@ +import React from 'react'; +import type { InterfaceTableCheckIn } from './types'; +import Button from '@mui/material/Button'; +import { useMutation } from '@apollo/client'; +import { MARK_CHECKIN } from 'GraphQl/Mutations/mutations'; +import { toast } from 'react-toastify'; +import { generate } from '@pdfme/generator'; +import { tagTemplate } from './tagTemplate'; + +export const TableRow = ({ + data, + refetch, +}: { + data: InterfaceTableCheckIn; + refetch: () => void; +}): JSX.Element => { + const [checkInMutation] = useMutation(MARK_CHECKIN); + + const markCheckIn = (): void => { + // Since the backend supports the storage of the alloted seat and the alloted room to the user, we pass the same as blank + // as we do not want to clutter the UI currently with the same (only provide the most basic of operations) + checkInMutation({ + variables: { + userId: data.userId, + eventId: data.eventId, + allotedSeat: '', + allotedRoom: '', + }, + }) + .then(() => { + toast.success('Checked in successfully!'); + refetch(); + }) + .catch((err) => { + toast.error('There was an error in checking in!'); + toast.error(err.message); + }); + }; + + const notify = (): Promise => + toast.promise(generateTag, { + pending: 'Generating pdf...', + success: 'PDF generated successfully!', + error: 'Error generating pdf!', + }); + const generateTag = async (): Promise => { + const inputs = [{ name: data.name }]; + const pdf = await generate({ template: tagTemplate, inputs }); + const blob = new Blob([pdf.buffer], { type: 'application/pdf' }); + window.open(URL.createObjectURL(blob)); + }; + + return ( + <> + {data.checkIn !== null ? ( +
    + + +
    + ) : ( + + )} + + ); +}; diff --git a/src/components/CheckIn/mocks.ts b/src/components/CheckIn/mocks.ts new file mode 100644 index 0000000000..b038e5ae7a --- /dev/null +++ b/src/components/CheckIn/mocks.ts @@ -0,0 +1,82 @@ +import { EVENT_CHECKINS } from 'GraphQl/Queries/Queries'; +import { MARK_CHECKIN } from 'GraphQl/Mutations/mutations'; +import type { InterfaceAttendeeQueryResponse } from './types'; + +const checkInQueryData: InterfaceAttendeeQueryResponse = { + event: { + _id: 'event123', + attendeesCheckInStatus: [ + { + _id: 'eventAttendee1', + user: { + _id: 'user1', + firstName: 'John', + lastName: 'Doe', + }, + checkIn: null, + }, + { + _id: 'eventAttendee2', + user: { + _id: 'user2', + firstName: 'John2', + lastName: 'Doe2', + }, + checkIn: { + _id: 'checkin1', + time: '08:00:00', + allotedRoom: 'Room 1', + allotedSeat: 'Seat 1', + }, + }, + ], + }, +}; + +export const checkInQueryMock = [ + { + request: { + query: EVENT_CHECKINS, + variables: { id: 'event123' }, + }, + result: { + data: checkInQueryData, + }, + }, +]; + +export const checkInMutationSuccess = [ + { + request: { + query: MARK_CHECKIN, + variables: { + userId: 'user123', + eventId: 'event123', + allotedSeat: '', + allotedRoom: '', + }, + }, + result: { + data: { + checkIn: { + _id: '123', + }, + }, + }, + }, +]; + +export const checkInMutationUnsuccess = [ + { + request: { + query: MARK_CHECKIN, + variables: { + userId: 'user123', + eventId: 'event123', + allotedSeat: '', + allotedRoom: '', + }, + }, + error: new Error('Oops'), + }, +]; diff --git a/src/components/CheckIn/tagTemplate.ts b/src/components/CheckIn/tagTemplate.ts new file mode 100644 index 0000000000..0af9eeeb15 --- /dev/null +++ b/src/components/CheckIn/tagTemplate.ts @@ -0,0 +1,22 @@ +import { Template } from '@pdfme/generator'; + +export const tagTemplate: Template = { + schemas: [ + { + name: { + type: 'text', + position: { x: 14.91, y: 27.03 }, + width: 58.55, + height: 5.67, + alignment: 'center', + fontSize: 16, + characterSpacing: 0, + lineHeight: 1, + fontName: 'Roboto', + fontColor: '#08780b', + }, + }, + ], + basePdf: + 'data:application/pdf;base64,JVBERi0xLjQKJfbk/N8KMSAwIG9iago8PAovVHlwZSAvQ2F0YWxvZwovVmVyc2lvbiAvMS40Ci9QYWdlcyAyIDAgUgovU3RydWN0VHJlZVJvb3QgMyAwIFIKL01hcmtJbmZvIDQgMCBSCi9MYW5nIChlbikKL1ZpZXdlclByZWZlcmVuY2VzIDUgMCBSCj4+CmVuZG9iago2IDAgb2JqCjw8Ci9DcmVhdG9yIChDYW52YSkKL1Byb2R1Y2VyIChDYW52YSkKL0NyZWF0aW9uRGF0ZSAoRDoyMDIzMDYyMDA3MjgxMyswMCcwMCcpCi9Nb2REYXRlIChEOjIwMjMwNjIwMDcyODEzKzAwJzAwJykKL0tleXdvcmRzIChEQUZjMjhYSXViTSxCQUUycS01WEdhaykKL0F1dGhvciAoRXNoYWFuIEFnZ2Fyd2FsKQovVGl0bGUgKEJsYW5rIE5hbWUgVGFnIGluIEVtZXJhbGQgTWludCBHcmVlbiBBc3BpcmF0aW9uYWwgRWxlZ2FuY2UgU3R5bGUpCj4+CmVuZG9iagoyIDAgb2JqCjw8Ci9UeXBlIC9QYWdlcwovS2lkcyBbNyAwIFJdCi9Db3VudCAxCj4+CmVuZG9iagozIDAgb2JqCjw8Ci9UeXBlIC9TdHJ1Y3RUcmVlUm9vdAovUGFyZW50VHJlZSA4IDAgUgovUGFyZW50VHJlZU5leHRLZXkgMQovSyBbOSAwIFJdCi9JRFRyZWUgMTAgMCBSCj4+CmVuZG9iago0IDAgb2JqCjw8Ci9NYXJrZWQgdHJ1ZQovU3VzcGVjdHMgZmFsc2UKPj4KZW5kb2JqCjUgMCBvYmoKPDwKL0Rpc3BsYXlEb2NUaXRsZSB0cnVlCj4+CmVuZG9iago3IDAgb2JqCjw8Ci9UeXBlIC9QYWdlCi9SZXNvdXJjZXMgMTEgMCBSCi9NZWRpYUJveCBbMC4wIDcuOTIwMDAyNSAyNTIuMCAxNTEuOTJdCi9Db250ZW50cyAxMiAwIFIKL1N0cnVjdFBhcmVudHMgMAovUGFyZW50IDIgMCBSCi9UYWJzIC9TCi9CbGVlZEJveCBbMC4wIDcuOTIwMDAyNSAyNTIuMCAxNTEuOTJdCi9UcmltQm94IFswLjAgNy45MjAwMDI1IDI1Mi4wIDE1MS45Ml0KL0Nyb3BCb3ggWzAuMCA3LjkyMDAwMjUgMjUyLjAgMTUxLjkyXQovUm90YXRlIDAKL0Fubm90cyBbXQo+PgplbmRvYmoKOCAwIG9iago8PAovTGltaXRzIFswIDBdCi9OdW1zIFswIFsxMyAwIFIgMTQgMCBSIDE1IDAgUiAxNiAwIFIgMTcgMCBSIDE4IDAgUiAxOSAwIFJdCl0KPj4KZW5kb2JqCjkgMCBvYmoKPDwKL1R5cGUgL1N0cnVjdEVsZW0KL1MgL0RvY3VtZW50Ci9MYW5nIChlbikKL1AgMyAwIFIKL0sgWzIwIDAgUl0KL0lEIChub2RlMDAwMDE3MzgpCj4+CmVuZG9iagoxMCAwIG9iago8PAovTmFtZXMgWyhub2RlMDAwMDE3MzgpIDkgMCBSIChub2RlMDAwMDE3MzkpIDEzIDAgUiAobm9kZTAwMDAxNzQwKSAyMCAwIFIgKG5vZGUwMDAwMTc0MSkgMjEgMCBSIChub2RlMDAwMDE3NDIpIDIyIDAgUgoobm9kZTAwMDAxNzQzKSAyMyAwIFIgKG5vZGUwMDAwMTc0NCkgMjQgMCBSIChub2RlMDAwMDE3NDUpIDI1IDAgUiAobm9kZTAwMDAxNzQ2KSAyNiAwIFIgKG5vZGUwMDAwMTc0NykgMjcgMCBSCihub2RlMDAwMDE3NjEpIDI4IDAgUiAobm9kZTAwMDAxNzYyKSAyOSAwIFIgKG5vZGUwMDAwMTc2MykgMzAgMCBSIChub2RlMDAwMDE3NjQpIDMxIDAgUiAobm9kZTAwMDAxNzY1KSAzMiAwIFIKKG5vZGUwMDAwMTc2NikgMzMgMCBSIChub2RlMDAwMDE3NjcpIDE0IDAgUiAobm9kZTAwMDAxNzY4KSAzNCAwIFIgKG5vZGUwMDAwMTc2OSkgMzUgMCBSIChub2RlMDAwMDE3NzApIDM2IDAgUgoobm9kZTAwMDAxNzcxKSAxNSAwIFIgKG5vZGUwMDAwMTc3MikgMzcgMCBSIChub2RlMDAwMDE3NzMpIDM4IDAgUiAobm9kZTAwMDAxNzc0KSAzOSAwIFIgKG5vZGUwMDAwMTc3NSkgMTYgMCBSCihub2RlMDAwMDE3NzYpIDE3IDAgUiAobm9kZTAwMDAxNzc3KSA0MCAwIFIgKG5vZGUwMDAwMTc3OCkgMTggMCBSIChub2Rl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Tm9uU3RydWN0Ci9QIDQwIDAgUgovSyBbNTMgMCBSXQovSUQgKG5vZGUwMDAwMTc3OCkKPj4KZW5kb2JqCjE5IDAgb2JqCjw8Ci9UeXBlIC9TdHJ1Y3RFbGVtCi9TIC9Ob25TdHJ1Y3QKL1AgNDQgMCBSCi9LIFs1NCAwIFJdCi9JRCAobm9kZTAwMDAxNzgzKQo+PgplbmRvYmoKMjAgMCBvYmoKPDwKL1R5cGUgL1N0cnVjdEVsZW0KL1MgL0RpdgovUCA5IDAgUgovSyBbMjEgMCBSXQovSUQgKG5vZGUwMDAwMTc0MCkKPj4KZW5kb2JqCjIxIDAgb2JqCjw8Ci9UeXBlIC9TdHJ1Y3RFbGVtCi9TIC9EaXYKL1AgMjAgMCBSCi9LIFsyMiAwIFJdCi9JRCAobm9kZTAwMDAxNzQxKQo+PgplbmRvYmoKMjIgMCBvYmoKPDwKL1R5cGUgL1N0cnVjdEVsZW0KL1MgL0RpdgovUCAyMSAwIFIKL0sgWzIzIDAgUl0KL0lEIChub2RlMDAwMDE3NDIpCj4+CmVuZG9iagoyMyAwIG9iago8PAovVHlwZSAvU3RydWN0RWxlbQovUyAvRGl2Ci9QIDIyIDAgUgovSyBbMjQgMCBSXQovSUQgKG5vZGUwMDAwMTc0MykKPj4KZW5kb2JqCjI0IDAgb2JqCjw8Ci9UeXBlIC9TdHJ1Y3RFbGVtCi9TIC9EaXYKL1AgMjMgMCBSCi9LIFsyNSAwIFJdCi9JRCAobm9kZTAwMDAxNzQ0KQo+PgplbmRvYmoKMjUgMCBvYmoKPDwKL1R5cGUgL1N0cnVjdEVsZW0KL1MgL0RpdgovUCAyNCAwIFIKL0sgWzI2IDAgUl0KL0lEIChub2RlMDAwMDE3NDUpCj4+CmVuZG9iagoyNiAwIG9iago8PAovVHlwZSAvU3RydWN0RWxlbQovUyAvRGl2Ci9QIDI1IDAgUgovSyBbMjcgMCBSXQovSUQgKG5vZGUwMDAwMTc0NikKPj4KZW5kb2JqCjI3IDAgb2JqCjw8Ci9UeXBlIC9TdHJ1Y3RFbGVtCi9TIC9EaXYKL1AgMjYgMCBSCi9LIFsyOCAwIFIgMzEgMCBSIDM0IDAgUiAzNyAwIFIgNDEgMCBSXQovSUQgKG5vZGUwMDAwMTc0NykKPj4KZW5kb2JqCjI4IDAgb2JqCjw8Ci9UeXBlIC9TdHJ1Y3RFbGVtCi9TIC9EaXYKL1AgMjcgMCBSCi9LIFsyOSAwIFJdCi9JRCAobm9kZTAwMDAxNzYxKQo+PgplbmRvYmoKMjkgMCBvYmoKPDwKL1R5cGUgL1N0cnVjdEVsZW0KL1MgL0RpdgovUCAyOCAwIFIKL0sgWzMwIDAgUl0KL0lEIChub2RlMDAwMDE3NjIpCj4+CmVuZG9iagozMCAwIG9iago8PAovVHlwZSAvU3RydWN0RWxlbQovUyAvRGl2Ci9QIDI5IDAgUgovSyBbMTMgMCBSXQovSUQgKG5vZGUwMDAwMTc2MykKPj4KZW5kb2JqCjMxIDAgb2JqCjw8Ci9UeXBlIC9TdHJ1Y3RFbGVtCi9TIC9EaXYKL1AgMjcgMCBSCi9LIFszMiAwIFJdCi9JRCAobm9kZTAwMDAxNzY0KQo+PgplbmRvYmoKMzIgMCBvYmoKPDwKL1R5cGUgL1N0cnVjdEVsZW0KL1MgL0RpdgovUCAzMSAwIFIKL0sgWzMzIDAgUl0KL0lEIChub2RlMDAwMDE3NjUpCj4+CmVuZG9iagozMyAwIG9iago8PAovVHlwZSAvU3RydWN0RWxlbQovUyAvUAovUCAzMiAwIFIKL0sgWzE0IDAgUl0KL0lEIChub2RlMDAwMDE3NjYpCj4+CmVuZG9iagozNCAwIG9iago8PAovVHlwZSAvU3RydWN0RWxlbQovUyAvRGl2Ci9QIDI3IDAgUgovSyBbMzUgMCBSXQovSUQgKG5vZGUwMDAwMTc2OCkKPj4KZW5kb2JqCjM1IDAgb2JqCjw8Ci9UeXBlIC9TdHJ1Y3RFbGVtCi9TIC9EaXYKL1AgMzQgMCBSCi9LIFszNiAwIFJdCi9JRCAobm9kZTAwMDAxNzY5KQo+PgplbmRvYmoKMzYgMCBvYmoKPDwKL1R5cGUgL1N0cnVjdEVsZW0KL1MgL1AKL1AgMzUgMCBSCi9LIFsxNSAwIFJdCi9JRCAobm9kZTAwMDAxNzcwKQo+PgplbmRvYmoKMzcgMCBvYmoKPDwKL1R5cGUgL1N0cnVjdEVsZW0KL1MgL0RpdgovUCAyNyAwIFIKL0sgWzM4IDAgUl0KL0lEIChub2RlMDAwMDE3NzIpCj4+CmVuZG9iagozOCAwIG9iago8PAovVHlwZSAvU3RydWN0RWxlbQovUyAvRGl2Ci9QIDM3IDAgUgovSyBbMzkgMCBSIDQwIDAgUl0KL0lEIChub2RlMDAwMDE3NzMpCj4+CmVuZG9iagozOSAwIG9iago8PAovVHlwZSAvU3RydWN0RWxlbQovUyAvUAovUCAzOCAwIFIKL0sgWzE2IDAgUiAxNyAwIFJdCi9JRCAobm9kZTAwMDAxNzc0KQo+PgplbmRvYmoKNDAgMCBvYmoKPDwKL1R5cGUgL1N0cnVjdEVsZW0KL1MgL1AKL1AgMzggMCBSCi9LIFsxOCAwIFJdCi9JRCAobm9kZTAwMDAxNzc3KQo+PgplbmRvYmoKNDEgMCBvYmoKPDwKL1R5cGUgL1N0cnVjdEVsZW0KL1MgL0RpdgovUCAyNyAwIFIKL0sgWzQyIDAgUl0KL0lEIChub2RlMDAwMDE3NzkpCj4+CmVuZG9iago0MiAwIG9iago8PAovVHlwZSAvU3RydWN0RWxlbQovUyAvRGl2Ci9QIDQxIDAgUgovSyBbNDMgMCBSXQovSUQgKG5vZGUwMDAwMTc4MCkKPj4KZW5kb2JqCjQzIDAgb2JqCjw8Ci9UeXBlIC9TdHJ1Y3RFbGVtCi9TIC9EaXYKL1AgNDIgMCBSCi9LIFs0NCAwIFJdCi9JRCAobm9kZTAwMDAxNzgxKQo+PgplbmRvYmoKNDQgMCBvYmoKPDwKL1R5cGUgL1N0cnVjdEVsZW0KL1MgL1AKL1AgNDMgMCBSCi9LIFsxOSAwIFJdCi9JRCAobm9kZTAwMDAxNzgyKQo+PgplbmRvYmoKNDUgMCBvYmoKPDwKL0czIDU1IDAgUgovRzQgNTYgMCBSCj4+CmVuZG9iago0NiAwIG9iago8PAovTGVuZ3RoIDMwMTg4Ci9UeXBlIC9YT2JqZWN0Ci9TdWJ0eXBlIC9JbWFnZQovV2lkdGggMzQ3Ci9IZWlnaHQgMjMzCi9Db2xvclNwYWNlIC9EZXZpY2VSR0IKL1NNYXNrIDU3IDAgUgovQml0c1BlckNvbXBvbmVudCA4Ci9GaWx0ZXIgL0ZsYXRlRGVjb2RlCj4+CnN0cmVhbQ0KeJzsfQl4FNeVbgmpN6GuajDYY1tIIpPJm8dbJhkyb5LJTIaZJCaYRRvCwTEOjmNi42DAZjGLpNbGamOMgVgJGGMMxo3QvqKltQsB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arVJSZxajbW01KrRlKs9h/BjZkdpqcM8035UbS3VWNRqi6bMzXLBceLFI+QgnL9QSjQ3F284UObxlJW5XMTrMpvcbpMZXofoP5F+JXQNCmVuZHN0cmVhbQplbmRvYmoKeHJlZgowIDY0CjAwMDAwMDAwMDAgNjU1MzUgZg0KMDAwMDAwMDAxNSAwMDAwMCBuDQowMDAwMDAwNDE5IDAwMDAwIG4NCjAwMDAwMDA0NzYgMDAwMDAgbg0KMDAwMDAwMDU4NCAwMDAwMCBuDQowMDAwMDAwNjM0IDAwMDAwIG4NCjAwMDAwMDAxNTIgMDAwMDAgbg0KMDAwMDAwMDY3NyAwMDAwMCBuDQowMDAwMDAwOTYwIDAwMDAwIG4NCjAwMDAwMDEwNTcgMDAwMDAgbg0KMDAwMDAwMTE2MCAwMDAwMCBuDQowMDAwMDAxOTE2IDAwMDAwIG4NCjAwMDAwMDIwNDEgMDAwMDAgbg0KMDAwMDAwMzA5NCAwMDAwMCBuDQowMDAwMDAzMTg2IDAwMDAwIG4NCjAwMDAwMDMyODEgMDAwMDAgbg0KMDAwMDAwMzM3NiAwMDAwMCBuDQowMDAwMDAzNDcxIDAwMDAwIG4NCjAwMDAwMDM1NjYgMDAwMDAgbg0KMDAwMDAwMzY2MSAwMDAwMCBuDQowMDAwMDAzNzU2IDAwMDAwIG4NCjAwMDAwMDM4NDQgMDAwMDAgbg0KMDAwMDAwMzkzMyAwMDAwMCBuDQowMDAwMDA0MDIyIDAwMDAwIG4NCjAwMDAwMDQxMTEgMDAwMDAgbg0KMDAwMDAwNDIwMCAwMDAwMCBuDQowMDAwMDA0Mjg5IDAwMDAwIG4NCjAwMDAwMDQzNzggMDAwMDAgbg0KMDAwMDAwNDQ5NSAwMDAwMCBuDQowMDAwMDA0NTg0IDAwMDAwIG4NCjAwMDAwMDQ2NzMgMDAwMDAgbg0KMDAwMDAwNDc2MiAwMDAwMCBuDQowMDAwMDA0ODUxIDAwMDAwIG4NCjAwMDAwMDQ5NDAgMDAwMDAgbg0KMDAwMDAwNTAyNyAwMDAwMCBuDQowMDAwMDA1MTE2IDAwMDAwIG4NCjAwMDAwMDUyMDUgMDAwMDAgbg0KMDAwMDAwNTI5MiAwMDAwMCBuDQowMDAwMDA1MzgxIDAwMDAwIG4NCjAwMDAwMDU0NzcgMDAwMDAgbg0KMDAwMDAwNTU3MSAwMDAwMCBuDQowMDAwMDA1NjU4IDAwMDAwIG4NCjAwMDAwMDU3NDcgMDAwMDAgbg0KMDAwMDAwNTgzNiAwMDAwMCBuDQowMDAwMDA1OTI1IDAwMDAwIG4NCjAwMDAwMDYwMTIgMDAwMDAgbg0KMDAwMDAwNjA1NiAwMDAwMCBuDQowMDAwMDM2NDMyIDAwMDAwIG4NCjAwMDAwMzY0NjUgMDAwMDAgbg0KMDAwMDAzNjUxNiAwMDAwMCBuDQowMDAwMDM2NTY3IDAwMDAwIG4NCjAwMDAwMzY2MTggMDAwMDAgbg0KMDAwMDAzNjY2OSAwMDAwMCBuDQowMDAwMDM2NzIwIDAwMDAwIG4NCjAwMDAwMzY3NzEgMDAwMDAgbg0KMDAwMDAzNjgyMiAwMDAwMCBuDQowMDAwMDM2ODYyIDAwMDAwIG4NCjAwMDAwMzY5NDEgMDAwMDAgbg0KMDAwMDA0OTMxNiAwMDAwMCBuDQowMDAwMDQ5NDY5IDAwMDAwIG4NCjAwMDAwNTAwMzcgMDAwMDAgbg0KMDAwMDA1MDQ2NSAwMDAwMCBuDQowMDAwMDUwNzIwIDAwMDAwIG4NCjAwMDAwNTA3OTUgMDAwMDAgbg0KdHJhaWxlcgo8PAovUm9vdCAxIDAgUgovSW5mbyA2IDAgUgovSUQgWzwwQ0M3NzdBRDZENEFBMThFRkFGQ0ExODQ3QjI1QkMxQz4gPDBDQzc3N0FENkQ0QUExOEVGQUZDQTE4NDdCMjVCQzFDPl0KL1NpemUgNjQKPj4Kc3RhcnR4cmVmCjU0MDk2CiUlRU9GCg==', +}; diff --git a/src/components/CheckIn/types.ts b/src/components/CheckIn/types.ts new file mode 100644 index 0000000000..19dc4db4af --- /dev/null +++ b/src/components/CheckIn/types.ts @@ -0,0 +1,48 @@ +export interface InterfaceUser { + _id: string; + firstName: string; + lastName: string; +} + +export interface InterfaceAttendeeCheckIn { + _id: string; + user: InterfaceUser; + checkIn: null | { + _id: string; + time: string; + allotedRoom: string; + allotedSeat: string; + }; +} + +export interface InterfaceAttendeeQueryResponse { + event: { + _id: string; + attendeesCheckInStatus: InterfaceAttendeeCheckIn[]; + }; +} + +export interface InterfaceModalProp { + show: boolean; + eventId: string; + handleClose: () => void; +} + +export interface InterfaceTableCheckIn { + id: string; + name: string; + userId: string; + checkIn: null | { + _id: string; + time: string; + allotedRoom: string; + allotedSeat: string; + }; + eventId: string; +} + +export interface InterfaceTableData { + userName: string; + id: string; + checkInData: InterfaceTableCheckIn; +} diff --git a/src/components/CollapsibleDropdown/CollapsibleDropdown.module.css b/src/components/CollapsibleDropdown/CollapsibleDropdown.module.css new file mode 100644 index 0000000000..4337742ecc --- /dev/null +++ b/src/components/CollapsibleDropdown/CollapsibleDropdown.module.css @@ -0,0 +1,14 @@ +.iconWrapper { + width: 36px; +} + +.collapseBtn { + height: 48px; +} + +.iconWrapperSm { + width: 36px; + display: flex; + justify-content: center; + align-items: center; +} diff --git a/src/components/CollapsibleDropdown/CollapsibleDropdown.test.tsx b/src/components/CollapsibleDropdown/CollapsibleDropdown.test.tsx new file mode 100644 index 0000000000..4f1916669a --- /dev/null +++ b/src/components/CollapsibleDropdown/CollapsibleDropdown.test.tsx @@ -0,0 +1,77 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import { BrowserRouter } from 'react-router-dom'; + +import CollapsibleDropdown from './CollapsibleDropdown'; +import type { InterfaceCollapsibleDropdown } from './CollapsibleDropdown'; + +const props: InterfaceCollapsibleDropdown = { + screenName: 'SubCategory 1', + target: { + name: 'DropDown Category', + url: undefined, + subTargets: [ + { + name: 'SubCategory 1', + url: '/sub-category-1', + icon: 'fa fa-home', + }, + { + name: 'SubCategory 2', + url: '/sub-category-2', + icon: 'fa fa-home', + }, + ], + }, +}; + +describe('Testing CollapsibleDropdown component', () => { + test('Component should be rendered properly', () => { + render(); + expect(screen.getByText('DropDown Category')).toBeInTheDocument(); + expect(screen.getByText('SubCategory 1')).toBeInTheDocument(); + expect(screen.getByText('SubCategory 2')).toBeInTheDocument(); + }); + + test('Dropdown should be rendered and functioning correctly', () => { + render( + + + + ); + const parentDropdownBtn = screen.getByTestId('collapsible-dropdown'); + const activeDropdownBtn = screen.getByText('SubCategory 1'); + const nonActiveDropdownBtn = screen.getByText('SubCategory 2'); + + // Check if dropdown is rendered with correct classes + expect(parentDropdownBtn).toBeInTheDocument(); + expect(parentDropdownBtn).toHaveClass('text-white'); + expect(parentDropdownBtn).toHaveClass('btn-success'); + + // Check if active dropdown is rendered with correct classes + expect(activeDropdownBtn).toBeInTheDocument(); + expect(activeDropdownBtn).toHaveClass('text-white'); + expect(activeDropdownBtn).toHaveClass('btn-success'); + + // Check if inactive dropdown is rendered with correct classes + expect(nonActiveDropdownBtn).toBeInTheDocument(); + expect(nonActiveDropdownBtn).toHaveClass('text-secondary'); + expect(nonActiveDropdownBtn).toHaveClass('btn-light'); + + // Check if dropdown is expanded by default since the screenName prop passes + // the same value as the name prop of the subTarget + expect(parentDropdownBtn).toHaveAttribute('aria-expanded', 'true'); + + // Check if dropdown is collapsed after clicking on it + parentDropdownBtn.click(); + expect(parentDropdownBtn).toHaveAttribute('aria-expanded', 'false'); + + // Check if dropdown is expanded after clicking on it again + parentDropdownBtn.click(); + expect(parentDropdownBtn).toHaveAttribute('aria-expanded', 'true'); + + // Click on non active dropdown button and check if it navigates to the correct url + nonActiveDropdownBtn.click(); + expect(window.location.pathname).toBe('/sub-category-2'); + }); +}); diff --git a/src/components/CollapsibleDropdown/CollapsibleDropdown.tsx b/src/components/CollapsibleDropdown/CollapsibleDropdown.tsx new file mode 100644 index 0000000000..81b82e220d --- /dev/null +++ b/src/components/CollapsibleDropdown/CollapsibleDropdown.tsx @@ -0,0 +1,91 @@ +import React, { useEffect } from 'react'; +import { Button, Collapse } from 'react-bootstrap'; +import type { TargetsType } from 'state/reducers/routesReducer'; +import styles from './CollapsibleDropdown.module.css'; +import IconComponent from 'components/IconComponent/IconComponent'; +import { useHistory } from 'react-router-dom'; + +export interface InterfaceCollapsibleDropdown { + screenName: string; + target: TargetsType; +} + +const collapsibleDropdown = ({ + screenName, + target, +}: InterfaceCollapsibleDropdown): JSX.Element => { + const [showDropdown, setShowDropdown] = React.useState(false); + const [active, setActive] = React.useState(false); + const { name, subTargets } = target; + const history = useHistory(); + + useEffect(() => { + target.subTargets?.map(({ name }) => { + if (name === screenName) { + setActive(true); + setShowDropdown(true); + } + }); + }, [target.subTargets]); + + return ( + <> + + +
    + {subTargets && + subTargets.map(({ name, icon: stringIcon, url }, index) => { + return ( + + ); + })} +
    +
    + + ); +}; + +export default collapsibleDropdown; diff --git a/src/components/ContriStats/ContriStats.module.css b/src/components/ContriStats/ContriStats.module.css new file mode 100644 index 0000000000..7d6c83ea8e --- /dev/null +++ b/src/components/ContriStats/ContriStats.module.css @@ -0,0 +1,7 @@ +.fonts { + color: #707070; +} + +.fonts > span { + font-weight: 600; +} diff --git a/src/components/ContriStats/ContriStats.test.tsx b/src/components/ContriStats/ContriStats.test.tsx new file mode 100644 index 0000000000..9c21944318 --- /dev/null +++ b/src/components/ContriStats/ContriStats.test.tsx @@ -0,0 +1,39 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import ContriStats from './ContriStats'; +import { I18nextProvider } from 'react-i18next'; +import { ApolloClient, ApolloProvider, InMemoryCache } from '@apollo/client'; +import type { NormalizedCacheObject } from '@apollo/client'; +import i18nForTest from 'utils/i18nForTest'; +import { BACKEND_URL } from 'Constant/constant'; + +const client: ApolloClient = new ApolloClient({ + cache: new InMemoryCache(), + uri: BACKEND_URL, +}); + +describe('Testing Contribution Stats', () => { + const props = { + key: '123', + id: '234', + recentAmount: '200', + highestAmount: '500', + totalAmount: '1000', + }; + + test('should render props and text elements test for the page component', () => { + render( + + + + + + ); + expect(screen.getByText('Recent Contribution: $')).toBeInTheDocument(); + expect(screen.getByText('Highest Contribution: $')).toBeInTheDocument(); + expect(screen.getByText('Total Contribution: $')).toBeInTheDocument(); + expect(screen.getByText('200')).toBeInTheDocument(); + expect(screen.getByText('500')).toBeInTheDocument(); + expect(screen.getByText('1000')).toBeInTheDocument(); + }); +}); diff --git a/src/components/ContriStats/ContriStats.tsx b/src/components/ContriStats/ContriStats.tsx new file mode 100644 index 0000000000..7891878335 --- /dev/null +++ b/src/components/ContriStats/ContriStats.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +import styles from './ContriStats.module.css'; + +interface InterfaceContriStatsProps { + key: string; + id: string; + recentAmount: string; + highestAmount: string; + totalAmount: string; +} + +function contriStats(props: InterfaceContriStatsProps): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'contriStats', + }); + + return ( + <> +

    + {t('recentContribution')}: $ {props.recentAmount} +

    +

    + {t('highestContribution')}: $ {props.highestAmount} +

    +

    + {t('totalContribution')}: $ {props.totalAmount} +

    + + ); +} +export default contriStats; diff --git a/src/components/DeleteOrg/DeleteOrg.module.css b/src/components/DeleteOrg/DeleteOrg.module.css new file mode 100644 index 0000000000..2b15a2ac0c --- /dev/null +++ b/src/components/DeleteOrg/DeleteOrg.module.css @@ -0,0 +1,25 @@ +.settingsBody { + margin: 2.5rem 0; +} + +.cardHeader { + padding: 1.25rem 1rem 1rem 1rem; + border-bottom: 1px solid var(--bs-gray-200); + display: flex; + justify-content: space-between; + align-items: center; +} + +.cardHeader .cardTitle { + font-size: 1.2rem; + font-weight: 600; +} + +.cardBody { + min-height: 180px; +} + +.cardBody .textBox { + margin: 0 0 3rem 0; + color: var(--bs-secondary); +} diff --git a/src/components/DeleteOrg/DeleteOrg.test.tsx b/src/components/DeleteOrg/DeleteOrg.test.tsx new file mode 100644 index 0000000000..936cf44e03 --- /dev/null +++ b/src/components/DeleteOrg/DeleteOrg.test.tsx @@ -0,0 +1,84 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { render, screen } from '@testing-library/react'; +import 'jest-location-mock'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; + +import { DELETE_ORGANIZATION_MUTATION } from 'GraphQl/Mutations/mutations'; +import { act } from 'react-dom/test-utils'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18nForTest from 'utils/i18nForTest'; +import DeleteOrg from './DeleteOrg'; + +const MOCKS = [ + { + request: { + query: DELETE_ORGANIZATION_MUTATION, + variables: { + id: 123, + }, + }, + result: { + data: { + removeOrganization: [ + { + _id: 123, + }, + ], + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); + +afterEach(() => { + localStorage.clear(); +}); + +describe('Delete Organization Component', () => { + test('should be able to Toggle Delete Organization Modal', async () => { + window.location.assign('/orgsetting/id=123'); + localStorage.setItem('UserType', 'SUPERADMIN'); + render( + + + + + + + + + + ); + screen.getByTestId(/openDeleteModalBtn/i).click(); + expect(screen.getByTestId(/orgDeleteModal/i)).toBeInTheDocument(); + screen.getByTestId(/closeDelOrgModalBtn/i).click(); + await act(async () => { + expect(screen.queryByTestId(/orgDeleteModal/i)).not.toHaveFocus(); + }); + expect(window.location).toBeAt('/orgsetting/id=123'); + }); + + test('Delete organization functionality should work properly', async () => { + window.location.assign('/orgsetting/id=123'); + localStorage.setItem('UserType', 'SUPERADMIN'); + render( + + + + + + + + + + ); + screen.getByTestId(/openDeleteModalBtn/i).click(); + screen.getByTestId(/deleteOrganizationBtn/i).click(); + expect(window.location).not.toBeNull(); + }); +}); diff --git a/src/components/DeleteOrg/DeleteOrg.tsx b/src/components/DeleteOrg/DeleteOrg.tsx new file mode 100644 index 0000000000..b7ceafbd5c --- /dev/null +++ b/src/components/DeleteOrg/DeleteOrg.tsx @@ -0,0 +1,111 @@ +import React, { useState } from 'react'; +import { Button, Card, Modal } from 'react-bootstrap'; +import { useTranslation } from 'react-i18next'; +import { useMutation, useQuery } from '@apollo/client'; +import { errorHandler } from 'utils/errorHandler'; +import { toast } from 'react-toastify'; +import { DELETE_ORGANIZATION_MUTATION } from 'GraphQl/Mutations/mutations'; +import { REMOVE_SAMPLE_ORGANIZATION_MUTATION } from 'GraphQl/Mutations/mutations'; +import { IS_SAMPLE_ORGANIZATION_QUERY } from 'GraphQl/Queries/Queries'; +import styles from './DeleteOrg.module.css'; + +function deleteOrg(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'deleteOrg', + }); + const [showDeleteModal, setShowDeleteModal] = useState(false); + const currentUrl = window.location.href.split('=')[1]; + const canDelete = localStorage.getItem('UserType') === 'SUPERADMIN'; + const toggleDeleteModal = (): void => setShowDeleteModal(!showDeleteModal); + + const [del] = useMutation(DELETE_ORGANIZATION_MUTATION); + const [removeSampleOrganization] = useMutation( + REMOVE_SAMPLE_ORGANIZATION_MUTATION + ); + + const { data } = useQuery(IS_SAMPLE_ORGANIZATION_QUERY, { + variables: { + isSampleOrganizationId: currentUrl, + }, + }); + + const deleteOrg = async (): Promise => { + if (data && data.isSampleOrganization) { + removeSampleOrganization() + .then(() => { + toast.success('Successfully deleted sample Organization'); + }) + .catch((error) => { + toast.error(error.message); + }); + window.location.replace('/orglist'); + } else { + try { + await del({ + variables: { + id: currentUrl, + }, + }); + window.location.replace('/orglist'); + } catch (error: any) { + errorHandler(t, error); + } + } + }; + + return ( + <> + {canDelete && ( + +
    +
    {t('deleteOrganization')}
    +
    + +
    {t('longDelOrgMsg')}
    + +
    +
    + )} + {/* Delete Organization Modal */} + {canDelete && ( + + +
    {t('deleteOrganization')}
    +
    + {t('deleteMsg')} + + + + +
    + )} + + ); +} + +export default deleteOrg; diff --git a/src/components/EventCalendar/EventCalendar.module.css b/src/components/EventCalendar/EventCalendar.module.css new file mode 100644 index 0000000000..37ecb175d4 --- /dev/null +++ b/src/components/EventCalendar/EventCalendar.module.css @@ -0,0 +1,82 @@ +.calendar { + /* display: flex; + flex-direction: column; */ + font-family: sans-serif; + font-size: 1.2rem; +} +.calendar__header { + display: flex; + margin-bottom: 2rem; +} +.calendar__header_month { + margin: 0.5rem; + color: #707070; + font-weight: bold; +} +.button { + background-color: rgba(40, 167, 69, 1); + color: #fff; + padding: 1px; + font-weight: bold; +} +.calendar__weekdays { + display: grid; + grid-template-columns: repeat(7, 1fr); + margin-bottom: 1rem; + background-color: black; +} +.weekday { + display: flex; + justify-content: center; + align-items: center; + border: 1px solid white; + color: #fff; + background-color: rgba(40, 167, 69, 1); +} +.calendar__days { + display: grid; + grid-template-columns: repeat(7, 1fr); + grid-template-rows: repeat(6, 1fr); +} +.day { + background-color: #ffffff; + border: 1px solid rgb(0, 0, 0); + padding-bottom: 4rem; + padding-left: 0.3rem; + padding-right: 0.3rem; + background-color: white; + border: 1px solid #707070; + color: #212121; +} +.day__outside { + background-color: #eeeded; + color: #898989; +} +.day__selected { + background-color: #007bff; + color: #707070; +} +.day__today { + background-color: #def6e1; + font-weight: 700; + text-decoration: underline; + color: #006000; +} +.btn__today { + background: #06960f; + transition: ease-in all 200ms; + border-radius: 11px; + box-shadow: 0px 1px 3px #666666; + font-family: Arial; + color: #ffffff; + font-size: 20px; + padding: 10px 20px 10px 20px; + text-decoration: none; + margin-left: 20px; + border: none; +} + +.btn__today:hover { + background: #006000; + text-decoration: none; +} diff --git a/src/components/EventCalendar/EventCalendar.test.tsx b/src/components/EventCalendar/EventCalendar.test.tsx new file mode 100644 index 0000000000..89d76329ac --- /dev/null +++ b/src/components/EventCalendar/EventCalendar.test.tsx @@ -0,0 +1,215 @@ +/* eslint-disable react/react-in-jsx-scope */ +import Calendar from './EventCalendar'; +import { render, screen, fireEvent } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider } from 'react-i18next'; + +import { + DELETE_EVENT_MUTATION, + UPDATE_EVENT_MUTATION, +} from 'GraphQl/Mutations/mutations'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import styles from './EventCalendar.module.css'; + +const eventData = [ + { + _id: '1', + title: 'Event 1', + description: 'This is event 1', + startDate: '2022-05-01', + endDate: '2022-05-01', + location: 'New York', + startTime: '10:00', + endTime: '12:00', + allDay: false, + recurring: false, + isPublic: true, + isRegisterable: true, + }, + { + _id: '2', + title: 'Event 2', + description: 'This is event 2', + startDate: '2022-05-03', + endDate: '2022-05-03', + location: 'Los Angeles', + startTime: '14:00', + endTime: '16:00', + allDay: false, + recurring: false, + isPublic: true, + isRegisterable: true, + }, +]; + +const MOCKS = [ + { + request: { + query: DELETE_EVENT_MUTATION, + variable: { id: '123' }, + }, + result: { + data: { + removeEvent: { + _id: '1', + }, + }, + }, + }, + { + request: { + query: UPDATE_EVENT_MUTATION, + variable: { + id: '123', + title: 'Updated title', + description: 'This is a new update', + isPublic: true, + recurring: false, + isRegisterable: true, + allDay: false, + location: 'New Delhi', + startTime: '02:00', + endTime: '07:00', + }, + }, + result: { + data: { + updateEvent: { + _id: '1', + }, + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); + +describe('Calendar', () => { + it('renders weekdays', () => { + render(); + const weekdays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; + weekdays.forEach((weekday) => { + expect(screen.getByText(weekday)).toBeInTheDocument(); + }); + }); + it('should initialize currentMonth and currentYear with the current date', () => { + const today = new Date(); + const { getByTestId } = render(); + + const currentMonth = getByTestId('current-date'); + const currentYear = getByTestId('current-date'); + + expect(currentMonth).toHaveTextContent( + today.toLocaleString('default', { month: 'long' }) + ); + expect(currentYear).toHaveTextContent(today.getFullYear().toString()); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should render the current month and year', () => { + const { getByText } = render(); + const currentMonth = new Date().toLocaleString('default', { + month: 'long', + }); + const currentYear = new Date().getFullYear(); + expect(getByText(`${currentMonth} ${currentYear}`)).toBeInTheDocument(); + }); + + it('should highlight the selected date when clicked', () => { + const { getByText } = render(); + const selectedDate = getByText('15'); + fireEvent.click(selectedDate); + expect(selectedDate).toHaveClass(styles.day); + }); + + it('Should show prev and next month on clicking < & > buttons', () => { + //testing previous month button + render( + + + + + + ); + const prevButton = screen.getByText('<'); + fireEvent.click(prevButton); + //testing next month button + const nextButton = screen.getByText('>'); + fireEvent.click(nextButton); + //Testing year change + for (let index = 0; index < 13; index++) { + fireEvent.click(nextButton); + } + for (let index = 0; index < 13; index++) { + fireEvent.click(prevButton); + } + }); + it('Should render eventlistcard of current day event', () => { + const currentDayEventMock = [ + { + _id: '0', + title: 'demo', + description: 'agrsg', + startDate: new Date().toISOString().split('T')[0], + endDate: new Date().toISOString().split('T')[0], + location: 'delhi', + startTime: '10:00', + endTime: '12:00', + allDay: false, + recurring: false, + isPublic: true, + isRegisterable: true, + }, + ]; + render( + + + + + + ); + }); + it('Test for superadmin case', () => { + render( + + + + + + ); + }); + it('Today Cell is having correct styles', () => { + render( + + + + + + ); + // const todayDate = new Date().getDate(); + // const todayElement = screen.getByText(todayDate.toString()); + // expect(todayElement).toHaveClass(styles.day__today); + }); + it('Today button should show today cell', () => { + render( + + + + + + ); + //Changing the month + const prevButton = screen.getByText('<'); + fireEvent.click(prevButton); + + // Clicking today button + const todayButton = screen.getByText('Today'); + fireEvent.click(todayButton); + // const todayCell = screen.getByText(new Date().getDate().toString()); + // expect(todayCell).toHaveClass(styles.day__today); + }); +}); diff --git a/src/components/EventCalendar/EventCalendar.tsx b/src/components/EventCalendar/EventCalendar.tsx new file mode 100644 index 0000000000..4cb027647d --- /dev/null +++ b/src/components/EventCalendar/EventCalendar.tsx @@ -0,0 +1,242 @@ +import EventListCard from 'components/EventListCard/EventListCard'; +import dayjs from 'dayjs'; +import Button from 'react-bootstrap/Button'; +import React, { useState, useEffect } from 'react'; +import styles from './EventCalendar.module.css'; + +interface InterfaceEvent { + _id: string; + title: string; + description: string; + startDate: string; + endDate: string; + location: string; + startTime: string; + endTime: string; + allDay: boolean; + recurring: boolean; + registrants?: InterfaceIEventAttendees[]; + isPublic: boolean; + isRegisterable: boolean; +} + +interface InterfaceCalendarProps { + eventData: InterfaceEvent[]; + orgData?: InterfaceIOrgList; + userRole?: string; + userId?: string; +} + +enum Status { + ACTIVE = 'ACTIVE', + BLOCKED = 'BLOCKED', + DELETED = 'DELETED', +} + +enum Role { + USER = 'USER', + SUPERADMIN = 'SUPERADMIN', + ADMIN = 'ADMIN', +} +interface InterfaceIEventAttendees { + userId: string; + user?: string; + status?: Status; + createdAt?: Date; +} + +interface InterfaceIOrgList { + admins: { _id: string }[]; +} +const Calendar: React.FC = ({ + eventData, + orgData, + userRole, + userId, +}) => { + const [selectedDate] = useState(null); + const weekdays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; + const months = [ + 'January', + 'February', + 'March', + 'April', + 'May', + 'June', + 'July', + 'August', + 'September', + 'October', + 'November', + 'December', + ]; + + const today = new Date(); + const [currentMonth, setCurrentMonth] = useState(today.getMonth()); + const [currentYear, setCurrentYear] = useState(today.getFullYear()); + const [events, setEvents] = useState(null); + + const filterData = ( + eventData: InterfaceEvent[], + orgData?: InterfaceIOrgList, + userRole?: string, + userId?: string + ): InterfaceEvent[] => { + const data: InterfaceEvent[] = []; + if (userRole === Role.SUPERADMIN) return eventData; + // Hard to test all the cases + /* istanbul ignore next */ + if (userRole === Role.ADMIN) { + eventData?.forEach((event) => { + if (event.isPublic) data.push(event); + if (!event.isPublic) { + const filteredOrg: boolean | undefined = orgData?.admins?.some( + (data) => data._id === userId + ); + + if (filteredOrg) { + data.push(event); + } + } + }); + } else { + eventData?.forEach((event) => { + if (event.isPublic) data.push(event); + const userAttending = event.registrants?.some( + (data) => data.userId === userId + ); + if (userAttending) { + data.push(event); + } + }); + } + return data; + }; + + useEffect(() => { + const data = filterData(eventData, orgData, userRole, userId); + setEvents(data); + }, [eventData, orgData, userRole, userId]); + + const handlePrevMonth = (): void => { + if (currentMonth === 0) { + setCurrentMonth(11); + setCurrentYear(currentYear - 1); + } else { + setCurrentMonth(currentMonth - 1); + } + }; + + const handleNextMonth = (): void => { + if (currentMonth === 11) { + setCurrentMonth(0); + setCurrentYear(currentYear + 1); + } else { + setCurrentMonth(currentMonth + 1); + } + }; + const handleTodayButton = (): void => { + setCurrentYear(today.getFullYear()); + setCurrentMonth(today.getMonth()); + }; + const renderDays = (): JSX.Element[] => { + const monthStart = new Date(currentYear, currentMonth, 1); + const monthEnd = new Date(currentYear, currentMonth + 1, 0); + const startDate = new Date( + monthStart.getFullYear(), + monthStart.getMonth(), + monthStart.getDate() - monthStart.getDay() + ); + const endDate = new Date( + monthEnd.getFullYear(), + monthEnd.getMonth(), + monthEnd.getDate() + (6 - monthEnd.getDay()) + ); + const days = []; + let currentDate = startDate; + while (currentDate <= endDate) { + days.push(currentDate); + currentDate = new Date( + currentDate.getFullYear(), + currentDate.getMonth(), + currentDate.getDate() + 1 + ); + } + return days.map((date, index) => { + const className = [ + date.toLocaleDateString() === today.toLocaleDateString() //Styling for today day cell + ? styles.day__today + : '', + date.getMonth() !== currentMonth ? styles.day__outside : '', //Styling for days outside the current month + selectedDate?.getTime() === date.getTime() ? styles.day__selected : '', + styles.day, + ].join(' '); + return ( +
    + {date.getDate()} +
    + {events + ?.filter((datas) => { + if (datas.startDate == dayjs(date).format('YYYY-MM-DD')) + return datas; + }) + .map((datas: InterfaceEvent) => { + return ( + + ); + })} +
    +
    + ); + }); + }; + + return ( +
    +
    + +
    + {months[currentMonth]} {currentYear} +
    + +
    + +
    +
    + +
    + {weekdays.map((weekday, index) => ( +
    + {weekday} +
    + ))} +
    +
    {renderDays()}
    +
    + ); +}; + +export default Calendar; diff --git a/src/components/EventListCard/EventListCard.module.css b/src/components/EventListCard/EventListCard.module.css new file mode 100644 index 0000000000..1648c9d16a --- /dev/null +++ b/src/components/EventListCard/EventListCard.module.css @@ -0,0 +1,193 @@ +.cards h2 { + font-size: 15px; + color: #fff; +} +.cards > h3 { + font-size: 17px; +} +.cards > p { + font-size: 14px; + margin-top: 0px; + margin-bottom: 7px; +} +.cards a { + color: #fff; + font-weight: 600; +} +.cards a:hover { + color: black; +} +.cards { + position: relative; + overflow: hidden; + transition: all 0.3s; +} +.dispflex { + display: flex; + height: 50px; + transition: transform 0.3s ease; + cursor: pointer; +} +.cards:hover { + transform: scale(2.5); + z-index: 5; +} +.cards:hover h2 { + font-size: 0.4vmax; + margin-bottom: 0; +} +.iconContainer { + display: flex; + justify-content: flex-end; +} +.icon { + margin: 1px; +} + +.cards { + width: 100%; + background: rgba(40, 167, 69, 1); + padding: 2px 3px; + border-radius: 5px; + border: 1px solid #e8e8e8; + box-shadow: 0 3px 5px #c9c9c9; + color: #737373; + box-sizing: border-box; +} +.cards:last-child:nth-last-child(odd) { + grid-column: auto / span 2; +} + +.cards:first-child:nth-last-child(even), +.cards:first-child:nth-last-child(even) ~ .box { + grid-column: auto / span 1; +} + +.sidebarsticky > input { + text-decoration: none; + margin-bottom: 50px; + border-color: #e8e5e5; + width: 80%; + border-radius: 7px; + padding-top: 5px; + padding-bottom: 5px; + padding-right: 10px; + padding-left: 10px; + box-shadow: none; +} +.datediv { + display: flex; + flex-direction: row; + margin-bottom: 15px; +} +.datebox { + width: 90%; + border-radius: 7px; + border-color: #e8e5e5; + outline: none; + box-shadow: none; + padding-top: 2px; + padding-bottom: 2px; + padding-right: 5px; + padding-left: 5px; +} +.checkboxdiv > label { + margin-right: 50px; +} +.checkboxdiv > label > input { + margin-left: 10px; +} +.dispflex { + display: flex; + margin-bottom: 5px; + margin-right: 5px; +} +.dispflex > input { + width: 20%; + border: none; + box-shadow: none; + margin-top: 5px; +} +.checkboxdiv { + display: flex; +} +.checkboxdiv > div { + width: 50%; +} + +.preview { + display: flex; + flex-direction: row; + font-weight: 900; + font-size: 16px; + color: rgb(80, 80, 80); +} +.view { + margin-left: 2%; + font-weight: 600; + font-size: 16px; + color: #707070; +} +.flexdir { + display: flex; + flex-direction: row; + justify-content: space-between; + border: none; +} + +.form_wrapper { + margin-top: 27px; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + position: absolute; + display: flex; + flex-direction: column; + padding: 20px 30px; + background: #ffffff; + border-color: #e8e5e5; + border-width: 5px; + border-radius: 10px; + width: 40%; +} + +.form_wrapper form { + display: flex; + align-items: left; + justify-content: left; + flex-direction: column; +} +.titlemodal { + color: #707070; + font-weight: 600; + font-size: 20px; + margin-bottom: 20px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 65%; +} +.cancel > i { + margin-top: 5px; + transform: scale(1.2); + cursor: pointer; + color: #707070; +} +.modalbody { + width: 50px; +} +.list_box { + height: 70vh; + overflow-y: auto; + width: auto; +} +@media only screen and (max-width: 600px) { + .form_wrapper { + width: 90%; + top: 45%; + } +} + +.customButton { + background-color: #31bb6b; + border: #31bb6b; +} diff --git a/src/components/EventListCard/EventListCard.test.tsx b/src/components/EventListCard/EventListCard.test.tsx new file mode 100644 index 0000000000..820e563957 --- /dev/null +++ b/src/components/EventListCard/EventListCard.test.tsx @@ -0,0 +1,344 @@ +import React from 'react'; +import { act, render, screen, fireEvent } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; + +import EventListCard from './EventListCard'; +import { + DELETE_EVENT_MUTATION, + UPDATE_EVENT_MUTATION, +} from 'GraphQl/Mutations/mutations'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; + +const MOCKS = [ + { + request: { + query: DELETE_EVENT_MUTATION, + variable: { id: '123' }, + }, + result: { + data: { + removeEvent: { + _id: '1', + }, + }, + }, + }, + { + request: { + query: UPDATE_EVENT_MUTATION, + variable: { + id: '123', + title: 'Updated title', + description: 'This is a new update', + isPublic: true, + recurring: false, + isRegisterable: true, + allDay: false, + location: 'New Delhi', + startTime: '02:00', + endTime: '07:00', + }, + }, + result: { + data: { + updateEvent: { + _id: '1', + }, + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Testing Event List Card', () => { + const props = { + key: '123', + id: '1', + eventLocation: 'India', + eventName: 'Shelter for Dogs', + eventDescription: 'This is shelter for dogs event', + regDate: '19/03/2022', + regEndDate: '26/03/2022', + startTime: '02:00', + endTime: '06:00', + allDay: true, + recurring: false, + isPublic: true, + isRegisterable: false, + }; + + global.alert = jest.fn(); + test('Testing for modal', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('card')); + + userEvent.click(screen.getByTestId('createEventModalCloseBtn')); + + await wait(); + }); + + test('Should render text elements when props value is not passed', async () => { + global.confirm = (): boolean => false; + + render( + + + + + + ); + + await wait(); + + expect(screen.queryByText(props.eventName)).not.toBeInTheDocument(); + }); + + test('Testing for update modal', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('card')); + userEvent.click(screen.getByTestId('editEventModalBtn')); + + userEvent.click(screen.getByTestId('EventUpdateModalCloseBtn')); + userEvent.click(screen.getByTestId('createEventModalCloseBtn')); + + await wait(); + }); + + test('Testing event update functionality', async () => { + render( + + + + + + ); + + await wait(); + userEvent.click(screen.getByTestId('card')); + userEvent.click(screen.getByTestId('editEventModalBtn')); + userEvent.type(screen.getByTestId('updateTitle'), props.eventName); + userEvent.type( + screen.getByTestId('updateDescription'), + props.eventDescription + ); + userEvent.type(screen.getByTestId('updateLocation'), props.eventLocation); + userEvent.click(screen.getByTestId('updateAllDay')); + userEvent.click(screen.getByTestId('updateRecurring')); + userEvent.click(screen.getByTestId('updateIsPublic')); + userEvent.click(screen.getByTestId('updateRegistrable')); + + userEvent.click(screen.getByTestId('updatePostBtn')); + }); + test('should render props and text elements test for the screen', async () => { + const { container } = render( + + + + + + + + ); + + expect(container.textContent).not.toBe('Loading data...'); + + await wait(); + }); + + test('Testing if the event is not for all day', async () => { + render( + + + + + + ); + + await wait(); + userEvent.click(screen.getByTestId('card')); + userEvent.click(screen.getByTestId('editEventModalBtn')); + userEvent.type(screen.getByTestId('updateTitle'), props.eventName); + userEvent.type( + screen.getByTestId('updateDescription'), + props.eventDescription + ); + userEvent.type(screen.getByTestId('updateLocation'), props.eventLocation); + userEvent.click(screen.getByTestId('updateAllDay')); + await wait(); + + userEvent.type(screen.getByTestId('updateStartTime'), props.startTime); + userEvent.type(screen.getByTestId('updateEndTime'), props.endTime); + + userEvent.click(screen.getByTestId('updatePostBtn')); + }); + test('Testing event preview modal', async () => { + render( + + + + + + ); + await wait(); + expect(screen.getByText(props.eventName)).toBeInTheDocument(); + }); + describe('EventListCard', () => { + it('should render the delete modal', () => { + render( + + + + ); + userEvent.click(screen.getByTestId('card')); + userEvent.click(screen.getByTestId('deleteEventModalBtn')); + + userEvent.click(screen.getByTestId('EventDeleteModalCloseBtn')); + userEvent.click(screen.getByTestId('createEventModalCloseBtn')); + }); + + it('should call the delete event mutation when the "Yes" button is clicked', async () => { + render( + + + + ); + userEvent.click(screen.getByTestId('card')); + userEvent.click(screen.getByTestId('deleteEventModalBtn')); + const deleteBtn = screen.getByTestId('deleteEventBtn'); + fireEvent.click(deleteBtn); + }); + + it('should show an error toast when the delete event mutation fails', async () => { + const errorMocks = [ + { + request: { + query: DELETE_EVENT_MUTATION, + variables: { + id: props.id, + }, + }, + error: new Error('Something went wrong'), + }, + ]; + const link2 = new StaticMockLink(errorMocks, true); + render( + + + + ); + userEvent.click(screen.getByTestId('card')); + userEvent.click(screen.getByTestId('deleteEventModalBtn')); + const deleteBtn = screen.getByTestId('deleteEventBtn'); + fireEvent.click(deleteBtn); + }); + }); + + test('Should render truncated event details', async () => { + const longEventName = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. A very long event name that exceeds 150 characters and needs to be truncated'; + const longDescription = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. A very long description that exceeds 150 characters and needs to be truncated'; + const longEventNameLength = longEventName.length; + const longDescriptionLength = longDescription.length; + const truncatedEventName = longEventName.substring(0, 150) + '...'; + const truncatedDescriptionName = longDescription.substring(0, 150) + '...'; + render( + + + + + + ); + + await wait(); + + expect(longEventNameLength).toBeGreaterThan(100); + expect(longDescriptionLength).toBeGreaterThan(256); + expect(truncatedEventName).toContain('...'); + expect(truncatedDescriptionName).toContain('...'); + await wait(); + }); +}); diff --git a/src/components/EventListCard/EventListCard.tsx b/src/components/EventListCard/EventListCard.tsx new file mode 100644 index 0000000000..0ec3a62d6f --- /dev/null +++ b/src/components/EventListCard/EventListCard.tsx @@ -0,0 +1,465 @@ +import type { ChangeEvent } from 'react'; +import React, { useEffect, useState } from 'react'; +import { useMutation } from '@apollo/client'; +import { toast } from 'react-toastify'; +import { useTranslation } from 'react-i18next'; +import Modal from 'react-bootstrap/Modal'; +import Button from 'react-bootstrap/Button'; +import styles from './EventListCard.module.css'; +import { + DELETE_EVENT_MUTATION, + UPDATE_EVENT_MUTATION, +} from 'GraphQl/Mutations/mutations'; +import { Form } from 'react-bootstrap'; +import { errorHandler } from 'utils/errorHandler'; +import { useHistory } from 'react-router-dom'; + +interface InterfaceEventListCardProps { + key: string; + id: string; + eventLocation: string; + eventName: string; + eventDescription: string; + regDate: string; + regEndDate: string; + startTime: string; + endTime: string; + allDay: boolean; + recurring: boolean; + isPublic: boolean; + isRegisterable: boolean; +} +function eventListCard(props: InterfaceEventListCardProps): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'eventListCard', + }); + const [eventmodalisOpen, setEventModalIsOpen] = useState(false); + const [alldaychecked, setAllDayChecked] = useState(true); + const [recurringchecked, setRecurringChecked] = useState(false); + const [publicchecked, setPublicChecked] = useState(true); + const [registrablechecked, setRegistrableChecked] = React.useState(false); + const [eventDeleteModalIsOpen, setEventDeleteModalIsOpen] = useState(false); + const [eventUpdateModalIsOpen, setEventUpdateModalIsOpen] = useState(false); + const history = useHistory(); + const [formState, setFormState] = useState({ + title: '', + eventdescrip: '', + location: '', + startTime: '08:00:00', + endTime: '18:00:00', + }); + const showViewModal = (): void => { + setEventModalIsOpen(true); + }; + const hideViewModal = (): void => { + setEventModalIsOpen(false); + }; + + const toggleDeleteModal = (): void => { + setEventDeleteModalIsOpen(!eventDeleteModalIsOpen); + }; + + const toggleUpdateModel = (): void => { + setEventUpdateModalIsOpen(!eventUpdateModalIsOpen); + }; + + useEffect(() => { + setFormState({ + title: props.eventName, + eventdescrip: props.eventDescription, + location: props.eventLocation, + startTime: props.startTime?.split('.')[0] || '08:00:00', + endTime: props.endTime?.split('.')[0] || '18:00:00', + }); + + setAllDayChecked(props.allDay); + setRecurringChecked(props.recurring); + setPublicChecked(props.isPublic); + setRegistrableChecked(props.isRegisterable); + }, []); + + const [create] = useMutation(DELETE_EVENT_MUTATION); + const [updateEvent] = useMutation(UPDATE_EVENT_MUTATION); + + const deleteEvent = async (): Promise => { + try { + const { data } = await create({ + variables: { + id: props.id, + }, + }); + + /* istanbul ignore next */ + if (data) { + toast.success(t('eventDeleted')); + setTimeout(() => { + window.location.reload(); + }, 2000); + } + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + + const updateEventHandler = async ( + e: ChangeEvent + ): Promise => { + e.preventDefault(); + + try { + const { data } = await updateEvent({ + variables: { + id: props.id, + title: formState.title, + description: formState.eventdescrip, + isPublic: publicchecked, + recurring: recurringchecked, + isRegisterable: registrablechecked, + allDay: alldaychecked, + location: formState.location, + startTime: !alldaychecked ? formState.startTime + 'Z' : null, + endTime: !alldaychecked ? formState.endTime + 'Z' : null, + }, + }); + + /* istanbul ignore next */ + if (data) { + toast.success(t('eventUpdated')); + setTimeout(() => { + window.location.reload(); + }, 2000); + } + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + + const openEventDashboard = (): void => { + history.push(`/event/${props.id}`); + }; + + return ( + <> +
    +
    +
    +

    + {props.eventName ? ( + <> + {props.eventName.length > 150 ? ( + <>{props.eventName.substring(0, 150)}... + ) : ( + <>{props.eventName} + )} + + ) : ( + <>Dogs Care + )} +

    +
    +
    +
    + {/* preview modal */} + + +

    {t('eventDetails')}

    + +
    + +
    +
    +

    + {t('eventTitle')}:{' '} + + {props.eventName ? ( + <> + {props.eventName.length > 100 ? ( + <>{props.eventName.substring(0, 100)}... + ) : ( + <>{props.eventName} + )} + + ) : ( + <>Dogs Care + )} + +

    +

    + {t('location')}: + + {props.eventLocation ? ( + <>{props.eventLocation} + ) : ( + <>India + )} + +

    +

    + {t('description')}:{' '} + + {props.eventDescription && props.eventDescription.length > 256 + ? props.eventDescription.substring(0, 256) + '...' + : props.eventDescription} + +

    +

    + {t('on')}: {props.regDate} +

    +

    + {t('end')}:{' '} + {props.regEndDate} +

    + +
    +
    + + +
    +
    +
    +
    + + {/* delete modal */} + + + + {t('deleteEvent')} + + + {t('deleteEventMsg')} + + + + + + + {/* Edit Modal */} + + + + {' '} + {t('editEvent')} + + +
    + + + { + setFormState({ + ...formState, + title: e.target.value, + }); + }} + /> + + { + setFormState({ + ...formState, + eventdescrip: e.target.value, + }); + }} + /> + + { + setFormState({ + ...formState, + location: e.target.value, + }); + }} + /> + {!alldaychecked && ( +
    +
    + + + setFormState({ + ...formState, + startTime: e.target.value, + }) + } + /> +
    +
    + + + setFormState({ + ...formState, + endTime: e.target.value, + }) + } + /> +
    +
    + )} +
    +
    + + setAllDayChecked(!alldaychecked)} + /> +
    +
    + + setRecurringChecked(!recurringchecked)} + /> +
    +
    +
    +
    + + setPublicChecked(!publicchecked)} + /> +
    +
    + + + setRegistrableChecked(!registrablechecked) + } + /> +
    +
    +
    + + + + +
    +
    + + ); +} +export {}; +export default eventListCard; diff --git a/src/components/EventProjectModals/AddEventProjectModal.test.tsx b/src/components/EventProjectModals/AddEventProjectModal.test.tsx new file mode 100644 index 0000000000..1dd57e0d1e --- /dev/null +++ b/src/components/EventProjectModals/AddEventProjectModal.test.tsx @@ -0,0 +1,132 @@ +import React from 'react'; +import { fireEvent, render, waitFor } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { AddEventProjectModal } from './AddEventProjectModal'; +import { ADD_EVENT_PROJECT_MUTATION } from 'GraphQl/Mutations/mutations'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; +import { ToastContainer } from 'react-toastify'; + +const successfulMutationMock = [ + { + request: { + query: ADD_EVENT_PROJECT_MUTATION, + variables: { + title: 'Title', + description: 'Description', + eventId: '123', + }, + }, + result: { + data: { + createEventProject: { + _id: '456', + }, + }, + }, + }, +]; + +const unsuccessfulMutationMock = [ + { + request: { + query: ADD_EVENT_PROJECT_MUTATION, + variables: { + title: 'Title', + description: 'Description', + eventId: '123', + }, + }, + error: new Error('Oops'), + }, +]; + +describe('Testing Add Event Project Modal', () => { + const props = { + show: true, + eventId: '123', + handleClose: jest.fn(), + refetchData: jest.fn(), + }; + + test('The modal should be rendered and add button should not work with blank values', async () => { + const { queryByText, queryByLabelText } = render( + + + + + + + + + + + ); + + await waitFor(() => + expect(queryByText('Add an Event Project')).toBeInTheDocument() + ); + + fireEvent.click(queryByText('Create Project') as Element); + + // Check for blank entry warning modals + await waitFor(() => + expect(queryByText('Title cannot be empty!')).toBeInTheDocument() + ); + await waitFor(() => + expect(queryByText('Description cannot be empty!')).toBeInTheDocument() + ); + + // Type in the title and the description of the event project + fireEvent.change(queryByLabelText('Title') as Element, { + target: { value: 'Title' }, + }); + fireEvent.change(queryByLabelText('Description') as Element, { + target: { value: 'Description' }, + }); + + fireEvent.click(queryByText('Create Project') as Element); + + await waitFor(() => + expect(queryByText('Adding the project...')).toBeInTheDocument() + ); + + await waitFor(() => + expect(queryByText('Added the project successfully!')).toBeInTheDocument() + ); + }); + + test('The modal should be rendered and error message should be shown if mutation fails', async () => { + const { queryByText, queryByLabelText } = render( + + + + + + + + + + + ); + + // Type in the title and the description of the event project + fireEvent.change(queryByLabelText('Title') as Element, { + target: { value: 'Title' }, + }); + fireEvent.change(queryByLabelText('Description') as Element, { + target: { value: 'Description' }, + }); + + fireEvent.click(queryByText('Create Project') as Element); + + await waitFor(() => + expect( + queryByText('There was an error in adding the project!') + ).toBeInTheDocument() + ); + }); +}); diff --git a/src/components/EventProjectModals/AddEventProjectModal.tsx b/src/components/EventProjectModals/AddEventProjectModal.tsx new file mode 100644 index 0000000000..10273b5e4f --- /dev/null +++ b/src/components/EventProjectModals/AddEventProjectModal.tsx @@ -0,0 +1,99 @@ +import React, { useState } from 'react'; +import { Modal, Button, Form } from 'react-bootstrap'; +import { toast } from 'react-toastify'; +import { useMutation } from '@apollo/client'; +import { ADD_EVENT_PROJECT_MUTATION } from 'GraphQl/Mutations/mutations'; + +type ModalPropType = { + show: boolean; + eventId: string; + handleClose: () => void; + refetchData: () => void; +}; + +export const AddEventProjectModal = ({ + show, + handleClose, + refetchData, + eventId, +}: ModalPropType): JSX.Element => { + const [title, setTitle] = useState(''); + const [description, setDescription] = useState(''); + + const [addMutation] = useMutation(ADD_EVENT_PROJECT_MUTATION); + + const notify = (e: React.FormEvent): Promise => { + e.preventDefault(); + return toast.promise(handleSubmit, { + pending: 'Adding the project...', + success: 'Added the project successfully!', + error: 'There was an error in adding the project!', + }); + }; + + const handleSubmit = async (): Promise => { + let toSubmit = true; + if (title.trim().length == 0) { + toast.error('Title cannot be empty!'); + toSubmit = false; + } + if (description.trim().length == 0) { + toast.error('Description cannot be empty!'); + toSubmit = false; + } + if (!toSubmit) return Promise.reject(); + await addMutation({ + variables: { + title, + description, + eventId, + }, + }); + refetchData(); + setTitle(''); + setDescription(''); + handleClose(); + }; + + return ( + <> + + + Add an Event Project + +
    + + + Title + setTitle(e.target.value)} + /> + + + + Description + setDescription(e.target.value)} + /> + + + + + +
    +
    + + ); +}; diff --git a/src/components/EventProjectModals/DeleteEventProjectModal.test.tsx b/src/components/EventProjectModals/DeleteEventProjectModal.test.tsx new file mode 100644 index 0000000000..6a29735f2e --- /dev/null +++ b/src/components/EventProjectModals/DeleteEventProjectModal.test.tsx @@ -0,0 +1,108 @@ +import React from 'react'; +import { fireEvent, render, waitFor } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { DeleteEventProjectModal } from './DeleteEventProjectModal'; +import { DELETE_EVENT_PROJECT_MUTATION } from 'GraphQl/Mutations/mutations'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; +import { ToastContainer } from 'react-toastify'; + +const successfulMutationMock = [ + { + request: { + query: DELETE_EVENT_PROJECT_MUTATION, + variables: { id: '123' }, + }, + result: { + data: { + removeEventProject: { + _id: '123', + }, + }, + }, + }, +]; + +const unsuccessfulMutationMock = [ + { + request: { + query: DELETE_EVENT_PROJECT_MUTATION, + variables: { id: '123' }, + }, + error: new Error('Oops'), + }, +]; + +describe('Testing Delete Event Project Modal', () => { + const props = { + show: true, + project: { + _id: '123', + title: 'Test Event Project', + description: 'Test Event Project Description', + }, + handleClose: jest.fn(), + refetchData: jest.fn(), + }; + + test('The modal should be rendered and delete button should work', async () => { + const { queryByText } = render( + + + + + + + + + + + ); + + await waitFor(() => + expect(queryByText('Delete Event Project')).toBeInTheDocument() + ); + + fireEvent.click(queryByText('Delete') as Element); + await waitFor(() => + expect(queryByText('Deleting the project...')).toBeInTheDocument() + ); + await waitFor(() => + expect( + queryByText('Deleted the project successfully!') + ).toBeInTheDocument() + ); + }); + + test('The modal should be rendered and error message should be shown if mutation fails', async () => { + const { queryByText } = render( + + + + + + + + + + + ); + + await waitFor(() => + expect(queryByText('Delete Event Project')).toBeInTheDocument() + ); + + fireEvent.click(queryByText('Delete') as Element); + await waitFor(() => + expect(queryByText('Deleting the project...')).toBeInTheDocument() + ); + await waitFor(() => + expect( + queryByText('There was an error in deleting the project details!') + ).toBeInTheDocument() + ); + }); +}); diff --git a/src/components/EventProjectModals/DeleteEventProjectModal.tsx b/src/components/EventProjectModals/DeleteEventProjectModal.tsx new file mode 100644 index 0000000000..042e2fcd15 --- /dev/null +++ b/src/components/EventProjectModals/DeleteEventProjectModal.tsx @@ -0,0 +1,70 @@ +import React from 'react'; +import { Modal, Button } from 'react-bootstrap'; +import { toast } from 'react-toastify'; +import { useMutation } from '@apollo/client'; +import { DELETE_EVENT_PROJECT_MUTATION } from 'GraphQl/Mutations/mutations'; + +type ModalPropType = { + show: boolean; + project: { + _id: string; + title: string; + description: string; + }; + handleClose: () => void; + refetchData: () => void; +}; + +export const DeleteEventProjectModal = (props: ModalPropType): JSX.Element => { + const [deleteMutation] = useMutation(DELETE_EVENT_PROJECT_MUTATION); + + const notify = (): Promise => { + return toast.promise(deleteProject, { + pending: 'Deleting the project...', + success: 'Deleted the project successfully!', + error: 'There was an error in deleting the project details!', + }); + }; + const deleteProject = async (): Promise => { + await deleteMutation({ + variables: { + id: props.project._id, + }, + }); + + props.refetchData(); + props.handleClose(); + }; + + return ( + <> + + + Delete Event Project + + +
    + Are you sure you want to delete this? +
    +
    + + + + +
    + + ); +}; diff --git a/src/components/EventProjectModals/UpdateEventProjectModal.test.tsx b/src/components/EventProjectModals/UpdateEventProjectModal.test.tsx new file mode 100644 index 0000000000..b184b24f75 --- /dev/null +++ b/src/components/EventProjectModals/UpdateEventProjectModal.test.tsx @@ -0,0 +1,155 @@ +import React from 'react'; +import { fireEvent, render, waitFor } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { UpdateEventProjectModal } from './UpdateEventProjectModal'; +import { UPDATE_EVENT_PROJECT_MUTATION } from 'GraphQl/Mutations/mutations'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; +import { ToastContainer } from 'react-toastify'; + +const successfulMutationMock = [ + { + request: { + query: UPDATE_EVENT_PROJECT_MUTATION, + variables: { + title: 'NewTitle', + description: 'NewDescription', + id: '123', + }, + }, + result: { + data: { + updateEventProject: { + _id: '123', + }, + }, + }, + }, +]; + +const unsuccessfulMutationMock = [ + { + request: { + query: UPDATE_EVENT_PROJECT_MUTATION, + variables: { + title: 'NewTitle', + description: 'NewDescription', + id: '123', + }, + }, + error: new Error('Oops'), + }, +]; + +describe('Testing Update Event Project Modal', () => { + const props = { + show: true, + project: { + title: 'OldTitle', + description: 'OldDescription', + _id: '123', + }, + handleClose: jest.fn(), + refetchData: jest.fn(), + }; + + test('The modal should be rendered, the default text should be added from the props and update button should not work with blank values', async () => { + const { queryByText, queryByLabelText } = render( + + + + + + + + + + + ); + + await waitFor(() => + expect(queryByText('Update Event Project')).toBeInTheDocument() + ); + + // Check for already populated values + await waitFor(() => + expect(queryByLabelText('Title')).toHaveValue('OldTitle') + ); + await waitFor(() => + expect(queryByLabelText('Description')).toHaveValue('OldDescription') + ); + + // Update the values to blank ones + // Type in the title and the description of the event project + fireEvent.change(queryByLabelText('Title') as Element, { + target: { value: '' }, + }); + fireEvent.change(queryByLabelText('Description') as Element, { + target: { value: '' }, + }); + + fireEvent.click(queryByText('Update Details') as Element); + + // Check for blank entry warning modals + await waitFor(() => + expect(queryByText('Title cannot be empty!')).toBeInTheDocument() + ); + await waitFor(() => + expect(queryByText('Description cannot be empty!')).toBeInTheDocument() + ); + + // Set the title and the description of the event project to new values + fireEvent.change(queryByLabelText('Title') as Element, { + target: { value: 'NewTitle' }, + }); + fireEvent.change(queryByLabelText('Description') as Element, { + target: { value: 'NewDescription' }, + }); + + fireEvent.click(queryByText('Update Details') as Element); + + await waitFor(() => + expect(queryByText('Updating the project...')).toBeInTheDocument() + ); + + await waitFor(() => + expect( + queryByText('Updated the project successfully!') + ).toBeInTheDocument() + ); + }); + + test('The modal should be rendered and error message should be shown if mutation fails', async () => { + const { queryByText, queryByLabelText } = render( + + + + + + + + + + + ); + + // Type in the title and the description of the event project + fireEvent.change(queryByLabelText('Title') as Element, { + target: { value: 'NewTitle' }, + }); + fireEvent.change(queryByLabelText('Description') as Element, { + target: { value: 'NewDescription' }, + }); + + fireEvent.click(queryByText('Update Details') as Element); + + await waitFor(() => + expect( + queryByText('There was an error in updating the project details!') + ).toBeInTheDocument() + ); + }); +}); diff --git a/src/components/EventProjectModals/UpdateEventProjectModal.tsx b/src/components/EventProjectModals/UpdateEventProjectModal.tsx new file mode 100644 index 0000000000..08ac230c69 --- /dev/null +++ b/src/components/EventProjectModals/UpdateEventProjectModal.tsx @@ -0,0 +1,103 @@ +import React, { useEffect, useState } from 'react'; +import { Modal, Button, Form } from 'react-bootstrap'; +import { toast } from 'react-toastify'; +import { useMutation } from '@apollo/client'; +import { UPDATE_EVENT_PROJECT_MUTATION } from 'GraphQl/Mutations/mutations'; + +type ModalPropType = { + show: boolean; + project: { + _id: string; + title: string; + description: string; + }; + handleClose: () => void; + refetchData: () => void; +}; + +export const UpdateEventProjectModal = (props: ModalPropType): JSX.Element => { + const [title, setTitle] = useState(''); + const [description, setDescription] = useState(''); + + useEffect(() => { + setTitle(props.project.title); + setDescription(props.project.description); + }, [props.project]); + + const [updateMutation] = useMutation(UPDATE_EVENT_PROJECT_MUTATION); + const notify = (e: React.FormEvent): Promise => { + e.preventDefault(); + return toast.promise(handleSubmit, { + pending: 'Updating the project...', + success: 'Updated the project successfully!', + error: 'There was an error in updating the project details!', + }); + }; + const handleSubmit = async (): Promise => { + let toSubmit = true; + + if (title.trim().length == 0) { + toast.error('Title cannot be empty!'); + toSubmit = false; + } + if (description.trim().length == 0) { + toast.error('Description cannot be empty!'); + toSubmit = false; + } + if (!toSubmit) return Promise.reject(); + await updateMutation({ + variables: { + id: props.project._id, + title, + description, + }, + }); + props.refetchData(); + props.handleClose(); + }; + + return ( + <> + + + Update Event Project + +
    + + + Title + setTitle(e.target.value)} + /> + + + + Description + setDescription(e.target.value)} + /> + + + + + +
    +
    + + ); +}; diff --git a/src/components/EventRegistrantsModal/EventRegistrantsModal.module.css b/src/components/EventRegistrantsModal/EventRegistrantsModal.module.css new file mode 100644 index 0000000000..0f78d81c01 --- /dev/null +++ b/src/components/EventRegistrantsModal/EventRegistrantsModal.module.css @@ -0,0 +1,43 @@ +.loader, +.loader:after { + border-radius: 50%; + width: 10em; + height: 10em; +} +.loader { + margin: 60px auto; + margin-top: 35vh !important; + font-size: 10px; + position: relative; + text-indent: -9999em; + border-top: 1.1em solid rgba(255, 255, 255, 0.2); + border-right: 1.1em solid rgba(255, 255, 255, 0.2); + border-bottom: 1.1em solid rgba(255, 255, 255, 0.2); + border-left: 1.1em solid #febc59; + -webkit-transform: translateZ(0); + -ms-transform: translateZ(0); + transform: translateZ(0); + -webkit-animation: load8 1.1s infinite linear; + animation: load8 1.1s infinite linear; +} + +@-webkit-keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} +@keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} diff --git a/src/components/EventRegistrantsModal/EventRegistrantsModal.test.tsx b/src/components/EventRegistrantsModal/EventRegistrantsModal.test.tsx new file mode 100644 index 0000000000..3e06f784f4 --- /dev/null +++ b/src/components/EventRegistrantsModal/EventRegistrantsModal.test.tsx @@ -0,0 +1,336 @@ +import React from 'react'; +import { fireEvent, render, waitFor } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { EventRegistrantsModal } from './EventRegistrantsModal'; +import { EVENT_ATTENDEES, MEMBERS_LIST } from 'GraphQl/Queries/Queries'; +import { + ADD_EVENT_ATTENDEE, + REMOVE_EVENT_ATTENDEE, +} from 'GraphQl/Mutations/mutations'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; +import { ToastContainer } from 'react-toastify'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; + +const queryMockWithoutRegistrant = [ + { + request: { + query: EVENT_ATTENDEES, + variables: { id: 'event123' }, + }, + result: { + data: { + event: { + attendees: [], + }, + }, + }, + }, +]; + +const queryMockWithRegistrant = [ + { + request: { + query: EVENT_ATTENDEES, + variables: { id: 'event123' }, + }, + result: { + data: { + event: { + attendees: [{ _id: 'user1', firstName: 'John', lastName: 'Doe' }], + }, + }, + }, + }, +]; + +const queryMockOrgMembers = [ + { + request: { + query: MEMBERS_LIST, + variables: { id: 'org123' }, + }, + result: { + data: { + organizations: [ + { + _id: 'org123', + members: [ + { + _id: 'user1', + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@palisadoes.com', + image: '', + createdAt: '12/12/22', + organizationsBlockedBy: [], + }, + ], + }, + ], + }, + }, + }, +]; + +const successfulAddRegistrantMock = [ + { + request: { + query: ADD_EVENT_ATTENDEE, + variables: { userId: 'user1', eventId: 'event123' }, + }, + result: { + data: { + addEventAttendee: { _id: 'user1' }, + }, + }, + }, +]; + +const unsuccessfulAddRegistrantMock = [ + { + request: { + query: ADD_EVENT_ATTENDEE, + variables: { userId: 'user1', eventId: 'event123' }, + }, + error: new Error('Oops'), + }, +]; + +const successfulRemoveRegistrantMock = [ + { + request: { + query: REMOVE_EVENT_ATTENDEE, + variables: { userId: 'user1', eventId: 'event123' }, + }, + result: { + data: { + removeEventAttendee: { _id: 'user1' }, + }, + }, + }, +]; + +const unsuccessfulRemoveRegistrantMock = [ + { + request: { + query: REMOVE_EVENT_ATTENDEE, + variables: { userId: 'user1', eventId: 'event123' }, + }, + error: new Error('Oops'), + }, +]; + +describe('Testing Event Registrants Modal', () => { + const props = { + show: true, + eventId: 'event123', + orgId: 'org123', + handleClose: jest.fn(), + }; + + test('The modal should be rendered, correct text must be displayed when there are no attendees and add attendee mutation must function properly', async () => { + const { queryByText, queryByLabelText } = render( + + + + + + + + + + + + + ); + + await waitFor(() => + expect(queryByText('Event Registrants')).toBeInTheDocument() + ); + + await waitFor(() => + expect(queryByText('Registered Registrants')).toBeInTheDocument() + ); + + await waitFor(() => + expect( + queryByText('There are no registered attendees for this event.') + ).toBeInTheDocument() + ); + + // Get warning modal on blank button click + fireEvent.click(queryByText('Add Registrant') as Element); + + await waitFor(() => + expect( + queryByText('Please choose an user to add first!') + ).toBeInTheDocument() + ); + + // Choose a user to add as an attendee + const attendeeInput = queryByLabelText('Add an Registrant'); + fireEvent.change(attendeeInput as Element, { + target: { value: 'John Doe' }, + }); + fireEvent.keyDown(attendeeInput as HTMLElement, { key: 'ArrowDown' }); + fireEvent.keyDown(attendeeInput as HTMLElement, { key: 'Enter' }); + + fireEvent.click(queryByText('Add Registrant') as Element); + + await waitFor(() => + expect(queryByText('Adding the attendee...')).toBeInTheDocument() + ); + + await waitFor(() => + expect( + queryByText('Added the attendee successfully!') + ).toBeInTheDocument() + ); + }); + + test('Add attendee mutation must fail properly', async () => { + const { queryByText, queryByLabelText } = render( + + + + + + + + + + + + + ); + + await waitFor(() => + expect( + queryByText('There are no registered attendees for this event.') + ).toBeInTheDocument() + ); + + // Choose a user to add as an attendee + const attendeeInput = queryByLabelText('Add an Registrant'); + fireEvent.change(attendeeInput as Element, { + target: { value: 'John Doe' }, + }); + fireEvent.keyDown(attendeeInput as HTMLElement, { key: 'ArrowDown' }); + fireEvent.keyDown(attendeeInput as HTMLElement, { key: 'Enter' }); + + fireEvent.click(queryByText('Add Registrant') as Element); + + await waitFor(() => + expect(queryByText('Adding the attendee...')).toBeInTheDocument() + ); + + await waitFor(() => + expect( + queryByText('There was an error in adding the attendee!') + ).toBeInTheDocument() + ); + }); + + test('Assigned attendees must be shown with badges and delete attendee mutation must function properly', async () => { + const { queryByText, queryByTestId } = render( + + + + + + + + + + + + + ); + + await waitFor(() => + expect(queryByText('Registered Registrants')).toBeInTheDocument() + ); + + await waitFor(() => expect(queryByText('John Doe')).toBeInTheDocument()); + + fireEvent.click(queryByTestId('CancelIcon') as Element); + + await waitFor(() => + expect(queryByText('Removing the attendee...')).toBeInTheDocument() + ); + + await waitFor(() => + expect( + queryByText('Removed the attendee successfully!') + ).toBeInTheDocument() + ); + }); + + test('Delete attendee mutation must fail properly', async () => { + const { queryByText, queryByTestId } = render( + + + + + + + + + + + + + ); + + await waitFor(() => + expect(queryByText('Registered Registrants')).toBeInTheDocument() + ); + + await waitFor(() => expect(queryByText('John Doe')).toBeInTheDocument()); + + fireEvent.click(queryByTestId('CancelIcon') as Element); + + await waitFor(() => + expect(queryByText('Removing the attendee...')).toBeInTheDocument() + ); + + await waitFor(() => + expect( + queryByText('There was an error in removing the attendee!') + ).toBeInTheDocument() + ); + }); +}); diff --git a/src/components/EventRegistrantsModal/EventRegistrantsModal.tsx b/src/components/EventRegistrantsModal/EventRegistrantsModal.tsx new file mode 100644 index 0000000000..a75c9d942d --- /dev/null +++ b/src/components/EventRegistrantsModal/EventRegistrantsModal.tsx @@ -0,0 +1,156 @@ +import React, { useState } from 'react'; +import { Modal, Button } from 'react-bootstrap'; +import { toast } from 'react-toastify'; +import { useMutation } from '@apollo/client'; +import { useQuery } from '@apollo/client'; +import { EVENT_ATTENDEES, MEMBERS_LIST } from 'GraphQl/Queries/Queries'; +import { + ADD_EVENT_ATTENDEE, + REMOVE_EVENT_ATTENDEE, +} from 'GraphQl/Mutations/mutations'; +import styles from 'components/EventRegistrantsModal/EventRegistrantsModal.module.css'; +import Avatar from '@mui/material/Avatar'; +import Chip from '@mui/material/Chip'; +import Stack from '@mui/material/Stack'; +import TextField from '@mui/material/TextField'; +import Autocomplete from '@mui/material/Autocomplete'; + +type ModalPropType = { + show: boolean; + eventId: string; + orgId: string; + handleClose: () => void; +}; + +interface InterfaceUser { + _id: string; + firstName: string; + lastName: string; +} + +export const EventRegistrantsModal = (props: ModalPropType): JSX.Element => { + const [member, setMember] = useState(null); + + const [addRegistrantMutation] = useMutation(ADD_EVENT_ATTENDEE); + const [removeRegistrantMutation] = useMutation(REMOVE_EVENT_ATTENDEE); + + const { + data: attendeesData, + loading: attendeesLoading, + refetch: attendeesRefetch, + } = useQuery(EVENT_ATTENDEES, { + variables: { id: props.eventId }, + }); + + const { data: memberData, loading: memberLoading } = useQuery(MEMBERS_LIST, { + variables: { id: props.orgId }, + }); + + const addRegistrant = (): void => { + if (member == null) { + toast.warning('Please choose an user to add first!'); + return; + } + toast.warn('Adding the attendee...'); + addRegistrantMutation({ + variables: { + userId: member._id, + eventId: props.eventId, + }, + }) + .then(() => { + toast.success('Added the attendee successfully!'); + attendeesRefetch(); + }) + .catch((err) => { + toast.error('There was an error in adding the attendee!'); + toast.error(err.message); + }); + }; + + const deleteRegistrant = (userId: string): void => { + toast.warn('Removing the attendee...'); + removeRegistrantMutation({ + variables: { + userId, + eventId: props.eventId, + }, + }) + .then(() => { + toast.success('Removed the attendee successfully!'); + attendeesRefetch(); + }) + .catch((err) => { + toast.error('There was an error in removing the attendee!'); + toast.error(err.message); + }); + }; + + // Render the loading screen + if (attendeesLoading || memberLoading) { + return ( + <> +
    + + ); + } + + return ( + <> + + + Event Registrants + + +
    Registered Registrants
    + {attendeesData.event.attendees.length == 0 + ? `There are no registered attendees for this event.` + : null} + + {attendeesData.event.attendees.map((attendee: InterfaceUser) => ( + {`${attendee.firstName[0]}${attendee.lastName[0]}`} + } + label={`${attendee.firstName} ${attendee.lastName}`} + variant="outlined" + key={attendee._id} + onDelete={(): void => deleteRegistrant(attendee._id)} + /> + ))} + +
    + + { + setMember(newMember); + }} + options={memberData.organizations[0].members} + getOptionLabel={(member: InterfaceUser): string => + `${member.firstName} ${member.lastName}` + } + renderInput={(params): React.ReactNode => ( + + )} + /> +
    +
    + + + +
    + + ); +}; diff --git a/src/components/EventRegistrantsModal/EventRegistrantsWrapper.module.css b/src/components/EventRegistrantsModal/EventRegistrantsWrapper.module.css new file mode 100644 index 0000000000..59b31333af --- /dev/null +++ b/src/components/EventRegistrantsModal/EventRegistrantsWrapper.module.css @@ -0,0 +1,13 @@ +button .iconWrapper { + width: 36px; + padding-right: 4px; + margin-right: 4px; + transform: translateY(4px); +} + +button .iconWrapperSm { + width: 36px; + display: flex; + justify-content: center; + align-items: center; +} diff --git a/src/components/EventRegistrantsModal/EventRegistrantsWrapper.test.tsx b/src/components/EventRegistrantsModal/EventRegistrantsWrapper.test.tsx new file mode 100644 index 0000000000..19d33803c4 --- /dev/null +++ b/src/components/EventRegistrantsModal/EventRegistrantsWrapper.test.tsx @@ -0,0 +1,92 @@ +import React from 'react'; +import { fireEvent, render, waitFor } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { EventRegistrantsWrapper } from './EventRegistrantsWrapper'; +import { EVENT_ATTENDEES, MEMBERS_LIST } from 'GraphQl/Queries/Queries'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; +import { ToastContainer } from 'react-toastify'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; + +const queryMock = [ + { + request: { + query: EVENT_ATTENDEES, + variables: { id: 'event123' }, + }, + result: { + data: { + event: { + attendees: [], + }, + }, + }, + }, + { + request: { + query: MEMBERS_LIST, + variables: { id: 'org123' }, + }, + result: { + data: { + organizations: [ + { + _id: 'org123', + members: [ + { + _id: 'user1', + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@palisadoes.com', + image: '', + createdAt: '12/12/22', + organizationsBlockedBy: [], + }, + ], + }, + ], + }, + }, + }, +]; + +describe('Testing Event Registrants Wrapper', () => { + const props = { + eventId: 'event123', + orgId: 'org123', + }; + + test('The button should work properly', async () => { + const { queryByText, queryByRole } = render( + + + + + + + + + + + + + ); + + // Open the modal + fireEvent.click(queryByText('Show Registrants') as Element); + + await waitFor(() => + expect(queryByText('Event Registrants')).toBeInTheDocument() + ); + + // Close the modal + fireEvent.click(queryByRole('button', { name: /close/i }) as HTMLElement); + await waitFor(() => + expect(queryByText('Event Registrants')).not.toBeInTheDocument() + ); + }); +}); diff --git a/src/components/EventRegistrantsModal/EventRegistrantsWrapper.tsx b/src/components/EventRegistrantsModal/EventRegistrantsWrapper.tsx new file mode 100644 index 0000000000..b621f8673a --- /dev/null +++ b/src/components/EventRegistrantsModal/EventRegistrantsWrapper.tsx @@ -0,0 +1,46 @@ +import React, { useState } from 'react'; +import { EventRegistrantsModal } from './EventRegistrantsModal'; +import { Button } from 'react-bootstrap'; +import IconComponent from 'components/IconComponent/IconComponent'; +import styles from './EventRegistrantsWrapper.module.css'; + +type PropType = { + eventId: string; + orgId: string; +}; + +export const EventRegistrantsWrapper = (props: PropType): JSX.Element => { + const [showModal, setShowModal] = useState(false); + + return ( + <> + + + {showModal && ( + { + setShowModal(false); + }} + eventId={props.eventId} + orgId={props.orgId} + /> + )} + + ); +}; diff --git a/src/components/EventStats/EventStats.test.tsx b/src/components/EventStats/EventStats.test.tsx new file mode 100644 index 0000000000..c02e0dd619 --- /dev/null +++ b/src/components/EventStats/EventStats.test.tsx @@ -0,0 +1,62 @@ +import React from 'react'; +import { render, waitFor } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { EventStats } from './EventStats'; +import { BrowserRouter } from 'react-router-dom'; +import { EVENT_FEEDBACKS } from 'GraphQl/Queries/Queries'; + +// Mock the modules for PieChart rendering as they require a trasformer being used (which is not done by Jest) +// These modules are used by the Feedback component +jest.mock('@mui/x-charts/PieChart', () => ({ + pieArcLabelClasses: jest.fn(), + PieChart: jest.fn().mockImplementation(() => <>Test), + pieArcClasses: jest.fn(), +})); + +const mockData = [ + { + request: { + query: EVENT_FEEDBACKS, + variables: { + id: 'eventStats123', + }, + }, + result: { + data: { + event: { + _id: 'eventStats123', + feedback: [ + { + _id: 'feedback1', + review: 'review1', + rating: 5, + }, + ], + averageFeedbackScore: 5, + }, + }, + }, + }, +]; + +describe('Testing Event Stats', () => { + const props = { + eventId: 'eventStats123', + show: true, + handleClose: jest.fn(), + }; + + test('The stats should be rendered properly', async () => { + const { queryByText } = render( + + + + + + ); + + await waitFor(() => + expect(queryByText('Event Statistics')).toBeInTheDocument() + ); + }); +}); diff --git a/src/components/EventStats/EventStats.tsx b/src/components/EventStats/EventStats.tsx new file mode 100644 index 0000000000..6158c39075 --- /dev/null +++ b/src/components/EventStats/EventStats.tsx @@ -0,0 +1,59 @@ +import React from 'react'; +import { Modal } from 'react-bootstrap'; +import { FeedbackStats } from './Statistics/Feedback'; +import { ReviewStats } from './Statistics/Review'; +import { AverageRating } from './Statistics/AverageRating'; +import Stack from '@mui/material/Stack'; +import styles from './Loader.module.css'; +import { useQuery } from '@apollo/client'; +import { EVENT_FEEDBACKS } from 'GraphQl/Queries/Queries'; + +type ModalPropType = { + show: boolean; + eventId: string; + handleClose: () => void; +}; + +export const EventStats = ({ + show, + handleClose, + eventId, +}: ModalPropType): JSX.Element => { + const { data, loading } = useQuery(EVENT_FEEDBACKS, { + variables: { id: eventId }, + }); + + // Render the loading screen + if (loading) { + return ( + <> +
    + + ); + } + + return ( + <> + + + Event Statistics + + + + +
    + + +
    +
    +
    +
    + + ); +}; diff --git a/src/components/EventStats/EventStatsWrapper.module.css b/src/components/EventStats/EventStatsWrapper.module.css new file mode 100644 index 0000000000..f5f42546c3 --- /dev/null +++ b/src/components/EventStats/EventStatsWrapper.module.css @@ -0,0 +1,13 @@ +button .iconWrapper { + width: 32px; + padding-right: 4px; + margin-right: 4px; + transform: translateY(4px); +} + +button .iconWrapperSm { + width: 32px; + display: flex; + justify-content: center; + align-items: center; +} diff --git a/src/components/EventStats/EventStatsWrapper.test.tsx b/src/components/EventStats/EventStatsWrapper.test.tsx new file mode 100644 index 0000000000..726ffa2b43 --- /dev/null +++ b/src/components/EventStats/EventStatsWrapper.test.tsx @@ -0,0 +1,76 @@ +import React from 'react'; +import { fireEvent, render, waitFor } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { EventStatsWrapper } from './EventStatsWrapper'; +import { BrowserRouter } from 'react-router-dom'; +import { EVENT_FEEDBACKS } from 'GraphQl/Queries/Queries'; + +// Mock the modules for PieChart rendering as they require a trasformer being used (which is not done by Jest) +jest.mock('@mui/x-charts/PieChart', () => ({ + pieArcLabelClasses: jest.fn(), + PieChart: jest.fn().mockImplementation(() => <>Test), + pieArcClasses: jest.fn(), +})); + +const mockData = [ + { + request: { + query: EVENT_FEEDBACKS, + variables: { + id: 'eventStats123', + }, + }, + result: { + data: { + event: { + _id: 'eventStats123', + feedback: [ + { + _id: 'feedback1', + review: 'review1', + rating: 5, + }, + ], + averageFeedbackScore: 5, + }, + }, + }, + }, +]; + +// Mock the modules for PieChart rendering as they require a trasformer being used (which is not done by Jest) +// These modules are used by the Feedback component +jest.mock('@mui/x-charts/PieChart', () => ({ + pieArcLabelClasses: jest.fn(), + PieChart: jest.fn().mockImplementation(() => <>Test), + pieArcClasses: jest.fn(), +})); + +describe('Testing Event Stats Wrapper', () => { + const props = { + eventId: 'eventStats123', + }; + + test('The button to open and close the modal should work properly', async () => { + const { queryByText, queryByRole } = render( + + + + + + ); + + // Open the modal + fireEvent.click(queryByText('View Event Statistics') as Element); + + await waitFor(() => + expect(queryByText('Event Statistics')).toBeInTheDocument() + ); + + // Close the modal + fireEvent.click(queryByRole('button', { name: /close/i }) as HTMLElement); + await waitFor(() => + expect(queryByText('Event Statistics')).not.toBeInTheDocument() + ); + }); +}); diff --git a/src/components/EventStats/EventStatsWrapper.tsx b/src/components/EventStats/EventStatsWrapper.tsx new file mode 100644 index 0000000000..b501e77430 --- /dev/null +++ b/src/components/EventStats/EventStatsWrapper.tsx @@ -0,0 +1,37 @@ +import React, { useState } from 'react'; +import { EventStats } from './EventStats'; +import { Button } from 'react-bootstrap'; +import IconComponent from 'components/IconComponent/IconComponent'; +import styles from './EventStatsWrapper.module.css'; + +type PropType = { + eventId: string; +}; + +export const EventStatsWrapper = (props: PropType): JSX.Element => { + const [showModal, setShowModal] = useState(false); + + return ( + <> + + setShowModal(false)} + key={props.eventId || 'eventStatsDetails'} + eventId={props.eventId} + /> + + ); +}; diff --git a/src/components/EventStats/Loader.module.css b/src/components/EventStats/Loader.module.css new file mode 100644 index 0000000000..0f78d81c01 --- /dev/null +++ b/src/components/EventStats/Loader.module.css @@ -0,0 +1,43 @@ +.loader, +.loader:after { + border-radius: 50%; + width: 10em; + height: 10em; +} +.loader { + margin: 60px auto; + margin-top: 35vh !important; + font-size: 10px; + position: relative; + text-indent: -9999em; + border-top: 1.1em solid rgba(255, 255, 255, 0.2); + border-right: 1.1em solid rgba(255, 255, 255, 0.2); + border-bottom: 1.1em solid rgba(255, 255, 255, 0.2); + border-left: 1.1em solid #febc59; + -webkit-transform: translateZ(0); + -ms-transform: translateZ(0); + transform: translateZ(0); + -webkit-animation: load8 1.1s infinite linear; + animation: load8 1.1s infinite linear; +} + +@-webkit-keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} +@keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} diff --git a/src/components/EventStats/Statistics/AverageRating.test.tsx b/src/components/EventStats/Statistics/AverageRating.test.tsx new file mode 100644 index 0000000000..53f0acacba --- /dev/null +++ b/src/components/EventStats/Statistics/AverageRating.test.tsx @@ -0,0 +1,58 @@ +import React from 'react'; +import { render, waitFor } from '@testing-library/react'; +import { AverageRating } from './AverageRating'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; +import { ToastContainer } from 'react-toastify'; + +const props = { + data: { + event: { + _id: '123', + feedback: [ + { + _id: 'feedback1', + review: 'review1', + rating: 5, + }, + { + _id: 'feedback2', + review: 'review2', + rating: 5, + }, + { + _id: 'feedback3', + review: null, + rating: 5, + }, + ], + averageFeedbackScore: 5, + }, + }, +}; + +describe('Testing Average Rating Card', () => { + test('The component should be rendered and the Score should be shown', async () => { + const { queryByText } = render( + + + + + + + + + ); + + await waitFor(() => + expect(queryByText('Average Review Score')).toBeInTheDocument() + ); + + await waitFor(() => + expect(queryByText('Rated 5.00 / 5')).toBeInTheDocument() + ); + }); +}); diff --git a/src/components/EventStats/Statistics/AverageRating.tsx b/src/components/EventStats/Statistics/AverageRating.tsx new file mode 100644 index 0000000000..a3769934d8 --- /dev/null +++ b/src/components/EventStats/Statistics/AverageRating.tsx @@ -0,0 +1,60 @@ +import React from 'react'; +import Card from 'react-bootstrap/Card'; +import Rating from '@mui/material/Rating'; +import FavoriteIcon from '@mui/icons-material/Favorite'; +import FavoriteBorderIcon from '@mui/icons-material/FavoriteBorder'; +import Typography from '@mui/material/Typography'; +import { styled } from '@mui/material/styles'; + +type ModalPropType = { + data: { + event: { + _id: string; + averageFeedbackScore: number; + feedback: FeedbackType[]; + }; + }; +}; + +type FeedbackType = { + _id: string; + rating: number; + review: string | null; +}; + +// eslint-disable-next-line @typescript-eslint/naming-convention +const StyledRating = styled(Rating)({ + '& .MuiRating-iconFilled': { + color: '#ff6d75', + }, + '& .MuiRating-iconHover': { + color: '#ff3d47', + }, +}); + +export const AverageRating = ({ data }: ModalPropType): JSX.Element => { + return ( + <> + + + +

    Average Review Score

    +
    + + Rated {data.event.averageFeedbackScore.toFixed(2)} / 5 + + } + size="medium" + emptyIcon={} + /> +
    +
    + + ); +}; diff --git a/src/components/EventStats/Statistics/Feedback.test.tsx b/src/components/EventStats/Statistics/Feedback.test.tsx new file mode 100644 index 0000000000..0a8b5a571d --- /dev/null +++ b/src/components/EventStats/Statistics/Feedback.test.tsx @@ -0,0 +1,100 @@ +import React from 'react'; +import { render, waitFor } from '@testing-library/react'; +import { FeedbackStats } from './Feedback'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; +import { ToastContainer } from 'react-toastify'; + +// Mock the modules for PieChart rendering as they require a trasformer being used (which is not done by Jest) +jest.mock('@mui/x-charts/PieChart', () => ({ + pieArcLabelClasses: jest.fn(), + PieChart: jest.fn().mockImplementation(() => <>Test), + pieArcClasses: jest.fn(), +})); + +const nonEmptyProps = { + data: { + event: { + _id: '123', + feedback: [ + { + _id: 'feedback1', + review: 'review1', + rating: 5, + }, + { + _id: 'feedback2', + review: 'review2', + rating: 5, + }, + { + _id: 'feedback3', + review: null, + rating: 5, + }, + ], + averageFeedbackScore: 5, + }, + }, +}; + +const emptyProps = { + data: { + event: { + _id: '123', + feedback: [], + averageFeedbackScore: 5, + }, + }, +}; + +describe('Testing Feedback Statistics Card', () => { + test('The component should be rendered and the feedback should be shown if present', async () => { + const { queryByText } = render( + + + + + + + + + ); + + await waitFor(() => + expect(queryByText('Feedback Analysis')).toBeInTheDocument() + ); + + await waitFor(() => + expect( + queryByText('3 people have filled feedback for this event.') + ).toBeInTheDocument() + ); + }); + + test('The component should be rendered and message should be shown if no feedback is present', async () => { + const { queryByText } = render( + + + + + + + + + ); + + await waitFor(() => + expect(queryByText('Feedback Analysis')).toBeInTheDocument() + ); + + await waitFor(() => + expect( + queryByText('Please ask attendees to submit feedback for insights!') + ).toBeInTheDocument() + ); + }); +}); diff --git a/src/components/EventStats/Statistics/Feedback.tsx b/src/components/EventStats/Statistics/Feedback.tsx new file mode 100644 index 0000000000..ff4fe7a647 --- /dev/null +++ b/src/components/EventStats/Statistics/Feedback.tsx @@ -0,0 +1,102 @@ +import React from 'react'; +import { + PieChart, + pieArcClasses, + pieArcLabelClasses, +} from '@mui/x-charts/PieChart'; +import Card from 'react-bootstrap/Card'; + +type ModalPropType = { + data: { + event: { + _id: string; + averageFeedbackScore: number | null; + feedback: FeedbackType[]; + }; + }; +}; + +type FeedbackType = { + _id: string; + rating: number; + review: string | null; +}; + +export const FeedbackStats = ({ data }: ModalPropType): JSX.Element => { + const ratingColors = [ + '#57bb8a', // Green + '#94bd77', + '#d4c86a', + '#e9b861', + '#e79a69', + '#dd776e', // Red + ]; + + const count: Record = {}; + + data.event.feedback.forEach((feedback: FeedbackType) => { + if (feedback.rating in count) count[feedback.rating]++; + else count[feedback.rating] = 1; + }); + + const chartData = []; + for (let rating = 0; rating <= 5; rating++) { + if (rating in count) + chartData.push({ + id: rating, + value: count[rating], + label: `${rating} (${count[rating]})`, + color: ratingColors[5 - rating], + }); + } + + return ( + <> + + + +

    Feedback Analysis

    +
    +
    + {data.event.feedback.length} people have filled feedback for this + event. +
    + {data.event.feedback.length ? ( + `${item.id} (${item.value})`, + innerRadius: 30, + outerRadius: 120, + paddingAngle: 2, + cornerRadius: 5, + startAngle: 0, + highlightScope: { faded: 'global', highlighted: 'item' }, + faded: { innerRadius: 30, additionalRadius: -30 }, + }, + ]} + sx={{ + [`& .${pieArcClasses.faded}`]: { + fill: 'gray', + }, + [`& .${pieArcLabelClasses.root}`]: { + fill: 'black', + fontSize: '15px', + }, + [`& .${pieArcLabelClasses.faded}`]: { + display: 'none', + }, + }} + width={380} + height={380} + /> + ) : ( + <>Please ask attendees to submit feedback for insights! + )} +
    +
    + + ); +}; diff --git a/src/components/EventStats/Statistics/Review.test.tsx b/src/components/EventStats/Statistics/Review.test.tsx new file mode 100644 index 0000000000..ee9f79c54c --- /dev/null +++ b/src/components/EventStats/Statistics/Review.test.tsx @@ -0,0 +1,95 @@ +import React from 'react'; +import { render, waitFor } from '@testing-library/react'; +import { ReviewStats } from './Review'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; +import { ToastContainer } from 'react-toastify'; + +const nonEmptyReviewProps = { + data: { + event: { + _id: '123', + feedback: [ + { + _id: 'feedback1', + review: 'review1', + rating: 5, + }, + { + _id: 'feedback2', + review: 'review2', + rating: 5, + }, + { + _id: 'feedback3', + review: null, + rating: 5, + }, + ], + averageFeedbackScore: 5, + }, + }, +}; + +const emptyReviewProps = { + data: { + event: { + _id: '123', + feedback: [ + { + _id: 'feedback3', + review: null, + rating: 5, + }, + ], + averageFeedbackScore: 5, + }, + }, +}; + +describe('Testing Review Statistics Card', () => { + test('The component should be rendered and the reviews should be shown if present', async () => { + const { queryByText } = render( + + + + + + + + + ); + + await waitFor(() => expect(queryByText('Reviews')).toBeInTheDocument()); + + await waitFor(() => + expect(queryByText('Filled by 2 people.')).toBeInTheDocument() + ); + + await waitFor(() => expect(queryByText('review2')).toBeInTheDocument()); + }); + + test('The component should be rendered and message should be shown if no review is present', async () => { + const { queryByText } = render( + + + + + + + + + ); + + await waitFor(() => expect(queryByText('Reviews')).toBeInTheDocument()); + + await waitFor(() => + expect( + queryByText('Waiting for people to talk about the event...') + ).toBeInTheDocument() + ); + }); +}); diff --git a/src/components/EventStats/Statistics/Review.tsx b/src/components/EventStats/Statistics/Review.tsx new file mode 100644 index 0000000000..b5aecd61de --- /dev/null +++ b/src/components/EventStats/Statistics/Review.tsx @@ -0,0 +1,57 @@ +import React from 'react'; +import Card from 'react-bootstrap/Card'; +import Rating from '@mui/material/Rating'; + +type ModalPropType = { + data: { + event: { + _id: string; + averageFeedbackScore: number | null; + feedback: FeedbackType[]; + }; + }; +}; + +type FeedbackType = { + _id: string; + rating: number; + review: string | null; +}; + +export const ReviewStats = ({ data }: ModalPropType): JSX.Element => { + const reviews = data.event.feedback.filter( + (feedback: FeedbackType) => feedback.review != null + ); + + return ( + <> + + + +

    Reviews

    +
    +
    Filled by {reviews.length} people.
    + {reviews.length ? ( + reviews.map((review) => ( +
    +
    + +

    {review.review}

    +
    +
    + )) + ) : ( + <>Waiting for people to talk about the event... + )} +
    +
    + + ); +}; diff --git a/src/components/IconComponent/IconComponent.test.tsx b/src/components/IconComponent/IconComponent.test.tsx new file mode 100644 index 0000000000..ff83ebe57c --- /dev/null +++ b/src/components/IconComponent/IconComponent.test.tsx @@ -0,0 +1,69 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import IconComponent from './IconComponent'; + +const screenTestIdMap: Record> = { + Dashboard: { + name: 'Dashboard', + testId: 'Icon-Component-DashboardIcon', + }, + People: { + name: 'People', + testId: 'Icon-Component-PeopleIcon', + }, + Events: { + name: 'Events', + testId: 'Icon-Component-EventsIcon', + }, + Posts: { + name: 'Posts', + testId: 'Icon-Component-PostsIcon', + }, + BlockUnblock: { + name: 'Block/Unblock', + testId: 'Block/Icon-Component-UnblockIcon', + }, + Plugins: { + name: 'Plugins', + testId: 'Icon-Component-PluginsIcon', + }, + Settings: { + name: 'Settings', + testId: 'Icon-Component-SettingsIcon', + }, + AllOrganizations: { + name: 'All Organizations', + testId: 'Icon-Component-AllOrganizationsIcon', + }, + EventProject: { + name: 'Add Event Project', + testId: 'Icon-Component-Add-Event-Project', + }, + ListEventRegistrant: { + name: 'List Event Registrants', + testId: 'Icon-Component-List-Event-Registrants', + }, + CheckInRegistrants: { + name: 'Check In Registrants', + testId: 'Icon-Component-Check-In-Registrants', + }, + EventStats: { + name: 'Event Stats', + testId: 'Icon-Component-Event-Stats', + }, + default: { + name: 'default', + testId: 'Icon-Component-DefaultIcon', + }, +}; + +describe('Testing Collapsible Dropdown component', () => { + it('Renders the correct icon according to the component', () => { + for (const component in screenTestIdMap) { + render(); + expect( + screen.getByTestId(screenTestIdMap[component].testId) + ).toBeInTheDocument(); + } + }); +}); diff --git a/src/components/IconComponent/IconComponent.tsx b/src/components/IconComponent/IconComponent.tsx new file mode 100644 index 0000000000..4c490c9c94 --- /dev/null +++ b/src/components/IconComponent/IconComponent.tsx @@ -0,0 +1,103 @@ +import React from 'react'; +import { QuestionMarkOutlined } from '@mui/icons-material'; +import { ReactComponent as BlockUserIcon } from 'assets/svgs/blockUser.svg'; +import { ReactComponent as DashboardIcon } from 'assets/svgs/dashboard.svg'; +import { ReactComponent as EventsIcon } from 'assets/svgs/events.svg'; +import { ReactComponent as OrganizationsIcon } from 'assets/svgs/organizations.svg'; +import { ReactComponent as PeopleIcon } from 'assets/svgs/people.svg'; +import { ReactComponent as PluginsIcon } from 'assets/svgs/plugins.svg'; +import { ReactComponent as PostsIcon } from 'assets/svgs/posts.svg'; +import { ReactComponent as SettingsIcon } from 'assets/svgs/settings.svg'; +import { ReactComponent as AddEventProjectIcon } from 'assets/svgs/addEventProject.svg'; +import { ReactComponent as ListEventRegistrantsIcon } from 'assets/svgs/listEventRegistrants.svg'; +import { ReactComponent as CheckInRegistrantsIcon } from 'assets/svgs/checkInRegistrants.svg'; +import { ReactComponent as EventStatsIcon } from 'assets/svgs/eventStats.svg'; + +export interface InterfaceIconComponent { + name: string; + fill?: string; + height?: string; + width?: string; +} + +const iconComponent = (props: InterfaceIconComponent): JSX.Element => { + switch (props.name) { + case 'Dashboard': + return ( + + ); + case 'People': + return ; + case 'Events': + return ; + case 'Posts': + return ; + case 'Block/Unblock': + return ( + + ); + case 'Plugins': + return ( + + ); + case 'Settings': + return ( + + ); + case 'All Organizations': + return ( + + ); + case 'Add Event Project': + return ( + + ); + case 'List Event Registrants': + return ( + + ); + case 'Check In Registrants': + return ( + + ); + case 'Event Stats': + return ( + + ); + case 'Advertisement': + return ; + default: + return ( + + ); + } +}; + +export default iconComponent; diff --git a/src/components/LeftDrawer/LeftDrawer.module.css b/src/components/LeftDrawer/LeftDrawer.module.css new file mode 100644 index 0000000000..6818dc05fb --- /dev/null +++ b/src/components/LeftDrawer/LeftDrawer.module.css @@ -0,0 +1,246 @@ +.leftDrawer { + width: calc(300px + 2rem); + position: fixed; + top: 0; + bottom: 0; + z-index: 100; + display: flex; + flex-direction: column; + padding: 1rem 1rem 0 1rem; + background-color: var(--bs-white); + transition: 0.5s; +} + +.activeDrawer { + width: calc(300px + 2rem); + position: fixed; + top: 0; + left: 0; + bottom: 0; + animation: comeToRightBigScreen 0.5s ease-in-out; +} + +.inactiveDrawer { + position: fixed; + top: 0; + left: calc(-300px - 2rem); + bottom: 0; + animation: goToLeftBigScreen 0.5s ease-in-out; +} + +.leftDrawer .closeModalBtn { + display: none; +} + +.leftDrawer .talawaLogo { + width: 100%; + height: 65px; +} + +.leftDrawer .talawaText { + font-size: 1rem; + text-align: center; +} + +.leftDrawer .titleHeader { + margin: 2rem 0 1rem 0; + font-weight: 600; +} + +.leftDrawer .optionList button { + display: flex; + align-items: center; + width: 100%; + text-align: start; + margin-bottom: 0.8rem; + border-radius: 8px; + border: 1px solid var(--bs-gray-200); +} + +.leftDrawer .optionList button .iconWrapper { + width: 36px; +} + +.leftDrawer .profileContainer { + border: none; + width: 100%; + height: 52px; + border-radius: 8px; + background-color: var(--bs-white); + display: flex; + align-items: center; +} + +.leftDrawer .profileContainer:focus { + outline: none; + background-color: var(--bs-gray-100); +} + +.leftDrawer .imageContainer { + width: 68px; +} + +.leftDrawer .profileContainer img { + height: 52px; + width: 52px; + border-radius: 50%; +} + +.leftDrawer .profileContainer .profileText { + flex: 1; + text-align: start; +} + +.leftDrawer .profileContainer .profileText .primaryText { + font-size: 1.1rem; + font-weight: 600; +} + +.leftDrawer .profileContainer .profileText .secondaryText { + font-size: 0.8rem; + font-weight: 400; + color: var(--bs-secondary); + display: block; + text-transform: capitalize; +} + +@media (max-width: 1120px) { + .leftDrawer { + width: calc(250px + 2rem); + padding: 1rem 1rem 0 1rem; + } +} + +/* For tablets */ +@media (max-width: 820px) { + .hideElemByDefault { + display: none; + } + + .leftDrawer { + width: 100%; + left: 0; + right: 0; + } + + .leftDrawer .closeModalBtn { + display: block; + position: absolute; + top: 1rem; + right: 1rem; + z-index: 10; + } + + /* For smaller devices .activeDrawer in real behaves like inactive */ + .activeDrawer { + opacity: 0; + left: 0; + z-index: -1; + animation: closeDrawer 0.4s ease-in-out; + } + + /* For smaller devices .inactiveDrawer in real behaves like active */ + .inactiveDrawer { + display: flex; + z-index: 100; + animation: openDrawer 0.6s ease-in-out; + } +} + +@keyframes goToLeftBigScreen { + from { + left: 0; + } + + to { + opacity: 0.1; + left: calc(-300px - 2rem); + } +} + +/* Webkit prefix for older browser compatibility */ +@-webkit-keyframes goToLeftBigScreen { + from { + left: 0; + } + + to { + opacity: 0.1; + left: calc(-300px - 2rem); + } +} + +@keyframes comeToRightBigScreen { + from { + opacity: 0.4; + left: calc(-300px - 2rem); + } + + to { + opacity: 1; + left: 0; + } +} + +/* Webkit prefix for older browser compatibility */ +@-webkit-keyframes comeToRightBigScreen { + from { + opacity: 0.4; + left: calc(-300px - 2rem); + } + + to { + opacity: 1; + left: 0; + } +} + +@keyframes closeDrawer { + from { + left: 0; + opacity: 1; + } + + to { + left: -1000px; + opacity: 0; + } +} + +/* Webkit prefix for older browser compatibility */ +@-webkit-keyframes closeDrawer { + from { + left: 0; + opacity: 1; + } + + to { + left: -1000px; + opacity: 0; + } +} + +@keyframes openDrawer { + from { + opacity: 0; + left: -1000px; + } + + to { + left: 0; + opacity: 1; + } +} + +/* Webkit prefix for older browser compatibility */ +@-webkit-keyframes openDrawer { + from { + opacity: 0; + left: -1000px; + } + + to { + left: 0; + opacity: 1; + } +} diff --git a/src/components/LeftDrawer/LeftDrawer.test.tsx b/src/components/LeftDrawer/LeftDrawer.test.tsx new file mode 100644 index 0000000000..a5aa6c1851 --- /dev/null +++ b/src/components/LeftDrawer/LeftDrawer.test.tsx @@ -0,0 +1,258 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import 'jest-localstorage-mock'; +import { I18nextProvider } from 'react-i18next'; +import { BrowserRouter } from 'react-router-dom'; + +import i18nForTest from 'utils/i18nForTest'; +import type { InterfaceLeftDrawerProps } from './LeftDrawer'; +import LeftDrawer from './LeftDrawer'; +import { REVOKE_REFRESH_TOKEN } from 'GraphQl/Mutations/mutations'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { MockedProvider } from '@apollo/react-testing'; + +const props = { + hideDrawer: true, + setHideDrawer: jest.fn(), +}; + +const propsOrg: InterfaceLeftDrawerProps = { + ...props, + screenName: 'Organizations', +}; +const propsReq: InterfaceLeftDrawerProps = { + ...props, + hideDrawer: false, + screenName: 'Requests', +}; +const propsUsers: InterfaceLeftDrawerProps = { + ...props, + hideDrawer: null, + screenName: 'Users', +}; + +const MOCKS = [ + { + request: { + query: REVOKE_REFRESH_TOKEN, + }, + result: {}, + }, +]; + +const link = new StaticMockLink(MOCKS, true); + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }, +})); + +beforeEach(() => { + localStorage.setItem('FirstName', 'John'); + localStorage.setItem('LastName', 'Doe'); + localStorage.setItem( + 'UserImage', + 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe' + ); +}); + +afterEach(() => { + jest.clearAllMocks(); + localStorage.clear(); +}); + +describe('Testing Left Drawer component for SUPERADMIN', () => { + test('Component should be rendered properly', () => { + localStorage.setItem('UserImage', ''); + localStorage.setItem('UserType', 'SUPERADMIN'); + render( + + + + + + + + ); + + expect(screen.getByText('Organizations')).toBeInTheDocument(); + expect(screen.getByText('Requests')).toBeInTheDocument(); + expect(screen.getByText('Users')).toBeInTheDocument(); + expect(screen.getByText('Talawa Admin Portal')).toBeInTheDocument(); + + expect(screen.getByText(/John Doe/i)).toBeInTheDocument(); + expect(screen.getByText(/Superadmin/i)).toBeInTheDocument(); + expect(screen.getByAltText(/dummy picture/i)).toBeInTheDocument(); + + const orgsBtn = screen.getByTestId(/orgsBtn/i); + const requestsBtn = screen.getByTestId(/requestsBtn/i); + const rolesBtn = screen.getByTestId(/rolesBtn/i); + + expect( + orgsBtn.className.includes('text-white btn btn-success') + ).toBeTruthy(); + expect( + requestsBtn.className.includes('text-secondary btn btn-light') + ).toBeTruthy(); + expect( + rolesBtn.className.includes('text-secondary btn btn-light') + ).toBeTruthy(); + + // Coming soon + userEvent.click(screen.getByTestId(/profileBtn/i)); + + // Send to roles screen + userEvent.click(rolesBtn); + expect(global.window.location.pathname).toContain('/users'); + }); + + test('Testing in requests screen', () => { + localStorage.setItem('UserType', 'SUPERADMIN'); + render( + + + + + + + + ); + + const orgsBtn = screen.getByTestId(/orgsBtn/i); + + // Send to organizations screen + userEvent.click(orgsBtn); + expect(global.window.location.pathname).toContain('/orglist'); + }); + + test('Testing in roles screen', () => { + localStorage.setItem('UserType', 'SUPERADMIN'); + render( + + + + + + + + ); + + const orgsBtn = screen.getByTestId(/orgsBtn/i); + const requestsBtn = screen.getByTestId(/requestsBtn/i); + const rolesBtn = screen.getByTestId(/rolesBtn/i); + + expect( + orgsBtn.className.includes('text-secondary btn btn-light') + ).toBeTruthy(); + expect( + requestsBtn.className.includes('text-secondary btn btn-light') + ).toBeTruthy(); + expect( + rolesBtn.className.includes('text-white btn btn-success') + ).toBeTruthy(); + + // Send to requests screen + userEvent.click(requestsBtn); + expect(global.window.location.pathname).toContain('/requests'); + }); + + test('Testing Drawer open close functionality', () => { + localStorage.setItem('UserType', 'SUPERADMIN'); + render( + + + + + + + + ); + const closeModalBtn = screen.getByTestId(/closeModalBtn/i); + userEvent.click(closeModalBtn); + }); + + test('Testing Drawer when hideDrawer is null', () => { + localStorage.setItem('UserType', 'SUPERADMIN'); + render( + + + + + + + + ); + }); + + test('Testing Drawer when hideDrawer is true', () => { + localStorage.setItem('UserType', 'SUPERADMIN'); + render( + + + + + + + + ); + }); + + test('Testing logout functionality', async () => { + localStorage.setItem('UserType', 'SUPERADMIN'); + render( + + + + + + + + ); + userEvent.click(screen.getByTestId('logoutBtn')); + expect(localStorage.clear).toHaveBeenCalled(); + expect(global.window.location.pathname).toBe('/'); + }); +}); + +describe('Testing Left Drawer component for ADMIN', () => { + test('Components should be rendered properly', () => { + localStorage.setItem('UserType', 'ADMIN'); + render( + + + + + + + + ); + + expect(screen.getByText('Organizations')).toBeInTheDocument(); + expect(screen.getByText('Talawa Admin Portal')).toBeInTheDocument(); + + expect(screen.getByText(/John Doe/i)).toBeInTheDocument(); + expect(screen.getAllByText(/admin/i)).toHaveLength(2); + expect(screen.getByAltText(/profile picture/i)).toBeInTheDocument(); + + const orgsBtn = screen.getByTestId(/orgsBtn/i); + + expect( + orgsBtn.className.includes('text-white btn btn-success') + ).toBeTruthy(); + + // These screens arent meant for admins so they should not be present + expect(screen.queryByTestId(/rolesBtn/i)).toBeNull(); + expect(screen.queryByTestId(/requestsBtn/i)).toBeNull(); + + // Coming soon + userEvent.click(screen.getByTestId(/profileBtn/i)); + + // Send to roles screen + userEvent.click(orgsBtn); + expect(global.window.location.pathname).toContain('/orglist'); + }); +}); diff --git a/src/components/LeftDrawer/LeftDrawer.tsx b/src/components/LeftDrawer/LeftDrawer.tsx new file mode 100644 index 0000000000..d8708e2327 --- /dev/null +++ b/src/components/LeftDrawer/LeftDrawer.tsx @@ -0,0 +1,183 @@ +import React from 'react'; +import Button from 'react-bootstrap/Button'; +import { useTranslation } from 'react-i18next'; +import { useHistory } from 'react-router-dom'; +import { ReactComponent as AngleRightIcon } from 'assets/svgs/angleRight.svg'; +import { ReactComponent as LogoutIcon } from 'assets/svgs/logout.svg'; +import { ReactComponent as OrganizationsIcon } from 'assets/svgs/organizations.svg'; +import { ReactComponent as RequestsIcon } from 'assets/svgs/requests.svg'; +import { ReactComponent as RolesIcon } from 'assets/svgs/roles.svg'; +import { ReactComponent as TalawaLogo } from 'assets/svgs/talawa.svg'; +import styles from './LeftDrawer.module.css'; +import { useMutation } from '@apollo/client'; +import { REVOKE_REFRESH_TOKEN } from 'GraphQl/Mutations/mutations'; + +export interface InterfaceLeftDrawerProps { + hideDrawer: boolean | null; + setHideDrawer: React.Dispatch>; + screenName: string; +} + +const leftDrawer = ({ + screenName, + hideDrawer, + setHideDrawer, +}: InterfaceLeftDrawerProps): JSX.Element => { + const { t } = useTranslation('translation', { keyPrefix: 'leftDrawer' }); + + const userType = localStorage.getItem('UserType'); + const firstName = localStorage.getItem('FirstName'); + const lastName = localStorage.getItem('LastName'); + const userImage = localStorage.getItem('UserImage'); + const userId = localStorage.getItem('id'); + const history = useHistory(); + + const [revokeRefreshToken] = useMutation(REVOKE_REFRESH_TOKEN); + + const logout = (): void => { + revokeRefreshToken(); + localStorage.clear(); + history.push('/'); + }; + + return ( + <> +
    + + +

    {t('talawaAdminPortal')}

    +
    {t('menu')}
    +
    + + {userType === 'SUPERADMIN' && ( + + )} + {userType === 'SUPERADMIN' && ( + + )} +
    +
    + + + +
    +
    + + ); +}; + +export default leftDrawer; diff --git a/src/components/LeftDrawerEvent/LeftDrawerEvent.module.css b/src/components/LeftDrawerEvent/LeftDrawerEvent.module.css new file mode 100644 index 0000000000..af654f9043 --- /dev/null +++ b/src/components/LeftDrawerEvent/LeftDrawerEvent.module.css @@ -0,0 +1,291 @@ +.leftDrawer { + width: calc(300px + 2rem); + position: fixed; + top: 0; + bottom: 0; + z-index: 100; + display: flex; + flex-direction: column; + padding: 0.8rem 1rem 0 1rem; + background-color: var(--bs-white); + transition: 0.5s; + overflow-y: scroll; +} + +.leftDrawer::-webkit-scrollbar { + width: 6px; +} + +.leftDrawer::-webkit-scrollbar-track { + background: #f1f1f1; +} + +.leftDrawer::-webkit-scrollbar-thumb { + background: var(--bs-gray-500); +} + +.leftDrawer::-webkit-scrollbar-thumb:hover { + background: var(--bs-gray-600); +} + +.activeDrawer { + width: calc(300px + 2rem); + position: fixed; + top: 0; + left: 0; + bottom: 0; + animation: comeToRightBigScreen 0.5s ease-in-out; +} + +.inactiveDrawer { + position: fixed; + top: 0; + left: calc(-300px - 2rem); + bottom: 0; + animation: goToLeftBigScreen 0.5s ease-in-out; +} + +.leftDrawer .closeModalBtn { + display: none; +} + +.leftDrawer .brandingContainer { + display: flex; + justify-content: flex-start; + align-items: center; +} + +.leftDrawer .organizationContainer button { + position: relative; + margin: 1.25rem 0; + padding: 2.5rem 0.1rem; + border-radius: 0.5rem; + border: 1px solid var(--bs-gray-300); + background-color: var(--bs-gray-100); +} + +.leftDrawer .talawaLogo { + width: 42px; + height: 42px; + margin-right: 0.5rem; +} + +.leftDrawer .talawaText { + font-size: 1.1rem; +} + +.leftDrawer .titleHeader { + margin-bottom: 1rem; + font-weight: 600; +} + +.leftDrawer .optionList button { + display: flex; + align-items: center; + width: 100%; + text-align: start; + margin-bottom: 0.8rem; + border: 1px solid var(--bs-gray-200); + border-radius: 8px; +} + +.leftDrawer button .iconWrapper { + width: 36px; + transform: translateY(3px) translateY(-2px); +} + +.leftDrawer .optionList .collapseBtn { + height: 48px; +} + +.leftDrawer button .iconWrapperSm { + width: 36px; + display: flex; + justify-content: center; + align-items: center; +} + +.leftDrawer .profileContainer { + border: none; + width: 100%; + margin-top: 5rem; + height: 52px; + border-radius: 8px; + background-color: var(--bs-white); + display: flex; + align-items: center; +} + +.leftDrawer .profileContainer:focus { + outline: none; + background-color: var(--bs-gray-100); +} + +.leftDrawer .imageContainer { + width: 68px; +} + +.leftDrawer .profileContainer img { + height: 52px; + width: 52px; + border-radius: 50%; +} + +.leftDrawer .profileContainer .profileText { + flex: 1; + text-align: start; +} + +.leftDrawer .profileContainer .profileText .primaryText { + font-size: 1.1rem; + font-weight: 600; +} + +.leftDrawer .profileContainer .profileText .secondaryText { + font-size: 0.8rem; + font-weight: 400; + color: var(--bs-secondary); + display: block; + text-transform: capitalize; +} + +@media (max-width: 1120px) { + .leftDrawer { + width: calc(250px + 2rem); + padding: 1rem 1rem 0 1rem; + } +} + +/* For tablets */ +@media (max-width: 820px) { + .hideElemByDefault { + display: none; + } + + .leftDrawer { + width: 100%; + left: 0; + right: 0; + } + + .leftDrawer .closeModalBtn { + display: block; + position: absolute; + top: 1rem; + right: 1rem; + z-index: 10; + } + + /* For smaller devices .activeDrawer in real behaves like inactive */ + .activeDrawer { + opacity: 0; + left: 0; + z-index: -1; + animation: closeDrawer 0.4s ease-in-out; + } + + /* For smaller devices .inactiveDrawer in real behaves like active */ + .inactiveDrawer { + display: flex; + z-index: 100; + animation: openDrawer 0.6s ease-in-out; + } +} + +@keyframes goToLeftBigScreen { + from { + left: 0; + } + + to { + opacity: 0.1; + left: calc(-300px - 2rem); + } +} + +/* Webkit prefix for older browser compatibility */ +@-webkit-keyframes goToLeftBigScreen { + from { + left: 0; + } + + to { + opacity: 0.1; + left: calc(-300px - 2rem); + } +} + +@keyframes comeToRightBigScreen { + from { + opacity: 0.4; + left: calc(-300px - 2rem); + } + + to { + opacity: 1; + left: 0; + } +} + +/* Webkit prefix for older browser compatibility */ +@-webkit-keyframes comeToRightBigScreen { + from { + opacity: 0.4; + left: calc(-300px - 2rem); + } + + to { + opacity: 1; + left: 0; + } +} + +@keyframes closeDrawer { + from { + left: 0; + opacity: 1; + } + + to { + left: -1000px; + opacity: 0; + } +} + +/* Webkit prefix for older browser compatibility */ +@-webkit-keyframes closeDrawer { + from { + left: 0; + opacity: 1; + } + + to { + left: -1000px; + opacity: 0; + } +} + +@keyframes openDrawer { + from { + opacity: 0; + left: -1000px; + } + + to { + left: 0; + opacity: 1; + } +} + +/* Webkit prefix for older browser compatibility */ +@-webkit-keyframes openDrawer { + from { + opacity: 0; + left: -1000px; + } + + to { + left: 0; + opacity: 1; + } +} diff --git a/src/components/LeftDrawerEvent/LeftDrawerEvent.test.tsx b/src/components/LeftDrawerEvent/LeftDrawerEvent.test.tsx new file mode 100644 index 0000000000..3ce94b2a1d --- /dev/null +++ b/src/components/LeftDrawerEvent/LeftDrawerEvent.test.tsx @@ -0,0 +1,243 @@ +import React from 'react'; +import { render, screen, waitFor, fireEvent } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import 'jest-localstorage-mock'; +import { I18nextProvider } from 'react-i18next'; +import { BrowserRouter } from 'react-router-dom'; +import i18nForTest from 'utils/i18nForTest'; +import LeftDrawerEvent, { + type InterfaceLeftDrawerProps, +} from './LeftDrawerEvent'; +import { MockedProvider } from '@apollo/react-testing'; +import { EVENT_FEEDBACKS } from 'GraphQl/Queries/Queries'; +import { REVOKE_REFRESH_TOKEN } from 'GraphQl/Mutations/mutations'; + +const props: InterfaceLeftDrawerProps = { + event: { + _id: 'testEvent', + title: 'Test Event', + description: 'Test Description', + organization: { + _id: 'TestOrganization', + }, + }, + hideDrawer: false, + setHideDrawer: jest.fn(), + setShowAddEventProjectModal: jest.fn(), +}; +const props2: InterfaceLeftDrawerProps = { + event: { + _id: 'testEvent', + title: 'This is a very long event title that exceeds 20 characters', + description: + 'This is a very long event description that exceeds 30 characters. It contains more details about the event.', + organization: { + _id: 'Test Organization', + }, + }, + hideDrawer: false, + setHideDrawer: jest.fn(), + setShowAddEventProjectModal: jest.fn(), +}; + +const mocks = [ + { + request: { + query: REVOKE_REFRESH_TOKEN, + }, + result: {}, + }, + { + request: { + query: EVENT_FEEDBACKS, + variables: { + id: 'testEvent', + }, + }, + result: { + data: { + event: { + _id: 'testEvent', + feedback: [], + averageFeedbackScore: 5, + }, + }, + }, + }, +]; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }, +})); + +// Mock the modules for PieChart rendering as they require a trasformer being used (which is not done by Jest) +// They are required by the feedback statistics component +jest.mock('@mui/x-charts/PieChart', () => ({ + pieArcLabelClasses: jest.fn(), + PieChart: jest.fn().mockImplementation(() => <>Test), + pieArcClasses: jest.fn(), +})); + +beforeEach(() => { + localStorage.setItem('FirstName', 'John'); + localStorage.setItem('LastName', 'Doe'); + localStorage.setItem( + 'UserImage', + 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe' + ); +}); + +afterEach(() => { + jest.clearAllMocks(); + localStorage.clear(); +}); + +describe('Testing Left Drawer component for the Event Dashboard', () => { + test('Component should be rendered properly', async () => { + localStorage.setItem('UserImage', ''); + localStorage.setItem('UserType', 'SUPERADMIN'); + + const { queryByText } = render( + + + + + + + + ); + + await waitFor(() => + expect(queryByText('Talawa Admin Portal')).toBeInTheDocument() + ); + await waitFor(() => expect(queryByText('Test Event')).toBeInTheDocument()); + await waitFor(() => + expect(queryByText('Test Description')).toBeInTheDocument() + ); + await waitFor(() => + expect(queryByText('Event Options')).toBeInTheDocument() + ); + }); + + test('Add Event Project button and profile page button should work properly', async () => { + localStorage.setItem('UserType', 'SUPERADMIN'); + + const { queryByText, queryByTestId } = render( + + + + + + + + ); + + await waitFor(() => + expect(queryByText('Talawa Admin Portal')).toBeInTheDocument() + ); + + fireEvent.click(queryByText('Add an Event Project') as HTMLElement); + expect(props.setShowAddEventProjectModal).toHaveBeenCalled(); + + fireEvent.click(queryByTestId(/profileBtn/i) as HTMLElement); + }); + + test('Testing Drawer when hideDrawer is null', () => { + localStorage.setItem('UserType', 'SUPERADMIN'); + render( + + + + + + + + ); + }); + + test('Testing Drawer when hideDrawer is true', () => { + localStorage.setItem('UserType', 'SUPERADMIN'); + render( + + + + + + + + ); + }); + + test('Testing Drawer open close functionality', () => { + localStorage.setItem('UserType', 'SUPERADMIN'); + render( + + + + + + + + ); + const closeModalBtn = screen.getByTestId(/closeModalBtn/i); + userEvent.click(closeModalBtn); + }); + + test('Testing logout functionality', async () => { + localStorage.setItem('UserType', 'SUPERADMIN'); + render( + + + + + + + + ); + + userEvent.click(screen.getByTestId('logoutBtn')); + expect(localStorage.clear).toHaveBeenCalled(); + expect(global.window.location.pathname).toBe('/'); + }); + test('Testing substring functionality in event title and description', async () => { + localStorage.setItem('UserType', 'SUPERADMIN'); + render( + + + + + + + + ); + const eventTitle = props2.event.title; + expect(eventTitle.length).toBeGreaterThan(20); + const eventDescription = props2.event.description; + expect(eventDescription.length).toBeGreaterThan(30); + const truncatedEventTitle = eventTitle.substring(0, 20) + '...'; + const truncatedEventDescription = eventDescription.substring(0, 30) + '...'; + expect(truncatedEventTitle).toContain('...'); + expect(truncatedEventDescription).toContain('...'); + }); + test('Testing all events button', async () => { + localStorage.setItem('UserType', 'SUPERADMIN'); + render( + + + + + + + + ); + + userEvent.click(screen.getByTestId('allEventsBtn')); + expect(global.window.location.pathname).toBe( + `/orgevents/id=${props.event.organization._id}` + ); + }); +}); diff --git a/src/components/LeftDrawerEvent/LeftDrawerEvent.tsx b/src/components/LeftDrawerEvent/LeftDrawerEvent.tsx new file mode 100644 index 0000000000..795f6016cb --- /dev/null +++ b/src/components/LeftDrawerEvent/LeftDrawerEvent.tsx @@ -0,0 +1,199 @@ +import React from 'react'; +import Button from 'react-bootstrap/Button'; +import { useHistory } from 'react-router-dom'; +import { ReactComponent as AngleRightIcon } from 'assets/svgs/angleRight.svg'; +import { ReactComponent as LogoutIcon } from 'assets/svgs/logout.svg'; +import { ReactComponent as TalawaLogo } from 'assets/svgs/talawa.svg'; +import styles from './LeftDrawerEvent.module.css'; +import IconComponent from 'components/IconComponent/IconComponent'; +import { EventRegistrantsWrapper } from 'components/EventRegistrantsModal/EventRegistrantsWrapper'; +import { CheckInWrapper } from 'components/CheckIn/CheckInWrapper'; +import { EventStatsWrapper } from 'components/EventStats/EventStatsWrapper'; +import { REVOKE_REFRESH_TOKEN } from 'GraphQl/Mutations/mutations'; +import { useMutation } from '@apollo/client'; + +export interface InterfaceLeftDrawerProps { + event: { + _id: string; + title: string; + description: string; + organization: { + _id: string; + }; + }; + hideDrawer: boolean | null; + setHideDrawer: React.Dispatch>; + setShowAddEventProjectModal: React.Dispatch>; +} + +const leftDrawerEvent = ({ + event, + hideDrawer, + setHideDrawer, + setShowAddEventProjectModal, +}: InterfaceLeftDrawerProps): JSX.Element => { + const [revokeRefreshToken] = useMutation(REVOKE_REFRESH_TOKEN); + const userType = localStorage.getItem('UserType'); + const firstName = localStorage.getItem('FirstName'); + const lastName = localStorage.getItem('LastName'); + const userImage = localStorage.getItem('UserImage'); + const userId = localStorage.getItem('id'); + + const history = useHistory(); + const logout = (): void => { + revokeRefreshToken(); + localStorage.clear(); + history.push('/'); + }; + + return ( + <> +
    + {/* Close Drawer Button for small devices */} + + + {/* Branding Section */} +
    + + Talawa Admin Portal +
    + + {/* Event Detail Section */} +
    + +
    + + {/* Options List */} +
    +
    Event Options
    + + + + + +
    + + {/* Profile Section & Logout Btn */} +
    + + +
    +
    + + ); +}; + +export default leftDrawerEvent; diff --git a/src/components/LeftDrawerEvent/LeftDrawerEventWrapper.module.css b/src/components/LeftDrawerEvent/LeftDrawerEventWrapper.module.css new file mode 100644 index 0000000000..681ac8823d --- /dev/null +++ b/src/components/LeftDrawerEvent/LeftDrawerEventWrapper.module.css @@ -0,0 +1,60 @@ +.pageContainer { + display: flex; + flex-direction: column; + min-height: 100vh; + padding: 1rem 1.5rem 0 calc(300px + 2rem + 1.5rem); +} + +.expand { + padding-left: 1.5rem; + animation: moveLeft 0.5s ease-in-out; +} + +.contract { + padding-left: calc(300px + 2rem + 1.5rem); + animation: moveRight 0.5s ease-in-out; +} + +@media (max-width: 1120px) { + .contract { + padding-left: calc(250px + 2rem + 1.5rem); + } +} + +/* For tablets */ +@media (max-width: 820px) { + .pageContainer { + padding-left: 1.5rem; + } + + .contract, + .expand { + animation: none; + } +} + +@media (max-width: 820px) { + .pageContainer { + padding: 1rem; + } +} + +@keyframes moveLeft { + from { + padding-left: calc(300px + 2rem + 1.5rem); + } + + to { + padding-left: 1.5rem; + } +} + +@keyframes moveRight { + from { + padding-left: 1.5rem; + } + + to { + padding-left: calc(300px + 2rem + 1.5rem); + } +} diff --git a/src/components/LeftDrawerEvent/LeftDrawerEventWrapper.test.tsx b/src/components/LeftDrawerEvent/LeftDrawerEventWrapper.test.tsx new file mode 100644 index 0000000000..72093aaf06 --- /dev/null +++ b/src/components/LeftDrawerEvent/LeftDrawerEventWrapper.test.tsx @@ -0,0 +1,94 @@ +import React from 'react'; +import 'jest-localstorage-mock'; +import { render, waitFor, fireEvent } from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { BrowserRouter } from 'react-router-dom'; +import i18nForTest from 'utils/i18nForTest'; +import { + type InterfacePropType, + LeftDrawerEventWrapper, +} from './LeftDrawerEventWrapper'; +import { MockedProvider } from '@apollo/react-testing'; +import { EVENT_FEEDBACKS } from 'GraphQl/Queries/Queries'; + +const props: InterfacePropType = { + event: { + _id: 'testEvent', + title: 'Test Event', + description: 'Test Description', + organization: { + _id: 'Test Organization', + }, + }, + setShowAddEventProjectModal: jest.fn(), + children: null, +}; + +const mocks = [ + { + request: { + query: EVENT_FEEDBACKS, + variables: { + id: 'testEvent', + }, + }, + result: { + data: { + event: { + _id: 'testEvent', + feedback: [], + averageFeedbackScore: 5, + }, + }, + }, + }, +]; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }, +})); + +// Mock the modules for PieChart rendering as they require a trasformer being used (which is not done by Jest) +// They are required by the feedback statistics component +jest.mock('@mui/x-charts/PieChart', () => ({ + pieArcLabelClasses: jest.fn(), + PieChart: jest.fn().mockImplementation(() => <>Test), + pieArcClasses: jest.fn(), +})); + +beforeEach(() => { + localStorage.setItem('FirstName', 'John'); + localStorage.setItem('LastName', 'Doe'); + localStorage.setItem( + 'UserImage', + 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe' + ); +}); + +afterEach(() => { + jest.clearAllMocks(); + localStorage.clear(); +}); + +describe('Testing Left Drawer Wrapper component for the Event Dashboard', () => { + test('Component should be rendered properly and the close menu button should function', async () => { + const { queryByText, queryByTestId } = render( + + + + + + + + ); + + await waitFor(() => + expect(queryByText('Event Management')).toBeInTheDocument() + ); + fireEvent.click(queryByTestId('closeLeftDrawerBtn') as HTMLElement); + }); +}); diff --git a/src/components/LeftDrawerEvent/LeftDrawerEventWrapper.tsx b/src/components/LeftDrawerEvent/LeftDrawerEventWrapper.tsx new file mode 100644 index 0000000000..1b1157385c --- /dev/null +++ b/src/components/LeftDrawerEvent/LeftDrawerEventWrapper.tsx @@ -0,0 +1,62 @@ +import MenuIcon from '@mui/icons-material/Menu'; +import LeftDrawerEvent from './LeftDrawerEvent'; +import React, { useState } from 'react'; +import Button from 'react-bootstrap/Button'; +import styles from './LeftDrawerEventWrapper.module.css'; + +export interface InterfacePropType { + event: { + _id: string; + title: string; + description: string; + organization: { + _id: string; + }; + }; + setShowAddEventProjectModal: React.Dispatch>; + children: React.ReactNode; +} + +export const LeftDrawerEventWrapper = ( + props: InterfacePropType +): JSX.Element => { + const [hideDrawer, setHideDrawer] = useState(null); + + return ( + <> + + +
    +
    +
    +

    Event Management

    +
    + +
    + {props.children} +
    + + ); +}; diff --git a/src/components/LeftDrawerOrg/LeftDrawerOrg.module.css b/src/components/LeftDrawerOrg/LeftDrawerOrg.module.css new file mode 100644 index 0000000000..399a7cb4ef --- /dev/null +++ b/src/components/LeftDrawerOrg/LeftDrawerOrg.module.css @@ -0,0 +1,290 @@ +.leftDrawer { + width: calc(300px + 2rem); + position: fixed; + top: 0; + bottom: 0; + z-index: 100; + display: flex; + flex-direction: column; + padding: 0.8rem 1rem 0 1rem; + background-color: var(--bs-white); + transition: 0.5s; + overflow-y: scroll; +} + +.leftDrawer::-webkit-scrollbar { + width: 6px; +} + +.leftDrawer::-webkit-scrollbar-track { + background: #f1f1f1; +} + +.leftDrawer::-webkit-scrollbar-thumb { + background: var(--bs-gray-500); +} + +.leftDrawer::-webkit-scrollbar-thumb:hover { + background: var(--bs-gray-600); +} + +.activeDrawer { + width: calc(300px + 2rem); + position: fixed; + top: 0; + left: 0; + bottom: 0; + animation: comeToRightBigScreen 0.5s ease-in-out; +} + +.inactiveDrawer { + position: fixed; + top: 0; + left: calc(-300px - 2rem); + bottom: 0; + animation: goToLeftBigScreen 0.5s ease-in-out; +} + +.leftDrawer .closeModalBtn { + display: none; +} + +.leftDrawer .brandingContainer { + display: flex; + justify-content: flex-start; + align-items: center; +} + +.leftDrawer .organizationContainer button { + position: relative; + margin: 1.25rem 0; + padding: 2.5rem 0.1rem; + border-radius: 0.5rem; + border: 1px solid var(--bs-gray-300); + background-color: var(--bs-gray-100); +} + +.leftDrawer .talawaLogo { + width: 42px; + height: 42px; + margin-right: 0.5rem; +} + +.leftDrawer .talawaText { + font-size: 1.1rem; +} + +.leftDrawer .titleHeader { + margin-bottom: 1rem; + font-weight: 600; +} + +.leftDrawer .optionList button { + display: flex; + align-items: center; + width: 100%; + text-align: start; + margin-bottom: 0.8rem; + border: 1px solid var(--bs-gray-200); + border-radius: 8px; +} + +.leftDrawer button .iconWrapper { + width: 36px; +} + +.leftDrawer .optionList .collapseBtn { + height: 48px; +} + +.leftDrawer button .iconWrapperSm { + width: 36px; + display: flex; + justify-content: center; + align-items: center; +} + +.leftDrawer .profileContainer { + border: none; + width: 100%; + margin-top: 5rem; + height: 52px; + border-radius: 8px; + background-color: var(--bs-white); + display: flex; + align-items: center; +} + +.leftDrawer .profileContainer:focus { + outline: none; + background-color: var(--bs-gray-100); +} + +.leftDrawer .imageContainer { + width: 68px; +} + +.leftDrawer .profileContainer img { + height: 52px; + width: 52px; + border-radius: 50%; +} + +.leftDrawer .profileContainer .profileText { + flex: 1; + text-align: start; +} + +.leftDrawer .profileContainer .profileText .primaryText { + font-size: 1.1rem; + font-weight: 600; +} + +.leftDrawer .profileContainer .profileText .secondaryText { + font-size: 0.8rem; + font-weight: 400; + color: var(--bs-secondary); + display: block; + text-transform: capitalize; +} + +@media (max-width: 1120px) { + .leftDrawer { + width: calc(250px + 2rem); + padding: 1rem 1rem 0 1rem; + } +} + +/* For tablets */ +@media (max-width: 820px) { + .hideElemByDefault { + display: none; + } + + .leftDrawer { + width: 100%; + left: 0; + right: 0; + } + + .leftDrawer .closeModalBtn { + display: block; + position: absolute; + top: 1rem; + right: 1rem; + z-index: 10; + } + + /* For smaller devices .activeDrawer in real behaves like inactive */ + .activeDrawer { + opacity: 0; + left: 0; + z-index: -1; + animation: closeDrawer 0.4s ease-in-out; + } + + /* For smaller devices .inactiveDrawer in real behaves like active */ + .inactiveDrawer { + display: flex; + z-index: 100; + animation: openDrawer 0.6s ease-in-out; + } +} + +@keyframes goToLeftBigScreen { + from { + left: 0; + } + + to { + opacity: 0.1; + left: calc(-300px - 2rem); + } +} + +/* Webkit prefix for older browser compatibility */ +@-webkit-keyframes goToLeftBigScreen { + from { + left: 0; + } + + to { + opacity: 0.1; + left: calc(-300px - 2rem); + } +} + +@keyframes comeToRightBigScreen { + from { + opacity: 0.4; + left: calc(-300px - 2rem); + } + + to { + opacity: 1; + left: 0; + } +} + +/* Webkit prefix for older browser compatibility */ +@-webkit-keyframes comeToRightBigScreen { + from { + opacity: 0.4; + left: calc(-300px - 2rem); + } + + to { + opacity: 1; + left: 0; + } +} + +@keyframes closeDrawer { + from { + left: 0; + opacity: 1; + } + + to { + left: -1000px; + opacity: 0; + } +} + +/* Webkit prefix for older browser compatibility */ +@-webkit-keyframes closeDrawer { + from { + left: 0; + opacity: 1; + } + + to { + left: -1000px; + opacity: 0; + } +} + +@keyframes openDrawer { + from { + opacity: 0; + left: -1000px; + } + + to { + left: 0; + opacity: 1; + } +} + +/* Webkit prefix for older browser compatibility */ +@-webkit-keyframes openDrawer { + from { + opacity: 0; + left: -1000px; + } + + to { + left: 0; + opacity: 1; + } +} diff --git a/src/components/LeftDrawerOrg/LeftDrawerOrg.test.tsx b/src/components/LeftDrawerOrg/LeftDrawerOrg.test.tsx new file mode 100644 index 0000000000..101f4133e2 --- /dev/null +++ b/src/components/LeftDrawerOrg/LeftDrawerOrg.test.tsx @@ -0,0 +1,395 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import 'jest-localstorage-mock'; +import { I18nextProvider } from 'react-i18next'; +import { BrowserRouter } from 'react-router-dom'; + +import i18nForTest from 'utils/i18nForTest'; +import type { InterfaceLeftDrawerProps } from './LeftDrawerOrg'; +import LeftDrawerOrg from './LeftDrawerOrg'; +import { Provider } from 'react-redux'; +import { MockedProvider } from '@apollo/react-testing'; +import { store } from 'state/store'; +import { ORGANIZATIONS_LIST } from 'GraphQl/Queries/Queries'; +import { act } from 'react-dom/test-utils'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { REVOKE_REFRESH_TOKEN } from 'GraphQl/Mutations/mutations'; + +const props: InterfaceLeftDrawerProps = { + screenName: 'Dashboard', + orgId: '123', + targets: [ + { + name: 'Dashboard', + url: '/orgdash/id=123', + }, + { + name: 'People', + url: '/orgpeople/id=123', + }, + { + name: 'Events', + url: '/orgevents/id=123', + }, + { + name: 'Posts', + url: '/orgpost/id=123', + }, + { + name: 'Block/Unblock', + url: '/blockuser/id=123', + }, + { + name: 'Plugins', + subTargets: [ + { + name: 'Plugin Store', + url: '/orgstore/id=123', + icon: 'fa-store', + }, + ], + }, + { + name: 'Settings', + url: '/orgsetting/id=123', + }, + { + name: 'All Organizations', + url: '/orglist/id=123', + }, + ], + hideDrawer: false, + setHideDrawer: jest.fn(), +}; + +const MOCKS = [ + { + request: { + query: REVOKE_REFRESH_TOKEN, + }, + result: {}, + }, + { + request: { + query: ORGANIZATIONS_LIST, + variables: { id: '123' }, + }, + result: { + data: { + organizations: [ + { + _id: '123', + image: null, + creator: { + firstName: 'John', + lastName: 'Doe', + email: 'JohnDoe@example.com', + }, + name: 'Test Organization', + description: 'Testing this organization', + location: 'Gotham, DC', + isPublic: true, + visibleInSearch: true, + members: [ + { + _id: 'john123', + firstName: 'John', + lastName: 'Doe', + email: 'JohnDoe@example.com', + }, + { + _id: 'jane123', + firstName: 'Jane', + lastName: 'Doe', + email: 'JaneDoe@example.com', + }, + ], + admins: [ + { + _id: 'john123', + firstName: 'John', + lastName: 'Doe', + email: 'JohnDoe@example.com', + }, + ], + membershipRequests: [], + blockedUsers: [], + }, + ], + }, + }, + }, +]; + +const MOCKS_WITH_IMAGE = [ + { + request: { + query: ORGANIZATIONS_LIST, + variables: { id: '123' }, + }, + result: { + data: { + organizations: [ + { + _id: '123', + image: + 'https://api.dicebear.com/5.x/initials/svg?seed=Test%20Organization', + creator: { + firstName: 'John', + lastName: 'Doe', + email: 'JohnDoe@example.com', + }, + name: 'Test Organization', + description: 'Testing this organization', + location: 'Gotham, DC', + isPublic: true, + visibleInSearch: true, + members: [ + { + _id: 'john123', + firstName: 'John', + lastName: 'Doe', + email: 'JohnDoe@example.com', + }, + { + _id: 'jane123', + firstName: 'Jane', + lastName: 'Doe', + email: 'JaneDoe@example.com', + }, + ], + admins: [ + { + _id: 'john123', + firstName: 'John', + lastName: 'Doe', + email: 'JohnDoe@example.com', + }, + ], + membershipRequests: [], + blockedUsers: [], + }, + ], + }, + }, + }, +]; +const MOCKS_EMPTY = [ + { + request: { + query: ORGANIZATIONS_LIST, + variables: { id: '123' }, + }, + result: { + data: { + organizations: [], + }, + }, + }, +]; + +const defaultScreens = [ + 'Dashboard', + 'People', + 'Events', + 'Posts', + 'Block/Unblock', + 'Plugins', + 'Settings', + 'All Organizations', +]; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }, +})); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} +beforeEach(() => { + localStorage.setItem('FirstName', 'John'); + localStorage.setItem('LastName', 'Doe'); + localStorage.setItem( + 'UserImage', + 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe' + ); +}); + +afterEach(() => { + jest.clearAllMocks(); + localStorage.clear(); +}); + +const link = new StaticMockLink(MOCKS, true); +const linkImage = new StaticMockLink(MOCKS_WITH_IMAGE, true); +const linkEmpty = new StaticMockLink(MOCKS_EMPTY, true); + +describe('Testing Left Drawer component for SUPERADMIN', () => { + test('Component should be rendered properly', async () => { + localStorage.setItem('UserImage', ''); + localStorage.setItem('UserType', 'SUPERADMIN'); + render( + + + + + + + + + + ); + await wait(); + defaultScreens.map((screenName) => { + expect(screen.getByText(screenName)).toBeInTheDocument(); + }); + expect(screen.getByText(/John Doe/i)).toBeInTheDocument(); + expect(screen.getByText(/Superadmin/i)).toBeInTheDocument(); + expect(screen.getByAltText(/dummy picture/i)).toBeInTheDocument(); + }); + + test('Testing Profile Page & Organization Detail Modal', async () => { + localStorage.setItem('UserType', 'SUPERADMIN'); + render( + + + + + + + + + + ); + await wait(); + expect(screen.getByTestId(/orgBtn/i)).toBeInTheDocument(); + userEvent.click(screen.getByTestId(/profileBtn/i)); + }); + + test('Testing Menu Buttons', async () => { + localStorage.setItem('UserType', 'SUPERADMIN'); + render( + + + + + + + + + + ); + await wait(); + userEvent.click(screen.getByText('Dashboard')); + expect(global.window.location.pathname).toContain('/orgdash/id=123'); + }); + + test('Testing when image is present for Organization', async () => { + localStorage.setItem('UserType', 'SUPERADMIN'); + render( + + + + + + + + + + ); + await wait(); + }); + + test('Testing when Organization does not exists', async () => { + localStorage.setItem('UserType', 'SUPERADMIN'); + render( + + + + + + + + + + ); + await wait(); + expect( + screen.getByText(/Error Occured while loading the Organization/i) + ).toBeInTheDocument(); + }); + + test('Testing Drawer when hideDrawer is null', () => { + localStorage.setItem('UserType', 'SUPERADMIN'); + render( + + + + + + + + + + ); + }); + + test('Testing Drawer when hideDrawer is true', () => { + localStorage.setItem('UserType', 'SUPERADMIN'); + render( + + + + + + + + + + ); + }); + + test('Testing Drawer open close functionality', () => { + localStorage.setItem('UserType', 'SUPERADMIN'); + render( + + + + + + + + + + ); + const closeModalBtn = screen.getByTestId(/closeModalBtn/i); + userEvent.click(closeModalBtn); + }); + + test('Testing logout functionality', async () => { + localStorage.setItem('UserType', 'SUPERADMIN'); + render( + + + + + + + + + + ); + userEvent.click(screen.getByTestId('logoutBtn')); + expect(localStorage.clear).toHaveBeenCalled(); + expect(global.window.location.pathname).toBe('/'); + }); +}); diff --git a/src/components/LeftDrawerOrg/LeftDrawerOrg.tsx b/src/components/LeftDrawerOrg/LeftDrawerOrg.tsx new file mode 100644 index 0000000000..aa263f7e12 --- /dev/null +++ b/src/components/LeftDrawerOrg/LeftDrawerOrg.tsx @@ -0,0 +1,230 @@ +import { useMutation, useQuery } from '@apollo/client'; +import { WarningAmberOutlined } from '@mui/icons-material'; +import { ORGANIZATIONS_LIST } from 'GraphQl/Queries/Queries'; +import CollapsibleDropdown from 'components/CollapsibleDropdown/CollapsibleDropdown'; +import IconComponent from 'components/IconComponent/IconComponent'; +import React, { useEffect, useState } from 'react'; +import Button from 'react-bootstrap/Button'; +import { useTranslation } from 'react-i18next'; +import { useHistory } from 'react-router-dom'; +import type { TargetsType } from 'state/reducers/routesReducer'; +import type { InterfaceQueryOrganizationsListObject } from 'utils/interfaces'; +import { ReactComponent as AngleRightIcon } from 'assets/svgs/angleRight.svg'; +import { ReactComponent as LogoutIcon } from 'assets/svgs/logout.svg'; +import { ReactComponent as TalawaLogo } from 'assets/svgs/talawa.svg'; +import styles from './LeftDrawerOrg.module.css'; +import { REVOKE_REFRESH_TOKEN } from 'GraphQl/Mutations/mutations'; + +export interface InterfaceLeftDrawerProps { + orgId: string; + screenName: string; + targets: TargetsType[]; + hideDrawer: boolean | null; + setHideDrawer: React.Dispatch>; +} + +const leftDrawerOrg = ({ + screenName, + targets, + orgId, + hideDrawer, + setHideDrawer, +}: InterfaceLeftDrawerProps): JSX.Element => { + const { t } = useTranslation('translation', { keyPrefix: 'leftDrawerOrg' }); + const [organization, setOrganization] = + useState(); + const { + data, + loading, + }: { + data: + | { organizations: InterfaceQueryOrganizationsListObject[] } + | undefined; + loading: boolean; + } = useQuery(ORGANIZATIONS_LIST, { + variables: { id: orgId }, + }); + + const [revokeRefreshToken] = useMutation(REVOKE_REFRESH_TOKEN); + + const userType = localStorage.getItem('UserType'); + const firstName = localStorage.getItem('FirstName'); + const lastName = localStorage.getItem('LastName'); + const userImage = localStorage.getItem('UserImage'); + const userId = localStorage.getItem('id'); + const history = useHistory(); + + // Set organization data + useEffect(() => { + let isMounted = true; + if (data && isMounted) { + setOrganization(data?.organizations[0]); + } + return () => { + isMounted = false; + }; + }, [data]); + + const logout = (): void => { + revokeRefreshToken(); + localStorage.clear(); + history.push('/'); + }; + + return ( + <> +
    + {/* Close Drawer Btn for small devices */} + + + {/* Branding Section */} +
    + + {t('talawaAdminPortal')} +
    + + {/* Organization Section */} +
    + {loading ? ( + <> + + + ) : ( + + )} +
    + + {/* Options List */} +
    +
    {t('menu')}
    + {targets.map(({ name, url }, index) => { + return url ? ( + + ) : ( + + ); + })} +
    + + {/* Profile Section & Logout Btn */} +
    + + +
    +
    + + ); +}; + +export default leftDrawerOrg; diff --git a/src/components/Loader/Loader.module.css b/src/components/Loader/Loader.module.css new file mode 100644 index 0000000000..aad512e826 --- /dev/null +++ b/src/components/Loader/Loader.module.css @@ -0,0 +1,25 @@ +.spinner_wrapper { + height: 100vh; + width: 100%; + display: flex; + justify-content: center; + align-items: center; +} + +.spinnerXl { + width: 6rem; + height: 6rem; + border-width: 0.5rem; +} + +.spinnerLg { + height: 4rem; + width: 4rem; + border-width: 0.3rem; +} + +.spinnerSm { + height: 2rem; + width: 2rem; + border-width: 0.2rem; +} diff --git a/src/components/Loader/Loader.test.tsx b/src/components/Loader/Loader.test.tsx new file mode 100644 index 0000000000..c512b480e3 --- /dev/null +++ b/src/components/Loader/Loader.test.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import Loader from './Loader'; + +describe('Testing Loader component', () => { + test('Component should be rendered properly', () => { + render(); + + expect(screen.getByTestId('spinner-wrapper')).toBeInTheDocument(); + expect(screen.getByTestId('spinner')).toBeInTheDocument(); + }); + + test('Component should render on custom sizes', () => { + render(); + + expect(screen.getByTestId('spinner-wrapper')).toBeInTheDocument(); + expect(screen.getByTestId('spinner')).toBeInTheDocument(); + }); + + test('Component should render with large size', () => { + render(); + + expect(screen.getByTestId('spinner-wrapper')).toBeInTheDocument(); + expect(screen.getByTestId('spinner')).toBeInTheDocument(); + }); +}); diff --git a/src/components/Loader/Loader.tsx b/src/components/Loader/Loader.tsx new file mode 100644 index 0000000000..f761ebd79b --- /dev/null +++ b/src/components/Loader/Loader.tsx @@ -0,0 +1,36 @@ +import React from 'react'; +import styles from './Loader.module.css'; +import { Spinner } from 'react-bootstrap'; + +interface InterfaceLoaderProps { + styles?: StyleSheet | string; + size?: 'sm' | 'lg' | 'xl'; +} + +const Loader = (props: InterfaceLoaderProps): JSX.Element => { + return ( + <> +
    + +
    + + ); +}; + +export default Loader; diff --git a/src/components/MemberRequestCard/MemberRequestCard.module.css b/src/components/MemberRequestCard/MemberRequestCard.module.css new file mode 100644 index 0000000000..fdc99eba83 --- /dev/null +++ b/src/components/MemberRequestCard/MemberRequestCard.module.css @@ -0,0 +1,57 @@ +.memberlist { + margin-top: -1px; +} +.memberimg { + border-radius: 10px; + margin-left: 10px; +} +.singledetails { + display: flex; + flex-direction: row; + justify-content: space-between; +} +.singledetails p { + margin-bottom: -5px; +} +.singledetails_data_left { + margin-top: 10px; + margin-left: 10px; + color: #707070; +} +.singledetails_data_right { + justify-content: right; + margin-top: 10px; + text-align: right; + color: #707070; +} +.membername { + font-size: 16px; + font-weight: bold; +} +.memberfont { + margin-top: 3px; +} +.memberfont > span { + width: 80%; +} +.memberfontcreated { + margin-top: 18px; +} +.memberfontcreatedbtn { + margin-top: 33px; + border-radius: 7px; + border-color: #e8e5e5; + background-color: #f7f7f7; + padding-right: 10px; + padding-left: 10px; + justify-content: flex-end; + float: right; + text-align: right; + box-shadow: none; +} +#grid_wrapper { + align-items: left; +} +.peoplelistdiv { + margin-right: 50px; +} diff --git a/src/components/MemberRequestCard/MemberRequestCard.test.tsx b/src/components/MemberRequestCard/MemberRequestCard.test.tsx new file mode 100644 index 0000000000..94efce5f09 --- /dev/null +++ b/src/components/MemberRequestCard/MemberRequestCard.test.tsx @@ -0,0 +1,122 @@ +import React from 'react'; +import { act, render, screen } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; + +import { + ACCEPT_ORGANIZATION_REQUEST_MUTATION, + REJECT_ORGANIZATION_REQUEST_MUTATION, +} from 'GraphQl/Mutations/mutations'; +import MemberRequestCard from './MemberRequestCard'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; + +const MOCKS = [ + { + request: { + query: ACCEPT_ORGANIZATION_REQUEST_MUTATION, + variable: { id: '123' }, + }, + result: { + data: { + organizations: [ + { + _id: '1', + }, + ], + }, + }, + }, + { + request: { + query: REJECT_ORGANIZATION_REQUEST_MUTATION, + variable: { id: '234' }, + }, + result: { + data: { + organizations: [ + { + _id: '2', + }, + ], + }, + }, + }, +]; +const link = new StaticMockLink(MOCKS, true); +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Testing Member Request Card', () => { + const props = { + key: '123', + id: '1', + memberName: 'John Doe', + memberLocation: 'India', + joinDate: '18/03/2022', + memberImage: 'image', + email: 'johndoe@gmail.com', + }; + + global.alert = jest.fn(); + + it('should render props and text elements test for the page component', async () => { + global.confirm = (): boolean => true; + + render( + + + + + + ); + + await wait(); + userEvent.click(screen.getByText(/Accept/i)); + userEvent.click(screen.getByText(/Reject/i)); + + expect(screen.getByAltText(/userImage/i)).toBeInTheDocument(); + expect(screen.getByText(/Joined:/i)).toBeInTheDocument(); + expect(screen.getByText(props.memberName)).toBeInTheDocument(); + expect(screen.getByText(props.memberLocation)).toBeInTheDocument(); + expect(screen.getByText(props.joinDate)).toBeInTheDocument(); + expect(screen.getByText(props.email)).toBeInTheDocument(); + }); + + it('Should render text elements when props value is not passed', async () => { + global.confirm = (): boolean => false; + + render( + + + + + + ); + + await wait(); + userEvent.click(screen.getByText(/Accept/i)); + userEvent.click(screen.getByText(/Reject/i)); + + expect(screen.getByAltText(/userImage/i)).toBeInTheDocument(); + expect(screen.getByText(/Joined:/i)).toBeInTheDocument(); + expect(screen.queryByText(props.memberName)).not.toBeInTheDocument(); + expect(screen.getByText(props.memberLocation)).toBeInTheDocument(); + expect(screen.getByText(props.joinDate)).toBeInTheDocument(); + expect(screen.getByText(props.email)).toBeInTheDocument(); + }); +}); diff --git a/src/components/MemberRequestCard/MemberRequestCard.tsx b/src/components/MemberRequestCard/MemberRequestCard.tsx new file mode 100644 index 0000000000..b238b66a9d --- /dev/null +++ b/src/components/MemberRequestCard/MemberRequestCard.tsx @@ -0,0 +1,125 @@ +import React from 'react'; +import styles from './MemberRequestCard.module.css'; +import Row from 'react-bootstrap/Row'; +import Col from 'react-bootstrap/Col'; +import Button from 'react-bootstrap/Button'; +import { useMutation } from '@apollo/client'; +import { + ACCEPT_ORGANIZATION_REQUEST_MUTATION, + REJECT_ORGANIZATION_REQUEST_MUTATION, +} from 'GraphQl/Mutations/mutations'; +import { useTranslation } from 'react-i18next'; +import { toast } from 'react-toastify'; +import defaultImg from 'assets/images/blank.png'; +import { errorHandler } from 'utils/errorHandler'; + +interface InterfaceMemberRequestCardProps { + key: string; + id: string; + memberName: string; + memberLocation: string; + joinDate: string; + memberImage: string; + email: string; +} + +function memberRequestCard( + props: InterfaceMemberRequestCardProps +): JSX.Element { + const [acceptMutation] = useMutation(ACCEPT_ORGANIZATION_REQUEST_MUTATION); + const [rejectMutation] = useMutation(REJECT_ORGANIZATION_REQUEST_MUTATION); + + const { t } = useTranslation('translation', { + keyPrefix: 'membershipRequest', + }); + + const addMember = async (): Promise => { + try { + await acceptMutation({ + variables: { + id: props.id, + }, + }); + + /* istanbul ignore next */ + toast.success(t('memberAdded')); + /* istanbul ignore next */ + setTimeout(() => { + window.location.reload(); + }, 2000); + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + + const rejectMember = async (): Promise => { + const sure = window.confirm('Are you sure you want to Reject Request ?'); + if (sure) { + try { + await rejectMutation({ + variables: { + userid: props.id, + }, + }); + + /* istanbul ignore next */ + window.location.reload(); + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + } + }; + + return ( + <> +
    + + {props.memberImage ? ( + userImage + ) : ( + userImage + )} + +
    +

    + {props.memberName ? <>{props.memberName} : <>Dogs Care} +

    +

    {props.memberLocation}

    +

    {props.email}

    +
    +
    +

    + {t('joined')}: {props.joinDate} +

    + + +
    + +
    +
    +
    + + ); +} +export {}; +export default memberRequestCard; diff --git a/src/components/NotFound/NotFound.module.css b/src/components/NotFound/NotFound.module.css new file mode 100644 index 0000000000..5f0ca7a730 --- /dev/null +++ b/src/components/NotFound/NotFound.module.css @@ -0,0 +1,24 @@ +.section { + position: relative; + margin: 20px auto; + width: 100%; + background-color: #fff; + padding: 4px; + border-radius: 0.5rem; +} + +.error { + font-size: 1.2rem; + color: #575656; + font-weight: 500; +} + +@media (min-width: 440px) and (max-width: 570px) { + .section { + margin-left: 50px; + } + .error { + font-size: 1.1rem; + font-style: oblique; + } +} diff --git a/src/components/NotFound/NotFound.test.tsx b/src/components/NotFound/NotFound.test.tsx new file mode 100644 index 0000000000..82c3bd348e --- /dev/null +++ b/src/components/NotFound/NotFound.test.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; + +import { render, screen } from '@testing-library/react'; +import NotFound from './NotFound'; + +describe('Tesing the NotFound Component', () => { + it('renders the component with the correct title for posts', () => { + render( + + + + ); + expect(screen.getByText(/Not Found!/i)).toBeInTheDocument(); + }); + + it('renders the component with the correct title for users', () => { + render( + + + + ); + expect(screen.getByText(/Not Found!/i)).toBeInTheDocument(); + }); +}); diff --git a/src/components/NotFound/NotFound.tsx b/src/components/NotFound/NotFound.tsx new file mode 100644 index 0000000000..6e2853cf82 --- /dev/null +++ b/src/components/NotFound/NotFound.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +import styles from './NotFound.module.css'; + +interface InterfaceNotFoundProps { + title: string; + keyPrefix: string; +} + +function notFound(props: InterfaceNotFoundProps): JSX.Element { + const key = props.keyPrefix.toString(); + const { t } = useTranslation('translation', { + keyPrefix: key, + }); + return ( + <> +
    +

    {t(`${props.title} not found!`)}

    +
    + + ); +} + +export default notFound; diff --git a/src/components/OrgAdminListCard/OrgAdminListCard.module.css b/src/components/OrgAdminListCard/OrgAdminListCard.module.css new file mode 100644 index 0000000000..187757a531 --- /dev/null +++ b/src/components/OrgAdminListCard/OrgAdminListCard.module.css @@ -0,0 +1,74 @@ +.memberlist { + margin-top: -1px; +} +.memberimg { + width: 200px; + height: 100px; + border-radius: 7px; + margin-left: 20px; +} +.singledetails { + display: flex; + flex-direction: row; + justify-content: space-between; +} +.singledetails p { + margin-bottom: -5px; +} +.singledetails_data_left { + margin-top: 10px; + margin-left: 10px; + color: #707070; +} +.singledetails_data_right { + justify-content: right; + margin-top: 10px; + text-align: right; + color: #707070; +} +.membername { + font-size: 16px; + font-weight: bold; +} +.memberfont { + margin-top: 3px; +} +.memberfont > span { + width: 80%; +} +.memberfontcreated { + margin-top: 18px; +} +.memberfontcreatedbtn { + margin-top: 33px; + border-radius: 7px; + border-color: #31bb6b; + background-color: #31bb6b; + color: white; + padding-right: 10px; + padding-left: 10px; + justify-content: flex-end; + float: right; + text-align: right; + box-shadow: none; +} +#grid_wrapper { + align-items: left; +} +.peoplelistdiv { + margin-right: 50px; +} +@media only screen and (max-width: 600px) { + .singledetails { + margin-left: 20px; + } + .memberimg { + margin: auto; + } + .singledetails_data_right { + margin-right: -52px; + } + .singledetails_data_left { + margin-left: 0px; + } +} diff --git a/src/components/OrgAdminListCard/OrgAdminListCard.test.tsx b/src/components/OrgAdminListCard/OrgAdminListCard.test.tsx new file mode 100644 index 0000000000..db499cd0b1 --- /dev/null +++ b/src/components/OrgAdminListCard/OrgAdminListCard.test.tsx @@ -0,0 +1,99 @@ +import React from 'react'; +import { act, render, screen } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; + +import { REMOVE_ADMIN_MUTATION } from 'GraphQl/Mutations/mutations'; +import OrgAdminListCard from './OrgAdminListCard'; +import i18nForTest from 'utils/i18nForTest'; +import { BrowserRouter } from 'react-router-dom'; +import { StaticMockLink } from 'utils/StaticMockLink'; + +const MOCKS = [ + { + request: { + query: REMOVE_ADMIN_MUTATION, + variable: { userid: '564', orgid: '987' }, + }, + result: { + data: { + organizations: [ + { + _id: '1', + }, + ], + }, + }, + }, +]; +const link = new StaticMockLink(MOCKS, true); +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Testing Organization Admin List Card', () => { + global.alert = jest.fn(); + + test('should render props and text elements test for the page component', async () => { + const props = { + key: '123', + id: '456', + memberName: 'John Doe', + joinDate: '05/05/2022', + memberImage: 'image', + memberEmail: 'johndoe@gmail.com', + }; + + render( + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId(/removeAdminModalBtn/i)); + userEvent.click(screen.getByTestId(/removeAdminBtn/i)); + + expect(screen.getByText(props.memberName)).toBeInTheDocument(); + expect(screen.getByText(props.joinDate)).toBeInTheDocument(); + }); + + test('Should render text elements when props value is not passed', async () => { + const props = { + key: '123', + id: '456', + memberName: '', + joinDate: '05/05/2022', + memberImage: '', + memberEmail: '', + }; + + render( + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId(/removeAdminModalBtn/i)); + userEvent.click(screen.getByTestId(/removeAdminBtn/i)); + + expect(screen.getByText(/Dogs Care/i)).toBeInTheDocument(); + expect(screen.getByText(props.joinDate)).toBeInTheDocument(); + }); +}); diff --git a/src/components/OrgAdminListCard/OrgAdminListCard.tsx b/src/components/OrgAdminListCard/OrgAdminListCard.tsx new file mode 100644 index 0000000000..df0bf70071 --- /dev/null +++ b/src/components/OrgAdminListCard/OrgAdminListCard.tsx @@ -0,0 +1,120 @@ +import React from 'react'; +import Row from 'react-bootstrap/Row'; +import Col from 'react-bootstrap/Col'; +import Button from 'react-bootstrap/Button'; +import Modal from 'react-bootstrap/Modal'; +import { useMutation } from '@apollo/client'; +import { toast } from 'react-toastify'; + +import styles from './OrgAdminListCard.module.css'; +import { REMOVE_ADMIN_MUTATION } from 'GraphQl/Mutations/mutations'; +import { useTranslation } from 'react-i18next'; +import { Link } from 'react-router-dom'; +import defaultImg from 'assets/images/blank.png'; +import { errorHandler } from 'utils/errorHandler'; + +interface InterfaceOrgPeopleListCardProps { + key: string; + id: string; + memberName: string; + joinDate: string; + memberImage: string; + memberEmail: string; +} +const currentUrl = window.location.href.split('=')[1]; + +function orgAdminListCard(props: InterfaceOrgPeopleListCardProps): JSX.Element { + const [remove] = useMutation(REMOVE_ADMIN_MUTATION); + const [showRemoveAdminModal, setShowRemoveAdminModal] = React.useState(false); + + const { t } = useTranslation('translation', { + keyPrefix: 'orgAdminListCard', + }); + + const toggleRemoveAdminModal = (): void => + setShowRemoveAdminModal(!showRemoveAdminModal); + + const removeAdmin = async (): Promise => { + try { + const { data } = await remove({ + variables: { + userid: props.id, + orgid: currentUrl, + }, + }); + + /* istanbul ignore next */ + if (data) { + toast.success(t('adminRemoved')); + setTimeout(() => { + window.location.reload(); + }, 2000); + } + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + return ( +
    +
    + + {props.memberImage ? ( + + ) : ( + + )} + +
    + + {props.memberName ? <>{props.memberName} : <>Dogs Care} + +

    {props.memberEmail}

    +
    +
    +

    + {t('joined')}: {props.joinDate} +

    + +
    + +
    +
    +
    + + +
    {t('removeAdmin')}
    + +
    + {t('removeAdminMsg')} + + + + +
    +
    + ); +} +export default orgAdminListCard; diff --git a/src/components/OrgContriCards/OrgContriCards.module.css b/src/components/OrgContriCards/OrgContriCards.module.css new file mode 100644 index 0000000000..d20b696621 --- /dev/null +++ b/src/components/OrgContriCards/OrgContriCards.module.css @@ -0,0 +1,22 @@ +.cards { + width: 45%; + background: #fcfcfc; + margin: 10px 20px; + padding: 20px 30px; + border-radius: 5px; + border: 1px solid #e8e8e8; + box-shadow: 0 3px 5px #c9c9c9; + margin-right: 40px; + color: #737373; +} +.cards > h2 { + font-size: 19px; +} +.cards > h3 { + font-size: 17px; +} +.cards > p { + font-size: 14px; + margin-top: -5px; + margin-bottom: 7px; +} diff --git a/src/components/OrgContriCards/OrgContriCards.test.tsx b/src/components/OrgContriCards/OrgContriCards.test.tsx new file mode 100644 index 0000000000..95de529d98 --- /dev/null +++ b/src/components/OrgContriCards/OrgContriCards.test.tsx @@ -0,0 +1,50 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import type { NormalizedCacheObject } from '@apollo/client'; +import { ApolloClient, ApolloProvider, InMemoryCache } from '@apollo/client'; +import { I18nextProvider } from 'react-i18next'; + +import OrgContriCards from './OrgContriCards'; +import i18nForTest from 'utils/i18nForTest'; +import { BACKEND_URL } from 'Constant/constant'; + +const client: ApolloClient = new ApolloClient({ + cache: new InMemoryCache(), + uri: BACKEND_URL, +}); + +describe('Testing the Organization Contributions Cards', () => { + const props = { + key: '123', + id: '123', + userName: 'John Doe', + contriDate: '06/03/2022', + contriAmount: '500', + contriTransactionId: 'QW56DA88', + userEmail: 'johndoe@gmail.com', + }; + + it('should render props and text elements test for the page component', () => { + render( + + + + + + ); + expect(screen.getByText('Date:')).toBeInTheDocument(); + expect(screen.getByText('John Doe')).toBeInTheDocument(); + expect(screen.getByText('06/03/2022')).toBeInTheDocument(); + expect(screen.getByText('500')).toBeInTheDocument(); + expect(screen.getByText('QW56DA88')).toBeInTheDocument(); + expect(screen.getByText('johndoe@gmail.com')).toBeInTheDocument(); + }); +}); diff --git a/src/components/OrgContriCards/OrgContriCards.tsx b/src/components/OrgContriCards/OrgContriCards.tsx new file mode 100644 index 0000000000..69a9e03d58 --- /dev/null +++ b/src/components/OrgContriCards/OrgContriCards.tsx @@ -0,0 +1,42 @@ +import React from 'react'; +import Row from 'react-bootstrap/Row'; +import Col from 'react-bootstrap/Col'; +import { useTranslation } from 'react-i18next'; + +import styles from './OrgContriCards.module.css'; + +interface InterfaceOrgContriCardsProps { + key: string; + id: string; + userName: string; + contriDate: string; + contriAmount: string; + contriTransactionId: string; + userEmail: string; +} +function orgContriCards(props: InterfaceOrgContriCardsProps): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'orgContriCards', + }); + + return ( + <> + + +

    {props.userName}

    +

    {props.userEmail}

    +

    + {t('date')}:{props.contriDate} +

    +

    + {t('transactionId')}: {props.contriTransactionId} +

    +

    + {t('amount')}: $ {props.contriAmount} +

    + +
    + + ); +} +export default orgContriCards; diff --git a/src/components/OrgDelete/OrgDelete.test.tsx b/src/components/OrgDelete/OrgDelete.test.tsx new file mode 100644 index 0000000000..cc89241f56 --- /dev/null +++ b/src/components/OrgDelete/OrgDelete.test.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import type { NormalizedCacheObject } from '@apollo/client'; +import { ApolloClient, ApolloProvider, InMemoryCache } from '@apollo/client'; +import { I18nextProvider } from 'react-i18next'; + +import OrgDelete from './OrgDelete'; +import i18nForTest from 'utils/i18nForTest'; +import { BACKEND_URL } from 'Constant/constant'; + +const client: ApolloClient = new ApolloClient({ + cache: new InMemoryCache(), + uri: BACKEND_URL, +}); + +describe('Testing Organization People List Card', () => { + test('should render props and text elements test for the page component', () => { + render( + + + + + + ); + expect(screen.getByText('Delete Org')).toBeInTheDocument(); + }); +}); diff --git a/src/components/OrgDelete/OrgDelete.tsx b/src/components/OrgDelete/OrgDelete.tsx new file mode 100644 index 0000000000..0f1335dae4 --- /dev/null +++ b/src/components/OrgDelete/OrgDelete.tsx @@ -0,0 +1,17 @@ +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +function orgDelete(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'orgDelete', + }); + + return ( + <> +
    + {t('deleteOrg')} +
    + + ); +} +export default orgDelete; diff --git a/src/components/OrgListCard/OrgListCard.module.css b/src/components/OrgListCard/OrgListCard.module.css new file mode 100644 index 0000000000..1f1e5e2974 --- /dev/null +++ b/src/components/OrgListCard/OrgListCard.module.css @@ -0,0 +1,92 @@ +.orgCard { + background-color: var(--bs-white); + margin: 0.5rem; + height: calc(120px + 2rem); + padding: 1rem; + border-radius: 8px; + outline: 1px solid var(--bs-gray-200); + position: relative; +} + +.orgCard .innerContainer { + display: flex; +} + +.orgCard .innerContainer .orgImgContainer { + display: flex; + justify-content: center; + align-items: center; + position: relative; + overflow: hidden; + border-radius: 4px; +} + +.orgCard .innerContainer .orgImgContainer img { + width: 125px; + height: 120px; + object-fit: contain; +} + +.orgCard .innerContainer .orgImgContainer .emptyImg { + width: 125px; + height: 120px; + background-color: var(--bs-gray-200); +} + +.orgCard .innerContainer .content { + flex: 1; + margin-left: 1rem; +} + +.orgCard button { + position: absolute; + bottom: 1rem; + right: 1rem; + z-index: 1; +} + +@media (max-width: 450px) { + .orgCard { + height: unset; + margin: 0.5rem 0; + padding: 1.25rem 1.5rem; + } + + .orgCard .innerContainer { + flex-direction: column; + } + + .orgCard .innerContainer .orgImgContainer { + margin-bottom: 0.8rem; + } + + .orgCard .innerContainer .orgImgContainer img { + height: auto; + width: 100%; + } + + .orgCard .innerContainer .content { + margin-left: 0; + } + + .orgCard button { + bottom: 0; + right: 0; + position: relative; + margin-left: auto; + display: block; + } +} + +.flaskIcon { + position: absolute; + top: 0; + right: 0; + margin: 10px 20px 0px 0px; +} + +.manageBtn { + display: flex; + justify-content: space-around; + width: 150px; +} diff --git a/src/components/OrgListCard/OrgListCard.test.tsx b/src/components/OrgListCard/OrgListCard.test.tsx new file mode 100644 index 0000000000..ffcf92981f --- /dev/null +++ b/src/components/OrgListCard/OrgListCard.test.tsx @@ -0,0 +1,119 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import 'jest-location-mock'; +import { I18nextProvider } from 'react-i18next'; + +import i18nForTest from 'utils/i18nForTest'; +import type { InterfaceOrgListCardProps } from './OrgListCard'; +import OrgListCard from './OrgListCard'; +import userEvent from '@testing-library/user-event'; +import { BrowserRouter } from 'react-router-dom'; +import { IS_SAMPLE_ORGANIZATION_QUERY } from 'GraphQl/Queries/Queries'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { MockedProvider } from '@apollo/react-testing'; + +const MOCKS = [ + { + request: { + query: IS_SAMPLE_ORGANIZATION_QUERY, + }, + result: { + data: { + isSampleOrganization: true, + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); + +const props: InterfaceOrgListCardProps = { + data: { + _id: 'xyz', + name: 'Dogs Care', + image: 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', + location: 'India', + admins: [ + { + _id: '123', + }, + { + _id: '456', + }, + ], + members: [], + createdAt: '04/07/2019', + creator: { + _id: 'abc', + firstName: 'John', + lastName: 'Doe', + }, + }, +}; + +describe('Testing the Super Dash List', () => { + test('should render props and text elements test for the page component', () => { + localStorage.setItem('id', '123'); // Means the user is an admin + + render( + + + + + + + + ); + expect(screen.getByAltText(/Dogs Care image/i)).toBeInTheDocument(); + expect(screen.getByText('Admins:')).toBeInTheDocument(); + expect(screen.getByText('Members:')).toBeInTheDocument(); + expect(screen.getByText('Dogs Care')).toBeInTheDocument(); + expect(screen.getByText('India')).toBeInTheDocument(); + userEvent.click(screen.getByTestId(/manageBtn/i)); + }); + + test('Testing if the props data is not provided', () => { + window.location.assign('/orgdash'); + + render( + + + + + + + + ); + + expect(window.location).toBeAt('/orgdash'); + }); + + test('Testing if component is rendered properly when image is null', () => { + const imageNullProps = { + ...props, + ...{ data: { ...props.data, ...{ image: null } } }, + }; + render( + + + + + + ); + expect(screen.getByTestId(/emptyContainerForImage/i)).toBeInTheDocument(); + }); + + test('Testing if user is redirected to orgDash screen', () => { + render( + + + + + + + + ); + userEvent.click(screen.getByTestId('manageBtn')); + expect(window.location).toBeAt('/orgdash/id=xyz'); + }); +}); diff --git a/src/components/OrgListCard/OrgListCard.tsx b/src/components/OrgListCard/OrgListCard.tsx new file mode 100644 index 0000000000..191a689bc0 --- /dev/null +++ b/src/components/OrgListCard/OrgListCard.tsx @@ -0,0 +1,90 @@ +import React from 'react'; +import { ReactComponent as FlaskIcon } from 'assets/svgs/flask.svg'; +import Button from 'react-bootstrap/Button'; +import { useTranslation } from 'react-i18next'; +import styles from './OrgListCard.module.css'; +import { useHistory } from 'react-router-dom'; +import type { InterfaceOrgConnectionInfoType } from 'utils/interfaces'; +import LocationOnIcon from '@mui/icons-material/LocationOn'; +import { IS_SAMPLE_ORGANIZATION_QUERY } from 'GraphQl/Queries/Queries'; +import { useQuery } from '@apollo/client'; + +export interface InterfaceOrgListCardProps { + data: InterfaceOrgConnectionInfoType; +} + +function orgListCard(props: InterfaceOrgListCardProps): JSX.Element { + const { _id, admins, image, location, members, name } = props.data; + + const { data } = useQuery(IS_SAMPLE_ORGANIZATION_QUERY, { + variables: { + isSampleOrganizationId: _id, + }, + }); + + const history = useHistory(); + + function handleClick(): void { + const url = '/orgdash/id=' + _id; + + // Dont change the below two lines + window.location.replace(url); + history.push(url); + } + + const { t } = useTranslation('translation', { + keyPrefix: 'orgListCard', + }); + + return ( + <> +
    +
    +
    + {image ? ( + {`${name} + ) : ( +
    + )} +
    +
    +
    + + {location} +
    +
    + {t('admins')}: {admins.length} +
    +
    + {t('members')}: {members.length} +
    +
    {name}
    +
    +
    + +
    + + ); +} +export default orgListCard; diff --git a/src/components/OrgPeopleListCard/OrgPeopleListCard.module.css b/src/components/OrgPeopleListCard/OrgPeopleListCard.module.css new file mode 100644 index 0000000000..187757a531 --- /dev/null +++ b/src/components/OrgPeopleListCard/OrgPeopleListCard.module.css @@ -0,0 +1,74 @@ +.memberlist { + margin-top: -1px; +} +.memberimg { + width: 200px; + height: 100px; + border-radius: 7px; + margin-left: 20px; +} +.singledetails { + display: flex; + flex-direction: row; + justify-content: space-between; +} +.singledetails p { + margin-bottom: -5px; +} +.singledetails_data_left { + margin-top: 10px; + margin-left: 10px; + color: #707070; +} +.singledetails_data_right { + justify-content: right; + margin-top: 10px; + text-align: right; + color: #707070; +} +.membername { + font-size: 16px; + font-weight: bold; +} +.memberfont { + margin-top: 3px; +} +.memberfont > span { + width: 80%; +} +.memberfontcreated { + margin-top: 18px; +} +.memberfontcreatedbtn { + margin-top: 33px; + border-radius: 7px; + border-color: #31bb6b; + background-color: #31bb6b; + color: white; + padding-right: 10px; + padding-left: 10px; + justify-content: flex-end; + float: right; + text-align: right; + box-shadow: none; +} +#grid_wrapper { + align-items: left; +} +.peoplelistdiv { + margin-right: 50px; +} +@media only screen and (max-width: 600px) { + .singledetails { + margin-left: 20px; + } + .memberimg { + margin: auto; + } + .singledetails_data_right { + margin-right: -52px; + } + .singledetails_data_left { + margin-left: 0px; + } +} diff --git a/src/components/OrgPeopleListCard/OrgPeopleListCard.test.tsx b/src/components/OrgPeopleListCard/OrgPeopleListCard.test.tsx new file mode 100644 index 0000000000..e283f92e13 --- /dev/null +++ b/src/components/OrgPeopleListCard/OrgPeopleListCard.test.tsx @@ -0,0 +1,103 @@ +import React from 'react'; +import { act, render, screen } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; + +import OrgPeopleListCard from './OrgPeopleListCard'; +import { REMOVE_MEMBER_MUTATION } from 'GraphQl/Mutations/mutations'; +import i18nForTest from 'utils/i18nForTest'; +import { BrowserRouter } from 'react-router-dom'; +import { StaticMockLink } from 'utils/StaticMockLink'; + +const MOCKS = [ + { + request: { + query: REMOVE_MEMBER_MUTATION, + variable: { userid: '123', orgid: '456' }, + }, + result: { + data: { + organizations: [ + { + _id: '1', + }, + ], + }, + }, + }, +]; +const link = new StaticMockLink(MOCKS, true); +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Testing Organization People List Card', () => { + const props = { + key: '123', + id: '1', + memberName: 'John Doe', + joinDate: '20/03/2022', + memberImage: 'image', + memberEmail: 'johndoe@gmail.com', + }; + + global.alert = jest.fn(); + + test('should render props and text elements test for the page component', async () => { + global.confirm = (): boolean => true; + + render( + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId(/removeMemberModalBtn/i)); + userEvent.click(screen.getByTestId(/removeMemberBtn/i)); + + expect(screen.getByText(/Joined:/i)).toBeInTheDocument(); + expect(screen.getByText(props.memberName)).toBeInTheDocument(); + expect(screen.getByText(props.joinDate)).toBeInTheDocument(); + }); + + test('Should render text elements when props value is not passed', async () => { + global.confirm = (): boolean => false; + + render( + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId(/removeMemberModalBtn/i)); + userEvent.click(screen.getByTestId(/removeMemberBtn/i)); + + expect(screen.getByText(/Joined:/i)).toBeInTheDocument(); + expect(screen.queryByText(props.memberName)).not.toBeInTheDocument(); + expect(screen.getByText(props.joinDate)).toBeInTheDocument(); + }); +}); diff --git a/src/components/OrgPeopleListCard/OrgPeopleListCard.tsx b/src/components/OrgPeopleListCard/OrgPeopleListCard.tsx new file mode 100644 index 0000000000..74f0ae1805 --- /dev/null +++ b/src/components/OrgPeopleListCard/OrgPeopleListCard.tsx @@ -0,0 +1,123 @@ +import React from 'react'; +import styles from './OrgPeopleListCard.module.css'; +import Row from 'react-bootstrap/Row'; +import Col from 'react-bootstrap/Col'; +import Button from 'react-bootstrap/Button'; +import Modal from 'react-bootstrap/Modal'; +import { useMutation } from '@apollo/client'; +import { toast } from 'react-toastify'; +import { useTranslation } from 'react-i18next'; +import { REMOVE_MEMBER_MUTATION } from 'GraphQl/Mutations/mutations'; +import { Link } from 'react-router-dom'; +import defaultImg from 'assets/images/blank.png'; +import { errorHandler } from 'utils/errorHandler'; + +interface InterfaceOrgPeopleListCardProps { + key: string; + id: string; + memberName: string; + joinDate: string; + memberImage: string; + memberEmail: string; +} + +function orgPeopleListCard( + props: InterfaceOrgPeopleListCardProps +): JSX.Element { + const currentUrl = window.location.href.split('=')[1]; + const [remove] = useMutation(REMOVE_MEMBER_MUTATION); + const [showRemoveAdminModal, setShowRemoveAdminModal] = React.useState(false); + + const toggleRemoveAdminModal = (): void => + setShowRemoveAdminModal(!showRemoveAdminModal); + + const { t } = useTranslation('translation', { + keyPrefix: 'orgPeopleListCard', + }); + + const removeMember = async (): Promise => { + try { + const { data } = await remove({ + variables: { + userid: props.id, + orgid: currentUrl, + }, + }); + + /* istanbul ignore next */ + if (data) { + toast.success(t('memberRemoved')); + setTimeout(() => { + window.location.reload(); + }, 2000); + } + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + return ( +
    +
    + + {props.memberImage ? ( + + ) : ( + + )} + +
    + + {props.memberName ? <>{props.memberName} : <>Dogs Care} + +

    {props.memberEmail}

    +
    +
    +

    + {t('joined')}: {props.joinDate} +

    + +
    + +
    +
    +
    + + +
    {t('removeMember')}
    + +
    + {t('removeMemberMsg')} + + + + +
    +
    + ); +} +export {}; +export default orgPeopleListCard; diff --git a/src/components/OrgPostCard/OrgPostCard.module.css b/src/components/OrgPostCard/OrgPostCard.module.css new file mode 100644 index 0000000000..c7ff8073d2 --- /dev/null +++ b/src/components/OrgPostCard/OrgPostCard.module.css @@ -0,0 +1,278 @@ +.cards h2 { + font-size: 20px; +} +.cards > h3 { + font-size: 17px; +} +.card { + width: 100%; + height: 20rem; + margin-bottom: 2rem; +} +.postimage { + border-radius: 0px; + width: 100%; + height: 12rem; + max-width: 100%; + max-height: 12rem; + object-fit: cover; + position: relative; + color: black; +} +.preview { + display: flex; + position: relative; + width: 100%; + margin-top: 10px; + justify-content: center; +} +.preview img { + width: 400px; + height: auto; +} +.preview video { + width: 400px; + height: auto; +} +.nopostimage { + border-radius: 0px; + width: 100%; + height: 12rem; + max-height: 12rem; + object-fit: cover; + position: relative; +} +.cards:hover { + filter: brightness(0.8); +} +.cards:hover::before { + opacity: 0.5; +} +.knowMoreText { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + opacity: 0; + color: white; + padding: 10px; + font-weight: bold; + font-size: 1.5rem; + transition: opacity 0.3s ease-in-out; +} + +.cards:hover .knowMoreText { + opacity: 1; +} +.modal { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + background-color: rgba( + 0, + 0, + 0, + 0.9 + ); /* Dark grey modal background with transparency */ + z-index: 9999; +} + +.modalContent { + display: flex; + align-items: center; + justify-content: center; + background-color: #fff; + padding: 20px; + max-width: 800px; + max-height: 600px; + overflow: auto; +} + +.modalImage { + flex: 1; + margin-right: 20px; + width: 25rem; + height: 15rem; +} +.nomodalImage { + flex: 1; + margin-right: 20px; + width: 100%; + height: 15rem; +} + +.modalImage img, +.modalImage video { + border-radius: 0px; + width: 100%; + height: 25rem; + max-width: 25rem; + max-height: 15rem; + object-fit: cover; + position: relative; +} +.modalInfo { + flex: 1; +} +.title { + font-size: 16px; + color: #000; + font-weight: 600; +} +.text { + font-size: 13px; + color: #000; + font-weight: 300; +} +.author { + color: #737373; + font-weight: 100; + font-size: 13px; +} +.closeButton { + position: relative; + bottom: 5rem; + right: 10px; + padding: 4px; + background-color: red; /* Red close button color */ + color: #fff; + border: none; + cursor: pointer; +} +.closeButtonP { + position: absolute; + top: 0px; + right: 0px; + background: transparent; + transform: scale(1.2); + cursor: pointer; + border: none; + color: #707070; + font-weight: 600; + font-size: 16px; + cursor: pointer; +} +.cards:hover::after { + opacity: 1; + mix-blend-mode: normal; +} +.cards > p { + font-size: 14px; + margin-top: 0px; + margin-bottom: 7px; +} +.cards a { + color: #737373; + font-weight: 600; +} +.cards a:hover { + color: black; +} +.infodiv { + margin-bottom: 7px; + width: 15rem; + text-align: justify; + word-wrap: break-word; +} +.infodiv > p { + margin: 0; +} +.dispflex { + display: flex; + justify-content: space-between; +} +.iconContainer { + display: flex; +} +.icon { + transform: scale(0.75); + cursor: pointer; +} +/* .cards { + width: 75%; + background: #fcfcfc; + margin: 10px 40px; + padding: 20px 30px; + border-radius: 5px; + border: 1px solid #e8e8e8; + box-shadow: 0 3px 5px #c9c9c9; + margin-right: 30px; + color: #737373; + box-sizing: border-box; +} */ +.cards:last-child:nth-last-child(odd) { + grid-column: auto / span 2; +} +.cards:first-child:nth-last-child(even), +.cards:first-child:nth-last-child(even) ~ .box { + grid-column: auto / span 1; +} +.toggleClickBtn { + color: #31bb6b; + cursor: pointer; + border: none; + font-size: 12px; + background-color: white; +} +.toggleClickBtnNone { + display: none; +} +/* Menu Modal Styles */ +.menuModal { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + background-color: rgba(0, 0, 0, 0.7); /* Dark grey modal background */ + z-index: 9999; +} + +.menuContent { + display: flex; + align-items: center; + justify-content: center; + background-color: #fff; + padding-top: 20px; + max-width: 700px; + max-height: 500px; + overflow: hidden; + position: relative; +} + +.menuOptions { + list-style-type: none; + padding: 0; + margin: 0; +} + +.menuOptions li { + padding: 10px; + border-bottom: 1px solid #ccc; + padding-left: 100px; + padding-right: 100px; + cursor: pointer; +} + +.moreOptionsButton { + position: relative; + bottom: 5rem; + right: 10px; + padding: 2px; + background-color: transparent; + color: #000; + border: none; + cursor: pointer; +} +.list { + color: red; + cursor: pointer; +} diff --git a/src/components/OrgPostCard/OrgPostCard.test.tsx b/src/components/OrgPostCard/OrgPostCard.test.tsx new file mode 100644 index 0000000000..e2a209c00f --- /dev/null +++ b/src/components/OrgPostCard/OrgPostCard.test.tsx @@ -0,0 +1,403 @@ +import React from 'react'; +import { + act, + render, + screen, + fireEvent, + waitFor, +} from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import OrgPostCard from './OrgPostCard'; +import { I18nextProvider } from 'react-i18next'; +import userEvent from '@testing-library/user-event'; +import 'jest-localstorage-mock'; +import { + DELETE_POST_MUTATION, + UPDATE_POST_MUTATION, + TOGGLE_PINNED_POST, +} from 'GraphQl/Mutations/mutations'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import convertToBase64 from 'utils/convertToBase64'; +import { BrowserRouter } from 'react-router-dom'; +const MOCKS = [ + { + request: { + query: DELETE_POST_MUTATION, + variable: { id: '123' }, + }, + result: { + data: { + removePost: { + _id: '123', + }, + }, + }, + }, + { + request: { + query: UPDATE_POST_MUTATION, + variable: { + id: '123', + title: 'updated title', + text: 'This is a updated text', + }, + }, + result: { + data: { + updatePost: { + _id: '32', + }, + }, + }, + }, + { + request: { + query: TOGGLE_PINNED_POST, + variables: { + id: '32', + }, + }, + result: { + data: { + togglePostPin: { + _id: '32', + }, + }, + }, + }, +]; +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }, +})); +const link = new StaticMockLink(MOCKS, true); +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} +describe('Testing Organization Post Card', () => { + const props = { + key: '123', + id: '12', + postTitle: 'Event Info', + postInfo: 'Time change', + postAuthor: 'John Doe', + postPhoto: 'test.png', + postVideo: 'test.mp4', + pinned: false, + }; + jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }, + })); + jest.mock('react', () => ({ + ...jest.requireActual('react'), + useRef: jest.fn(), + })); + global.alert = jest.fn(); + + test('renders with default props', () => { + const { getByAltText, getByTestId } = render( + + + + + + ); + expect(getByTestId('card-text')).toBeInTheDocument(); + expect(getByTestId('card-title')).toBeInTheDocument(); + expect(getByAltText('image')).toBeInTheDocument(); + }); + + test('toggles "Read more" button', () => { + const { getByTestId } = render( + + + + + + ); + userEvent.click(screen.getByAltText('image')); + const toggleButton = getByTestId('toggleBtn'); + fireEvent.click(toggleButton); + expect(toggleButton).toHaveTextContent('hide'); + fireEvent.click(toggleButton); + expect(toggleButton).toHaveTextContent('Read more'); + }); + test('opens and closes edit modal', async () => { + localStorage.setItem('id', '123'); + + render( + + + + + + ); + await wait(); + userEvent.click(screen.getByAltText('image')); + userEvent.click(screen.getByTestId('moreiconbtn')); + userEvent.click(screen.getByTestId('editPostModalBtn')); + + const createOrgBtn = screen.getByTestId('modalOrganizationHeader'); + expect(createOrgBtn).toBeInTheDocument(); + userEvent.click(createOrgBtn); + userEvent.click(screen.getByTestId('closeOrganizationModal')); + }); + test('Should render text elements when props value is not passed', async () => { + global.confirm = (): boolean => false; + render( + + + + + + ); + await wait(); + userEvent.click(screen.getByAltText('image')); + expect(screen.getByAltText('Post Image')).toBeInTheDocument(); + }); + test('Testing post updating after post is updated', async () => { + render( + + + + + + ); + + await wait(); + + userEvent.click(screen.getByAltText('image')); + userEvent.click(screen.getByTestId('moreiconbtn')); + + userEvent.click(screen.getByTestId('editPostModalBtn')); + userEvent.type(screen.getByTestId('updateTitle'), 'updated title'); + userEvent.type(screen.getByTestId('updateText'), 'This is a updated text'); + userEvent.click(screen.getByTestId('updatePostBtn')); + }); + test('Testing pin post functionality', async () => { + render( + + + + + + ); + + await wait(); + + userEvent.click(screen.getByAltText('image')); + userEvent.click(screen.getByTestId('moreiconbtn')); + + userEvent.click(screen.getByTestId('pinpostBtn')); + }); + test('Testing post delete functionality', async () => { + render( + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByAltText('image')); + userEvent.click(screen.getByTestId('moreiconbtn')); + + userEvent.click(screen.getByTestId('deletePostModalBtn')); + fireEvent.click(screen.getByTestId('deletePostBtn')); + }); + test('Testing close functionality of primary modal', async () => { + render( + + + + + + ); + + await wait(); + + userEvent.click(screen.getByAltText('image')); + userEvent.click(screen.getByTestId('closeiconbtn')); + }); + test('Testing close functionality of secondary modal', async () => { + render( + + + + + + ); + + await wait(); + + userEvent.click(screen.getByAltText('image')); + userEvent.click(screen.getByTestId('moreiconbtn')); + userEvent.click(screen.getByTestId('closebtn')); + }); + test('renders without "Read more" button when postInfo length is less than or equal to 43', () => { + const props = { + key: '123', + id: '12', + postTitle: 'Event Info', + postInfo: 'Lorem ipsum dolor sit amet', + postAuthor: 'John Doe', + postPhoto: 'photoLink', + postVideo: 'videoLink', + pinned: false, + }; + render( + + + + + + ); + }); + test('updates state variables correctly when handleEditModal is called', () => { + const link2 = new StaticMockLink(MOCKS, true); + render( + + + + ); + userEvent.click(screen.getByAltText('image')); + + userEvent.click(screen.getByTestId('moreiconbtn')); + + expect(screen.queryByTestId('editPostModalBtn')).toBeInTheDocument(); + + userEvent.click(screen.getByTestId('editPostModalBtn')); + + // expect(screen.queryByTestId('editPostModalBtn')).toBeInTheDocument(); + // expect(screen.queryByTestId('deletePostModalBtn')).not.toBeInTheDocument(); + // expect(screen.queryByTestId('closeiconbtn')).not.toBeInTheDocument(); + + // expect(screen.getByTestId('editPostModal')).toHaveClass('show'); + // expect(screen.getByTestId('deletePostModal')).not.toHaveClass('show'); + + // expect(screen.getByTestId('modalVisible')).toBe('false'); + // expect(screen.getByTestId('menuVisible')).toBe('false'); + // expect(screen.getByTestId('showEditModal')).toBe('true'); + // expect(screen.getByTestId('showDeleteModal')).toBe('false'); + }); + test('clears postvideo state and resets file input value', async () => { + const { getByTestId } = render( + + + + + + ); + + userEvent.click(screen.getByAltText('image')); + userEvent.click(screen.getByTestId('moreiconbtn')); + + userEvent.click(screen.getByTestId('editPostModalBtn')); + userEvent.click(screen.getByTestId('closePreview')); + + fireEvent.change(getByTestId('postVideoUrl'), { + target: { value: '' }, + }); + userEvent.click(screen.getByPlaceholderText(/video/i)); + const input = getByTestId('postVideoUrl'); + const file = new File(['test-video'], 'test.mp4', { type: 'video/mp4' }); + Object.defineProperty(input, 'files', { + value: [file], + }); + fireEvent.change(input); + await waitFor(() => { + convertToBase64(file); + }); + }); + test('clears postimage state and resets file input value', async () => { + const { getByTestId } = render( + + + + + + ); + + userEvent.click(screen.getByAltText('image')); + userEvent.click(screen.getByTestId('moreiconbtn')); + + userEvent.click(screen.getByTestId('editPostModalBtn')); + userEvent.click(screen.getByTestId('closePreview')); + + fireEvent.change(getByTestId('postImageUrl'), { + target: { value: '' }, + }); + userEvent.click(screen.getByPlaceholderText(/image/i)); + const input = getByTestId('postImageUrl'); + const file = new File(['test-image'], 'test.jpg', { type: 'image/jpeg' }); + Object.defineProperty(input, 'files', { + value: [file], + }); + fireEvent.change(input); + + // Simulate the asynchronous base64 conversion function + await waitFor(() => { + convertToBase64(file); // Replace with the expected base64-encoded image + }); + document.getElementById = jest.fn(() => input); + const clearImageButton = getByTestId('closeimage'); + fireEvent.click(clearImageButton); + }); + test('Testing create organization modal', async () => { + localStorage.setItem('id', '123'); + + render( + + + + + + ); + + await wait(); + userEvent.click(screen.getByAltText('image')); + + userEvent.click(screen.getByTestId('moreiconbtn')); + + userEvent.click(screen.getByTestId('editPostModalBtn')); + const createOrgBtn = screen.getByTestId('modalOrganizationHeader'); + expect(createOrgBtn).toBeInTheDocument(); + userEvent.click(createOrgBtn); + userEvent.click(screen.getByTestId('closeOrganizationModal')); + }); + test('should toggle post pin when pin button is clicked', async () => { + const { getByTestId } = render( + + + + + + ); + userEvent.click(screen.getByAltText('image')); + + userEvent.click(screen.getByTestId('moreiconbtn')); + const pinButton = getByTestId('pinpostBtn'); + fireEvent.click(pinButton); + await waitFor(() => { + expect(MOCKS[2].request.variables).toEqual({ + id: '32', + }); + }); + }); +}); diff --git a/src/components/OrgPostCard/OrgPostCard.tsx b/src/components/OrgPostCard/OrgPostCard.tsx new file mode 100644 index 0000000000..5845ef90ba --- /dev/null +++ b/src/components/OrgPostCard/OrgPostCard.tsx @@ -0,0 +1,629 @@ +import type { ChangeEvent } from 'react'; +import React, { useEffect, useState, useRef } from 'react'; +import { useMutation } from '@apollo/client'; +import Button from 'react-bootstrap/Button'; +import Modal from 'react-bootstrap/Modal'; +import Card from 'react-bootstrap/Card'; +import { toast } from 'react-toastify'; +import MoreVertIcon from '@mui/icons-material/MoreVert'; +import CloseIcon from '@mui/icons-material/Close'; +import PushPinIcon from '@mui/icons-material/PushPin'; +import AboutImg from 'assets/images/defaultImg.png'; +import { + DELETE_POST_MUTATION, + UPDATE_POST_MUTATION, + TOGGLE_PINNED_POST, +} from 'GraphQl/Mutations/mutations'; +import { useTranslation } from 'react-i18next'; +import { errorHandler } from 'utils/errorHandler'; +import styles from './OrgPostCard.module.css'; +import { Form } from 'react-bootstrap'; +import convertToBase64 from 'utils/convertToBase64'; + +interface InterfaceOrgPostCardProps { + key: string; + id: string; + postTitle: string; + postInfo: string; + postAuthor: string; + postPhoto: string; + postVideo: string; + pinned: boolean; +} + +// eslint-disable-next-line @typescript-eslint/naming-convention +export default function OrgPostCard( + props: InterfaceOrgPostCardProps +): JSX.Element { + const [postformState, setPostFormState] = useState({ + posttitle: '', + postinfo: '', + postphoto: '', + postvideo: '', + pinned: false, + }); + + const [togglePost, setPostToggle] = useState('Read more'); + const [showEditModal, setShowEditModal] = useState(false); + const [showDeleteModal, setShowDeleteModal] = useState(false); + const [modalVisible, setModalVisible] = useState(false); + const [menuVisible, setMenuVisible] = useState(false); + const [playing, setPlaying] = useState(false); + const videoRef = useRef(null); + const [toggle] = useMutation(TOGGLE_PINNED_POST); + const togglePostPin = async (id: string, pinned: boolean): Promise => { + try { + const { data } = await toggle({ + variables: { + id, + }, + }); + if (data) { + setModalVisible(false); + setMenuVisible(false); + toast.success(`${pinned ? 'Post unpinned' : 'Post pinned'}`); + setTimeout(() => { + window.location.reload(); + }, 2000); + } + } catch (error: any) { + console.log(error); + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + const toggleShowEditModal = (): void => { + setPostFormState({ + posttitle: props.postTitle, + postinfo: props.postInfo, + postphoto: props.postPhoto, + postvideo: props.postVideo, + pinned: props.pinned, + }); + setShowEditModal((prev) => !prev); + }; + const toggleShowDeleteModal = (): void => setShowDeleteModal((prev) => !prev); + + const handleVideoPlay = (): void => { + setPlaying(true); + videoRef.current?.play(); + }; + + const handleVideoPause = (): void => { + setPlaying(false); + videoRef.current?.pause(); + }; + const handleCardClick = (): void => { + setModalVisible(true); + }; + + const handleMoreOptionsClick = (): void => { + setMenuVisible(true); + }; + const clearImageInput = (): void => { + setPostFormState({ + ...postformState, + postphoto: '', + }); + const fileInput = document.getElementById( + 'postImageUrl' + ) as HTMLInputElement; + if (fileInput) { + fileInput.value = ''; + } + }; + + const clearVideoInput = (): void => { + setPostFormState({ + ...postformState, + postvideo: '', + }); + const fileInput = document.getElementById( + 'postVideoUrl' + ) as HTMLInputElement; + if (fileInput) { + fileInput.value = ''; + } + }; + function handletoggleClick(): void { + if (togglePost === 'Read more') { + setPostToggle('hide'); + } else { + setPostToggle('Read more'); + } + } + + function handleEditModal(): void { + setModalVisible(false); + setMenuVisible(false); + setShowEditModal(true); + setPostFormState({ + ...postformState, + postphoto: props.postPhoto, + postvideo: props.postVideo, + }); + } + + function handleDeleteModal(): void { + setModalVisible(false); + setMenuVisible(false); + setShowDeleteModal(true); + } + + useEffect(() => { + setPostFormState({ + posttitle: props.postTitle, + postinfo: props.postInfo, + postphoto: props.postPhoto, + postvideo: props.postVideo, + pinned: props.pinned, + }); + }, []); + + const { t } = useTranslation('translation', { + keyPrefix: 'orgPostCard', + }); + + const [deletePostMutation] = useMutation(DELETE_POST_MUTATION); + const [updatePostMutation] = useMutation(UPDATE_POST_MUTATION); + + const deletePost = async (): Promise => { + try { + const { data } = await deletePostMutation({ + variables: { + id: props.id, + }, + }); + + if (data) { + toast.success(t('postDeleted')); + setTimeout(() => { + window.location.reload(); + }); + } + } catch (error: any) { + errorHandler(t, error); + } + }; + const handleInputEvent = ( + e: ChangeEvent + ): void => { + const { name, value } = e.target; + setPostFormState((prevPostFormState) => ({ + ...prevPostFormState, + [name]: value, + })); + }; + + const updatePostHandler = async ( + e: ChangeEvent + ): Promise => { + e.preventDefault(); + + try { + let imageUrl = null; + let videoUrl = null; + + if (e.target?.postphoto && e.target?.postphoto.files.length > 0) { + imageUrl = postformState.postphoto; + } + + if (e.target?.postvideo && e.target?.postvideo.files.length > 0) { + videoUrl = postformState.postvideo; + } + + const { data } = await updatePostMutation({ + variables: { + id: props.id, + title: postformState.posttitle, + text: postformState.postinfo, + imageUrl, + videoUrl, + }, + }); + + if (data) { + toast.success(t('postUpdated')); + setTimeout(() => { + window.location.reload(); + }, 2000); + } + } catch (error: any) { + toast.error(error.message); + } + }; + + return ( + <> +
    +
    + {props.postVideo && ( + + + + {props.pinned && ( + + )} + + {props.postTitle} + + + {props.postInfo} + + + {props.postAuthor} + + + + )} + {props.postPhoto ? ( + + + + {props.pinned && ( + + )} + + {props.postTitle} + + {props.postInfo} + {props.postAuthor} + + + ) : !props.postVideo ? ( + + + + + {props.pinned && ( + + )} + + {props.postTitle} + + + {props.postInfo && props.postInfo.length > 20 + ? props.postInfo.substring(0, 20) + '...' + : props.postInfo} + {' '} + + {props.postAuthor} + + + + + ) : ( + '' + )} +
    + {modalVisible && ( +
    +
    + {props.postPhoto && ( +
    + Post Image +
    + )} + {props.postVideo && ( +
    + +
    + )} + {!props.postPhoto && !props.postVideo && ( +
    + {' '} + Post Image +
    + )} + +
    +

    + {t('author')}: {props.postAuthor} +

    +
    + {togglePost === 'Read more' ? ( +

    + {props.postInfo.length > 43 + ? props.postInfo.substring(0, 40) + '...' + : props.postInfo} +

    + ) : ( +

    {props.postInfo}

    + )} + +
    +
    + + +
    +
    + )} + + {menuVisible && ( +
    +
    +
      +
    • + {t('edit')} +
    • +
    • + {t('deletePost')} +
    • +
    • => + togglePostPin(props.id, props.pinned) + } + > + {!props.pinned ? 'Pin post' : 'Unpin post'} +
    • +
    • setMenuVisible(false)} + data-testid="closebtn" + > + {t('close')} +
    • +
    +
    +
    + )} +
    + + {/* Delete Modal */} + + +
    {t('deletePost')}
    + +
    + {t('deletePostMsg')} + + + + +
    + + {/* Edit Modal */} + + + {t('editPost')} + +
    + + {t('postTitle')} + + {t('information')} + + {props.postPhoto && ( + <> + {t('image')} + + ): Promise => { + setPostFormState((prevPostFormState) => ({ + ...prevPostFormState, + postphoto: '', + })); + + const file = e.target.files?.[0]; + if (file) { + setPostFormState({ + ...postformState, + postphoto: await convertToBase64(file), + }); + } + }} + /> + {props.postPhoto && ( + <> + {postformState.postphoto && ( +
    + Post Image Preview + +
    + )} + + )} + + )} + {props.postVideo && ( + <> + {t('video')} + + ): Promise => { + setPostFormState((prevPostFormState) => ({ + ...prevPostFormState, + postvideo: '', + })); + const target = e.target as HTMLInputElement; + const file = target.files && target.files[0]; + if (file) { + const videoBase64 = await convertToBase64(file); + setPostFormState({ + ...postformState, + postvideo: videoBase64, + }); + } + }} + /> + {postformState.postvideo && ( +
    + + +
    + )} + + )} +
    + + + + +
    +
    + + ); +} diff --git a/src/components/OrgUpdate/OrgUpdate.module.css b/src/components/OrgUpdate/OrgUpdate.module.css new file mode 100644 index 0000000000..fca7ac5e5b --- /dev/null +++ b/src/components/OrgUpdate/OrgUpdate.module.css @@ -0,0 +1,13 @@ +.message { + height: 420px; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; +} + +.icon { + transform: scale(1.5); + color: var(--bs-danger); + margin-bottom: 1rem; +} diff --git a/src/components/OrgUpdate/OrgUpdate.test.tsx b/src/components/OrgUpdate/OrgUpdate.test.tsx new file mode 100644 index 0000000000..79b076c452 --- /dev/null +++ b/src/components/OrgUpdate/OrgUpdate.test.tsx @@ -0,0 +1,174 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { act, fireEvent, render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18nForTest from 'utils/i18nForTest'; +import OrgUpdate from './OrgUpdate'; +import { + MOCKS, + MOCKS_ERROR_ORGLIST, + MOCKS_ERROR_UPDATE_ORGLIST, +} from './OrgUpdateMocks'; + +const link = new StaticMockLink(MOCKS, true); + +async function wait(ms = 500): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Testing Organization Update', () => { + const props = { + orgId: '123', + }; + + const formData = { + name: 'Palisadoes Organization', + description: 'This is a updated description', + location: 'This is updated location', + displayImage: new File(['hello'], 'hello.png', { type: 'image/png' }), + isPublic: false, + isVisible: true, + }; + + global.alert = jest.fn(); + + test('should render props and text elements test for the page component along with mock data', async () => { + act(() => { + render( + + + + + + ); + }); + await wait(); + // Check labels are present or not + expect(screen.getByText('Name')).toBeInTheDocument(); + expect(screen.getByText('Description')).toBeInTheDocument(); + expect(screen.getByText('Location')).toBeInTheDocument(); + expect(screen.getByText('Display Image:')).toBeInTheDocument(); + expect(screen.getByText('Public:')).toBeInTheDocument(); + expect(screen.getByText('Visible in Search:')).toBeInTheDocument(); + + // Get the input fields, and btns + const name = screen.getByPlaceholderText(/Enter Organization Name/i); + const des = screen.getByPlaceholderText(/Description/i); + const location = screen.getByPlaceholderText(/Location/i); + const isPublic = screen.getByPlaceholderText(/Public/i); + const isVisible = screen.getByPlaceholderText(/Visible/i); + + // Checking if form fields got updated according to the mock data + expect(name).toHaveValue('Palisadoes'); + expect(des).toHaveValue('Equitable Access to STEM Education Jobs'); + expect(location).toHaveValue('Jamaica'); + expect(isPublic).toBeChecked(); + expect(isVisible).not.toBeChecked(); + }); + + test('Should Update organization properly', async () => { + await act(async () => { + render( + + + + + + ); + }); + + await wait(); + + // Get the input fields, and btns + const name = screen.getByPlaceholderText(/Enter Organization Name/i); + const des = screen.getByPlaceholderText(/Description/i); + const location = screen.getByPlaceholderText(/Location/i); + const displayImage = screen.getByPlaceholderText(/Display Image/i); + const isPublic = screen.getByPlaceholderText(/Public/i); + const isVisible = screen.getByPlaceholderText(/Visible/i); + const saveChangesBtn = screen.getByText(/Save Changes/i); + + // Emptying the text fields to add updated data + fireEvent.change(name, { target: { value: '' } }); + fireEvent.change(des, { target: { value: '' } }); + fireEvent.change(location, { target: { value: '' } }); + + // Mocking filling form behaviour + userEvent.type(name, formData.name); + userEvent.type(des, formData.description); + userEvent.type(location, formData.location); + userEvent.upload(displayImage, formData.displayImage); + userEvent.click(isPublic); + userEvent.click(isVisible); + + await wait(); + userEvent.click(saveChangesBtn); + + // Checking if the form got update accordingly + expect(name).toHaveValue(formData.name); + expect(des).toHaveValue(formData.description); + expect(location).toHaveValue(formData.location); + expect(displayImage).toBeTruthy(); + expect(isPublic).not.toBeChecked(); + expect(isVisible).toBeChecked(); + }); + + test('Should render error occured text when Organization Could not be found', async () => { + act(() => { + render( + + + + + + ); + }); + await wait(); + expect(screen.getByText(/Mock Graphql Error/i)).toBeInTheDocument(); + }); + + test('Should show error occured toast when Organization could not be updated', async () => { + await act(async () => { + render( + + + + + + ); + }); + + await wait(); + + // Get the input fields, and btns + const name = screen.getByPlaceholderText(/Enter Organization Name/i); + const des = screen.getByPlaceholderText(/Description/i); + const location = screen.getByPlaceholderText(/Location/i); + const displayImage = screen.getByPlaceholderText(/Display Image/i); + const isPublic = screen.getByPlaceholderText(/Public/i); + const isVisible = screen.getByPlaceholderText(/Visible/i); + const saveChangesBtn = screen.getByText(/Save Changes/i); + + // Emptying the text fields to add updated data + fireEvent.change(name, { target: { value: '' } }); + fireEvent.change(des, { target: { value: '' } }); + fireEvent.change(location, { target: { value: '' } }); + + // Mocking filling form behaviour + userEvent.type(name, formData.name); + userEvent.type(des, formData.description); + userEvent.type(location, formData.location); + userEvent.upload(displayImage, formData.displayImage); + userEvent.click(isPublic); + userEvent.click(isVisible); + + await wait(); + userEvent.click(saveChangesBtn); + }); +}); diff --git a/src/components/OrgUpdate/OrgUpdate.tsx b/src/components/OrgUpdate/OrgUpdate.tsx new file mode 100644 index 0000000000..16222717d6 --- /dev/null +++ b/src/components/OrgUpdate/OrgUpdate.tsx @@ -0,0 +1,220 @@ +import React, { useState, useEffect } from 'react'; +import { useMutation, useQuery } from '@apollo/client'; +import Button from 'react-bootstrap/Button'; +import { useTranslation } from 'react-i18next'; +import { toast } from 'react-toastify'; + +import type { ApolloError } from '@apollo/client'; +import { WarningAmberRounded } from '@mui/icons-material'; +import { UPDATE_ORGANIZATION_MUTATION } from 'GraphQl/Mutations/mutations'; +import { ORGANIZATIONS_LIST } from 'GraphQl/Queries/Queries'; +import Loader from 'components/Loader/Loader'; +import { Col, Form, Row } from 'react-bootstrap'; +import convertToBase64 from 'utils/convertToBase64'; +import { errorHandler } from 'utils/errorHandler'; +import type { InterfaceQueryOrganizationsListObject } from 'utils/interfaces'; +import styles from './OrgUpdate.module.css'; + +interface InterfaceOrgUpdateProps { + orgId: string; +} + +function orgUpdate(props: InterfaceOrgUpdateProps): JSX.Element { + const { orgId } = props; + + const [formState, setFormState] = useState<{ + orgName: string; + orgDescrip: string; + location: string; + orgImage: string | null; + }>({ + orgName: '', + orgDescrip: '', + location: '', + orgImage: null, + }); + + const [publicchecked, setPublicChecked] = React.useState(false); + const [visiblechecked, setVisibleChecked] = React.useState(false); + + const [login] = useMutation(UPDATE_ORGANIZATION_MUTATION); + + const { t } = useTranslation('translation', { + keyPrefix: 'orgUpdate', + }); + + const { + data, + loading, + refetch, + error, + }: { + data?: { + organizations: InterfaceQueryOrganizationsListObject[]; + }; + loading: boolean; + refetch: (variables: { id: string }) => void; + error?: ApolloError; + } = useQuery(ORGANIZATIONS_LIST, { + variables: { id: orgId }, + notifyOnNetworkStatusChange: true, + }); + + useEffect(() => { + let isMounted = true; + if (data && isMounted) { + setFormState({ + ...formState, + orgName: data.organizations[0].name, + orgDescrip: data.organizations[0].description, + location: data.organizations[0].location, + }); + setPublicChecked(data.organizations[0].isPublic); + setVisibleChecked(data.organizations[0].visibleInSearch); + } + return () => { + isMounted = false; + }; + }, [data, orgId]); + + const onSaveChangesClicked = async (): Promise => { + try { + const { data } = await login({ + variables: { + id: orgId, + name: formState.orgName, + description: formState.orgDescrip, + location: formState.location, + isPublic: publicchecked, + visibleInSearch: visiblechecked, + file: formState.orgImage, + }, + }); + // istanbul ignore next + if (data) { + refetch({ id: orgId }); + toast.success(t('successfulUpdated')); + } + } catch (error: any) { + errorHandler(t, error); + } + }; + + if (loading) { + return ; + } + + if (error) { + return ( +
    + +
    + Error occured while loading Organization Data +
    + {`${error.message}`} +
    +
    + ); + } + + return ( + <> +
    +
    + {t('name')} + { + setFormState({ + ...formState, + orgName: e.target.value, + }); + }} + /> + {t('description')} + { + setFormState({ + ...formState, + orgDescrip: e.target.value, + }); + }} + /> + {t('location')} + { + setFormState({ + ...formState, + location: e.target.value, + }); + }} + /> + + + {t('isPublic')}: + setPublicChecked(!publicchecked)} + /> + + + + {t('isVisibleInSearch')}: + + setVisibleChecked(!visiblechecked)} + /> + + + {t('displayImage')}: + => { + const target = e.target as HTMLInputElement; + const file = target.files && target.files[0]; + /* istanbul ignore else */ + if (file) + setFormState({ + ...formState, + orgImage: await convertToBase64(file), + }); + }} + data-testid="organisationImage" + /> +
    + +
    + +
    + + ); +} +export default orgUpdate; diff --git a/src/components/OrgUpdate/OrgUpdateMocks.ts b/src/components/OrgUpdate/OrgUpdateMocks.ts new file mode 100644 index 0000000000..cd78d37fd0 --- /dev/null +++ b/src/components/OrgUpdate/OrgUpdateMocks.ts @@ -0,0 +1,157 @@ +import { UPDATE_ORGANIZATION_MUTATION } from 'GraphQl/Mutations/mutations'; +import { ORGANIZATIONS_LIST } from 'GraphQl/Queries/Queries'; + +export const MOCKS = [ + { + request: { + query: ORGANIZATIONS_LIST, + variables: { id: '123' }, + }, + result: { + data: { + organizations: [ + { + _id: '123', + image: null, + name: 'Palisadoes', + description: 'Equitable Access to STEM Education Jobs', + location: 'Jamaica', + isPublic: true, + visibleInSearch: false, + creator: { + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@example.com', + }, + members: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@gmail.com', + }, + admins: [ + { + _id: '123', + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@gmail.com', + }, + ], + membershipRequests: { + _id: '456', + user: { + firstName: 'Sam', + lastName: 'Smith', + email: 'samsmith@gmail.com', + }, + }, + blockedUsers: [], + }, + ], + }, + }, + }, + { + request: { + query: UPDATE_ORGANIZATION_MUTATION, + variables: { + id: '123', + name: 'Updated Organization', + description: 'This is an updated test organization', + location: 'Updated location', + image: new File(['hello'], 'hello.png', { type: 'image/png' }), + isPublic: true, + visibleInSearch: false, + }, + }, + result: { + data: { + updateOrganization: { + _id: '123', + name: 'Updated Organization', + description: 'This is an updated test organization', + location: 'Updated location', + isPublic: true, + visibleInSearch: false, + }, + }, + }, + }, +]; + +export const MOCKS_ERROR_ORGLIST = [ + { + request: { + query: ORGANIZATIONS_LIST, + variables: { id: '123' }, + }, + error: new Error('Mock Graphql Error'), + }, +]; + +export const MOCKS_ERROR_UPDATE_ORGLIST = [ + { + request: { + query: ORGANIZATIONS_LIST, + variables: { id: '123' }, + }, + result: { + data: { + organizations: [ + { + _id: '123', + image: null, + name: 'Palisadoes', + description: 'Equitable Access to STEM Education Jobs', + location: 'Jamaica', + isPublic: true, + visibleInSearch: false, + creator: { + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@example.com', + }, + members: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@gmail.com', + }, + admins: [ + { + _id: '123', + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@gmail.com', + }, + ], + membershipRequests: { + _id: '456', + user: { + firstName: 'Sam', + lastName: 'Smith', + email: 'samsmith@gmail.com', + }, + }, + blockedUsers: [], + }, + ], + }, + }, + }, + { + request: { + query: UPDATE_ORGANIZATION_MUTATION, + variables: { + id: '123', + name: 'Updated Organization', + description: 'This is an updated test organization', + location: 'Updated location', + image: new File(['hello'], 'hello.png', { type: 'image/png' }), + isPublic: true, + visibleInSearch: false, + }, + }, + erorr: new Error('Mock Graphql Updating Organization Error'), + }, +]; diff --git a/src/components/OrganizationCard/OrganizationCard.module.css b/src/components/OrganizationCard/OrganizationCard.module.css new file mode 100644 index 0000000000..6c65b8258b --- /dev/null +++ b/src/components/OrganizationCard/OrganizationCard.module.css @@ -0,0 +1,46 @@ +.alignimg { + border-radius: 50%; + background-blend-mode: darken; + height: 65px; + width: 65px; +} + +.box { + color: #ffbd59; +} + +.box :hover { + color: #ffbd59; +} + +.first_box { + display: flex; + flex-direction: row; + padding-bottom: 10px; + padding-top: 10px; +} + +.second_box { + padding-left: 20px; + padding-top: 10px; +} + +.second_box > h4 { + font-size: 10; + font-weight: bold; + text-decoration: none; + color: black; +} + +.second_box > h5 { + text-decoration: none; + font-size: 10; + font-weight: 100; + color: #969696; +} + +.deco { + border: 1px solid #dfdfdf; + width: 65vw; + height: 0px !important; +} diff --git a/src/components/OrganizationCard/OrganizationCard.test.tsx b/src/components/OrganizationCard/OrganizationCard.test.tsx new file mode 100644 index 0000000000..e0095d20b2 --- /dev/null +++ b/src/components/OrganizationCard/OrganizationCard.test.tsx @@ -0,0 +1,41 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import OrganizationCard from './OrganizationCard'; + +describe('Testing the Organization Card', () => { + test('should render props and text elements test for the page component', () => { + const props = { + id: '123', + key: '456', + image: 'https://via.placeholder.com/80', + firstName: 'John', + lastName: 'Doe', + name: 'Sample', + }; + + render(); + + expect(screen.getByText(props.name)).toBeInTheDocument(); + expect(screen.getByText(/Owner:/i)).toBeInTheDocument(); + expect(screen.getByText(props.firstName)).toBeInTheDocument(); + expect(screen.getByText(props.lastName)).toBeInTheDocument(); + }); + + test('Should render text elements when props value is not passed', () => { + const props = { + id: '123', + key: '456', + image: '', + firstName: 'John', + lastName: 'Doe', + name: 'Sample', + }; + + render(); + + expect(screen.getByText(props.name)).toBeInTheDocument(); + expect(screen.getByText(/Owner:/i)).toBeInTheDocument(); + expect(screen.getByText(props.firstName)).toBeInTheDocument(); + expect(screen.getByText(props.lastName)).toBeInTheDocument(); + }); +}); diff --git a/src/components/OrganizationCard/OrganizationCard.tsx b/src/components/OrganizationCard/OrganizationCard.tsx new file mode 100644 index 0000000000..ba90f3f83f --- /dev/null +++ b/src/components/OrganizationCard/OrganizationCard.tsx @@ -0,0 +1,49 @@ +import React from 'react'; +import styles from './OrganizationCard.module.css'; + +interface InterfaceOrganizationCardProps { + key: any; + image: string; + id: string; + name: string; + lastName: string; + firstName: string; +} + +function organizationCard(props: InterfaceOrganizationCardProps): JSX.Element { + const uri = '/superorghome/i=' + props.id; + + return ( + <> +
    +
    +
    + {props.image ? ( + + ) : ( + + )} +
    +

    {props.name}

    +
    + Owner: + {props.firstName} + +   + {props.lastName} + +
    +
    +
    +
    +
    +
    + + ); +} + +export {}; +export default organizationCard; diff --git a/src/components/OrganizationCardStart/OrganizationCardStart.module.css b/src/components/OrganizationCardStart/OrganizationCardStart.module.css new file mode 100644 index 0000000000..6c65b8258b --- /dev/null +++ b/src/components/OrganizationCardStart/OrganizationCardStart.module.css @@ -0,0 +1,46 @@ +.alignimg { + border-radius: 50%; + background-blend-mode: darken; + height: 65px; + width: 65px; +} + +.box { + color: #ffbd59; +} + +.box :hover { + color: #ffbd59; +} + +.first_box { + display: flex; + flex-direction: row; + padding-bottom: 10px; + padding-top: 10px; +} + +.second_box { + padding-left: 20px; + padding-top: 10px; +} + +.second_box > h4 { + font-size: 10; + font-weight: bold; + text-decoration: none; + color: black; +} + +.second_box > h5 { + text-decoration: none; + font-size: 10; + font-weight: 100; + color: #969696; +} + +.deco { + border: 1px solid #dfdfdf; + width: 65vw; + height: 0px !important; +} diff --git a/src/components/OrganizationCardStart/OrganizationCardStart.test.tsx b/src/components/OrganizationCardStart/OrganizationCardStart.test.tsx new file mode 100644 index 0000000000..2a9f03a9be --- /dev/null +++ b/src/components/OrganizationCardStart/OrganizationCardStart.test.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import OrganizationCardStart from './OrganizationCardStart'; + +describe('Testing the Organization Cards', () => { + test('should render props and text elements test for the page component', () => { + const props = { + id: '123', + key: '456', + image: 'https://via.placeholder.com/80', + name: 'Sample', + }; + + render(); + + expect(screen.getByText(props.name)).toBeInTheDocument(); + }); + + test('Should render text elements when props value is not passed', () => { + const props = { + id: '123', + key: '456', + image: '', + name: 'Sample', + }; + + render(); + + expect(screen.getByText(props.name)).toBeInTheDocument(); + }); +}); diff --git a/src/components/OrganizationCardStart/OrganizationCardStart.tsx b/src/components/OrganizationCardStart/OrganizationCardStart.tsx new file mode 100644 index 0000000000..37c7b65686 --- /dev/null +++ b/src/components/OrganizationCardStart/OrganizationCardStart.tsx @@ -0,0 +1,41 @@ +import React from 'react'; +import styles from './OrganizationCardStart.module.css'; + +interface InterfaceOrganizationCardStartProps { + key: any; + image: string; + id: string; + name: string; +} + +function organizationCardStart( + props: InterfaceOrganizationCardStartProps +): JSX.Element { + const uri = '/orghome/i=' + props.id; + + return ( + <> + +
    +
    + {props.image ? ( + + ) : ( + + )} +
    +

    {props.name}

    +
    +
    +
    +
    +
    +
    + + ); +} + +export default organizationCardStart; diff --git a/src/components/OrganizationDashCards/CardItem.module.css b/src/components/OrganizationDashCards/CardItem.module.css new file mode 100644 index 0000000000..0330411b0c --- /dev/null +++ b/src/components/OrganizationDashCards/CardItem.module.css @@ -0,0 +1,60 @@ +.cardItem { + position: relative; + display: flex; + align-items: center; + padding: 0.75rem 0; +} + +.cardItem .iconWrapper { + position: relative; + height: 40px; + width: 40px; + display: flex; + justify-content: center; + align-items: center; +} + +.cardItem .iconWrapper .themeOverlay { + background: var(--bs-primary); + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + opacity: 0.12; + border-radius: 50%; +} + +.cardItem .iconWrapper .dangerOverlay { + background: var(--bs-danger); + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + opacity: 0.12; + border-radius: 50%; +} + +.cardItem .title { + font-size: 1rem; + flex: 1; +} + +.cardItem .time { + font-size: 0.9rem; + color: var(--bs-secondary); +} + +.cardItem .creator { + font-size: 1rem; + color: rgb(33, 208, 21); +} + +.rightCard { + display: flex; + gap: 5px; + min-width: 170px; + justify-content: center; + flex-direction: column; +} diff --git a/src/components/OrganizationDashCards/CardItem.test.tsx b/src/components/OrganizationDashCards/CardItem.test.tsx new file mode 100644 index 0000000000..2102e86f94 --- /dev/null +++ b/src/components/OrganizationDashCards/CardItem.test.tsx @@ -0,0 +1,47 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import CardItem from './CardItem'; +import type { InterfaceCardItem } from './CardItem'; +import dayjs from 'dayjs'; + +describe('Testing the Organization Card', () => { + test('should render props and text elements For event card', () => { + const props: InterfaceCardItem = { + type: 'Event', + title: 'Event Title', + time: '2023-09-03', + }; + + render(); + + expect(screen.getByText(/Event Title/i)).toBeInTheDocument(); + expect( + screen.getByText(dayjs(props.time).format('MMM D, YYYY')) + ).toBeInTheDocument(); + }); + + test('Should render props and text elements for Post card', () => { + const props: InterfaceCardItem = { + type: 'Post', + title: 'Post Title', + time: '2023-09-03', + }; + + render(); + + expect(screen.getByText(/Post Title/i)).toBeInTheDocument(); + expect( + screen.getByText(dayjs(props.time).format('MMM D, YYYY')) + ).toBeInTheDocument(); + }); + + test('Should render props and text elements for Membership Request card', () => { + const props: InterfaceCardItem = { + type: 'MembershipRequest', + title: 'Membership Request Title', + }; + + render(); + expect(screen.getByText(/Membership Request Title/i)).toBeInTheDocument(); + }); +}); diff --git a/src/components/OrganizationDashCards/CardItem.tsx b/src/components/OrganizationDashCards/CardItem.tsx new file mode 100644 index 0000000000..bcaaea68c5 --- /dev/null +++ b/src/components/OrganizationDashCards/CardItem.tsx @@ -0,0 +1,88 @@ +import React from 'react'; +import { ReactComponent as EventsIcon } from 'assets/svgs/events.svg'; +import { ReactComponent as PostsIcon } from 'assets/svgs/post.svg'; +import { ReactComponent as MarkerIcon } from 'assets/svgs/location.svg'; +import { ReactComponent as DateIcon } from 'assets/svgs/date.svg'; +import { ReactComponent as UserIcon } from 'assets/svgs/user.svg'; +import dayjs from 'dayjs'; +import styles from './CardItem.module.css'; +import { PersonAddAlt1Rounded } from '@mui/icons-material'; + +export interface InterfaceCardItem { + type: 'Event' | 'Post' | 'MembershipRequest'; + title: string; + time?: string; + creator?: any; + location?: string; +} + +const cardItem = (props: InterfaceCardItem): JSX.Element => { + const { creator, type, title, time, location } = props; + return ( + <> +
    +
    +
    + {type == 'Event' ? ( + + ) : type == 'Post' ? ( + + ) : ( + type == 'MembershipRequest' && ( + + ) + )} +
    + {`${title}`} + +
    + {creator && ( + + {' '} + {' '} + + {creator.firstName} {creator.lastName} + + + )} + + {location && ( + + {' '} + {location} + + )} + {time && ( + + {type === 'Event' && ( + + )}{' '} + {dayjs(time).format('MMM D, YYYY')} + + )} +
    +
    + + ); +}; + +export default cardItem; diff --git a/src/components/OrganizationDashCards/CardItemLoading.tsx b/src/components/OrganizationDashCards/CardItemLoading.tsx new file mode 100644 index 0000000000..923128c2f2 --- /dev/null +++ b/src/components/OrganizationDashCards/CardItemLoading.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import styles from './CardItem.module.css'; + +const cardItemLoading = (): JSX.Element => { + return ( + <> +
    +
    +
    +
    + +   + +
    + + ); +}; + +export default cardItemLoading; diff --git a/src/components/OrganizationDashCards/DashboardCard.test.tsx b/src/components/OrganizationDashCards/DashboardCard.test.tsx new file mode 100644 index 0000000000..71e5e1fed0 --- /dev/null +++ b/src/components/OrganizationDashCards/DashboardCard.test.tsx @@ -0,0 +1,18 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import DashboardCard from './DashboardCard'; + +describe('Testing the Dashboard Card', () => { + test('should render props and text elements For event card', () => { + const props = { + icon: , + title: 'Example Title', + count: 100, + }; + + render(); + + expect(screen.getByText(/Example Title/i)).toBeInTheDocument(); + expect(screen.getByText(/100/i)).toBeInTheDocument(); + }); +}); diff --git a/src/components/OrganizationDashCards/DashboardCard.tsx b/src/components/OrganizationDashCards/DashboardCard.tsx new file mode 100644 index 0000000000..4ad8fe8849 --- /dev/null +++ b/src/components/OrganizationDashCards/DashboardCard.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import { Card, Row } from 'react-bootstrap'; +import Col from 'react-bootstrap/Col'; +import styles from './Dashboardcard.module.css'; + +const dashBoardCard = (props: { + icon: React.ReactNode; + title: string; + count?: number; +}): JSX.Element => { + const { icon, count, title } = props; + return ( + + + + +
    +
    + {icon} +
    + + + {count ?? 0} + {title} + + + + + ); +}; + +export default dashBoardCard; diff --git a/src/components/OrganizationDashCards/DashboardCardLoading.tsx b/src/components/OrganizationDashCards/DashboardCardLoading.tsx new file mode 100644 index 0000000000..5b596f32b2 --- /dev/null +++ b/src/components/OrganizationDashCards/DashboardCardLoading.tsx @@ -0,0 +1,36 @@ +import React from 'react'; +import { Card, Row } from 'react-bootstrap'; +import Col from 'react-bootstrap/Col'; +import styles from './Dashboardcard.module.css'; + +const dashBoardCardLoading = (): JSX.Element => { + return ( + + + + +
    +
    +
    + + + + + + + + + ); +}; + +export default dashBoardCardLoading; diff --git a/src/components/OrganizationDashCards/Dashboardcard.module.css b/src/components/OrganizationDashCards/Dashboardcard.module.css new file mode 100644 index 0000000000..365657fb4f --- /dev/null +++ b/src/components/OrganizationDashCards/Dashboardcard.module.css @@ -0,0 +1,60 @@ +.cardBody { + padding: 1.25rem 1.5rem; +} + +.cardBody .iconWrapper { + position: relative; + height: 48px; + width: 48px; + display: flex; + justify-content: center; + align-items: center; +} + +.cardBody .iconWrapper .themeOverlay { + background: var(--bs-primary); + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + opacity: 0.12; + border-radius: 50%; +} + +.cardBody .textWrapper .primaryText { + font-size: 24px; + font-weight: bold; + display: block; +} + +.cardBody .textWrapper .secondaryText { + font-size: 14px; + display: block; + color: var(--bs-secondary); +} + +@media (max-width: 600px) { + .cardBody { + min-height: 120px; + } + + .cardBody .iconWrapper { + position: absolute; + top: 1rem; + left: 1rem; + } + + .cardBody .textWrapper { + margin-top: calc(0.5rem + 36px); + text-align: right; + } + + .cardBody .textWrapper .primaryText { + font-size: 1.5rem; + } + + .cardBody .textWrapper .secondaryText { + font-size: 1rem; + } +} diff --git a/src/components/OrganizationScreen/OrganizationScreen.module.css b/src/components/OrganizationScreen/OrganizationScreen.module.css new file mode 100644 index 0000000000..681ac8823d --- /dev/null +++ b/src/components/OrganizationScreen/OrganizationScreen.module.css @@ -0,0 +1,60 @@ +.pageContainer { + display: flex; + flex-direction: column; + min-height: 100vh; + padding: 1rem 1.5rem 0 calc(300px + 2rem + 1.5rem); +} + +.expand { + padding-left: 1.5rem; + animation: moveLeft 0.5s ease-in-out; +} + +.contract { + padding-left: calc(300px + 2rem + 1.5rem); + animation: moveRight 0.5s ease-in-out; +} + +@media (max-width: 1120px) { + .contract { + padding-left: calc(250px + 2rem + 1.5rem); + } +} + +/* For tablets */ +@media (max-width: 820px) { + .pageContainer { + padding-left: 1.5rem; + } + + .contract, + .expand { + animation: none; + } +} + +@media (max-width: 820px) { + .pageContainer { + padding: 1rem; + } +} + +@keyframes moveLeft { + from { + padding-left: calc(300px + 2rem + 1.5rem); + } + + to { + padding-left: 1.5rem; + } +} + +@keyframes moveRight { + from { + padding-left: 1.5rem; + } + + to { + padding-left: calc(300px + 2rem + 1.5rem); + } +} diff --git a/src/components/OrganizationScreen/OrganizationScreen.test.tsx b/src/components/OrganizationScreen/OrganizationScreen.test.tsx new file mode 100644 index 0000000000..8df2640990 --- /dev/null +++ b/src/components/OrganizationScreen/OrganizationScreen.test.tsx @@ -0,0 +1,39 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import type { InterfaceOrganizationScreenProps } from './OrganizationScreen'; +import OrganizationScreen from './OrganizationScreen'; + +const props: InterfaceOrganizationScreenProps = { + title: 'Dashboard', + screenName: 'Dashboard', + children:
    Testing ...
    , +}; + +describe('Testing LeftDrawer in OrganizationScreen', () => { + test('Testing LeftDrawer in page functionality', async () => { + localStorage.setItem('UserType', 'SUPERADMIN'); + + render( + + + + + + + + + + ); + // sets hideDrawer to true + userEvent.click(screen.getByTestId('menuBtn')); + // sets hideDrawer to false + userEvent.click(screen.getByTestId('menuBtn')); + }); +}); diff --git a/src/components/OrganizationScreen/OrganizationScreen.tsx b/src/components/OrganizationScreen/OrganizationScreen.tsx new file mode 100644 index 0000000000..de82dc7eec --- /dev/null +++ b/src/components/OrganizationScreen/OrganizationScreen.tsx @@ -0,0 +1,66 @@ +import MenuIcon from '@mui/icons-material/Menu'; +import LeftDrawerOrg from 'components/LeftDrawerOrg/LeftDrawerOrg'; +import React, { useState } from 'react'; +import Button from 'react-bootstrap/Button'; +import styles from './OrganizationScreen.module.css'; +import { useSelector } from 'react-redux'; +import type { TargetsType } from 'state/reducers/routesReducer'; +import type { RootState } from 'state/reducers'; + +export interface InterfaceOrganizationScreenProps { + title: string; // Multilingual Page title + screenName: string; // Internal Screen name for developers + children: React.ReactNode; +} +const organizationScreen = ({ + title, + screenName, + children, +}: InterfaceOrganizationScreenProps): JSX.Element => { + const [hideDrawer, setHideDrawer] = useState(null); + + const appRoutes: { + targets: TargetsType[]; + configUrl: string; + } = useSelector((state: RootState) => state.appRoutes); + const { targets, configUrl } = appRoutes; + return ( + <> + +
    +
    +
    +

    {title}

    +
    + +
    + {children} +
    + + ); +}; + +export default organizationScreen; diff --git a/src/components/Pagination/Pagination.test.tsx b/src/components/Pagination/Pagination.test.tsx new file mode 100644 index 0000000000..88bb3752c5 --- /dev/null +++ b/src/components/Pagination/Pagination.test.tsx @@ -0,0 +1,62 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { createTheme } from '@mui/material/styles'; +import Pagination from './Pagination'; +import { store } from 'state/store'; +import userEvent from '@testing-library/user-event'; +import { ThemeProvider } from '@mui/material/styles'; + +describe('Testing Pagination component', () => { + const props = { + count: 5, + page: 10, + rowsPerPage: 5, + onPageChange: (): number => { + return 10; + }, + }; + + test('Component should be rendered properly on rtl', () => { + render( + + + + + + ); + + userEvent.click(screen.getByTestId(/nextPage/i)); + userEvent.click(screen.getByTestId(/previousPage/i)); + }); +}); + +const props = { + count: 5, + page: 10, + rowsPerPage: 5, + onPageChange: (): number => { + return 10; + }, + theme: { direction: 'rtl' }, +}; + +test('Component should be rendered properly', () => { + const theme = createTheme({ + direction: 'rtl', + }); + + render( + + + + + + + + ); + + userEvent.click(screen.getByTestId(/nextPage/i)); + userEvent.click(screen.getByTestId(/previousPage/i)); +}); diff --git a/src/components/Pagination/Pagination.tsx b/src/components/Pagination/Pagination.tsx new file mode 100644 index 0000000000..1a4b1d5921 --- /dev/null +++ b/src/components/Pagination/Pagination.tsx @@ -0,0 +1,97 @@ +import React from 'react'; +import { useTheme } from '@mui/material/styles'; +import Box from '@mui/material/Box'; +import IconButton from '@mui/material/IconButton'; +import FirstPageIcon from '@mui/icons-material/FirstPage'; +import KeyboardArrowLeft from '@mui/icons-material/KeyboardArrowLeft'; +import KeyboardArrowRight from '@mui/icons-material/KeyboardArrowRight'; +import LastPageIcon from '@mui/icons-material/LastPage'; + +interface InterfaceTablePaginationActionsProps { + count: number; + page: number; + rowsPerPage: number; + onPageChange: ( + event: React.MouseEvent, + newPage: number + ) => void; +} + +function pagination(props: InterfaceTablePaginationActionsProps): JSX.Element { + const theme = useTheme(); + const { count, page, rowsPerPage, onPageChange } = props; + + /* istanbul ignore next */ + const handleFirstPageButtonClick = ( + event: React.MouseEvent + ): void => { + onPageChange(event, 0); + }; + + const handleBackButtonClick = ( + event: React.MouseEvent + ): void => { + onPageChange(event, page - 1); + }; + + /* istanbul ignore next */ + const handleNextButtonClick = ( + event: React.MouseEvent + ): void => { + onPageChange(event, page + 1); + }; + + /* istanbul ignore next */ + const handleLastPageButtonClick = ( + event: React.MouseEvent + ): void => { + onPageChange(event, Math.max(0, Math.ceil(count / rowsPerPage) - 1)); + }; + + return ( + + + {theme.direction === 'rtl' ? : } + + + {theme.direction === 'rtl' ? ( + + ) : ( + + )} + + = Math.ceil(count / rowsPerPage) - 1} + aria-label="next page" + data-testid="nextPage" + > + {theme.direction === 'rtl' ? ( + + ) : ( + + )} + + = Math.ceil(count / rowsPerPage) - 1} + aria-label="last page" + data-testid="lastPage" + > + {theme.direction === 'rtl' ? : } + + + ); +} + +export default pagination; diff --git a/src/components/PaginationList/PaginationList.css b/src/components/PaginationList/PaginationList.css new file mode 100644 index 0000000000..2354c9a5f9 --- /dev/null +++ b/src/components/PaginationList/PaginationList.css @@ -0,0 +1,7 @@ +.MuiTablePagination-selectLabel { + margin-top: 1rem; +} + +.MuiTablePagination-displayedRows { + margin-top: 1rem; +} diff --git a/src/components/PaginationList/PaginationList.tsx b/src/components/PaginationList/PaginationList.tsx new file mode 100644 index 0000000000..562f5204bb --- /dev/null +++ b/src/components/PaginationList/PaginationList.tsx @@ -0,0 +1,81 @@ +import React from 'react'; +import { Hidden, TablePagination } from '@mui/material'; +import { useTranslation } from 'react-i18next'; + +import Pagination from '../Pagination/Pagination'; +import './PaginationList.css'; + +interface InterfacePropsInterface { + count: number; + rowsPerPage: number; + page: number; + onPageChange: ( + event: React.MouseEvent | null, + newPage: number + ) => void; + onRowsPerPageChange: ( + event: React.ChangeEvent + ) => void; +} + +const PaginationList = (props: InterfacePropsInterface): JSX.Element => { + const { t } = useTranslation('translation', { + keyPrefix: 'paginationList', + }); + + return ( + <> + + + + + + + + ); +}; + +export default PaginationList; diff --git a/src/components/SecuredRoute/SecuredRoute.tsx b/src/components/SecuredRoute/SecuredRoute.tsx new file mode 100644 index 0000000000..ebed98518a --- /dev/null +++ b/src/components/SecuredRoute/SecuredRoute.tsx @@ -0,0 +1,39 @@ +import React from 'react'; +import { Redirect, Route } from 'react-router-dom'; +import { toast } from 'react-toastify'; + +const SecuredRoute = (props: any): JSX.Element => { + const isLoggedIn = localStorage.getItem('IsLoggedIn'); + return isLoggedIn === 'TRUE' ? ( + <> + + + ) : ( + + ); +}; + +const timeoutMinutes = 15; +const timeoutMilliseconds = timeoutMinutes * 60 * 1000; + +const inactiveIntervalMin = 1; +const inactiveIntervalMilsec = inactiveIntervalMin * 60 * 1000; +let lastActive: number = Date.now(); + +document.addEventListener('mousemove', () => { + lastActive = Date.now(); +}); + +setInterval(() => { + const currentTime = Date.now(); + const timeSinceLastActive = currentTime - lastActive; + + if (timeSinceLastActive > timeoutMilliseconds) { + toast.warn('Kindly relogin as sessison has expired'); + + window.location.href = '/'; + localStorage.setItem('IsLoggedIn', 'FALSE'); + } +}, inactiveIntervalMilsec); + +export default SecuredRoute; diff --git a/src/components/SuperAdminScreen/SuperAdminScreen.module.css b/src/components/SuperAdminScreen/SuperAdminScreen.module.css new file mode 100644 index 0000000000..681ac8823d --- /dev/null +++ b/src/components/SuperAdminScreen/SuperAdminScreen.module.css @@ -0,0 +1,60 @@ +.pageContainer { + display: flex; + flex-direction: column; + min-height: 100vh; + padding: 1rem 1.5rem 0 calc(300px + 2rem + 1.5rem); +} + +.expand { + padding-left: 1.5rem; + animation: moveLeft 0.5s ease-in-out; +} + +.contract { + padding-left: calc(300px + 2rem + 1.5rem); + animation: moveRight 0.5s ease-in-out; +} + +@media (max-width: 1120px) { + .contract { + padding-left: calc(250px + 2rem + 1.5rem); + } +} + +/* For tablets */ +@media (max-width: 820px) { + .pageContainer { + padding-left: 1.5rem; + } + + .contract, + .expand { + animation: none; + } +} + +@media (max-width: 820px) { + .pageContainer { + padding: 1rem; + } +} + +@keyframes moveLeft { + from { + padding-left: calc(300px + 2rem + 1.5rem); + } + + to { + padding-left: 1.5rem; + } +} + +@keyframes moveRight { + from { + padding-left: 1.5rem; + } + + to { + padding-left: calc(300px + 2rem + 1.5rem); + } +} diff --git a/src/components/SuperAdminScreen/SuperAdminScreen.test.tsx b/src/components/SuperAdminScreen/SuperAdminScreen.test.tsx new file mode 100644 index 0000000000..e578b0bb4f --- /dev/null +++ b/src/components/SuperAdminScreen/SuperAdminScreen.test.tsx @@ -0,0 +1,42 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import 'jest-localstorage-mock'; +import 'jest-location-mock'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import type { InterfaceSuperAdminScreenProps } from './SuperAdminScreen'; +import SuperAdminScreen from './SuperAdminScreen'; + +const props: InterfaceSuperAdminScreenProps = { + title: 'Organizations', + screenName: 'Organizations', + children:
    Testing ...
    , +}; + +describe('Testing LeftDrawer in SuperAdminScreen', () => { + test('Testing LeftDrawer in page functionality', async () => { + localStorage.setItem('UserType', 'SUPERADMIN'); + + render( + + + + + + + + + + ); + + // Expand LeftDrawer + userEvent.click(screen.getByTestId('menuBtn')); + // Contract LeftDrawer + userEvent.click(screen.getByTestId('menuBtn')); + }); +}); diff --git a/src/components/SuperAdminScreen/SuperAdminScreen.tsx b/src/components/SuperAdminScreen/SuperAdminScreen.tsx new file mode 100644 index 0000000000..214b8bd1ed --- /dev/null +++ b/src/components/SuperAdminScreen/SuperAdminScreen.tsx @@ -0,0 +1,56 @@ +import MenuIcon from '@mui/icons-material/Menu'; +import LeftDrawer from 'components/LeftDrawer/LeftDrawer'; +import React, { useState } from 'react'; +import Button from 'react-bootstrap/Button'; +import styles from './SuperAdminScreen.module.css'; + +export interface InterfaceSuperAdminScreenProps { + title: string; // Multilingual Page title + screenName: string; // Internal Screen name for developers + children: React.ReactNode; +} +const superAdminScreen = ({ + title, + screenName, + children, +}: InterfaceSuperAdminScreenProps): JSX.Element => { + const [hideDrawer, setHideDrawer] = useState(null); + + return ( + <> + +
    +
    +
    +

    {title}

    +
    + +
    + {children} +
    + + ); +}; + +export default superAdminScreen; diff --git a/src/components/TableLoader/TableLoader.module.css b/src/components/TableLoader/TableLoader.module.css new file mode 100644 index 0000000000..66349e2aa9 --- /dev/null +++ b/src/components/TableLoader/TableLoader.module.css @@ -0,0 +1,3 @@ +.loadingItem { + height: 30px; +} diff --git a/src/components/TableLoader/TableLoader.test.tsx b/src/components/TableLoader/TableLoader.test.tsx new file mode 100644 index 0000000000..b6526a65c7 --- /dev/null +++ b/src/components/TableLoader/TableLoader.test.tsx @@ -0,0 +1,78 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import { BrowserRouter } from 'react-router-dom'; + +import type { InterfaceTableLoader } from './TableLoader'; +import TableLoader from './TableLoader'; + +beforeAll(() => { + console.error = jest.fn(); +}); + +describe('Testing Loader component', () => { + test('Component should be rendered properly only headerTitles is provided', () => { + const props: InterfaceTableLoader = { + noOfRows: 10, + headerTitles: ['header1', 'header2', 'header3'], + }; + render( + + + + ); + // Check if header titles are rendered properly + const data = props.headerTitles as string[]; + data.forEach((title) => { + expect(screen.getByText(title)).toBeInTheDocument(); + }); + + // Check if elements are rendered properly + for (let rowIndex = 0; rowIndex < props.noOfRows; rowIndex++) { + expect( + screen.getByTestId(`row-${rowIndex}-tableLoading`) + ).toBeInTheDocument(); + for (let colIndex = 0; colIndex < data.length; colIndex++) { + expect( + screen.getByTestId(`row-${rowIndex}-col-${colIndex}-tableLoading`) + ).toBeInTheDocument(); + } + } + }); + test('Component should be rendered properly only noCols is provided', () => { + const props: InterfaceTableLoader = { + noOfRows: 10, + noOfCols: 3, + }; + render( + + + + ); + // Check if header titles are rendered properly + const data = [...Array(props.noOfCols)]; + + // Check if elements are rendered properly + for (let rowIndex = 0; rowIndex < props.noOfRows; rowIndex++) { + expect( + screen.getByTestId(`row-${rowIndex}-tableLoading`) + ).toBeInTheDocument(); + for (let colIndex = 0; colIndex < data.length; colIndex++) { + expect( + screen.getByTestId(`row-${rowIndex}-col-${colIndex}-tableLoading`) + ).toBeInTheDocument(); + } + } + }); + test('Component should be throw error when noOfCols and headerTitles are undefined', () => { + const props = { + noOfRows: 10, + }; + expect(() => { + render( + + + + ); + }).toThrowError(); + }); +}); diff --git a/src/components/TableLoader/TableLoader.tsx b/src/components/TableLoader/TableLoader.tsx new file mode 100644 index 0000000000..2da4b1d172 --- /dev/null +++ b/src/components/TableLoader/TableLoader.tsx @@ -0,0 +1,67 @@ +import React, { useEffect } from 'react'; +import styles from './TableLoader.module.css'; +import { Table } from 'react-bootstrap'; + +export interface InterfaceTableLoader { + noOfRows: number; + headerTitles?: string[]; + noOfCols?: number; +} + +const tableLoader = (props: InterfaceTableLoader): JSX.Element => { + const { noOfRows, headerTitles, noOfCols } = props; + + useEffect(() => { + if (headerTitles == undefined && noOfCols == undefined) { + throw new Error( + 'TableLoader error Either headerTitles or noOfCols is required !' + ); + } + }, []); + + return ( + <> + + + + {headerTitles + ? headerTitles.map((title, index) => { + return ; + }) + : noOfCols && + [...Array(noOfCols)].map((_, index) => { + return + + + + {[...Array(noOfRows)].map((_, rowIndex) => { + return ( + + {[...Array(headerTitles ? headerTitles?.length : noOfCols)].map( + (_, colIndex) => { + return ( + + ); + } + )} + + ); + })} + +
    {title}; + })} +
    +
    +
    + + ); +}; + +export default tableLoader; diff --git a/src/components/TaskListItem/TaskListItem.test.tsx b/src/components/TaskListItem/TaskListItem.test.tsx new file mode 100644 index 0000000000..9047f72541 --- /dev/null +++ b/src/components/TaskListItem/TaskListItem.test.tsx @@ -0,0 +1,130 @@ +import React from 'react'; +import { fireEvent, render, waitFor } from '@testing-library/react'; +import { TaskListItem } from './TaskListItem'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; +import { ToastContainer } from 'react-toastify'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; + +describe('Testing Delete Event Project Modal', () => { + const props = { + organization: { + _id: '123', + members: [ + { + _id: 'abc1', + firstName: 'John', + lastName: 'Doe', + }, + { + _id: 'abc2', + firstName: 'John2', + lastName: 'Doe2', + }, + ], + }, + task: { + _id: 'xyz1', + title: 'Task 1', + deadline: '22/04/2025', + description: 'Task description', + completed: false, + volunteers: [], + }, + refetchData: jest.fn(), + }; + + test('The modal should be rendered and data should be displayed correctly', async () => { + const { queryByText, queryByRole } = render( + + + + + + + + + + + + + ); + + await waitFor(() => + expect(queryByText(props.task.title)).toBeInTheDocument() + ); + + await waitFor(() => + expect(queryByText(props.task.description)).toBeInTheDocument() + ); + + // Open the Update Task Modal + fireEvent.click(queryByText('View') as Element); + + await waitFor(() => + expect(queryByText('Update the Event Task')).toBeInTheDocument() + ); + + // Close the Update Task Modal + fireEvent.click(queryByRole('button', { name: /close/i }) as HTMLElement); + + await waitFor(() => + expect(queryByText('Update the Event Task')).not.toBeInTheDocument() + ); + }); + + test('The task should have the right when it is not completed', async () => { + const { queryByTestId } = render( + + + + + + + + + + + + + ); + + await waitFor(() => + expect(queryByTestId('AssignmentIcon')).toBeInTheDocument() + ); + await waitFor(() => + expect(queryByTestId('AssignmentTurnedInIcon')).not.toBeInTheDocument() + ); + }); + + test('The task should have the right when it is completed', async () => { + props.task.completed = true; + + const { queryByTestId } = render( + + + + + + + + + + + + + ); + + await waitFor(() => + expect(queryByTestId('AssignmentIcon')).not.toBeInTheDocument() + ); + await waitFor(() => + expect(queryByTestId('AssignmentTurnedInIcon')).toBeInTheDocument() + ); + }); +}); diff --git a/src/components/TaskListItem/TaskListItem.tsx b/src/components/TaskListItem/TaskListItem.tsx new file mode 100644 index 0000000000..5840ca136f --- /dev/null +++ b/src/components/TaskListItem/TaskListItem.tsx @@ -0,0 +1,106 @@ +import React, { useState } from 'react'; +import ListItem from '@mui/material/ListItem'; +import Divider from '@mui/material/Divider'; +import ListItemText from '@mui/material/ListItemText'; +import Chip from '@mui/material/Chip'; +import Typography from '@mui/material/Typography'; +import ListItemAvatar from '@mui/material/ListItemAvatar'; +import Avatar from '@mui/material/Avatar'; +import EditOutlinedIcon from '@mui/icons-material/EditOutlined'; +import { common } from '@mui/material/colors'; +import AssignmentIcon from '@mui/icons-material/Assignment'; +import AssignmentTurnedInIcon from '@mui/icons-material/AssignmentTurnedIn'; +import { UpdateTaskModal } from 'components/TaskModals/UpdateTaskModal'; + +interface InterfaceUser { + _id: string; + firstName: string; + lastName: string; +} +interface InterfaceTask { + _id: string; + title: string; + deadline: string; + description: string; + completed: boolean; + volunteers: InterfaceUser[]; +} + +type PropType = { + task: InterfaceTask; + refetchData: () => void; + organization: { + _id: string; + members: InterfaceUser[]; + }; +}; + +export const TaskListItem = ({ + task, + refetchData, + organization: organizationData, +}: PropType): JSX.Element => { + const [showUpdateTaskModal, setShowUpdateTaskModal] = useState(false); + + return ( + <> +
    + + + + {' '} + {task.completed ? ( + + ) : ( + + )} + + + + + {task.description} + + + } + /> + } + label="View" + variant="outlined" + onClick={(): void => { + setShowUpdateTaskModal(true); + }} + /> + + +
    + {/* Wrapper Div for all the relevant modals */} + { + setShowUpdateTaskModal(false); + }} + task={task} + refetchData={refetchData} + organization={organizationData} + /> +
    +
    + + ); +}; diff --git a/src/components/TaskModals/AddTaskModal.test.tsx b/src/components/TaskModals/AddTaskModal.test.tsx new file mode 100644 index 0000000000..ca7aa895ac --- /dev/null +++ b/src/components/TaskModals/AddTaskModal.test.tsx @@ -0,0 +1,150 @@ +import React from 'react'; +import { fireEvent, render, waitFor } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { AddTaskModal } from './AddTaskModal'; +import { ADD_EVENT_PROJECT_TASK_MUTATION } from 'GraphQl/Mutations/mutations'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; +import { ToastContainer } from 'react-toastify'; +import dayjs from 'dayjs'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; + +const today = dayjs(new Date()); +const taskDatetime = today.add(7, 'days'); + +const successfulMutationMock = [ + { + request: { + query: ADD_EVENT_PROJECT_TASK_MUTATION, + variables: { + title: 'Title', + description: 'Description', + projectId: '123', + deadline: null, + }, + }, + result: { + data: { + createTask: { + _id: '456', + }, + }, + }, + }, +]; + +const unsuccessfulMutationMock = [ + { + request: { + query: ADD_EVENT_PROJECT_TASK_MUTATION, + variables: { + title: 'Title', + description: 'Description', + projectId: '123', + deadline: taskDatetime, + }, + }, + error: new Error('Oops'), + }, +]; + +describe('Testing Add Event Task Modal', () => { + const props = { + show: true, + projectId: '123', + handleClose: jest.fn(), + refetchData: jest.fn(), + }; + + test('The modal should be rendered and add button should not work with blank values', async () => { + const { queryByText, queryByLabelText } = render( + + + + + + + + + + + + + ); + + await waitFor(() => + expect(queryByText('Add an Event Task')).toBeInTheDocument() + ); + + fireEvent.click(queryByText('Create Task') as Element); + + // Check for blank entry warning modals + await waitFor(() => + expect(queryByText('Title cannot be empty!')).toBeInTheDocument() + ); + await waitFor(() => + expect(queryByText('Description cannot be empty!')).toBeInTheDocument() + ); + + // Type in the title and the description of the event project + fireEvent.change(queryByLabelText('Title') as Element, { + target: { value: 'Title' }, + }); + fireEvent.change(queryByLabelText('Description') as Element, { + target: { value: 'Description' }, + }); + fireEvent.change(queryByLabelText('Deadline') as Element, { + target: { value: taskDatetime }, + }); + + fireEvent.click(queryByText('Create Task') as Element); + + await waitFor(() => + expect(queryByText('Adding the task...')).toBeInTheDocument() + ); + + await waitFor(() => + expect(queryByText('Added the task successfully!')).toBeInTheDocument() + ); + }); + + test('The modal should be rendered and error message should be shown if mutation fails', async () => { + const { queryByText, queryByLabelText } = render( + + + + + + + + + + + + + ); + + // Type in the title and the description of the event project + fireEvent.change(queryByLabelText('Title') as Element, { + target: { value: 'Title' }, + }); + fireEvent.change(queryByLabelText('Description') as Element, { + target: { value: 'Description' }, + }); + fireEvent.change(queryByLabelText('Deadline') as Element, { + target: { value: taskDatetime }, + }); + + fireEvent.click(queryByText('Create Task') as Element); + + await waitFor(() => + expect( + queryByText('There was an error in adding the task!') + ).toBeInTheDocument() + ); + }); +}); diff --git a/src/components/TaskModals/AddTaskModal.tsx b/src/components/TaskModals/AddTaskModal.tsx new file mode 100644 index 0000000000..0134077afe --- /dev/null +++ b/src/components/TaskModals/AddTaskModal.tsx @@ -0,0 +1,114 @@ +import React, { useState } from 'react'; +import { Modal, Button, Form } from 'react-bootstrap'; +import { toast } from 'react-toastify'; +import { useMutation } from '@apollo/client'; +import type { Dayjs } from 'dayjs'; +import dayjs from 'dayjs'; +import { DateTimePicker } from '@mui/x-date-pickers/DateTimePicker'; +import { ADD_EVENT_PROJECT_TASK_MUTATION } from 'GraphQl/Mutations/mutations'; + +type ModalPropType = { + show: boolean; + projectId: string; + handleClose: () => void; + refetchData: () => void; +}; + +export const AddTaskModal = ({ + show, + handleClose, + refetchData, + projectId, +}: ModalPropType): JSX.Element => { + const today = dayjs(new Date()); + + const [title, setTitle] = useState(''); + const [description, setDescription] = useState(''); + const [deadline, setDeadline] = useState(today); + + const [addMutation] = useMutation(ADD_EVENT_PROJECT_TASK_MUTATION); + const notify = async (e: React.FormEvent): Promise => { + e.preventDefault(); + toast.promise(handleSubmit, { + pending: 'Adding the task...', + success: 'Added the task successfully!', + error: 'There was an error in adding the task!', + }); + }; + const handleSubmit = async (): Promise => { + let toSubmit = true; + + if (title.trim().length == 0) { + toast.error('Title cannot be empty!'); + toSubmit = false; + } + if (description.trim().length == 0) { + toast.error('Description cannot be empty!'); + toSubmit = false; + } + if (!toSubmit) return Promise.reject(); + await addMutation({ + variables: { + title, + description, + projectId, + deadline, + }, + }); + refetchData(); + setTitle(''); + setDescription(''); + handleClose(); + }; + + return ( + <> + + + Add an Event Task + +
    + + + Title + setTitle(e.target.value)} + /> + + + + Description + setDescription(e.target.value)} + /> + + + + { + setDeadline(date); + }} + disablePast + /> + + + + + +
    +
    + + ); +}; diff --git a/src/components/TaskModals/DeleteTaskModal.test.tsx b/src/components/TaskModals/DeleteTaskModal.test.tsx new file mode 100644 index 0000000000..4eb40e53a8 --- /dev/null +++ b/src/components/TaskModals/DeleteTaskModal.test.tsx @@ -0,0 +1,100 @@ +import React from 'react'; +import { fireEvent, render, waitFor } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { DeleteTaskModal } from './DeleteTaskModal'; +import { DELETE_EVENT_TASK_MUTATION } from 'GraphQl/Mutations/mutations'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; +import { ToastContainer } from 'react-toastify'; + +const successfulMutationMock = [ + { + request: { + query: DELETE_EVENT_TASK_MUTATION, + variables: { id: '123' }, + }, + result: { + data: { + removeTask: { + _id: '123', + }, + }, + }, + }, +]; + +const unsuccessfulMutationMock = [ + { + request: { + query: DELETE_EVENT_TASK_MUTATION, + variables: { + id: '123', + }, + }, + error: new Error('Oops'), + }, +]; + +describe('Testing Delete Event Project Modal', () => { + const props = { + show: true, + taskId: '123', + handleClose: jest.fn(), + refetchData: jest.fn(), + }; + + test('The modal should be rendered and delete button should work', async () => { + const { queryByText } = render( + + + + + + + + + + + ); + + await waitFor(() => expect(queryByText('Delete Task')).toBeInTheDocument()); + + fireEvent.click(queryByText('Delete') as Element); + await waitFor(() => + expect(queryByText('Deleting the task...')).toBeInTheDocument() + ); + await waitFor(() => + expect(queryByText('Deleted the task successfully!')).toBeInTheDocument() + ); + }); + + test('The modal should be rendered and error message should be shown if mutation fails', async () => { + const { queryByText } = render( + + + + + + + + + + + ); + + await waitFor(() => expect(queryByText('Delete Task')).toBeInTheDocument()); + + fireEvent.click(queryByText('Delete') as Element); + await waitFor(() => + expect(queryByText('Deleting the task...')).toBeInTheDocument() + ); + await waitFor(() => + expect( + queryByText('There was an error in deleting the task!') + ).toBeInTheDocument() + ); + }); +}); diff --git a/src/components/TaskModals/DeleteTaskModal.tsx b/src/components/TaskModals/DeleteTaskModal.tsx new file mode 100644 index 0000000000..73baff5775 --- /dev/null +++ b/src/components/TaskModals/DeleteTaskModal.tsx @@ -0,0 +1,64 @@ +import React from 'react'; +import { Modal, Button } from 'react-bootstrap'; +import { toast } from 'react-toastify'; +import { useMutation } from '@apollo/client'; +import { DELETE_EVENT_TASK_MUTATION } from 'GraphQl/Mutations/mutations'; + +type ModalPropType = { + show: boolean; + taskId: string; + handleClose: () => void; + refetchData: () => void; +}; + +export const DeleteTaskModal = (props: ModalPropType): JSX.Element => { + const [deleteMutation] = useMutation(DELETE_EVENT_TASK_MUTATION); + const notify = (): Promise => { + return toast.promise(deleteProject, { + pending: 'Deleting the task...', + success: 'Deleted the task successfully!', + error: 'There was an error in deleting the task!', + }); + }; + const deleteProject = async (): Promise => { + await deleteMutation({ + variables: { + id: props.taskId, + }, + }); + props.refetchData(); + props.handleClose(); + }; + + return ( + <> + + + Delete Task + + +
    + Are you sure you want to delete this? +
    +
    + + + + +
    + + ); +}; diff --git a/src/components/TaskModals/ManageVolunteerModal.test.tsx b/src/components/TaskModals/ManageVolunteerModal.test.tsx new file mode 100644 index 0000000000..e284984969 --- /dev/null +++ b/src/components/TaskModals/ManageVolunteerModal.test.tsx @@ -0,0 +1,135 @@ +import React from 'react'; +import { fireEvent, render, waitFor } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { ManageVolunteerModal } from './ManageVolunteerModal'; +import { SET_TASK_VOLUNTEERS_MUTATION } from 'GraphQl/Mutations/mutations'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; +import { ToastContainer } from 'react-toastify'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; + +const successfulMutationMock = [ + { + request: { + query: SET_TASK_VOLUNTEERS_MUTATION, + variables: { + id: '123', + volunteers: ['user1'], + }, + }, + result: { + data: { + setTaskVolunteers: { + _id: '456', + }, + }, + }, + }, +]; + +const unsuccessfulMutationMock = [ + { + request: { + query: SET_TASK_VOLUNTEERS_MUTATION, + variables: { + id: '123', + volunteers: [], + }, + }, + error: new Error('Oops'), + }, +]; + +describe('Testing Manage Volunteers Modal', () => { + const props = { + show: true, + taskId: '123', + organization: { + _id: 'testorg', + members: [ + { _id: 'user1', firstName: 'John1', lastName: 'Doe1' }, + { _id: 'user2', firstName: 'John2', lastName: 'Doe2' }, + { _id: 'user3', firstName: 'John3', lastName: 'Doe3' }, + ], + }, + volunteers: [], + handleClose: jest.fn(), + refetchData: jest.fn(), + }; + + test('The modal should be rendered and update button should work properly', async () => { + const { queryByText, queryByLabelText } = render( + + + + + + + + + + + + + ); + + await waitFor(() => + expect(queryByText('Manage Volunteers')).toBeInTheDocument() + ); + + // Fill out the autocomplete with volunteer information + const volunteerInput = queryByLabelText('Assign Volunteers'); + expect(volunteerInput).toBeInTheDocument(); + + fireEvent.change(volunteerInput as Element, { + target: { value: 'John1 Doe1' }, + }); + fireEvent.keyDown(volunteerInput as HTMLElement, { key: 'Enter' }); + + // Click the update button + fireEvent.click(queryByText('Update Volunteers') as Element); + + await waitFor(() => + expect(queryByText('Updating the volunteers...')).toBeInTheDocument() + ); + + await waitFor(() => + expect( + queryByText('Successfully updated the volunteers!') + ).toBeInTheDocument() + ); + }); + + test('The modal should be rendered and error message should be shown if mutation fails', async () => { + const { queryByText } = render( + + + + + + + + + + + + + ); + + fireEvent.click(queryByText('Update Volunteers') as Element); + + await waitFor(() => + expect(queryByText('Updating the volunteers...')).toBeInTheDocument() + ); + + await waitFor(() => + expect( + queryByText('There was an error in updating the volunteers!') + ).toBeInTheDocument() + ); + }); +}); diff --git a/src/components/TaskModals/ManageVolunteerModal.tsx b/src/components/TaskModals/ManageVolunteerModal.tsx new file mode 100644 index 0000000000..162fda4a02 --- /dev/null +++ b/src/components/TaskModals/ManageVolunteerModal.tsx @@ -0,0 +1,102 @@ +import React, { useEffect, useState } from 'react'; +import { Modal } from 'react-bootstrap'; +import Autocomplete from '@mui/material/Autocomplete'; +import TextField from '@mui/material/TextField'; +import Stack from '@mui/material/Stack'; +import { Button } from 'react-bootstrap'; +import { useMutation } from '@apollo/client'; +import { SET_TASK_VOLUNTEERS_MUTATION } from 'GraphQl/Mutations/mutations'; +import { toast } from 'react-toastify'; + +interface InterfaceUser { + _id: string; + firstName: string; + lastName: string; +} + +type ModalPropType = { + show: boolean; + taskId: string; + organization: { + _id: string; + members: InterfaceUser[]; + }; + volunteers: InterfaceUser[]; + handleClose: () => void; + refetchData: () => void; +}; + +export const ManageVolunteerModal = (props: ModalPropType): JSX.Element => { + const [volunteers, setVolunteers] = useState([]); + + useEffect(() => setVolunteers(props.volunteers), [props.volunteers]); + + const [setMutation] = useMutation(SET_TASK_VOLUNTEERS_MUTATION); + const notify = (): Promise => { + return toast.promise(handleSubmit, { + pending: 'Updating the volunteers...', + success: 'Successfully updated the volunteers!', + error: 'There was an error in updating the volunteers!', + }); + }; + const handleSubmit = async (): Promise => { + await setMutation({ + variables: { + id: props.taskId, + volunteers: volunteers.map((volunteer) => volunteer._id), + }, + }); + props.refetchData(); + props.handleClose(); + }; + + return ( + <> + + + Manage Volunteers + + +

    + All the members of the organization of the event can be added as + volunteers for a task. +

    + + + `${memberOption.firstName} ${memberOption.lastName}` + } + filterSelectedOptions={true} + onChange={(_, value): void => { + setVolunteers(value); + }} + autoHighlight={true} + renderInput={(params): React.ReactNode => ( + + )} + /> + +
    +
    + + + +
    + + ); +}; diff --git a/src/components/TaskModals/UpdateTaskModal.test.tsx b/src/components/TaskModals/UpdateTaskModal.test.tsx new file mode 100644 index 0000000000..9541d6d26b --- /dev/null +++ b/src/components/TaskModals/UpdateTaskModal.test.tsx @@ -0,0 +1,262 @@ +import React from 'react'; +import { fireEvent, render, waitFor } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { UpdateTaskModal } from './UpdateTaskModal'; +import { UPDATE_EVENT_PROJECT_TASK_MUTATION } from 'GraphQl/Mutations/mutations'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; +import { ToastContainer } from 'react-toastify'; +import dayjs from 'dayjs'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import type { ModalPropType } from './UpdateTaskModal'; + +const today = dayjs(new Date()); +const oldDeadline = today.add(7, 'days'); +const newDeadline = today.add(10, 'days'); + +const successfulMutationMock = [ + { + request: { + query: UPDATE_EVENT_PROJECT_TASK_MUTATION, + variables: { + title: 'Title', + description: 'Description', + taskId: 'task1', + completed: true, + deadline: null, + }, + }, + result: { + data: { + updateTask: { + _id: '456', + }, + }, + }, + }, +]; + +const unsuccessfulMutationMock = [ + { + request: { + query: UPDATE_EVENT_PROJECT_TASK_MUTATION, + variables: { + title: 'Title', + description: 'Description', + taskId: 'task1', + completed: true, + deadline: null, + }, + }, + error: new Error('Oops'), + }, +]; + +describe('Testing Update Event Task Modal', () => { + const props = { + show: true, + task: { + _id: 'task1', + title: 'Task 1', + description: 'Description 1', + deadline: oldDeadline.toString(), + completed: false, + volunteers: [], + }, + organization: { + _id: 'org1', + members: [], + }, + handleClose: jest.fn(), + refetchData: jest.fn(), + }; + + test('The modal should be rendered and update button should not work with blank values', async () => { + const { queryByText, queryByLabelText } = render( + + + + + + + + + + + + + ); + + await waitFor(() => + expect(queryByText('Update the Event Task')).toBeInTheDocument() + ); + + // Set the title and the description of the event task to blank + fireEvent.change(queryByLabelText('Title') as Element, { + target: { value: '' }, + }); + fireEvent.change(queryByLabelText('Description') as Element, { + target: { value: '' }, + }); + + fireEvent.click(queryByText('Update Task') as Element); + + // Check for blank entry warning modals + await waitFor(() => + expect(queryByText('Title cannot be empty!')).toBeInTheDocument() + ); + await waitFor(() => + expect(queryByText('Description cannot be empty!')).toBeInTheDocument() + ); + + // Type in the title and the description of the event task + fireEvent.change(queryByLabelText('Title') as Element, { + target: { value: 'Title' }, + }); + fireEvent.change(queryByLabelText('Description') as Element, { + target: { value: 'Description' }, + }); + fireEvent.change(queryByLabelText('Deadline') as Element, { + target: { value: newDeadline }, + }); + fireEvent.click(queryByLabelText('Completed') as Element); + + // Click the update button + fireEvent.click(queryByText('Update Task') as Element); + + await waitFor(() => + expect(queryByText('Updating the task...')).toBeInTheDocument() + ); + + await waitFor(() => + expect(queryByText('Updated the task successfully!')).toBeInTheDocument() + ); + }); + + test('The modal should show message when there are no volunteers', async () => { + const { queryByText } = render( + + + + + + + + + + + + + ); + + await waitFor(() => + expect( + queryByText('There are no volunteers assigned for this task.') + ).toBeInTheDocument() + ); + }); + + test('The modal should not show message when there are no volunteers', async () => { + const customProps: ModalPropType = { ...props }; + customProps.task.volunteers = [ + { + _id: 'user1', + firstName: 'John', + lastName: 'Doe', + }, + ]; + + const { queryByText } = render( + + + + + + + + + + + + + ); + + await waitFor(() => + expect( + queryByText('There are no volunteers assigned for this task.') + ).not.toBeInTheDocument() + ); + + await waitFor(() => expect(queryByText('John Doe')).toBeInTheDocument()); + }); + + test('The modal should be rendered and error message should be shown if mutation fails', async () => { + const { queryByText, queryByLabelText } = render( + + + + + + + + + + + + + ); + + // Type in the title and the description of the event project + fireEvent.change(queryByLabelText('Title') as Element, { + target: { value: 'Title' }, + }); + fireEvent.change(queryByLabelText('Description') as Element, { + target: { value: 'Description' }, + }); + fireEvent.change(queryByLabelText('Deadline') as Element, { + target: { value: newDeadline }, + }); + fireEvent.click(queryByLabelText('Completed') as Element); + + fireEvent.click(queryByText('Update Task') as Element); + + await waitFor(() => + expect( + queryByText('There was an error in updating the task!') + ).toBeInTheDocument() + ); + }); + + test('Manage volunteer modal and delete task modal should open and close properly', async () => { + const { queryByText, queryAllByRole } = render( + + + + + + + + + + + + + ); + + // Manage Volunteer Modal + fireEvent.click(queryByText('Manage Volunteers') as Element); + queryAllByRole('button', { name: /close/i }).forEach((ele) => + fireEvent.click(ele as HTMLElement) + ); + + // Delete Task Modal + fireEvent.click(queryByText('Delete Task') as Element); + queryAllByRole('button', { name: /close/i }).forEach((ele) => + fireEvent.click(ele as HTMLElement) + ); + }); +}); diff --git a/src/components/TaskModals/UpdateTaskModal.tsx b/src/components/TaskModals/UpdateTaskModal.tsx new file mode 100644 index 0000000000..d79dd19a36 --- /dev/null +++ b/src/components/TaskModals/UpdateTaskModal.tsx @@ -0,0 +1,222 @@ +import React, { useEffect, useState } from 'react'; +import { Modal, Button as BootstrapButton, Form } from 'react-bootstrap'; +import { toast } from 'react-toastify'; +import { useMutation } from '@apollo/client'; +import type { Dayjs } from 'dayjs'; +import dayjs from 'dayjs'; +import { DateTimePicker } from '@mui/x-date-pickers/DateTimePicker'; +import { UPDATE_EVENT_PROJECT_TASK_MUTATION } from 'GraphQl/Mutations/mutations'; +import { DeleteTaskModal } from './DeleteTaskModal'; +import { ManageVolunteerModal } from './ManageVolunteerModal'; +import Chip from '@mui/material/Chip'; +import Stack from '@mui/material/Stack'; +import Avatar from '@mui/material/Avatar'; +import ModeEditIcon from '@mui/icons-material/ModeEdit'; +import Button from '@mui/material/Button'; + +interface InterfaceUser { + _id: string; + firstName: string; + lastName: string; +} +interface InterfaceTask { + _id: string; + title: string; + deadline: string; + description: string; + completed: boolean; + volunteers: InterfaceUser[]; +} + +export type ModalPropType = { + show: boolean; + task: InterfaceTask; + organization: { + _id: string; + members: InterfaceUser[]; + }; + handleClose: () => void; + refetchData: () => void; +}; + +export const UpdateTaskModal = (props: ModalPropType): JSX.Element => { + const [title, setTitle] = useState(''); + const [description, setDescription] = useState(''); + const [deadline, setDeadline] = useState(null); + const [completed, setCompleted] = useState(false); + + const [showDeleteTaskModal, setShowDeleteTaskModal] = useState(false); + const [showManageVolunteerModal, setShowManageVolunteerModal] = + useState(false); + + useEffect(() => { + setTitle(props.task.title); + setDescription(props.task.description); + setDeadline(dayjs(props.task.deadline)); + setCompleted(props.task.completed); + }, [props.task]); + + const [updateMutation] = useMutation(UPDATE_EVENT_PROJECT_TASK_MUTATION); + const notify = (e: React.FormEvent): Promise => { + e.preventDefault(); + return toast.promise(handleSubmit, { + pending: 'Updating the task...', + success: 'Updated the task successfully!', + error: 'There was an error in updating the task!', + }); + }; + const handleSubmit = async (): Promise => { + let toSubmit = true; + + if (title.trim().length == 0) { + toast.error('Title cannot be empty!'); + toSubmit = false; + } + if (description.trim().length == 0) { + toast.error('Description cannot be empty!'); + toSubmit = false; + } + if (!toSubmit) return Promise.reject(); + + await updateMutation({ + variables: { + taskId: props.task._id, + title, + description, + deadline, + completed, + }, + }); + props.refetchData(); + props.handleClose(); + }; + + return ( + <> + + + + Update the Event Task + + +
    + + + Title + setTitle(e.target.value)} + /> + + + + Description + setDescription(e.target.value)} + /> + + + { + setDeadline(date); + }} + disablePast + className="mb-1" + /> + + + Completed + setCompleted(!completed)} + /> + + + + Volunteers +
    + {!props.task.volunteers.length + ? `There are no volunteers assigned for this task.` + : null} + + {props.task.volunteers.map( + (user): React.ReactNode => ( + {`${user.firstName[0].toUpperCase()}${user.lastName[0].toUpperCase()}`} + } + label={`${user.firstName} ${user.lastName}`} + variant="outlined" + /> + ) + )} + + +
    +
    +
    + + + Update Task + + { + setShowDeleteTaskModal(true); + props.handleClose(); + }} + > + Delete Task + + +
    +
    + { + setShowDeleteTaskModal(false); + }} + /> + { + setShowManageVolunteerModal(false); + }} + volunteers={props.task.volunteers} + organization={props.organization} + taskId={props.task._id} + /> + + ); +}; diff --git a/src/components/UserListCard/UserListCard.module.css b/src/components/UserListCard/UserListCard.module.css new file mode 100644 index 0000000000..187757a531 --- /dev/null +++ b/src/components/UserListCard/UserListCard.module.css @@ -0,0 +1,74 @@ +.memberlist { + margin-top: -1px; +} +.memberimg { + width: 200px; + height: 100px; + border-radius: 7px; + margin-left: 20px; +} +.singledetails { + display: flex; + flex-direction: row; + justify-content: space-between; +} +.singledetails p { + margin-bottom: -5px; +} +.singledetails_data_left { + margin-top: 10px; + margin-left: 10px; + color: #707070; +} +.singledetails_data_right { + justify-content: right; + margin-top: 10px; + text-align: right; + color: #707070; +} +.membername { + font-size: 16px; + font-weight: bold; +} +.memberfont { + margin-top: 3px; +} +.memberfont > span { + width: 80%; +} +.memberfontcreated { + margin-top: 18px; +} +.memberfontcreatedbtn { + margin-top: 33px; + border-radius: 7px; + border-color: #31bb6b; + background-color: #31bb6b; + color: white; + padding-right: 10px; + padding-left: 10px; + justify-content: flex-end; + float: right; + text-align: right; + box-shadow: none; +} +#grid_wrapper { + align-items: left; +} +.peoplelistdiv { + margin-right: 50px; +} +@media only screen and (max-width: 600px) { + .singledetails { + margin-left: 20px; + } + .memberimg { + margin: auto; + } + .singledetails_data_right { + margin-right: -52px; + } + .singledetails_data_left { + margin-left: 0px; + } +} diff --git a/src/components/UserListCard/UserListCard.test.tsx b/src/components/UserListCard/UserListCard.test.tsx new file mode 100644 index 0000000000..894571a597 --- /dev/null +++ b/src/components/UserListCard/UserListCard.test.tsx @@ -0,0 +1,98 @@ +import React from 'react'; +import { act, render, screen } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; + +import UserListCard from './UserListCard'; +import { ADD_ADMIN_MUTATION } from 'GraphQl/Mutations/mutations'; +import i18nForTest from 'utils/i18nForTest'; +import { BrowserRouter } from 'react-router-dom'; +import { StaticMockLink } from 'utils/StaticMockLink'; + +const MOCKS = [ + { + request: { + query: ADD_ADMIN_MUTATION, + variable: { userid: '784', orgid: '554' }, + }, + result: { + data: { + organizations: [ + { + _id: '1', + }, + ], + }, + }, + }, +]; +const link = new StaticMockLink(MOCKS, true); +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Testing User List Card', () => { + global.alert = jest.fn(); + + test('Should render props and text elements test for the page component', async () => { + const props = { + key: '123', + id: '456', + memberName: 'John Doe', + joinDate: '07/05/2022', + memberImage: 'image', + memberEmail: 'johndoe@gmail.com', + }; + + render( + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByText(/Add Admin/i)); + + expect(screen.getByText('Joined:')).toBeInTheDocument(); + expect(screen.getByText(props.memberName)).toBeInTheDocument(); + expect(screen.getByText(props.joinDate)).toBeInTheDocument(); + }); + + test('Should render text elements when props value is not passed', async () => { + const props = { + key: '123', + id: '456', + memberName: '', + joinDate: '09/05/2022', + memberImage: '', + memberEmail: '', + }; + + render( + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByText(/Add Admin/i)); + + expect(screen.getByText('Joined:')).toBeInTheDocument(); + expect(screen.getByText(props.joinDate)).toBeInTheDocument(); + }); +}); diff --git a/src/components/UserListCard/UserListCard.tsx b/src/components/UserListCard/UserListCard.tsx new file mode 100644 index 0000000000..9bdda78636 --- /dev/null +++ b/src/components/UserListCard/UserListCard.tsx @@ -0,0 +1,95 @@ +import React from 'react'; +import Row from 'react-bootstrap/Row'; +import Col from 'react-bootstrap/Col'; +import Button from 'react-bootstrap/Button'; +import { useMutation } from '@apollo/client'; +import { toast } from 'react-toastify'; +import { useTranslation } from 'react-i18next'; + +import { ADD_ADMIN_MUTATION } from 'GraphQl/Mutations/mutations'; +import styles from './UserListCard.module.css'; +import { Link } from 'react-router-dom'; +import defaultImg from 'assets/images/blank.png'; +import { errorHandler } from 'utils/errorHandler'; + +interface InterfaceUserListCardProps { + key: string; + id: string; + memberName: string; + joinDate: string; + memberImage: string; + memberEmail: string; +} + +function userListCard(props: InterfaceUserListCardProps): JSX.Element { + const currentUrl = window.location.href.split('=')[1]; + const [adda] = useMutation(ADD_ADMIN_MUTATION); + + const { t } = useTranslation('translation', { + keyPrefix: 'userListCard', + }); + + const addAdmin = async (): Promise => { + try { + const { data } = await adda({ + variables: { + userid: props.id, + orgid: currentUrl, + }, + }); + + /* istanbul ignore next */ + if (data) { + toast.success(t('addedAsAdmin')); + setTimeout(() => { + window.location.reload(); + }, 2000); + } + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + + return ( + <> +
    + + {props.memberImage ? ( + + ) : ( + + )} + +
    + + {props.memberName ? <>{props.memberName} : <>Dogs Care} + +

    {props.memberEmail}

    +
    +
    +

    + {t('joined')}: {props.joinDate} +

    + +
    + +
    +
    +
    + + ); +} +export {}; +export default userListCard; diff --git a/src/components/UserPasswordUpdate/UserPasswordUpdate.module.css b/src/components/UserPasswordUpdate/UserPasswordUpdate.module.css new file mode 100644 index 0000000000..54cf1c020c --- /dev/null +++ b/src/components/UserPasswordUpdate/UserPasswordUpdate.module.css @@ -0,0 +1,93 @@ +/* .userupdatediv{ + border: 1px solid #e8e5e5; + box-shadow: 2px 1px #e8e5e5; + padding:25px 16px; + border-radius: 5px; + background:#fdfdfd; +} */ +.settingstitle { + color: #707070; + font-size: 20px; + margin-bottom: 30px; + text-align: center; + margin-top: -10px; +} +.dispflex { + display: flex; + justify-content: flex-start; + margin: 0 auto; +} +.dispbtnflex { + width: 90%; + margin-top: 20px; + display: flex; + margin: 0 30%; +} +.dispflex > div { + width: 50%; + margin-right: 50px; +} + +.radio_buttons > input { + margin-bottom: 20px; + border: none; + box-shadow: none; + padding: 0 0; + border-radius: 5px; + background: none; + width: 50%; +} + +.whitebtn { + margin: 1rem 0 0; + margin-top: 10px; + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + padding: 10px 20px; + border-radius: 5px; + background: none; + width: 20%; + font-size: 16px; + color: #31bb6b; + outline: none; + font-weight: 600; + cursor: pointer; + float: left; + transition: transform 0.2s, box-shadow 0.2s; +} +.greenregbtn { + margin: 1rem 0 0; + margin-top: 10px; + margin-right: 30px; + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + padding: 10px 10px; + border-radius: 5px; + background-color: #31bb6b; + width: 20%; + font-size: 16px; + color: white; + outline: none; + font-weight: 600; + cursor: pointer; + transition: transform 0.2s, box-shadow 0.2s; +} +.radio_buttons { + width: 55%; + margin-top: 10px; + display: flex; + color: #707070; + font-weight: 600; + font-size: 14px; +} +.radio_buttons > input { + transform: scale(1.2); +} +.radio_buttons > label { + margin-top: -4px; + margin-left: 0px; + margin-right: 7px; +} +.idtitle { + width: 88%; +} diff --git a/src/components/UserPasswordUpdate/UserPasswordUpdate.test.tsx b/src/components/UserPasswordUpdate/UserPasswordUpdate.test.tsx new file mode 100644 index 0000000000..285b430c59 --- /dev/null +++ b/src/components/UserPasswordUpdate/UserPasswordUpdate.test.tsx @@ -0,0 +1,150 @@ +import React from 'react'; +import { act, render, screen } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; +import { UPDATE_USER_PASSWORD_MUTATION } from 'GraphQl/Mutations/mutations'; +import i18nForTest from 'utils/i18nForTest'; +import UserPasswordUpdate from './UserPasswordUpdate'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { toast as mockToast } from 'react-toastify'; + +jest.mock('react-toastify', () => ({ + toast: { + error: jest.fn(), + success: jest.fn(), + }, +})); + +const MOCKS = [ + { + request: { + query: UPDATE_USER_PASSWORD_MUTATION, + variable: { + previousPassword: 'anshgoyal', + newPassword: 'anshgoyalansh', + confirmNewPassword: 'anshgoyalansh', + }, + }, + result: { + data: { + users: [ + { + _id: '1', + }, + ], + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); + +async function wait(ms = 5): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Testing User Password Update', () => { + const props = { + key: '123', + id: '1', + }; + + const formData = { + previousPassword: 'Palisadoes', + newPassword: 'ThePalisadoesFoundation', + wrongPassword: 'This is wrong passoword', + confirmNewPassword: 'ThePalisadoesFoundation', + }; + + global.alert = jest.fn(); + + test('should render props and text elements test for the page component', async () => { + render( + + + + + + ); + + await wait(); + + userEvent.type( + screen.getByPlaceholderText(/Previous Password/i), + formData.previousPassword + ); + userEvent.type( + screen.getAllByPlaceholderText(/New Password/i)[0], + formData.newPassword + ); + userEvent.type( + screen.getByPlaceholderText(/Confirm New Password/i), + formData.confirmNewPassword + ); + + userEvent.click(screen.getByText(/Save Changes/i)); + + expect(screen.getByText(/Cancel/i)).toBeTruthy(); + expect( + screen.getByPlaceholderText(/Previous Password/i) + ).toBeInTheDocument(); + expect( + screen.getByPlaceholderText(/Confirm New Password/i) + ).toBeInTheDocument(); + }); + + test('displays an error when the password field is empty', async () => { + render( + + + + + + ); + + userEvent.click(screen.getByText(/Save Changes/i)); + + await wait(); + expect(mockToast.error).toHaveBeenCalledWith( + 'The password field cannot be empty.' + ); + }); + + test('displays an error when new and confirm password field does not match', async () => { + render( + + + + + + ); + + await wait(); + + userEvent.type( + screen.getByPlaceholderText(/Previous Password/i), + formData.previousPassword + ); + userEvent.type( + screen.getAllByPlaceholderText(/New Password/i)[0], + formData.wrongPassword + ); + userEvent.type( + screen.getByPlaceholderText(/Confirm New Password/i), + formData.confirmNewPassword + ); + + userEvent.click(screen.getByText(/Save Changes/i)); + + expect(screen.getByText(/Cancel/i)).toBeTruthy(); + await wait(); + expect(mockToast.error).toHaveBeenCalledWith( + 'New and Confirm password do not match.' + ); + }); +}); diff --git a/src/components/UserPasswordUpdate/UserPasswordUpdate.tsx b/src/components/UserPasswordUpdate/UserPasswordUpdate.tsx new file mode 100644 index 0000000000..2fc2874360 --- /dev/null +++ b/src/components/UserPasswordUpdate/UserPasswordUpdate.tsx @@ -0,0 +1,156 @@ +import React from 'react'; +import { useMutation } from '@apollo/client'; +import { UPDATE_USER_PASSWORD_MUTATION } from 'GraphQl/Mutations/mutations'; +import { useTranslation } from 'react-i18next'; +import Button from 'react-bootstrap/Button'; +import styles from './UserPasswordUpdate.module.css'; +import { toast } from 'react-toastify'; +import { Form } from 'react-bootstrap'; + +interface InterfaceUserPasswordUpdateProps { + id: string; +} + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const UserUpdate: React.FC = ({ + // eslint-disable-next-line @typescript-eslint/no-unused-vars + id, +}): JSX.Element => { + const { t } = useTranslation('translation', { + keyPrefix: 'userPasswordUpdate', + }); + const [formState, setFormState] = React.useState({ + previousPassword: '', + newPassword: '', + confirmNewPassword: '', + }); + + const [login] = useMutation(UPDATE_USER_PASSWORD_MUTATION); + + const loginLink = async (): Promise => { + if ( + !formState.previousPassword || + !formState.newPassword || + !formState.confirmNewPassword + ) { + toast.error('The password field cannot be empty.'); + return; + } + + if (formState.newPassword !== formState.confirmNewPassword) { + toast.error('New and Confirm password do not match.'); + return; + } + + try { + const { data } = await login({ + variables: { + previousPassword: formState.previousPassword, + newPassword: formState.newPassword, + confirmNewPassword: formState.confirmNewPassword, + }, + }); + /* istanbul ignore next */ + if (data) { + toast.success('Successful updated'); + setTimeout(() => { + window.location.reload(); + }, 2000); + } + } catch (error: any) { + /* istanbul ignore next */ + toast.error(error.toString()); + } + }; + + /* istanbul ignore next */ + const cancelUpdate = (): void => { + window.location.reload(); + }; + + return ( + <> +
    +
    + {/*

    Update Your Details

    */} +
    +
    + + { + setFormState({ + ...formState, + previousPassword: e.target.value, + }); + }} + /> +
    +
    +
    +
    + + { + setFormState({ + ...formState, + newPassword: e.target.value, + }); + }} + /> +
    +
    +
    +
    + + { + setFormState({ + ...formState, + confirmNewPassword: e.target.value, + }); + }} + /> +
    +
    +
    + + +
    +
    +
    + + ); +}; +export default UserUpdate; diff --git a/src/components/UserPortal/ChatRoom/ChatRoom.module.css b/src/components/UserPortal/ChatRoom/ChatRoom.module.css new file mode 100644 index 0000000000..592004d523 --- /dev/null +++ b/src/components/UserPortal/ChatRoom/ChatRoom.module.css @@ -0,0 +1,13 @@ +.chatAreaContainer { + padding: 10px; + flex-grow: 1; + background-color: rgba(196, 255, 211, 0.3); +} + +.backgroundWhite { + background-color: white; +} + +.grey { + color: grey; +} diff --git a/src/components/UserPortal/ChatRoom/ChatRoom.tsx b/src/components/UserPortal/ChatRoom/ChatRoom.tsx new file mode 100644 index 0000000000..c7ada20a13 --- /dev/null +++ b/src/components/UserPortal/ChatRoom/ChatRoom.tsx @@ -0,0 +1,81 @@ +import React from 'react'; +import type { ChangeEvent } from 'react'; +import { Paper } from '@mui/material'; +import SendIcon from '@mui/icons-material/Send'; +import { Button, Form, InputGroup } from 'react-bootstrap'; +import styles from './ChatRoom.module.css'; +import PermContactCalendarIcon from '@mui/icons-material/PermContactCalendar'; +import { useTranslation } from 'react-i18next'; + +interface InterfaceChatRoomProps { + selectedContact: string; +} + +export default function chatRoom(props: InterfaceChatRoomProps): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'userChatRoom', + }); + + const [newMessage, setNewMessage] = React.useState(''); + + const handleNewMessageChange = (e: ChangeEvent): void => { + const newMessageValue = e.target.value; + + setNewMessage(newMessageValue); + }; + + return ( +
    + {!props.selectedContact ? ( +
    + +
    {t('selectContact')}
    +
    + ) : ( + <> +
    + + My message + + + Other message + +
    +
    + + + + +
    + + )} +
    + ); +} diff --git a/src/components/UserPortal/CommentCard/CommentCard.module.css b/src/components/UserPortal/CommentCard/CommentCard.module.css new file mode 100644 index 0000000000..1124f6369d --- /dev/null +++ b/src/components/UserPortal/CommentCard/CommentCard.module.css @@ -0,0 +1,46 @@ +.mainContainer { + width: 100%; + display: flex; + flex-direction: row; + padding: 10px; + background-color: white; + border-radius: 10px; + box-shadow: 2px 2px 8px 0px #c8c8c8; + overflow: hidden; + margin-top: 10px; +} + +.personDetails { + display: flex; + flex-direction: column; + justify-content: center; +} + +.personImage { + border-radius: 50%; + margin-right: 20px; +} + +.cardActions { + display: flex; + flex-direction: row; + align-items: center; + gap: 10px; + margin-top: 10px; +} + +.cardActionBtn { + background-color: rgba(0, 0, 0, 0); + border: none; + color: black; +} + +.cardActionBtn:hover { + background-color: ghostwhite; + border: none; + color: green !important; +} + +.likeIcon { + width: 20px; +} diff --git a/src/components/UserPortal/CommentCard/CommentCard.test.tsx b/src/components/UserPortal/CommentCard/CommentCard.test.tsx new file mode 100644 index 0000000000..c586809132 --- /dev/null +++ b/src/components/UserPortal/CommentCard/CommentCard.test.tsx @@ -0,0 +1,228 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { act, render, screen } from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; + +import CommentCard from './CommentCard'; +import userEvent from '@testing-library/user-event'; +import { LIKE_COMMENT, UNLIKE_COMMENT } from 'GraphQl/Mutations/mutations'; + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +const MOCKS = [ + { + request: { + query: LIKE_COMMENT, + variables: { + commentId: '1', + }, + result: { + data: { + likeComment: { + _id: '1', + }, + }, + }, + }, + }, + { + request: { + query: UNLIKE_COMMENT, + variables: { + commentId: '1', + }, + result: { + data: { + unlikeComment: { + _id: '1', + }, + }, + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); + +describe('Testing CommentCard Component [User Portal]', () => { + afterEach(async () => { + await act(async () => { + await i18nForTest.changeLanguage('en'); + }); + }); + + test('Component should be rendered properly if comment is already liked by the user.', async () => { + const cardProps = { + id: '1', + creator: { + id: '1', + firstName: 'test', + lastName: 'user', + email: 'test@user.com', + }, + likeCount: 1, + likedBy: [ + { + id: '1', + }, + ], + text: 'testComment', + }; + + const beforeUserId = localStorage.getItem('userId'); + localStorage.setItem('userId', '2'); + + render( + + + + + + + + + + ); + + await wait(); + if (beforeUserId) { + localStorage.setItem('userId', beforeUserId); + } + }); + + test('Component should be rendered properly if comment is not already liked by the user.', async () => { + const cardProps = { + id: '1', + creator: { + id: '1', + firstName: 'test', + lastName: 'user', + email: 'test@user.com', + }, + likeCount: 1, + likedBy: [ + { + id: '1', + }, + ], + text: 'testComment', + }; + + const beforeUserId = localStorage.getItem('userId'); + localStorage.setItem('userId', '1'); + + render( + + + + + + + + + + ); + + await wait(); + if (beforeUserId) { + localStorage.setItem('userId', beforeUserId); + } + }); + + test('Component renders as expected if user likes the comment.', async () => { + const cardProps = { + id: '1', + creator: { + id: '1', + firstName: 'test', + lastName: 'user', + email: 'test@user.com', + }, + likeCount: 1, + likedBy: [ + { + id: '1', + }, + ], + text: 'testComment', + }; + + const beforeUserId = localStorage.getItem('userId'); + localStorage.setItem('userId', '2'); + + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('likeCommentBtn')); + + await wait(); + + if (beforeUserId) { + localStorage.setItem('userId', beforeUserId); + } + }); + + test('Component renders as expected if user unlikes the comment.', async () => { + const cardProps = { + id: '1', + creator: { + id: '1', + firstName: 'test', + lastName: 'user', + email: 'test@user.com', + }, + likeCount: 1, + likedBy: [ + { + id: '1', + }, + ], + text: 'testComment', + }; + + const beforeUserId = localStorage.getItem('userId'); + localStorage.setItem('userId', '1'); + + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('likeCommentBtn')); + + if (beforeUserId) { + localStorage.setItem('userId', beforeUserId); + } + }); +}); diff --git a/src/components/UserPortal/CommentCard/CommentCard.tsx b/src/components/UserPortal/CommentCard/CommentCard.tsx new file mode 100644 index 0000000000..8b2d5a8fca --- /dev/null +++ b/src/components/UserPortal/CommentCard/CommentCard.tsx @@ -0,0 +1,101 @@ +import React from 'react'; +import { Button } from 'react-bootstrap'; +import styles from './CommentCard.module.css'; +import ThumbUpIcon from '@mui/icons-material/ThumbUp'; +import { useMutation } from '@apollo/client'; +import { LIKE_COMMENT, UNLIKE_COMMENT } from 'GraphQl/Mutations/mutations'; +import { toast } from 'react-toastify'; +import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; +import ThumbUpOffAltIcon from '@mui/icons-material/ThumbUpOffAlt'; + +interface InterfaceCommentCardProps { + id: string; + creator: { + id: string; + firstName: string; + lastName: string; + email: string; + }; + likeCount: number; + likedBy: { + id: string; + }[]; + text: string; +} + +function commentCard(props: InterfaceCommentCardProps): JSX.Element { + const creatorName = `${props.creator.firstName} ${props.creator.lastName}`; + + const userId = localStorage.getItem('userId'); + const likedByUser = props.likedBy.some((likedBy) => likedBy.id === userId); + + const [likes, setLikes] = React.useState(props.likeCount); + const [isLikedByUser, setIsLikedByUser] = React.useState(likedByUser); + const [likeComment, { loading: likeLoading }] = useMutation(LIKE_COMMENT); + const [unlikeComment, { loading: unlikeLoading }] = + useMutation(UNLIKE_COMMENT); + + const handleToggleLike = async (): Promise => { + if (isLikedByUser) { + try { + const { data } = await unlikeComment({ + variables: { + commentId: props.id, + }, + }); + /* istanbul ignore next */ + if (data) { + setLikes((likes) => likes - 1); + setIsLikedByUser(false); + } + } catch (error: any) { + /* istanbul ignore next */ + toast.error(error); + } + } else { + try { + const { data } = await likeComment({ + variables: { + commentId: props.id, + }, + }); + /* istanbul ignore next */ + if (data) { + setLikes((likes) => likes + 1); + setIsLikedByUser(true); + } + } catch (error: any) { + /* istanbul ignore next */ + toast.error(error); + } + } + }; + + return ( +
    +
    + {creatorName} + {props.text} +
    + + {`${likes} Likes`} +
    +
    +
    + ); +} + +export default commentCard; diff --git a/src/components/UserPortal/ContactCard/ContactCard.module.css b/src/components/UserPortal/ContactCard/ContactCard.module.css new file mode 100644 index 0000000000..d722a3a302 --- /dev/null +++ b/src/components/UserPortal/ContactCard/ContactCard.module.css @@ -0,0 +1,33 @@ +.contact { + display: flex; + flex-direction: row; + padding: 10px 10px; + cursor: pointer; + border-radius: 10px; + margin-bottom: 10px; + border: 2px solid #f5f5f5; +} + +.contactImage { + width: 50px; + height: auto; + border-radius: 10px; +} + +.contactNameContainer { + display: flex; + flex-direction: column; + padding: 0px 10px; +} + +.grey { + color: grey; +} + +.bgGrey { + background-color: #f5f5f5; +} + +.bgWhite { + background-color: white; +} diff --git a/src/components/UserPortal/ContactCard/ContactCard.test.tsx b/src/components/UserPortal/ContactCard/ContactCard.test.tsx new file mode 100644 index 0000000000..cb7aaec882 --- /dev/null +++ b/src/components/UserPortal/ContactCard/ContactCard.test.tsx @@ -0,0 +1,116 @@ +import React from 'react'; +import { act, render, screen } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider } from 'react-i18next'; + +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import ContactCard from './ContactCard'; +import userEvent from '@testing-library/user-event'; + +const link = new StaticMockLink([], true); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +let props = { + id: '1', + firstName: 'Noble', + lastName: 'Mittal', + email: 'noble@mittal.com', + image: '', + selectedContact: '', + setSelectedContact: jest.fn(), + setSelectedContactName: jest.fn(), +}; + +describe('Testing ContactCard Component [User Portal]', () => { + test('Component should be rendered properly if person image is undefined', async () => { + render( + + + + + + + + + + ); + + await wait(); + }); + + test('Component should be rendered properly if person image is not undefined', async () => { + props = { + ...props, + image: 'personImage', + }; + + render( + + + + + + + + + + ); + + await wait(); + }); + + test('Contact gets selectected when component is clicked', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('contactContainer')); + + await wait(); + }); + + test('Component is rendered with background color grey if the contact is selected', async () => { + props = { + ...props, + selectedContact: '1', + }; + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('contactContainer')); + + await wait(); + }); +}); diff --git a/src/components/UserPortal/ContactCard/ContactCard.tsx b/src/components/UserPortal/ContactCard/ContactCard.tsx new file mode 100644 index 0000000000..8dd5352b43 --- /dev/null +++ b/src/components/UserPortal/ContactCard/ContactCard.tsx @@ -0,0 +1,53 @@ +import React from 'react'; +import styles from './ContactCard.module.css'; + +interface InterfaceContactCardProps { + id: string; + firstName: string; + lastName: string; + email: string; + image: string; + selectedContact: string; + setSelectedContact: React.Dispatch>; + setSelectedContactName: React.Dispatch>; +} + +function contactCard(props: InterfaceContactCardProps): JSX.Element { + const contactName = `${props.firstName} ${props.lastName}`; + const imageUrl = props.image + ? props.image + : `https://api.dicebear.com/5.x/initials/svg?seed=${contactName}`; + + const handleSelectedContactChange = (): void => { + props.setSelectedContact(props.id); + props.setSelectedContactName(contactName); + }; + + const [isSelected, setIsSelected] = React.useState( + props.selectedContact === props.id + ); + + React.useEffect(() => { + setIsSelected(props.selectedContact === props.id); + }, [props.selectedContact]); + + return ( + <> +
    + {contactName} +
    + {contactName} + {props.email} +
    +
    + + ); +} + +export default contactCard; diff --git a/src/components/UserPortal/DonationCard/DonationCard.module.css b/src/components/UserPortal/DonationCard/DonationCard.module.css new file mode 100644 index 0000000000..76fcaf3b0c --- /dev/null +++ b/src/components/UserPortal/DonationCard/DonationCard.module.css @@ -0,0 +1,22 @@ +.mainContainer { + width: 100%; + display: flex; + flex-direction: row; + padding: 10px; + cursor: pointer; + background-color: white; + border-radius: 10px; + box-shadow: 2px 2px 8px 0px #c8c8c8; + overflow: hidden; +} + +.personDetails { + display: flex; + flex-direction: column; + justify-content: center; +} + +.personImage { + border-radius: 50%; + margin-right: 20px; +} diff --git a/src/components/UserPortal/DonationCard/DonationCard.tsx b/src/components/UserPortal/DonationCard/DonationCard.tsx new file mode 100644 index 0000000000..436e3049b8 --- /dev/null +++ b/src/components/UserPortal/DonationCard/DonationCard.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import styles from './DonationCard.module.css'; + +interface InterfaceDonationCardProps { + id: string; + name: string; + amount: string; + userId: string; + payPalId: string; +} + +function donationCard(props: InterfaceDonationCardProps): JSX.Element { + return ( +
    +
    + {props.name} + Amount: {props.amount} + PayPal Id: {props.payPalId} +
    +
    + ); +} + +export default donationCard; diff --git a/src/components/UserPortal/EventCard/EventCard.module.css b/src/components/UserPortal/EventCard/EventCard.module.css new file mode 100644 index 0000000000..28278dd5a6 --- /dev/null +++ b/src/components/UserPortal/EventCard/EventCard.module.css @@ -0,0 +1,26 @@ +.mainContainer { + width: 100%; + display: flex; + flex-direction: column; + padding: 10px; + cursor: pointer; + background-color: white; + border-radius: 10px; + box-shadow: 2px 2px 8px 0px #c8c8c8; + overflow: hidden; +} + +.eventDetails { + gap: 5px; +} + +.personImage { + border-radius: 50%; + margin-right: 20px; +} + +.eventActions { + display: flex; + flex-direction: row; + justify-content: right; +} diff --git a/src/components/UserPortal/EventCard/EventCard.test.tsx b/src/components/UserPortal/EventCard/EventCard.test.tsx new file mode 100644 index 0000000000..8e5079767e --- /dev/null +++ b/src/components/UserPortal/EventCard/EventCard.test.tsx @@ -0,0 +1,185 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider } from 'react-i18next'; +import { BrowserRouter } from 'react-router-dom'; +import { ToastContainer } from 'react-toastify'; +import i18nForTest from 'utils/i18nForTest'; +import EventCard from './EventCard'; +import { render, screen, waitFor } from '@testing-library/react'; +import { REGISTER_EVENT } from 'GraphQl/Mutations/mutations'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import userEvent from '@testing-library/user-event'; + +const MOCKS = [ + { + request: { + query: REGISTER_EVENT, + variables: { eventId: '123' }, + }, + result: { + data: { + registerForEvent: [ + { + _id: '123', + }, + ], + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); + +afterEach(() => { + localStorage.clear(); +}); + +describe('Testing Event Card In User portal', () => { + const props = { + id: '123', + title: 'Test Event', + description: 'This is a test event', + location: 'Virtual', + startDate: '2023-04-13', + endDate: '2023-04-15', + isRegisterable: true, + isPublic: true, + endTime: '19:49:12Z', + startTime: '17:49:12Z', + recurring: false, + allDay: true, + creator: { + firstName: 'Joe', + lastName: 'David', + id: '123', + }, + registrants: [ + { + id: '234', + }, + ], + }; + + test('The card should be rendered properly, and all the details should be displayed correct', async () => { + const { queryByText } = render( + + + + + + + + + + + ); + await waitFor(() => expect(queryByText('Test Event')).toBeInTheDocument()); + await waitFor(() => + expect(queryByText('This is a test event')).toBeInTheDocument() + ); + await waitFor(() => expect(queryByText('Location')).toBeInTheDocument()); + await waitFor(() => expect(queryByText('Virtual')).toBeInTheDocument()); + await waitFor(() => expect(queryByText('Starts')).toBeInTheDocument()); + await waitFor(() => expect(queryByText('5:49:12 PM')).toBeInTheDocument()); + await waitFor(() => + expect(queryByText(`13 April '23`)).toBeInTheDocument() + ); + await waitFor(() => expect(queryByText('Ends')).toBeInTheDocument()); + await waitFor(() => expect(queryByText('7:49:12 PM')).toBeInTheDocument()); + await waitFor(() => + expect(queryByText(`15 April '23`)).toBeInTheDocument() + ); + await waitFor(() => expect(queryByText('Creator')).toBeInTheDocument()); + await waitFor(() => expect(queryByText('Joe David')).toBeInTheDocument()); + await waitFor(() => expect(queryByText('Register')).toBeInTheDocument()); + }); + + test('When the user is already registered', async () => { + localStorage.setItem('userId', '234'); + const { queryByText } = render( + + + + + + + + + + + ); + await waitFor(() => + expect(queryByText('Already registered')).toBeInTheDocument() + ); + }); + + test('Handle register should work properly', async () => { + localStorage.setItem('userId', '456'); + const { queryByText } = render( + + + + + + + + + + + ); + userEvent.click(screen.getByText('Register')); + await waitFor(() => + expect( + queryByText('Successfully registered for Test Event') + ).toBeInTheDocument() + ); + }); +}); + +describe('Event card when start and end time are not given', () => { + const props = { + id: '123', + title: 'Test Event', + description: 'This is a test event', + location: 'Virtual', + startDate: '2023-04-13', + endDate: '2023-04-15', + isRegisterable: true, + isPublic: true, + endTime: '', + startTime: '', + recurring: false, + allDay: true, + creator: { + firstName: 'Joe', + lastName: 'David', + id: '123', + }, + registrants: [ + { + id: '234', + }, + ], + }; + + test('Card is rendered correctly', async () => { + const { container } = render( + + + + + + + + + + + ); + + await waitFor(() => + expect(container.querySelector(':empty')).toBeInTheDocument() + ); + }); +}); diff --git a/src/components/UserPortal/EventCard/EventCard.tsx b/src/components/UserPortal/EventCard/EventCard.tsx new file mode 100644 index 0000000000..5aac562c06 --- /dev/null +++ b/src/components/UserPortal/EventCard/EventCard.tsx @@ -0,0 +1,124 @@ +import React from 'react'; +import styles from './EventCard.module.css'; +import CalendarMonthIcon from '@mui/icons-material/CalendarMonth'; +import dayjs from 'dayjs'; +import { Button } from 'react-bootstrap'; +import { useMutation } from '@apollo/client'; +import { toast } from 'react-toastify'; +import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; + +import { REGISTER_EVENT } from 'GraphQl/Mutations/mutations'; +import { useTranslation } from 'react-i18next'; + +interface InterfaceEventCardProps { + id: string; + title: string; + description: string; + location: string; + startDate: string; + endDate: string; + isRegisterable: boolean; + isPublic: boolean; + endTime: string; + startTime: string; + recurring: boolean; + allDay: boolean; + creator: { + firstName: string; + lastName: string; + id: string; + }; + registrants: { + id: string; + }[]; +} + +function eventCard(props: InterfaceEventCardProps): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'userEventCard', + }); + const userId = localStorage.getItem('userId'); + const creatorName = `${props.creator.firstName} ${props.creator.lastName}`; + const isInitiallyRegistered = props.registrants.some( + (registrant) => registrant.id === userId + ); + + const [registerEventMutation, { loading }] = useMutation(REGISTER_EVENT); + const [isRegistered, setIsRegistered] = React.useState(isInitiallyRegistered); + + const handleRegister = async (): Promise => { + if (!isRegistered) { + try { + const { data } = await registerEventMutation({ + variables: { + eventId: props.id, + }, + }); + /* istanbul ignore next */ + if (data) { + setIsRegistered(true); + toast.success(`Successfully registered for ${props.title}`); + } + } catch (error: any) { + /* istanbul ignore next */ + toast.error(error); + } + } + }; + + return ( +
    +
    +
    + {props.title} +
    +
    + +
    +
    + {props.description} + + {`${t('location')} `} + {props.location} + +
    + {`${t('starts')} `} + {props.startTime ? ( + {dayjs(`2015-03-04T${props.startTime}`).format('h:mm:ss A')} + ) : ( + <> + )} + {dayjs(props.startDate).format("D MMMM 'YY")} +
    +
    + {`${t('ends')} `} + {props.endTime ? ( + {dayjs(`2015-03-04T${props.endTime}`).format('h:mm:ss A')} + ) : ( + <> + )}{' '} + {dayjs(props.endDate).format("D MMMM 'YY")} +
    + + {`${t('creator')} `} + {creatorName} + + +
    + {loading ? ( + + ) : isRegistered ? ( + + ) : ( + + )} +
    +
    + ); +} + +export default eventCard; diff --git a/src/components/UserPortal/Login/Login.module.css b/src/components/UserPortal/Login/Login.module.css new file mode 100644 index 0000000000..98be9db02a --- /dev/null +++ b/src/components/UserPortal/Login/Login.module.css @@ -0,0 +1,29 @@ +.forgotPasswordContainer { + display: flex; + justify-content: flex-end; + flex-direction: row; + margin: 5px 0px; +} + +.forgotPasswordText { + color: black; + font-size: 12px; + margin: 2px 0px; +} + +.borderNone { + border: none; +} + +.colorWhite { + color: white; +} + +.colorPrimary { + background: #31bb6b; +} + +.colorPrimaryHover:hover { + background: #31bb6b; + border: none; +} diff --git a/src/components/UserPortal/Login/Login.test.tsx b/src/components/UserPortal/Login/Login.test.tsx new file mode 100644 index 0000000000..2ce9ebe9cc --- /dev/null +++ b/src/components/UserPortal/Login/Login.test.tsx @@ -0,0 +1,296 @@ +import type { SetStateAction } from 'react'; +import React from 'react'; +import { act, render, screen } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; + +import { LOGIN_MUTATION } from 'GraphQl/Mutations/mutations'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import Login from './Login'; +import { toast } from 'react-toastify'; + +const MOCKS = [ + { + request: { + query: LOGIN_MUTATION, + variables: { + email: 'johndoe@gmail.com', + password: 'johndoe', + }, + }, + result: { + data: { + login: { + user: { + _id: '1', + userType: 'ADMIN', + adminApproved: true, + }, + accessToken: 'accessToken', + refreshToken: 'refreshToken', + }, + }, + }, + }, + { + request: { + query: LOGIN_MUTATION, + variables: { + email: 'johndoe@gmail.com', + password: 'jdoe', + }, + }, + result: { + data: { + login: { + user: { + _id: '1', + userType: 'ADMIN', + adminApproved: false, + }, + accessToken: 'accessToken', + refreshToken: 'refreshToken', + }, + }, + }, + }, + { + request: { + query: LOGIN_MUTATION, + variables: { + email: 'invalid@gmail.com', + password: 'anything', + }, + }, + result: {}, + }, +]; + +const link = new StaticMockLink(MOCKS, true); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }, +})); + +const setCurrentMode: React.Dispatch> = jest.fn(); + +const props = { + setCurrentMode, +}; + +describe('Testing Login Component [User Portal]', () => { + test('Component should be rendered properly', async () => { + render( + + + + + + + + + + ); + + await wait(); + }); + + test('Expect the mode to be changed to Register', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('setRegisterBtn')); + + expect(setCurrentMode).toBeCalledWith('register'); + }); + + test('toast.error is triggered if the email input is empty.', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('loginBtn')); + + expect(toast.error).toBeCalledWith( + 'Please enter a valid email and password.' + ); + }); + + test('toast.error is triggered if the password input is empty.', async () => { + const formData = { + email: 'johndoe@gmail.com', + password: 'joe', + }; + + render( + + + + + + + + + + ); + + await wait(); + + userEvent.type( + screen.getByPlaceholderText(/Enter your email address/i), + formData.email + ); + userEvent.click(screen.getByTestId('loginBtn')); + + expect(toast.error).toBeCalledWith( + 'Please enter a valid email and password.' + ); + }); + + test('Incorrect password is entered.', async () => { + const formData = { + email: 'invalid@gmail.com', + password: 'anything', + }; + + render( + + + + + + + + + + ); + + await wait(); + + userEvent.type( + screen.getByPlaceholderText(/Enter your email address/i), + formData.email + ); + + userEvent.type( + screen.getByPlaceholderText(/Enter your password/i), + formData.password + ); + + userEvent.click(screen.getByTestId('loginBtn')); + + expect(toast.error).toBeCalled(); + + await wait(); + }); + + test('Login details are entered correctly.', async () => { + const formData = { + email: 'johndoe@gmail.com', + password: 'johndoe', + }; + + render( + + + + + + + + + + ); + + await wait(); + + userEvent.type( + screen.getByPlaceholderText(/Enter your email address/i), + formData.email + ); + + userEvent.type( + screen.getByPlaceholderText(/Enter your password/i), + formData.password + ); + + userEvent.click(screen.getByTestId('loginBtn')); + + await wait(); + }); + + test('Current user has not been approved by admin.', async () => { + const formData = { + email: 'johndoe@gmail.com', + password: 'jdoe', + }; + + render( + + + + + + + + + + ); + + await wait(); + + userEvent.type( + screen.getByPlaceholderText(/Enter your email address/i), + formData.email + ); + + userEvent.type( + screen.getByPlaceholderText(/Enter your password/i), + formData.password + ); + + userEvent.click(screen.getByTestId('loginBtn')); + + expect(toast.error).toBeCalled(); + + await wait(); + }); +}); diff --git a/src/components/UserPortal/Login/Login.tsx b/src/components/UserPortal/Login/Login.tsx new file mode 100644 index 0000000000..326d416c06 --- /dev/null +++ b/src/components/UserPortal/Login/Login.tsx @@ -0,0 +1,147 @@ +import type { ChangeEvent, SetStateAction } from 'react'; +import React from 'react'; +import { Button, Form, InputGroup } from 'react-bootstrap'; +import { useTranslation } from 'react-i18next'; +import EmailOutlinedIcon from '@mui/icons-material/EmailOutlined'; +import { LockOutlined } from '@mui/icons-material'; +import { Link } from 'react-router-dom'; +import { useMutation } from '@apollo/client'; +import { toast } from 'react-toastify'; + +import { LOGIN_MUTATION } from 'GraphQl/Mutations/mutations'; +import styles from './Login.module.css'; +import { errorHandler } from 'utils/errorHandler'; + +interface InterfaceLoginProps { + setCurrentMode: React.Dispatch>; +} + +export default function login(props: InterfaceLoginProps): JSX.Element { + const { t } = useTranslation('translation', { keyPrefix: 'userLogin' }); + + const { setCurrentMode } = props; + + const handleModeChangeToRegister = (): void => { + setCurrentMode('register'); + }; + + const [loginMutation] = useMutation(LOGIN_MUTATION); + + const [loginVariables, setLoginVariables] = React.useState({ + email: '', + password: '', + }); + + const handleLogin = async (): Promise => { + if (!(loginVariables.email && loginVariables.password)) { + toast.error(t('invalidDetailsMessage')); + } else { + try { + const { data } = await loginMutation({ + variables: { + email: loginVariables.email, + password: loginVariables.password, + }, + }); + + if (data) { + localStorage.setItem('token', data.login.accessToken); + localStorage.setItem('userId', data.login.user._id); + + navigator.clipboard.writeText(''); + /* istanbul ignore next */ + window.location.assign('/user/organizations'); + } else { + toast.warn(t('notAuthorised')); + } + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + } + }; + + /* istanbul ignore next */ + const handleEmailChange = (e: ChangeEvent): void => { + const email = e.target.value; + + setLoginVariables({ + email, + password: loginVariables.password, + }); + }; + + /* istanbul ignore next */ + const handlePasswordChange = (e: ChangeEvent): void => { + const password = e.target.value; + + setLoginVariables({ + email: loginVariables.email, + password, + }); + }; + + return ( + <> +

    {t('login')}

    +
    {t('loginIntoYourAccount')}
    + +
    +
    {t('emailAddress')}
    + + + + + + +
    {t('password')}
    + + + + + + +
    + +
    + + {t('forgotPassword')} + +
    + + +
    + + + ); +} diff --git a/src/components/UserPortal/OrganizationCard/OrganizationCard.module.css b/src/components/UserPortal/OrganizationCard/OrganizationCard.module.css new file mode 100644 index 0000000000..dd3cd90378 --- /dev/null +++ b/src/components/UserPortal/OrganizationCard/OrganizationCard.module.css @@ -0,0 +1,22 @@ +.mainContainer { + width: 100%; + display: flex; + flex-direction: row; + padding: 10px; + cursor: pointer; + background-color: white; + border-radius: 10px; + box-shadow: 2px 2px 8px 0px #c8c8c8; + overflow: hidden; +} + +.organizationDetails { + display: flex; + flex-direction: column; + justify-content: center; +} + +.removeDecoration { + text-decoration: none !important; + color: black; +} diff --git a/src/components/UserPortal/OrganizationCard/OrganizationCard.test.tsx b/src/components/UserPortal/OrganizationCard/OrganizationCard.test.tsx new file mode 100644 index 0000000000..fa4339e810 --- /dev/null +++ b/src/components/UserPortal/OrganizationCard/OrganizationCard.test.tsx @@ -0,0 +1,67 @@ +import React from 'react'; +import { act, render } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider } from 'react-i18next'; + +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import OrganizationCard from './OrganizationCard'; + +const link = new StaticMockLink([], true); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +let props = { + id: '1', + name: 'organizationName', + image: '', + description: 'organizationDescription', +}; + +describe('Testing OrganizationCard Component [User Portal]', () => { + test('Component should be rendered properly', async () => { + render( + + + + + + + + + + ); + + await wait(); + }); + + test('Component should be rendered properly if organization Image is not undefined', async () => { + props = { + ...props, + image: 'organizationImage', + }; + + render( + + + + + + + + + + ); + + await wait(); + }); +}); diff --git a/src/components/UserPortal/OrganizationCard/OrganizationCard.tsx b/src/components/UserPortal/OrganizationCard/OrganizationCard.tsx new file mode 100644 index 0000000000..427d29366d --- /dev/null +++ b/src/components/UserPortal/OrganizationCard/OrganizationCard.tsx @@ -0,0 +1,30 @@ +import React from 'react'; +import aboutImg from 'assets/images/defaultImg.png'; +import styles from './OrganizationCard.module.css'; +import { Link } from 'react-router-dom'; + +interface InterfaceOrganizationCardProps { + id: string; + name: string; + image: string; + description: string; +} + +function organizationCard(props: InterfaceOrganizationCardProps): JSX.Element { + const imageUrl = props.image ? props.image : aboutImg; + const redirectLink = `/user/organization/id=${props.id}`; + + return ( + +
    + +
    + {props.name} + {props.description} +
    +
    + + ); +} + +export default organizationCard; diff --git a/src/components/UserPortal/OrganizationNavbar/OrganizationNavbar.module.css b/src/components/UserPortal/OrganizationNavbar/OrganizationNavbar.module.css new file mode 100644 index 0000000000..761b389541 --- /dev/null +++ b/src/components/UserPortal/OrganizationNavbar/OrganizationNavbar.module.css @@ -0,0 +1,27 @@ +.talawaImage { + width: 40px; + height: auto; + margin-top: -5px; + border: 2px solid white; + margin-right: 10px; + background-color: white; + border-radius: 10px; +} + +.colorWhite { + color: white; +} + +.colorPrimary { + background: #31bb6b; +} + +.offcanvasContainer { + background-color: #31bb6b; + color: white; +} + +.link { + text-decoration: none !important; + color: inherit; +} diff --git a/src/components/UserPortal/OrganizationNavbar/OrganizationNavbar.test.tsx b/src/components/UserPortal/OrganizationNavbar/OrganizationNavbar.test.tsx new file mode 100644 index 0000000000..a5c1859ccd --- /dev/null +++ b/src/components/UserPortal/OrganizationNavbar/OrganizationNavbar.test.tsx @@ -0,0 +1,236 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { act, render, screen } from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import cookies from 'js-cookie'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import * as getOrganizationId from 'utils/getOrganizationId'; + +import OrganizationNavbar from './OrganizationNavbar'; +import userEvent from '@testing-library/user-event'; +import { USER_ORGANIZATION_CONNECTION } from 'GraphQl/Queries/Queries'; + +const MOCKS = [ + { + request: { + query: USER_ORGANIZATION_CONNECTION, + variables: { + id: '', + }, + }, + result: { + data: { + organizationsConnection: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + image: '', + name: 'anyOrganization1', + description: 'desc', + isPublic: true, + creator: { __typename: 'User', firstName: 'John', lastName: 'Doe' }, + }, + ], + }, + }, + }, +]; + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +const link = new StaticMockLink(MOCKS, true); + +const navbarProps = { + currentPage: 'home', +}; + +describe('Testing OrganizationNavbar Component [User Portal]', () => { + jest.mock('utils/getOrganizationId'); + + Object.defineProperty(window, 'matchMedia', { + writable: true, + value: jest.fn().mockImplementation((query) => ({ + matches: false, + media: query, + onchange: null, + addListener: jest.fn(), // Deprecated + removeListener: jest.fn(), // Deprecated + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn(), + })), + }); + + const getOrganizationIdSpy = jest + .spyOn(getOrganizationId, 'default') + .mockImplementation(() => { + return ''; + }); + + afterEach(async () => { + await act(async () => { + await i18nForTest.changeLanguage('en'); + }); + }); + + test('Component should be rendered properly', async () => { + render( + + + + + + + + + + ); + + await wait(); + + expect(getOrganizationIdSpy).toHaveBeenCalled(); + expect(screen.queryByText('anyOrganization1')).toBeInTheDocument(); + // Check if navigation links are rendered + expect(screen.getByText('Home')).toBeInTheDocument(); + expect(screen.getByText('People')).toBeInTheDocument(); + expect(screen.getByText('Events')).toBeInTheDocument(); + expect(screen.getByText('Donate')).toBeInTheDocument(); + // expect(screen.getByText('Chat')).toBeInTheDocument(); + }); + + test('The language is switched to English', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('languageIcon')); + + userEvent.click(screen.getByTestId('changeLanguageBtn0')); + + await wait(); + + expect(cookies.get('i18next')).toBe('en'); + // Check if navigation links are rendered + expect(screen.getByText('Home')).toBeInTheDocument(); + expect(screen.getByText('People')).toBeInTheDocument(); + expect(screen.getByText('Events')).toBeInTheDocument(); + expect(screen.getByText('Donate')).toBeInTheDocument(); + // expect(screen.getByText('Chat')).toBeInTheDocument(); + }); + + test('The language is switched to fr', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('languageIcon')); + + userEvent.click(screen.getByTestId('changeLanguageBtn1')); + + await wait(); + + expect(cookies.get('i18next')).toBe('fr'); + }); + + test('The language is switched to hi', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('languageIcon')); + + userEvent.click(screen.getByTestId('changeLanguageBtn2')); + + await wait(); + + expect(cookies.get('i18next')).toBe('hi'); + }); + + test('The language is switched to sp', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('languageIcon')); + + userEvent.click(screen.getByTestId('changeLanguageBtn3')); + + await wait(); + + expect(cookies.get('i18next')).toBe('sp'); + }); + + test('The language is switched to zh', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('languageIcon')); + + userEvent.click(screen.getByTestId('changeLanguageBtn4')); + + await wait(); + + expect(cookies.get('i18next')).toBe('zh'); + }); +}); diff --git a/src/components/UserPortal/OrganizationNavbar/OrganizationNavbar.tsx b/src/components/UserPortal/OrganizationNavbar/OrganizationNavbar.tsx new file mode 100644 index 0000000000..4bcaca4a8e --- /dev/null +++ b/src/components/UserPortal/OrganizationNavbar/OrganizationNavbar.tsx @@ -0,0 +1,252 @@ +import React from 'react'; +import styles from './OrganizationNavbar.module.css'; +import TalawaImage from 'assets/images/talawa-logo-200x200.png'; +import { Container, Dropdown, Nav, Navbar, Offcanvas } from 'react-bootstrap'; +import { languages } from 'utils/languages'; +import i18next from 'i18next'; +import cookies from 'js-cookie'; +import PermIdentityIcon from '@mui/icons-material/PermIdentity'; +import LanguageIcon from '@mui/icons-material/Language'; +import { useTranslation } from 'react-i18next'; +import { useQuery, useSubscription } from '@apollo/client'; +import { USER_ORGANIZATION_CONNECTION } from 'GraphQl/Queries/Queries'; +import getOrganizationId from 'utils/getOrganizationId'; +import type { DropDirection } from 'react-bootstrap/esm/DropdownContext'; +import { Link, useHistory } from 'react-router-dom'; +import { PLUGIN_SUBSCRIPTION } from 'GraphQl/Mutations/mutations'; +interface InterfaceNavbarProps { + currentPage: string | null; +} + +type Plugin = { + pluginName: string; + + alias: string; + link: string; + translated: string; + view: boolean; +}; +function organizationNavbar(props: InterfaceNavbarProps): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'userNavbar', + }); + + const history = useHistory(); + + const [organizationDetails, setOrganizationDetails]: any = React.useState({}); + // const dropDirection: DropDirection = screen.width > 767 ? 'start' : 'down'; + const dropDirection: DropDirection = 'start'; + + const organizationId = getOrganizationId(window.location.href); + + const { data } = useQuery(USER_ORGANIZATION_CONNECTION, { + variables: { id: organizationId }, + }); + + const [currentLanguageCode, setCurrentLanguageCode] = React.useState( + /* istanbul ignore next */ + cookies.get('i18next') || 'en' + ); + + /* istanbul ignore next */ + const handleLogout = (): void => { + localStorage.clear(); + window.location.replace('/user'); + }; + + const userName = localStorage.getItem('name'); + React.useEffect(() => { + if (data) { + setOrganizationDetails(data.organizationsConnection[0]); + } + }, [data]); + + const homeLink = `/user/organization/id=${organizationId}`; + let plugins: Plugin[] = [ + { + pluginName: 'People', + alias: 'people', + link: `/user/people/id=${organizationId}`, + translated: t('people'), + view: true, + }, + { + pluginName: 'Events', + alias: 'events', + link: `/user/events/id=${organizationId}`, + translated: t('events'), + view: true, + }, + { + pluginName: 'Donation', + alias: 'donate', + link: `/user/donate/id=${organizationId}`, + translated: t('donate'), + view: true, + }, + // { + // pluginName: 'Chats', + // alias: 'chat', + // link: `/user/chat/id=${organizationId}`, + // translated: t('chat'), + // view: true, + // }, + ]; + if (localStorage.getItem('talawaPlugins')) { + const talawaPlugins: string = localStorage.getItem('talawaPlugins') || '{}'; + plugins = JSON.parse(talawaPlugins); + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { data: updatedPluginData, loading: _loadingSub } = useSubscription( + PLUGIN_SUBSCRIPTION + // { variables: { } } + ); + function getPluginIndex(pluginName: string, pluginsArray: Plugin[]): number { + for (let i = 0; i < pluginsArray.length; i++) { + if (pluginsArray[i].pluginName === pluginName) { + return i; // Return the index of the matching object + } + } + return -1; // Return -1 if not found + } + + if (updatedPluginData != undefined) { + const pluginName = updatedPluginData.onPluginUpdate.pluginName; + const uninstalledOrgs = updatedPluginData.onPluginUpdate.uninstalledOrgs; + const pluginIndexToRemove = getPluginIndex(pluginName, plugins); + if (uninstalledOrgs.includes(organizationId)) { + if (pluginIndexToRemove != -1) { + plugins[pluginIndexToRemove].view = false; + localStorage.setItem('talawaPlugins', JSON.stringify(plugins)); + console.log(`Plugin ${pluginName} has been removed.`); + } else { + console.log(`Plugin ${pluginName} is not present.`); + } + } else { + if (pluginIndexToRemove != -1) { + plugins[pluginIndexToRemove].view = true; + localStorage.setItem('talawaPlugins', JSON.stringify(plugins)); + } + } + } + return ( + + + + Talawa Branding + {organizationDetails.name} + + + + + Talawa + + + + + + + + + + {languages.map((language, index: number) => ( + => { + setCurrentLanguageCode(language.code); + await i18next.changeLanguage(language.code); + }} + disabled={currentLanguageCode === language.code} + data-testid={`changeLanguageBtn${index}`} + > + {' '} + {language.name} + + ))} + + + + + + + + + + {userName} + + + + {t('settings')} + + + + + {t('myTasks')} + + + + {t('logout')} + + + + + + + + + ); +} + +export default organizationNavbar; diff --git a/src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.module.css b/src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.module.css new file mode 100644 index 0000000000..cf8bc84dda --- /dev/null +++ b/src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.module.css @@ -0,0 +1,76 @@ +.mainContainer { + display: flex; + overflow: auto; + flex-direction: column; + /* align-items: center; */ + padding: 20px; + /* padding-top: 20px; */ + width: 250px; + flex-grow: 1; + background-color: var(--bs-white); +} + +@media screen and (max-width: 900px) { + .mainContainer { + display: none; + } +} + +.userDetails { + display: flex; + flex-direction: column; + align-items: center; + padding-top: 20px; +} + +.boxShadow { + box-shadow: 4px 4px 8px 4px #c8c8c8; +} + +.organizationsConatiner { + width: 100%; + padding-top: 50px; +} + +.heading { + padding: 10px 0px; +} + +.orgName { + font-size: 16px; + font-weight: 600; + margin-top: 4px; + margin-left: 5px; +} + +.alignRight { + width: 100%; + text-align: right; + padding: 5px; +} + +.link { + text-decoration: none !important; + color: black; +} + +.rounded { + border-radius: 10px !important; +} + +.colorLight { + background-color: #f5f5f5; +} + +.marginTop { + margin-top: -2px; +} + +.eventDetails { + font-size: small; + gap: 5px; +} + +.memberImage { + border-radius: 50%; +} diff --git a/src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.test.tsx b/src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.test.tsx new file mode 100644 index 0000000000..ccfe7e4d31 --- /dev/null +++ b/src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.test.tsx @@ -0,0 +1,174 @@ +import React from 'react'; +import { act, render, screen } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider } from 'react-i18next'; + +import { + ORGANIZATIONS_MEMBER_CONNECTION_LIST, + ORGANIZATION_EVENT_CONNECTION_LIST, +} from 'GraphQl/Queries/Queries'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import OrganizationSidebar from './OrganizationSidebar'; +import * as getOrganizationId from 'utils/getOrganizationId'; + +const MOCKS = [ + { + request: { + query: ORGANIZATION_EVENT_CONNECTION_LIST, + variables: { + organization_id: 'events', + first: 3, + skip: 0, + }, + }, + result: { + data: { + eventsByOrganizationConnection: [ + { + _id: 1, + title: 'Event', + description: 'Event Test', + startDate: '', + endDate: '', + location: 'New Delhi', + startTime: '02:00', + endTime: '06:00', + allDay: false, + recurring: false, + isPublic: true, + isRegisterable: true, + }, + ], + }, + }, + }, + { + request: { + query: ORGANIZATIONS_MEMBER_CONNECTION_LIST, + variables: { + orgId: 'members', + first: 3, + skip: 0, + }, + }, + result: { + data: { + organizationsMemberConnection: { + edges: [ + { + _id: '64001660a711c62d5b4076a2', + firstName: 'Noble', + lastName: 'Mittal', + image: null, + email: 'noble@gmail.com', + createdAt: '2023-03-02T03:22:08.101Z', + }, + { + _id: '64001660a711c62d5b4076a3', + firstName: 'Noble', + lastName: 'Mittal', + image: 'mockImage', + email: 'noble@gmail.com', + createdAt: '2023-03-02T03:22:08.101Z', + }, + ], + }, + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Testing OrganizationSidebar Component [User Portal]', () => { + jest.mock('utils/getOrganizationId'); + + test('Component should be rendered properly when members and events list is empty', async () => { + const getOrganizationIdSpy = jest + .spyOn(getOrganizationId, 'default') + .mockImplementation(() => { + return ''; + }); + + render( + + + + + + + + + + ); + + await wait(); + + expect(getOrganizationIdSpy).toHaveBeenCalled(); + expect(screen.queryByText('No Members to show')).toBeInTheDocument(); + expect(screen.queryByText('No Events to show')).toBeInTheDocument(); + }); + + test('Component should be rendered properly when events list is not empty', async () => { + const getOrganizationIdSpy = jest + .spyOn(getOrganizationId, 'default') + .mockImplementation(() => { + return 'events'; + }); + + render( + + + + + + + + + + ); + + await wait(); + expect(getOrganizationIdSpy).toHaveBeenCalled(); + expect(screen.queryByText('No Members to show')).toBeInTheDocument(); + expect(screen.queryByText('No Events to show')).not.toBeInTheDocument(); + expect(screen.queryByText('Event')).toBeInTheDocument(); + }); + + test('Component should be rendered properly when members list is not empty', async () => { + const getOrganizationIdSpy = jest + .spyOn(getOrganizationId, 'default') + .mockImplementation(() => { + return 'members'; + }); + + render( + + + + + + + + + + ); + + await wait(); + expect(getOrganizationIdSpy).toHaveBeenCalled(); + expect(screen.queryByText('No Members to show')).not.toBeInTheDocument(); + expect(screen.queryByText('No Events to show')).toBeInTheDocument(); + }); +}); diff --git a/src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.tsx b/src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.tsx new file mode 100644 index 0000000000..570ea9de85 --- /dev/null +++ b/src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.tsx @@ -0,0 +1,157 @@ +import React, { useEffect } from 'react'; +import { ListGroup } from 'react-bootstrap'; +import AboutImg from 'assets/images/defaultImg.png'; +import styles from './OrganizationSidebar.module.css'; +import ChevronRightIcon from '@mui/icons-material/ChevronRight'; +import { Link } from 'react-router-dom'; +import getOrganizationId from 'utils/getOrganizationId'; +import { useQuery } from '@apollo/client'; +import { + ORGANIZATIONS_MEMBER_CONNECTION_LIST, + ORGANIZATION_EVENT_CONNECTION_LIST, +} from 'GraphQl/Queries/Queries'; +import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; +import CalendarMonthIcon from '@mui/icons-material/CalendarMonth'; +import dayjs from 'dayjs'; +import { useTranslation } from 'react-i18next'; + +export default function organizationSidebar(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'organizationSidebar', + }); + + const organizationId = getOrganizationId(window.location.href); + const [members, setMembers]: any = React.useState([]); + const [events, setEvents]: any = React.useState([]); + const eventsLink = `/user/events/id=${organizationId}`; + const peopleLink = `/user/people/id=${organizationId}`; + + const { data: memberData, loading: memberLoading } = useQuery( + ORGANIZATIONS_MEMBER_CONNECTION_LIST, + { + variables: { + orgId: organizationId, + first: 3, + skip: 0, + }, + } + ); + + const { data: eventsData, loading: eventsLoading } = useQuery( + ORGANIZATION_EVENT_CONNECTION_LIST, + { + variables: { + organization_id: organizationId, + first: 3, + skip: 0, + }, + } + ); + + /* istanbul ignore next */ + useEffect(() => { + if (memberData) { + setMembers(memberData.organizationsMemberConnection.edges); + } + }, [memberData]); + + /* istanbul ignore next */ + useEffect(() => { + if (eventsData) { + setEvents(eventsData.eventsByOrganizationConnection); + } + }, [eventsData]); + + return ( +
    +
    + {t('members')} +
    + {memberLoading ? ( +
    + Loading... +
    + ) : ( + + {members.length ? ( + members.map((member: any, index: React.Key | null | undefined) => { + const memberName = `${member.firstName} ${member.lastName}`; + return ( + +
    + +
    {memberName}
    +
    +
    + ); + }) + ) : ( +
    {t('noMembers')}
    + )} +
    + )} + +
    + + {t('viewAll')} + + +
    +
    + {t('events')} +
    + {eventsLoading ? ( +
    + Loading... +
    + ) : ( + + {events.length ? ( + events.map((event: any, index: React.Key | null | undefined) => { + return ( + +
    +
    +
    {event.title}
    +
    + +
    +
    +
    + Starts{' '} + {dayjs(event.startDate).format("D MMMM 'YY")} +
    +
    + Ends {dayjs(event.endDate).format("D MMMM 'YY")} +
    +
    +
    + ); + }) + ) : ( +
    {t('noEvents')}
    + )} +
    + )} +
    + + {t('viewAll')} + + +
    +
    + ); +} diff --git a/src/components/UserPortal/PeopleCard/PeopleCard.module.css b/src/components/UserPortal/PeopleCard/PeopleCard.module.css new file mode 100644 index 0000000000..76fcaf3b0c --- /dev/null +++ b/src/components/UserPortal/PeopleCard/PeopleCard.module.css @@ -0,0 +1,22 @@ +.mainContainer { + width: 100%; + display: flex; + flex-direction: row; + padding: 10px; + cursor: pointer; + background-color: white; + border-radius: 10px; + box-shadow: 2px 2px 8px 0px #c8c8c8; + overflow: hidden; +} + +.personDetails { + display: flex; + flex-direction: column; + justify-content: center; +} + +.personImage { + border-radius: 50%; + margin-right: 20px; +} diff --git a/src/components/UserPortal/PeopleCard/PeopleCard.test.tsx b/src/components/UserPortal/PeopleCard/PeopleCard.test.tsx new file mode 100644 index 0000000000..d0bad51b11 --- /dev/null +++ b/src/components/UserPortal/PeopleCard/PeopleCard.test.tsx @@ -0,0 +1,67 @@ +import React from 'react'; +import { act, render } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider } from 'react-i18next'; + +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import PeopleCard from './PeopleCard'; + +const link = new StaticMockLink([], true); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +let props = { + id: '1', + name: 'First Last', + image: '', + email: 'first@last.com', +}; + +describe('Testing PeopleCard Component [User Portal]', () => { + test('Component should be rendered properly', async () => { + render( + + + + + + + + + + ); + + await wait(); + }); + + test('Component should be rendered properly if person image is not undefined', async () => { + props = { + ...props, + image: 'personImage', + }; + + render( + + + + + + + + + + ); + + await wait(); + }); +}); diff --git a/src/components/UserPortal/PeopleCard/PeopleCard.tsx b/src/components/UserPortal/PeopleCard/PeopleCard.tsx new file mode 100644 index 0000000000..578cf31194 --- /dev/null +++ b/src/components/UserPortal/PeopleCard/PeopleCard.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import aboutImg from 'assets/images/defaultImg.png'; +import styles from './PeopleCard.module.css'; + +interface InterfaceOrganizationCardProps { + id: string; + name: string; + image: string; + email: string; +} + +function peopleCard(props: InterfaceOrganizationCardProps): JSX.Element { + const imageUrl = props.image ? props.image : aboutImg; + + return ( +
    + +
    + {props.name} + {props.email} +
    +
    + ); +} + +export default peopleCard; diff --git a/src/components/UserPortal/PostCard/PostCard.module.css b/src/components/UserPortal/PostCard/PostCard.module.css new file mode 100644 index 0000000000..56158473f9 --- /dev/null +++ b/src/components/UserPortal/PostCard/PostCard.module.css @@ -0,0 +1,55 @@ +.cardActions { + display: flex; + flex-direction: row; + align-items: center; + gap: 1px; +} + +.cardActionBtn { + background-color: rgba(0, 0, 0, 0); + border: none; + color: black; +} + +.cardActionBtn:hover { + background-color: ghostwhite; + border: none; + color: black !important; +} + +.imageContainer { + max-width: 100%; +} + +.cardHeader { + display: flex; + flex-direction: row; + gap: 10px; + align-items: center; +} + +.creatorNameModal { + display: flex; + flex-direction: row; + gap: 5px; + align-items: center; + margin-bottom: 10px; +} + +.modalActions { + display: flex; + flex-direction: row; + align-items: center; + gap: 1px; + margin: 5px 0px; +} + +.textModal { + margin-top: 10px; +} + +.colorPrimary { + background: #31bb6b; + color: white; + cursor: pointer; +} diff --git a/src/components/UserPortal/PostCard/PostCard.test.tsx b/src/components/UserPortal/PostCard/PostCard.test.tsx new file mode 100644 index 0000000000..acd6176b02 --- /dev/null +++ b/src/components/UserPortal/PostCard/PostCard.test.tsx @@ -0,0 +1,419 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { act, render, screen } from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; + +import PostCard from './PostCard'; +import userEvent from '@testing-library/user-event'; +import { + CREATE_COMMENT_POST, + LIKE_POST, + UNLIKE_POST, +} from 'GraphQl/Mutations/mutations'; + +const MOCKS = [ + { + request: { + query: LIKE_POST, + variables: { + postId: '', + }, + result: { + data: { + likePost: { + _id: '', + }, + }, + }, + }, + }, + { + request: { + query: UNLIKE_POST, + variables: { + post: '', + }, + result: { + data: { + unlikePost: { + _id: '', + }, + }, + }, + }, + }, + { + request: { + query: CREATE_COMMENT_POST, + variables: { + postId: '1', + comment: 'testComment', + }, + result: { + data: { + createComment: { + _id: '64ef885bca85de60ebe0f304', + creator: { + _id: '63d6064458fce20ee25c3bf7', + firstName: 'Noble', + lastName: 'Mittal', + email: 'test@gmail.com', + __typename: 'User', + }, + likeCount: 0, + likedBy: [], + text: 'testComment', + __typename: 'Comment', + }, + }, + }, + }, + }, +]; + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +const link = new StaticMockLink(MOCKS, true); + +describe('Testing PostCard Component [User Portal]', () => { + test('Component should be rendered properly', async () => { + const cardProps = { + id: '', + creator: { + firstName: 'test', + lastName: 'user', + email: 'test@user.com', + id: '1', + }, + image: '', + video: '', + text: 'This is post test text', + title: 'This is post test title', + likeCount: 1, + commentCount: 1, + comments: [ + { + _id: '64eb13beca85de60ebe0ed0e', + creator: { + _id: '63d6064458fce20ee25c3bf7', + firstName: 'Noble', + lastName: 'Mittal', + email: 'test@gmail.com', + __typename: 'User', + }, + likeCount: 0, + likedBy: [], + text: 'First comment from Talawa user portal.', + __typename: 'Comment', + }, + ], + likedBy: [ + { + firstName: '', + lastName: '', + id: '2', + }, + ], + }; + + render( + + + + + + + + + + ); + + await wait(); + }); + + test('Component should be rendered properly if user has liked the post', async () => { + const beforeUserId = localStorage.getItem('userId'); + localStorage.setItem('userId', '2'); + + const cardProps = { + id: '', + creator: { + firstName: 'test', + lastName: 'user', + email: 'test@user.com', + id: '1', + }, + image: '', + video: '', + text: 'This is post test text', + title: 'This is post test title', + likeCount: 1, + commentCount: 0, + comments: [], + likedBy: [ + { + firstName: 'test', + lastName: 'user', + id: '2', + }, + ], + }; + + render( + + + + + + + + + + ); + + await wait(); + + if (beforeUserId) { + localStorage.setItem('userId', beforeUserId); + } + }); + + test('Component should be rendered properly if user unlikes a post', async () => { + const beforeUserId = localStorage.getItem('userId'); + localStorage.setItem('userId', '2'); + + const cardProps = { + id: '', + creator: { + firstName: 'test', + lastName: 'user', + email: 'test@user.com', + id: '1', + }, + image: '', + video: '', + text: 'This is post test text', + title: 'This is post test title', + likeCount: 1, + commentCount: 0, + comments: [], + likedBy: [ + { + firstName: 'test', + lastName: 'user', + id: '2', + }, + ], + }; + + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('likePostBtn')); + + if (beforeUserId) { + localStorage.setItem('userId', beforeUserId); + } + }); + + test('Component should be rendered properly if user likes a post', async () => { + const beforeUserId = localStorage.getItem('userId'); + localStorage.setItem('userId', '2'); + + const cardProps = { + id: '', + creator: { + firstName: 'test', + lastName: 'user', + email: 'test@user.com', + id: '1', + }, + image: '', + video: '', + text: 'This is post test text', + title: 'This is post test title', + likeCount: 1, + commentCount: 0, + comments: [], + likedBy: [ + { + firstName: 'test', + lastName: 'user', + id: '1', + }, + ], + }; + + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('likePostBtn')); + + if (beforeUserId) { + localStorage.setItem('userId', beforeUserId); + } + }); + + test('Component should be rendered properly if post image is defined', async () => { + const cardProps = { + id: '', + creator: { + firstName: 'test', + lastName: 'user', + email: 'test@user.com', + id: '1', + }, + image: 'testImage', + video: '', + text: 'This is post test text', + title: 'This is post test title', + likeCount: 1, + commentCount: 0, + comments: [], + likedBy: [ + { + firstName: 'test', + lastName: 'user', + id: '1', + }, + ], + }; + + render( + + + + + + + + + + ); + + await wait(); + }); + + test('Comment is created successfully after create comment button is clicked.', async () => { + const cardProps = { + id: '1', + creator: { + firstName: 'test', + lastName: 'user', + email: 'test@user.com', + id: '1', + }, + image: 'testImage', + video: '', + text: 'This is post test text', + title: 'This is post test title', + likeCount: 1, + commentCount: 0, + comments: [], + likedBy: [ + { + firstName: 'test', + lastName: 'user', + id: '1', + }, + ], + }; + + render( + + + + + + + + + + ); + + const randomComment = 'testComment'; + + userEvent.click(screen.getByTestId('showCommentsBtn')); + + userEvent.type(screen.getByTestId('commentInput'), randomComment); + userEvent.click(screen.getByTestId('createCommentBtn')); + + await wait(); + }); + + test('Comment modal pops when show comments button is clicked.', async () => { + const cardProps = { + id: '', + creator: { + firstName: 'test', + lastName: 'user', + email: 'test@user.com', + id: '1', + }, + image: 'testImage', + video: '', + text: 'This is post test text', + title: 'This is post test title', + likeCount: 1, + commentCount: 0, + comments: [], + likedBy: [ + { + firstName: 'test', + lastName: 'user', + id: '1', + }, + ], + }; + + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('showCommentsBtn')); + expect(screen.findAllByText('Comments')).not.toBeNull(); + }); +}); diff --git a/src/components/UserPortal/PostCard/PostCard.tsx b/src/components/UserPortal/PostCard/PostCard.tsx new file mode 100644 index 0000000000..0374858f23 --- /dev/null +++ b/src/components/UserPortal/PostCard/PostCard.tsx @@ -0,0 +1,291 @@ +import React from 'react'; +import { Button, Card, Form, InputGroup, Modal } from 'react-bootstrap'; +import ThumbUpIcon from '@mui/icons-material/ThumbUp'; +import CommentIcon from '@mui/icons-material/Comment'; +import AccountCircleIcon from '@mui/icons-material/AccountCircle'; +import styles from './PostCard.module.css'; +import { useMutation } from '@apollo/client'; +import { + CREATE_COMMENT_POST, + LIKE_POST, + UNLIKE_POST, +} from 'GraphQl/Mutations/mutations'; +import { toast } from 'react-toastify'; +import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; +import ThumbUpOffAltIcon from '@mui/icons-material/ThumbUpOffAlt'; +import { useTranslation } from 'react-i18next'; +import SendIcon from '@mui/icons-material/Send'; +import { errorHandler } from 'utils/errorHandler'; +import CommentCard from '../CommentCard/CommentCard'; + +interface InterfacePostCardProps { + id: string; + creator: { + firstName: string; + lastName: string; + email: string; + id: string; + }; + image: string; + video: string; + text: string; + title: string; + likeCount: number; + commentCount: number; + comments: { + creator: { + _id: string; + firstName: string; + lastName: string; + email: string; + }; + likeCount: number; + likedBy: { + id: string; + }[]; + text: string; + }[]; + likedBy: { + firstName: string; + lastName: string; + id: string; + }[]; +} + +interface InterfaceCommentCardProps { + id: string; + creator: { + id: string; + firstName: string; + lastName: string; + email: string; + }; + likeCount: number; + likedBy: { + id: string; + }[]; + text: string; +} + +export default function postCard(props: InterfacePostCardProps): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'postCard', + }); + + const userId = localStorage.getItem('userId'); + const likedByUser = props.likedBy.some((likedBy) => likedBy.id === userId); + const [comments, setComments] = React.useState(props.comments); + const [numComments, setNumComments] = React.useState(props.commentCount); + + const [likes, setLikes] = React.useState(props.likeCount); + const [isLikedByUser, setIsLikedByUser] = React.useState(likedByUser); + const [showComments, setShowComments] = React.useState(false); + const [commentInput, setCommentInput] = React.useState(''); + + const postCreator = `${props.creator.firstName} ${props.creator.lastName}`; + + const [likePost, { loading: likeLoading }] = useMutation(LIKE_POST); + const [unLikePost, { loading: unlikeLoading }] = useMutation(UNLIKE_POST); + const [create, { loading: commentLoading }] = + useMutation(CREATE_COMMENT_POST); + + const toggleCommentsModal = (): void => setShowComments(!showComments); + + const handleToggleLike = async (): Promise => { + if (isLikedByUser) { + try { + const { data } = await unLikePost({ + variables: { + postId: props.id, + }, + }); + /* istanbul ignore next */ + if (data) { + setLikes((likes) => likes - 1); + setIsLikedByUser(false); + } + } catch (error: any) { + /* istanbul ignore next */ + toast.error(error); + } + } else { + try { + const { data } = await likePost({ + variables: { + postId: props.id, + }, + }); + /* istanbul ignore next */ + if (data) { + setLikes((likes) => likes + 1); + setIsLikedByUser(true); + } + } catch (error: any) { + /* istanbul ignore next */ + toast.error(error); + } + } + }; + + const handleCommentInput = ( + event: React.ChangeEvent + ): void => { + const comment = event.target.value; + setCommentInput(comment); + }; + + const createComment = async (): Promise => { + try { + const { data: createEventData } = await create({ + variables: { + postId: props.id, + comment: commentInput, + }, + }); + + /* istanbul ignore next */ + if (createEventData) { + setCommentInput(''); + setNumComments((numComments) => numComments + 1); + + const newComment: any = { + id: createEventData.createComment._id, + creator: { + id: createEventData.createComment.creator.id, + firstName: createEventData.createComment.creator.firstName, + lastName: createEventData.createComment.creator.lastName, + email: createEventData.createComment.creator.email, + }, + likeCount: createEventData.createComment.likeCount, + likedBy: createEventData.createComment.likedBy, + text: createEventData.createComment.text, + }; + + setComments([...comments, newComment]); + } + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + + return ( + <> + + +
    + + {postCreator} +
    +
    + + {props.title} + {props.text} + {props.image && ( + + )} + + +
    + + {likes} + {` ${t('likes')}`} + + {numComments} + {` ${t('comments')}`} +
    +
    +
    + + +
    + + {postCreator} +
    + {props.image && ( + + )} +
    {props.text}
    +
    + + {likes} + {` ${t('likes')}`} +
    +

    Comments

    + {numComments ? ( + comments.map((comment: any, index: any) => { + const cardProps: InterfaceCommentCardProps = { + id: comment.id, + creator: { + id: comment.creator.id, + firstName: comment.creator.firstName, + lastName: comment.creator.lastName, + email: comment.creator.email, + }, + likeCount: comment.likeCount, + likedBy: comment.likedBy, + text: comment.text, + }; + + return ; + }) + ) : ( + <>No comments to show. + )} +
    + + + + {commentLoading ? ( + + ) : ( + + )} + + +
    +
    + + ); +} diff --git a/src/components/UserPortal/PromotedPost/PromotedPost.module.css b/src/components/UserPortal/PromotedPost/PromotedPost.module.css new file mode 100644 index 0000000000..cdc13e621b --- /dev/null +++ b/src/components/UserPortal/PromotedPost/PromotedPost.module.css @@ -0,0 +1,56 @@ +.cardActions { + display: flex; + flex-direction: row; + align-items: center; + gap: 1px; +} + +.cardActionBtn { + background-color: rgba(0, 0, 0, 0); + border: none; + color: black; +} + +.cardActionBtn:hover { + background-color: ghostwhite; + border: none; + color: black !important; +} + +.imageContainer { + max-width: 100%; +} + +.cardHeader { + display: flex; + flex-direction: row; + gap: 10px; + align-items: center; + color: #50c878; +} + +.creatorNameModal { + display: flex; + flex-direction: row; + gap: 5px; + align-items: center; + margin-bottom: 10px; +} + +.modalActions { + display: flex; + flex-direction: row; + align-items: center; + gap: 1px; + margin: 5px 0px; +} + +.textModal { + margin-top: 10px; +} + +.colorPrimary { + background: #31bb6b; + color: white; + cursor: pointer; +} diff --git a/src/components/UserPortal/PromotedPost/PromotedPost.test.tsx b/src/components/UserPortal/PromotedPost/PromotedPost.test.tsx new file mode 100644 index 0000000000..6b68509a51 --- /dev/null +++ b/src/components/UserPortal/PromotedPost/PromotedPost.test.tsx @@ -0,0 +1,127 @@ +import React from 'react'; +import { act, render, waitFor } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider } from 'react-i18next'; + +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import PromotedPost from './PromotedPost'; + +const link = new StaticMockLink([], true); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +let props = { + id: '1', + image: '', + title: 'Test Post', +}; + +describe('Testing PromotedPost Test', () => { + test('Component should be rendered properly', async () => { + render( + + + + + + + + + + ); + + await wait(); + }); + + test('Component should be rendered properly if prop image is not undefined', async () => { + props = { + ...props, + image: 'promotedPostImage', + }; + + render( + + + + + + + + + + ); + + await wait(); + }); +}); + +test('Component should display the icon correctly', async () => { + const { queryByTestId } = render( + + + + + + + + + + ); + + await waitFor(() => { + const icon = queryByTestId('StarPurple500Icon'); + expect(icon).toBeInTheDocument(); + }); +}); + +test('Component should display the text correctly', async () => { + const { queryAllByText } = render( + + + + + + + + + + ); + + await waitFor(() => { + const title = queryAllByText('Test Post') as HTMLElement[]; + expect(title[0]).toBeInTheDocument(); + }); +}); + +test('Component should display the image correctly', async () => { + props = { + ...props, + image: 'promotedPostImage', + }; + const { queryByRole } = render( + + + + + + + + + + ); + + await waitFor(() => { + const image = queryByRole('img'); + expect(image).toHaveAttribute('src', 'promotedPostImage'); + }); +}); diff --git a/src/components/UserPortal/PromotedPost/PromotedPost.tsx b/src/components/UserPortal/PromotedPost/PromotedPost.tsx new file mode 100644 index 0000000000..81f3aa0e7e --- /dev/null +++ b/src/components/UserPortal/PromotedPost/PromotedPost.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import { Card } from 'react-bootstrap'; +import styles from './PromotedPost.module.css'; +import StarPurple500Icon from '@mui/icons-material/StarPurple500'; +interface InterfacePostCardProps { + id: string; + image: string; + title: string; +} +export default function promotedPost( + props: InterfacePostCardProps +): JSX.Element { + return ( + <> + + +
    + + {'Promoted Content'} +
    +
    + + {props.title} + {props.title} + {props.image && ( + + )} + +
    + + ); +} diff --git a/src/components/UserPortal/Register/Register.module.css b/src/components/UserPortal/Register/Register.module.css new file mode 100644 index 0000000000..1fc2a34af2 --- /dev/null +++ b/src/components/UserPortal/Register/Register.module.css @@ -0,0 +1,15 @@ +.loginText { + cursor: pointer; +} + +.borderNone { + border: none; +} + +.colorWhite { + color: white; +} + +.colorPrimary { + background: #31bb6b; +} diff --git a/src/components/UserPortal/Register/Register.test.tsx b/src/components/UserPortal/Register/Register.test.tsx new file mode 100644 index 0000000000..8020ac03fa --- /dev/null +++ b/src/components/UserPortal/Register/Register.test.tsx @@ -0,0 +1,267 @@ +import type { SetStateAction } from 'react'; +import React from 'react'; +import { act, render, screen } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; +import { SIGNUP_MUTATION } from 'GraphQl/Mutations/mutations'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import Register from './Register'; +import { toast } from 'react-toastify'; + +const MOCKS = [ + { + request: { + query: SIGNUP_MUTATION, + variables: { + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@gmail.com', + password: 'johnDoe', + }, + }, + result: { + data: { + signUp: { + user: { + _id: '1', + }, + accessToken: 'accessToken', + refreshToken: 'refreshToken', + }, + }, + }, + }, +]; + +const formData = { + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@gmail.com', + password: 'johnDoe', + confirmPassword: 'johnDoe', +}; + +const link = new StaticMockLink(MOCKS, true); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }, +})); + +const setCurrentMode: React.Dispatch> = jest.fn(); + +const props = { + setCurrentMode, +}; + +describe('Testing Register Component [User Portal]', () => { + test('Component should be rendered properly', async () => { + render( + + + + + + + + + + ); + + await wait(); + }); + + test('Expect the mode to be changed to Login', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('setLoginBtn')); + + expect(setCurrentMode).toBeCalledWith('login'); + }); + + test('Expect toast.error to be called if email input is empty', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('registerBtn')); + + expect(toast.error).toBeCalledWith('Please enter valid details.'); + }); + + test('Expect toast.error to be called if password input is empty', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.type(screen.getByTestId('emailInput'), formData.email); + userEvent.click(screen.getByTestId('registerBtn')); + + expect(toast.error).toBeCalledWith('Please enter valid details.'); + }); + + test('Expect toast.error to be called if first name input is empty', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.type(screen.getByTestId('passwordInput'), formData.password); + + userEvent.type(screen.getByTestId('emailInput'), formData.email); + + userEvent.click(screen.getByTestId('registerBtn')); + + expect(toast.error).toBeCalledWith('Please enter valid details.'); + }); + + test('Expect toast.error to be called if last name input is empty', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.type(screen.getByTestId('passwordInput'), formData.password); + + userEvent.type(screen.getByTestId('emailInput'), formData.email); + + userEvent.type(screen.getByTestId('firstNameInput'), formData.firstName); + + userEvent.click(screen.getByTestId('registerBtn')); + + expect(toast.error).toBeCalledWith('Please enter valid details.'); + }); + + test("Expect toast.error to be called if confirmPassword doesn't match with password", async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.type(screen.getByTestId('passwordInput'), formData.password); + + userEvent.type(screen.getByTestId('emailInput'), formData.email); + + userEvent.type(screen.getByTestId('firstNameInput'), formData.firstName); + + userEvent.type(screen.getByTestId('lastNameInput'), formData.lastName); + + userEvent.click(screen.getByTestId('registerBtn')); + + expect(toast.error).toBeCalledWith( + "Password doesn't match. Confirm Password and try again." + ); + }); + + test('Expect toast.success to be called if valid credentials are entered.', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.type(screen.getByTestId('passwordInput'), formData.password); + + userEvent.type( + screen.getByTestId('confirmPasswordInput'), + formData.confirmPassword + ); + + userEvent.type(screen.getByTestId('emailInput'), formData.email); + + userEvent.type(screen.getByTestId('firstNameInput'), formData.firstName); + + userEvent.type(screen.getByTestId('lastNameInput'), formData.lastName); + + userEvent.click(screen.getByTestId('registerBtn')); + + await wait(); + + expect(toast.success).toBeCalledWith( + 'Successfully registered. Please wait for admin to approve your request.' + ); + }); +}); diff --git a/src/components/UserPortal/Register/Register.tsx b/src/components/UserPortal/Register/Register.tsx new file mode 100644 index 0000000000..1867eceecc --- /dev/null +++ b/src/components/UserPortal/Register/Register.tsx @@ -0,0 +1,221 @@ +import type { ChangeEvent, SetStateAction } from 'react'; +import React from 'react'; +import { Button, Form, InputGroup } from 'react-bootstrap'; +import EmailOutlinedIcon from '@mui/icons-material/EmailOutlined'; +import BadgeOutlinedIcon from '@mui/icons-material/BadgeOutlined'; +import { LockOutlined } from '@mui/icons-material'; +import { useTranslation } from 'react-i18next'; +import { SIGNUP_MUTATION } from 'GraphQl/Mutations/mutations'; + +import styles from './Register.module.css'; +import { useMutation } from '@apollo/client'; +import { toast } from 'react-toastify'; +import { errorHandler } from 'utils/errorHandler'; + +interface InterfaceRegisterProps { + setCurrentMode: React.Dispatch>; +} + +export default function register(props: InterfaceRegisterProps): JSX.Element { + const { setCurrentMode } = props; + + const { t } = useTranslation('translation', { keyPrefix: 'userRegister' }); + + const handleModeChangeToLogin = (): void => { + setCurrentMode('login'); + }; + + const [registerMutation] = useMutation(SIGNUP_MUTATION); + + const [registerVariables, setRegisterVariables] = React.useState({ + firstName: '', + lastName: '', + email: '', + password: '', + confirmPassword: '', + }); + + const handleRegister = async (): Promise => { + if ( + !( + registerVariables.email && + registerVariables.password && + registerVariables.firstName && + registerVariables.lastName + ) + ) { + toast.error(t('invalidDetailsMessage')); + } else if ( + registerVariables.password !== registerVariables.confirmPassword + ) { + toast.error(t('passwordNotMatch')); + } else { + try { + await registerMutation({ + variables: { + firstName: registerVariables.firstName, + lastName: registerVariables.lastName, + email: registerVariables.email, + password: registerVariables.password, + }, + }); + + toast.success(t('afterRegister')); + + /* istanbul ignore next */ + setRegisterVariables({ + firstName: '', + lastName: '', + email: '', + password: '', + confirmPassword: '', + }); + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + } + }; + + /* istanbul ignore next */ + const handleFirstName = (e: ChangeEvent): void => { + const firstName = e.target.value; + + setRegisterVariables({ ...registerVariables, firstName }); + }; + + /* istanbul ignore next */ + const handleLastName = (e: ChangeEvent): void => { + const lastName = e.target.value; + + setRegisterVariables({ ...registerVariables, lastName }); + }; + + /* istanbul ignore next */ + const handleEmailChange = (e: ChangeEvent): void => { + const email = e.target.value; + + setRegisterVariables({ ...registerVariables, email }); + }; + + /* istanbul ignore next */ + const handlePasswordChange = (e: ChangeEvent): void => { + const password = e.target.value; + + setRegisterVariables({ ...registerVariables, password }); + }; + + /* istanbul ignore next */ + const handleConfirmPasswordChange = ( + e: ChangeEvent + ): void => { + const confirmPassword = e.target.value; + + setRegisterVariables({ ...registerVariables, confirmPassword }); + }; + + return ( + <> +

    {t('register')}

    +
    +
    {t('firstName')}
    + + + + + + +
    {t('lastName')}
    + + + + + + +
    {t('emailAddress')}
    + + + + + + +
    {t('password')}
    + + + + + + +
    {t('confirmPassword')}
    + + + + + + +
    + + +
    + {t('alreadyhaveAnAccount')}{' '} + + {t('login')} + +
    + + ); +} diff --git a/src/components/UserPortal/SecuredRouteForUser/SecuredRouteForUser.test.tsx b/src/components/UserPortal/SecuredRouteForUser/SecuredRouteForUser.test.tsx new file mode 100644 index 0000000000..72ee402369 --- /dev/null +++ b/src/components/UserPortal/SecuredRouteForUser/SecuredRouteForUser.test.tsx @@ -0,0 +1,54 @@ +import React from 'react'; +import { MemoryRouter, Route } from 'react-router-dom'; +import { render, screen, waitFor } from '@testing-library/react'; +import SecuredRouteForUser from './SecuredRouteForUser'; + +describe('SecuredRouteForUser', () => { + test('renders the route when the user is logged in', () => { + // Set the 'IsLoggedIn' value to 'TRUE' in localStorage to simulate a logged-in user + localStorage.setItem('IsLoggedIn', 'TRUE'); + + render( + + ( + ( +
    + Organizations Component +
    + )} + /> + )} + /> +
    + ); + + expect(screen.getByTestId('organizations-content')).toBeInTheDocument(); + }); + + test('redirects to /user when the user is not logged in', async () => { + // Set the user as not logged in in local storage + localStorage.setItem('IsLoggedIn', 'FALSE'); + + render( + + ( + +
    Secured Content
    +
    + )} + /> +
    + ); + + await waitFor(() => { + expect(window.location.pathname).toBe('/'); + }); + }); +}); diff --git a/src/components/UserPortal/SecuredRouteForUser/SecuredRouteForUser.tsx b/src/components/UserPortal/SecuredRouteForUser/SecuredRouteForUser.tsx new file mode 100644 index 0000000000..967e6c00a0 --- /dev/null +++ b/src/components/UserPortal/SecuredRouteForUser/SecuredRouteForUser.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import { Redirect, Route } from 'react-router-dom'; + +const SecuredRouteForUser = (props: any): JSX.Element => { + const isLoggedIn = localStorage.getItem('IsLoggedIn'); + return isLoggedIn === 'TRUE' ? ( + <> + + + ) : ( + + ); +}; + +export default SecuredRouteForUser; diff --git a/src/components/UserPortal/TaskCard/TaskCard.module.css b/src/components/UserPortal/TaskCard/TaskCard.module.css new file mode 100644 index 0000000000..bf11a53e48 --- /dev/null +++ b/src/components/UserPortal/TaskCard/TaskCard.module.css @@ -0,0 +1,41 @@ +.mainContainer { + width: 100%; + padding: 15px; + cursor: pointer; + border-radius: 10px; + /* box-shadow: 2px 2px 8px 0px #c8c8c8; */ + overflow: hidden; + background-color: rgba(50, 187, 107, 0.15); +} + +.cardDetails { + display: flex; + flex-direction: column; +} + +.cardDetail { + display: flex; + flex-direction: row; + gap: 10px; + margin: 5px; +} + +.fillPrimary { + fill: var(--bs-primary) !important; +} + +.badge { + display: flex; + width: fit-content; + background-color: var(--bs-secondary) !important; + justify-content: center; + align-items: center; +} + +.fitContent { + width: fit-content; +} + +.marginTop { + margin-top: 10px; +} diff --git a/src/components/UserPortal/TaskCard/TaskCard.test.tsx b/src/components/UserPortal/TaskCard/TaskCard.test.tsx new file mode 100644 index 0000000000..1dcec3179c --- /dev/null +++ b/src/components/UserPortal/TaskCard/TaskCard.test.tsx @@ -0,0 +1,95 @@ +import React from 'react'; +import { act, render, screen } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider } from 'react-i18next'; + +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import TaskCard from './TaskCard'; + +const link = new StaticMockLink([], true); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +let props = { + id: '1', + title: 'Test Task Card', + deadline: '2023-09-28T16:25:47.000Z', + description: 'Test Description', + volunteers: [ + { + id: '1', + firstName: 'Test', + lastName: 'User', + email: 'test@user.com', + }, + ], + creator: { + id: '2', + firstName: 'Test', + lastName: 'User', + }, + event: { + id: '3', + title: 'Test Event', + organization: { + id: '1', + name: 'Test Organization', + image: '', + }, + }, + createdAt: '2023-09-21T13:24:31.217Z', + completed: false, +}; + +describe('Testing TaskCard Component [User Portal]', () => { + test('Component should be rendered properly if task.completed === false', async () => { + render( + + + + + + + + + + ); + + await wait(); + + expect(screen.queryAllByText('Test Task Card')).not.toBe([]); + }); + + test('Component should be rendered properly if task.completed === true', async () => { + props = { + ...props, + completed: true, + }; + + render( + + + + + + + + + + ); + + await wait(); + + expect(screen.queryAllByText('Test Task Card')).not.toBe([]); + }); +}); diff --git a/src/components/UserPortal/TaskCard/TaskCard.tsx b/src/components/UserPortal/TaskCard/TaskCard.tsx new file mode 100644 index 0000000000..72b8cfd66a --- /dev/null +++ b/src/components/UserPortal/TaskCard/TaskCard.tsx @@ -0,0 +1,131 @@ +import React from 'react'; +import styles from './TaskCard.module.css'; +import TimerIcon from '@mui/icons-material/Timer'; +import DescriptionIcon from '@mui/icons-material/Description'; +import AssignmentIndIcon from '@mui/icons-material/AssignmentInd'; +import CreateIcon from '@mui/icons-material/Create'; +import EventIcon from '@mui/icons-material/Event'; +import CorporateFareIcon from '@mui/icons-material/CorporateFare'; +import { Badge } from 'react-bootstrap'; +import { Tooltip } from '@mui/material'; +import dayjs from 'dayjs'; +import { useTranslation } from 'react-i18next'; + +interface InterfaceTaskCardProps { + id: string; + title: string; + deadline: string; + description: string; + volunteers: { + id: string; + firstName: string; + lastName: string; + email: string; + }[]; + creator: { + id: string; + firstName: string; + lastName: string; + }; + event: { + id: string; + title: string; + organization: { + id: string; + name: string; + image: string | null; + }; + }; + createdAt: string; + completed: boolean; +} + +function taskCard(props: InterfaceTaskCardProps): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'userTaskCard', + }); + + const creatorName = `${props.creator.firstName} ${props.creator.lastName}`; + + return ( +
    +
    +
    + {props.title} +
    + +
    + + + {' '} + {props.event.title} +
    + +
    + + + {' '} + {props.event.organization.name} +
    + +
    + + + {' '} + {props.description} +
    + +
    + + + {' '} + {dayjs(props.deadline).format('llll')} +
    + +
    + + + {' '} + {`${dayjs(props.createdAt).format('llll')} by ${creatorName}`} +
    + +
    + + + + {props.volunteers.map((volunteer: any, index) => { + const name = `${volunteer.firstName} ${volunteer.lastName}`; + + return ( + + {name} + + ); + })} +
    + + {props.completed ? ( + + + {t('completed')} + + + ) : ( + + + {t('incomplete')} + + + )} +
    +
    + ); +} + +export default taskCard; diff --git a/src/components/UserPortal/UserNavbar/UserNavbar.module.css b/src/components/UserPortal/UserNavbar/UserNavbar.module.css new file mode 100644 index 0000000000..764a24ab93 --- /dev/null +++ b/src/components/UserPortal/UserNavbar/UserNavbar.module.css @@ -0,0 +1,26 @@ +.talawaImage { + width: 40px; + height: auto; + margin-top: -5px; + border: 2px solid white; + margin-right: 10px; + background-color: white; + border-radius: 10px; +} + +.boxShadow { + box-shadow: 4px 4px 8px 4px #c8c8c8; +} + +.colorWhite { + color: white; +} + +.colorPrimary { + background: #31bb6b; +} + +.link { + text-decoration: none !important; + color: inherit; +} diff --git a/src/components/UserPortal/UserNavbar/UserNavbar.test.tsx b/src/components/UserPortal/UserNavbar/UserNavbar.test.tsx new file mode 100644 index 0000000000..57d478b8d0 --- /dev/null +++ b/src/components/UserPortal/UserNavbar/UserNavbar.test.tsx @@ -0,0 +1,177 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { act, render, screen } from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import cookies from 'js-cookie'; +import { StaticMockLink } from 'utils/StaticMockLink'; + +import UserNavbar from './UserNavbar'; +import userEvent from '@testing-library/user-event'; +import { REVOKE_REFRESH_TOKEN } from 'GraphQl/Mutations/mutations'; + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +const MOCKS = [ + { + request: { + query: REVOKE_REFRESH_TOKEN, + }, + result: {}, + }, +]; + +const link = new StaticMockLink(MOCKS, true); + +describe('Testing UserNavbar Component [User Portal]', () => { + afterEach(async () => { + await act(async () => { + await i18nForTest.changeLanguage('en'); + }); + }); + + test('Component should be rendered properly', async () => { + render( + + + + + + + + + + ); + + await wait(); + }); + + test('The language is switched to English', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('languageIcon')); + + userEvent.click(screen.getByTestId('changeLanguageBtn0')); + + await wait(); + + expect(cookies.get('i18next')).toBe('en'); + }); + + test('The language is switched to fr', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('languageIcon')); + + userEvent.click(screen.getByTestId('changeLanguageBtn1')); + + await wait(); + + expect(cookies.get('i18next')).toBe('fr'); + }); + + test('The language is switched to hi', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('languageIcon')); + + userEvent.click(screen.getByTestId('changeLanguageBtn2')); + + await wait(); + + expect(cookies.get('i18next')).toBe('hi'); + }); + + test('The language is switched to sp', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('languageIcon')); + + userEvent.click(screen.getByTestId('changeLanguageBtn3')); + + await wait(); + + expect(cookies.get('i18next')).toBe('sp'); + }); + + test('The language is switched to zh', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('languageIcon')); + + userEvent.click(screen.getByTestId('changeLanguageBtn4')); + + await wait(); + + expect(cookies.get('i18next')).toBe('zh'); + }); +}); diff --git a/src/components/UserPortal/UserNavbar/UserNavbar.tsx b/src/components/UserPortal/UserNavbar/UserNavbar.tsx new file mode 100644 index 0000000000..e10268e85e --- /dev/null +++ b/src/components/UserPortal/UserNavbar/UserNavbar.tsx @@ -0,0 +1,119 @@ +import React from 'react'; +import styles from './UserNavbar.module.css'; +import TalawaImage from 'assets/images/talawa-logo-200x200.png'; +import { Container, Dropdown, Navbar } from 'react-bootstrap'; +import { languages } from 'utils/languages'; +import i18next from 'i18next'; +import cookies from 'js-cookie'; +import PermIdentityIcon from '@mui/icons-material/PermIdentity'; +import LanguageIcon from '@mui/icons-material/Language'; +import { useTranslation } from 'react-i18next'; +import { Link } from 'react-router-dom'; +import { useMutation } from '@apollo/client'; +import { REVOKE_REFRESH_TOKEN } from 'GraphQl/Mutations/mutations'; + +function userNavbar(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'userNavbar', + }); + + const [revokeRefreshToken] = useMutation(REVOKE_REFRESH_TOKEN); + + const [currentLanguageCode, setCurrentLanguageCode] = React.useState( + /* istanbul ignore next */ + cookies.get('i18next') || 'en' + ); + + /* istanbul ignore next */ + const handleLogout = (): void => { + revokeRefreshToken(); + localStorage.clear(); + window.location.replace('/user'); + }; + + const userName = localStorage.getItem('name'); + + return ( + + + + Talawa Branding + {t('talawa')} + + + + + + + + + + {languages.map((language, index: number) => ( + => { + setCurrentLanguageCode(language.code); + await i18next.changeLanguage(language.code); + }} + disabled={currentLanguageCode === language.code} + data-testid={`changeLanguageBtn${index}`} + > + {' '} + {language.name} + + ))} + + + + + + + + + + {userName} + + + + {t('settings')} + + + + + {t('myTasks')} + + + + {t('logout')} + + + + + + + ); +} + +export default userNavbar; diff --git a/src/components/UserPortal/UserSidebar/UserSidebar.module.css b/src/components/UserPortal/UserSidebar/UserSidebar.module.css new file mode 100644 index 0000000000..00eb9b631f --- /dev/null +++ b/src/components/UserPortal/UserSidebar/UserSidebar.module.css @@ -0,0 +1,71 @@ +.mainContainer { + display: flex; + overflow: hidden; + flex-direction: column; + align-items: center; + padding: 0px 10px; + padding-top: 50px; + flex-grow: 1; + width: 250px; + background-color: var(--bs-white); +} + +@media screen and (max-width: 700px) { + .mainContainer { + display: none; + } +} + +.userDetails { + display: flex; + flex-direction: column; + align-items: center; + padding-top: 20px; +} + +.boxShadow { + box-shadow: 4px 4px 8px 4px #c8c8c8; +} + +.organizationsConatiner { + width: 100%; + padding-top: 50px; +} + +.heading { + text-align: center; + padding: 10px 0px; +} + +.orgName { + font-size: 16px; + font-weight: 600; + margin-top: 4px; +} + +.alignRight { + width: 100%; + text-align: right; + padding: 5px; +} + +.link { + text-decoration: none !important; + color: black; +} + +.rounded { + border-radius: 10px !important; +} + +.colorLight { + background-color: #f5f5f5; +} + +.marginTop { + margin-top: -2px; +} + +.personImage { + border-radius: 50%; +} diff --git a/src/components/UserPortal/UserSidebar/UserSidebar.test.tsx b/src/components/UserPortal/UserSidebar/UserSidebar.test.tsx new file mode 100644 index 0000000000..36327f6c93 --- /dev/null +++ b/src/components/UserPortal/UserSidebar/UserSidebar.test.tsx @@ -0,0 +1,252 @@ +import React from 'react'; +import { act, render } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider } from 'react-i18next'; + +import { + USER_DETAILS, + USER_JOINED_ORGANIZATIONS, +} from 'GraphQl/Queries/Queries'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import UserSidebar from './UserSidebar'; + +const MOCKS = [ + { + request: { + query: USER_DETAILS, + variables: { + id: localStorage.getItem('userId'), + }, + }, + result: { + data: { + user: { + __typename: 'User', + image: null, + firstName: 'Noble', + lastName: 'Mittal', + email: 'noble@mittal.com', + role: 'SUPERADMIN', + appLanguageCode: 'en', + userType: 'SUPERADMIN', + pluginCreationAllowed: true, + adminApproved: true, + createdAt: '2023-02-18T09:22:27.969Z', + adminFor: [], + createdOrganizations: [], + joinedOrganizations: [], + organizationUserBelongsTo: null, + organizationsBlockedBy: [], + createdEvents: [], + registeredEvents: [], + eventAdmin: [], + membershipRequests: [], + }, + }, + }, + }, + { + request: { + query: USER_DETAILS, + variables: { + id: '2', + }, + }, + result: { + data: { + user: { + __typename: 'User', + image: 'adssda', + firstName: 'Noble', + lastName: 'Mittal', + email: 'noble@mittal.com', + role: 'SUPERADMIN', + appLanguageCode: 'en', + userType: 'SUPERADMIN', + pluginCreationAllowed: true, + adminApproved: true, + createdAt: '2023-02-18T09:22:27.969Z', + adminFor: [], + createdOrganizations: [], + joinedOrganizations: [], + organizationUserBelongsTo: null, + organizationsBlockedBy: [], + createdEvents: [], + registeredEvents: [], + eventAdmin: [], + membershipRequests: [], + }, + }, + }, + }, + { + request: { + query: USER_JOINED_ORGANIZATIONS, + variables: { + id: localStorage.getItem('userId'), + }, + }, + result: { + data: { + users: [ + { + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + name: 'Any Organization', + image: '', + description: 'New Desc', + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: USER_JOINED_ORGANIZATIONS, + variables: { + id: '2', + }, + }, + result: { + data: { + users: [ + { + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + name: 'Any Organization', + image: 'dadsa', + description: 'New Desc', + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: USER_JOINED_ORGANIZATIONS, + variables: { + id: '3', + }, + }, + result: { + data: { + users: [ + { + joinedOrganizations: [], + }, + ], + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Testing UserSidebar Component [User Portal]', () => { + test('Component should be rendered properly', async () => { + render( + + + + + + + + + + ); + + await wait(); + }); + + test('Component should be rendered properly when userImage is not undefined', async () => { + const beforeUserId = localStorage.getItem('userId'); + + localStorage.setItem('userId', '2'); + + render( + + + + + + + + + + ); + + await wait(); + if (beforeUserId) { + localStorage.setItem('userId', beforeUserId); + } + }); + + test('Component should be rendered properly when organizationImage is not undefined', async () => { + const beforeUserId = localStorage.getItem('userId'); + + localStorage.setItem('userId', '2'); + + render( + + + + + + + + + + ); + + await wait(); + + if (beforeUserId) { + localStorage.setItem('userId', beforeUserId); + } + }); + + test('Component should be rendered properly when joinedOrganizations list is empty', async () => { + const beforeUserId = localStorage.getItem('userId'); + + localStorage.setItem('userId', '3'); + + render( + + + + + + + + + + ); + + await wait(); + + if (beforeUserId) { + localStorage.setItem('userId', beforeUserId); + } + }); +}); diff --git a/src/components/UserPortal/UserSidebar/UserSidebar.tsx b/src/components/UserPortal/UserSidebar/UserSidebar.tsx new file mode 100644 index 0000000000..2e455358b0 --- /dev/null +++ b/src/components/UserPortal/UserSidebar/UserSidebar.tsx @@ -0,0 +1,123 @@ +import React from 'react'; +import AboutImg from 'assets/images/defaultImg.png'; +import styles from './UserSidebar.module.css'; +import { ListGroup } from 'react-bootstrap'; +import { Link } from 'react-router-dom'; +import ChevronRightIcon from '@mui/icons-material/ChevronRight'; +import { useQuery } from '@apollo/client'; +import { + USER_DETAILS, + USER_JOINED_ORGANIZATIONS, +} from 'GraphQl/Queries/Queries'; +import { useTranslation } from 'react-i18next'; +import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; + +function userSidebar(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'userSidebar', + }); + + const [organizations, setOrganizations] = React.useState([]); + const [details, setDetails] = React.useState({} as any); + + const userId: string | null = localStorage.getItem('userId'); + + const { data, loading: loadingJoinedOrganizations } = useQuery( + USER_JOINED_ORGANIZATIONS, + { + variables: { id: userId }, + } + ); + + const { data: data2, loading: loadingUserDetails } = useQuery(USER_DETAILS, { + variables: { id: userId }, + }); + + /* istanbul ignore next */ + React.useEffect(() => { + if (data) { + setOrganizations(data.users[0].joinedOrganizations); + } + }, [data]); + + /* istanbul ignore next */ + React.useEffect(() => { + if (data2) { + setDetails(data2.user); + } + }, [data2]); + + return ( +
    + {loadingJoinedOrganizations || loadingUserDetails ? ( + <> + Loading... + + ) : ( + <> + +
    +
    + {`${details.firstName} ${details.lastName}`} +
    +
    {details.email}
    +
    +
    +
    + {t('yourOrganizations')} +
    + + {organizations.length ? ( + organizations.map((organization: any, index) => { + const organizationUrl = `/user/organization/id=${organization._id}`; + + return ( + + +
    + +
    + {organization.name} +
    +
    + +
    + ); + }) + ) : ( +
    {t('noOrganizations')}
    + )} +
    +
    + + {t('viewAll')} + + +
    +
    + + )} +
    + ); +} + +export default userSidebar; diff --git a/src/components/UserUpdate/UserUpdate.module.css b/src/components/UserUpdate/UserUpdate.module.css new file mode 100644 index 0000000000..54cf1c020c --- /dev/null +++ b/src/components/UserUpdate/UserUpdate.module.css @@ -0,0 +1,93 @@ +/* .userupdatediv{ + border: 1px solid #e8e5e5; + box-shadow: 2px 1px #e8e5e5; + padding:25px 16px; + border-radius: 5px; + background:#fdfdfd; +} */ +.settingstitle { + color: #707070; + font-size: 20px; + margin-bottom: 30px; + text-align: center; + margin-top: -10px; +} +.dispflex { + display: flex; + justify-content: flex-start; + margin: 0 auto; +} +.dispbtnflex { + width: 90%; + margin-top: 20px; + display: flex; + margin: 0 30%; +} +.dispflex > div { + width: 50%; + margin-right: 50px; +} + +.radio_buttons > input { + margin-bottom: 20px; + border: none; + box-shadow: none; + padding: 0 0; + border-radius: 5px; + background: none; + width: 50%; +} + +.whitebtn { + margin: 1rem 0 0; + margin-top: 10px; + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + padding: 10px 20px; + border-radius: 5px; + background: none; + width: 20%; + font-size: 16px; + color: #31bb6b; + outline: none; + font-weight: 600; + cursor: pointer; + float: left; + transition: transform 0.2s, box-shadow 0.2s; +} +.greenregbtn { + margin: 1rem 0 0; + margin-top: 10px; + margin-right: 30px; + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + padding: 10px 10px; + border-radius: 5px; + background-color: #31bb6b; + width: 20%; + font-size: 16px; + color: white; + outline: none; + font-weight: 600; + cursor: pointer; + transition: transform 0.2s, box-shadow 0.2s; +} +.radio_buttons { + width: 55%; + margin-top: 10px; + display: flex; + color: #707070; + font-weight: 600; + font-size: 14px; +} +.radio_buttons > input { + transform: scale(1.2); +} +.radio_buttons > label { + margin-top: -4px; + margin-left: 0px; + margin-right: 7px; +} +.idtitle { + width: 88%; +} diff --git a/src/components/UserUpdate/UserUpdate.test.tsx b/src/components/UserUpdate/UserUpdate.test.tsx new file mode 100644 index 0000000000..e10f4a5b4e --- /dev/null +++ b/src/components/UserUpdate/UserUpdate.test.tsx @@ -0,0 +1,159 @@ +import React from 'react'; +import { act, render, screen } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; +import { BrowserRouter as Router } from 'react-router-dom'; +import UserUpdate from './UserUpdate'; +import { UPDATE_USER_MUTATION } from 'GraphQl/Mutations/mutations'; +import i18nForTest from 'utils/i18nForTest'; +import { USER_DETAILS } from 'GraphQl/Queries/Queries'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { toast } from 'react-toastify'; + +const MOCKS = [ + { + request: { + query: USER_DETAILS, + variables: { + id: '1', + }, + }, + result: { + data: { + user: { + __typename: 'User', + image: null, + firstName: '', + lastName: '', + email: '', + role: 'SUPERADMIN', + appLanguageCode: 'en', + userType: 'SUPERADMIN', + pluginCreationAllowed: true, + adminApproved: true, + createdAt: '2023-02-18T09:22:27.969Z', + adminFor: [], + createdOrganizations: [], + joinedOrganizations: [], + organizationUserBelongsTo: null, + organizationsBlockedBy: [], + createdEvents: [], + registeredEvents: [], + eventAdmin: [], + membershipRequests: [], + }, + }, + }, + }, + { + request: { + query: UPDATE_USER_MUTATION, + variable: { + firstName: '', + lastName: '', + email: '', + }, + }, + result: { + data: { + users: [ + { + _id: '1', + }, + ], + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); + +async function wait(ms = 5): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Testing User Update', () => { + const props = { + key: '123', + id: '1', + toggleStateValue: jest.fn(), + }; + + const formData = { + firstName: 'Ansh', + lastName: 'Goyal', + email: 'ansh@gmail.com', + image: new File(['hello'], 'hello.png', { type: 'image/png' }), + }; + + global.alert = jest.fn(); + + test('should render props and text elements test for the page component', async () => { + render( + + + + + + + + ); + + await wait(); + + userEvent.type( + screen.getByPlaceholderText(/First Name/i), + formData.firstName + ); + userEvent.type( + screen.getByPlaceholderText(/Last Name/i), + formData.lastName + ); + userEvent.type(screen.getByPlaceholderText(/Email/i), formData.email); + userEvent.selectOptions(screen.getByTestId('applangcode'), 'Français'); + userEvent.upload(screen.getByLabelText(/Display Image:/i), formData.image); + await wait(); + + userEvent.click(screen.getByText(/Save Changes/i)); + + expect(screen.getByPlaceholderText(/First Name/i)).toHaveValue( + formData.firstName + ); + expect(screen.getByPlaceholderText(/Last Name/i)).toHaveValue( + formData.lastName + ); + expect(screen.getByPlaceholderText(/Email/i)).toHaveValue(formData.email); + + expect(screen.getByText(/Cancel/i)).toBeTruthy(); + expect(screen.getByPlaceholderText(/First Name/i)).toBeInTheDocument(); + expect(screen.getByPlaceholderText(/Last Name/i)).toBeInTheDocument(); + expect(screen.getByPlaceholderText(/Email/i)).toBeInTheDocument(); + expect(screen.getByText(/Display Image/i)).toBeInTheDocument(); + }); + test('should display warnings for blank form submission', async () => { + jest.spyOn(toast, 'warning'); + + render( + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByText(/Save Changes/i)); + + expect(toast.warning).toHaveBeenCalledWith('First Name cannot be blank!'); + expect(toast.warning).toHaveBeenCalledWith('Last Name cannot be blank!'); + expect(toast.warning).toHaveBeenCalledWith('Email cannot be blank!'); + }); +}); diff --git a/src/components/UserUpdate/UserUpdate.tsx b/src/components/UserUpdate/UserUpdate.tsx new file mode 100644 index 0000000000..a58740b965 --- /dev/null +++ b/src/components/UserUpdate/UserUpdate.tsx @@ -0,0 +1,257 @@ +import React from 'react'; +import { useMutation, useQuery } from '@apollo/client'; +import { UPDATE_USER_MUTATION } from 'GraphQl/Mutations/mutations'; +import { useTranslation } from 'react-i18next'; +import Button from 'react-bootstrap/Button'; +import styles from './UserUpdate.module.css'; +import convertToBase64 from 'utils/convertToBase64'; +import { USER_DETAILS } from 'GraphQl/Queries/Queries'; +import { useLocation } from 'react-router-dom'; + +import { languages } from 'utils/languages'; +import { toast } from 'react-toastify'; +import { errorHandler } from 'utils/errorHandler'; +import { Form } from 'react-bootstrap'; +import Loader from 'components/Loader/Loader'; + +interface InterfaceUserUpdateProps { + id: string; + toggleStateValue: () => void; +} + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const UserUpdate: React.FC = ({ + id, + toggleStateValue, +}): JSX.Element => { + const location = useLocation(); + const currentUrl = location.state?.id || localStorage.getItem('id') || id; + const { t } = useTranslation('translation', { + keyPrefix: 'userUpdate', + }); + const [formState, setFormState] = React.useState({ + firstName: '', + lastName: '', + email: '', + password: '', + applangcode: '', + file: '', + }); + + const [updateUser] = useMutation(UPDATE_USER_MUTATION); + + const { + data: data, + loading: loading, + error: error, + } = useQuery(USER_DETAILS, { + variables: { id: currentUrl }, // For testing we are sending the id as a prop + }); + React.useEffect(() => { + if (data) { + setFormState({ + ...formState, + firstName: data?.user?.firstName, + lastName: data?.user?.lastName, + email: data?.user?.email, + }); + } + }, [data]); + + if (loading) { + return ; + } + + /* istanbul ignore next */ + if (error) { + window.location.assign(`/orgsettings/id=${currentUrl}`); + } + + const loginLink = async (): Promise => { + try { + const firstName = formState.firstName; + const lastName = formState.lastName; + const email = formState.email; + const file = formState.file; + let toSubmit = true; + if (firstName.trim().length == 0 || !firstName) { + toast.warning('First Name cannot be blank!'); + toSubmit = false; + } + if (lastName.trim().length == 0 || !lastName) { + toast.warning('Last Name cannot be blank!'); + toSubmit = false; + } + if (email.trim().length == 0 || !email) { + toast.warning('Email cannot be blank!'); + toSubmit = false; + } + if (!toSubmit) return; + const { data } = await updateUser({ + variables: { + //Currently on these fields are supported by the api + firstName, + lastName, + email, + file, + }, + }); + /* istanbul ignore next */ + if (data) { + setFormState({ + firstName: '', + lastName: '', + email: '', + password: '', + applangcode: '', + file: '', + }); + localStorage.setItem('FirstName', firstName); + localStorage.setItem('LastName', lastName); + localStorage.setItem('Email', email); + localStorage.setItem('UserImage', file); + toast.success('Successful updated'); + + toggleStateValue(); + } + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + + /* istanbul ignore next */ + const cancelUpdate = (): void => { + toggleStateValue(); + }; + + return ( + <> +
    +
    + {/*

    Update Your Details

    */} +
    +
    + + { + setFormState({ + ...formState, + firstName: e.target.value, + }); + }} + /> +
    +
    +
    +
    + + { + setFormState({ + ...formState, + lastName: e.target.value, + }); + }} + /> +
    +
    +
    +
    + + { + setFormState({ + ...formState, + email: e.target.value, + }); + }} + /> +
    +
    + +
    +
    + +
    +
    + +
    + + +
    +
    +
    + + ); +}; +export default UserUpdate; diff --git a/src/components/UsersTableItem/UserTableItem.test.tsx b/src/components/UsersTableItem/UserTableItem.test.tsx new file mode 100644 index 0000000000..0e67a02022 --- /dev/null +++ b/src/components/UsersTableItem/UserTableItem.test.tsx @@ -0,0 +1,1054 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { act, fireEvent, render, screen } from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { toast } from 'react-toastify'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18nForTest from 'utils/i18nForTest'; +import type { InterfaceQueryUserListItem } from 'utils/interfaces'; +import { MOCKS } from './UserTableItemMocks'; +import UsersTableItem from './UsersTableItem'; + +const link = new StaticMockLink(MOCKS, true); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} +const resetAndRefetchMock = jest.fn(); + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + warning: jest.fn(), + }, +})); + +Object.defineProperty(window, 'location', { + value: { + replace: jest.fn(), + }, + writable: true, +}); + +const mockHistoryPush = jest.fn(); + +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useHistory: () => ({ + push: mockHistoryPush, + }), +})); + +beforeEach(() => { + localStorage.setItem('UserType', 'SUPERADMIN'); + localStorage.setItem('id', '123'); +}); + +afterEach(() => { + localStorage.clear(); + jest.clearAllMocks(); +}); + +describe('Testing User Table Item', () => { + console.error = jest.fn((message) => { + if (message.includes('validateDOMNesting')) { + return; + } + // Log other console errors + console.warn(message); + }); + test('Should render props and text elements test for the page component', async () => { + const props: { + user: InterfaceQueryUserListItem; + index: number; + loggedInUserId: string; + resetAndRefetch: () => void; + } = { + user: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + userType: 'SUPERADMIN', + adminApproved: true, + adminFor: [ + { + _id: 'abc', + }, + ], + createdAt: '2023-09-29T15:39:36.355Z', + organizationsBlockedBy: [ + { + _id: 'xyz', + name: 'XYZ', + image: null, + location: 'Jamaica', + createdAt: '2023-01-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, + }, + { + _id: 'mno', + name: 'MNO', + image: null, + location: 'Jamaica', + createdAt: '2023-01-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, + }, + ], + joinedOrganizations: [ + { + _id: 'abc', + name: 'Joined Organization 1', + image: null, + location: 'Jamaica', + createdAt: '2023-06-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, + }, + { + _id: 'def', + name: 'Joined Organization 2', + image: null, + location: 'Jamaica', + createdAt: '2023-07-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, + }, + ], + }, + index: 0, + loggedInUserId: '123', + resetAndRefetch: resetAndRefetchMock, + }; + + render( + + + + + + ); + + await wait(); + expect(screen.getByText(/1/i)).toBeInTheDocument(); + expect(screen.getByText(/John Doe/i)).toBeInTheDocument(); + expect(screen.getByText(/john@example.com/i)).toBeInTheDocument(); + expect(screen.getByTestId(`changeRole${123}`)).toBeInTheDocument(); + expect(screen.getByTestId(`changeRole${123}`)).toHaveValue( + `SUPERADMIN?${123}` + ); + expect(screen.getByTestId(`showJoinedOrgsBtn${123}`)).toBeInTheDocument(); + expect( + screen.getByTestId(`showBlockedByOrgsBtn${123}`) + ).toBeInTheDocument(); + }); + + test('Should render elements correctly when JoinedOrgs and BlockedByOrgs are empty', async () => { + const props: { + user: InterfaceQueryUserListItem; + index: number; + loggedInUserId: string; + resetAndRefetch: () => void; + } = { + user: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + userType: 'SUPERADMIN', + adminApproved: true, + adminFor: [ + { + _id: 'abc', + }, + ], + createdAt: '2023-09-29T15:39:36.355Z', + organizationsBlockedBy: [], + joinedOrganizations: [], + }, + index: 0, + loggedInUserId: '123', + resetAndRefetch: resetAndRefetchMock, + }; + render( + + + + + + ); + + await wait(); + const showJoinedOrgsBtn = screen.getByTestId(`showJoinedOrgsBtn${123}`); // 123 is userId + const showBlockedByOrgsBtn = screen.getByTestId( + `showBlockedByOrgsBtn${123}` + ); // 123 is userId + + // Open JoinedOrgs Modal -> Expect modal to contain text and no search box -> Close Modal + fireEvent.click(showJoinedOrgsBtn); + expect( + screen.queryByTestId(`searchByNameJoinedOrgs`) + ).not.toBeInTheDocument(); + expect( + screen.getByText(/John Doe has not joined any organization/i) + ).toBeInTheDocument(); + fireEvent.click(screen.getByTestId(`closeJoinedOrgsBtn${123}`)); + + // Open BlockedByOrgs Modal -> Expect modal to contain text and no search box -> Close Modal + fireEvent.click(showBlockedByOrgsBtn); + expect( + screen.queryByTestId(`searchByNameOrgsBlockedBy`) + ).not.toBeInTheDocument(); + expect( + screen.getByText(/John Doe is not blocked by any organization/i) + ).toBeInTheDocument(); + fireEvent.click(screen.getByTestId(`closeBlockedByOrgsBtn${123}`)); + }); + + test('Should render props and text elements test for the Joined Organizations Modal properly', async () => { + const props: { + user: InterfaceQueryUserListItem; + index: number; + loggedInUserId: string; + resetAndRefetch: () => void; + } = { + user: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + userType: 'SUPERADMIN', + adminApproved: true, + adminFor: [ + { + _id: 'abc', + }, + ], + createdAt: '2022-09-29T15:39:36.355Z', + organizationsBlockedBy: [ + { + _id: 'xyz', + name: 'Blocked Organization 1', + image: null, + location: 'Jamaica', + createdAt: '2023-08-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, + }, + { + _id: 'mno', + name: 'Blocked Organization 2', + image: null, + location: 'Jamaica', + createdAt: '2023-09-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, + }, + ], + joinedOrganizations: [ + { + _id: 'abc', + name: 'Joined Organization 1', + image: + 'https://api.dicebear.com/5.x/initials/svg?seed=Joined%20Organization%201', + location: 'Jamaica', + createdAt: '2023-08-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: + 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', + email: 'john@example.com', + }, + }, + { + _id: 'def', + name: 'Joined Organization 2', + image: null, + location: 'Jamaica', + createdAt: '2023-09-19T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, + }, + ], + }, + index: 0, + loggedInUserId: '123', + resetAndRefetch: resetAndRefetchMock, + }; + + render( + + + + + + ); + + await wait(); + const showJoinedOrgsBtn = screen.getByTestId(`showJoinedOrgsBtn${123}`); + expect(showJoinedOrgsBtn).toBeInTheDocument(); + fireEvent.click(showJoinedOrgsBtn); + expect(screen.getByTestId('modal-joined-org-123')).toBeInTheDocument(); + + // Close using escape key and reopen + fireEvent.keyDown(screen.getByTestId('modal-joined-org-123'), { + key: 'Escape', + code: 'Escape', + keyCode: 27, + charCode: 27, + }); + expect( + screen.queryByRole('dialog')?.className.includes('show') + ).toBeFalsy(); + fireEvent.click(showJoinedOrgsBtn); + // Close using close button and reopen + fireEvent.click(screen.getByTestId(`closeJoinedOrgsBtn${123}`)); + expect( + screen.queryByRole('dialog')?.className.includes('show') + ).toBeFalsy(); + + fireEvent.click(showJoinedOrgsBtn); + + // Expect the following to exist in modal + const inputBox = screen.getByTestId(`searchByNameJoinedOrgs`); + expect(inputBox).toBeInTheDocument(); + expect(screen.getByText(/Joined Organization 1/i)).toBeInTheDocument(); + expect(screen.getByText(/Joined Organization 2/i)).toBeInTheDocument(); + expect(screen.getAllByText(/Jamaica/i)).toHaveLength(2); + expect(screen.getByText(/29-08-2023/i)).toBeInTheDocument(); + expect(screen.getByText(/19-09-2023/i)).toBeInTheDocument(); + expect(screen.getByTestId('removeUserFromOrgBtnabc')).toBeInTheDocument(); + expect(screen.getByTestId('removeUserFromOrgBtndef')).toBeInTheDocument(); + expect(screen.getByTestId(`changeRoleInOrgabc`)).toHaveValue('ADMIN?abc'); + expect(screen.getByTestId(`changeRoleInOrgdef`)).toHaveValue('USER?def'); + + // Search for Joined Organization 1 + fireEvent.change(inputBox, { target: { value: 'Joined Organization 1' } }); + expect(screen.getByText(/Joined Organization 1/i)).toBeInTheDocument(); + expect( + screen.queryByText(/Joined Organization 2/i) + ).not.toBeInTheDocument(); + + // Search for an Organization which does not exist + fireEvent.change(inputBox, { target: { value: 'Joined Organization 3' } }); + expect( + screen.getByText(`No results found for "Joined Organization 3"`) + ).toBeInTheDocument(); + + // Now clear the search box + fireEvent.change(inputBox, { target: { value: '' } }); + + // Click on Creator Link + fireEvent.click(screen.getByTestId(`creatorabc`)); + expect(toast.success).toBeCalledWith('Profile Page Coming Soon !'); + + // Click on Organization Link + fireEvent.click(screen.getByText(/Joined Organization 1/i)); + expect(window.location.replace).toBeCalledWith('/orgdash/id=abc'); + expect(mockHistoryPush).toBeCalledWith('/orgdash/id=abc'); + fireEvent.click(screen.getByTestId(`closeJoinedOrgsBtn${123}`)); + }); + + test('Should render props and text elements test for the Blocked By Organizations Modal properly', async () => { + const props: { + user: InterfaceQueryUserListItem; + index: number; + loggedInUserId: string; + resetAndRefetch: () => void; + } = { + user: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', + email: 'john@example.com', + userType: 'SUPERADMIN', + adminApproved: true, + adminFor: [ + { + _id: 'abc', + }, + { + _id: 'xyz', + }, + ], + createdAt: '2022-09-29T15:39:36.355Z', + organizationsBlockedBy: [ + { + _id: 'xyz', + name: 'Blocked Organization 1', + image: + 'https://api.dicebear.com/5.x/initials/svg?seed=Blocked%20Organization%201', + location: 'Jamaica', + createdAt: '2023-08-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: + 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', + email: 'john@example.com', + }, + }, + { + _id: 'mno', + name: 'Blocked Organization 2', + image: null, + location: 'Jamaica', + createdAt: '2023-09-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, + }, + ], + joinedOrganizations: [ + { + _id: 'abc', + name: 'Joined Organization 1', + image: null, + location: 'Jamaica', + createdAt: '2023-08-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, + }, + { + _id: 'def', + name: 'Joined Organization 2', + image: null, + location: 'Jamaica', + createdAt: '2023-09-19T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, + }, + ], + }, + index: 0, + loggedInUserId: '123', + resetAndRefetch: resetAndRefetchMock, + }; + + render( + + + + + + ); + + await wait(); + const showBlockedByOrgsBtn = screen.getByTestId( + `showBlockedByOrgsBtn${123}` + ); + expect(showBlockedByOrgsBtn).toBeInTheDocument(); + fireEvent.click(showBlockedByOrgsBtn); + expect(screen.getByTestId('modal-blocked-org-123')).toBeInTheDocument(); + + // Close using escape key and reopen + fireEvent.keyDown(screen.getByTestId('modal-blocked-org-123'), { + key: 'Escape', + code: 'Escape', + keyCode: 27, + charCode: 27, + }); + expect( + screen.queryByRole('dialog')?.className.includes('show') + ).toBeFalsy(); + fireEvent.click(showBlockedByOrgsBtn); + // Close using close button and reopen + fireEvent.click(screen.getByTestId(`closeBlockedByOrgsBtn${123}`)); + expect( + screen.queryByRole('dialog')?.className.includes('show') + ).toBeFalsy(); + + fireEvent.click(showBlockedByOrgsBtn); + + // Expect the following to exist in modal + + const inputBox = screen.getByTestId(`searchByNameOrgsBlockedBy`); + expect(inputBox).toBeInTheDocument(); + expect(screen.getByText(/Blocked Organization 1/i)).toBeInTheDocument(); + expect(screen.getByText(/Blocked Organization 2/i)).toBeInTheDocument(); + expect(screen.getAllByText(/Jamaica/i)).toHaveLength(2); + expect(screen.getByText(/29-08-2023/i)).toBeInTheDocument(); + expect(screen.getByText(/29-09-2023/i)).toBeInTheDocument(); + expect(screen.getByTestId('removeUserFromOrgBtnxyz')).toBeInTheDocument(); + expect(screen.getByTestId('removeUserFromOrgBtnmno')).toBeInTheDocument(); + expect(screen.getByTestId(`changeRoleInOrgxyz`)).toHaveValue('ADMIN?xyz'); + expect(screen.getByTestId(`changeRoleInOrgmno`)).toHaveValue('USER?mno'); + // Click on Creator Link + fireEvent.click(screen.getByTestId(`creatorxyz`)); + expect(toast.success).toBeCalledWith('Profile Page Coming Soon !'); + + // Search for Blocked Organization 1 + fireEvent.change(inputBox, { target: { value: 'Blocked Organization 1' } }); + expect(screen.getByText(/Blocked Organization 1/i)).toBeInTheDocument(); + expect( + screen.queryByText(/Blocked Organization 2/i) + ).not.toBeInTheDocument(); + + // Search for an Organization which does not exist + fireEvent.change(inputBox, { target: { value: 'Blocked Organization 3' } }); + expect( + screen.getByText(`No results found for "Blocked Organization 3"`) + ).toBeInTheDocument(); + + // Now clear the search box + fireEvent.change(inputBox, { target: { value: '' } }); + + // Click on Organization Link + fireEvent.click(screen.getByText(/Blocked Organization 1/i)); + expect(window.location.replace).toBeCalledWith('/orgdash/id=xyz'); + expect(mockHistoryPush).toBeCalledWith('/orgdash/id=xyz'); + fireEvent.click(screen.getByTestId(`closeBlockedByOrgsBtn${123}`)); + }); + + test('Remove user from Organization should function properly in Organizations Joined Modal', async () => { + const props: { + user: InterfaceQueryUserListItem; + index: number; + loggedInUserId: string; + resetAndRefetch: () => void; + } = { + user: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', + email: 'john@example.com', + userType: 'SUPERADMIN', + adminApproved: true, + adminFor: [ + { + _id: 'abc', + }, + { + _id: 'xyz', + }, + ], + createdAt: '2022-09-29T15:39:36.355Z', + organizationsBlockedBy: [ + { + _id: 'xyz', + name: 'Blocked Organization 1', + image: + 'https://api.dicebear.com/5.x/initials/svg?seed=Blocked%20Organization%201', + location: 'Jamaica', + createdAt: '2023-08-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: + 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', + email: 'john@example.com', + }, + }, + { + _id: 'mno', + name: 'Blocked Organization 2', + image: null, + location: 'Jamaica', + createdAt: '2023-09-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, + }, + ], + joinedOrganizations: [ + { + _id: 'abc', + name: 'Joined Organization 1', + image: null, + location: 'Jamaica', + createdAt: '2023-08-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, + }, + { + _id: 'def', + name: 'Joined Organization 2', + image: null, + location: 'Jamaica', + createdAt: '2023-09-19T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, + }, + ], + }, + index: 0, + loggedInUserId: '123', + resetAndRefetch: resetAndRefetchMock, + }; + + render( + + + + + + ); + + await wait(); + const showJoinedOrgsBtn = screen.getByTestId(`showJoinedOrgsBtn${123}`); + expect(showJoinedOrgsBtn).toBeInTheDocument(); + fireEvent.click(showJoinedOrgsBtn); + expect(screen.getByTestId('modal-joined-org-123')).toBeInTheDocument(); + fireEvent.click(showJoinedOrgsBtn); + fireEvent.click(screen.getByTestId(`removeUserFromOrgBtn${'abc'}`)); + expect(screen.getByTestId('modal-remove-user-123')).toBeInTheDocument(); + + // Close using escape key and reopen + fireEvent.keyDown(screen.getByTestId('modal-joined-org-123'), { + key: 'Escape', + code: 'Escape', + keyCode: 27, + charCode: 27, + }); + expect( + screen + .queryAllByRole('dialog') + .some((el) => el.className.includes('show')) + ).toBeTruthy(); + fireEvent.click(showJoinedOrgsBtn); + // Close using close button and reopen + fireEvent.click(screen.getByTestId('closeRemoveUserModal123')); + expect( + screen + .queryAllByRole('dialog') + .some((el) => el.className.includes('show')) + ).toBeTruthy(); + + fireEvent.click(showJoinedOrgsBtn); + fireEvent.click(screen.getByTestId(`removeUserFromOrgBtn${'abc'}`)); + const confirmRemoveBtn = screen.getByTestId(`confirmRemoveUser123`); + expect(confirmRemoveBtn).toBeInTheDocument(); + + fireEvent.click(confirmRemoveBtn); + }); + + test('Remove user from Organization should function properly in Organizations Blocked by Modal', async () => { + const props: { + user: InterfaceQueryUserListItem; + index: number; + loggedInUserId: string; + resetAndRefetch: () => void; + } = { + user: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', + email: 'john@example.com', + userType: 'SUPERADMIN', + adminApproved: true, + adminFor: [ + { + _id: 'abc', + }, + { + _id: 'xyz', + }, + ], + createdAt: '2022-09-29T15:39:36.355Z', + organizationsBlockedBy: [ + { + _id: 'xyz', + name: 'Blocked Organization 1', + image: + 'https://api.dicebear.com/5.x/initials/svg?seed=Blocked%20Organization%201', + location: 'Jamaica', + createdAt: '2023-08-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: + 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', + email: 'john@example.com', + }, + }, + { + _id: 'mno', + name: 'Blocked Organization 2', + image: null, + location: 'Jamaica', + createdAt: '2023-09-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, + }, + ], + joinedOrganizations: [ + { + _id: 'abc', + name: 'Joined Organization 1', + image: null, + location: 'Jamaica', + createdAt: '2023-08-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, + }, + { + _id: 'def', + name: 'Joined Organization 2', + image: null, + location: 'Jamaica', + createdAt: '2023-09-19T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, + }, + ], + }, + index: 0, + loggedInUserId: '123', + resetAndRefetch: resetAndRefetchMock, + }; + + render( + + + + + + ); + + await wait(); + const showBlockedByOrgsBtn = screen.getByTestId( + `showBlockedByOrgsBtn${123}` + ); + expect(showBlockedByOrgsBtn).toBeInTheDocument(); + fireEvent.click(showBlockedByOrgsBtn); + expect(screen.getByTestId('modal-blocked-org-123')).toBeInTheDocument(); + fireEvent.click(showBlockedByOrgsBtn); + fireEvent.click(screen.getByTestId(`removeUserFromOrgBtn${'xyz'}`)); + expect(screen.getByTestId('modal-remove-user-123')).toBeInTheDocument(); + + // Close using escape key and reopen + fireEvent.keyDown(screen.getByTestId('modal-blocked-org-123'), { + key: 'Escape', + code: 'Escape', + keyCode: 27, + charCode: 27, + }); + expect( + screen + .queryAllByRole('dialog') + .some((el) => el.className.includes('show')) + ).toBeTruthy(); + fireEvent.click(showBlockedByOrgsBtn); + // Close using close button and reopen + fireEvent.click(screen.getByTestId('closeRemoveUserModal123')); + expect( + screen + .queryAllByRole('dialog') + .some((el) => el.className.includes('show')) + ).toBeTruthy(); + + fireEvent.click(showBlockedByOrgsBtn); + fireEvent.click(screen.getByTestId(`removeUserFromOrgBtn${'xyz'}`)); + const confirmRemoveBtn = screen.getByTestId(`confirmRemoveUser123`); + expect(confirmRemoveBtn).toBeInTheDocument(); + + fireEvent.click(confirmRemoveBtn); + }); + + test('Should be able to change userType of a user if not self', async () => { + const props: { + user: InterfaceQueryUserListItem; + index: number; + loggedInUserId: string; + resetAndRefetch: () => void; + } = { + user: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', + email: 'john@example.com', + userType: 'USER', + adminApproved: true, + adminFor: [ + { + _id: 'abc', + }, + { + _id: 'xyz', + }, + ], + createdAt: '2022-09-29T15:39:36.355Z', + organizationsBlockedBy: [ + { + _id: 'xyz', + name: 'Blocked Organization 1', + image: + 'https://api.dicebear.com/5.x/initials/svg?seed=Blocked%20Organization%201', + location: 'Jamaica', + createdAt: '2023-08-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: + 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', + email: 'john@example.com', + }, + }, + { + _id: 'mno', + name: 'Blocked Organization 2', + image: null, + location: 'Jamaica', + createdAt: '2023-09-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, + }, + ], + joinedOrganizations: [ + { + _id: 'abc', + name: 'Joined Organization 1', + image: null, + location: 'Jamaica', + createdAt: '2023-08-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, + }, + { + _id: 'def', + name: 'Joined Organization 2', + image: null, + location: 'Jamaica', + createdAt: '2023-09-19T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, + }, + ], + }, + index: 0, + loggedInUserId: '456', + resetAndRefetch: resetAndRefetchMock, + }; + + render( + + + + + + ); + + await wait(); + fireEvent.select(screen.getByTestId(`changeRole123`), { + target: { value: 'ADMIN?123' }, + }); + }); + + test('Should be not able to change userType of self', async () => { + const props: { + user: InterfaceQueryUserListItem; + index: number; + loggedInUserId: string; + resetAndRefetch: () => void; + } = { + user: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', + email: 'john@example.com', + userType: 'ADMIN', + adminApproved: true, + adminFor: [ + { + _id: 'abc', + }, + { + _id: 'xyz', + }, + ], + createdAt: '2022-09-29T15:39:36.355Z', + organizationsBlockedBy: [ + { + _id: 'xyz', + name: 'Blocked Organization 1', + image: + 'https://api.dicebear.com/5.x/initials/svg?seed=Blocked%20Organization%201', + location: 'Jamaica', + createdAt: '2023-08-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: + 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', + email: 'john@example.com', + }, + }, + { + _id: 'mno', + name: 'Blocked Organization 2', + image: null, + location: 'Jamaica', + createdAt: '2023-09-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, + }, + ], + joinedOrganizations: [ + { + _id: 'abc', + name: 'Joined Organization 1', + image: null, + location: 'Jamaica', + createdAt: '2023-08-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, + }, + { + _id: 'def', + name: 'Joined Organization 2', + image: null, + location: 'Jamaica', + createdAt: '2023-09-19T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, + }, + ], + }, + index: 0, + loggedInUserId: '123', + resetAndRefetch: resetAndRefetchMock, + }; + + render( + + + + + + ); + + await wait(); + expect(screen.getByTestId(`changeRole123`)).toBeDisabled(); + expect(screen.getByTestId(`changeRole123`)).toHaveValue('ADMIN?123'); + }); +}); diff --git a/src/components/UsersTableItem/UserTableItemMocks.ts b/src/components/UsersTableItem/UserTableItemMocks.ts new file mode 100644 index 0000000000..5f81c8cfe9 --- /dev/null +++ b/src/components/UsersTableItem/UserTableItemMocks.ts @@ -0,0 +1,59 @@ +import { + REMOVE_MEMBER_MUTATION, + UPDATE_USERTYPE_MUTATION, + UPDATE_USER_ROLE_IN_ORG_MUTATION, +} from 'GraphQl/Mutations/mutations'; + +export const MOCKS = [ + { + request: { + query: UPDATE_USERTYPE_MUTATION, + variables: { + id: '123', + userType: 'ADMIN', + }, + }, + result: { + data: { + updateUserType: { + data: { + id: '123', + }, + }, + }, + }, + }, + { + request: { + query: REMOVE_MEMBER_MUTATION, + variables: { + userid: '123', + orgid: 'abc', + }, + }, + result: { + data: { + removeMember: { + _id: '123', + }, + }, + }, + }, + { + request: { + query: UPDATE_USER_ROLE_IN_ORG_MUTATION, + variables: { + userId: '123', + organizationId: 'abc', + role: 'ADMIN', + }, + }, + result: { + data: { + updateUserRoleInOrganization: { + _id: '123', + }, + }, + }, + }, +]; diff --git a/src/components/UsersTableItem/UsersTableItem.module.css b/src/components/UsersTableItem/UsersTableItem.module.css new file mode 100644 index 0000000000..d5fad679a7 --- /dev/null +++ b/src/components/UsersTableItem/UsersTableItem.module.css @@ -0,0 +1,26 @@ +.input { + position: relative; +} + +.notJoined { + height: 300px; + display: flex; + justify-content: center; + align-items: center; +} + +.modalTable img[alt='creator'] { + height: 24px; + width: 24px; + object-fit: contain; + border-radius: 12px; + margin-right: 0.4rem; +} + +.modalTable img[alt='orgImage'] { + height: 28px; + width: 28px; + object-fit: contain; + border-radius: 4px; + margin-right: 0.4rem; +} diff --git a/src/components/UsersTableItem/UsersTableItem.tsx b/src/components/UsersTableItem/UsersTableItem.tsx new file mode 100644 index 0000000000..dbf51e809a --- /dev/null +++ b/src/components/UsersTableItem/UsersTableItem.tsx @@ -0,0 +1,598 @@ +import { useMutation } from '@apollo/client'; +import { Search } from '@mui/icons-material'; +import { + REMOVE_MEMBER_MUTATION, + UPDATE_USERTYPE_MUTATION, + UPDATE_USER_ROLE_IN_ORG_MUTATION, +} from 'GraphQl/Mutations/mutations'; +import dayjs from 'dayjs'; +import React, { useState } from 'react'; +import { Button, Form, Modal, Row, Table } from 'react-bootstrap'; +import { useTranslation } from 'react-i18next'; +import { useHistory } from 'react-router-dom'; +import { toast } from 'react-toastify'; +import { errorHandler } from 'utils/errorHandler'; +import type { InterfaceQueryUserListItem } from 'utils/interfaces'; +import styles from './UsersTableItem.module.css'; + +type Props = { + user: InterfaceQueryUserListItem; + index: number; + loggedInUserId: string; + resetAndRefetch: () => void; +}; + +const UsersTableItem = (props: Props): JSX.Element => { + const { t } = useTranslation('translation', { keyPrefix: 'users' }); + const { user, index, loggedInUserId, resetAndRefetch } = props; + + const [showJoinedOrganizations, setShowJoinedOrganizations] = useState(false); + const [showBlockedOrganizations, setShowBlockedOrganizations] = + useState(false); + const [showRemoveUserModal, setShowRemoveUserModal] = useState(false); + const [removeUserProps, setremoveUserProps] = useState<{ + orgName: string; + orgId: string; + setShowOnCancel: 'JOINED' | 'BLOCKED' | ''; + }>({ + orgName: '', + orgId: '', + setShowOnCancel: '', + }); + const [joinedOrgs, setJoinedOrgs] = useState(user.joinedOrganizations); + const [orgsBlockedBy, setOrgsBlockedBy] = useState( + user.organizationsBlockedBy + ); + const [searchByNameJoinedOrgs, setSearchByNameJoinedOrgs] = useState(''); + const [searchByNameOrgsBlockedBy, setSearchByNameOrgsBlockedBy] = + useState(''); + const [updateUserType] = useMutation(UPDATE_USERTYPE_MUTATION); + const [removeUser] = useMutation(REMOVE_MEMBER_MUTATION); + const [updateUserInOrgType] = useMutation(UPDATE_USER_ROLE_IN_ORG_MUTATION); + const history = useHistory(); + + /* istanbul ignore next */ + const changeRole = async (e: any): Promise => { + const { value } = e.target; + + const inputData = value.split('?'); + + try { + const { data } = await updateUserType({ + variables: { + id: inputData[1], + userType: inputData[0], + }, + }); + if (data) { + toast.success(t('roleUpdated')); + resetAndRefetch(); + } + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + + const confirmRemoveUser = async (): Promise => { + try { + const { data } = await removeUser({ + variables: { + userid: user._id, + orgid: removeUserProps.orgId, + }, + }); + + if (data) { + toast.success('Removed User from Organization successfully'); + resetAndRefetch(); + } + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + + /* istanbul ignore next */ + const changeRoleInOrg = async (e: any): Promise => { + const { value } = e.target; + + const inputData = value.split('?'); + + try { + const { data } = await updateUserInOrgType({ + variables: { + userId: user._id, + role: inputData[0], + organizationId: inputData[1], + }, + }); + if (data) { + toast.success(t('roleUpdated')); + resetAndRefetch(); + } + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + + function goToOrg(_id: string): void { + const url = '/orgdash/id=' + _id; + + // Dont change the below two lines + window.location.replace(url); + history.push(url); + } + function handleCreator(): void { + toast.success('Profile Page Coming Soon !'); + } + function handleSearchJoinedOrgs(e: any): void { + const { value } = e.target; + setSearchByNameJoinedOrgs(value); + if (value == '') { + setJoinedOrgs(user.joinedOrganizations); + } else { + const filteredOrgs = user.joinedOrganizations.filter((org) => + org.name.toLowerCase().includes(value.toLowerCase()) + ); + setJoinedOrgs(filteredOrgs); + } + } + function handleSearcgByOrgsBlockedBy(e: any): void { + const { value } = e.target; + setSearchByNameOrgsBlockedBy(value); + if (value == '') { + setOrgsBlockedBy(user.organizationsBlockedBy); + } else { + const filteredOrgs = user.organizationsBlockedBy.filter((org) => + org.name.toLowerCase().includes(value.toLowerCase()) + ); + setOrgsBlockedBy(filteredOrgs); + } + } + + /* istanbul ignore next */ + function onHideRemoveUserModal(): void { + setShowRemoveUserModal(false); + if (removeUserProps.setShowOnCancel == 'JOINED') { + setShowJoinedOrganizations(true); + } else if (removeUserProps.setShowOnCancel == 'BLOCKED') { + setShowBlockedOrganizations(true); + } + } + return ( + <> + {/* Table Item */} + + {index + 1} + {`${user.firstName} ${user.lastName}`} + {user.email} + + + + + + + + + + + + + + + + {/* Organizations joined modal */} + setShowJoinedOrganizations(false)} + > + + + {t('orgJoinedBy')} {`${user.firstName}`} {`${user.lastName}`} ( + {user.joinedOrganizations.length}) + + + + {user.joinedOrganizations.length !== 0 && ( +
    + + +
    + )} + + {user.joinedOrganizations.length == 0 ? ( +
    +

    + {user.firstName} {user.lastName} {t('hasNotJoinedAnyOrg')} +

    +
    + ) : joinedOrgs.length == 0 ? ( + <> +
    +

    + {t('noResultsFoundFor')} "{searchByNameJoinedOrgs} + " +

    +
    + + ) : ( + + + + + + + + + + + + + + {joinedOrgs.map((org) => { + // Check user is admin for this organization or not + let isAdmin = false; + user.adminFor.map((item) => { + if (item._id == org._id) { + isAdmin = true; + } + }); + return ( + + + + + + + + + + ); + })} + +
    NameLocationCreated onCreated ByUsers RoleChange RoleAction
    + + {org.location}{dayjs(org.createdAt).format('DD-MM-YYYY')} + + {isAdmin ? 'ADMIN' : 'USER'} + + {isAdmin ? ( + <> + + + + ) : ( + <> + + + + )} + + + +
    + )} +
    +
    + + + +
    + {/* Organizations blocked by modal */} + setShowBlockedOrganizations(false)} + data-testid={`modal-blocked-org-${user._id}`} + > + + + {t('orgThatBlocked')} {`${user.firstName}`} {`${user.lastName}`} ( + {user.organizationsBlockedBy.length}) + + + + {user.organizationsBlockedBy.length !== 0 && ( +
    + + +
    + )} + + {user.organizationsBlockedBy.length == 0 ? ( +
    +

    + {user.firstName} {user.lastName} {t('isNotBlockedByAnyOrg')} +

    +
    + ) : orgsBlockedBy.length == 0 ? ( + <> +
    +

    + {t('noResultsFoundFor')} "{searchByNameOrgsBlockedBy} + " +

    +
    + + ) : ( + + + + + + + + + + + + + + + {orgsBlockedBy.map((org) => { + // Check user is admin for this organization or not + let isAdmin = false; + user.adminFor.map((item) => { + if (item._id == org._id) { + isAdmin = true; + } + }); + return ( + + + + + + + + + + ); + })} + +
    NameLocationCreated onCreated ByUsers RoleChange RoleAction
    + + {org.location}{dayjs(org.createdAt).format('DD-MM-YYYY')} + + {isAdmin ? 'ADMIN' : 'USER'} + + {isAdmin ? ( + <> + + + + ) : ( + <> + + + + )} + + + +
    + )} +
    +
    + + + +
    + {/* Remove user from Organization modal */} + onHideRemoveUserModal()} + > + + + Remove User from {removeUserProps.orgName} + + + +

    + Are you sure you want to remove{' '} + + “{user.firstName} {user.lastName}” + {' '} + from organization{' '} + + “ + {removeUserProps.orgName}” + {' '} + ? +

    +
    + + + + +
    + + ); +}; + +export default UsersTableItem; diff --git a/src/components/plugins/DummyPlugin/DummyPlugin.module.css b/src/components/plugins/DummyPlugin/DummyPlugin.module.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/components/plugins/DummyPlugin/DummyPlugin.test.jsx b/src/components/plugins/DummyPlugin/DummyPlugin.test.jsx new file mode 100644 index 0000000000..ce9aa0b9d9 --- /dev/null +++ b/src/components/plugins/DummyPlugin/DummyPlugin.test.jsx @@ -0,0 +1,30 @@ +/* eslint-disable react/react-in-jsx-scope */ +/* eslint-disable react/jsx-filename-extension */ +import { MockedProvider } from '@apollo/react-testing'; +import { render } from '@testing-library/react'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { I18nextProvider } from 'react-i18next'; + +import { store } from 'state/store'; +import DummyPlugin from './DummyPlugin'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +const link = new StaticMockLink([], true); +describe('Testing dummy plugin', () => { + test('should render props and text elements test for the page component', () => { + const { getByText } = render( + + + + + + + + + + ); + + expect(getByText(/Welcome to the Dummy Plugin!/i)).toBeInTheDocument(); + }); +}); diff --git a/src/components/plugins/DummyPlugin/DummyPlugin.tsx b/src/components/plugins/DummyPlugin/DummyPlugin.tsx new file mode 100644 index 0000000000..8fd2388784 --- /dev/null +++ b/src/components/plugins/DummyPlugin/DummyPlugin.tsx @@ -0,0 +1,17 @@ +import React from 'react'; +import AddOn from 'components/AddOn/AddOn'; + +// Validate Extras +function dummyPlugin(): JSX.Element { + return ( + +
    Welcome to the Dummy Plugin!
    +
    + ); +} + +dummyPlugin.defaultProps = {}; + +dummyPlugin.propTypes = {}; + +export default dummyPlugin; diff --git a/src/components/plugins/DummyPlugin2/DummyPlugin2.module.css b/src/components/plugins/DummyPlugin2/DummyPlugin2.module.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/components/plugins/DummyPlugin2/DummyPlugin2.test.jsx b/src/components/plugins/DummyPlugin2/DummyPlugin2.test.jsx new file mode 100644 index 0000000000..9b28f88693 --- /dev/null +++ b/src/components/plugins/DummyPlugin2/DummyPlugin2.test.jsx @@ -0,0 +1,19 @@ +/* eslint-disable react/react-in-jsx-scope */ +/* eslint-disable react/jsx-filename-extension */ +import { render } from '@testing-library/react'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import DummyPlugin2 from './DummyPlugin2'; + +describe('Testing dummy plugin 2', () => { + test('should render props and text elements test for the page component', () => { + render( + + + + + + ); + }); +}); diff --git a/src/components/plugins/DummyPlugin2/DummyPlugin2.tsx b/src/components/plugins/DummyPlugin2/DummyPlugin2.tsx new file mode 100644 index 0000000000..2e96213e23 --- /dev/null +++ b/src/components/plugins/DummyPlugin2/DummyPlugin2.tsx @@ -0,0 +1,12 @@ +import React from 'react'; + +// Validate Extras +function dummyPlugin2(): JSX.Element { + return
    ; +} + +dummyPlugin2.defaultProps = {}; + +dummyPlugin2.propTypes = {}; + +export default dummyPlugin2; diff --git a/src/components/plugins/index.ts b/src/components/plugins/index.ts new file mode 100644 index 0000000000..db688e0da2 --- /dev/null +++ b/src/components/plugins/index.ts @@ -0,0 +1,4 @@ +import DummyPlugin from './DummyPlugin/DummyPlugin'; +import DummyPlugin2 from './DummyPlugin2/DummyPlugin2'; + +export { DummyPlugin, DummyPlugin2 }; diff --git a/src/index.css b/src/index.css deleted file mode 100644 index ec2585e8c0..0000000000 --- a/src/index.css +++ /dev/null @@ -1,13 +0,0 @@ -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; -} - -code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; -} diff --git a/src/index.tsx b/src/index.tsx index 15d9bd34d8..3d528d9d77 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,14 +1,111 @@ -import React from 'react'; +import React, { Suspense } from 'react'; import ReactDOM from 'react-dom'; -import './index.css'; +import { BrowserRouter } from 'react-router-dom'; +import type { NormalizedCacheObject } from '@apollo/client'; +import { + ApolloClient, + ApolloProvider, + InMemoryCache, + HttpLink, + split, +} from '@apollo/client'; +import { getMainDefinition } from '@apollo/client/utilities'; +import { GraphQLWsLink } from '@apollo/client/link/subscriptions'; +import { createClient } from 'graphql-ws'; +import { onError } from '@apollo/link-error'; +import './assets/css/app.css'; +import 'bootstrap/dist/js/bootstrap.min.js'; +import 'react-datepicker/dist/react-datepicker.css'; +import 'flag-icons/css/flag-icons.min.css'; +import { Provider } from 'react-redux'; +import { ToastContainer } from 'react-toastify'; +import 'react-toastify/dist/ReactToastify.css'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; + import App from './App'; -import reportWebVitals from './reportWebVitals'; +import { store } from './state/store'; +import './utils/i18n'; +import { + BACKEND_URL, + REACT_APP_BACKEND_WEBSOCKET_URL, +} from 'Constant/constant'; +import { refreshToken } from 'utils/getRefreshToken'; + +const errorLink = onError( + ({ graphQLErrors, networkError, operation, forward }) => { + if (graphQLErrors) { + graphQLErrors.map(({ message }) => { + if (message === 'User is not authenticated') { + refreshToken().then((success) => { + if (success) { + const oldHeaders = operation.getContext().headers; + operation.setContext({ + headers: { + ...oldHeaders, + authorization: 'Bearer ' + localStorage.getItem('token'), + }, + }); + return forward(operation); + } else { + localStorage.clear(); + } + }); + } + }); + } else if (networkError) { + console.log(`[Network error]: ${networkError}`); + } + } +); + +const httpLink = new HttpLink({ + uri: BACKEND_URL, + headers: { + authorization: 'Bearer ' + localStorage.getItem('token') || '', + }, +}); + +// if didnt work use /subscriptions +const wsLink = new GraphQLWsLink( + createClient({ + url: REACT_APP_BACKEND_WEBSOCKET_URL, + }) +); +// The split function takes three parameters: +// +// * A function that's called for each operation to execute +// * The Link to use for an operation if the function returns a "truthy" value +// * The Link to use for an operation if the function returns a "falsy" value +const splitLink = split( + ({ query }) => { + const definition = getMainDefinition(query); + return ( + definition.kind === 'OperationDefinition' && + definition.operation === 'subscription' + ); + }, + wsLink, + httpLink +); +const client: ApolloClient = new ApolloClient({ + cache: new InMemoryCache(), + link: errorLink.concat(splitLink), +}); +const fallbackLoader =
    ; ReactDOM.render( - - - , + + + + + + + + + + + + , document.getElementById('root') ); - -reportWebVitals(); diff --git a/src/reportWebVitals.ts b/src/reportWebVitals.ts index eb4be08f20..59de1b72a4 100644 --- a/src/reportWebVitals.ts +++ b/src/reportWebVitals.ts @@ -1,4 +1,4 @@ -import { ReportHandler } from 'web-vitals'; +import type { ReportHandler } from 'web-vitals'; const reportWebVitals = (onPerfEntry?: ReportHandler): void => { if (onPerfEntry && onPerfEntry instanceof Function) { diff --git a/src/screens/BlockUser/BlockUser.module.css b/src/screens/BlockUser/BlockUser.module.css new file mode 100644 index 0000000000..ed93446206 --- /dev/null +++ b/src/screens/BlockUser/BlockUser.module.css @@ -0,0 +1,102 @@ +.btnsContainer { + display: flex; + margin: 2.5rem 0 2.5rem 0; +} + +.btnsContainer .btnsBlock { + display: flex; +} + +.btnsContainer .btnsBlock button { + margin-left: 1rem; + display: flex; + justify-content: center; + align-items: center; +} + +.btnsContainer .inputContainer { + flex: 1; + position: relative; +} + +.btnsContainer .input { + width: 70%; + position: relative; +} + +.btnsContainer input { + outline: 1px solid var(--bs-gray-400); +} + +.btnsContainer .inputContainer button { + width: 52px; +} + +.largeBtnsWrapper { + display: flex; +} + +.listBox { + width: 100%; + flex: 1; +} + +.notFound { + flex: 1; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; +} + +@media (max-width: 1020px) { + .btnsContainer { + flex-direction: column; + margin: 1.5rem 0; + } + + .btnsContainer .input { + width: 100%; + } + + .btnsContainer .btnsBlock { + margin: 1.5rem 0 0 0; + justify-content: space-between; + } + + .btnsContainer .btnsBlock button { + margin: 0; + } + + .btnsContainer .btnsBlock div button { + margin-right: 1.5rem; + } +} + +/* For mobile devices */ + +@media (max-width: 520px) { + .btnsContainer { + margin-bottom: 0; + } + + .btnsContainer .btnsBlock { + display: block; + margin-top: 1rem; + margin-right: 0; + } + + .largeBtnsWrapper { + flex-direction: column; + } + + .btnsContainer .btnsBlock div { + flex: 1; + } + + .btnsContainer .btnsBlock button { + margin-bottom: 1rem; + margin-right: 0; + width: 100%; + } +} diff --git a/src/screens/BlockUser/BlockUser.test.tsx b/src/screens/BlockUser/BlockUser.test.tsx new file mode 100644 index 0000000000..1c8be48624 --- /dev/null +++ b/src/screens/BlockUser/BlockUser.test.tsx @@ -0,0 +1,612 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { act, render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { + BLOCK_USER_MUTATION, + UNBLOCK_USER_MUTATION, +} from 'GraphQl/Mutations/mutations'; +import { + BLOCK_PAGE_MEMBER_LIST, + ORGANIZATIONS_LIST, +} from 'GraphQl/Queries/Queries'; +import 'jest-location-mock'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { ToastContainer } from 'react-toastify'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18nForTest from 'utils/i18nForTest'; +import BlockUser from './BlockUser'; + +let userQueryCalled = false; + +const USER_BLOCKED = { + _id: '123', + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@gmail.com', + organizationsBlockedBy: [ + { + _id: 'orgid', + }, + ], +}; + +const USER_UNBLOCKED = { + _id: '456', + firstName: 'Sam', + lastName: 'Smith', + email: 'samsmith@gmail.com', + organizationsBlockedBy: [], +}; + +const DATA_INITIAL = { + data: { + organizationsMemberConnection: { + edges: [USER_BLOCKED, USER_UNBLOCKED], + }, + }, +}; + +const DATA_AFTER_MUTATION = { + data: { + organizationsMemberConnection: { + edges: [ + { + _id: '123', + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@gmail.com', + organizationsBlockedBy: [], + }, + { + _id: '456', + firstName: 'Sam', + lastName: 'Smith', + email: 'samsmith@gmail.com', + organizationsBlockedBy: [ + { + _id: 'orgid', + }, + ], + }, + ], + }, + }, +}; + +const MOCKS = [ + { + request: { + query: ORGANIZATIONS_LIST, + variables: { + id: 'orgid', + }, + }, + result: { + data: { + organizations: [ + { + _id: 'orgid', + image: '', + creator: { + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + name: 'name', + description: 'description', + location: 'location', + members: { + _id: 'id', + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + admins: { + _id: 'id', + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + membershipRequests: { + _id: 'id', + user: { + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + }, + blockedUsers: { + _id: 'id', + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + }, + ], + }, + }, + }, + + { + request: { + query: BLOCK_USER_MUTATION, + variables: { + userId: '456', + orgId: 'orgid', + }, + }, + result: { + data: { + blockUser: { + _id: '456', + }, + }, + }, + }, + + { + request: { + query: UNBLOCK_USER_MUTATION, + variables: { + userId: '123', + orgId: 'orgid', + }, + }, + result: { + data: { + unblockUser: { + _id: '123', + }, + }, + }, + }, + + { + request: { + query: BLOCK_PAGE_MEMBER_LIST, + variables: { + firstName_contains: '', + lastName_contains: '', + orgId: 'orgid', + }, + }, + result: DATA_INITIAL, + newData: (): typeof DATA_AFTER_MUTATION | typeof DATA_INITIAL => { + if (userQueryCalled) { + return DATA_AFTER_MUTATION; + } else { + userQueryCalled = true; + + return DATA_INITIAL; + } + }, + }, + + { + request: { + query: BLOCK_PAGE_MEMBER_LIST, + variables: { + firstName_contains: 'john', + lastName_contains: '', + orgId: 'orgid', + }, + }, + result: { + data: { + organizationsMemberConnection: { + edges: [USER_BLOCKED], + }, + }, + }, + }, + + { + request: { + query: BLOCK_PAGE_MEMBER_LIST, + variables: { + firstName_contains: '', + lastName_contains: 'doe', + orgId: 'orgid', + }, + }, + result: { + data: { + organizationsMemberConnection: { + edges: [USER_BLOCKED], + }, + }, + }, + }, + + { + request: { + query: BLOCK_PAGE_MEMBER_LIST, + variables: { + firstName_contains: 'Peter', + lastName_contains: '', + orgId: 'orgid', + }, + }, + result: { + data: { + organizationsMemberConnection: { + edges: [], + }, + }, + }, + }, +]; +const MOCKS_EMPTY = [ + { + request: { + query: ORGANIZATIONS_LIST, + variables: { + id: 'orgid', + }, + }, + result: { + data: { + organizations: [ + { + _id: 'orgid', + image: '', + creator: { + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + name: 'name', + description: 'description', + location: 'location', + members: { + _id: 'id', + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + admins: { + _id: 'id', + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + membershipRequests: { + _id: 'id', + user: { + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + }, + blockedUsers: { + _id: 'id', + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + }, + ], + }, + }, + }, + + { + request: { + query: BLOCK_PAGE_MEMBER_LIST, + variables: { + firstName_contains: 'Peter', + lastName_contains: '', + orgId: 'orgid', + }, + }, + result: { + data: { + organizationsMemberConnection: { + edges: [], + }, + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); +const link2 = new StaticMockLink(MOCKS_EMPTY, true); + +async function wait(ms = 500): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Testing Block/Unblock user screen', () => { + beforeEach(() => { + userQueryCalled = false; + }); + + test('Components should be rendered properly', async () => { + window.location.assign('/blockuser/id=orgid'); + + render( + + + + + + + + + + ); + + await wait(); + + expect(screen.getByText('Search By First Name')).toBeInTheDocument(); + expect(screen.getByText('List of Users who spammed')).toBeInTheDocument(); + + expect(window.location).toBeAt('/blockuser/id=orgid'); + }); + + test('Testing block user functionality', async () => { + window.location.assign('/blockuser/id=orgid'); + + render( + + + + + + + + + + ); + + await wait(); + + expect(screen.getByTestId('unBlockUser123')).toBeInTheDocument(); + expect(screen.getByTestId('blockUser456')).toBeInTheDocument(); + + userEvent.click(screen.getByTestId('unBlockUser123')); + await wait(); + + expect(screen.getByTestId('blockUser123')).toBeInTheDocument(); + expect(screen.getByTestId('unBlockUser456')).toBeInTheDocument(); + + expect(window.location).toBeAt('/blockuser/id=orgid'); + }); + + test('Testing unblock user functionality', async () => { + window.location.assign('/blockuser/id=orgid'); + + render( + + + + + + + + + + ); + + await wait(); + + expect(screen.getByTestId('unBlockUser123')).toBeInTheDocument(); + expect(screen.getByTestId('blockUser456')).toBeInTheDocument(); + + userEvent.click(screen.getByTestId('blockUser456')); + await wait(); + + expect(screen.getByTestId('blockUser123')).toBeInTheDocument(); + expect(screen.getByTestId('unBlockUser456')).toBeInTheDocument(); + + expect(window.location).toBeAt('/blockuser/id=orgid'); + }); + + test('Testing First Name Filter', async () => { + window.location.assign('/blockuser/id=orgid'); + + render( + + + + + + + + + + ); + + await wait(); + + expect(screen.getByText('John Doe')).toBeInTheDocument(); + expect(screen.getByText('Sam Smith')).toBeInTheDocument(); + + const firstNameInput = screen.getByPlaceholderText(/Search by First Name/i); + // Open Dropdown + await act(async () => { + userEvent.click(screen.getByTestId('nameFilter')); + }); + // Select option and enter first name + userEvent.click(screen.getByTestId('searchByFirstName')); + userEvent.type(firstNameInput, 'john'); + + await wait(700); + + expect(screen.getByText('John Doe')).toBeInTheDocument(); + expect(screen.queryByText('Sam Smith')).not.toBeInTheDocument(); + + expect(window.location).toBeAt('/blockuser/id=orgid'); + }); + + test('Testing Last Name Filter', async () => { + window.location.assign('/blockuser/id=orgid'); + + render( + + + + + + + + + + ); + + await wait(); + + expect(screen.getByText('John Doe')).toBeInTheDocument(); + expect(screen.getByText('Sam Smith')).toBeInTheDocument(); + + // Open Dropdown + await act(async () => { + userEvent.click(screen.getByTestId('nameFilter')); + }); + // Select option and enter last name + userEvent.click(screen.getByTestId('searchByLastName')); + const lastNameInput = screen.getByPlaceholderText(/Search by Last Name/i); + userEvent.type(lastNameInput, 'doe'); + + await wait(700); + + expect(lastNameInput).toHaveValue('doe'); + expect(screen.getByText('John Doe')).toBeInTheDocument(); + expect(screen.queryByText('Sam Smith')).not.toBeInTheDocument(); + expect(window.location).toBeAt('/blockuser/id=orgid'); + }); + + test('Testing No Spammers Present', async () => { + window.location.assign('/blockuser/id=orgid'); + render( + + + + + + + + + + ); + + await wait(); + expect(screen.getByText(/No spammer found/i)).toBeInTheDocument(); + expect(window.location).toBeAt('/blockuser/id=orgid'); + }); + + test('Testing All Members', async () => { + window.location.assign('/blockuser/id=orgid'); + + render( + + + + + + + + + + + ); + await wait(); + await act(async () => { + userEvent.click(screen.getByTestId('userFilter')); + }); + userEvent.click(screen.getByTestId('showMembers')); + + await wait(700); + + expect(screen.getByTestId(/userFilter/i)).toHaveTextContent('All Members'); + expect(screen.getByText('John Doe')).toBeInTheDocument(); + expect(screen.getByText('Sam Smith')).toBeInTheDocument(); + + expect(window.location).toBeAt('/blockuser/id=orgid'); + }); + + test('Testing Blocked Users', async () => { + window.location.assign('/blockuser/id=orgid'); + + render( + + + + + + + + + + + ); + + await act(async () => { + userEvent.click(screen.getByTestId('userFilter')); + }); + + userEvent.click(screen.getByTestId('showBlockedMembers')); + await wait(); + + expect(screen.getByText('John Doe')).toBeInTheDocument(); + expect(screen.queryByText('Sam Smith')).not.toBeInTheDocument(); + + expect(window.location).toBeAt('/blockuser/id=orgid'); + }); + + test('Testing table data getting rendered', async () => { + window.location.assign('/orglist/id=orgid'); + const link = new StaticMockLink(MOCKS, true); + render( + + + + + + + + + + ); + + await wait(); + + expect(screen.getByTestId(/userList/)).toBeInTheDocument(); + expect(screen.getAllByText('Block/Unblock')).toHaveLength(2); + expect(screen.getByText('John Doe')).toBeInTheDocument(); + expect(screen.getByText('Sam Smith')).toBeInTheDocument(); + }); + + test('Testing No Results Found', async () => { + window.location.assign('/blockuser/id=orgid'); + render( + + + + + + + + + + ); + + const input = screen.getByPlaceholderText('Search By First Name'); + await act(async () => { + userEvent.type(input, 'Peter'); + }); + await wait(700); + expect( + screen.getByText(`No results found for "Peter"`) + ).toBeInTheDocument(); + expect(window.location).toBeAt('/blockuser/id=orgid'); + }); +}); diff --git a/src/screens/BlockUser/BlockUser.tsx b/src/screens/BlockUser/BlockUser.tsx new file mode 100644 index 0000000000..2b39a00650 --- /dev/null +++ b/src/screens/BlockUser/BlockUser.tsx @@ -0,0 +1,295 @@ +import { useMutation, useQuery } from '@apollo/client'; +import React, { useEffect, useState } from 'react'; +import { Dropdown, Form, Table } from 'react-bootstrap'; +import Button from 'react-bootstrap/Button'; +import { toast } from 'react-toastify'; + +import { Search } from '@mui/icons-material'; +import SortIcon from '@mui/icons-material/Sort'; +import { + BLOCK_USER_MUTATION, + UNBLOCK_USER_MUTATION, +} from 'GraphQl/Mutations/mutations'; +import { BLOCK_PAGE_MEMBER_LIST } from 'GraphQl/Queries/Queries'; +import OrganizationScreen from 'components/OrganizationScreen/OrganizationScreen'; +import TableLoader from 'components/TableLoader/TableLoader'; +import { useTranslation } from 'react-i18next'; +import debounce from 'utils/debounce'; +import { errorHandler } from 'utils/errorHandler'; +import styles from './BlockUser.module.css'; + +interface InterfaceMember { + _id: string; + email: string; + firstName: string; + lastName: string; + organizationsBlockedBy: { + _id: string; + __typename: 'Organization'; + }[]; + __typename: 'User'; +} + +const Requests = (): JSX.Element => { + const { t } = useTranslation('translation', { + keyPrefix: 'blockUnblockUser', + }); + + document.title = t('title'); + const currentUrl = window.location.href.split('=')[1]; + const [membersData, setMembersData] = useState([]); + const [searchByFirstName, setSearchByFirstName] = useState(true); + const [searchByName, setSearchByName] = useState(''); + const [showBlockedMembers, setShowBlockedMembers] = useState(false); + + const { + data: memberData, + loading: loadingMembers, + error: memberError, + refetch: memberRefetch, + } = useQuery(BLOCK_PAGE_MEMBER_LIST, { + variables: { + orgId: currentUrl, + firstName_contains: '', + lastName_contains: '', + }, + }); + + const [blockUser] = useMutation(BLOCK_USER_MUTATION); + const [unBlockUser] = useMutation(UNBLOCK_USER_MUTATION); + + useEffect(() => { + if (!memberData) { + setMembersData([]); + return; + } + + if (showBlockedMembers == false) { + setMembersData(memberData?.organizationsMemberConnection.edges); + } else { + const blockUsers = memberData?.organizationsMemberConnection.edges.filter( + (user: InterfaceMember) => + user.organizationsBlockedBy.some((org) => org._id === currentUrl) + ); + setMembersData(blockUsers); + } + }, [memberData, showBlockedMembers]); + + const handleBlockUser = async (userId: string): Promise => { + try { + const { data } = await blockUser({ + variables: { + userId, + orgId: currentUrl, + }, + }); + /* istanbul ignore next */ + if (data) { + toast.success(t('blockedSuccessfully')); + memberRefetch(); + } + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + + const handleUnBlockUser = async (userId: string): Promise => { + try { + const { data } = await unBlockUser({ + variables: { + userId, + orgId: currentUrl, + }, + }); + /* istanbul ignore next */ + if (data) { + toast.success(t('Un-BlockedSuccessfully')); + memberRefetch(); + } + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + + /* istanbul ignore next */ + if (memberError) { + toast.error(memberError.message); + } + + const handleSearch = (e: any): void => { + const { value } = e.target; + setSearchByName(value); + memberRefetch({ + orgId: currentUrl, + firstName_contains: searchByFirstName ? value : '', + lastName_contains: searchByFirstName ? '' : value, + }); + }; + + const handleSearchDebounced = debounce(handleSearch); + const headerTitles: string[] = [ + '#', + t('name'), + t('email'), + t('block_unblock'), + ]; + + return ( + <> + + {/* Buttons Container */} +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    + {/* Table */} + {loadingMembers == false && + membersData.length === 0 && + searchByName.length > 0 ? ( +
    +

    + {t('noResultsFoundFor')} "{searchByName}" +

    +
    + ) : loadingMembers == false && membersData.length === 0 ? ( +
    +

    {t('noSpammerFound')}

    +
    + ) : ( +
    + {loadingMembers ? ( + + ) : ( + + + + {headerTitles.map((title: string, index: number) => { + return ( + + ); + })} + + + + {membersData.map((user, index: number) => { + return ( + + + + + + + ); + })} + +
    + {title} +
    {index + 1}{`${user.firstName} ${user.lastName}`}{user.email} + {user.organizationsBlockedBy.some( + (spam: any) => spam._id === currentUrl + ) ? ( + + ) : ( + + )} +
    + )} +
    + )} +
    + + ); +}; + +export default Requests; diff --git a/src/screens/EventDashboard/EventDashboard.mocks.ts b/src/screens/EventDashboard/EventDashboard.mocks.ts new file mode 100644 index 0000000000..fe5b66a959 --- /dev/null +++ b/src/screens/EventDashboard/EventDashboard.mocks.ts @@ -0,0 +1,227 @@ +import { EVENT_DETAILS } from 'GraphQl/Queries/Queries'; +import { EVENT_FEEDBACKS } from 'GraphQl/Queries/Queries'; + +const constantMocks = [ + { + request: { + query: EVENT_FEEDBACKS, + variables: { + id: 'event123', + }, + }, + result: { + data: { + event: { + _id: 'event123', + feedback: [], + averageFeedbackScore: 0, + }, + }, + }, + }, + { + request: { + query: EVENT_FEEDBACKS, + variables: { + id: '', + }, + }, + result: { + data: { + event: { + _id: '', + feedback: [], + averageFeedbackScore: 0, + }, + }, + }, + }, + { + request: { + query: EVENT_DETAILS, + variables: { + id: '', + }, + }, + result: { + data: { + event: { + _id: '', + title: 'Event Title', + description: 'Event Description', + startDate: '1/1/23', + endDate: '2/2/23', + startTime: '08:00:00', + endTime: '09:00:00', + allDay: false, + location: 'India', + organization: { + _id: '', + members: [], + }, + attendees: [], + projects: [], + }, + }, + }, + }, +]; + +// Mock 1 +export const queryMockWithTime = [ + { + request: { + query: EVENT_DETAILS, + variables: { + id: 'event123', + }, + }, + result: { + data: { + event: { + _id: 'event123', + title: 'Event Title', + description: 'Event Description', + startDate: '1/1/23', + endDate: '2/2/23', + startTime: '08:00:00', + endTime: '09:00:00', + allDay: false, + location: 'India', + organization: { + _id: 'org1', + members: [{ _id: 'user1', firstName: 'John', lastName: 'Doe' }], + }, + attendees: [{ _id: 'user1' }], + projects: [], + }, + }, + }, + }, + ...constantMocks, +]; + +// Mock 2 +export const queryMockWithoutTime = [ + { + request: { + query: EVENT_DETAILS, + variables: { + id: 'event123', + }, + }, + result: { + data: { + event: { + _id: 'event123', + title: 'Event Title', + description: 'Event Description', + startDate: '1/1/23', + endDate: '2/2/23', + startTime: null, + endTime: null, + allDay: false, + location: 'India', + organization: { + _id: 'org1', + members: [{ _id: 'user1', firstName: 'John', lastName: 'Doe' }], + }, + attendees: [{ _id: 'user1' }], + projects: [], + }, + }, + }, + }, + ...constantMocks, +]; + +// Mock 3 +export const queryMockWithProject = [ + { + request: { + query: EVENT_DETAILS, + variables: { + id: 'event123', + }, + }, + result: { + data: { + event: { + _id: 'event123', + title: 'Event Title', + description: 'Event Description', + startDate: '1/1/23', + endDate: '2/2/23', + startTime: '08:00:00', + endTime: '09:00:00', + allDay: false, + location: 'India', + organization: { + _id: 'org1', + members: [{ _id: 'user1', firstName: 'John', lastName: 'Doe' }], + }, + attendees: [{ _id: 'user1' }], + projects: [ + { + _id: 'project1', + title: 'Project 1', + description: 'Project Description 1', + tasks: [], + }, + ], + }, + }, + }, + }, + ...constantMocks, +]; + +// Mock 4 +export const queryMockWithProjectAndTask = [ + { + request: { + query: EVENT_DETAILS, + variables: { + id: 'event123', + }, + }, + result: { + data: { + event: { + _id: 'event123', + title: 'Event Title', + description: 'Event Description', + startDate: '1/1/23', + endDate: '2/2/23', + startTime: '08:00:00', + endTime: '09:00:00', + allDay: false, + location: 'India', + organization: { + _id: 'org1', + members: [{ _id: 'user1', firstName: 'John', lastName: 'Doe' }], + }, + attendees: [{ _id: 'user1' }], + projects: [ + { + _id: 'project1', + title: 'Project 1', + description: 'Project Description 1', + tasks: [ + { + _id: 'task1', + title: 'Task 1', + description: 'Description 1', + deadline: '22/12/23', + completed: false, + volunteers: [], + }, + ], + }, + ], + }, + }, + }, + }, + ...constantMocks, +]; diff --git a/src/screens/EventDashboard/EventDashboard.module.css b/src/screens/EventDashboard/EventDashboard.module.css new file mode 100644 index 0000000000..10ac2ee4ed --- /dev/null +++ b/src/screens/EventDashboard/EventDashboard.module.css @@ -0,0 +1,198 @@ +.mainpage { + display: flex; + flex-direction: row; +} + +.toporgloc { + padding-top: 8px; + font-size: 16px; +} +.sidebar { + z-index: 0; + padding-top: 5px; + margin: 0; + height: 100%; +} +.sidebar:after { + content: ''; + background-color: #f7f7f7; + position: absolute; + width: 2px; + height: 600px; + top: 10px; + left: 94%; + display: block; +} +.sidebarsticky { + padding-left: 30px; +} +.sidebarsticky > p { + margin-top: -10px; + width: 90%; +} + +.description { + word-wrap: break-word; +} + +.titlename { + color: #707070; + font-weight: 600; + font-size: 20px; + margin-bottom: 30px; + padding-bottom: 5px; + width: 100%; +} +.tagdetailsGreen > button { + background-color: #31bb6b; + color: white; + outline: none; + cursor: pointer; + transition: transform 0.2s, box-shadow 0.2s; + border: none; + border-radius: 5px; + margin-top: -12px; + margin-bottom: 10px; + margin-right: 30px; + padding-right: 20px; + padding-left: 20px; + padding-top: 5px; + padding-bottom: 5px; +} +.mainpageright > hr { + margin-top: 20px; + width: 100%; + margin-left: -15px; + margin-right: -15px; + margin-bottom: 20px; +} +.justifysp { + display: flex; + justify-content: space-between; +} +.org_about_img { + margin-top: 0px; + margin-bottom: 30px; + border-radius: 5px; + max-width: 100%; + height: auto; + width: 90%; +} +.invitebtn { + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + border-radius: 5px; + background-color: #31bb6b; + width: 20%; + height: 40px; + font-size: 16px; + color: white; + outline: none; + font-weight: 600; + cursor: pointer; + transition: transform 0.2s, box-shadow 0.2s; +} +.flexdir { + display: flex; + flex-direction: row; + justify-content: space-between; + border: none; +} + +.logintitleinvite { + color: #707070; + font-weight: 600; + font-size: 20px; + margin-bottom: 20px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 40%; +} + +.cancel > i { + margin-top: 5px; + transform: scale(1.2); + cursor: pointer; + color: #707070; +} + +.greenregbtn { + margin: 1rem 0 0; + margin-top: 10px; + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + padding: 10px 10px; + border-radius: 5px; + background-color: #31bb6b; + width: 100%; + font-size: 16px; + color: white; + outline: none; + font-weight: 600; + cursor: pointer; + transition: transform 0.2s, box-shadow 0.2s; + width: 100%; +} + +.loader, +.loader:after { + border-radius: 50%; + width: 10em; + height: 10em; +} +.loader { + margin: 60px auto; + margin-top: 35vh !important; + font-size: 10px; + position: relative; + text-indent: -9999em; + border-top: 1.1em solid rgba(255, 255, 255, 0.2); + border-right: 1.1em solid rgba(255, 255, 255, 0.2); + border-bottom: 1.1em solid rgba(255, 255, 255, 0.2); + border-left: 1.1em solid #febc59; + -webkit-transform: translateZ(0); + -ms-transform: translateZ(0); + transform: translateZ(0); + -webkit-animation: load8 1.1s infinite linear; + animation: load8 1.1s infinite linear; +} +@-webkit-keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} +@keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +.cardContainer { + box-shadow: 0 5px 20px rgba(0, 0, 0, 0.05); +} + +.dashboardIcon { + font-size: 50px; + color: #31bb6b; +} + +.counterNumber { + font-size: 24px; + margin-bottom: 0rem !important; +} + +.counterHead { + color: #565658; + font-size: 15px; + margin-bottom: 0rem !important; +} diff --git a/src/screens/EventDashboard/EventDashboard.test.tsx b/src/screens/EventDashboard/EventDashboard.test.tsx new file mode 100644 index 0000000000..b595f893eb --- /dev/null +++ b/src/screens/EventDashboard/EventDashboard.test.tsx @@ -0,0 +1,192 @@ +import React from 'react'; +import { fireEvent, render, waitFor, act } from '@testing-library/react'; +import EventDashboard from './EventDashboard'; +import { BrowserRouter } from 'react-router-dom'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; +import { ToastContainer } from 'react-toastify'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { type DefaultOptions } from '@apollo/client'; +import { + queryMockWithProject, + queryMockWithTime, + queryMockWithoutTime, + queryMockWithProjectAndTask, +} from './EventDashboard.mocks'; + +// We want to disable all forms of caching so that we do not need to define a custom merge function in testing for the network requests +const defaultOptions: DefaultOptions = { + watchQuery: { + fetchPolicy: 'no-cache', + errorPolicy: 'ignore', + }, + query: { + fetchPolicy: 'no-cache', + errorPolicy: 'all', + }, +}; + +// Mock the modules for PieChart rendering as they require a trasformer being used (which is not done by Jest) +// These modules are used by the Feedback components +jest.mock('@mui/x-charts/PieChart', () => ({ + pieArcLabelClasses: jest.fn(), + PieChart: jest.fn().mockImplementation(() => <>Test), + pieArcClasses: jest.fn(), +})); + +// We will wait for 500 ms after each test to ensure that the queries and rendering of the nested components such as `Feedback` and `Statistics` is complete before moving on to the next test suite +// This is important to mitigate the cleanup errors due to nesting of components +async function wait(ms = 500): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Testing Event Dashboard Screen', () => { + beforeEach(() => { + global.window = Object.create(window); + Object.defineProperty(window, 'location', { + value: { + href: 'http://localhost:3000/event/event123', + }, + writable: true, + }); + }); + + test('The page should display event details correctly and also show the time if provided', async () => { + const { queryByText, queryAllByText } = render( + + + + + + + + + ); + + await waitFor(() => expect(queryAllByText('Event Title').length).toBe(2)); + + await waitFor(() => + expect(queryAllByText('Event Description').length).toBe(2) + ); + + await waitFor(() => expect(queryByText('India')).toBeInTheDocument()); + + // Relevant message should be shown if the projects are 0 in length + await waitFor(() => + expect( + queryByText('There are no active projects for this event!') + ).toBeInTheDocument() + ); + + await wait(); + }); + + test('The page should display event details correctly and should not show the time if it is null', async () => { + const { queryAllByText } = render( + + + + + + + + + ); + + await waitFor(() => expect(queryAllByText('Event Title').length).toBe(2)); + + await wait(); + }); + + test('The page should display event project details correctly when provided', async () => { + const { queryByText } = render( + + + + + + + + + + + ); + + await waitFor(() => expect(queryByText('Project 1')).toBeInTheDocument()); + + await waitFor(() => + expect(queryByText('Project Description 1')).toBeInTheDocument() + ); + + await wait(); + }); + + test('The modals from the page should work properly', async () => { + const { queryByRole, getByRole, queryAllByText } = render( + + + + + + + + + ); + + await waitFor(() => expect(queryAllByText('Event Title').length).toBe(2)); + + // Add Event Project Modal + await waitFor(() => + fireEvent.click( + getByRole('button', { name: 'addEventProject' }) as HTMLElement + ) + ); + + fireEvent.click(queryByRole('button', { name: /close/i }) as HTMLElement); + // Edit Event Project Modal + await waitFor(() => + fireEvent.click( + getByRole('button', { name: 'editEventProject' }) as HTMLElement + ) + ); + fireEvent.click(queryByRole('button', { name: /close/i }) as HTMLElement); + + // Delete Event Project Modal + await waitFor(() => + fireEvent.click( + getByRole('button', { name: 'deleteEventProject' }) as HTMLElement + ) + ); + fireEvent.click(queryByRole('button', { name: /close/i }) as HTMLElement); + + // Add Task Modal + await waitFor(() => + fireEvent.click(getByRole('button', { name: 'addTask' }) as HTMLElement) + ); + fireEvent.click(queryByRole('button', { name: /close/i }) as HTMLElement); + + await wait(); + }); +}); diff --git a/src/screens/EventDashboard/EventDashboard.tsx b/src/screens/EventDashboard/EventDashboard.tsx new file mode 100644 index 0000000000..f47988a2fc --- /dev/null +++ b/src/screens/EventDashboard/EventDashboard.tsx @@ -0,0 +1,252 @@ +import React, { useEffect, useState } from 'react'; +import Row from 'react-bootstrap/Row'; +import Col from 'react-bootstrap/Col'; +import { useQuery } from '@apollo/client'; +import { Container } from 'react-bootstrap'; +import styles from './EventDashboard.module.css'; +import { AddEventProjectModal } from 'components/EventProjectModals/AddEventProjectModal'; +import { UpdateEventProjectModal } from 'components/EventProjectModals/UpdateEventProjectModal'; +import { DeleteEventProjectModal } from 'components/EventProjectModals/DeleteEventProjectModal'; +import { AddTaskModal } from 'components/TaskModals/AddTaskModal'; +import { EVENT_DETAILS } from 'GraphQl/Queries/Queries'; +import Button from 'react-bootstrap/Button'; +import List from '@mui/material/List'; +import { TaskListItem } from 'components/TaskListItem/TaskListItem'; +import Loader from 'components/Loader/Loader'; +import { LeftDrawerEventWrapper } from 'components/LeftDrawerEvent/LeftDrawerEventWrapper'; + +interface InterfaceEventTask { + _id: string; + title: string; + description: string; + deadline: string; + completed: boolean; + volunteers: { + _id: string; + firstName: string; + lastName: string; + }[]; +} +interface InterfaceEventProject { + _id: string; + title: string; + description: string; + tasks: InterfaceEventTask[]; +} + +const EventDashboard = (): JSX.Element => { + // Get the Event ID from the URL + document.title = 'Event Dashboard'; + + const [eventId, setEventId] = useState(''); + + useEffect(() => { + setEventId(window.location.href.split('/')[4]); + }, [window.location.href]); + + // Data fetching + const { + data: eventData, + loading: eventInfoLoading, + refetch: refetchEventData, + } = useQuery(EVENT_DETAILS, { + variables: { id: eventId }, + }); + + const [currentProject, setCurrentProject] = useState({ + _id: '', + title: '', + description: '', + }); + + // State management for modals + const [showAddEventProjectModal, setShowAddEventProjectModal] = + useState(false); + const [showAddTaskModal, setShowAddTaskModal] = useState(false); + const [showUpdateEventProjectModal, setShowUpdateEventProjectModal] = + useState(false); + const [showDeleteEventProjectModal, setShowDeleteEventProjectModal] = + useState(false); + + // Render the loading screen + if (eventInfoLoading) { + return ; + } + + return ( + + + +
    +
    + {/* Side Bar - Static Information about the Event */} +

    {eventData.event.title}

    +

    + {eventData.event.description} +

    +

    + Location: {eventData.event.location} +

    +

    + Start: {eventData.event.startDate}{' '} + {eventData.event.startTime !== null + ? `- ${eventData.event.startTime}` + : ``} +

    +

    + End: {eventData.event.endDate}{' '} + {eventData.event.endTime !== null + ? `- ${eventData.event.endTime}` + : ``} +

    +

    + Registrants: {eventData.event.attendees.length} +

    +
    +
    +
    + + + {/* Main Screen Container */} + +
    + +

    Event Projects

    +
    + + {eventData.event.projects.length == 0 + ? `There are no active projects for this event!` + : null} + {eventData.event.projects.map( + (project: InterfaceEventProject) => ( + +
    +
    +
    +

    + {project.title} +

    +

    + {project.description} +

    +
    +
    +
    +
    Tasks
    +
    + +
    + {!project.tasks.length + ? `There are no tasks for this project.` + : null} +
    + {project.tasks.map((task) => ( + + ))} +
    +
    + + + +
    +
    + + ) + )} +
    +
    +
    + +
    + + {/* Wrapper for Different Modals */} + { + setShowAddEventProjectModal(false); + }} + eventId={eventId} + refetchData={refetchEventData} + /> + + { + setShowUpdateEventProjectModal(false); + }} + refetchData={refetchEventData} + project={currentProject} + /> + + { + setShowDeleteEventProjectModal(false); + }} + refetchData={refetchEventData} + project={currentProject} + /> + + { + setShowAddTaskModal(false); + }} + refetchData={refetchEventData} + projectId={currentProject._id} + /> +
    + ); +}; + +export default EventDashboard; diff --git a/src/screens/ForgotPassword/ForgotPassword.module.css b/src/screens/ForgotPassword/ForgotPassword.module.css new file mode 100644 index 0000000000..74e09aecc6 --- /dev/null +++ b/src/screens/ForgotPassword/ForgotPassword.module.css @@ -0,0 +1,71 @@ +.pageWrapper { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100vh; +} + +.cardBody { + padding: 2rem; + background-color: #fff; + border-radius: 0.8rem; + border: 1px solid var(--bs-gray-200); +} + +.keyWrapper { + height: 72px; + width: 72px; + transform: rotate(180deg); + position: relative; + overflow: hidden; + display: block; + display: flex; + justify-content: center; + align-items: center; + border-radius: 50%; + margin: 1rem auto; +} + +.keyWrapper .themeOverlay { + position: absolute; + background-color: var(--bs-primary); + height: 100%; + width: 100%; + opacity: 0.15; +} + +.keyWrapper .keyLogo { + height: 42px; + width: 42px; + -webkit-animation: zoomIn 0.3s ease-in-out; + animation: zoomIn 0.3s ease-in-out; +} + +@-webkit-keyframes zoomIn { + 0% { + opacity: 0; + -webkit-transform: scale(0.5); + transform: scale(0.5); + } + + 100% { + opacity: 1; + -webkit-transform: scale(1); + transform: scale(1); + } +} + +@keyframes zoomIn { + 0% { + opacity: 0; + -webkit-transform: scale(0.5); + transform: scale(0.5); + } + + 100% { + opacity: 1; + -webkit-transform: scale(1); + transform: scale(1); + } +} diff --git a/src/screens/ForgotPassword/ForgotPassword.test.tsx b/src/screens/ForgotPassword/ForgotPassword.test.tsx new file mode 100644 index 0000000000..94db5b2839 --- /dev/null +++ b/src/screens/ForgotPassword/ForgotPassword.test.tsx @@ -0,0 +1,259 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { act, render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import 'jest-localstorage-mock'; +import 'jest-location-mock'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; + +import { + FORGOT_PASSWORD_MUTATION, + GENERATE_OTP_MUTATION, +} from 'GraphQl/Mutations/mutations'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18nForTest from 'utils/i18nForTest'; +import ForgotPassword from './ForgotPassword'; + +const MOCKS = [ + { + request: { + query: FORGOT_PASSWORD_MUTATION, + variables: { + userOtp: '12345', + newPassword: 'johndoe', + otpToken: 'otpToken', + }, + }, + result: { + data: { + forgotPassword: true, + }, + }, + }, + { + request: { + query: GENERATE_OTP_MUTATION, + variables: { + email: 'johndoe@gmail.com', + }, + }, + result: { + data: { + otp: { + otpToken: 'otpToken', + }, + }, + }, + }, +]; +const link = new StaticMockLink(MOCKS, true); +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} +beforeEach(() => { + localStorage.setItem('IsLoggedIn', 'FALSE'); +}); +afterEach(() => { + localStorage.clear(); +}); + +describe('Testing Forgot Password screen', () => { + test('Component should be rendered properly', async () => { + window.location.assign('/orglist'); + + render( + + + + + + + + + + ); + + await wait(); + + expect(screen.getByText(/Forgot Password/i)).toBeInTheDocument(); + expect(screen.getByText(/Registered Email/i)).toBeInTheDocument(); + expect(screen.getByText(/Get Otp/i)).toBeInTheDocument(); + expect(screen.getByText(/Back to Login/i)).toBeInTheDocument(); + expect(window.location).toBeAt('/orglist'); + }); + + test('Testing, If user is already loggedIn', async () => { + localStorage.setItem('IsLoggedIn', 'TRUE'); + + render( + + + + + + + + + + ); + + await wait(); + }); + + test('Testing get OTP functionality', async () => { + const formData = { + email: 'johndoe@gmail.com', + }; + + render( + + + + + + + + + + ); + + await wait(); + + userEvent.type( + screen.getByPlaceholderText(/Registered email/i), + formData.email + ); + + userEvent.click(screen.getByText('Get OTP')); + await wait(); + }); + + test('Testing forgot password functionality', async () => { + const formData = { + userOtp: '12345', + newPassword: 'johnDoe', + confirmNewPassword: 'johnDoe', + email: 'johndoe@gmail.com', + }; + + render( + + + + + + + + + + ); + + await wait(); + + userEvent.type( + screen.getByPlaceholderText(/Registered email/i), + formData.email + ); + + userEvent.click(screen.getByText('Get OTP')); + await wait(); + + userEvent.type(screen.getByPlaceholderText('e.g. 12345'), formData.userOtp); + userEvent.type(screen.getByTestId('newPassword'), formData.newPassword); + userEvent.type( + screen.getByTestId('confirmNewPassword'), + formData.confirmNewPassword + ); + localStorage.setItem('otpToken', 'lorem ipsum'); + userEvent.click(screen.getByText('Change Password')); + await wait(); + }); + + test('Testing forgot password functionality, when new password and confirm password is not same', async () => { + const formData = { + email: 'johndoe@gmail.com', + userOtp: '12345', + newPassword: 'johnDoe', + confirmNewPassword: 'doeJohn', + }; + + render( + + + + + + + + + + ); + + await wait(); + + userEvent.type( + screen.getByPlaceholderText(/Registered email/i), + formData.email + ); + + userEvent.click(screen.getByText('Get OTP')); + await wait(); + + userEvent.type(screen.getByPlaceholderText('e.g. 12345'), formData.userOtp); + userEvent.type(screen.getByTestId('newPassword'), formData.newPassword); + userEvent.type( + screen.getByTestId('confirmNewPassword'), + formData.confirmNewPassword + ); + + userEvent.click(screen.getByText('Change Password')); + }); + + test('Testing forgot password functionality, when otp token is not present', async () => { + const formData = { + userOtp: '12345', + newPassword: 'johnDoe', + confirmNewPassword: 'johnDoe', + email: 'johndoe@gmail.com', + }; + + localStorage.setItem('otpToken', ''); + + render( + + + + + + + + + + ); + + await wait(); + + userEvent.type( + screen.getByPlaceholderText(/Registered email/i), + formData.email + ); + + userEvent.click(screen.getByText('Get OTP')); + await wait(); + + userEvent.type(screen.getByPlaceholderText('e.g. 12345'), formData.userOtp); + userEvent.type(screen.getByTestId('newPassword'), formData.newPassword); + userEvent.type( + screen.getByTestId('confirmNewPassword'), + formData.confirmNewPassword + ); + userEvent.click(screen.getByText('Change Password')); + }); +}); diff --git a/src/screens/ForgotPassword/ForgotPassword.tsx b/src/screens/ForgotPassword/ForgotPassword.tsx new file mode 100644 index 0000000000..10b4c4db0b --- /dev/null +++ b/src/screens/ForgotPassword/ForgotPassword.tsx @@ -0,0 +1,247 @@ +import { useMutation } from '@apollo/client'; +import type { ChangeEvent } from 'react'; +import React, { useEffect, useState } from 'react'; +import { Link } from 'react-router-dom'; +import { toast } from 'react-toastify'; + +import { + FORGOT_PASSWORD_MUTATION, + GENERATE_OTP_MUTATION, +} from 'GraphQl/Mutations/mutations'; +import { ReactComponent as KeyLogo } from 'assets/svgs/key.svg'; + +import ArrowRightAlt from '@mui/icons-material/ArrowRightAlt'; +import Loader from 'components/Loader/Loader'; +import { Form } from 'react-bootstrap'; +import Button from 'react-bootstrap/Button'; +import { useTranslation } from 'react-i18next'; +import { errorHandler } from 'utils/errorHandler'; +import styles from './ForgotPassword.module.css'; + +const ForgotPassword = (): JSX.Element => { + const { t } = useTranslation('translation', { + keyPrefix: 'forgotPassword', + }); + + document.title = t('title'); + + const [showEnterEmail, setShowEnterEmail] = useState(true); + + const [registeredEmail, setregisteredEmail] = useState(''); + + const [forgotPassFormData, setForgotPassFormData] = useState({ + userOtp: '', + newPassword: '', + confirmNewPassword: '', + }); + + const [otp, { loading: otpLoading }] = useMutation(GENERATE_OTP_MUTATION); + const [forgotPassword, { loading: forgotPasswordLoading }] = useMutation( + FORGOT_PASSWORD_MUTATION + ); + const isLoggedIn = localStorage.getItem('IsLoggedIn'); + useEffect(() => { + if (isLoggedIn == 'TRUE') { + window.location.replace('/orglist'); + } + return () => { + localStorage.removeItem('otpToken'); + }; + }, []); + + const getOTP = async (e: ChangeEvent): Promise => { + e.preventDefault(); + + try { + const { data } = await otp({ + variables: { + email: registeredEmail, + }, + }); + + if (data) { + localStorage.setItem('otpToken', data.otp.otpToken); + toast.success(t('OTPsent')); + setShowEnterEmail(false); + } + } catch (error: any) { + if (error.message === 'User not found') { + toast.warn(t('emailNotRegistered')); + } else if (error.message === 'Failed to fetch') { + toast.error(t('talawaApiUnavailable')); + } else { + toast.error(t('errorSendingMail')); + } + } + }; + + const submitForgotPassword = async ( + e: ChangeEvent + ): Promise => { + e.preventDefault(); + const { userOtp, newPassword, confirmNewPassword } = forgotPassFormData; + + if (newPassword !== confirmNewPassword) { + toast.error(t('passwordMismatches')); + return; + } + + const otpToken = localStorage.getItem('otpToken'); + + if (!otpToken) { + return; + } + + try { + const { data } = await forgotPassword({ + variables: { + userOtp, + newPassword, + otpToken, + }, + }); + + /* istanbul ignore next */ + if (data) { + toast.success(t('passwordChanges')); + setShowEnterEmail(true); + setForgotPassFormData({ + userOtp: '', + newPassword: '', + confirmNewPassword: '', + }); + } + } catch (error: any) { + setShowEnterEmail(true); + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + + if (otpLoading || forgotPasswordLoading) { + return ; + } + return ( + <> +
    +
    +
    +
    +
    +
    + +
    +

    {t('forgotPassword')}

    + {showEnterEmail ? ( +
    +
    + + {t('registeredEmail')}: + +
    + + setregisteredEmail(e.target.value) + } + /> +
    + +
    +
    + ) : ( +
    +
    + {t('enterOtp')}: + + setForgotPassFormData({ + ...forgotPassFormData, + userOtp: e.target.value, + }) + } + /> + + {t('enterNewPassword')}: + + + setForgotPassFormData({ + ...forgotPassFormData, + newPassword: e.target.value, + }) + } + /> + + {t('cofirmNewPassword')}: + + + setForgotPassFormData({ + ...forgotPassFormData, + confirmNewPassword: e.target.value, + }) + } + /> + + +
    + )} +
    + + + {t('backToLogin')} + +
    +
    +
    +
    +
    + + ); +}; + +export default ForgotPassword; diff --git a/src/screens/LoginPage/LoginPage.module.css b/src/screens/LoginPage/LoginPage.module.css new file mode 100644 index 0000000000..8e8e314ba9 --- /dev/null +++ b/src/screens/LoginPage/LoginPage.module.css @@ -0,0 +1,188 @@ +.login_background { + min-height: 100vh; +} + +.row .left_portion { + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + height: 100vh; +} + +.row .left_portion .inner .palisadoes_logo { + width: 600px; + height: auto; +} + +.row .right_portion { + min-height: 100vh; + position: relative; + overflow-y: scroll; + display: flex; + flex-direction: column; + justify-content: center; + padding: 1rem 2.5rem; + background: var(--bs-white); +} + +.row .right_portion::-webkit-scrollbar { + display: none; +} + +.row .right_portion .langChangeBtn { + margin: 0; + position: absolute; + top: 1rem; + left: 2rem; +} + +.row .right_portion .talawa_logo { + height: 150px; + width: 150px; + display: block; + margin: 1rem auto; + -webkit-animation: zoomIn 0.3s ease-in-out; + animation: zoomIn 0.3s ease-in-out; +} + +.row .orText { + display: block; + position: absolute; + top: calc(-0.7rem - 0.5rem); + left: calc(50% - 2.6rem); + margin: 0 auto; + padding: 0.5rem 2rem; + z-index: 100; + background: var(--bs-white); + color: var(--bs-secondary); +} + +@media (max-width: 992px) { + .row .left_portion { + padding: 0 2rem; + } + + .row .left_portion .inner .palisadoes_logo { + width: 100%; + } +} + +@media (max-width: 769px) { + .row { + flex-direction: column-reverse; + } + + .row .right_portion, + .row .left_portion { + height: unset; + } + + .row .right_portion { + min-height: 100vh; + overflow-y: unset; + } + + .row .left_portion .inner { + display: flex; + justify-content: center; + } + + .row .left_portion .inner .palisadoes_logo { + height: 70px; + width: unset; + position: absolute; + margin: 0.5rem; + top: 0; + right: 0; + z-index: 100; + } + + .row .left_portion .inner p { + margin-bottom: 0; + padding: 1rem; + } +} + +@media (max-width: 577px) { + .row .right_portion { + padding: 1rem 1rem 0 1rem; + } + + .row .right_portion .langChangeBtn { + position: absolute; + margin: 1rem; + left: 0; + top: 0; + } + + .marginTopForReg { + margin-top: 4rem !important; + } + + .row .right_portion .talawa_logo { + height: 120px; + margin: 0 auto 2rem auto; + } +} + +.active_tab { + -webkit-animation: fadeIn 0.3s ease-in-out; + animation: fadeIn 0.3s ease-in-out; +} + +@-webkit-keyframes zoomIn { + 0% { + opacity: 0; + -webkit-transform: scale(0.5); + transform: scale(0.5); + } + + 100% { + opacity: 1; + -webkit-transform: scale(1); + transform: scale(1); + } +} + +@keyframes zoomIn { + 0% { + opacity: 0; + -webkit-transform: scale(0.5); + transform: scale(0.5); + } + + 100% { + opacity: 1; + -webkit-transform: scale(1); + transform: scale(1); + } +} + +@-webkit-keyframes fadeIn { + 0% { + opacity: 0; + -webkit-transform: translateY(2rem); + transform: translateY(2rem); + } + + 100% { + opacity: 1; + -webkit-transform: translateY(0); + transform: translateY(0); + } +} + +@keyframes fadeIn { + 0% { + opacity: 0; + -webkit-transform: translateY(2rem); + transform: translateY(2rem); + } + + 100% { + opacity: 1; + -webkit-transform: translateY(0); + transform: translateY(0); + } +} diff --git a/src/screens/LoginPage/LoginPage.test.tsx b/src/screens/LoginPage/LoginPage.test.tsx new file mode 100644 index 0000000000..c92ba07e43 --- /dev/null +++ b/src/screens/LoginPage/LoginPage.test.tsx @@ -0,0 +1,582 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { act, render, screen } from '@testing-library/react'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; +import 'jest-localstorage-mock'; +import 'jest-location-mock'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import LoginPage from './LoginPage'; +import { + LOGIN_MUTATION, + RECAPTCHA_MUTATION, + SIGNUP_MUTATION, +} from 'GraphQl/Mutations/mutations'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; + +const MOCKS = [ + { + request: { + query: LOGIN_MUTATION, + variables: { + email: 'johndoe@gmail.com', + password: 'johndoe', + }, + }, + result: { + data: { + login: { + user: { + _id: '1', + userType: 'ADMIN', + adminApproved: true, + }, + accessToken: 'accessToken', + refreshToken: 'refreshToken', + }, + }, + }, + }, + { + request: { + query: SIGNUP_MUTATION, + variables: { + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@gmail.com', + password: 'johnDoe', + }, + }, + result: { + data: { + register: { + user: { + _id: '1', + }, + accessToken: 'accessToken', + refreshToken: 'refreshToken', + }, + }, + }, + }, + { + request: { + query: RECAPTCHA_MUTATION, + variables: { + recaptchaToken: null, + }, + }, + result: { + data: { + recaptcha: true, + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }, +})); + +jest.mock('Constant/constant.ts', () => ({ + ...jest.requireActual('Constant/constant.ts'), + REACT_APP_USE_RECAPTCHA: 'yes', + RECAPTCHA_SITE_KEY: 'xxx', +})); + +describe('Talawa-API server fetch check', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + test('Checks if Talawa-API resource is loaded successfully', async () => { + global.fetch = jest.fn(() => Promise.resolve({} as unknown as Response)); + + await act(async () => { + render( + + + + + + + + + + ); + }); + + expect(fetch).toHaveBeenCalledWith('http://localhost:4000/graphql/'); + }); + + test('displays warning message when resource loading fails', async () => { + const mockError = new Error('Network error'); + global.fetch = jest.fn(() => Promise.reject(mockError)); + + await act(async () => { + render( + + + + + + + + + + ); + }); + + expect(fetch).toHaveBeenCalledWith('http://localhost:4000/graphql/'); + }); +}); + +describe('Testing Login Page Screen', () => { + test('Component Should be rendered properly', async () => { + window.location.assign('/orglist'); + + render( + + + + + + + + + + ); + + await wait(); + + expect(screen.getByText(/Admin Portal/i)).toBeInTheDocument(); + expect(window.location).toBeAt('/orglist'); + }); + + test('Testing registration functionality', async () => { + const formData = { + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@gmail.com', + password: 'johndoe', + confirmPassword: 'johndoe', + }; + + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId(/goToRegisterPortion/i)); + + await wait(); + + userEvent.type( + screen.getByPlaceholderText(/First Name/i), + formData.firstName + ); + userEvent.type( + screen.getByPlaceholderText(/Last name/i), + formData.lastName + ); + userEvent.type(screen.getByTestId(/signInEmail/i), formData.email); + userEvent.type(screen.getByPlaceholderText('Password'), formData.password); + userEvent.type( + screen.getByPlaceholderText('Confirm Password'), + formData.confirmPassword + ); + + userEvent.click(screen.getByTestId('registrationBtn')); + }); + + test('Testing registration functionality, when password and confirm password is not same', async () => { + const formData = { + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@gmail.com', + password: 'johndoe', + confirmPassword: 'doeJohn', + }; + + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId(/goToRegisterPortion/i)); + + userEvent.type( + screen.getByPlaceholderText(/First Name/i), + formData.firstName + ); + userEvent.type( + screen.getByPlaceholderText(/Last Name/i), + formData.lastName + ); + userEvent.type(screen.getByTestId(/signInEmail/i), formData.email); + userEvent.type(screen.getByPlaceholderText('Password'), formData.password); + userEvent.type( + screen.getByPlaceholderText('Confirm Password'), + formData.confirmPassword + ); + + userEvent.click(screen.getByTestId('registrationBtn')); + }); + + test('Testing registration functionality, when input is not filled correctly', async () => { + const formData = { + firstName: 'J', + lastName: 'D', + email: 'johndoe@gmail.com', + password: 'joe', + confirmPassword: 'joe', + }; + + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId(/goToRegisterPortion/i)); + + userEvent.type( + screen.getByPlaceholderText(/First Name/i), + formData.firstName + ); + userEvent.type( + screen.getByPlaceholderText(/Last Name/i), + formData.lastName + ); + userEvent.type(screen.getByTestId(/signInEmail/i), formData.email); + userEvent.type(screen.getByPlaceholderText('Password'), formData.password); + userEvent.type( + screen.getByPlaceholderText('Confirm Password'), + formData.confirmPassword + ); + + userEvent.click(screen.getByTestId('registrationBtn')); + }); + + test('Testing toggle login register portion', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('goToRegisterPortion')); + + userEvent.click(screen.getByTestId('goToLoginPortion')); + + await wait(); + }); + + test('Testing login functionality', async () => { + const formData = { + email: 'johndoe@gmail.com', + password: 'johndoe', + }; + + render( + + + + + + + + + + ); + + await wait(); + + userEvent.type(screen.getByTestId(/loginEmail/i), formData.email); + userEvent.type( + screen.getByPlaceholderText(/Enter Password/i), + formData.password + ); + + userEvent.click(screen.getByTestId('loginBtn')); + + await wait(); + }); + + test('Testing password preview feature for login', async () => { + render( + + + + + + + + + + ); + + await wait(); + + const input = screen.getByTestId('password') as HTMLInputElement; + const toggleText = screen.getByTestId('showLoginPassword'); + // password should be hidden + expect(input.type).toBe('password'); + // click the toggle button to show password + userEvent.click(toggleText); + expect(input.type).toBe('text'); + // click the toggle button to hide password + userEvent.click(toggleText); + expect(input.type).toBe('password'); + + await wait(); + }); + + test('Testing password preview feature for register', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('goToRegisterPortion')); + + const input = screen.getByTestId('passwordField') as HTMLInputElement; + const toggleText = screen.getByTestId('showPassword'); + // password should be hidden + expect(input.type).toBe('password'); + // click the toggle button to show password + userEvent.click(toggleText); + expect(input.type).toBe('text'); + // click the toggle button to hide password + userEvent.click(toggleText); + expect(input.type).toBe('password'); + + await wait(); + }); + + test('Testing confirm password preview feature', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('goToRegisterPortion')); + + const input = screen.getByTestId('cpassword') as HTMLInputElement; + const toggleText = screen.getByTestId('showPasswordCon'); + // password should be hidden + expect(input.type).toBe('password'); + // click the toggle button to show password + userEvent.click(toggleText); + expect(input.type).toBe('text'); + // click the toggle button to hide password + userEvent.click(toggleText); + expect(input.type).toBe('password'); + + await wait(); + }); + + test('Testing for the password error warning when user firsts lands on a page', async () => { + render( + + + + + + + + + + ); + await wait(); + + expect(screen.queryByTestId('passwordCheck')).toBeNull(); + }); + + test('Testing for the password error warning when user clicks on password field and password is less than 8 character', async () => { + const password = { + password: '7', + }; + + render( + + + + + + + + + + ); + await wait(); + + userEvent.click(screen.getByTestId('goToRegisterPortion')); + + userEvent.type(screen.getByPlaceholderText('Password'), password.password); + + expect(screen.getByTestId('passwordField')).toHaveFocus(); + + expect(password.password.length).toBeLessThan(8); + + expect(screen.queryByTestId('passwordCheck')).toBeInTheDocument(); + }); + + test('Testing for the password error warning when user clicks on password field and password is greater than or equal to 8 character', async () => { + const password = { + password: '12345678', + }; + + render( + + + + + + + + + + ); + await wait(); + + userEvent.click(screen.getByTestId('goToRegisterPortion')); + + userEvent.type(screen.getByPlaceholderText('Password'), password.password); + + expect(screen.getByTestId('passwordField')).toHaveFocus(); + + expect(password.password.length).toBeGreaterThanOrEqual(8); + + expect(screen.queryByTestId('passwordCheck')).toBeNull(); + }); + + test('Testing for the password error warning when user clicks on fields except password field and password is less than 8 character', async () => { + const password = { + password: '7', + }; + + render( + + + + + + + + + + ); + await wait(); + + userEvent.click(screen.getByTestId('goToRegisterPortion')); + + expect(screen.getByPlaceholderText('Password')).not.toHaveFocus(); + + userEvent.type(screen.getByPlaceholderText('Password'), password.password); + + expect(password.password.length).toBeLessThan(8); + + expect(screen.queryByTestId('passwordCheck')).toBeInTheDocument(); + }); + + test('Testing for the password error warning when user clicks on fields except password field and password is greater than or equal to 8 character', async () => { + const password = { + password: '12345678', + }; + + render( + + + + + + + + + + ); + await wait(); + + userEvent.click(screen.getByTestId('goToRegisterPortion')); + + await wait(); + + expect(screen.getByPlaceholderText('Password')).not.toHaveFocus(); + + userEvent.type(screen.getByPlaceholderText('Password'), password.password); + + expect(password.password.length).toBeGreaterThanOrEqual(8); + + expect(screen.queryByTestId('passwordCheck')).toBeNull(); + }); +}); diff --git a/src/screens/LoginPage/LoginPage.tsx b/src/screens/LoginPage/LoginPage.tsx new file mode 100644 index 0000000000..481f8d09c2 --- /dev/null +++ b/src/screens/LoginPage/LoginPage.tsx @@ -0,0 +1,564 @@ +import { useMutation } from '@apollo/client'; +import type { ChangeEvent } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; +import { Form } from 'react-bootstrap'; +import Button from 'react-bootstrap/Button'; +import Col from 'react-bootstrap/Col'; +import Row from 'react-bootstrap/Row'; +import ReCAPTCHA from 'react-google-recaptcha'; +import { useTranslation } from 'react-i18next'; +import { Link } from 'react-router-dom'; +import { toast } from 'react-toastify'; + +import { REACT_APP_USE_RECAPTCHA, RECAPTCHA_SITE_KEY } from 'Constant/constant'; +import { + LOGIN_MUTATION, + RECAPTCHA_MUTATION, + SIGNUP_MUTATION, +} from 'GraphQl/Mutations/mutations'; +import { ReactComponent as TalawaLogo } from 'assets/svgs/talawa.svg'; +import { ReactComponent as PalisadoesLogo } from 'assets/svgs/palisadoes.svg'; +import ChangeLanguageDropDown from 'components/ChangeLanguageDropdown/ChangeLanguageDropDown'; +import Loader from 'components/Loader/Loader'; +import { errorHandler } from 'utils/errorHandler'; +import styles from './LoginPage.module.css'; +import EmailOutlinedIcon from '@mui/icons-material/EmailOutlined'; + +function loginPage(): JSX.Element { + const { t } = useTranslation('translation', { keyPrefix: 'loginPage' }); + + document.title = t('title'); + + const [showTab, setShowTab] = useState<'LOGIN' | 'REGISTER'>('LOGIN'); + const [componentLoader, setComponentLoader] = useState(true); + const [isInputFocused, setIsInputFocused] = useState(false); + const [signformState, setSignFormState] = useState({ + signfirstName: '', + signlastName: '', + signEmail: '', + signPassword: '', + cPassword: '', + }); + const [formState, setFormState] = useState({ + email: '', + password: '', + }); + const [showPassword, setShowPassword] = useState(false); + const [showConfirmPassword, setShowConfirmPassword] = + useState(false); + const recaptchaRef = useRef(null); + + useEffect(() => { + const isLoggedIn = localStorage.getItem('IsLoggedIn'); + if (isLoggedIn == 'TRUE') { + window.location.assign('/orglist'); + } + setComponentLoader(false); + }, []); + + const togglePassword = (): void => setShowPassword(!showPassword); + const toggleConfirmPassword = (): void => + setShowConfirmPassword(!showConfirmPassword); + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const [login, { loading: loginLoading }] = useMutation(LOGIN_MUTATION); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const [signup, { loading: signinLoading }] = useMutation(SIGNUP_MUTATION); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const [recaptcha, { loading: recaptchaLoading }] = + useMutation(RECAPTCHA_MUTATION); + + useEffect(() => { + async function loadResource(): Promise { + try { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const response = await fetch('http://localhost:4000/graphql/'); + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + } + + loadResource(); + }, []); + + const verifyRecaptcha = async ( + recaptchaToken: any + ): Promise => { + try { + /* istanbul ignore next */ + if (REACT_APP_USE_RECAPTCHA !== 'yes') { + return true; + } + const { data } = await recaptcha({ + variables: { + recaptchaToken, + }, + }); + + return data.recaptcha; + } catch (error: any) { + /* istanbul ignore next */ + toast.error(t('captchaError')); + } + }; + + const signupLink = async (e: ChangeEvent): Promise => { + e.preventDefault(); + + const { signfirstName, signlastName, signEmail, signPassword, cPassword } = + signformState; + + const recaptchaToken = recaptchaRef.current?.getValue(); + recaptchaRef.current?.reset(); + + const isVerified = await verifyRecaptcha(recaptchaToken); + /* istanbul ignore next */ + if (!isVerified) { + toast.error(t('Please_check_the_captcha')); + return; + } + + if ( + signfirstName.length > 1 && + signlastName.length > 1 && + signEmail.length >= 8 && + signPassword.length > 1 + ) { + if (cPassword == signPassword) { + try { + const { data: signUpData } = await signup({ + variables: { + firstName: signfirstName, + lastName: signlastName, + email: signEmail, + password: signPassword, + }, + }); + + /* istanbul ignore next */ + if (signUpData) { + toast.success( + 'Successfully Registered. Please wait until you will be approved.' + ); + + setSignFormState({ + signfirstName: '', + signlastName: '', + signEmail: '', + signPassword: '', + cPassword: '', + }); + } + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + } else { + toast.warn(t('passwordMismatches')); + } + } else { + toast.warn(t('fillCorrectly')); + } + }; + + const loginLink = async (e: ChangeEvent): Promise => { + e.preventDefault(); + + const recaptchaToken = recaptchaRef.current?.getValue(); + recaptchaRef.current?.reset(); + + const isVerified = await verifyRecaptcha(recaptchaToken); + /* istanbul ignore next */ + if (!isVerified) { + toast.error(t('Please_check_the_captcha')); + return; + } + + try { + const { data: loginData } = await login({ + variables: { + email: formState.email, + password: formState.password, + }, + }); + + /* istanbul ignore next */ + if (loginData) { + if ( + loginData.login.user.userType === 'SUPERADMIN' || + (loginData.login.user.userType === 'ADMIN' && + loginData.login.user.adminApproved === true) + ) { + localStorage.setItem('token', loginData.login.accessToken); + localStorage.setItem('refreshToken', loginData.login.refreshToken); + localStorage.setItem('id', loginData.login.user._id); + localStorage.setItem('IsLoggedIn', 'TRUE'); + localStorage.setItem('UserType', loginData.login.user.userType); + if (localStorage.getItem('IsLoggedIn') == 'TRUE') { + window.location.replace('/orglist'); + } + } else { + toast.warn(t('notAuthorised')); + } + } else { + toast.warn(t('notFound')); + } + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + + if (componentLoader || loginLoading || signinLoading || recaptchaLoading) { + return ; + } + + return ( + <> +
    + + +
    + +

    {t('fromPalisadoes')}

    +
    + + +
    + + + {/* LOGIN FORM */} +
    +
    +

    + {t('login_to_admin_portal')} +

    + {t('email')} +
    + { + setFormState({ + ...formState, + email: e.target.value, + }); + }} + autoComplete="username" + data-testid="loginEmail" + /> + +
    + {t('password')} +
    + { + setFormState({ + ...formState, + password: e.target.value, + }); + }} + autoComplete="current-password" + /> + +
    +
    + + {t('forgotPassword')} + +
    + {REACT_APP_USE_RECAPTCHA === 'yes' ? ( +
    + +
    + ) : ( + /* istanbul ignore next */ + <> + )} + +
    +
    + {t('OR')} +
    + +
    +
    + {/* REGISTER FORM */} +
    +
    +

    + {t('register')} +

    + + +
    + {t('firstName')} + { + setSignFormState({ + ...signformState, + signfirstName: e.target.value, + }); + }} + /> +
    + + +
    + {t('lastName')} + { + setSignFormState({ + ...signformState, + signlastName: e.target.value, + }); + }} + /> +
    + +
    + {t('email')} +
    + { + setSignFormState({ + ...signformState, + signEmail: e.target.value.toLowerCase(), + }); + }} + /> + +
    + +
    + {t('password')} +
    + setIsInputFocused(true)} + onBlur={(): void => setIsInputFocused(false)} + required + value={signformState.signPassword} + onChange={(e): void => { + setSignFormState({ + ...signformState, + signPassword: e.target.value, + }); + }} + /> + +
    + {isInputFocused && + signformState.signPassword.length < 8 && ( +
    + {t('atleast_8_char_long')} +
    + )} + {!isInputFocused && + signformState.signPassword.length > 0 && + signformState.signPassword.length < 8 && ( +
    + {t('atleast_8_char_long')} +
    + )} +
    +
    + {t('confirmPassword')} +
    + { + setSignFormState({ + ...signformState, + cPassword: e.target.value, + }); + }} + data-testid="cpassword" + autoComplete="new-password" + /> + +
    + {signformState.cPassword.length > 0 && + signformState.signPassword !== + signformState.cPassword && ( +
    + {t('Password_and_Confirm_password_mismatches.')} +
    + )} +
    + {REACT_APP_USE_RECAPTCHA === 'yes' ? ( +
    + +
    + ) : ( + /* istanbul ignore next */ + <> + )} + +
    +
    + {t('OR')} +
    + +
    +
    +
    + +
    +
    + + ); +} + +export default loginPage; diff --git a/src/screens/MemberDetail/MemberDetail.module.css b/src/screens/MemberDetail/MemberDetail.module.css new file mode 100644 index 0000000000..101dcb64e3 --- /dev/null +++ b/src/screens/MemberDetail/MemberDetail.module.css @@ -0,0 +1,446 @@ +.mainpage { + display: flex; + flex-direction: row; +} + +.sidebar { + z-index: 0; + padding-top: 5px; + margin: 0; + height: 100%; +} + +.sidebar:after { + content: ''; + background-color: #f7f7f7; + position: absolute; + width: 2px; + height: 600px; + top: 10px; + left: 94%; + display: block; +} + +.sidebarsticky { + padding: 0 2rem; + text-overflow: ellipsis; + /* overflow-x: hidden; */ +} + +/* .sidebarsticky:hover{ + overflow-x:visible; + transition: all 0.4s ease; + background-color: #707070; + +} */ +.sidebarsticky > p { + margin-top: -10px; +} + +.navitem { + padding-left: 27%; + padding-top: 12px; + padding-bottom: 12px; + cursor: pointer; +} + +.searchtitle { + color: #707070; + font-weight: 600; + font-size: 18px; + margin-top: 60px; + margin-bottom: 20px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 60%; +} + +.sidebarsticky > input { + text-decoration: none; + margin-bottom: 50px; + border-color: #e8e5e5; + width: 80%; + border-radius: 7px; + padding-top: 5px; + padding-bottom: 5px; + padding-right: 10px; + padding-left: 10px; + box-shadow: none; +} + +.logintitle { + color: #707070; + font-weight: 600; + font-size: 20px; + margin-bottom: 30px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 30%; +} + +.logintitleadmin { + color: #707070; + font-weight: 600; + font-size: 20px; + margin-top: 50px; + margin-bottom: 40px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 60%; +} + +.admindetails { + display: flex; + justify-content: space-between; +} + +.admindetails > p { + margin-top: -12px; + margin-right: 30px; +} + +.mainpageright > hr { + margin-top: 20px; + width: 100%; + margin-left: -15px; + margin-right: -15px; + margin-bottom: 20px; +} + +.justifysp { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: flex-start; + /* gap : 2px; */ +} + +.flexclm { + display: flex; + flex-direction: column; +} + +.btngroup { + display: flex; + gap: 2rem; + margin-bottom: 2rem; +} +@media screen and (max-width: 1200px) { + .justifysp { + padding-left: 55px; + display: flex; + justify-content: space-evenly; + } + + .mainpageright { + width: 100%; + } + + .invitebtn { + position: relative; + right: 15px; + } +} + +.invitebtn { + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + border-radius: 5px; + font-size: 16px; + height: 60%; + color: white; + outline: none; + font-weight: 600; + cursor: pointer; + transition: transform 0.2s, box-shadow 0.2s; + background-color: #31bb6b; + margin-right: 13px; +} + +.flexdir { + display: flex; + flex-direction: row; + justify-content: space-between; + border: none; +} + +.form_wrapper { + margin-top: 27px; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + position: absolute; + display: flex; + flex-direction: column; + width: 30%; + padding: 40px 30px; + background: #ffffff; + border-color: #e8e5e5; + border-width: 5px; + border-radius: 10px; + max-height: 86vh; + overflow: auto; +} + +.form_wrapper form { + display: flex; + align-items: left; + justify-content: left; + flex-direction: column; +} + +.titlemodal { + color: #707070; + font-weight: 600; + font-size: 20px; + margin-bottom: 20px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 65%; +} + +.checkboxdiv > label { + margin-right: 50px; +} + +.checkboxdiv > label > input { + margin-left: 10px; +} + +.orgphoto { + margin-top: 5px; +} + +.orgphoto > input { + margin-top: 10px; + cursor: pointer; + margin-bottom: 5px; +} + +.cancel > i { + margin-top: 5px; + transform: scale(1.2); + cursor: pointer; + color: #707070; +} + +.modalbody { + width: 50px; +} + +.greenregbtn { + margin: 1rem 0 0; + margin-top: 10px; + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + padding: 10px 10px; + border-radius: 5px; + background-color: #31bb6b; + width: 100%; + font-size: 16px; + color: white; + outline: none; + font-weight: 600; + cursor: pointer; + transition: transform 0.2s, box-shadow 0.2s; + width: 100%; +} + +.loader, +.loader:after { + border-radius: 50%; + width: 10em; + height: 10em; +} + +.loader { + margin: 60px auto; + margin-top: 35vh !important; + font-size: 10px; + position: relative; + text-indent: -9999em; + border-top: 1.1em solid rgba(255, 255, 255, 0.2); + border-right: 1.1em solid rgba(255, 255, 255, 0.2); + border-bottom: 1.1em solid rgba(255, 255, 255, 0.2); + border-left: 1.1em solid #febc59; + -webkit-transform: translateZ(0); + -ms-transform: translateZ(0); + transform: translateZ(0); + -webkit-animation: load8 1.1s infinite linear; + animation: load8 1.1s infinite linear; +} + +@-webkit-keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +.list_box { + height: 70vh; + overflow-y: auto; + width: auto; + padding-right: 50px; +} + +.dispflex { + display: flex; +} + +.dispflex > input { + width: 20%; + border: none; + box-shadow: none; + margin-top: 5px; +} + +.checkboxdiv { + display: flex; +} + +.checkboxdiv > div { + width: 50%; +} + +@media only screen and (max-width: 600px) { + .sidebar { + position: relative; + bottom: 18px; + } + + .invitebtn { + width: 135px; + position: relative; + right: 10px; + } + + .form_wrapper { + width: 90%; + } + + .searchtitle { + margin-top: 30px; + } +} + +/* User page */ + +.memberfontcreatedbtn { + border-radius: 7px; + border-color: #31bb6b; + background-color: #31bb6b; + color: white; + box-shadow: none; + height: 2.5rem; + width: max-content; + display: flex; + justify-content: center; + align-items: center; +} + +.userImage { + width: 180px; + height: 180px; + object-fit: cover; + border-radius: 8px; +} + +@media only screen and (max-width: 1200px) { + .userImage { + width: 100px; + height: 100px; + } +} + +.activeBtn { + width: 100%; + display: flex; + color: #fff; + border: 1px solid #000; + background-color: #31bb6b; + transition: 0.5s; +} + +.activeBtn:hover { + color: #fff; + background: #23864c; + transition: 0.5s; +} + +.inactiveBtn { + width: 100%; + display: flex; + color: #31bb6b; + border: 1px solid #31bb6a60; + background-color: #fff; + transition: 0.5s; +} + +.inactiveBtn:hover { + color: #fff; + background: #31bb6b; + transition: 0.5s; +} + +.sidebarsticky > button { + display: flex; + align-items: center; + text-align: start; + padding: 0 1.5rem; + height: 3.25rem; + margin: 0 0 1.5rem 0; + font-weight: bold; + border-radius: 50px; +} + +.bgFill { + height: 2rem; + width: 2rem; + border-radius: 50%; + margin-right: 1rem; + display: flex; + justify-content: center; + align-items: center; +} + +.activeBtn .bgFill { + background-color: #fff; +} + +.activeBtn i { + color: #31bb6b; +} + +.inactiveBtn .bgFill { + background-color: #31bb6b; +} + +.inactiveBtn:hover .bgFill { + background-color: #fff; +} + +.inactiveBtn i { + color: #fff; +} + +.inactiveBtn:hover i { + color: #31bb6b; +} diff --git a/src/screens/MemberDetail/MemberDetail.test.tsx b/src/screens/MemberDetail/MemberDetail.test.tsx new file mode 100644 index 0000000000..a4b29fb604 --- /dev/null +++ b/src/screens/MemberDetail/MemberDetail.test.tsx @@ -0,0 +1,309 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { act, render, screen, waitFor } from '@testing-library/react'; +import { ADD_ADMIN_MUTATION } from 'GraphQl/Mutations/mutations'; +import { USER_DETAILS } from 'GraphQl/Queries/Queries'; +import 'jest-location-mock'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import MemberDetail, { getLanguageName, prettyDate } from './MemberDetail'; +import userEvent from '@testing-library/user-event'; +import { StaticMockLink } from 'utils/StaticMockLink'; + +const MOCKS1 = [ + { + request: { + query: USER_DETAILS, + variables: { + id: 'rishav-jha-mech', + }, + }, + result: { + data: { + user: { + __typename: 'User', + image: null, + firstName: 'Rishav', + lastName: 'Jha', + email: 'ris@gmail.com', + role: 'SUPERADMIN', + appLanguageCode: 'en', + userType: 'SUPERADMIN', + pluginCreationAllowed: true, + adminApproved: true, + createdAt: '2023-02-18T09:22:27.969Z', + adminFor: [], + createdOrganizations: [], + joinedOrganizations: [], + organizationUserBelongsTo: null, + organizationsBlockedBy: [], + createdEvents: [], + registeredEvents: [], + eventAdmin: [], + membershipRequests: [], + }, + }, + }, + }, + { + request: { + query: ADD_ADMIN_MUTATION, + variables: { + userid: '123', + orgid: '456', + }, + }, + result: { + data: { + success: true, + }, + }, + }, +]; + +const MOCKS2 = [ + { + request: { + query: USER_DETAILS, + variables: { + id: 'rishav-jha-mech', + }, + }, + result: { + data: { + user: { + __typename: 'User', + image: 'https://placeholder.com/200x200', + firstName: 'Rishav', + lastName: 'Jha', + email: 'ris@gmail.com', + role: 'SUPERADMIN', + appLanguageCode: 'en', + userType: 'SUPERADMIN', + pluginCreationAllowed: false, + adminApproved: false, + createdAt: '2023-02-18T09:22:27.969Z', + adminFor: [], + createdOrganizations: [], + joinedOrganizations: [], + organizationUserBelongsTo: null, + organizationsBlockedBy: [], + createdEvents: [], + registeredEvents: [], + eventAdmin: [], + membershipRequests: [], + }, + }, + }, + }, + { + request: { + query: ADD_ADMIN_MUTATION, + variables: { + userid: '123', + orgid: '456', + }, + }, + result: { + data: { + success: true, + }, + }, + }, +]; +const link1 = new StaticMockLink(MOCKS1, true); +const link2 = new StaticMockLink(MOCKS2, true); +async function wait(ms = 2): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +jest.mock('react-toastify'); + +describe('MemberDetail', () => { + global.alert = jest.fn(); + + test('should render the elements', async () => { + const props = { + id: 'rishav-jha-mech', + }; + + const { container, getByTestId } = render( + + + + + + + + + + ); + + expect(container.textContent).not.toBe('Loading data...'); + await wait(); + + userEvent.click(screen.getByText(/Add Admin/i)); + + expect(getByTestId(/dashboardTitleBtn/i)).toBeInTheDocument(); + expect(getByTestId(/dashboardTitleBtn/i)).toHaveTextContent('User Details'); + expect(screen.getAllByText(/Email/i)).toBeTruthy(); + expect(screen.getAllByText(/Main/i)).toBeTruthy(); + expect(screen.getAllByText(/First name/i)).toBeTruthy(); + expect(screen.getAllByText(/Last name/i)).toBeTruthy(); + expect(screen.getAllByText(/Member of Organization/i)).toBeTruthy(); + expect(screen.getAllByText(/Language/i)).toBeTruthy(); + expect(screen.getByText(/Admin approved/i)).toBeInTheDocument(); + expect(screen.getByText(/Plugin creation allowed/i)).toBeInTheDocument(); + expect(screen.getAllByText(/Created on/i)).toBeTruthy(); + expect(screen.getAllByText(/Admin for organizations/i)).toBeTruthy(); + expect(screen.getAllByText(/Membership requests/i)).toBeTruthy(); + expect(screen.getAllByText(/Events/i)).toBeTruthy(); + expect(screen.getAllByText(/Admin for events/i)).toBeTruthy(); + + expect(screen.getAllByText(/Created On/i)).toHaveLength(2); + expect(screen.getAllByText(/User Details/i)).toHaveLength(3); + expect(screen.getAllByText(/Role/i)).toHaveLength(2); + expect(screen.getAllByText(/Created/i)).toHaveLength(4); + expect(screen.getAllByText(/Joined/i)).toHaveLength(2); + expect(screen.getByTestId('stateBtn')).toBeInTheDocument(); + userEvent.click(screen.getByTestId('stateBtn')); + }); + test('prettyDate function should work properly', () => { + // If the date is provided + const datePretty = jest.fn(prettyDate); + expect(datePretty('2023-02-18T09:22:27.969Z')).toBe( + prettyDate('2023-02-18T09:22:27.969Z') + ); + // If there's some error in formatting the date + expect(datePretty('')).toBe('Unavailable'); + }); + test('getLanguageName function should work properly', () => { + const getLangName = jest.fn(getLanguageName); + // If the language code is provided + expect(getLangName('en')).toBe('English'); + // If the language code is not provided + expect(getLangName('')).toBe('Unavailable'); + }); + + test('Should display dicebear image if image is null', async () => { + const props = { + id: 'rishav-jha-mech', + }; + + const { container } = render( + + + + + + + + + + ); + + expect(container.textContent).not.toBe('Loading data...'); + const user = MOCKS1[0].result.data.user; + + waitFor(() => + expect(screen.getByTestId(/userImageAbsent/i)).toBeInTheDocument() + ); + waitFor(() => + expect(screen.getByTestId(/userImageAbsent/i).getAttribute('src')).toBe( + `https://api.dicebear.com/5.x/initials/svg?seed=${user?.firstName} ${user?.lastName}` + ) + ); + }); + + test('Should display image if image is present', async () => { + const props = { + id: 'rishav-jha-mech', + }; + + const { container } = render( + + + + + + + + + + ); + + expect(container.textContent).not.toBe('Loading data...'); + + const user = MOCKS2[0].result.data.user; + + waitFor(() => + expect(screen.getByTestId(/userImagePresent/i)).toBeInTheDocument() + ); + waitFor(() => + expect(screen.getByTestId(/userImagePresent/i).getAttribute('src')).toBe( + user?.image + ) + ); + }); + test('should call setState with 2 when button is clicked', async () => { + const props = { + id: 'rishav-jha-mech', + }; + const { container } = render( + + + + + + + + + + ); + + expect(container.textContent).not.toBe('Loading data...'); + + waitFor(() => userEvent.click(screen.getByText(/Edit Profile/i))); + }); + test('should show Yes if plugin creation is allowed and admin approved', async () => { + const props = { + id: 'rishav-jha-mech', + }; + render( + + + + + + + + + + ); + waitFor(() => expect(screen.getByText('Yes')).toHaveLength(2)); + }); + test('should show No if plugin creation is not allowed and not admin approved', async () => { + const props = { + id: 'rishav-jha-mech', + }; + render( + + + + + + + + + + ); + waitFor(() => expect(screen.getAllByText('No')).toHaveLength(2)); + }); +}); diff --git a/src/screens/MemberDetail/MemberDetail.tsx b/src/screens/MemberDetail/MemberDetail.tsx new file mode 100644 index 0000000000..d190b47246 --- /dev/null +++ b/src/screens/MemberDetail/MemberDetail.tsx @@ -0,0 +1,324 @@ +import React, { useState } from 'react'; +import { useMutation, useQuery } from '@apollo/client'; +import Col from 'react-bootstrap/Col'; +import Row from 'react-bootstrap/Row'; +import Button from 'react-bootstrap/Button'; +import { useTranslation } from 'react-i18next'; +import { useLocation } from 'react-router-dom'; +import UserUpdate from 'components/UserUpdate/UserUpdate'; + +import OrganizationScreen from 'components/OrganizationScreen/OrganizationScreen'; +import { USER_DETAILS } from 'GraphQl/Queries/Queries'; +import styles from './MemberDetail.module.css'; +import { languages } from 'utils/languages'; +import { ADD_ADMIN_MUTATION } from 'GraphQl/Mutations/mutations'; +import { toast } from 'react-toastify'; +import { errorHandler } from 'utils/errorHandler'; +import Loader from 'components/Loader/Loader'; + +type MemberDetailProps = { + id: string; // This is the userId +}; + +const MemberDetail: React.FC = ({ id }): JSX.Element => { + const { t } = useTranslation('translation', { + keyPrefix: 'memberDetail', + }); + + const [state, setState] = useState(1); + + const location = useLocation(); + const currentUrl = location.state?.id || localStorage.getItem('id') || id; + document.title = t('title'); + + const [adda] = useMutation(ADD_ADMIN_MUTATION); + const { + data: userData, + loading: loading, + error: error, + refetch: refetch, + } = useQuery(USER_DETAILS, { + variables: { id: currentUrl }, // For testing we are sending the id as a prop + }); + + /* istanbul ignore next */ + const toggleStateValue = (): void => { + if (state === 1) setState(2); + else setState(1); + refetch(); + }; + + if (loading) { + return ; + } + + /* istanbul ignore next */ + if (error) { + window.location.assign(`/orgpeople/id=${currentUrl}`); + } + + const addAdmin = async (): Promise => { + try { + const { data } = await adda({ + variables: { + userid: location.state?.id, + orgid: currentUrl, + }, + }); + + /* istanbul ignore next */ + if (data) { + toast.success(t('addedAsAdmin')); + setTimeout(() => { + window.location.reload(); + }, 2000); + } + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + + return ( + <> + + + +
    +
    +
    + +
    +
    + + + {state == 1 ? ( +
    + +

    {t('title')}

    +
    + + +
    +
    + + +
    + {userData?.user?.image ? ( + + ) : ( + + )} +
    + + + {/* User section */} +
    +

    + + {userData?.user?.firstName} {userData?.user?.lastName} + +

    +

    + {t('role')} :{' '} + {userData?.user?.userType} +

    +

    + {t('email')} :{' '} + {userData?.user?.email} +

    +

    + {t('createdOn')} :{' '} + {prettyDate(userData?.user?.createdAt)} +

    +
    + +
    +
    +
    +
    + {/* Main Section And Activity section */} +
    + + {/* Main Section */} + +
    +
    +
    + {t('main')} +
    +
    +
    + + {t('firstName')} + {userData?.user?.firstName} + + + {t('lastName')} + {userData?.user?.lastName} + + + {t('role')} + {userData?.user?.userType} + + + {t('memberOfOrganization')} + + {userData?.user?.organizationUserBelongsTo ?? + 'None'} + + + + {t('language')} + + {getLanguageName(userData?.user?.appLanguageCode)} + + + + {t('adminApproved')} + + {userData?.user?.adminApproved ? 'Yes' : 'No'} + + + + {t('pluginCreationAllowed')} + + {userData?.user?.pluginCreationAllowed + ? 'Yes' + : 'No'} + + + + {t('createdOn')} + + {prettyDate(userData?.user?.createdAt)} + + +
    +
    + + {/* Activity Section */} + + {/* Organizations */} +
    +
    +
    + {t('organizations')} +
    +
    +
    + + {t('created')} + + {userData?.user?.createdOrganizations?.length} + + + + {t('joined')} + + {userData?.user?.joinedOrganizations?.length} + + + + {t('adminForOrganizations')} + {userData?.user?.adminFor?.length} + + + {t('membershipRequests')} + + {userData?.user?.membershipRequests?.length} + + +
    +
    + {/* Events */} +
    +
    +
    + {t('events')} +
    +
    +
    + + {t('created')} + + {userData?.user?.createdEvents?.length} + + + + {t('joined')} + + {userData?.user?.registeredEvents?.length} + + + + {t('adminForEvents')} + + {userData?.user?.eventAdmin?.length} + + +
    +
    + +
    +
    +
    + ) : ( + + )} + +
    +
    + + ); +}; + +export const prettyDate = (param: string): string => { + const date = new Date(param); + if (date?.toDateString() === 'Invalid Date') { + return 'Unavailable'; + } + return `${date?.toDateString()} ${date.toLocaleTimeString()}`; +}; + +export const getLanguageName = (code: string): string => { + let language = 'Unavailable'; + languages.map((data) => { + if (data.code == code) { + language = data.name; + } + }); + return language; +}; + +export default MemberDetail; diff --git a/src/screens/OrgContribution/OrgContribution.module.css b/src/screens/OrgContribution/OrgContribution.module.css new file mode 100644 index 0000000000..1a3930690c --- /dev/null +++ b/src/screens/OrgContribution/OrgContribution.module.css @@ -0,0 +1,258 @@ +.navbarbg { + height: 60px; + background-color: white; + display: flex; + margin-bottom: 30px; + z-index: 1; + position: relative; + flex-direction: row; + justify-content: space-between; + box-shadow: 0px 0px 8px 2px #c8c8c8; +} + +.logo { + color: #707070; + margin-left: 0; + display: flex; + align-items: center; + text-decoration: none; +} + +.logo img { + margin-top: 0px; + margin-left: 10px; + height: 64px; + width: 70px; +} + +.logo > strong { + line-height: 1.5rem; + margin-left: -5px; + font-family: sans-serif; + font-size: 19px; + color: #707070; +} +.mainpage { + display: flex; + flex-direction: row; +} +.sidebar { + z-index: 0; + padding-top: 5px; + margin: 0; + height: 100%; +} +.sidebar:after { + content: ''; + background-color: #f7f7f7; + position: absolute; + width: 2px; + height: 600px; + top: 10px; + left: 94%; + display: block; +} +.sidebarsticky { + padding-left: 45px; + margin-top: 7px; +} +.sidebarsticky > p { + margin-top: -10px; +} + +.navitem { + padding-left: 27%; + padding-top: 12px; + padding-bottom: 12px; + cursor: pointer; +} + +.logintitle { + color: #707070; + font-weight: 600; + font-size: 20px; + margin-bottom: 30px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 15%; +} +.searchtitle { + color: #707070; + font-weight: 600; + font-size: 18px; + margin-bottom: 20px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 60%; +} +.logintitleadmin { + color: #707070; + font-weight: 600; + font-size: 18px; + margin-top: 50px; + margin-bottom: 40px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 30%; +} +.admindetails { + display: flex; + justify-content: space-between; +} +.admindetails > p { + margin-top: -12px; + margin-right: 30px; +} + +.mainpageright > hr { + margin-top: 20px; + width: 100%; + margin-left: -15px; + margin-right: -15px; + margin-bottom: 20px; +} +.justifysp { + display: flex; + justify-content: space-between; +} +@media screen and (max-width: 575.5px) { + .justifysp { + padding-left: 55px; + display: flex; + justify-content: space-between; + width: 100%; + } +} +.addbtn { + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + border-radius: 5px; + background-color: #31bb6b; + width: 15%; + height: 40px; + font-size: 16px; + color: white; + outline: none; + font-weight: 600; + cursor: pointer; + transition: transform 0.2s, box-shadow 0.2s; +} +.flexdir { + display: flex; + flex-direction: row; + justify-content: space-between; + border: none; +} + +.form_wrapper { + margin-top: 27px; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + position: absolute; + display: flex; + flex-direction: column; + width: 30%; + padding: 40px 30px; + background: #ffffff; + border-color: #e8e5e5; + border-width: 5px; + border-radius: 10px; +} + +.form_wrapper form { + display: flex; + align-items: left; + justify-content: left; + flex-direction: column; +} +.logintitleinvite { + color: #707070; + font-weight: 600; + font-size: 20px; + margin-bottom: 20px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 40%; +} +.cancel > i { + margin-top: 5px; + transform: scale(1.2); + cursor: pointer; + color: #707070; +} +.modalbody { + width: 50px; +} +.greenregbtn { + margin: 1rem 0 0; + margin-top: 10px; + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + padding: 10px 10px; + border-radius: 5px; + background-color: #31bb6b; + width: 100%; + font-size: 16px; + color: white; + outline: none; + font-weight: 600; + cursor: pointer; + transition: transform 0.2s, box-shadow 0.2s; + width: 100%; +} +.sidebarsticky > input { + text-decoration: none; + margin-bottom: 50px; + border-color: #e8e5e5; + width: 80%; + border-radius: 7px; + padding-top: 5px; + padding-bottom: 5px; + padding-right: 10px; + padding-left: 10px; + box-shadow: none; +} + +.loader, +.loader:after { + border-radius: 50%; + width: 10em; + height: 10em; +} +.loader { + margin: 60px auto; + margin-top: 35vh !important; + font-size: 10px; + position: relative; + text-indent: -9999em; + border-top: 1.1em solid rgba(255, 255, 255, 0.2); + border-right: 1.1em solid rgba(255, 255, 255, 0.2); + border-bottom: 1.1em solid rgba(255, 255, 255, 0.2); + border-left: 1.1em solid #febc59; + -webkit-transform: translateZ(0); + -ms-transform: translateZ(0); + transform: translateZ(0); + -webkit-animation: load8 1.1s infinite linear; + animation: load8 1.1s infinite linear; +} +@-webkit-keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} +@keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} diff --git a/src/screens/OrgContribution/OrgContribution.test.tsx b/src/screens/OrgContribution/OrgContribution.test.tsx new file mode 100644 index 0000000000..3f22371014 --- /dev/null +++ b/src/screens/OrgContribution/OrgContribution.test.tsx @@ -0,0 +1,47 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { act, render } from '@testing-library/react'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import 'jest-location-mock'; +import { I18nextProvider } from 'react-i18next'; + +import OrgContribution from './OrgContribution'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +const link = new StaticMockLink([], true); +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Organisation Contribution Page', () => { + test('should render props and text elements test for the screen', async () => { + window.location.assign('/orglist'); + + const { container } = render( + + + + + + + + + + ); + + expect(container.textContent).not.toBe('Loading data...'); + await wait(); + + expect(container.textContent).toMatch('Filter by Name'); + expect(container.textContent).toMatch('Filter by Trans. ID'); + expect(container.textContent).toMatch('Recent Stats'); + expect(container.textContent).toMatch('Contribution'); + expect(window.location).toBeAt('/orglist'); + }); +}); diff --git a/src/screens/OrgContribution/OrgContribution.tsx b/src/screens/OrgContribution/OrgContribution.tsx new file mode 100644 index 0000000000..bcd8641609 --- /dev/null +++ b/src/screens/OrgContribution/OrgContribution.tsx @@ -0,0 +1,74 @@ +import React from 'react'; +import Col from 'react-bootstrap/Col'; +import Row from 'react-bootstrap/Row'; +import { useTranslation } from 'react-i18next'; + +import ContriStats from 'components/ContriStats/ContriStats'; +import OrgContriCards from 'components/OrgContriCards/OrgContriCards'; +import { Form } from 'react-bootstrap'; +import styles from './OrgContribution.module.css'; + +function orgContribution(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'orgContribution', + }); + + document.title = t('title'); + + return ( + <> + + +
    +
    +
    {t('filterByName')}
    + + +
    {t('filterByTransId')}
    + + +
    {t('recentStats')}
    + +
    +
    + + +
    + +

    {t('contribution')}

    +
    + +
    + +
    + + ); +} + +export default orgContribution; diff --git a/src/screens/OrgList/OrgList.module.css b/src/screens/OrgList/OrgList.module.css new file mode 100644 index 0000000000..e1f1729d18 --- /dev/null +++ b/src/screens/OrgList/OrgList.module.css @@ -0,0 +1,350 @@ +.btnsContainer { + display: flex; + margin: 2.5rem 0 2.5rem 0; +} + +.btnsContainer .btnsBlock { + display: flex; +} + +.orgCreationBtn { + width: 100%; + border: None; +} + +.line::before { + content: ''; + display: inline-block; + width: 100px; + border-top: 1px solid #000; + margin: 0 10px; +} + +.line::before { + left: 0; +} + +.line::after { + right: 0; +} + +.flexContainer { + display: flex; + justify-content: center; + align-items: center; + width: 100%; +} + +.orText { + display: block; + position: absolute; + top: calc(-0.7rem + 0.5rem); + left: calc(50% - 2.6rem); + margin: 0 auto; + padding: 0.5rem 2rem; + z-index: 100; + background: var(--bs-white); + color: var(--bs-secondary); +} +.sampleOrgSection { + display: grid; + grid-template-columns: repeat(1, 1fr); + row-gap: 1em; +} + +.sampleOrgCreationBtn { + width: 100%; + background-color: transparent; + color: #707070; + border-color: #707070; + display: flex; + justify-content: center; + align-items: center; +} + +.sampleHover:hover { + border-color: grey; + color: grey; +} + +.sampleOrgSection { + font-family: Arial, Helvetica, sans-serif; + width: 100%; + display: grid; + grid-auto-columns: repeat(1, 1fr); + justify-content: center; + flex-direction: column; + align-items: center; +} + +.sampleModalTitle { + background-color: green; +} + +.btnsContainer .btnsBlock button { + margin-left: 1rem; + display: flex; + justify-content: center; + align-items: center; +} + +.btnsContainer .input { + flex: 1; + position: relative; +} + +.btnsContainer input { + outline: 1px solid var(--bs-gray-400); +} + +.btnsContainer .input button { + width: 52px; +} + +.listBox { + display: flex; + flex-wrap: wrap; + overflow: unset !important; +} + +.listBox .itemCard { + width: 50%; +} + +.notFound { + flex: 1; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; +} + +@media (max-width: 1120px) { + .contract { + padding-left: calc(250px + 2rem + 1.5rem); + } + + .listBox .itemCard { + width: 100%; + } +} + +@media (max-width: 1020px) { + .btnsContainer { + flex-direction: column; + margin: 1.5rem 0; + } + + .btnsContainer .btnsBlock { + margin: 1.5rem 0 0 0; + justify-content: space-between; + } + + .btnsContainer .btnsBlock button { + margin: 0; + } + + .btnsContainer .btnsBlock div button { + margin-right: 1.5rem; + } +} + +/* For mobile devices */ + +@media (max-width: 520px) { + .btnsContainer { + margin-bottom: 0; + } + + .btnsContainer .btnsBlock { + display: block; + margin-top: 1rem; + margin-right: 0; + } + + .btnsContainer .btnsBlock div { + flex: 1; + } + + .btnsContainer .btnsBlock div[title='Sort organizations'] { + margin-right: 0.5rem; + } + + .btnsContainer .btnsBlock button { + margin-bottom: 1rem; + margin-right: 0; + width: 100%; + } +} + +/* Loading OrgList CSS */ +.itemCard .loadingWrapper { + background-color: var(--bs-white); + margin: 0.5rem; + height: calc(120px + 2rem); + padding: 1rem; + border-radius: 8px; + outline: 1px solid var(--bs-gray-200); + position: relative; +} + +.itemCard .loadingWrapper .innerContainer { + display: flex; +} + +.itemCard .loadingWrapper .innerContainer .orgImgContainer { + width: 120px; + height: 120px; + border-radius: 4px; +} + +.itemCard .loadingWrapper .innerContainer .content { + flex: 1; + display: flex; + flex-direction: column; + margin-left: 1rem; +} + +.titlemodaldialog { + color: #707070; + font-size: 20px; + margin-bottom: 20px; + padding-bottom: 5px; +} + +form label { + font-weight: bold; + padding-bottom: 1px; + font-size: 14px; + color: #707070; +} + +form > input { + display: block; + margin-bottom: 20px; + border: 1px solid #e8e5e5; + box-shadow: 2px 1px #e8e5e5; + padding: 10px 20px; + border-radius: 5px; + background: none; + width: 100%; + transition: all 0.3s ease-in-out; + -webkit-transition: all 0.3s ease-in-out; + -moz-transition: all 0.3s ease-in-out; + -ms-transition: all 0.3s ease-in-out; + -o-transition: all 0.3s ease-in-out; +} + +.itemCard .loadingWrapper .innerContainer .content h5 { + height: 24px; + width: 60%; + margin-bottom: 0.8rem; +} + +.cancel > i { + margin-top: 5px; + transform: scale(1.2); + cursor: pointer; + color: #707070; +} + +.modalbody { + width: 50px; +} + +.pluginStoreBtnContainer { + display: flex; + gap: 1rem; +} + +.greenregbtn { + margin: 1rem 0 0; + margin-top: 10px; + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + padding: 10px 10px; + border-radius: 5px; + background-color: #31bb6b; + width: 100%; + font-size: 16px; + color: white; + outline: none; + font-weight: 600; + cursor: pointer; + transition: transform 0.2s, box-shadow 0.2s; + width: 100%; +} + +.itemCard .loadingWrapper .innerContainer .content h6[title='Location'] { + display: block; + width: 45%; + height: 18px; +} + +.secondbtn { + display: flex; + align-items: center; + justify-content: center; + margin: 1rem 0 0; + margin-top: 10px; + border: 1px solid #d0cfcf; + box-shadow: 0 2px 2px #d0cfcf; + padding: 10px 10px; + border-radius: 5px; + background-color: white; + width: 100%; + font-size: 16px; + color: #31bb6b; + outline: none; + font-weight: 600; + cursor: pointer; + transition: transform 0.2s, box-shadow 0.2s; + width: 100%; +} + +.itemCard .loadingWrapper .innerContainer .content h6 { + display: block; + width: 30%; + height: 16px; + margin-bottom: 0.8rem; +} + +.itemCard .loadingWrapper .button { + position: absolute; + height: 48px; + width: 92px; + bottom: 1rem; + right: 1rem; + z-index: 1; +} + +@media (max-width: 450px) { + .itemCard .loadingWrapper { + height: unset; + margin: 0.5rem 0; + padding: 1.25rem 1.5rem; + } + + .itemCard .loadingWrapper .innerContainer { + flex-direction: column; + } + + .itemCard .loadingWrapper .innerContainer .orgImgContainer { + height: 200px; + width: 100%; + margin-bottom: 0.8rem; + } + + .itemCard .loadingWrapper .innerContainer .content { + margin-left: 0; + } + + .itemCard .loadingWrapper .button { + bottom: 0; + right: 0; + border-radius: 0.5rem; + position: relative; + margin-left: auto; + display: block; + } +} diff --git a/src/screens/OrgList/OrgList.test.tsx b/src/screens/OrgList/OrgList.test.tsx new file mode 100644 index 0000000000..ca2e89ad98 --- /dev/null +++ b/src/screens/OrgList/OrgList.test.tsx @@ -0,0 +1,202 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { act, render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import 'jest-localstorage-mock'; +import 'jest-location-mock'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18nForTest from 'utils/i18nForTest'; +import OrgList from './OrgList'; +import { MOCKS, MOCKS_ADMIN, MOCKS_EMPTY } from './OrgListMocks'; + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +afterEach(() => { + localStorage.clear(); +}); + +describe('Organisations Page testing as SuperAdmin', () => { + localStorage.setItem('id', '123'); + + const link = new StaticMockLink(MOCKS, true); + const link2 = new StaticMockLink(MOCKS_EMPTY, true); + + const formData = { + name: 'Dummy Organization', + description: 'This is a dummy organization', + location: 'Delhi, India', + image: new File(['hello'], 'hello.png', { type: 'image/png' }), + }; + + test('Testing search functionality', async () => { + localStorage.setItem('id', '123'); + render( + + + + + + + + + + ); + await wait(); + + // Test that the search bar filters organizations by name + const searchBar = screen.getByTestId(/searchByName/i); + expect(searchBar).toBeInTheDocument(); + userEvent.type(searchBar, 'Dummy'); + }); + + test('Should render no organisation warning alert when there are no organization', async () => { + window.location.assign('/'); + localStorage.setItem('id', '123'); + + render( + + + + + + + + + + ); + + await wait(); + expect(screen.queryByText('Organizations Not Found')).toBeInTheDocument(); + expect( + screen.queryByText('Please create an organization through dashboard') + ).toBeInTheDocument(); + expect(window.location).toBeAt('/'); + }); + + test('Testing Organization data is not present', async () => { + render( + + + + + + + + ); + + await wait(); + }); + + test('Testing create organization modal', async () => { + localStorage.setItem('id', '123'); + + render( + + + + + + + + + + ); + + await wait(); + const createOrgBtn = screen.getByTestId(/createOrganizationBtn/i); + expect(createOrgBtn).toBeInTheDocument(); + userEvent.click(createOrgBtn); + userEvent.click(screen.getByTestId(/closeModalBtn/i)); + }); + + test('Create organization model should work properly', async () => { + localStorage.setItem('id', '123'); + localStorage.setItem('UserType', 'SUPERADMIN'); + await act(async () => { + render( + + + + + + + + ); + + await wait(500); + + expect(localStorage.setItem).toHaveBeenLastCalledWith( + 'UserType', + 'SUPERADMIN' + ); + + userEvent.click(screen.getByTestId(/createOrganizationBtn/i)); + + userEvent.type( + screen.getByTestId(/modalOrganizationName/i), + formData.name + ); + userEvent.type( + screen.getByPlaceholderText(/Description/i), + formData.description + ); + userEvent.type( + screen.getByPlaceholderText(/Location/i), + formData.location + ); + userEvent.click(screen.getByTestId(/isPublic/i)); + userEvent.click(screen.getByTestId(/visibleInSearch/i)); + userEvent.upload(screen.getByLabelText(/Display Image/i), formData.image); + + await wait(500); + }); + + expect(screen.getByTestId(/modalOrganizationName/i)).toHaveValue( + formData.name + ); + expect(screen.getByPlaceholderText(/Description/i)).toHaveValue( + formData.description + ); + expect(screen.getByPlaceholderText(/Location/i)).toHaveValue( + formData.location + ); + expect(screen.getByTestId(/isPublic/i)).not.toBeChecked(); + expect(screen.getByTestId(/visibleInSearch/i)).toBeChecked(); + expect(screen.getByLabelText(/Display Image/i)).toBeTruthy(); + + userEvent.click(screen.getByTestId(/submitOrganizationForm/i)); + }, 10000); +}); + +describe('Organisations Page testing as Admin', () => { + const link = new StaticMockLink(MOCKS_ADMIN, true); + + test('Create organization modal should not be present in the page for Admin', async () => { + localStorage.setItem('id', '123'); + + render( + + + + + + + + + + ); + + await wait(); + expect(screen.queryByText(/Create Organization/i)).toBeNull(); + }); +}); diff --git a/src/screens/OrgList/OrgList.tsx b/src/screens/OrgList/OrgList.tsx new file mode 100644 index 0000000000..7e0f71ffb9 --- /dev/null +++ b/src/screens/OrgList/OrgList.tsx @@ -0,0 +1,648 @@ +import { useMutation, useQuery } from '@apollo/client'; +import { Search } from '@mui/icons-material'; +import FilterListIcon from '@mui/icons-material/FilterList'; +import SortIcon from '@mui/icons-material/Sort'; +import { CREATE_ORGANIZATION_MUTATION } from 'GraphQl/Mutations/mutations'; +import { + ORGANIZATION_CONNECTION_LIST, + USER_ORGANIZATION_LIST, +} from 'GraphQl/Queries/Queries'; + +import { CREATE_SAMPLE_ORGANIZATION_MUTATION } from 'GraphQl/Mutations/mutations'; + +import OrgListCard from 'components/OrgListCard/OrgListCard'; +import SuperAdminScreen from 'components/SuperAdminScreen/SuperAdminScreen'; +import type { ChangeEvent } from 'react'; +import React, { useEffect, useState } from 'react'; +import { Col, Dropdown, Form, Row } from 'react-bootstrap'; +import Button from 'react-bootstrap/Button'; +import Modal from 'react-bootstrap/Modal'; +import { useTranslation } from 'react-i18next'; +import InfiniteScroll from 'react-infinite-scroll-component'; +import { Link } from 'react-router-dom'; +import { toast } from 'react-toastify'; +import convertToBase64 from 'utils/convertToBase64'; +import debounce from 'utils/debounce'; +import { errorHandler } from 'utils/errorHandler'; +import type { + InterfaceOrgConnectionInfoType, + InterfaceOrgConnectionType, + InterfaceUserType, +} from 'utils/interfaces'; +import styles from './OrgList.module.css'; + +function orgList(): JSX.Element { + const { t } = useTranslation('translation', { keyPrefix: 'orgList' }); + const [dialogModalisOpen, setdialogModalIsOpen] = useState(false); + const [dialogRedirectOrgId, setDialogRedirectOrgId] = useState(''); + /* eslint-disable @typescript-eslint/explicit-function-return-type */ + function openDialogModal(redirectOrgId: string) { + setDialogRedirectOrgId(redirectOrgId); + // console.log(redirectOrgId, dialogRedirectOrgId); + setdialogModalIsOpen(true); + } + + /* eslint-disable @typescript-eslint/explicit-function-return-type */ + function closeDialogModal() { + setdialogModalIsOpen(false); + } + const toggleDialogModal = (): void => + setdialogModalIsOpen(!dialogModalisOpen); + document.title = t('title'); + + const perPageResult = 8; + const [isLoading, setIsLoading] = useState(true); + const [hasMore, sethasMore] = useState(true); + const [isLoadingMore, setIsLoadingMore] = useState(false); + const [searchByName, setSearchByName] = useState(''); + const [showModal, setShowModal] = useState(false); + const [formState, setFormState] = useState({ + name: '', + descrip: '', + ispublic: true, + visible: false, + location: '', + image: '', + }); + + const toggleModal = (): void => setShowModal(!showModal); + + const [create] = useMutation(CREATE_ORGANIZATION_MUTATION); + + const [createSampleOrganization] = useMutation( + CREATE_SAMPLE_ORGANIZATION_MUTATION + ); + + const { + data: userData, + error: errorUser, + }: { + data: InterfaceUserType | undefined; + loading: boolean; + error?: Error | undefined; + } = useQuery(USER_ORGANIZATION_LIST, { + variables: { id: localStorage.getItem('id') }, + }); + + const { + data: orgsData, + loading, + error: errorList, + refetch: refetchOrgs, + fetchMore, + }: { + data: InterfaceOrgConnectionType | undefined; + loading: boolean; + error?: Error | undefined; + refetch: any; + fetchMore: any; + } = useQuery(ORGANIZATION_CONNECTION_LIST, { + variables: { + first: perPageResult, + skip: 0, + filter: searchByName, + }, + notifyOnNetworkStatusChange: true, + }); + + // To clear the search field and form fields on unmount + useEffect(() => { + return () => { + setSearchByName(''); + setFormState({ + name: '', + descrip: '', + ispublic: true, + visible: false, + location: '', + image: '', + }); + }; + }, []); + + useEffect(() => { + setIsLoading(loading && isLoadingMore); + }, [loading]); + + /* istanbul ignore next */ + const isAdminForCurrentOrg = ( + currentOrg: InterfaceOrgConnectionInfoType + ): boolean => { + if (userData?.user?.adminFor.length === 1) { + // If user is admin for one org only then check if that org is current org + return userData?.user?.adminFor[0]._id === currentOrg._id; + } else { + // If user is admin for more than one org then check if current org is present in adminFor array + return ( + userData?.user?.adminFor.some( + (org: { _id: string; name: string; image: string | null }) => + org._id === currentOrg._id + ) ?? false + ); + } + }; + + const triggerCreateSampleOrg = () => { + createSampleOrganization() + .then(() => { + toast.success(t('sampleOrgSuccess')); + window.location.reload(); + }) + .catch(() => { + toast.error(t('sampleOrgDuplicate')); + }); + }; + + const createOrg = async (e: ChangeEvent): Promise => { + e.preventDefault(); + + const { + name: _name, + descrip: _descrip, + location: _location, + visible, + ispublic, + image, + } = formState; + + const name = _name.trim(); + const descrip = _descrip.trim(); + const location = _location.trim(); + + try { + const { data } = await create({ + variables: { + name: name, + description: descrip, + location: location, + visibleInSearch: visible, + isPublic: ispublic, + image: image, + }, + }); + + /* istanbul ignore next */ + if (data) { + toast.success('Congratulation the Organization is created'); + refetchOrgs(); + openDialogModal(data.createOrganization._id); + setFormState({ + name: '', + descrip: '', + ispublic: true, + visible: false, + location: '', + image: '', + }); + toggleModal(); + } + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + + /* istanbul ignore next */ + if (errorList || errorUser) { + window.location.assign('/'); + } + + /* istanbul ignore next */ + const resetAllParams = (): void => { + refetchOrgs({ + filter: '', + first: perPageResult, + skip: 0, + }); + sethasMore(true); + }; + + /* istanbul ignore next */ + const handleSearchByName = (e: any): void => { + const { value } = e.target; + setSearchByName(value); + if (value == '') { + resetAllParams(); + return; + } + refetchOrgs({ + filter: value, + }); + }; + + /* istanbul ignore next */ + const loadMoreOrganizations = (): void => { + console.log('loadMoreOrganizations'); + setIsLoadingMore(true); + fetchMore({ + variables: { + skip: orgsData?.organizationsConnection.length || 0, + }, + updateQuery: ( + prev: + | { organizationsConnection: InterfaceOrgConnectionType[] } + | undefined, + { + fetchMoreResult, + }: { + fetchMoreResult: + | { organizationsConnection: InterfaceOrgConnectionType[] } + | undefined; + } + ): + | { organizationsConnection: InterfaceOrgConnectionType[] } + | undefined => { + setIsLoadingMore(false); + if (!fetchMoreResult) return prev; + if (fetchMoreResult.organizationsConnection.length < perPageResult) { + sethasMore(false); + } + return { + organizationsConnection: [ + ...(prev?.organizationsConnection || []), + ...(fetchMoreResult.organizationsConnection || []), + ], + }; + }, + }); + }; + + const debouncedHandleSearchByName = debounce(handleSearchByName); + return ( + <> + + {/* Buttons Container */} +
    +
    + + +
    +
    +
    + + +
    + {userData && userData.user.userType === 'SUPERADMIN' && ( + + )} +
    +
    + {/* Text Infos for list */} + {!isLoading && + ((orgsData?.organizationsConnection.length === 0 && + searchByName.length == 0) || + (userData && + userData.user.userType === 'ADMIN' && + userData.user.adminFor.length === 0)) ? ( + // eslint-disable-next-line +
    +

    {t('noOrgErrorTitle')}

    +
    {t('noOrgErrorDescription')}
    +
    + ) : !isLoading && + orgsData?.organizationsConnection.length == 0 && + /* istanbul ignore next */ + searchByName.length > 0 ? ( + /* istanbul ignore next */ + // eslint-disable-next-line +
    +

    + {t('noResultsFoundFor')} "{searchByName}" +

    +
    + ) : ( + <> + + {[...Array(perPageResult)].map((_, index) => ( +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + ))} + + } + hasMore={hasMore} + className={styles.listBox} + data-testid="organizations-list" + endMessage={ +
    +
    {t('endOfResults')}
    +
    + } + > + {isLoading ? ( + <> + {[...Array(perPageResult)].map((_, index) => ( +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + ))} + + ) : userData && userData.user.userType == 'SUPERADMIN' ? ( + orgsData?.organizationsConnection.map((item) => { + return ( +
    + +
    + ); + }) + ) : ( + userData && + userData.user.userType == 'ADMIN' && + userData.user.adminFor.length > 0 && + orgsData?.organizationsConnection.map((item) => { + if (isAdminForCurrentOrg(item)) { + return ( +
    + +
    + ); + } + }) + )} + + + )} + {/* Create Organization Modal */} + + + + {t('createOrganization')} + + +
    + + {t('name')} + { + setFormState({ + ...formState, + name: e.target.value, + }); + }} + /> + {t('description')} + { + setFormState({ + ...formState, + descrip: e.target.value, + }); + }} + /> + {t('location')} + { + setFormState({ + ...formState, + location: e.target.value, + }); + }} + /> + + + + {t('isPublic')} + + setFormState({ + ...formState, + ispublic: !formState.ispublic, + }) + } + /> + + + + {t('visibleInSearch')} + + + setFormState({ + ...formState, + visible: !formState.visible, + }) + } + /> + + + {t('displayImage')} + => { + const target = e.target as HTMLInputElement; + const file = target.files && target.files[0]; + /* istanbul ignore else */ + if (file) + setFormState({ + ...formState, + image: await convertToBase64(file), + }); + }} + data-testid="organisationImage" + /> + + + +
    +
    + {t('OR')} +
    + {userData && + ((userData.user.userType === 'ADMIN' && + userData.user.adminFor.length > 0) || + userData.user.userType === 'SUPERADMIN') && ( +
    + +
    + )} + +
    +
    +
    {' '} + {/* Plugin Notification Modal after Org is Created */} + + +
    +
    +
    +

    {t('manageFeatures')}

    + + + + +
    +

    + {t('manageFeaturesInfo')} +

    + +
    + + {t('goToStore')} + + {/* */} + +
    +
    +
    +
    +
    + + + ); +} +export default orgList; diff --git a/src/screens/OrgList/OrgListMocks.ts b/src/screens/OrgList/OrgListMocks.ts new file mode 100644 index 0000000000..1a1ab30ab7 --- /dev/null +++ b/src/screens/OrgList/OrgListMocks.ts @@ -0,0 +1,163 @@ +import { + ORGANIZATION_CONNECTION_LIST, + USER_ORGANIZATION_LIST, +} from 'GraphQl/Queries/Queries'; +import 'jest-location-mock'; +import type { + InterfaceOrgConnectionInfoType, + InterfaceUserType, +} from 'utils/interfaces'; + +const superAdminUser: InterfaceUserType = { + user: { + firstName: 'John', + lastName: 'Doe', + image: '', + email: 'John_Does_Palasidoes@gmail.com', + userType: 'SUPERADMIN', + adminFor: [ + { + _id: '1', + name: 'Akatsuki', + image: '', + }, + ], + }, +}; + +const adminUser: InterfaceUserType = { + user: { ...superAdminUser.user, userType: 'ADMIN' }, +}; + +const organizations: InterfaceOrgConnectionInfoType[] = [ + { + _id: '1', + creator: { _id: 'xyz', firstName: 'John', lastName: 'Doe' }, + image: '', + name: 'Palisadoes Foundation', + createdAt: '02/02/2022', + admins: [ + { + _id: '123', + }, + ], + members: [ + { + _id: '234', + }, + ], + location: 'Jamaica', + }, +]; + +for (let x = 0; x < 100; x++) { + organizations.push({ + _id: 'a' + x, + image: '', + name: 'name', + creator: { + _id: '123', + firstName: 'firstName', + lastName: 'lastName', + }, + admins: [ + { + _id: x + '1', + }, + ], + members: [ + { + _id: x + '2', + }, + ], + createdAt: new Date().toISOString(), + location: 'location', + }); +} + +// MOCKS FOR SUPERADMIN +const MOCKS = [ + { + request: { + query: ORGANIZATION_CONNECTION_LIST, + variables: { + first: 8, + skip: 0, + filter: '', + }, + notifyOnNetworkStatusChange: true, + }, + result: { + data: { + organizationsConnection: organizations, + }, + }, + }, + { + request: { + query: USER_ORGANIZATION_LIST, + variables: { id: '123' }, + }, + result: { + data: superAdminUser, + }, + }, +]; +const MOCKS_EMPTY = [ + { + request: { + query: ORGANIZATION_CONNECTION_LIST, + variables: { + first: 8, + skip: 0, + filter: '', + }, + notifyOnNetworkStatusChange: true, + }, + result: { + data: { + organizationsConnection: [], + }, + }, + }, + { + request: { + query: USER_ORGANIZATION_LIST, + variables: { id: '123' }, + }, + result: { + data: superAdminUser, + }, + }, +]; + +// MOCKS FOR ADMIN +const MOCKS_ADMIN = [ + { + request: { + query: ORGANIZATION_CONNECTION_LIST, + variables: { + first: 8, + skip: 0, + filter: '', + }, + notifyOnNetworkStatusChange: true, + }, + result: { + data: { + organizationsConnection: organizations, + }, + }, + }, + { + request: { + query: USER_ORGANIZATION_LIST, + variables: { id: '123' }, + }, + result: { + data: adminUser, + }, + }, +]; + +export { MOCKS, MOCKS_ADMIN, MOCKS_EMPTY }; diff --git a/src/screens/OrgPost/OrgPost.module.css b/src/screens/OrgPost/OrgPost.module.css new file mode 100644 index 0000000000..f9ff4a0794 --- /dev/null +++ b/src/screens/OrgPost/OrgPost.module.css @@ -0,0 +1,323 @@ +.mainpage { + display: flex; + flex-direction: row; +} +.btnsContainer { + display: flex; + margin: 2.5rem 0 2.5rem 0; +} + +.btnsContainer .btnsBlock { + display: flex; +} + +.btnsContainer .btnsBlock button { + margin-left: 1rem; + display: flex; + justify-content: center; + align-items: center; +} + +.btnsContainer .input { + flex: 1; + position: relative; +} + +.btnsContainer input { + outline: 1px solid var(--bs-gray-400); +} + +.btnsContainer .input button { + width: 52px; +} + +.preview { + display: flex; + position: relative; + width: 100%; + margin-top: 10px; + justify-content: center; +} +.preview img { + width: 400px; + height: auto; +} +.preview video { + width: 400px; + height: auto; +} +.logintitle { + color: #707070; + font-weight: 600; + font-size: 20px; + margin-bottom: 30px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 15%; +} +.logintitleadmin { + color: #707070; + font-weight: 600; + font-size: 18px; + margin-top: 50px; + margin-bottom: 40px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 30%; +} +.admindetails { + display: flex; + justify-content: space-between; +} +.admindetails > p { + margin-top: -12px; + margin-right: 30px; +} + +.mainpageright > hr { + margin-top: 20px; + width: 100%; + margin-left: -15px; + margin-right: -15px; + margin-bottom: 20px; +} +.justifysp { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 3rem; +} + +@media (max-width: 1120px) { + .contract { + padding-left: calc(250px + 2rem + 1.5rem); + } + + .listBox .itemCard { + width: 100%; + } +} + +@media (max-width: 1020px) { + .btnsContainer { + flex-direction: column; + margin: 1.5rem 0; + } + + .btnsContainer .btnsBlock { + margin: 1.5rem 0 0 0; + justify-content: space-between; + } + + .btnsContainer .btnsBlock button { + margin: 0; + } + + .btnsContainer .btnsBlock div button { + margin-right: 1.5rem; + } +} + +/* For mobile devices */ + +@media (max-width: 520px) { + .btnsContainer { + margin-bottom: 0; + } + + .btnsContainer .btnsBlock { + display: block; + margin-top: 1rem; + margin-right: 0; + } + + .btnsContainer .btnsBlock div { + flex: 1; + } + + .btnsContainer .btnsBlock div[title='Sort organizations'] { + margin-right: 0.5rem; + } + + .btnsContainer .btnsBlock button { + margin-bottom: 1rem; + margin-right: 0; + width: 100%; + } +} +@media screen and (max-width: 575.5px) { + .justifysp { + display: flex; + justify-content: space-between; + width: 100%; + } + + .mainpageright { + width: 98%; + } +} +.addbtn { + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + border-radius: 5px; + font-size: 16px; + height: 60%; + width: 60%; + color: white; + outline: none; + font-weight: 600; + cursor: pointer; + transition: transform 0.2s, box-shadow 0.2s; +} +.flexdir { + display: flex; + flex-direction: row; + justify-content: space-between; + border: none; +} +.form_wrapper { + margin-top: 27px; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + position: absolute; + display: flex; + flex-direction: column; + padding: 20px 30px; + background: #ffffff; + border-color: #e8e5e5; + border-width: 5px; + border-radius: 10px; +} + +.form_wrapper form { + display: flex; + align-items: left; + justify-content: left; + flex-direction: column; +} +.logintitleinvite { + color: #707070; + font-weight: 600; + font-size: 20px; + margin-bottom: 20px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 40%; +} +.postinfo { + height: 80px; +} + +.postinfo { + height: 80px; + margin-bottom: 20px; +} +.titlemodal { + color: #707070; + font-weight: 600; + font-size: 20px; + margin-bottom: 20px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 65%; +} +.cancel > i { + margin-top: 5px; + transform: scale(1.2); + cursor: pointer; + color: #707070; +} +.modalbody { + width: 50px; +} + +.closeButton { + position: absolute; + top: 0px; + right: 0px; + background: transparent; + transform: scale(1.2); + cursor: pointer; + border: none; + color: #707070; + font-weight: 600; + font-size: 16px; + cursor: pointer; +} +.sidebarsticky > input { + text-decoration: none; + margin-bottom: 50px; + border: solid 1.5px #d3d3d3; + border-radius: 5px; + width: 80%; + border-radius: 7px; + padding-top: 5px; + padding-bottom: 5px; + padding-right: 10px; + padding-left: 10px; + text-decoration: none; + box-shadow: none; +} + +.sidebarsticky > input:focus { + border-color: #fff; + box-shadow: 0 0 5pt 0.5pt #d3d3d3; + outline: none; +} +button[data-testid='createPostBtn'] { + display: block; +} +.loader, +.loader:after { + border-radius: 50%; + width: 10em; + height: 10em; +} +.loader { + margin: 60px auto; + margin-top: 35vh !important; + font-size: 10px; + position: relative; + text-indent: -9999em; + border-top: 1.1em solid rgba(255, 255, 255, 0.2); + border-right: 1.1em solid rgba(255, 255, 255, 0.2); + border-bottom: 1.1em solid rgba(255, 255, 255, 0.2); + border-left: 1.1em solid #febc59; + -webkit-transform: translateZ(0); + -ms-transform: translateZ(0); + transform: translateZ(0); + -webkit-animation: load8 1.1s infinite linear; + animation: load8 1.1s infinite linear; +} +@-webkit-keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} +@keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} +.list_box { + height: 70vh; + overflow-y: auto; + width: auto; +} +@media only screen and (max-width: 600px) { + .form_wrapper { + width: 90%; + top: 45%; + } +} diff --git a/src/screens/OrgPost/OrgPost.test.tsx b/src/screens/OrgPost/OrgPost.test.tsx new file mode 100644 index 0000000000..85dfc03edc --- /dev/null +++ b/src/screens/OrgPost/OrgPost.test.tsx @@ -0,0 +1,548 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { BrowserRouter } from 'react-router-dom'; +import { act, render, screen, fireEvent } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { Provider } from 'react-redux'; +import 'jest-location-mock'; +import { I18nextProvider } from 'react-i18next'; + +import OrgPost from './OrgPost'; +import { store } from 'state/store'; +import { ORGANIZATION_POST_CONNECTION_LIST } from 'GraphQl/Queries/Queries'; +import { CREATE_POST_MUTATION } from 'GraphQl/Mutations/mutations'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { ToastContainer } from 'react-toastify'; +import { debug } from 'jest-preview'; + +const MOCKS = [ + { + request: { + query: ORGANIZATION_POST_CONNECTION_LIST, + variables: { + id: undefined, + title_contains: '', + text_contains: '', + }, + }, + result: { + data: { + postsByOrganizationConnection: { + edges: [ + { + _id: '6411e53835d7ba2344a78e21', + title: 'postone', + text: 'This is the first post', + imageUrl: null, + videoUrl: null, + createdAt: '2023-08-24T09:26:56.524+00:00', + creator: { + _id: '640d98d9eb6a743d75341067', + firstName: 'Aditya', + lastName: 'Shelke', + email: 'adidacreator1@gmail.com', + }, + likeCount: 0, + commentCount: 0, + comments: [], + pinned: false, + likedBy: [], + }, + { + _id: '6411e54835d7ba2344a78e29', + title: 'posttwo', + text: 'Tis is the post two', + imageUrl: null, + videoUrl: null, + createdAt: '2023-08-24T09:26:56.524+00:00', + creator: { + _id: '640d98d9eb6a743d75341067', + firstName: 'Aditya', + lastName: 'Shelke', + email: 'adidacreator1@gmail.com', + }, + likeCount: 0, + commentCount: 0, + pinned: false, + likedBy: [], + comments: [], + }, + ], + }, + }, + }, + }, + { + request: { + query: CREATE_POST_MUTATION, + variables: { + title: 'Dummy Post', + text: 'This is dummy text', + organizationId: '123', + }, + result: { + data: { + createPost: { + _id: '453', + }, + }, + }, + }, + }, + { + request: { + query: CREATE_POST_MUTATION, + variables: { + title: 'Dummy Post', + text: 'This is dummy text', + organizationId: '123', + }, + result: { + data: { + createPost: { + _id: '453', + }, + }, + }, + }, + }, +]; +const link = new StaticMockLink(MOCKS, true); + +async function wait(ms = 500): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Organisation Post Page', () => { + const formData = { + posttitle: 'dummy post', + postinfo: 'This is a dummy post', + postImage: new File(['hello'], 'hello.png', { type: 'image/png' }), + postVideo: new File(['hello'], 'hello.mp4', { type: 'video/mp4' }), + }; + + test('correct mock data should be queried', async () => { + const dataQuery1 = + MOCKS[0]?.result?.data?.postsByOrganizationConnection.edges[0]; + + expect(dataQuery1).toEqual({ + _id: '6411e53835d7ba2344a78e21', + title: 'postone', + text: 'This is the first post', + imageUrl: null, + videoUrl: null, + createdAt: '2023-08-24T09:26:56.524+00:00', + creator: { + _id: '640d98d9eb6a743d75341067', + firstName: 'Aditya', + lastName: 'Shelke', + email: 'adidacreator1@gmail.com', + }, + likeCount: 0, + commentCount: 0, + pinned: false, + likedBy: [], + comments: [], + }); + }); + + test('Testing create post functionality', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('createPostModalBtn')); + + userEvent.type(screen.getByTestId('modalTitle'), formData.posttitle); + + userEvent.type(screen.getByTestId('modalinfo'), formData.postinfo); + userEvent.upload( + screen.getByTestId('organisationImage'), + formData.postImage + ); + userEvent.upload( + screen.getByTestId('organisationImage'), + formData.postVideo + ); + + userEvent.click(screen.getByTestId('createPostBtn')); + + await wait(); + + userEvent.click(screen.getByTestId('closeOrganizationModal')); + }, 15000); + + test('Testing search functionality', async () => { + render( + + + + + + + + + + ); + async function debounceWait(ms = 200): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); + } + await debounceWait(); + userEvent.type(screen.getByPlaceholderText(/Search By/i), 'postone'); + await debounceWait(); + const sortDropdown = screen.getByTestId('sort'); + userEvent.click(sortDropdown); + }); + test('Testing search text and title toggle', async () => { + await act(async () => { + // Wrap the test code in act + render( + + + + + + + + + + ); + + await wait(); + + const searchInput = screen.getByTestId('searchByName'); + expect(searchInput).toHaveAttribute('placeholder', 'Search By Title'); + + const inputText = screen.getByTestId('searchBy'); + + fireEvent.click(inputText); + const toggleText = screen.getByTestId('Text'); + + fireEvent.click(toggleText); + + expect(searchInput).toHaveAttribute('placeholder', 'Search By Text'); + fireEvent.click(inputText); + const toggleTite = screen.getByTestId('searchTitle'); + fireEvent.click(toggleTite); + expect(searchInput).toHaveAttribute('placeholder', 'Search By Title'); + }); + }); + test('Testing search latest and oldest toggle', async () => { + await act(async () => { + // Wrap the test code in act + render( + + + + + + + + + + ); + + await wait(); + + const searchInput = screen.getByTestId('sort'); + expect(searchInput).toBeInTheDocument(); + + const inputText = screen.getByTestId('sortpost'); + + fireEvent.click(inputText); + const toggleText = screen.getByTestId('latest'); + + fireEvent.click(toggleText); + + expect(searchInput).toBeInTheDocument(); + fireEvent.click(inputText); + const toggleTite = screen.getByTestId('oldest'); + fireEvent.click(toggleTite); + expect(searchInput).toBeInTheDocument(); + }); + }); + test('After creating a post, the data should be refetched', async () => { + const refetchMock = jest.fn(); + + render( + + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('createPostModalBtn')); + + // Fill in post form fields... + + userEvent.click(screen.getByTestId('createPostBtn')); + + await wait(); + + expect(refetchMock).toHaveBeenCalledTimes(0); + }); + + test('Create post without media', async () => { + render( + + + + + + + + + + + ); + + await wait(); + userEvent.click(screen.getByTestId('createPostModalBtn')); + + const postTitleInput = screen.getByTestId('modalTitle'); + fireEvent.change(postTitleInput, { target: { value: 'Test Post' } }); + + const postInfoTextarea = screen.getByTestId('modalinfo'); + fireEvent.change(postInfoTextarea, { + target: { value: 'Test post information' }, + }); + + const createPostBtn = screen.getByTestId('createPostBtn'); + fireEvent.click(createPostBtn); + }, 15000); + + test('Create post and preview', async () => { + render( + + + + + + + + + + + ); + + await wait(); + userEvent.click(screen.getByTestId('createPostModalBtn')); + + const postTitleInput = screen.getByTestId('modalTitle'); + fireEvent.change(postTitleInput, { target: { value: 'Test Post' } }); + + const postInfoTextarea = screen.getByTestId('modalinfo'); + fireEvent.change(postInfoTextarea, { + target: { value: 'Test post information' }, + }); + const file = new File(['image content'], 'image.png', { + type: 'image/png', + }); + const input = screen.getByTestId('organisationImage'); + userEvent.upload(input, file); + + await screen.findByAltText('Post Image Preview'); + expect(screen.getByAltText('Post Image Preview')).toBeInTheDocument(); + + const createPostBtn = screen.getByTestId('createPostBtn'); + fireEvent.click(createPostBtn); + debug(); + }, 15000); + + test('Modal opens and closes', async () => { + render( + + + + + + + + + + ); + + await wait(); + + const createPostModalBtn = screen.getByTestId('createPostModalBtn'); + + userEvent.click(createPostModalBtn); + + const modalTitle = screen.getByTestId('modalOrganizationHeader'); + expect(modalTitle).toBeInTheDocument(); + + const closeButton = screen.getByTestId('closeOrganizationModal'); + userEvent.click(closeButton); + + await wait(); + + const closedModalTitle = screen.queryByText(/postDetail/i); + expect(closedModalTitle).not.toBeInTheDocument(); + }); + it('renders the form with input fields and buttons', async () => { + render( + + + + + + + + + + + ); + + await wait(); + userEvent.click(screen.getByTestId('createPostModalBtn')); + + // Check if input fields and buttons are present + expect(screen.getByTestId('modalTitle')).toBeInTheDocument(); + expect(screen.getByTestId('modalinfo')).toBeInTheDocument(); + expect(screen.getByTestId('organisationImage')).toBeInTheDocument(); + expect(screen.getByTestId('organisationVideo')).toBeInTheDocument(); + expect(screen.getByTestId('createPostBtn')).toBeInTheDocument(); + }); + + it('allows users to input data into the form fields', async () => { + render( + + + + + + + + + + + ); + + await wait(); + userEvent.click(screen.getByTestId('createPostModalBtn')); + + // Simulate user input + fireEvent.change(screen.getByTestId('modalTitle'), { + target: { value: 'Test Title' }, + }); + fireEvent.change(screen.getByTestId('modalinfo'), { + target: { value: 'Test Info' }, + }); + + // Check if input values are set correctly + expect(screen.getByTestId('modalTitle')).toHaveValue('Test Title'); + expect(screen.getByTestId('modalinfo')).toHaveValue('Test Info'); + }); + + test('allows users to upload an image', async () => { + render( + + + + + + + + + + + ); + + await wait(); + userEvent.click(screen.getByTestId('createPostModalBtn')); + + const postTitleInput = screen.getByTestId('modalTitle'); + fireEvent.change(postTitleInput, { target: { value: 'Test Post' } }); + + const postInfoTextarea = screen.getByTestId('modalinfo'); + fireEvent.change(postInfoTextarea, { + target: { value: 'Test post information' }, + }); + const file = new File(['image content'], 'image.png', { + type: 'image/png', + }); + const input = screen.getByTestId('organisationImage'); + userEvent.upload(input, file); + + await screen.findByAltText('Post Image Preview'); + expect(screen.getByAltText('Post Image Preview')).toBeInTheDocument(); + + const closeButton = screen.getByTestId('closePreview'); + fireEvent.click(closeButton); + }, 15000); + test('Create post, preview image, and close preview', async () => { + await act(async () => { + render( + + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('createPostModalBtn')); + + const postTitleInput = screen.getByTestId('modalTitle'); + fireEvent.change(postTitleInput, { target: { value: 'Test Post' } }); + + const postInfoTextarea = screen.getByTestId('modalinfo'); + fireEvent.change(postInfoTextarea, { + target: { value: 'Test post information' }, + }); + + const videoFile = new File(['video content'], 'video.mp4', { + type: 'video/mp4', + }); + + const videoInput = screen.getByTestId('organisationVideo'); + fireEvent.change(videoInput, { + target: { + files: [videoFile], + }, + }); + + // Check if the video is displayed + const videoPreview = await screen.findByTestId('videoPreview'); + expect(videoPreview).toBeInTheDocument(); + + // Check if the close button for the video works + const closeVideoPreviewButton = screen.getByTestId('videoclosebutton'); + fireEvent.click(closeVideoPreviewButton); + expect(videoPreview).not.toBeInTheDocument(); + }); + }); +}); diff --git a/src/screens/OrgPost/OrgPost.tsx b/src/screens/OrgPost/OrgPost.tsx new file mode 100644 index 0000000000..9f098c291b --- /dev/null +++ b/src/screens/OrgPost/OrgPost.tsx @@ -0,0 +1,502 @@ +import type { ChangeEvent } from 'react'; +import React, { useState, useEffect } from 'react'; +import { Search } from '@mui/icons-material'; +import SortIcon from '@mui/icons-material/Sort'; +import Row from 'react-bootstrap/Row'; +import Modal from 'react-bootstrap/Modal'; +import { Form } from 'react-bootstrap'; +import { useMutation, useQuery } from '@apollo/client'; +import Button from 'react-bootstrap/Button'; +import { toast } from 'react-toastify'; +import { useTranslation } from 'react-i18next'; +import Dropdown from 'react-bootstrap/Dropdown'; +import styles from './OrgPost.module.css'; +import OrgPostCard from 'components/OrgPostCard/OrgPostCard'; +import { ORGANIZATION_POST_CONNECTION_LIST } from 'GraphQl/Queries/Queries'; +import { CREATE_POST_MUTATION } from 'GraphQl/Mutations/mutations'; +import debounce from 'utils/debounce'; +import convertToBase64 from 'utils/convertToBase64'; +import NotFound from 'components/NotFound/NotFound'; +import { errorHandler } from 'utils/errorHandler'; +import Loader from 'components/Loader/Loader'; +import OrganizationScreen from 'components/OrganizationScreen/OrganizationScreen'; + +interface InterfaceOrgPost { + _id: string; + title: string; + text: string; + imageUrl: string; + videoUrl: string; + organizationId: string; + creator: { firstName: string; lastName: string }; + pinned: boolean; + createdAt: string; +} + +function orgPost(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'orgPost', + }); + + document.title = t('title'); + const [postmodalisOpen, setPostModalIsOpen] = useState(false); + const [postformState, setPostFormState] = useState({ + posttitle: '', + postinfo: '', + postImage: '', + postVideo: '', + }); + const [sortingOption, setSortingOption] = useState('latest'); + const [showTitle, setShowTitle] = useState(true); + + const currentUrl = window.location.href.split('=')[1]; + + const showInviteModal = (): void => { + setPostModalIsOpen(true); + }; + const hideInviteModal = (): void => { + setPostModalIsOpen(false); + setPostFormState({ + posttitle: '', + postinfo: '', + postImage: '', + postVideo: '', + }); + }; + + const { + data: orgPostListData, + loading: orgPostListLoading, + error: orgPostListError, + refetch, + } = useQuery(ORGANIZATION_POST_CONNECTION_LIST, { + variables: { id: currentUrl, title_contains: '', text_contains: '' }, + }); + const [create, { loading: createPostLoading }] = + useMutation(CREATE_POST_MUTATION); + const [displayedPosts, setDisplayedPosts] = useState( + orgPostListData?.postsByOrganizationConnection.edges || [] + ); + + useEffect(() => { + if (orgPostListData && orgPostListData.postsByOrganizationConnection) { + const newDisplayedPosts = sortPosts( + orgPostListData.postsByOrganizationConnection.edges, + sortingOption + ); + setDisplayedPosts(newDisplayedPosts); + } + }, [orgPostListData, sortingOption]); + const createPost = async (e: ChangeEvent): Promise => { + e.preventDefault(); + + const { + posttitle: _posttitle, + postinfo: _postinfo, + postImage, + postVideo, + } = postformState; + + const posttitle = _posttitle.trim(); + const postinfo = _postinfo.trim(); + + try { + if (!posttitle || !postinfo) { + throw new Error('Text fields cannot be empty strings'); + } + + const { data } = await create({ + variables: { + title: posttitle, + text: postinfo, + organizationId: currentUrl, + file: postImage || postVideo, + }, + }); + /* istanbul ignore next */ + if (data) { + toast.success('Congratulations! You have Posted Something.'); + refetch(); + setPostFormState({ + posttitle: '', + postinfo: '', + postImage: '', + postVideo: '', + }); + setPostModalIsOpen(false); // close the modal + } + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + + if (createPostLoading || orgPostListLoading) { + return ; + } + + /* istanbul ignore next */ + if (orgPostListError) { + window.location.assign('/orglist'); + } + + const handleSearch = (e: any): void => { + const { value } = e.target; + const filterData = { + id: currentUrl, + title_contains: showTitle ? value : null, + text_contains: !showTitle ? value : null, + }; + refetch(filterData); + }; + + const debouncedHandleSearch = debounce(handleSearch); + + const handleSorting = (option: string): void => { + setSortingOption(option); + }; + + const sortPosts = ( + posts: InterfaceOrgPost[], + sortingOption: string + ): InterfaceOrgPost[] => { + const sortedPosts = [...posts]; + + if (sortingOption === 'latest') { + sortedPosts.sort( + (a, b) => + new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime() + ); + } else if (sortingOption === 'oldest') { + sortedPosts.sort( + (a, b) => + new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime() + ); + } + + return sortedPosts; + }; + + const sortedPostsList: InterfaceOrgPost[] = [...displayedPosts]; + sortedPostsList.sort((a: InterfaceOrgPost, b: InterfaceOrgPost) => { + if (a.pinned === b.pinned) { + return 0; + } + + if (a.pinned) { + return -1; + } + return 1; + }); + return ( + <> + + +
    +
    +
    + + +
    +
    +
    + + +
    + + +
    +
    +
    + {sortedPostsList && sortedPostsList.length > 0 ? ( + sortedPostsList.map( + (datas: { + _id: string; + title: string; + text: string; + imageUrl: string; + videoUrl: string; + organizationId: string; + creator: { firstName: string; lastName: string }; + pinned: boolean; + }) => ( + + ) + ) + ) : ( + + )} +
    +
    +
    +
    + + + {t('postDetails')} + +
    + + {t('postTitle')} + { + setPostFormState({ + ...postformState, + posttitle: e.target.value, + }); + }} + /> + {t('information')} + { + setPostFormState({ + ...postformState, + postinfo: e.target.value, + }); + }} + /> + {!postformState.postVideo && ( + <> + {t('image')} + + ): Promise => { + setPostFormState((prevPostFormState) => ({ + ...prevPostFormState, + postImage: '', + })); + const file = e.target.files?.[0]; + if (file) { + setPostFormState({ + ...postformState, + postImage: await convertToBase64(file), + }); + } + }} + /> + + {postformState.postImage && ( +
    + Post Image Preview + +
    + )} + + )} + {!postformState.postImage && ( + <> + {t('video')} + => { + setPostFormState((prevPostFormState) => ({ + ...prevPostFormState, + postVideo: '', + })); + const target = e.target as HTMLInputElement; + const file = target.files && target.files[0]; + if (file) { + const videoBase64 = await convertToBase64(file); + setPostFormState({ + ...postformState, + postVideo: videoBase64, + }); + } + }} + data-testid="organisationVideo" + /> + + {postformState.postVideo && ( +
    + + +
    + )} + + )} +
    + + + + +
    +
    + + ); +} +export default orgPost; diff --git a/src/screens/OrgSettings/OrgSettings.module.css b/src/screens/OrgSettings/OrgSettings.module.css new file mode 100644 index 0000000000..2b15a2ac0c --- /dev/null +++ b/src/screens/OrgSettings/OrgSettings.module.css @@ -0,0 +1,25 @@ +.settingsBody { + margin: 2.5rem 0; +} + +.cardHeader { + padding: 1.25rem 1rem 1rem 1rem; + border-bottom: 1px solid var(--bs-gray-200); + display: flex; + justify-content: space-between; + align-items: center; +} + +.cardHeader .cardTitle { + font-size: 1.2rem; + font-weight: 600; +} + +.cardBody { + min-height: 180px; +} + +.cardBody .textBox { + margin: 0 0 3rem 0; + color: var(--bs-secondary); +} diff --git a/src/screens/OrgSettings/OrgSettings.test.tsx b/src/screens/OrgSettings/OrgSettings.test.tsx new file mode 100644 index 0000000000..a5323f39c5 --- /dev/null +++ b/src/screens/OrgSettings/OrgSettings.test.tsx @@ -0,0 +1,121 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { render, screen } from '@testing-library/react'; +import 'jest-location-mock'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; + +import { DELETE_ORGANIZATION_MUTATION } from 'GraphQl/Mutations/mutations'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18nForTest from 'utils/i18nForTest'; +import OrgSettings from './OrgSettings'; +import { ORGANIZATIONS_LIST } from 'GraphQl/Queries/Queries'; + +const MOCKS = [ + { + request: { + query: ORGANIZATIONS_LIST, + }, + result: { + data: { + organizations: [ + { + _id: '123', + image: null, + name: 'Palisadoes', + description: 'Equitable Access to STEM Education Jobs', + location: 'Jamaica', + isPublic: true, + visibleInSearch: false, + creator: { + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@example.com', + }, + members: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@gmail.com', + }, + admins: [ + { + _id: '123', + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@gmail.com', + }, + ], + membershipRequests: { + _id: '456', + user: { + firstName: 'Sam', + lastName: 'Smith', + email: 'samsmith@gmail.com', + }, + }, + blockedUsers: [], + }, + ], + }, + }, + }, + { + request: { + query: DELETE_ORGANIZATION_MUTATION, + }, + result: { + data: { + removeOrganization: [ + { + _id: 123, + }, + ], + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); + +afterEach(() => { + localStorage.clear(); +}); + +describe('Organisation Settings Page', () => { + test('correct mock data should be queried', async () => { + const dataQuery1 = MOCKS[1]?.result?.data?.removeOrganization; + expect(dataQuery1).toEqual([ + { + _id: 123, + }, + ]); + }); + + test('should render props and text elements test for the screen', async () => { + window.location.assign('/orgsetting/id=123'); + localStorage.setItem('UserType', 'SUPERADMIN'); + render( + + + + + + + + + + ); + expect(screen.getAllByText(/Delete Organization/i)).toHaveLength(3); + expect( + screen.getByText( + /By clicking on Delete Organization button the organization will be permanently deleted along with its events, tags and all related data/i + ) + ).toBeInTheDocument(); + expect(screen.getByText(/Other Settings/i)).toBeInTheDocument(); + expect(screen.getByText(/Change Language/i)).toBeInTheDocument(); + expect(window.location).toBeAt('/orgsetting/id=123'); + }); +}); diff --git a/src/screens/OrgSettings/OrgSettings.tsx b/src/screens/OrgSettings/OrgSettings.tsx new file mode 100644 index 0000000000..91a8874fa1 --- /dev/null +++ b/src/screens/OrgSettings/OrgSettings.tsx @@ -0,0 +1,58 @@ +import React from 'react'; +import ChangeLanguageDropDown from 'components/ChangeLanguageDropdown/ChangeLanguageDropDown'; +import DeleteOrg from 'components/DeleteOrg/DeleteOrg'; +import OrgUpdate from 'components/OrgUpdate/OrgUpdate'; +import OrganizationScreen from 'components/OrganizationScreen/OrganizationScreen'; +import { Card, Form } from 'react-bootstrap'; +import Col from 'react-bootstrap/Col'; +import Row from 'react-bootstrap/Row'; +import { useTranslation } from 'react-i18next'; +import styles from './OrgSettings.module.css'; + +function orgSettings(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'orgSettings', + }); + + document.title = t('title'); + const orgId = window.location.href.split('=')[1]; + + return ( + <> + + + + +
    +
    + {t('updateOrganization')} +
    +
    + + {orgId && } + +
    + + + + +
    +
    {t('otherSettings')}
    +
    + +
    + + {t('changeLanguage')} + + +
    +
    +
    + +
    +
    + + ); +} + +export default orgSettings; diff --git a/src/screens/OrganizationDashboard/OrganizationDashboard.module.css b/src/screens/OrganizationDashboard/OrganizationDashboard.module.css new file mode 100644 index 0000000000..485200b1ae --- /dev/null +++ b/src/screens/OrganizationDashboard/OrganizationDashboard.module.css @@ -0,0 +1,24 @@ +.cardHeader { + padding: 1.25rem 1rem 1rem 1rem; + border-bottom: 1px solid var(--bs-gray-200); + display: flex; + justify-content: space-between; + align-items: center; +} + +.cardHeader .cardTitle { + font-size: 1.2rem; + font-weight: 600; +} + +.cardBody { + min-height: 180px; + padding-top: 0; +} + +.cardBody .emptyContainer { + display: flex; + height: 180px; + justify-content: center; + align-items: center; +} diff --git a/src/screens/OrganizationDashboard/OrganizationDashboard.test.tsx b/src/screens/OrganizationDashboard/OrganizationDashboard.test.tsx new file mode 100644 index 0000000000..cb221f94ce --- /dev/null +++ b/src/screens/OrganizationDashboard/OrganizationDashboard.test.tsx @@ -0,0 +1,150 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { act, fireEvent, render, screen } from '@testing-library/react'; +import 'jest-location-mock'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; + +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import OrganizationDashboard from './OrganizationDashboard'; +import { EMPTY_MOCKS, ERROR_MOCKS, MOCKS } from './OrganizationDashboardMocks'; +import i18nForTest from 'utils/i18nForTest'; +import { toast } from 'react-toastify'; +import userEvent from '@testing-library/user-event'; + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} +const link1 = new StaticMockLink(MOCKS, true); +const link2 = new StaticMockLink(EMPTY_MOCKS, true); +const link3 = new StaticMockLink(ERROR_MOCKS, true); + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }, +})); + +beforeEach(() => { + localStorage.setItem('FirstName', 'John'); + localStorage.setItem('LastName', 'Doe'); + localStorage.setItem('UserType', 'SUPERADMIN'); + localStorage.setItem( + 'UserImage', + 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe' + ); +}); + +afterEach(() => { + jest.clearAllMocks(); + localStorage.clear(); +}); + +describe('Organisation Dashboard Page', () => { + test('Should render props and text elements test for the screen', async () => { + await act(async () => { + render( + + + + + + + + + + ); + }); + + await wait(); + expect(screen.getByText('Members')).toBeInTheDocument(); + expect(screen.getByText('Admins')).toBeInTheDocument(); + expect(screen.getAllByText('Posts')).toHaveLength(2); + expect(screen.getAllByText('Events')).toHaveLength(2); + expect(screen.getByText('Blocked Users')).toBeInTheDocument(); + expect(screen.getByText('Requests')).toBeInTheDocument(); + expect(screen.getByText('Upcoming Events')).toBeInTheDocument(); + expect(screen.getByText('Latest Posts')).toBeInTheDocument(); + expect(screen.getByText('Membership requests')).toBeInTheDocument(); + + // Checking if posts are rendered + expect(screen.getByText('Post 15')).toBeInTheDocument(); + + // Checking if membership requests are rendered + expect(screen.getByText('Jane Doe')).toBeInTheDocument(); + + const peopleBtn = screen.getByText('Members'); + const adminBtn = screen.getByText('Admins'); + const postBtn = screen.getAllByText('Posts'); + const eventBtn = screen.getAllByText('Events'); + const blockUserBtn = screen.getByText('Blocked Users'); + const requestBtn = screen.getByText('Requests'); + userEvent.click(peopleBtn); + userEvent.click(adminBtn); + userEvent.click(postBtn[0]); + userEvent.click(eventBtn[0]); + userEvent.click(postBtn[1]); + userEvent.click(eventBtn[1]); + userEvent.click(blockUserBtn); + userEvent.click(requestBtn); + }); + + test('Testing buttons and checking empty events, posts and membership requests', async () => { + await act(async () => { + render( + + + + + + + + + + ); + }); + + await wait(); + const viewEventsBtn = screen.getByTestId('viewAllEvents'); + const viewPostsBtn = screen.getByTestId('viewAllPosts'); + const viewMSBtn = screen.getByTestId('viewAllMembershipRequests'); + + userEvent.click(viewEventsBtn); + userEvent.click(viewPostsBtn); + fireEvent.click(viewMSBtn); + expect(toast.success).toBeCalledWith('Coming soon!'); + + expect( + screen.getByText(/No membership requests present/i) + ).toBeInTheDocument(); + expect(screen.getByText(/No upcoming events/i)).toBeInTheDocument(); + expect(screen.getByText(/No posts present/i)).toBeInTheDocument(); + }); + + test('Testing error scenario', async () => { + await act(async () => { + render( + + + + + + + + + + ); + }); + + await wait(); + expect(window.location).toBeAt('/orglist'); + }); +}); diff --git a/src/screens/OrganizationDashboard/OrganizationDashboard.tsx b/src/screens/OrganizationDashboard/OrganizationDashboard.tsx new file mode 100644 index 0000000000..60e31396a5 --- /dev/null +++ b/src/screens/OrganizationDashboard/OrganizationDashboard.tsx @@ -0,0 +1,349 @@ +import React, { useEffect, useState } from 'react'; +import { useQuery } from '@apollo/client'; +import { Button, Card } from 'react-bootstrap'; +import Col from 'react-bootstrap/Col'; +import Row from 'react-bootstrap/Row'; +import { useTranslation } from 'react-i18next'; + +import { + ORGANIZATIONS_LIST, + ORGANIZATION_POST_CONNECTION_LIST, + ORGANIZATION_EVENT_CONNECTION_LIST, +} from 'GraphQl/Queries/Queries'; +import { ReactComponent as AdminsIcon } from 'assets/svgs/admin.svg'; +import { ReactComponent as BlockedUsersIcon } from 'assets/svgs/blockedUser.svg'; +import { ReactComponent as EventsIcon } from 'assets/svgs/events.svg'; +import { ReactComponent as PostsIcon } from 'assets/svgs/post.svg'; +import { ReactComponent as UsersIcon } from 'assets/svgs/users.svg'; +import DashBoardCard from 'components/OrganizationDashCards/DashboardCard'; +import OrganizationScreen from 'components/OrganizationScreen/OrganizationScreen'; +import styles from './OrganizationDashboard.module.css'; +import CardItem from 'components/OrganizationDashCards/CardItem'; +import type { ApolloError } from '@apollo/client'; +import type { + InterfaceQueryOrganizationEventListItem, + InterfaceQueryOrganizationsListObject, +} from 'utils/interfaces'; +import { toast } from 'react-toastify'; +import { useHistory } from 'react-router-dom'; +import CardItemLoading from 'components/OrganizationDashCards/CardItemLoading'; +import DashboardCardLoading from 'components/OrganizationDashCards/DashboardCardLoading'; + +function organizationDashboard(): JSX.Element { + const { t } = useTranslation('translation', { keyPrefix: 'dashboard' }); + document.title = t('title'); + const currentUrl = window.location.href.split('=')[1]; + const peopleLink = `/orgpeople/id=${currentUrl}`; + const postsLink = `/orgpost/id=${currentUrl}`; + const eventsLink = `/orgevents/id=${currentUrl}`; + const blockUserLink = `/blockuser/id=${currentUrl}`; + const requestLink = '/requests'; + + const history = useHistory(); + const [upcomingEvents, setUpcomingEvents] = useState< + InterfaceQueryOrganizationEventListItem[] + >([]); + + const { + data, + loading: loadingOrgData, + error: errorOrg, + }: { + data?: { + organizations: InterfaceQueryOrganizationsListObject[]; + }; + loading: boolean; + error?: ApolloError; + } = useQuery(ORGANIZATIONS_LIST, { + variables: { id: currentUrl }, + }); + + const { + data: postData, + loading: loadingPost, + error: errorPost, + } = useQuery(ORGANIZATION_POST_CONNECTION_LIST, { + variables: { id: currentUrl }, + }); + + const { + data: eventData, + loading: loadingEvent, + error: errorEvent, + }: { + data: any; + loading: boolean; + error?: ApolloError; + } = useQuery(ORGANIZATION_EVENT_CONNECTION_LIST, { + variables: { + organization_id: currentUrl, + }, + }); + + // UseEffect to update upcomingEvents array + useEffect(() => { + if (eventData && eventData?.eventsByOrganizationConnection.length > 0) { + const tempUpcomingEvents: InterfaceQueryOrganizationEventListItem[] = []; + eventData?.eventsByOrganizationConnection.map((event: any) => { + const startDate = new Date(event.startDate); + const now = new Date(); + if (startDate > now) { + tempUpcomingEvents.push(event); + } + }); + setUpcomingEvents(tempUpcomingEvents); + } + }, [eventData?.eventsByOrganizationConnection]); + + if (errorOrg || errorPost || errorEvent) { + window.location.replace('/orglist'); + } + + return ( + <> + + + + {loadingOrgData ? ( + + {[...Array(6)].map((_, index) => { + return ( + + + + ); + })} + + ) : ( + + { + history.push(peopleLink); + }} + > + } + /> + + { + history.push(peopleLink); + }} + > + } + /> + + { + history.push(postsLink); + }} + > + } + /> + + { + history.push(eventsLink); + }} + > + } + /> + + { + history.push(blockUserLink); + }} + > + } + /> + + { + history.push(requestLink); + }} + > + } + /> + + + )} + + + +
    +
    + {t('upcomingEvents')} +
    + +
    + + {loadingEvent ? ( + [...Array(4)].map((_, index) => { + return ; + }) + ) : upcomingEvents.length == 0 ? ( +
    +
    {t('noUpcomingEvents')}
    +
    + ) : ( + upcomingEvents.map( + (event: InterfaceQueryOrganizationEventListItem) => { + return ( + + ); + } + ) + )} +
    +
    + + + +
    +
    {t('latestPosts')}
    + +
    + + {loadingPost ? ( + [...Array(4)].map((_, index) => { + return ; + }) + ) : postData?.postsByOrganizationConnection.edges.length == + 0 ? ( + /* eslint-disable */ +
    +
    {t('noPostsPresent')}
    +
    + ) : ( + /* eslint-enable */ + postData?.postsByOrganizationConnection.edges + .slice(0, 5) + .map((post: any) => { + return ( + + ); + }) + )} +
    +
    + +
    + + + +
    +
    + {t('membershipRequests')} +
    + +
    + + {loadingOrgData ? ( + [...Array(4)].map((_, index) => { + return ; + }) + ) : data?.organizations[0].membershipRequests.length == 0 ? ( +
    +
    {t('noMembershipRequests')}
    +
    + ) : ( + data?.organizations[0]?.membershipRequests + .slice(0, 8) + .map((request) => { + return ( + + ); + }) + )} +
    +
    + +
    +
    + + ); +} + +export default organizationDashboard; diff --git a/src/screens/OrganizationDashboard/OrganizationDashboardMocks.ts b/src/screens/OrganizationDashboard/OrganizationDashboardMocks.ts new file mode 100644 index 0000000000..dc1f158709 --- /dev/null +++ b/src/screens/OrganizationDashboard/OrganizationDashboardMocks.ts @@ -0,0 +1,282 @@ +import { + ORGANIZATIONS_LIST, + ORGANIZATION_EVENT_CONNECTION_LIST, + ORGANIZATION_POST_CONNECTION_LIST, +} from 'GraphQl/Queries/Queries'; +import dayjs from 'dayjs'; + +export const MOCKS = [ + { + request: { + query: ORGANIZATIONS_LIST, + }, + result: { + data: { + organizations: [ + { + _id: 123, + image: '', + name: 'Dummy Organization', + description: 'This is a Dummy Organization', + location: 'New Delhi', + isPublic: true, + visibleInSearch: false, + creator: { + firstName: '', + lastName: '', + email: '', + }, + members: [ + { + _id: '123', + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@gmail.com', + }, + ], + admins: [ + { + _id: '123', + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@gmail.com', + }, + ], + membershipRequests: [ + { + _id: '456', + user: { + firstName: 'Jane', + lastName: 'Doe', + email: 'janedoe@gmail.com', + }, + }, + ], + blockedUsers: [ + { + _id: '789', + firstName: 'Steve', + lastName: 'Smith', + email: 'stevesmith@gmail.com', + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: ORGANIZATION_POST_CONNECTION_LIST, + }, + result: { + data: { + postsByOrganizationConnection: { + edges: [ + { + _id: '6411e53835d7ba2344a78e21', + title: 'Post 15', + text: 'This is the first post that was made', + imageUrl: null, + videoUrl: null, + creator: { + _id: '640d98d9eb6a743d75341067', + firstName: 'Aditya', + lastName: 'Shelke', + email: 'adidacreator1@gmail.com', + }, + createdAt: dayjs(new Date()).add(1, 'day'), + likeCount: 0, + commentCount: 0, + comments: [], + likedBy: [], + pinned: false, + }, + { + _id: '6411e54835d7ba2344a78e29', + title: 'Post 2', + text: 'Hey, anyone saw my watch that I left at the office?', + imageUrl: null, + videoUrl: null, + creator: { + _id: '640d98d9eb6a743d75341067', + firstName: 'Aditya', + lastName: 'Shelke', + email: 'adidacreator1@gmail.com', + }, + pinned: false, + createdAt: dayjs(new Date()).add(1, 'day'), + likeCount: 0, + commentCount: 2, + comments: [ + { + _id: '64eb13beca85de60ebe0ed0e', + creator: { + _id: '63d6064458fce20ee25c3bf7', + firstName: 'Noble', + lastName: 'Mittal', + email: 'test@gmail.com', + __typename: 'User', + }, + likeCount: 1, + likedBy: [ + { + _id: 1, + }, + ], + text: 'Yes, that is $50', + __typename: 'Comment', + }, + { + _id: '64eb483aca85de60ebe0ef99', + creator: { + _id: '63d6064458fce20ee25c3bf7', + firstName: 'Noble', + lastName: 'Mittal', + email: 'test@gmail.com', + __typename: 'User', + }, + likeCount: 0, + likedBy: [], + text: 'Great View', + __typename: 'Comment', + }, + ], + likedBy: [ + { + _id: '63d6064458fce20ee25c3bf7', + firstName: 'Comment', + lastName: 'Likkert', + }, + ], + }, + ], + }, + }, + }, + }, + { + request: { + query: ORGANIZATION_EVENT_CONNECTION_LIST, + variables: { + organization_id: '123', + }, + }, + result: { + data: { + eventsByOrganizationConnection: [ + { + _id: '1', + title: 'Sample Event', + description: 'Sample Description', + startDate: '2023-10-29T00:00:00.000Z', + endDate: '2023-10-29T23:59:59.000Z', + location: 'Sample Location', + startTime: '08:00:00', + endTime: '17:00:00', + allDay: false, + recurring: false, + isPublic: true, + isRegisterable: true, + }, + ], + }, + }, + }, +]; + +export const EMPTY_MOCKS = [ + { + request: { + query: ORGANIZATIONS_LIST, + }, + result: { + data: { + organizations: [ + { + _id: 123, + image: '', + name: 'Dummy Organization', + description: 'This is a Dummy Organization', + location: 'New Delhi', + isPublic: true, + visibleInSearch: false, + creator: { + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@gmail.com', + }, + members: [ + { + _id: '123', + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@gmail.com', + }, + ], + admins: [ + { + _id: '123', + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@gmail.com', + }, + ], + membershipRequests: [], + blockedUsers: [ + { + _id: '789', + firstName: 'Steve', + lastName: 'Smith', + email: 'stevesmith@gmail.com', + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: ORGANIZATION_POST_CONNECTION_LIST, + }, + result: { + data: { + postsByOrganizationConnection: { + edges: [], + }, + }, + }, + }, + { + request: { + query: ORGANIZATION_EVENT_CONNECTION_LIST, + }, + result: { + data: { + eventsByOrganizationConnection: [], + }, + }, + }, +]; + +export const ERROR_MOCKS = [ + { + request: { + query: ORGANIZATIONS_LIST, + }, + error: new Error('Mock Graphql ORGANIZATIONS_LIST Error'), + }, + { + request: { + query: ORGANIZATION_POST_CONNECTION_LIST, + }, + error: new Error('Mock Graphql ORGANIZATION_POST_LIST Error'), + }, + { + request: { + query: ORGANIZATION_EVENT_CONNECTION_LIST, + }, + error: new Error('Mock Graphql ORGANIZATION_EVENT_LIST Error'), + }, +]; diff --git a/src/screens/OrganizationEvents/OrganizationEvents.module.css b/src/screens/OrganizationEvents/OrganizationEvents.module.css new file mode 100644 index 0000000000..05a70c3fa3 --- /dev/null +++ b/src/screens/OrganizationEvents/OrganizationEvents.module.css @@ -0,0 +1,312 @@ +.navbarbg { + height: 60px; + background-color: white; + display: flex; + margin-bottom: 30px; + z-index: 1; + position: relative; + flex-direction: row; + justify-content: space-between; + box-shadow: 0px 0px 8px 2px #c8c8c8; +} + +.logo { + color: #707070; + margin-left: 0; + display: flex; + align-items: center; + text-decoration: none; +} + +.logo img { + margin-top: 0px; + margin-left: 10px; + height: 64px; + width: 70px; +} + +.logo > strong { + line-height: 1.5rem; + margin-left: -5px; + font-family: sans-serif; + font-size: 19px; + color: #707070; +} +.mainpage { + display: flex; + flex-direction: row; +} +.sidebar { + z-index: 0; + padding-top: 5px; + margin: 0; + height: 100%; +} +.sidebar:after { + content: ''; + background-color: #f7f7f7; + position: absolute; + width: 2px; + height: 600px; + top: 10px; + left: 94%; + display: block; +} +.sidebarsticky { + padding-left: 45px; +} +.sidebarsticky > p { + margin-top: -10px; +} + +.navitem { + padding-left: 27%; + padding-top: 12px; + padding-bottom: 12px; + cursor: pointer; +} + +.logintitle { + color: #707070; + font-weight: 600; + font-size: 20px; + margin-bottom: 30px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 15%; +} +.searchtitle { + color: #707070; + font-weight: 600; + font-size: 18px; + margin-bottom: 20px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 60%; +} +.logintitleadmin { + color: #707070; + font-weight: 600; + font-size: 18px; + margin-top: 50px; + margin-bottom: 40px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 30%; +} +.admindetails { + display: flex; + justify-content: space-between; +} +.admindetails > p { + margin-top: -12px; + margin-right: 30px; +} + +.mainpageright > hr { + margin-top: 20px; + width: 100%; + margin-left: -15px; + margin-right: -15px; + margin-bottom: 20px; +} +.justifysp { + display: flex; + justify-content: space-between; +} +@media screen and (max-width: 575.5px) { + .justifysp { + padding-left: 55px; + display: flex; + justify-content: space-between; + width: 100%; + } + + .mainpageright { + width: 90%; + } +} +.addbtn { + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + border-radius: 5px; + font-size: 16px; + height: 60%; + color: white; + outline: none; + font-weight: 600; + cursor: pointer; + transition: transform 0.2s, box-shadow 0.2s; +} +.flexdir { + display: flex; + flex-direction: row; + justify-content: space-between; + border: none; +} + +.form_wrapper { + margin-top: 27px; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + position: absolute; + display: flex; + flex-direction: column; + padding: 40px 30px; + background: #ffffff; + border-color: #e8e5e5; + border-width: 5px; + border-radius: 10px; + max-height: 86vh; + overflow: auto; +} + +.form_wrapper form { + display: flex; + align-items: left; + justify-content: left; + flex-direction: column; +} +.logintitleinvite { + color: #707070; + font-weight: 600; + font-size: 20px; + margin-bottom: 20px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 40%; +} +.titlemodal { + color: #707070; + font-weight: 600; + font-size: 20px; + margin-bottom: 20px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 65%; +} +.cancel > i { + margin-top: 5px; + transform: scale(1.2); + cursor: pointer; + color: #707070; +} +.modalbody { + width: 50px; +} +.greenregbtn { + margin: 1rem 0 0; + margin-top: 15px; + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + padding: 10px 10px; + border-radius: 5px; + background-color: #31bb6b; + width: 100%; + font-size: 16px; + color: white; + outline: none; + font-weight: 600; + cursor: pointer; + transition: transform 0.2s, box-shadow 0.2s; + width: 100%; +} +.sidebarsticky > input { + text-decoration: none; + margin-bottom: 50px; + border-color: #e8e5e5; + width: 80%; + border-radius: 7px; + padding-top: 5px; + padding-bottom: 5px; + padding-right: 10px; + padding-left: 10px; + box-shadow: none; +} +.datediv { + display: flex; + flex-direction: row; + margin-bottom: 15px; +} +.datebox { + width: 90%; + border-radius: 7px; + border-color: #e8e5e5; + outline: none; + box-shadow: none; + padding-top: 2px; + padding-bottom: 2px; + padding-right: 5px; + padding-left: 5px; +} +.checkboxdiv > label { + margin-right: 50px; +} +.checkboxdiv > label > input { + margin-left: 10px; +} +.loader, +.loader:after { + border-radius: 50%; + width: 10em; + height: 10em; +} +.loader { + margin: 60px auto; + margin-top: 35vh !important; + font-size: 10px; + position: relative; + text-indent: -9999em; + border-top: 1.1em solid rgba(255, 255, 255, 0.2); + border-right: 1.1em solid rgba(255, 255, 255, 0.2); + border-bottom: 1.1em solid rgba(255, 255, 255, 0.2); + border-left: 1.1em solid #febc59; + -webkit-transform: translateZ(0); + -ms-transform: translateZ(0); + transform: translateZ(0); + -webkit-animation: load8 1.1s infinite linear; + animation: load8 1.1s infinite linear; +} +@-webkit-keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} +@keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} +.dispflex { + display: flex; + align-items: center; +} +.dispflex > input { + border: none; + box-shadow: none; + margin-top: 5px; +} +.checkboxdiv { + display: flex; +} +.checkboxdiv > div { + width: 50%; +} + +@media only screen and (max-width: 600px) { + .form_wrapper { + width: 90%; + top: 45%; + } +} diff --git a/src/screens/OrganizationEvents/OrganizationEvents.test.tsx b/src/screens/OrganizationEvents/OrganizationEvents.test.tsx new file mode 100644 index 0000000000..9f79991274 --- /dev/null +++ b/src/screens/OrganizationEvents/OrganizationEvents.test.tsx @@ -0,0 +1,430 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { act, render, screen, fireEvent } from '@testing-library/react'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import 'jest-location-mock'; +import { I18nextProvider } from 'react-i18next'; + +import OrganizationEvents from './OrganizationEvents'; +import { ORGANIZATION_EVENT_CONNECTION_LIST } from 'GraphQl/Queries/Queries'; +import { store } from 'state/store'; +import { CREATE_EVENT_MUTATION } from 'GraphQl/Mutations/mutations'; +import i18nForTest from 'utils/i18nForTest'; +import userEvent from '@testing-library/user-event'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { toast } from 'react-toastify'; + +const MOCKS = [ + { + request: { + query: ORGANIZATION_EVENT_CONNECTION_LIST, + variables: { + organization_id: undefined, + title_contains: '', + description_contains: '', + location_contains: '', + }, + }, + result: { + data: { + eventsByOrganizationConnection: [ + { + _id: 1, + title: 'Event', + description: 'Event Test', + startDate: '', + endDate: '', + location: 'New Delhi', + startTime: '02:00', + endTime: '06:00', + allDay: false, + recurring: false, + isPublic: true, + isRegisterable: true, + }, + ], + }, + }, + }, + { + request: { + query: ORGANIZATION_EVENT_CONNECTION_LIST, + variables: { + title_contains: '', + description_contains: '', + organization_id: undefined, + location_contains: '', + }, + }, + result: { + data: { + eventsByOrganizationConnection: [ + { + _id: '1', + title: 'Dummy Org', + description: 'This is a dummy organization', + location: 'string', + startDate: '', + endDate: '', + startTime: '02:00', + endTime: '06:00', + allDay: false, + recurring: false, + isPublic: true, + isRegisterable: true, + }, + ], + }, + }, + }, + { + request: { + query: CREATE_EVENT_MUTATION, + variables: { + title: 'Dummy Org', + description: 'This is a dummy organization', + isPublic: false, + recurring: true, + isRegisterable: true, + organizationId: undefined, + startDate: 'Thu Mar 28 20222', + endDate: 'Fri Mar 28 20223', + allDay: true, + }, + }, + result: { + data: { + createEvent: { + _id: '1', + }, + }, + }, + }, +]; +const link = new StaticMockLink(MOCKS, true); +const link2 = new StaticMockLink([], true); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + warning: jest.fn(), + error: jest.fn(), + }, +})); + +describe('Organisation Events Page', () => { + const formData = { + title: 'Dummy Org', + description: 'This is a dummy organization', + startDate: '03/28/2022', + endDate: '04/15/2023', + location: 'New Delhi', + startTime: '02:00', + endTime: '06:00', + }; + + global.alert = jest.fn(); + + test('It is necessary to query the correct mock data.', async () => { + const dataQuery1 = MOCKS[0]?.result?.data?.eventsByOrganizationConnection; + + expect(dataQuery1).toEqual([ + { + _id: 1, + title: 'Event', + description: 'Event Test', + startDate: '', + endDate: '', + location: 'New Delhi', + startTime: '02:00', + endTime: '06:00', + allDay: false, + recurring: false, + isPublic: true, + isRegisterable: true, + }, + ]); + }); + test('It is necessary to query the correct mock data for organization.', async () => { + const dataQuery1 = MOCKS[1]?.result?.data?.eventsByOrganizationConnection; + + expect(dataQuery1).toEqual([ + { + _id: '1', + title: 'Dummy Org', + description: 'This is a dummy organization', + location: 'string', + startDate: '', + endDate: '', + startTime: '02:00', + endTime: '06:00', + allDay: false, + recurring: false, + isPublic: true, + isRegisterable: true, + }, + ]); + }); + test('It is necessary to check correct render', async () => { + window.location.assign('/orglist'); + + const { container } = render( + + + + + + + + + + ); + + expect(container.textContent).not.toBe('Loading data...'); + await wait(); + expect(container.textContent).toMatch('Events'); + expect(container.textContent).toMatch('Search Date'); + expect(container.textContent).toMatch('Events'); + expect(window.location).toBeAt('/orglist'); + }); + + test('No mock data', async () => { + render( + + + + + + + + + + ); + + await wait(); + }); + + test('Testing toggling of Create event modal', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('createEventModalBtn')); + + userEvent.click(screen.getByTestId('createEventModalCloseBtn')); + }); + + test('Testing Create event modal', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('createEventModalBtn')); + + userEvent.type(screen.getByPlaceholderText(/Enter Title/i), formData.title); + userEvent.type( + screen.getByPlaceholderText(/Enter Description/i), + formData.description + ); + userEvent.type( + screen.getByPlaceholderText(/Enter Location/i), + formData.location + ); + userEvent.type( + screen.getByPlaceholderText(/Enter Location/i), + formData.location + ); + + const endDateDatePicker = screen.getByPlaceholderText(/End Date/i); + const startDateDatePicker = screen.getByPlaceholderText(/Start Date/i); + + fireEvent.click(endDateDatePicker); + fireEvent.click(startDateDatePicker); + + await act(async () => { + fireEvent.change(endDateDatePicker, { + target: { + value: formData.endDate, + }, + }); + fireEvent.change(startDateDatePicker, { + target: { + value: formData.startDate, + }, + }); + }); + userEvent.click(screen.getByTestId('alldayCheck')); + userEvent.click(screen.getByTestId('recurringCheck')); + userEvent.click(screen.getByTestId('ispublicCheck')); + userEvent.click(screen.getByTestId('registrableCheck')); + + await wait(); + + expect(screen.getByPlaceholderText(/Enter Title/i)).toHaveValue( + formData.title + ); + expect(screen.getByPlaceholderText(/Enter Description/i)).toHaveValue( + formData.description + ); + + expect(endDateDatePicker).toHaveValue(formData.endDate); + expect(startDateDatePicker).toHaveValue(formData.startDate); + expect(screen.getByTestId('alldayCheck')).not.toBeChecked(); + expect(screen.getByTestId('recurringCheck')).toBeChecked(); + expect(screen.getByTestId('ispublicCheck')).not.toBeChecked(); + expect(screen.getByTestId('registrableCheck')).toBeChecked(); + + userEvent.click(screen.getByTestId('createEventBtn')); + }, 15000); + + test('Testing Create event with invalid inputs', async () => { + const formData = { + title: ' ', + description: ' ', + location: ' ', + startDate: '03/28/2022', + endDate: '04/15/2023', + startTime: '02:00', + endTime: '06:00', + allDay: false, + recurring: false, + isPublic: true, + isRegisterable: true, + }; + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('createEventModalBtn')); + + userEvent.type(screen.getByPlaceholderText(/Enter Title/i), formData.title); + userEvent.type( + screen.getByPlaceholderText(/Enter Description/i), + formData.description + ); + userEvent.type( + screen.getByPlaceholderText(/Enter Location/i), + formData.location + ); + userEvent.type( + screen.getByPlaceholderText(/Enter Location/i), + formData.location + ); + + const endDateDatePicker = screen.getByPlaceholderText(/End Date/i); + const startDateDatePicker = screen.getByPlaceholderText(/Start Date/i); + + fireEvent.click(endDateDatePicker); + fireEvent.click(startDateDatePicker); + + await act(async () => { + fireEvent.change(endDateDatePicker, { + target: { + value: formData.endDate, + }, + }); + fireEvent.change(startDateDatePicker, { + target: { + value: formData.startDate, + }, + }); + }); + userEvent.click(screen.getByTestId('alldayCheck')); + userEvent.click(screen.getByTestId('recurringCheck')); + userEvent.click(screen.getByTestId('ispublicCheck')); + userEvent.click(screen.getByTestId('registrableCheck')); + + await wait(); + + expect(screen.getByPlaceholderText(/Enter Title/i)).toHaveValue(' '); + expect(screen.getByPlaceholderText(/Enter Description/i)).toHaveValue(' '); + + expect(endDateDatePicker).toHaveValue(formData.endDate); + expect(startDateDatePicker).toHaveValue(formData.startDate); + expect(screen.getByTestId('alldayCheck')).not.toBeChecked(); + expect(screen.getByTestId('recurringCheck')).toBeChecked(); + expect(screen.getByTestId('ispublicCheck')).not.toBeChecked(); + expect(screen.getByTestId('registrableCheck')).toBeChecked(); + + userEvent.click(screen.getByTestId('createEventBtn')); + expect(toast.warning).toBeCalledWith('Title can not be blank!'); + expect(toast.warning).toBeCalledWith('Description can not be blank!'); + expect(toast.warning).toBeCalledWith('Location can not be blank!'); + }, 15000); + + test('Testing if the event is not for all day', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('createEventModalBtn')); + userEvent.type(screen.getByPlaceholderText(/Enter Title/i), formData.title); + userEvent.type( + screen.getByPlaceholderText(/Enter Description/i), + formData.description + ); + userEvent.type( + screen.getByPlaceholderText(/Enter Location/i), + formData.location + ); + userEvent.click(screen.getByTestId('alldayCheck')); + await wait(); + + userEvent.type( + screen.getByPlaceholderText(/Start Time/i), + formData.startTime + ); + userEvent.type(screen.getByPlaceholderText(/End Time/i), formData.endTime); + + userEvent.click(screen.getByTestId('createEventBtn')); + }); +}); diff --git a/src/screens/OrganizationEvents/OrganizationEvents.tsx b/src/screens/OrganizationEvents/OrganizationEvents.tsx new file mode 100644 index 0000000000..36852389eb --- /dev/null +++ b/src/screens/OrganizationEvents/OrganizationEvents.tsx @@ -0,0 +1,363 @@ +import type { ChangeEvent } from 'react'; +import React, { useState } from 'react'; +import Row from 'react-bootstrap/Row'; +import Col from 'react-bootstrap/Col'; +import Button from 'react-bootstrap/Button'; +import Modal from 'react-bootstrap/Modal'; +import DatePicker from 'react-datepicker'; +import { Form } from 'react-bootstrap'; +import { useMutation, useQuery } from '@apollo/client'; +import { toast } from 'react-toastify'; +import { useTranslation } from 'react-i18next'; +import EventCalendar from 'components/EventCalendar/EventCalendar'; +import Calendar from 'react-calendar'; +import './calendar.css'; + +import styles from './OrganizationEvents.module.css'; +import { + ORGANIZATION_EVENT_CONNECTION_LIST, + ORGANIZATIONS_LIST, +} from 'GraphQl/Queries/Queries'; +import { CREATE_EVENT_MUTATION } from 'GraphQl/Mutations/mutations'; +import dayjs from 'dayjs'; +import { errorHandler } from 'utils/errorHandler'; +import Loader from 'components/Loader/Loader'; +import OrganizationScreen from 'components/OrganizationScreen/OrganizationScreen'; + +function organizationEvents(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'organizationEvents', + }); + + document.title = t('title'); + const [eventmodalisOpen, setEventModalIsOpen] = useState(false); + + const [startDate, setStartDate] = React.useState(new Date()); + const [endDate, setEndDate] = React.useState(new Date()); + + const [alldaychecked, setAllDayChecked] = React.useState(true); + const [recurringchecked, setRecurringChecked] = React.useState(false); + + const [publicchecked, setPublicChecked] = React.useState(true); + const [registrablechecked, setRegistrableChecked] = React.useState(false); + + const [formState, setFormState] = useState({ + title: '', + eventdescrip: '', + date: '', + location: '', + startTime: '08:00:00', + endTime: '18:00:00', + }); + const currentUrl = window.location.href.split('=')[1]; + + const showInviteModal = (): void => { + setEventModalIsOpen(true); + }; + const hideInviteModal = (): void => { + setEventModalIsOpen(false); + }; + + const { data, loading, error, refetch } = useQuery( + ORGANIZATION_EVENT_CONNECTION_LIST, + { + variables: { + organization_id: currentUrl, + title_contains: '', + description_contains: '', + location_contains: '', + }, + } + ); + + const { data: orgData } = useQuery(ORGANIZATIONS_LIST, { + variables: { id: currentUrl }, + }); + + const userId = localStorage.getItem('id') as string; + const userRole = localStorage.getItem('UserType') as string; + + const [create, { loading: loading2 }] = useMutation(CREATE_EVENT_MUTATION); + + const createEvent = async ( + e: ChangeEvent + ): Promise => { + e.preventDefault(); + if ( + formState.title.trim().length > 0 && + formState.eventdescrip.trim().length > 0 && + formState.location.trim().length > 0 + ) { + try { + const { data: createEventData } = await create({ + variables: { + title: formState.title, + description: formState.eventdescrip, + isPublic: publicchecked, + recurring: recurringchecked, + isRegisterable: registrablechecked, + organizationId: currentUrl, + startDate: dayjs(startDate).format('YYYY-MM-DD'), + endDate: dayjs(endDate).format('YYYY-MM-DD'), + allDay: alldaychecked, + location: formState.location, + startTime: !alldaychecked ? formState.startTime + 'Z' : null, + endTime: !alldaychecked ? formState.endTime + 'Z' : null, + }, + }); + + /* istanbul ignore next */ + if (createEventData) { + toast.success(t('eventCreated')); + refetch(); + hideInviteModal(); + setFormState({ + title: '', + eventdescrip: '', + date: '', + location: '', + startTime: '08:00:00', + endTime: '18:00:00', + }); + } + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + } + if (formState.title.trim().length === 0) { + toast.warning('Title can not be blank!'); + } + if (formState.eventdescrip.trim().length === 0) { + toast.warning('Description can not be blank!'); + } + if (formState.location.trim().length === 0) { + toast.warning('Location can not be blank!'); + } + }; + + if (loading || loading2) { + return ; + } + + /* istanbul ignore next */ + if (error) { + window.location.assign('/orglist'); + } + + /* istanbul ignore next */ + + return ( + <> + + + +
    +
    +
    Search Date
    + +
    +
    + + +
    + +

    {t('events')}

    + +
    +
    + + +
    +
    + + + +

    {t('eventDetails')}

    + +
    + +
    + + { + setFormState({ + ...formState, + title: e.target.value, + }); + }} + /> + + { + setFormState({ + ...formState, + eventdescrip: e.target.value, + }); + }} + /> + + { + setFormState({ + ...formState, + location: e.target.value, + }); + }} + /> +
    +
    + + setStartDate(date)} + placeholderText={t('startDate')} + /> +
    +
    + + setEndDate(date)} + placeholderText={t('endDate')} + /> +
    +
    + {!alldaychecked && ( +
    +
    + + + setFormState({ + ...formState, + startTime: e.target.value, + }) + } + /> +
    +
    + + + setFormState({ + ...formState, + endTime: e.target.value, + }) + } + /> +
    +
    + )} +
    +
    + + setAllDayChecked(!alldaychecked)} + /> +
    +
    + + setRecurringChecked(!recurringchecked)} + /> +
    +
    +
    +
    + + setPublicChecked(!publicchecked)} + /> +
    +
    + + + setRegistrableChecked(!registrablechecked) + } + /> +
    +
    + + +
    +
    + + ); +} + +export default organizationEvents; diff --git a/src/screens/OrganizationEvents/calendar.css b/src/screens/OrganizationEvents/calendar.css new file mode 100644 index 0000000000..80d4909822 --- /dev/null +++ b/src/screens/OrganizationEvents/calendar.css @@ -0,0 +1,146 @@ +.react-calendar { + width: 250px; + max-width: 100%; + background: white; + border: 1px solid #a0a096; + font-family: Arial, Helvetica, sans-serif; + line-height: 1.125em; +} + +.react-calendar--doubleView { + width: 700px; +} + +.react-calendar--doubleView .react-calendar__viewContainer { + display: flex; + margin: -0.5em; +} + +.react-calendar--doubleView .react-calendar__viewContainer > * { + width: 50%; + margin: 0.5em; +} + +.react-calendar, +.react-calendar *, +.react-calendar *:before, +.react-calendar *:after { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +.react-calendar button { + margin: 0; + border: 0; + outline: none; +} + +.react-calendar button:enabled:hover { + cursor: pointer; +} + +.react-calendar__navigation { + display: flex; + height: 44px; + margin-bottom: 1em; +} + +.react-calendar__navigation button { + min-width: 44px; + background: none; +} + +.react-calendar__navigation button:disabled { + background-color: #f0f0f0; +} + +.react-calendar__navigation button:enabled:hover, +.react-calendar__navigation button:enabled:focus { + background-color: #e6e6e6; +} + +.react-calendar__month-view__weekdays { + text-align: center; + text-transform: uppercase; + font-weight: bold; + font-size: 0.75em; + color: #7f7f7f; +} + +.react-calendar__month-view__weekdays__weekday { + padding: 0.5em; +} + +.react-calendar__month-view__weekNumbers .react-calendar__tile { + display: flex; + align-items: center; + justify-content: center; + font-size: 0.75em; + font-weight: bold; + color: #7f7f7f; +} + +.react-calendar__month-view__days__day--weekend { + color: green !important; +} + +.react-calendar__month-view__days__day--neighboringMonth { + color: #757575; +} + +.react-calendar__year-view .react-calendar__tile, +.react-calendar__decade-view .react-calendar__tile, +.react-calendar__century-view .react-calendar__tile { + padding: 2em 0.5em; +} + +.react-calendar__tile { + max-width: 100%; + padding: 10px 6.6667px; + background: none; + text-align: center; + line-height: 16px; + color: #7f7f7f; +} + +.react-calendar__tile:disabled { + background-color: #f0f0f0; +} + +.react-calendar__tile:enabled:hover, +.react-calendar__tile:enabled:focus { + background-color: #e6e6e6; +} + +.react-calendar__tile--now { + background: #a3eaba; +} + +.react-calendar__tile--now:enabled:hover, +.react-calendar__tile--now:enabled:focus { + background: #a3eaba; +} + +.react-calendar__tile--hasActive { + background: #76baff; +} + +.react-calendar__tile--hasActive:enabled:hover, +.react-calendar__tile--hasActive:enabled:focus { + background: #a9d4ff; +} + +.react-calendar__tile--active { + background: #7f7f7f; + color: white; +} + +.react-calendar__tile--active:enabled:hover, +.react-calendar__tile--active:enabled:focus { + background: #7f7f7f; +} + +.react-calendar--selectRange .react-calendar__tile--hover { + background-color: #e6e6e6; +} diff --git a/src/screens/OrganizationPeople/OrganizationPeople.module.css b/src/screens/OrganizationPeople/OrganizationPeople.module.css new file mode 100644 index 0000000000..13972524d7 --- /dev/null +++ b/src/screens/OrganizationPeople/OrganizationPeople.module.css @@ -0,0 +1,282 @@ +.navbarbg { + height: 60px; + background-color: white; + display: flex; + margin-bottom: 30px; + z-index: 1; + position: relative; + flex-direction: row; + justify-content: space-between; + box-shadow: 0px 0px 8px 2px #c8c8c8; +} + +.logo { + color: #707070; + margin-left: 0; + display: flex; + align-items: center; + text-decoration: none; +} + +.logo img { + margin-top: 0px; + margin-left: 10px; + height: 64px; + width: 70px; +} + +.logo > strong { + line-height: 1.5rem; + margin-left: -5px; + font-family: sans-serif; + font-size: 19px; + color: #707070; +} +.mainpage { + display: flex; + flex-direction: row; +} +.sidebar { + z-index: 0; + padding-top: 10px; + margin: 0; + height: 100%; +} +.sidebar:after { + content: ''; + background-color: #f7f7f7; + position: absolute; + width: 2px; + height: 600px; + top: 10px; + left: 94%; + display: block; +} +.sidebarsticky { + padding-left: 45px; +} +.sidebarsticky > p { + margin-top: -10px; +} + +.navitem { + padding-left: 27%; + padding-top: 12px; + padding-bottom: 12px; + cursor: pointer; +} + +.logintitle { + color: #707070; + font-weight: 600; + font-size: 20px; + margin-bottom: 30px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 15%; +} +.searchtitle { + color: #707070; + font-weight: 600; + font-size: 20px; + margin-bottom: 20px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 60%; +} +.justifysp { + display: flex; + justify-content: space-between; +} +@media screen and (max-width: 575.5px) { + .justifysp { + padding-left: 55px; + display: flex; + justify-content: space-between; + width: 100%; + } +} + +.logintitleadmin { + color: #707070; + font-weight: 600; + font-size: 18px; + margin-top: 50px; + margin-bottom: 40px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 40%; +} +.admindetails { + display: flex; + justify-content: space-between; +} +.admindetails > p { + margin-top: -12px; + margin-right: 30px; +} +.mainpageright > hr { + margin-top: 20px; + width: 97%; + margin-left: -15px; + margin-right: -15px; + margin-bottom: 20px; +} +.addbtnmain { + width: 60%; + margin-right: 50px; +} +.addbtn { + float: right; + width: 23%; + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + border-radius: 5px; + background-color: #31bb6b; + height: 40px; + font-size: 16px; + color: white; + outline: none; + font-weight: 600; + cursor: pointer; + margin-left: 30px; + transition: transform 0.2s, box-shadow 0.2s; +} +.flexdir { + display: flex; + flex-direction: row; + justify-content: space-between; + border: none; +} + +.form_wrapper { + margin-top: 27px; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + position: absolute; + display: flex; + flex-direction: column; + padding: 40px 30px; + background: #ffffff; + border-color: #e8e5e5; + border-width: 5px; + border-radius: 10px; +} + +.form_wrapper form { + display: flex; + align-items: left; + justify-content: left; + flex-direction: column; +} +.logintitleinvite { + color: #707070; + font-weight: 600; + font-size: 20px; + margin-bottom: 20px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 40%; +} +.cancel > i { + margin-top: 5px; + transform: scale(1.2); + cursor: pointer; + color: #707070; +} +.modalbody { + width: 50px; +} +.greenregbtn { + margin: 1rem 0 0; + margin-top: 10px; + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + padding: 10px 10px; + border-radius: 5px; + background-color: #31bb6b; + width: 100%; + font-size: 16px; + color: white; + outline: none; + font-weight: 600; + cursor: pointer; + transition: transform 0.2s, box-shadow 0.2s; + width: 100%; +} +.sidebarsticky > input { + text-decoration: none; + margin-bottom: 50px; + border-color: #e8e5e5; + width: 80%; + border-radius: 7px; + padding-top: 5px; + padding-bottom: 5px; + padding-right: 10px; + padding-left: 10px; + box-shadow: none; +} + +.loader, +.loader:after { + border-radius: 50%; + width: 10em; + height: 10em; +} +.loader { + margin: 60px auto; + margin-top: 35vh !important; + font-size: 10px; + position: relative; + text-indent: -9999em; + border-top: 1.1em solid rgba(255, 255, 255, 0.2); + border-right: 1.1em solid rgba(255, 255, 255, 0.2); + border-bottom: 1.1em solid rgba(255, 255, 255, 0.2); + border-left: 1.1em solid #febc59; + -webkit-transform: translateZ(0); + -ms-transform: translateZ(0); + transform: translateZ(0); + -webkit-animation: load8 1.1s infinite linear; + animation: load8 1.1s infinite linear; +} +.radio_buttons { + color: #707070; + font-weight: 600; + font-size: 14px; +} +.radio_buttons > input { + transform: scale(1.2); +} +.radio_buttons > label { + margin-top: -4px; + margin-left: 5px; + margin-right: 15px; +} + +@-webkit-keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} +@keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} +.list_box { + height: 70vh; + overflow-y: auto; + width: auto; + padding-right: 50px; +} diff --git a/src/screens/OrganizationPeople/OrganizationPeople.test.tsx b/src/screens/OrganizationPeople/OrganizationPeople.test.tsx new file mode 100644 index 0000000000..605c01f785 --- /dev/null +++ b/src/screens/OrganizationPeople/OrganizationPeople.test.tsx @@ -0,0 +1,1033 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { act, render, screen } from '@testing-library/react'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; +import OrganizationPeople from './OrganizationPeople'; +import { store } from 'state/store'; +import { + ORGANIZATIONS_LIST, + ORGANIZATIONS_MEMBER_CONNECTION_LIST, + USER_LIST, +} from 'GraphQl/Queries/Queries'; +import 'jest-location-mock'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; + +// This loop creates dummy data for members, admin and users +const members: any[] = []; +const admins: any[] = []; +const users: any[] = []; + +for (let i = 0; i < 100; i++) { + members.push({ + __typename: 'User', + _id: i + '1', + firstName: 'firstName', + lastName: 'lastName', + image: null, + email: 'email', + createdAt: new Date().toISOString(), + }); + + admins.push({ + __typename: 'User', + _id: i + '1', + firstName: 'firstName', + lastName: 'lastName', + image: null, + email: 'email', + createdAt: new Date().toISOString(), + }); + + users.push({ + __typename: 'User', + firstName: 'firstName', + lastName: 'lastName', + image: null, + _id: i + 'id', + email: 'email', + userType: ['SUPERADMIN', 'USER'][i < 50 ? 0 : 1], + adminApproved: true, + organizationsBlockedBy: [], + createdAt: new Date().toISOString(), + joinedOrganizations: [ + { + __typename: 'Organization', + _id: `6411a8f197d5631eb0765857${i}`, + }, + ], + }); +} + +const createMemberMock = ( + orgId = '', + firstNameContains = '', + lastNameContains = '' +): any => ({ + request: { + query: ORGANIZATIONS_MEMBER_CONNECTION_LIST, + variables: { + orgId: orgId, + firstNameContains, + lastNameContains, + }, + }, + result: { + data: { + organizationsMemberConnection: { + __typename: 'UserConnection', + edges: [ + { + __typename: 'User', + _id: '64001660a711c62d5b4076a2', + firstName: 'Aditya', + lastName: 'Memberguy', + image: null, + email: 'member@gmail.com', + createdAt: '2023-03-02T03:22:08.101Z', + }, + ], + }, + }, + }, + newData: () => ({ + data: { + organizationsMemberConnection: { + __typename: 'UserConnection', + edges: [ + { + __typename: 'User', + _id: '64001660a711c62d5b4076a2', + firstName: 'Aditya', + lastName: 'Memberguy', + image: null, + email: 'member@gmail.com', + createdAt: '2023-03-02T03:22:08.101Z', + }, + ], + }, + }, + }), +}); + +const createAdminMock = ( + orgId = '', + firstNameContains = '', + lastNameContains = '', + adminFor = '' +): any => ({ + request: { + query: ORGANIZATIONS_MEMBER_CONNECTION_LIST, + variables: { + orgId, + firstNameContains, + lastNameContains, + adminFor, + }, + }, + result: { + data: { + organizationsMemberConnection: { + __typename: 'UserConnection', + edges: [ + { + __typename: 'User', + _id: '64001660a711c62d5b4076a2', + firstName: 'Aditya', + lastName: 'Adminguy', + image: null, + email: 'admin@gmail.com', + createdAt: '2023-03-02T03:22:08.101Z', + }, + ...admins, + ], + }, + }, + }, + newData: () => ({ + data: { + organizationsMemberConnection: { + __typename: 'UserConnection', + edges: [ + { + __typename: 'User', + _id: '64001660a711c62d5b4076a2', + firstName: 'Aditya', + lastName: 'Adminguy', + image: null, + email: 'admin@gmail.com', + createdAt: '2023-03-02T03:22:08.101Z', + lol: true, + }, + ], + }, + }, + }), +}); + +const createUserMock = ( + firstNameContains = '', + lastNameContains = '' +): any => ({ + request: { + query: USER_LIST, + variables: { + firstNameContains, + lastNameContains, + }, + }, + result: { + data: { + users: [ + { + __typename: 'User', + firstName: 'Aditya', + lastName: 'Userguy', + image: null, + _id: '64001660a711c62d5b4076a2', + email: 'adidacreator1@gmail.com', + userType: 'SUPERADMIN', + adminApproved: true, + organizationsBlockedBy: [], + createdAt: '2023-03-02T03:22:08.101Z', + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af1', + }, + ], + }, + { + __typename: 'User', + firstName: 'Aditya', + lastName: 'Userguytwo', + image: null, + _id: '6402030dce8e8406b8f07b0e', + email: 'adi1@gmail.com', + userType: 'USER', + adminApproved: true, + organizationsBlockedBy: [], + createdAt: '2023-03-03T14:24:13.084Z', + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + }, + ], + }, + ], + }, + }, +}); + +const MOCKS: any[] = [ + { + request: { + query: ORGANIZATIONS_LIST, + variables: { + id: 'orgid', + }, + }, + result: { + data: { + organizations: [ + { + _id: 'orgid', + image: '', + creator: { + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + name: 'name', + description: 'description', + location: 'location', + members: { + _id: 'id', + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + admins: { + _id: 'id', + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + membershipRequests: { + _id: 'id', + user: { + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + }, + blockedUsers: { + _id: 'id', + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + }, + ], + }, + }, + }, + + { + //These are mocks for 1st query (member list) + request: { + query: ORGANIZATIONS_MEMBER_CONNECTION_LIST, + variables: { + orgId: 'orgid', + firstName_contains: '', + lastName_contains: '', + }, + }, + result: { + data: { + organizationsMemberConnection: { + __typename: 'UserConnection', + edges: [ + { + __typename: 'User', + _id: '64001660a711c62d5b4076a2', + firstName: 'Aditya', + lastName: 'Memberguy', + image: null, + email: 'member@gmail.com', + createdAt: '2023-03-02T03:22:08.101Z', + }, + ...members, + ], + }, + }, + }, + newData: () => ({ + //A function if multiple request are sent + data: { + organizationsMemberConnection: { + __typename: 'UserConnection', + edges: [ + { + __typename: 'User', + _id: '64001660a711c62d5b4076a2', + firstName: 'Aditya', + lastName: 'Memberguy', + image: null, + email: 'member@gmail.com', + createdAt: '2023-03-02T03:22:08.101Z', + }, + ...members, + ], + }, + }, + }), + }, + + { + request: { + query: ORGANIZATIONS_MEMBER_CONNECTION_LIST, + variables: { + orgId: 'orgid', + firstName_contains: '', + lastName_contains: '', + admin_for: 'orgid', + }, + }, + result: { + data: { + organizationsMemberConnection: { + __typename: 'UserConnection', + edges: [ + { + __typename: 'User', + _id: '64001660a711c62d5b4076a2', + firstName: 'Aditya', + lastName: 'Adminguy', + image: null, + email: 'admin@gmail.com', + createdAt: '2023-03-02T03:22:08.101Z', + }, + ...admins, + ], + }, + }, + }, + newData: () => ({ + data: { + organizationsMemberConnection: { + __typename: 'UserConnection', + edges: [ + { + __typename: 'User', + _id: '64001660a711c62d5b4076a2', + firstName: 'Aditya', + lastName: 'Adminguy', + image: null, + email: 'admin@gmail.com', + createdAt: '2023-03-02T03:22:08.101Z', + lol: true, + }, + ...admins, + ], + }, + }, + }), + }, + + { + //This is mock for user list + request: { + query: USER_LIST, + variables: { + firstName_contains: '', + lastName_contains: '', + }, + }, + result: { + data: { + users: [ + { + __typename: 'User', + firstName: 'Aditya', + lastName: 'Userguy', + image: null, + _id: '64001660a711c62d5b4076a2', + email: 'adidacreator1@gmail.com', + userType: 'SUPERADMIN', + adminApproved: true, + organizationsBlockedBy: [], + createdAt: '2023-03-02T03:22:08.101Z', + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af1', + }, + ], + }, + { + __typename: 'User', + firstName: 'Aditya', + lastName: 'Userguytwo', + image: null, + _id: '6402030dce8e8406b8f07b0e', + email: 'adi1@gmail.com', + userType: 'USER', + adminApproved: true, + organizationsBlockedBy: [], + createdAt: '2023-03-03T14:24:13.084Z', + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + }, + ], + }, + ...users, + ], + }, + }, + }, + + createMemberMock('orgid', 'Aditya', ''), + createMemberMock('orgid', '', 'Memberguy'), + createMemberMock('orgid', 'Aditya', 'Memberguy'), + + createAdminMock('orgid', 'Aditya', '', 'orgid'), + createAdminMock('orgid', '', 'Adminguy', 'orgid'), + createAdminMock('orgid', 'Aditya', 'Adminguy', 'orgid'), + + createUserMock('Aditya', ''), + createUserMock('', 'Userguytwo'), + createUserMock('Aditya', 'Userguytwo'), +]; + +const link = new StaticMockLink(MOCKS, true); +async function wait(ms = 2): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +// TODO - REMOVE THE NEXT LINE IT IS TO SUPPRESS THE ERROR +// FOR THE FIRST TEST WHICH CAME OUT OF NOWHERE +console.error = jest.fn(); + +describe('Organization People Page', () => { + const searchData = { + firstName: 'Aditya', + lastNameMember: 'Memberguy', + lastNameAdmin: 'Adminguy', + lastNameUser: 'Userguytwo', + location: 'Delhi, India', + event: 'Event', + }; + + test('The number of organizations people rendered on the DOM should be equal to the rowsPerPage state value', async () => { + window.location.assign('orgpeople/id=6401ff65ce8e8406b8f07af1'); + + render( + + + + + + + + + + ); + + await wait(); + + await screen.findByTestId('rowsPPSelect'); + + // Get the reference to all userTypes through the radio buttons in the DOM + // => users, members, admins + const allPeopleTypes = Array.from( + screen.getByTestId('usertypelist').querySelectorAll('input[type="radio"]') + ).map((radioButton: HTMLInputElement | any) => radioButton.dataset?.testid); + + // This variable represents the array index of currently selected UserType(i.e "member" or "admin" or "user") + let peopleTypeIndex = 0; + + const changeRowsPerPage = async (currRowPPindex: number): Promise => { + // currRowPPindex is the index of the currently selected option of rows per page dropdown + + await screen.findByTestId('rowsPPSelect'); + + //Get the reference to the dropdown for rows per page + const rowsPerPageSelect: HTMLSelectElement | null = + screen.getByTestId('rowsPPSelect').querySelector('select') || null; + + if (rowsPerPageSelect === null) { + throw new Error('rowsPerPageSelect is null'); + } + + // Get all possible dropdown options + // => -1, 5, 10, 30 + const rowsPerPageOptions: any[] = Array.from( + rowsPerPageSelect?.querySelectorAll('option') + ); + + // Change the selected option of dropdown to the value of the current option + userEvent.selectOptions( + rowsPerPageSelect, + rowsPerPageOptions[currRowPPindex].textContent + ); + + const expectedUsersLength = MOCKS[3]?.result?.data?.users?.filter( + (datas: { + _id: string; + lastName: string; + firstName: string; + image: string; + email: string; + createdAt: string; + joinedOrganizations: { + __typename: string; + _id: string; + }[]; + }) => { + window.location.assign('/orgpeople/id=6401ff65ce8e8406b8f07af1'); + const pathname = window.location.pathname; + const id = pathname.split('=')[1]; + return datas.joinedOrganizations.some((org) => org._id === id); + } + ).length; + + await wait(); + const totalNumPeople = screen.getAllByTestId('orgpeoplelist').length; + expect(totalNumPeople).toBe(expectedUsersLength); + + if (rowsPerPageOptions[currRowPPindex].textContent === 'All') { + peopleTypeIndex += 1; + + await changePeopleType(); + + return; + } + + if (currRowPPindex < rowsPerPageOptions.length) { + currRowPPindex += 1; + await changeRowsPerPage(currRowPPindex); + } + }; + + const changePeopleType = async (): Promise => { + if (peopleTypeIndex === allPeopleTypes.length - 1) return; + + const peopleTypeButton = screen + .getByTestId('usertypelist') + .querySelector(`input[data-testid=${allPeopleTypes[peopleTypeIndex]}]`); + + if (peopleTypeButton === null) { + throw new Error('peopleTypeButton is null'); + } + + // Change people type + userEvent.click(peopleTypeButton); + + await changeRowsPerPage(1); + }; + + await changePeopleType(); + }, 15000); + + test('Correct mock data should be queried', async () => { + window.location.assign('/orgpeople/id=orgid'); + + const dataQuery1 = + MOCKS[1]?.result?.data?.organizationsMemberConnection?.edges; + const dataQuery2 = + MOCKS[2]?.result?.data?.organizationsMemberConnection?.edges; + + const dataQuery3 = MOCKS[3]?.result?.data?.users; + + expect(dataQuery1).toEqual([ + { + __typename: 'User', + _id: '64001660a711c62d5b4076a2', + firstName: 'Aditya', + lastName: 'Memberguy', + image: null, + email: 'member@gmail.com', + createdAt: '2023-03-02T03:22:08.101Z', + }, + ...members, + ]); + + expect(dataQuery2).toEqual([ + { + __typename: 'User', + _id: '64001660a711c62d5b4076a2', + firstName: 'Aditya', + lastName: 'Adminguy', + image: null, + email: 'admin@gmail.com', + createdAt: '2023-03-02T03:22:08.101Z', + }, + ...admins, + ]); + + expect(dataQuery3).toEqual([ + { + __typename: 'User', + firstName: 'Aditya', + lastName: 'Userguy', + image: null, + _id: '64001660a711c62d5b4076a2', + email: 'adidacreator1@gmail.com', + userType: 'SUPERADMIN', + adminApproved: true, + organizationsBlockedBy: [], + createdAt: '2023-03-02T03:22:08.101Z', + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af1', + }, + ], + }, + { + __typename: 'User', + firstName: 'Aditya', + lastName: 'Userguytwo', + image: null, + _id: '6402030dce8e8406b8f07b0e', + email: 'adi1@gmail.com', + userType: 'USER', + adminApproved: true, + organizationsBlockedBy: [], + createdAt: '2023-03-03T14:24:13.084Z', + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + }, + ], + }, + ...users, + ]); + + expect(window.location).toBeAt('/orgpeople/id=orgid'); + }); + + test('It is necessary to query the correct mock data.', async () => { + window.location.assign('/orgpeople/id=orgid'); + + const { container } = render( + + + + + + + + + + ); + + expect(container.textContent).not.toBe('Loading data...'); + + await wait(); + + expect(container.textContent).toMatch('Members'); + expect(container.textContent).toMatch('Filter by Name'); + + expect(window.location).toBeAt('/orgpeople/id=orgid'); + }); + + test('Testing MEMBERS list', async () => { + window.location.assign('/orgpeople/id=orgid'); + render( + + + + + + + + + + ); + await wait(); + + userEvent.click(screen.getByLabelText(/Members/i)); + await wait(); + expect(screen.getByLabelText(/Members/i)).toBeChecked(); + await wait(); + + const findtext = screen.getByText(/Aditya Memberguy/i); + await wait(); + expect(findtext).toBeInTheDocument(); + + userEvent.type( + screen.getByPlaceholderText(/Enter First Name/i), + searchData.firstName + ); + await wait(); + expect(screen.getByPlaceholderText(/Enter First Name/i)).toHaveValue( + searchData.firstName + ); + + await wait(); + expect(window.location).toBeAt('/orgpeople/id=orgid'); + }); + + test('Testing MEMBERS list with filters', async () => { + window.location.assign('/orgpeople/id=orgid'); + render( + + + + + + + + + + ); + await wait(); + + userEvent.click(screen.getByLabelText(/Members/i)); + await wait(); + expect(screen.getByLabelText(/Members/i)).toBeChecked(); + await wait(); + + const firstNameInput = screen.getByPlaceholderText(/Enter First Name/i); + const lastNameInput = screen.getByPlaceholderText(/Enter Last Name/i); + + // Only First Name + userEvent.type(firstNameInput, searchData.firstName); + await wait(); + + let findtext = screen.getByText(/Aditya Memberguy/i); + await wait(); + expect(findtext).toBeInTheDocument(); + + // First & Last Name + userEvent.type(lastNameInput, searchData.lastNameMember); + await wait(); + + findtext = screen.getByText(/Aditya Memberguy/i); + await wait(); + expect(findtext).toBeInTheDocument(); + + // Only Last Name + userEvent.type(firstNameInput, ''); + await wait(); + + findtext = screen.getByText(/Aditya Memberguy/i); + await wait(); + expect(findtext).toBeInTheDocument(); + + await wait(); + expect(window.location).toBeAt('/orgpeople/id=orgid'); + }); + + test('Testing ADMIN LIST', async () => { + window.location.assign('/orgpeople/id=orgid'); + + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByLabelText(/Admins/i)); + await wait(); + expect(screen.getByLabelText(/Admins/i)).toBeChecked(); + await wait(); + + const findtext = screen.getByText('Aditya Adminguy'); + expect(findtext).toBeInTheDocument(); + + userEvent.type( + screen.getByPlaceholderText(/Enter First Name/i), + searchData.firstName + ); + await wait(); + expect(screen.getByPlaceholderText(/Enter First Name/i)).toHaveValue( + searchData.firstName + ); + await wait(); + + await wait(); + expect(window.location).toBeAt('/orgpeople/id=orgid'); + }); + + test('Testing ADMIN list with filters', async () => { + window.location.assign('/orgpeople/id=orgid'); + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByLabelText(/Admins/i)); + await wait(); + expect(screen.getByLabelText(/Admins/i)).toBeChecked(); + await wait(); + + const firstNameInput = screen.getByPlaceholderText(/Enter First Name/i); + const lastNameInput = screen.getByPlaceholderText(/Enter Last Name/i); + + // Only First Name + userEvent.type(firstNameInput, searchData.firstName); + await wait(); + + let findtext = screen.getByText(/Aditya Adminguy/i); + await wait(); + expect(findtext).toBeInTheDocument(); + + // First & Last Name + userEvent.type(lastNameInput, searchData.lastNameAdmin); + await wait(); + + findtext = screen.getByText(/Aditya Adminguy/i); + await wait(); + expect(findtext).toBeInTheDocument(); + + // Only Last Name + userEvent.type(firstNameInput, ''); + await wait(); + + findtext = screen.getByText(/Aditya Adminguy/i); + await wait(); + expect(findtext).toBeInTheDocument(); + + await wait(); + expect(window.location).toBeAt('/orgpeople/id=orgid'); + }); + + test('Testing USERS list', async () => { + const dataQueryForUsers = MOCKS[3]?.result?.data?.users; + window.location.assign('/orgpeople/id=6401ff65ce8e8406b8f07af1'); + + render( + + + + + + + + + + ); + await wait(); + userEvent.click(screen.getByLabelText(/Users/i)); + await wait(); + expect(screen.getByLabelText(/Users/i)).toBeChecked(); + await wait(); + const orgUsers = dataQueryForUsers?.filter( + (datas: { + _id: string; + lastName: string; + firstName: string; + image: string; + email: string; + createdAt: string; + joinedOrganizations: { + __typename: string; + _id: string; + }[]; + }) => { + window.location.assign('/orgpeople/id=6401ff65ce8e8406b8f07af1'); + const pathname = window.location.pathname; + const id = pathname.split('=')[1]; + return datas.joinedOrganizations?.some((org) => org._id === id); + } + ); + await wait(); + expect(orgUsers?.length).toBe(1); + + await wait(); + expect(window.location).toBeAt('/orgpeople/id=6401ff65ce8e8406b8f07af1'); + }); + + test('Testing USERS list with filters', async () => { + window.location.assign('/orgpeople/id=6401ff65ce8e8406b8f07af2'); + const dataQueryForUsers = MOCKS[3]?.result?.data?.users; + + render( + + + + + + + + + + ); + await wait(); + userEvent.click(screen.getByLabelText(/Users/i)); + await wait(); + expect(screen.getByLabelText(/Users/i)).toBeChecked(); + await wait(); + + const firstNameInput = screen.getByPlaceholderText(/Enter First Name/i); + + // Only First Name + userEvent.type(firstNameInput, searchData.firstName); + await wait(); + + const orgUsers = dataQueryForUsers?.filter( + (datas: { + _id: string; + lastName: string; + firstName: string; + image: string; + email: string; + createdAt: string; + joinedOrganizations: { + __typename: string; + _id: string; + }[]; + }) => { + window.location.assign('/orgpeople/id=6401ff65ce8e8406b8f07af2'); + const pathname = window.location.pathname; + const id = pathname.split('=')[1]; + return datas.joinedOrganizations?.some((org) => org._id === id); + } + ); + await wait(); + expect(orgUsers?.length).toBe(1); + + await wait(); + expect(window.location).toBeAt('/orgpeople/id=6401ff65ce8e8406b8f07af2'); + }); + + test('No Mock Data test', async () => { + window.location.assign('/orgpeople/id=orgid'); + + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByLabelText(/Admins/i)); + + await wait(); + + userEvent.click(screen.getByLabelText(/Users/i)); + + await wait(); + expect(window.location).toBeAt('/orgpeople/id=orgid'); + }); +}); diff --git a/src/screens/OrganizationPeople/OrganizationPeople.tsx b/src/screens/OrganizationPeople/OrganizationPeople.tsx new file mode 100644 index 0000000000..9d33ae2833 --- /dev/null +++ b/src/screens/OrganizationPeople/OrganizationPeople.tsx @@ -0,0 +1,419 @@ +import { useLazyQuery } from '@apollo/client'; +import dayjs from 'dayjs'; +import React, { useEffect, useState } from 'react'; +import { Container, Form } from 'react-bootstrap'; +import Col from 'react-bootstrap/Col'; +import Row from 'react-bootstrap/Row'; + +import { + ORGANIZATIONS_MEMBER_CONNECTION_LIST, + USER_LIST, +} from 'GraphQl/Queries/Queries'; +import NotFound from 'components/NotFound/NotFound'; +import OrgAdminListCard from 'components/OrgAdminListCard/OrgAdminListCard'; +import OrgPeopleListCard from 'components/OrgPeopleListCard/OrgPeopleListCard'; +import OrganizationScreen from 'components/OrganizationScreen/OrganizationScreen'; +import PaginationList from 'components/PaginationList/PaginationList'; +import UserListCard from 'components/UserListCard/UserListCard'; +import { useTranslation } from 'react-i18next'; +import debounce from 'utils/debounce'; +import styles from './OrganizationPeople.module.css'; + +import { toast } from 'react-toastify'; + +function organizationPeople(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'organizationPeople', + }); + + document.title = t('title'); + + const currentUrl = window.location.href.split('=')[1]; + + const [state, setState] = useState(0); + const [page, setPage] = useState(0); + const [rowsPerPage, setRowsPerPage] = useState(5); + + const [filterData, setFilterData] = useState({ + firstName_contains: '', + lastName_contains: '', + }); + + const { + data: memberData, + loading: memberLoading, + error: memberError, + refetch: memberRefetch, + } = useLazyQuery(ORGANIZATIONS_MEMBER_CONNECTION_LIST, { + variables: { + firstName_contains: '', + lastName_contains: '', + orgId: currentUrl, + }, + })[1]; + + const { + data: adminData, + loading: adminLoading, + error: adminError, + refetch: adminRefetch, + } = useLazyQuery(ORGANIZATIONS_MEMBER_CONNECTION_LIST, { + variables: { + firstName_contains: '', + lastName_contains: '', + orgId: currentUrl, + admin_for: currentUrl, + }, + })[1]; + + const { + data: usersData, + loading: usersLoading, + error: usersError, + refetch: usersRefetch, + } = useLazyQuery(USER_LIST, { + variables: { + firstName_contains: '', + lastName_contains: '', + }, + })[1]; + + useEffect(() => { + if (state === 0) { + memberRefetch({ + ...filterData, + orgId: currentUrl, + }); + } else if (state === 1) { + adminRefetch({ + ...filterData, + orgId: currentUrl, + admin_for: currentUrl, + }); + } else { + usersRefetch({ + ...filterData, + }); + } + }, [state]); + + /* istanbul ignore next */ + if (memberError || usersError || adminError) { + const error = memberError ?? usersError ?? adminError; + toast.error(error?.message); + } + + /* istanbul ignore next */ + const handleFirstNameSearchChange = (filterData: any): void => { + /* istanbul ignore next */ + if (state === 0) { + memberRefetch({ + ...filterData, + orgId: currentUrl, + }); + } else if (state === 1) { + adminRefetch({ + ...filterData, + orgId: currentUrl, + admin_for: currentUrl, + }); + } else { + usersRefetch({ + ...filterData, + }); + } + }; + + /* istanbul ignore next */ + const handleChangePage = ( + event: React.MouseEvent | null, + newPage: number + ): void => { + setPage(newPage); + }; + + /* istanbul ignore next */ + const handleChangeRowsPerPage = ( + event: React.ChangeEvent + ): void => { + setRowsPerPage(parseInt(event.target.value, 10)); + setPage(0); + }; + + const debouncedHandleFirstNameSearchChange = debounce( + handleFirstNameSearchChange + ); + + return ( + <> + + + +
    +
    +
    {t('filterByName')}
    + { + const { value } = e.target; + + const newFilterData = { + ...filterData, + firstName_contains: value?.trim(), + }; + + setFilterData(newFilterData); + debouncedHandleFirstNameSearchChange(newFilterData); + }} + /> + { + const { value } = e.target; + + const newFilterData = { + ...filterData, + lastName_contains: value?.trim(), + }; + + setFilterData(newFilterData); + debouncedHandleFirstNameSearchChange(newFilterData); + }} + /> +
    + { + setState(2); + }} + /> + + { + setState(0); + }} + /> + + { + setState(1); + }} + /> + +
    +
    +
    + + + +
    + +

    + {state == 0 + ? t('members') + : state == 1 + ? t('admins') + : t('users')} +

    +
    + {memberLoading || usersLoading || adminLoading ? ( + <> +
    + + ) : ( +
    + { + /* istanbul ignore next */ + state == 0 ? ( + memberData && + memberData.organizationsMemberConnection.edges.length > + 0 ? ( + (rowsPerPage > 0 + ? memberData.organizationsMemberConnection.edges.slice( + page * rowsPerPage, + page * rowsPerPage + rowsPerPage + ) + : memberData.organizationsMemberConnection.edges + ).map( + (datas: { + _id: string; + lastName: string; + firstName: string; + image: string; + email: string; + createdAt: string; + }) => { + return ( + + ); + } + ) + ) : ( + + ) + ) : state == 1 ? ( + adminData && + adminData.organizationsMemberConnection.edges.length > + 0 ? ( + (rowsPerPage > 0 + ? adminData.organizationsMemberConnection.edges.slice( + page * rowsPerPage, + page * rowsPerPage + rowsPerPage + ) + : adminData.organizationsMemberConnection.edges + ).map( + (datas: { + _id: string; + lastName: string; + firstName: string; + image: string; + email: string; + createdAt: string; + }) => { + return ( + + ); + } + ) + ) : ( + + ) + ) : state == 2 ? ( + usersData && usersData.users.length > 0 ? ( + (rowsPerPage > 0 + ? usersData.users.slice( + page * rowsPerPage, + page * rowsPerPage + rowsPerPage + ) + : usersData.users + ).map( + (datas: { + _id: string; + lastName: string; + firstName: string; + image: string; + email: string; + createdAt: string; + }) => { + return ( + + ); + } + ) + ) : ( + + ) + ) : ( + /* istanbul ignore next */ + + ) + } +
    + )} +
    +
    + + + + <> + + + + +
    +
    +
    + +
    +
    + + ); +} + +export default organizationPeople; diff --git a/src/screens/PageNotFound/PageNotFound.module.css b/src/screens/PageNotFound/PageNotFound.module.css new file mode 100644 index 0000000000..3c1b9a3413 --- /dev/null +++ b/src/screens/PageNotFound/PageNotFound.module.css @@ -0,0 +1,109 @@ +.notfound { + position: relative; + bottom: 20px; +} + +.notfound h3 { + font-family: 'Roboto', sans-serif; + font-weight: normal; + letter-spacing: 1px; +} + +.notfound .brand span { + margin-top: 50px; + font-size: 40px; +} +.notfound .brand h3 { + font-weight: 300; + margin: 10px 0 0 0; +} +.notfound h1.head { + font-size: 250px; + font-weight: 900; + color: #31bb6b; + letter-spacing: 25px; + margin: 10px 0 0 0; +} +.notfound h1.head span { + position: relative; + display: inline-block; +} +.notfound h1.head span:before, +.notfound h1.head span:after { + position: absolute; + top: 50%; + width: 50%; + height: 1px; + background: #fff; + content: ''; +} +.notfound h1.head span:before { + left: -55%; +} +.notfound h1.head span:after { + right: -55%; +} + +@media (max-width: 1024px) { + .notfound h1.head { + font-size: 200px; + letter-spacing: 25px; + } +} + +@media (max-width: 768px) { + .notfound h1.head { + font-size: 150px; + letter-spacing: 25px; + } +} + +@media (max-width: 640px) { + .notfound h1.head { + font-size: 150px; + letter-spacing: 0; + } +} + +@media (max-width: 480px) { + .notfound .brand h3 { + font-size: 20px; + } + .notfound h1.head { + font-size: 130px; + letter-spacing: 0; + } + .notfound h1.head span:before, + .notfound h1.head span:after { + width: 40%; + } + .notfound h1.head span:before { + left: -45%; + } + .notfound h1.head span:after { + right: -45%; + } + .notfound p { + font-size: 18px; + } +} + +@media (max-width: 320px) { + .notfound .brand h3 { + font-size: 16px; + } + .notfound h1.head { + font-size: 100px; + letter-spacing: 0; + } + .notfound h1.head span:before, + .notfound h1.head span:after { + width: 25%; + } + .notfound h1.head span:before { + left: -30%; + } + .notfound h1.head span:after { + right: -30%; + } +} diff --git a/src/screens/PageNotFound/PageNotFound.test.tsx b/src/screens/PageNotFound/PageNotFound.test.tsx new file mode 100644 index 0000000000..f02b5ccfd0 --- /dev/null +++ b/src/screens/PageNotFound/PageNotFound.test.tsx @@ -0,0 +1,30 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { I18nextProvider } from 'react-i18next'; + +import { store } from 'state/store'; +import PageNotFound from './PageNotFound'; +import i18nForTest from 'utils/i18nForTest'; + +describe('Testing Page not found component', () => { + test('Component should be rendered properly', () => { + render( + + + + + + + + ); + + expect(screen.getByText(/Talawa Admin/i)).toBeTruthy(); + expect(screen.getByText(/404/i)).toBeTruthy(); + expect( + screen.getByText(/Oops! The Page you requested was not found!/i) + ).toBeTruthy(); + expect(screen.getByText(/Back to Home/i)).toBeTruthy(); + }); +}); diff --git a/src/screens/PageNotFound/PageNotFound.tsx b/src/screens/PageNotFound/PageNotFound.tsx new file mode 100644 index 0000000000..ddc56cdcac --- /dev/null +++ b/src/screens/PageNotFound/PageNotFound.tsx @@ -0,0 +1,34 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; + +import styles from './PageNotFound.module.css'; +import Logo from 'assets/images/talawa-logo-200x200.png'; + +const PageNotFound = (): JSX.Element => { + const { t } = useTranslation('translation', { + keyPrefix: 'pageNotFound', + }); + + document.title = t('title'); + + return ( +
    +
    +
    + Logo +

    {t('talawaAdmin')}

    +
    +

    + {t('404')} +

    +

    {t('notFoundMsg')}

    + + {t('backToHome')} + +
    +
    + ); +}; + +export default PageNotFound; diff --git a/src/screens/Requests/Requests.module.css b/src/screens/Requests/Requests.module.css new file mode 100644 index 0000000000..0750dba108 --- /dev/null +++ b/src/screens/Requests/Requests.module.css @@ -0,0 +1,95 @@ +.btnsContainer { + display: flex; + margin: 2.5rem 0 2.5rem 0; +} + +.btnsContainer .btnsBlock { + display: flex; +} + +.btnsContainer .btnsBlock button { + margin-left: 1rem; + display: flex; + justify-content: center; + align-items: center; +} + +.btnsContainer .inputContainer { + flex: 1; + position: relative; +} +.btnsContainer .input { + width: 70%; + position: relative; +} + +.btnsContainer input { + outline: 1px solid var(--bs-gray-400); +} + +.btnsContainer .inputContainer button { + width: 52px; +} + +.listBox { + width: 100%; + flex: 1; +} + +.notFound { + flex: 1; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; +} + +@media (max-width: 1020px) { + .btnsContainer { + flex-direction: column; + margin: 1.5rem 0; + } + .btnsContainer .input { + width: 100%; + } + .btnsContainer .btnsBlock { + margin: 1.5rem 0 0 0; + justify-content: space-between; + } + + .btnsContainer .btnsBlock button { + margin: 0; + } + + .btnsContainer .btnsBlock div button { + margin-right: 1.5rem; + } +} + +/* For mobile devices */ + +@media (max-width: 520px) { + .btnsContainer { + margin-bottom: 0; + } + + .btnsContainer .btnsBlock { + display: block; + margin-top: 1rem; + margin-right: 0; + } + + .btnsContainer .btnsBlock div { + flex: 1; + } + + .btnsContainer .btnsBlock div[title='Sort organizations'] { + margin-right: 0.5rem; + } + + .btnsContainer .btnsBlock button { + margin-bottom: 1rem; + margin-right: 0; + width: 100%; + } +} diff --git a/src/screens/Requests/Requests.test.tsx b/src/screens/Requests/Requests.test.tsx new file mode 100644 index 0000000000..f8247905bc --- /dev/null +++ b/src/screens/Requests/Requests.test.tsx @@ -0,0 +1,169 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { act, render, screen } from '@testing-library/react'; +import 'jest-localstorage-mock'; +import 'jest-location-mock'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; + +import userEvent from '@testing-library/user-event'; +import { ToastContainer } from 'react-toastify'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18nForTest from 'utils/i18nForTest'; +import Requests from './Requests'; +import { EMPTY_ORG_MOCKS, MOCKS, ORG_LIST_MOCK } from './RequestsMocks'; + +const link = new StaticMockLink(MOCKS, true); +const link2 = new StaticMockLink(EMPTY_ORG_MOCKS, true); +const link3 = new StaticMockLink(ORG_LIST_MOCK, true); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +beforeEach(() => { + localStorage.setItem('UserType', 'SUPERADMIN'); + localStorage.setItem('FirstName', 'John'); + localStorage.setItem('LastName', 'Doe'); +}); + +afterEach(() => { + localStorage.clear(); +}); + +describe('Testing Request screen', () => { + test('Component should be rendered properly', async () => { + window.location.assign('/orglist'); + render( + + + + + + + + + + ); + + await wait(); + expect(screen.getByTestId(/searchByName/i)).toBeInTheDocument(); + expect(window.location).toBeAt('/orglist'); + }); + + test('Testing, If userType is not SUPERADMIN', async () => { + localStorage.setItem('UserType', 'USER'); + + render( + + + + + + + + + + ); + + await wait(); + }); + + test('Testing seach by name functionality', async () => { + render( + + + + + + + + + + ); + + await wait(); + }); + + test('Testing accept user functionality', async () => { + render( + + + + + + + + + + ); + + await wait(); + userEvent.click(screen.getByTestId(/acceptUser456/i)); + }); + + test('Testing reject user functionality', async () => { + render( + + + + + + + + + + ); + + await wait(); + userEvent.click(screen.getByTestId(/rejectUser456/i)); + }); + + test('Should render warning alert when there are no organizations', async () => { + const { container } = render( + + + + + + + + + + + ); + + await wait(200); + + expect(container.textContent).toMatch( + 'Organizations not found, please create an organization through dashboard' + ); + }); + + test('Should not render warning alert when there are organizations present', async () => { + const { container } = render( + + + + + + + + + + + ); + + await wait(); + + expect(container.textContent).not.toMatch( + 'Organizations not found, please create an organization through dashboard' + ); + }); +}); diff --git a/src/screens/Requests/Requests.tsx b/src/screens/Requests/Requests.tsx new file mode 100644 index 0000000000..b0b0a5f6ad --- /dev/null +++ b/src/screens/Requests/Requests.tsx @@ -0,0 +1,380 @@ +import React from 'react'; +import { useMutation, useQuery } from '@apollo/client'; +import type { ApolloError } from '@apollo/client'; +import { useEffect, useState } from 'react'; +import { Dropdown, Form, Table } from 'react-bootstrap'; +import Button from 'react-bootstrap/Button'; +import { useTranslation } from 'react-i18next'; +import { toast } from 'react-toastify'; + +import { Search } from '@mui/icons-material'; +import FilterListIcon from '@mui/icons-material/FilterList'; +import SortIcon from '@mui/icons-material/Sort'; +import { + ACCEPT_ADMIN_MUTATION, + REJECT_ADMIN_MUTATION, +} from 'GraphQl/Mutations/mutations'; +import { + ORGANIZATION_CONNECTION_LIST, + USER_LIST_REQUEST, + USER_ORGANIZATION_LIST, +} from 'GraphQl/Queries/Queries'; +import SuperAdminScreen from 'components/SuperAdminScreen/SuperAdminScreen'; +import TableLoader from 'components/TableLoader/TableLoader'; +import InfiniteScroll from 'react-infinite-scroll-component'; +import debounce from 'utils/debounce'; +import { errorHandler } from 'utils/errorHandler'; +import type { + InterfaceOrgConnectionType, + InterfaceQueryRequestListItem, + InterfaceUserType, +} from 'utils/interfaces'; +import styles from './Requests.module.css'; + +const Requests = (): JSX.Element => { + const { t } = useTranslation('translation', { keyPrefix: 'requests' }); + + document.title = t('title'); + + const perPageResult = 12; + const [isLoading, setIsLoading] = useState(true); + const [hasMore, sethasMore] = useState(true); + const [isLoadingMore, setIsLoadingMore] = useState(false); + const [searchByName, setSearchByName] = useState(''); + + const [acceptAdminFunc] = useMutation(ACCEPT_ADMIN_MUTATION); + const [rejectAdminFunc] = useMutation(REJECT_ADMIN_MUTATION); + const { + data: currentUserData, + }: { + data?: InterfaceUserType; + error?: ApolloError; + } = useQuery(USER_ORGANIZATION_LIST, { + variables: { id: localStorage.getItem('id') }, + }); + + const { + data: usersData, + loading: loading, + fetchMore, + refetch: refetchUsers, + }: { + data?: { users: InterfaceQueryRequestListItem[] }; + loading: boolean; + fetchMore: any; + refetch: any; + error?: ApolloError; + } = useQuery(USER_LIST_REQUEST, { + variables: { + first: perPageResult, + skip: 0, + userType: 'ADMIN', + adminApproved: false, + firstName_contains: searchByName, + lastName_contains: '', + }, + notifyOnNetworkStatusChange: true, + }); + + const { + data: dataOrgs, + }: { + data?: InterfaceOrgConnectionType; + error?: ApolloError; + } = useQuery(ORGANIZATION_CONNECTION_LIST); + + // To clear the search when the component is unmounted + useEffect(() => { + return () => { + setSearchByName(''); + }; + }, []); + + // To manage loading states + useEffect(() => { + if (!usersData) { + return; + } + if (usersData.users.length < perPageResult) { + sethasMore(false); + } + }, [usersData]); + + // If the user is not Superadmin, redirect to Organizations screen + useEffect(() => { + const userType = localStorage.getItem('UserType'); + if (userType != 'SUPERADMIN') { + window.location.assign('/orglist'); + } + }, []); + + // Check if there are no organizations then show a warning + useEffect(() => { + if (!dataOrgs) { + return; + } + if (dataOrgs.organizationsConnection.length === 0) { + toast.warning(t('noOrgError')); + } + }, [dataOrgs]); + + // Manage the loading state + useEffect(() => { + if (loading && isLoadingMore == false) { + setIsLoading(true); + } else { + setIsLoading(false); + } + }, [loading]); + + /* istanbul ignore next */ + const resetAndRefetch = (): void => { + refetchUsers({ + first: perPageResult, + skip: 0, + userType: 'ADMIN', + adminApproved: false, + firstName_contains: '', + lastName_contains: '', + }); + sethasMore(true); + }; + /* istanbul ignore next */ + const loadMoreRequests = (): void => { + setIsLoadingMore(true); + fetchMore({ + variables: { + skip: usersData?.users.length || 0, + userType: 'ADMIN', + adminApproved: false, + firstName_contains: searchByName, + lastName_contains: '', + }, + updateQuery: ( + prev: { users: InterfaceQueryRequestListItem[] } | undefined, + { + fetchMoreResult, + }: { + fetchMoreResult: + | { users: InterfaceQueryRequestListItem[] } + | undefined; + } + ): { users: InterfaceQueryRequestListItem[] } | undefined => { + setIsLoadingMore(false); + if (!fetchMoreResult) return prev; + if (fetchMoreResult.users.length < perPageResult) { + sethasMore(false); + } + return { + users: [...(prev?.users || []), ...(fetchMoreResult.users || [])], + }; + }, + }); + }; + + const acceptAdmin = async (userId: any): Promise => { + try { + const { data } = await acceptAdminFunc({ + variables: { + id: userId, + }, + }); + + /* istanbul ignore next */ + if (data) { + toast.success(t('userApproved')); + resetAndRefetch(); + } + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + + const rejectAdmin = async (userId: any): Promise => { + try { + const { data } = await rejectAdminFunc({ + variables: { + id: userId, + }, + }); + + /* istanbul ignore next */ + if (data) { + toast.success(t('userRejected')); + resetAndRefetch(); + } + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + + /* istanbul ignore next */ + const handleSearchByName = async (e: any): Promise => { + const { value } = e.target; + setSearchByName(value); + if (value === '') { + resetAndRefetch(); + return; + } + await refetchUsers({ + firstName_contains: value, + lastName_contains: '', + // Later on we can add several search and filter options + }); + }; + + const debouncedHandleSearchByName = debounce(handleSearchByName); + + const headerTitles: string[] = [ + '#', + t('name'), + t('email'), + t('accept'), + t('reject'), + ]; + + return ( + <> + + {/* Buttons Container */} +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    + {isLoading == false && + usersData?.users.length === 0 && + searchByName.length > 0 ? ( +
    +

    + {t('noResultsFoundFor')} "{searchByName}" +

    +
    + ) : isLoading == false && usersData?.users.length === 0 ? ( +
    +

    {t('noRequestFound')}

    +
    + ) : isLoading ? ( + + ) : ( + } + hasMore={hasMore} + className={styles.listBox} + data-testid="organizations-list" + endMessage={ +
    +
    {t('endOfResults')}
    +
    + } + > + + + + {headerTitles.map((title: string, index: number) => { + return ( + + ); + })} + + + + {usersData?.users && + usersData.users.map((user, index) => { + return ( + + + + + + + + ); + })} + +
    + {title} +
    {index + 1}{`${user.firstName} ${user.lastName}`}{user.email} + + + +
    +
    + )} +
    + + ); +}; + +export default Requests; diff --git a/src/screens/Requests/RequestsMocks.ts b/src/screens/Requests/RequestsMocks.ts new file mode 100644 index 0000000000..a57bff7c83 --- /dev/null +++ b/src/screens/Requests/RequestsMocks.ts @@ -0,0 +1,220 @@ +import { + ACCEPT_ADMIN_MUTATION, + REJECT_ADMIN_MUTATION, +} from 'GraphQl/Mutations/mutations'; +import { + ORGANIZATION_CONNECTION_LIST, + USER_LIST_REQUEST, + USER_ORGANIZATION_LIST, +} from 'GraphQl/Queries/Queries'; + +export const MOCKS = [ + { + request: { + query: USER_ORGANIZATION_LIST, + variables: { id: localStorage.getItem('id') }, + }, + result: { + data: { + user: { + _id: '123', + userType: 'SUPERADMIN', + firstName: 'John', + lastName: 'Doe', + image: '', + email: 'John_Does_Palasidoes@gmail.com', + adminFor: { + _id: 1, + name: 'Akatsuki', + image: '', + }, + }, + }, + }, + }, + { + request: { + query: USER_LIST_REQUEST, + variables: { + adminApproved: false, + first: 12, + firstName_contains: '', + lastName_contains: '', + skip: 0, + userType: 'ADMIN', + }, + notifyOnNetworkStatusChange: true, + }, + result: { + data: { + users: [ + { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: 'dummyImage', + email: 'johndoe@gmail.com', + userType: 'SUPERADMIN', + adminApproved: true, + createdAt: '20/06/2022', + organizationsBlockedBy: [ + { + _id: '256', + name: 'ABC', + }, + ], + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af1', + }, + ], + }, + { + _id: '456', + firstName: 'Sam', + lastName: 'Smith', + image: 'dummyImage', + email: 'samsmith@gmail.com', + userType: 'ADMIN', + adminApproved: false, + createdAt: '20/06/2022', + organizationsBlockedBy: [ + { + _id: '256', + name: 'ABC', + }, + ], + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + }, + ], + }, + { + _id: '789', + firstName: 'Peter', + lastName: 'Parker', + image: 'dummyImage', + email: 'peterparker@gmail.com', + userType: 'USER', + adminApproved: true, + createdAt: '20/06/2022', + organizationsBlockedBy: [ + { + _id: '256', + name: 'ABC', + }, + ], + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af3', + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: ACCEPT_ADMIN_MUTATION, + variables: { + id: '123', + userType: 'ADMIN', + }, + }, + result: { + data: { + acceptAdmin: true, + }, + }, + }, + { + request: { + query: REJECT_ADMIN_MUTATION, + variables: { + id: '123', + userType: 'ADMIN', + }, + }, + result: { + data: { + rejectAdmin: true, + }, + }, + }, +]; + +export const EMPTY_ORG_MOCKS = [ + { + request: { + query: ACCEPT_ADMIN_MUTATION, + variables: { + id: '123', + userType: 'ADMIN', + }, + }, + result: { + data: undefined, + }, + }, + { + request: { + query: REJECT_ADMIN_MUTATION, + variables: { + id: '123', + userType: 'ADMIN', + }, + }, + result: { + data: undefined, + }, + }, + { + request: { + query: ORGANIZATION_CONNECTION_LIST, + }, + result: { + data: { + organizationsConnection: [], + }, + }, + }, +]; + +export const ORG_LIST_MOCK = [ + ...MOCKS, + { + request: { + query: ORGANIZATION_CONNECTION_LIST, + }, + result: { + data: { + organizationsConnection: [ + { + _id: 1, + image: '', + name: 'Akatsuki', + creator: { + firstName: 'John', + lastName: 'Doe', + }, + admins: [ + { + _id: '123', + }, + ], + members: { + _id: '234', + }, + createdAt: '02/02/2022', + location: 'Washington DC', + }, + ], + }, + }, + }, +]; diff --git a/src/screens/UserPortal/Chat/Chat.module.css b/src/screens/UserPortal/Chat/Chat.module.css new file mode 100644 index 0000000000..40add650f4 --- /dev/null +++ b/src/screens/UserPortal/Chat/Chat.module.css @@ -0,0 +1,63 @@ +.containerHeight { + height: calc(100vh - 66px); +} + +.mainContainer { + width: 50%; + flex-grow: 3; + padding: 20px; + max-height: 100%; + overflow: auto; + display: flex; + flex-direction: row; +} + +.chatContainer { + flex-grow: 4; + display: flex; + flex-direction: column; + background-color: white; + border-top-right-radius: 10px; + border-bottom-right-radius: 10px; +} + +.contactContainer { + flex-grow: 1; + display: flex; + flex-direction: column; + background-color: white; + border-top-left-radius: 10px; + border-bottom-left-radius: 10px; +} + +.colorLight { + background-color: #f5f5f5; +} + +.addChatContainer { + gap: 5px; + padding: 10px; +} + +.contactListContainer { + flex-grow: 1; + padding: 15px 10px; +} + +.chatHeadingContainer { + padding: 10px; + color: white; + border-radius: 0px 10px 0px 0px; +} + +.borderNone { + border: none; +} + +.colorWhite { + color: white; +} + +.colorPrimary { + background: #31bb6b; +} diff --git a/src/screens/UserPortal/Chat/Chat.test.tsx b/src/screens/UserPortal/Chat/Chat.test.tsx new file mode 100644 index 0000000000..6476e9ee40 --- /dev/null +++ b/src/screens/UserPortal/Chat/Chat.test.tsx @@ -0,0 +1,173 @@ +import React from 'react'; +import { act, render, screen } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider } from 'react-i18next'; + +import { ORGANIZATIONS_MEMBER_CONNECTION_LIST } from 'GraphQl/Queries/Queries'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import Chat from './Chat'; +import * as getOrganizationId from 'utils/getOrganizationId'; +import userEvent from '@testing-library/user-event'; + +const MOCKS = [ + { + request: { + query: ORGANIZATIONS_MEMBER_CONNECTION_LIST, + variables: { + orgId: '', + firstName_contains: '', + }, + }, + result: { + data: { + organizationsMemberConnection: { + edges: [ + { + _id: '64001660a711c62d5b4076a2', + firstName: 'Noble', + lastName: 'Mittal', + image: null, + email: 'noble1@gmail.com', + createdAt: '2023-03-02T03:22:08.101Z', + }, + { + _id: '64001660a711c62d5b4076a3', + firstName: 'Noble', + lastName: 'Mittal', + image: 'mockImage', + email: 'noble@gmail.com', + createdAt: '2023-03-02T03:22:08.101Z', + }, + ], + }, + }, + }, + }, + { + request: { + query: ORGANIZATIONS_MEMBER_CONNECTION_LIST, + variables: { + orgId: '', + firstName_contains: 'j', + }, + }, + result: { + data: { + organizationsMemberConnection: { + edges: [ + { + _id: '64001660a711c62d5b4076a2', + firstName: 'John', + lastName: 'Cena', + image: null, + email: 'john@gmail.com', + createdAt: '2023-03-02T03:22:08.101Z', + }, + ], + }, + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Testing People Screen [User Portal]', () => { + jest.mock('utils/getOrganizationId'); + + Object.defineProperty(window, 'matchMedia', { + writable: true, + value: jest.fn().mockImplementation((query) => ({ + matches: false, + media: query, + onchange: null, + addListener: jest.fn(), // Deprecated + removeListener: jest.fn(), // Deprecated + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn(), + })), + }); + + const getOrganizationIdSpy = jest + .spyOn(getOrganizationId, 'default') + .mockImplementation(() => { + return ''; + }); + + test('Screen should be rendered properly', async () => { + render( + + + + + + + + + + ); + + await wait(); + + expect(getOrganizationIdSpy).toHaveBeenCalled(); + expect(screen.queryAllByText('Noble Mittal')).not.toBe([]); + }); + + test('User is able to select a contact', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByText('noble1@gmail.com')); + await wait(); + + expect(getOrganizationIdSpy).toHaveBeenCalled(); + expect(screen.queryAllByText('Noble Mittal')).not.toBe([]); + }); + + test('Search functionality works as expected', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.type(screen.getByTestId('searchInput'), 'j'); + await wait(); + + expect(getOrganizationIdSpy).toHaveBeenCalled(); + expect(screen.queryByText('John Cena')).toBeInTheDocument(); + expect(screen.queryByText('Noble Mittal')).not.toBeInTheDocument(); + }); +}); diff --git a/src/screens/UserPortal/Chat/Chat.tsx b/src/screens/UserPortal/Chat/Chat.tsx new file mode 100644 index 0000000000..1ae9d5764d --- /dev/null +++ b/src/screens/UserPortal/Chat/Chat.tsx @@ -0,0 +1,142 @@ +import React from 'react'; +import OrganizationNavbar from 'components/UserPortal/OrganizationNavbar/OrganizationNavbar'; +import UserSidebar from 'components/UserPortal/UserSidebar/UserSidebar'; +import { ORGANIZATIONS_MEMBER_CONNECTION_LIST } from 'GraphQl/Queries/Queries'; +import { useQuery } from '@apollo/client'; +import styles from './Chat.module.css'; +import getOrganizationId from 'utils/getOrganizationId'; +import { useTranslation } from 'react-i18next'; +import { Form, InputGroup } from 'react-bootstrap'; +import { SearchOutlined } from '@mui/icons-material'; +import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; +import ContactCard from 'components/UserPortal/ContactCard/ContactCard'; +import ChatRoom from 'components/UserPortal/ChatRoom/ChatRoom'; + +interface InterfaceContactCardProps { + id: string; + firstName: string; + lastName: string; + email: string; + image: string; + selectedContact: string; + setSelectedContact: React.Dispatch>; + setSelectedContactName: React.Dispatch>; +} + +interface InterfaceChatRoomProps { + selectedContact: string; +} + +export default function chat(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'userChat', + }); + const organizationId = getOrganizationId(location.href); + + const [selectedContact, setSelectedContact] = React.useState(''); + const [selectedContactName, setSelectedContactName] = React.useState(''); + const [contacts, setContacts] = React.useState([]); + const [filterName, setFilterName] = React.useState(''); + + const navbarProps = { + currentPage: 'chat', + }; + + const chatRoomProps: InterfaceChatRoomProps = { + selectedContact, + }; + + const { + data: contactData, + loading: contactLoading, + refetch: contactRefetch, + } = useQuery(ORGANIZATIONS_MEMBER_CONNECTION_LIST, { + variables: { + orgId: organizationId, + firstName_contains: filterName, + }, + }); + + const handleSearch = ( + event: React.ChangeEvent + ): void => { + const newFilter = event.target.value; + setFilterName(newFilter); + + const filter = { + firstName_contains: newFilter, + }; + + contactRefetch(filter); + }; + + React.useEffect(() => { + if (contactData) { + setContacts(contactData.organizationsMemberConnection.edges); + } + }, [contactData]); + + return ( + <> + +
    + +
    +
    +
    +

    + {t('contacts')} +

    + + + + + + +
    +
    + {contactLoading ? ( +
    + Loading... +
    + ) : ( + contacts.map((contact: any, index: number) => { + const cardProps: InterfaceContactCardProps = { + id: contact._id, + firstName: contact.firstName, + lastName: contact.lastName, + email: contact.email, + image: contact.image, + setSelectedContactName, + selectedContact, + setSelectedContact, + }; + return ; + }) + )} +
    +
    +
    +
    + {selectedContact ? selectedContactName : t('chat')} +
    + +
    +
    +
    + + ); +} diff --git a/src/screens/UserPortal/Donate/Donate.module.css b/src/screens/UserPortal/Donate/Donate.module.css new file mode 100644 index 0000000000..c137003c0e --- /dev/null +++ b/src/screens/UserPortal/Donate/Donate.module.css @@ -0,0 +1,56 @@ +.containerHeight { + height: calc(100vh - 66px); +} + +.mainContainer { + width: 50%; + flex-grow: 3; + padding: 20px; + max-height: 100%; + overflow: auto; + display: flex; + flex-direction: column; +} + +.box { + width: auto; + /* height: 200px; */ + background-color: white; + margin: 20px; + padding: 20px; + border-radius: 20px; +} + +.donationInputContainer { + display: flex; + flex-direction: row; + margin-top: 20px; +} + +.maxWidth { + width: 100%; +} + +.donateActions { + margin-top: 40px; + width: 100%; + display: flex; + flex-direction: row-reverse; +} + +.donationsContainer { + margin: 20px; + padding-top: 20px; + flex-grow: 1; + display: flex; + flex-direction: column; +} + +.colorLight { + background-color: #f5f5f5; +} + +.content { + padding-top: 10px; + flex-grow: 1; +} diff --git a/src/screens/UserPortal/Donate/Donate.test.tsx b/src/screens/UserPortal/Donate/Donate.test.tsx new file mode 100644 index 0000000000..3abb433c51 --- /dev/null +++ b/src/screens/UserPortal/Donate/Donate.test.tsx @@ -0,0 +1,183 @@ +import React from 'react'; +import { act, render, screen } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider } from 'react-i18next'; + +import { + ORGANIZATION_DONATION_CONNECTION_LIST, + USER_ORGANIZATION_CONNECTION, +} from 'GraphQl/Queries/Queries'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import Donate from './Donate'; +import userEvent from '@testing-library/user-event'; +import * as getOrganizationId from 'utils/getOrganizationId'; + +const MOCKS = [ + { + request: { + query: ORGANIZATION_DONATION_CONNECTION_LIST, + variables: { + orgId: '', + }, + }, + result: { + data: { + getDonationByOrgIdConnection: [ + { + _id: '6391a15bcb738c181d238957', + nameOfUser: 'firstName lastName', + amount: 1, + userId: '6391a15bcb738c181d238952', + payPalId: 'payPalId', + __typename: 'Donation', + }, + ], + }, + }, + }, + { + request: { + query: USER_ORGANIZATION_CONNECTION, + variables: { + id: '', + }, + }, + result: { + data: { + organizationsConnection: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af3', + image: '', + name: 'anyOrganization2', + description: 'desc', + isPublic: true, + creator: { __typename: 'User', firstName: 'John', lastName: 'Doe' }, + }, + ], + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Testing Donate Screen [User Portal]', () => { + jest.mock('utils/getOrganizationId'); + + Object.defineProperty(window, 'matchMedia', { + writable: true, + value: jest.fn().mockImplementation((query) => ({ + matches: false, + media: query, + onchange: null, + addListener: jest.fn(), // Deprecated + removeListener: jest.fn(), // Deprecated + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn(), + })), + }); + + const getOrganizationIdSpy = jest + .spyOn(getOrganizationId, 'default') + .mockImplementation(() => { + return ''; + }); + + test('Screen should be rendered properly', async () => { + render( + + + + + + + + + + ); + + await wait(); + + expect(getOrganizationIdSpy).toHaveBeenCalled(); + }); + + test('Currency is swtiched to USD', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('changeCurrencyBtn')); + + userEvent.click(screen.getByTestId('currency0')); + + await wait(); + }); + + test('Currency is swtiched to INR', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('changeCurrencyBtn')); + + userEvent.click(screen.getByTestId('currency1')); + + await wait(); + }); + + test('Currency is swtiched to EUR', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('changeCurrencyBtn')); + + userEvent.click(screen.getByTestId('currency2')); + + await wait(); + }); +}); diff --git a/src/screens/UserPortal/Donate/Donate.tsx b/src/screens/UserPortal/Donate/Donate.tsx new file mode 100644 index 0000000000..cbe31f9937 --- /dev/null +++ b/src/screens/UserPortal/Donate/Donate.tsx @@ -0,0 +1,202 @@ +import React from 'react'; +import OrganizationNavbar from 'components/UserPortal/OrganizationNavbar/OrganizationNavbar'; +import OrganizationSidebar from 'components/UserPortal/OrganizationSidebar/OrganizationSidebar'; +import UserSidebar from 'components/UserPortal/UserSidebar/UserSidebar'; +import { Button, Dropdown, Form, InputGroup } from 'react-bootstrap'; +import PaginationList from 'components/PaginationList/PaginationList'; +import { + ORGANIZATION_DONATION_CONNECTION_LIST, + USER_ORGANIZATION_CONNECTION, +} from 'GraphQl/Queries/Queries'; +import { useQuery } from '@apollo/client'; +import styles from './Donate.module.css'; +import SendIcon from '@mui/icons-material/Send'; +import getOrganizationId from 'utils/getOrganizationId'; +import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; +import DonationCard from 'components/UserPortal/DonationCard/DonationCard'; +import { useTranslation } from 'react-i18next'; + +interface InterfaceDonationCardProps { + id: string; + name: string; + amount: string; + userId: string; + payPalId: string; +} + +export default function donate(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'donate', + }); + + const organizationId = getOrganizationId(location.href); + const [organizationDetails, setOrganizationDetails]: any = React.useState({}); + const [donations, setDonations] = React.useState([]); + const [selectedCurrency, setSelectedCurrency] = React.useState(0); + const [page, setPage] = React.useState(0); + const [rowsPerPage, setRowsPerPage] = React.useState(5); + + const currencies = ['USD', 'INR', 'EUR']; + + const { data: data2, loading } = useQuery( + ORGANIZATION_DONATION_CONNECTION_LIST, + { + variables: { orgId: organizationId }, + } + ); + + const { data } = useQuery(USER_ORGANIZATION_CONNECTION, { + variables: { id: organizationId }, + }); + + const navbarProps = { + currentPage: 'donate', + }; + + /* istanbul ignore next */ + const handleChangePage = ( + _event: React.MouseEvent | null, + newPage: number + ): void => { + setPage(newPage); + }; + + /* istanbul ignore next */ + const handleChangeRowsPerPage = ( + event: React.ChangeEvent + ): void => { + const newRowsPerPage = event.target.value; + + setRowsPerPage(parseInt(newRowsPerPage, 10)); + setPage(0); + }; + + React.useEffect(() => { + if (data) { + setOrganizationDetails(data.organizationsConnection[0]); + } + }, [data]); + + React.useEffect(() => { + if (data2) { + setDonations(data2.getDonationByOrgIdConnection); + } + }, [data2]); + + return ( + <> + +
    + +
    +
    +

    + {t('donateTo')} {organizationDetails.name} +

    +
    + + + {t('amount')} + + + + + + {currencies[selectedCurrency]} + + + + {currencies.map((currency, index) => { + return ( + setSelectedCurrency(index)} + data-testid={`currency${index}`} + > + {currency} + + ); + })} + + + +
    +
    + +
    +
    +
    +
    {t('yourPreviousDonations')}
    +
    +
    + {loading ? ( +
    + Loading... +
    + ) : ( + <> + {donations && donations.length > 0 ? ( + (rowsPerPage > 0 + ? donations.slice( + page * rowsPerPage, + page * rowsPerPage + rowsPerPage + ) + : /* istanbul ignore next */ + donations + ).map((donation: any, index) => { + const cardProps: InterfaceDonationCardProps = { + name: donation.nameOfUser, + id: donation._id, + amount: donation.amount, + userId: donation.userId, + payPalId: donation.payPalId, + }; + return ; + }) + ) : ( + {t('nothingToShow')} + )} + + )} +
    + + + + + + +
    +
    +
    +
    + +
    + + ); +} diff --git a/src/screens/UserPortal/Events/Events.module.css b/src/screens/UserPortal/Events/Events.module.css new file mode 100644 index 0000000000..52a305cc20 --- /dev/null +++ b/src/screens/UserPortal/Events/Events.module.css @@ -0,0 +1,83 @@ +.borderNone { + border: none; +} + +.colorWhite { + color: white; +} + +.backgroundWhite { + background-color: white; +} + +.maxWidth { + max-width: 300px; +} + +.colorLight { + background-color: #f5f5f5; +} + +.mainContainer { + width: 50%; + flex-grow: 3; + padding: 40px; + max-height: 100%; + overflow: auto; +} + +.content { + height: fit-content; + min-height: calc(100% - 40px); +} + +.gap { + gap: 20px; +} + +.paddingY { + padding: 30px 0px; +} + +.containerHeight { + height: calc(100vh - 66px); +} + +.colorPrimary { + background: #31bb6b; + color: white; +} + +.eventActionsContainer { + display: flex; + flex-direction: row; + gap: 15px; +} + +.datePicker { + border-radius: 10px; + height: 40px; + text-align: center; + background-color: #f2f2f2; + border: none; + width: 100%; +} + +.modalBody { + display: flex; + flex-direction: column; + gap: 10px; +} + +.switchContainer { + display: flex; + align-items: center; +} + +.switches { + display: flex; + flex-direction: row; + gap: 20px; + flex-wrap: wrap; + margin-top: 20px; +} diff --git a/src/screens/UserPortal/Events/Events.test.tsx b/src/screens/UserPortal/Events/Events.test.tsx new file mode 100644 index 0000000000..4243efa8ee --- /dev/null +++ b/src/screens/UserPortal/Events/Events.test.tsx @@ -0,0 +1,473 @@ +import React from 'react'; +import { act, render, screen } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider } from 'react-i18next'; + +import { ORGANIZATION_EVENTS_CONNECTION } from 'GraphQl/Queries/Queries'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import Events from './Events'; +import userEvent from '@testing-library/user-event'; +import * as getOrganizationId from 'utils/getOrganizationId'; +import { CREATE_EVENT_MUTATION } from 'GraphQl/Mutations/mutations'; +import { toast } from 'react-toastify'; +import dayjs from 'dayjs'; + +jest.mock('react-toastify', () => ({ + toast: { + error: jest.fn(), + info: jest.fn(), + success: jest.fn(), + }, +})); + +const MOCKS = [ + { + request: { + query: ORGANIZATION_EVENTS_CONNECTION, + variables: { + organization_id: '', + title_contains: '', + }, + }, + result: { + data: { + eventsByOrganizationConnection: [ + { + _id: '6404a267cc270739118e2349', + title: 'NewEvent', + description: 'sdadsasad', + startDate: '2023-03-05', + endDate: '2023-03-05', + location: 'NewLocation', + startTime: null, + endTime: null, + allDay: true, + recurring: false, + isPublic: true, + isRegisterable: false, + creator: { + _id: '63d649417ffe6e4d5174ea32', + firstName: 'Noble', + lastName: 'Mittal', + __typename: 'User', + }, + attendees: [ + { + _id: '63d649417ffe6e4d5174ea32', + __typename: 'User', + }, + { + _id: '63d6064458fce20ee25c3bf7', + __typename: 'User', + }, + ], + __typename: 'Event', + }, + { + _id: '6404e952c651df745358849d', + title: '1parti', + description: 'asddas', + startDate: '2023-03-06', + endDate: '2023-03-06', + location: 'das', + startTime: '00:40:00.000Z', + endTime: '02:40:00.000Z', + allDay: false, + recurring: false, + isPublic: true, + isRegisterable: true, + creator: { + _id: '63d649417ffe6e4d5174ea32', + firstName: 'Noble', + lastName: 'Mittal', + __typename: 'User', + }, + attendees: [ + { + _id: '63d649417ffe6e4d5174ea32', + __typename: 'User', + }, + { + _id: '63dd52bbe69f63814b0a5dd4', + __typename: 'User', + }, + { + _id: '63d6064458fce20ee25c3bf7', + __typename: 'User', + }, + ], + __typename: 'Event', + }, + ], + }, + }, + }, + { + request: { + query: ORGANIZATION_EVENTS_CONNECTION, + variables: { + organization_id: '', + title_contains: 'test', + }, + }, + result: { + data: { + eventsByOrganizationConnection: [ + { + _id: '6404a267cc270739118e2349', + title: 'NewEvent', + description: 'sdadsasad', + startDate: '2023-03-05', + endDate: '2023-03-05', + location: 'NewLocation', + startTime: null, + endTime: null, + allDay: true, + recurring: false, + isPublic: true, + isRegisterable: false, + creator: { + _id: '63d649417ffe6e4d5174ea32', + firstName: 'Noble', + lastName: 'Mittal', + __typename: 'User', + }, + attendees: [ + { + _id: '63d649417ffe6e4d5174ea32', + __typename: 'User', + }, + { + _id: '63d6064458fce20ee25c3bf7', + __typename: 'User', + }, + ], + __typename: 'Event', + }, + ], + }, + }, + }, + { + request: { + query: CREATE_EVENT_MUTATION, + variables: { + title: 'testEventTitle', + description: 'testEventDescription', + location: 'testEventLocation', + isPublic: true, + recurring: false, + isRegisterable: true, + organizationId: '', + startDate: dayjs(new Date()).format('YYYY-MM-DD'), + endDate: dayjs(new Date()).format('YYYY-MM-DD'), + allDay: false, + startTime: '08:00:00Z', + endTime: '10:00:00Z', + }, + }, + result: { + data: { + createEvent: { + _id: '2', + }, + }, + }, + }, + { + request: { + query: CREATE_EVENT_MUTATION, + variables: { + title: 'testEventTitle', + description: 'testEventDescription', + location: 'testEventLocation', + isPublic: true, + recurring: false, + isRegisterable: true, + organizationId: '', + startDate: dayjs(new Date()).format('YYYY-MM-DD'), + endDate: dayjs(new Date()).format('YYYY-MM-DD'), + allDay: true, + startTime: null, + endTime: null, + }, + }, + result: { + data: { + createEvent: { + _id: '1', + }, + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Testing Events Screen [User Portal]', () => { + jest.mock('utils/getOrganizationId'); + + Object.defineProperty(window, 'matchMedia', { + writable: true, + value: jest.fn().mockImplementation((query) => ({ + matches: false, + media: query, + onchange: null, + addListener: jest.fn(), // Deprecated + removeListener: jest.fn(), // Deprecated + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn(), + })), + }); + + test('Screen should be rendered properly', async () => { + const getOrganizationIdSpy = jest + .spyOn(getOrganizationId, 'default') + .mockImplementation(() => { + return ''; + }); + + render( + + + + + + + + + + ); + + await wait(); + + expect(getOrganizationIdSpy).toHaveBeenCalled(); + }); + + test('Events are visible as expected without search query', async () => { + const getOrganizationIdSpy = jest + .spyOn(getOrganizationId, 'default') + .mockImplementation(() => { + return ''; + }); + + render( + + + + + + + + + + ); + + await wait(); + + let mockEventTitle = ''; + if (MOCKS[0].result?.data.eventsByOrganizationConnection) { + mockEventTitle = + MOCKS[0].result?.data.eventsByOrganizationConnection[0].title; + } + + expect(getOrganizationIdSpy).toHaveBeenCalled(); + expect(screen.queryByText(mockEventTitle)).toBeInTheDocument(); + }); + + test('Search works as expected when user types in search input', async () => { + const getOrganizationIdSpy = jest + .spyOn(getOrganizationId, 'default') + .mockImplementation(() => { + return ''; + }); + + render( + + + + + + + + + + ); + + await wait(); + + expect(getOrganizationIdSpy).toHaveBeenCalled(); + + const randomSearchInput = 'test'; + userEvent.type(screen.getByTestId('searchInput'), randomSearchInput); + + await wait(); + + let mockEventTitle = ''; + if (MOCKS[0].result?.data.eventsByOrganizationConnection) { + mockEventTitle = + MOCKS[0].result?.data.eventsByOrganizationConnection[0].title; + } + + let mockEventTitleAbsent = ''; + if (MOCKS[0].result?.data.eventsByOrganizationConnection) { + mockEventTitleAbsent = + MOCKS[0].result?.data.eventsByOrganizationConnection[1].title; + } + + expect(screen.queryByText(mockEventTitle)).toBeInTheDocument(); + expect(screen.queryByText(mockEventTitleAbsent)).not.toBeInTheDocument(); + }); + + test('Create event works as expected when event is not an all day event.', async () => { + const getOrganizationIdSpy = jest + .spyOn(getOrganizationId, 'default') + .mockImplementation(() => { + return ''; + }); + + render( + + + + + + + + + + ); + + await wait(); + + expect(getOrganizationIdSpy).toHaveBeenCalled(); + userEvent.click(screen.getByTestId('createEventModalBtn')); + + const randomEventTitle = 'testEventTitle'; + const randomEventDescription = 'testEventDescription'; + const randomEventLocation = 'testEventLocation'; + + userEvent.type(screen.getByTestId('eventTitleInput'), randomEventTitle); + userEvent.type( + screen.getByTestId('eventDescriptionInput'), + randomEventDescription + ); + userEvent.type( + screen.getByTestId('eventLocationInput'), + randomEventLocation + ); + + userEvent.click(screen.getByTestId('publicEventCheck')); + userEvent.click(screen.getByTestId('publicEventCheck')); + + userEvent.click(screen.getByTestId('registerableEventCheck')); + userEvent.click(screen.getByTestId('registerableEventCheck')); + + userEvent.click(screen.getByTestId('recurringEventCheck')); + userEvent.click(screen.getByTestId('recurringEventCheck')); + + userEvent.click(screen.getByTestId('recurringEventCheck')); + userEvent.click(screen.getByTestId('recurringEventCheck')); + + userEvent.click(screen.getByTestId('allDayEventCheck')); + + userEvent.click(screen.getByTestId('createEventBtn')); + + await wait(); + + expect(toast.success).toBeCalledWith( + 'Event created and posted successfully.' + ); + }); + + test('Create event works as expected when event is an all day event.', async () => { + const getOrganizationIdSpy = jest + .spyOn(getOrganizationId, 'default') + .mockImplementation(() => { + return ''; + }); + + render( + + + + + + + + + + ); + + await wait(); + + expect(getOrganizationIdSpy).toHaveBeenCalled(); + userEvent.click(screen.getByTestId('createEventModalBtn')); + + const randomEventTitle = 'testEventTitle'; + const randomEventDescription = 'testEventDescription'; + const randomEventLocation = 'testEventLocation'; + + userEvent.type(screen.getByTestId('eventTitleInput'), randomEventTitle); + userEvent.type( + screen.getByTestId('eventDescriptionInput'), + randomEventDescription + ); + userEvent.type( + screen.getByTestId('eventLocationInput'), + randomEventLocation + ); + + userEvent.click(screen.getByTestId('createEventBtn')); + + await wait(); + + expect(toast.success).toBeCalledWith( + 'Event created and posted successfully.' + ); + }); + + test('Switch to calendar view works as expected.', async () => { + const getOrganizationIdSpy = jest + .spyOn(getOrganizationId, 'default') + .mockImplementation(() => { + return ''; + }); + + render( + + + + + + + + + + ); + + await wait(); + expect(getOrganizationIdSpy).toHaveBeenCalled(); + + userEvent.click(screen.getByTestId('modeChangeBtn')); + userEvent.click(screen.getByTestId('modeBtn1')); + + await wait(); + const calenderView = 'Calendar View'; + + expect(screen.queryAllByText(calenderView)).not.toBeNull(); + }); +}); diff --git a/src/screens/UserPortal/Events/Events.tsx b/src/screens/UserPortal/Events/Events.tsx new file mode 100644 index 0000000000..caf1d72fd2 --- /dev/null +++ b/src/screens/UserPortal/Events/Events.tsx @@ -0,0 +1,485 @@ +import React from 'react'; +import OrganizationNavbar from 'components/UserPortal/OrganizationNavbar/OrganizationNavbar'; +import OrganizationSidebar from 'components/UserPortal/OrganizationSidebar/OrganizationSidebar'; +import EventCard from 'components/UserPortal/EventCard/EventCard'; +import UserSidebar from 'components/UserPortal/UserSidebar/UserSidebar'; +import { Button, Dropdown, Form, InputGroup } from 'react-bootstrap'; +import PaginationList from 'components/PaginationList/PaginationList'; +import { ORGANIZATION_EVENTS_CONNECTION } from 'GraphQl/Queries/Queries'; +import { useMutation, useQuery } from '@apollo/client'; +import { SearchOutlined } from '@mui/icons-material'; +import styles from './Events.module.css'; +import { useTranslation } from 'react-i18next'; +import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; +import getOrganizationId from 'utils/getOrganizationId'; +import Modal from 'react-bootstrap/Modal'; +import ReactDatePicker from 'react-datepicker'; +import { CREATE_EVENT_MUTATION } from 'GraphQl/Mutations/mutations'; +import dayjs from 'dayjs'; +import { toast } from 'react-toastify'; +import { errorHandler } from 'utils/errorHandler'; + +interface InterfaceEventCardProps { + id: string; + title: string; + description: string; + location: string; + startDate: string; + endDate: string; + isRegisterable: boolean; + isPublic: boolean; + endTime: string; + startTime: string; + recurring: boolean; + allDay: boolean; + creator: { + firstName: string; + lastName: string; + id: string; + }; + registrants: { + id: string; + }[]; +} + +export default function events(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'userEvents', + }); + + const [page, setPage] = React.useState(0); + const [rowsPerPage, setRowsPerPage] = React.useState(5); + const [events, setEvents] = React.useState([]); + const [filterName, setFilterName] = React.useState(''); + const [mode, setMode] = React.useState(0); + const [showCreateEventModal, setShowCreateEventModal] = React.useState(false); + const [eventTitle, setEventTitle] = React.useState(''); + const [eventDescription, setEventDescription] = React.useState(''); + const [eventLocation, setEventLocation] = React.useState(''); + const [startDate, setStartDate] = React.useState(new Date()); + const [endDate, setEndDate] = React.useState(new Date()); + const [isPublic, setIsPublic] = React.useState(true); + const [isRegisterable, setIsRegisterable] = React.useState(true); + const [isRecurring, setIsRecurring] = React.useState(false); + const [isAllDay, setIsAllDay] = React.useState(true); + const [startTime, setStartTime] = React.useState('08:00:00'); + const [endTime, setEndTime] = React.useState('10:00:00'); + + const organizationId = getOrganizationId(window.location.href); + + const modes = [t('listView'), t('calendarView')]; + + const { data, loading, refetch } = useQuery(ORGANIZATION_EVENTS_CONNECTION, { + variables: { + organization_id: organizationId, + title_contains: '', + }, + }); + + const [create] = useMutation(CREATE_EVENT_MUTATION); + + const createEvent = async (): Promise => { + try { + const { data: createEventData } = await create({ + variables: { + title: eventTitle, + description: eventDescription, + isPublic, + recurring: isRecurring, + isRegisterable: isRegisterable, + organizationId, + startDate: dayjs(startDate).format('YYYY-MM-DD'), + endDate: dayjs(endDate).format('YYYY-MM-DD'), + allDay: isAllDay, + location: eventLocation, + startTime: !isAllDay ? startTime + 'Z' : null, + endTime: !isAllDay ? endTime + 'Z' : null, + }, + }); + + /* istanbul ignore next */ + if (createEventData) { + toast.success(t('eventCreated')); + refetch(); + setEventTitle(''); + setEventDescription(''); + setEventLocation(''); + setStartDate(new Date()); + setEndDate(new Date()); + setStartTime('08:00:00'); + setEndTime('10:00:00'); + } + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + + /* istanbul ignore next */ + const handleChangePage = ( + _event: React.MouseEvent | null, + newPage: number + ): void => { + setPage(newPage); + }; + + const toggleCreateEventModal = (): void => + setShowCreateEventModal(!showCreateEventModal); + + /* istanbul ignore next */ + const handleChangeRowsPerPage = ( + event: React.ChangeEvent + ): void => { + const newRowsPerPage = event.target.value; + + setRowsPerPage(parseInt(newRowsPerPage, 10)); + setPage(0); + }; + + const handleSearch = ( + event: React.ChangeEvent + ): void => { + const newFilter = event.target.value; + setFilterName(newFilter); + const filter = { + title_contains: newFilter, + }; + setPage(0); + refetch(filter); + }; + + const handleEventTitleChange = ( + event: React.ChangeEvent + ): void => { + setEventTitle(event.target.value); + }; + + const handleEventLocationChange = ( + event: React.ChangeEvent + ): void => { + setEventLocation(event.target.value); + }; + + const handleEventDescriptionChange = ( + event: React.ChangeEvent + ): void => { + setEventDescription(event.target.value); + }; + + /* istanbul ignore next */ + const handleStartDateChange = (newDate: any): void => { + setStartDate(newDate); + }; + + /* istanbul ignore next */ + const handleEndDateChange = (newDate: any): void => { + setEndDate(newDate); + }; + + /* istanbul ignore next */ + React.useEffect(() => { + if (data) { + setEvents(data.eventsByOrganizationConnection); + } + }, [data]); + + const navbarProps = { + currentPage: 'events', + }; + + return ( + <> + +
    + +
    +
    + + + + + + +
    + + + + {modes[mode]} + + + {modes.map((value, index) => { + return ( + setMode(index)} + > + {value} + + ); + })} + + +
    +
    +
    +
    + {loading ? ( +
    + Loading... +
    + ) : ( + <> + {events && events.length > 0 ? ( + (rowsPerPage > 0 + ? events.slice( + page * rowsPerPage, + page * rowsPerPage + rowsPerPage + ) + : /* istanbul ignore next */ + events + ).map((event: any) => { + const attendees: any = []; + event.attendees.forEach((attendee: any) => { + const r = { + id: attendee._id, + }; + + attendees.push(r); + }); + + const creator: any = {}; + creator.firstName = event.creator.firstName; + creator.lastName = event.creator.lastName; + creator.id = event.creator._id; + + const cardProps: InterfaceEventCardProps = { + id: event._id, + title: event.title, + description: event.description, + location: event.location, + startDate: event.startDate, + endDate: event.endDate, + isRegisterable: event.isRegisterable, + isPublic: event.isPublic, + endTime: event.endTime, + startTime: event.startTime, + recurring: event.recurring, + allDay: event.allDay, + registrants: attendees, + creator, + }; + + return ; + }) + ) : ( + {t('nothingToShow')} + )} + + )} +
    + + + + + + +
    +
    +
    + + + +
    {t('createEvent')}
    + +
    + + + + {t('eventTitle')} + + + + + + + {t('eventDescription')} + + + + + + + {t('eventLocation')} + + + +
    {t('startDate')}
    + +
    {t('endDate')}
    + +
    +
    + + setIsPublic(!isPublic)} + /> +
    + +
    + + setIsRegisterable(!isRegisterable)} + /> +
    + +
    + + setIsRecurring(!isRecurring)} + /> +
    + +
    + + setIsAllDay(!isAllDay)} + /> +
    + + {!isAllDay && ( +
    +
    + + setStartTime(e.target.value) + } + /> +
    +
    + + setEndTime(e.target.value) + } + /> +
    +
    + )} +
    +
    + + + + +
    +
    + + ); +} diff --git a/src/screens/UserPortal/Home/Home.module.css b/src/screens/UserPortal/Home/Home.module.css new file mode 100644 index 0000000000..48643b3445 --- /dev/null +++ b/src/screens/UserPortal/Home/Home.module.css @@ -0,0 +1,71 @@ +.borderNone { + border: none; +} + +.colorWhite { + color: white; +} + +.maxWidth { + max-width: 300px; +} + +.colorLight { + background-color: #f5f5f5; +} + +.mainContainer { + width: 50%; + flex-grow: 3; + padding: 30px; + max-height: 100%; + overflow: auto; +} + +.containerHeight { + height: calc(100vh - 66px); +} + +.link { + text-decoration: none !important; + color: black; +} + +.postInputContainer { + background-color: white; + padding: 10px; + border-radius: 10px; + margin-bottom: 20px; +} + +.postActionContainer { + display: flex; + flex-direction: row; + justify-content: space-between; + gap: 10px; +} + +.postActionBtn { + background-color: white; + border: none; + color: black; +} + +.postActionBtn:hover { + background-color: ghostwhite; + border: none; + color: black; +} + +.postInput { + height: 200px !important; + resize: none; + border: none; + box-shadow: none; + background-color: white; + margin-bottom: 10px; +} + +.imageInput { + background-color: white; +} diff --git a/src/screens/UserPortal/Home/Home.test.tsx b/src/screens/UserPortal/Home/Home.test.tsx new file mode 100644 index 0000000000..105714cfc8 --- /dev/null +++ b/src/screens/UserPortal/Home/Home.test.tsx @@ -0,0 +1,285 @@ +import React from 'react'; +import { act, render, screen } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider } from 'react-i18next'; + +import { ORGANIZATION_POST_CONNECTION_LIST } from 'GraphQl/Queries/Queries'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import Home from './Home'; +import userEvent from '@testing-library/user-event'; +import * as getOrganizationId from 'utils/getOrganizationId'; +import { CREATE_POST_MUTATION } from 'GraphQl/Mutations/mutations'; +import { toast } from 'react-toastify'; +import dayjs from 'dayjs'; + +jest.mock('react-toastify', () => ({ + toast: { + error: jest.fn(), + info: jest.fn(), + success: jest.fn(), + }, +})); + +const MOCKS = [ + { + request: { + query: ORGANIZATION_POST_CONNECTION_LIST, + variables: { + id: '', + }, + }, + result: { + data: { + postsByOrganizationConnection: { + edges: [ + { + _id: '6411e53835d7ba2344a78e21', + title: 'postone', + text: 'THis is the frist post', + imageUrl: null, + videoUrl: null, + creator: { + _id: '640d98d9eb6a743d75341067', + firstName: 'Aditya', + lastName: 'Shelke', + email: 'adidacreator1@gmail.com', + }, + createdAt: dayjs(new Date()).add(1, 'day'), + likeCount: 0, + commentCount: 0, + comments: [], + likedBy: [], + pinned: false, + }, + { + _id: '6411e54835d7ba2344a78e29', + title: 'posttwo', + text: 'THis is the post two', + imageUrl: null, + videoUrl: null, + creator: { + _id: '640d98d9eb6a743d75341067', + firstName: 'Aditya', + lastName: 'Shelke', + email: 'adidacreator1@gmail.com', + }, + createdAt: dayjs(new Date()).add(1, 'day'), + likeCount: 0, + commentCount: 2, + comments: [ + { + _id: '64eb13beca85de60ebe0ed0e', + creator: { + _id: '63d6064458fce20ee25c3bf7', + firstName: 'Noble', + lastName: 'Mittal', + email: 'test@gmail.com', + __typename: 'User', + }, + likeCount: 1, + likedBy: [ + { + _id: 1, + }, + ], + text: 'First comment from Talawa user portal.', + __typename: 'Comment', + }, + { + _id: '64eb483aca85de60ebe0ef99', + creator: { + _id: '63d6064458fce20ee25c3bf7', + firstName: 'Noble', + lastName: 'Mittal', + email: 'test@gmail.com', + createdAt: '2023-02-18T09:22:27.969Z', + + __typename: 'User', + }, + likeCount: 0, + likedBy: [], + text: 'Great View', + __typename: 'Comment', + }, + ], + likedBy: [ + { + _id: '63d6064458fce20ee25c3bf7', + firstName: 'test', + lastName: 'abc', + }, + ], + pinned: false, + }, + ], + }, + }, + }, + }, + { + request: { + query: CREATE_POST_MUTATION, + variables: { + title: '', + text: 'This is a test', + organizationId: '', + file: '', + }, + result: { + data: { + createPost: { + _id: '453', + }, + }, + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Testing Home Screen [User Portal]', () => { + jest.mock('utils/getOrganizationId'); + + Object.defineProperty(window, 'matchMedia', { + writable: true, + value: jest.fn().mockImplementation((query) => ({ + matches: false, + media: query, + onchange: null, + addListener: jest.fn(), // Deprecated + removeListener: jest.fn(), // Deprecated + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn(), + })), + }); + + test('Screen should be rendered properly', async () => { + const getOrganizationIdSpy = jest + .spyOn(getOrganizationId, 'default') + .mockImplementation(() => { + return ''; + }); + + render( + + + + + + + + + + ); + + await wait(); + + expect(getOrganizationIdSpy).toHaveBeenCalled(); + }); + + test('Screen should be rendered properly when user types on the Post Input', async () => { + const getOrganizationIdSpy = jest + .spyOn(getOrganizationId, 'default') + .mockImplementation(() => { + return ''; + }); + + render( + + + + + + + + + + ); + + await wait(); + + expect(getOrganizationIdSpy).toHaveBeenCalled(); + + const randomPostInput = 'This is a test'; + userEvent.type(screen.getByTestId('postInput'), randomPostInput); + + expect(screen.queryByText(randomPostInput)).toBeInTheDocument(); + }); + + test('Error toast should be visible when user tries to create a post with an empty body', async () => { + const getOrganizationIdSpy = jest + .spyOn(getOrganizationId, 'default') + .mockImplementation(() => { + return ''; + }); + + render( + + + + + + + + + + ); + + await wait(); + + expect(getOrganizationIdSpy).toHaveBeenCalled(); + + userEvent.click(screen.getByTestId('postAction')); + + expect(toast.error).toBeCalledWith( + "Can't create a post with an empty body." + ); + }); + + test('Info toast should be visible when user tries to create a post with a valid body', async () => { + const getOrganizationIdSpy = jest + .spyOn(getOrganizationId, 'default') + .mockImplementation(() => { + return ''; + }); + + render( + + + + + + + + + + ); + + await wait(); + + expect(getOrganizationIdSpy).toHaveBeenCalled(); + + const randomPostInput = 'This is a test'; + userEvent.type(screen.getByTestId('postInput'), randomPostInput); + expect(screen.queryByText(randomPostInput)).toBeInTheDocument(); + + userEvent.click(screen.getByTestId('postAction')); + + expect(toast.error).not.toBeCalledWith(); + expect(toast.info).toBeCalledWith('Processing your post. Please wait.'); + }); +}); diff --git a/src/screens/UserPortal/Home/Home.tsx b/src/screens/UserPortal/Home/Home.tsx new file mode 100644 index 0000000000..ad02e1b26c --- /dev/null +++ b/src/screens/UserPortal/Home/Home.tsx @@ -0,0 +1,291 @@ +import React from 'react'; +import type { ChangeEvent } from 'react'; +import OrganizationNavbar from 'components/UserPortal/OrganizationNavbar/OrganizationNavbar'; +import styles from './Home.module.css'; +import UserSidebar from 'components/UserPortal/UserSidebar/UserSidebar'; +import OrganizationSidebar from 'components/UserPortal/OrganizationSidebar/OrganizationSidebar'; +import ChevronRightIcon from '@mui/icons-material/ChevronRight'; +import { Button, FloatingLabel, Form } from 'react-bootstrap'; +import { Link } from 'react-router-dom'; +import getOrganizationId from 'utils/getOrganizationId'; +import SendIcon from '@mui/icons-material/Send'; +import PostCard from 'components/UserPortal/PostCard/PostCard'; +import { useMutation, useQuery } from '@apollo/client'; +import { + ADVERTISEMENTS_GET, + ORGANIZATION_POST_CONNECTION_LIST, +} from 'GraphQl/Queries/Queries'; +import { CREATE_POST_MUTATION } from 'GraphQl/Mutations/mutations'; +import { errorHandler } from 'utils/errorHandler'; +import { useTranslation } from 'react-i18next'; +import convertToBase64 from 'utils/convertToBase64'; +import { toast } from 'react-toastify'; +import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; +import PromotedPost from 'components/UserPortal/PromotedPost/PromotedPost'; + +interface InterfacePostCardProps { + id: string; + creator: { + firstName: string; + lastName: string; + email: string; + id: string; + }; + image: string; + video: string; + text: string; + title: string; + likeCount: number; + commentCount: number; + comments: { + creator: { + _id: string; + firstName: string; + lastName: string; + email: string; + }; + likeCount: number; + likedBy: { + id: string; + }[]; + text: string; + }[]; + likedBy: { + firstName: string; + lastName: string; + id: string; + }[]; +} + +export default function home(): JSX.Element { + const { t } = useTranslation('translation', { keyPrefix: 'home' }); + + const organizationId = getOrganizationId(window.location.href); + const [posts, setPosts] = React.useState([]); + const [postContent, setPostContent] = React.useState(''); + const [postImage, setPostImage] = React.useState(''); + const currentOrgId = window.location.href.split('/id=')[1] + ''; + const [adContent, setAdContent] = React.useState([]); + + const navbarProps = { + currentPage: 'home', + }; + const { + data: promotedPostsData, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + refetch: _promotedPostsRefetch, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + loading: promotedPostsLoading, + } = useQuery(ADVERTISEMENTS_GET); + const { + data, + refetch, + loading: loadingPosts, + } = useQuery(ORGANIZATION_POST_CONNECTION_LIST, { + variables: { id: organizationId }, + }); + + const [create] = useMutation(CREATE_POST_MUTATION); + + const handlePost = async (): Promise => { + try { + if (!postContent) { + throw new Error("Can't create a post with an empty body."); + } + toast.info('Processing your post. Please wait.'); + + const { data } = await create({ + variables: { + title: '', + text: postContent, + organizationId: organizationId, + file: postImage, + }, + }); + /* istanbul ignore next */ + if (data) { + toast.dismiss(); + toast.success('Your post is now visible in the feed.'); + refetch(); + setPostContent(''); + setPostImage(''); + } + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + + const handlePostInput = (e: ChangeEvent): void => { + const content = e.target.value; + + setPostContent(content); + }; + + React.useEffect(() => { + if (data) { + setPosts(data.postsByOrganizationConnection.edges); + } + }, [data]); + + React.useEffect(() => { + if (promotedPostsData) { + setAdContent(promotedPostsData.getAdvertisements); + } + }, [data]); + + return ( + <> + +
    + +
    +
    + + + +
    + => { + const target = e.target as HTMLInputElement; + const file = target.files && target.files[0]; + if (file) { + const image = await convertToBase64(file); + setPostImage(image); + } + } + } + /> + +
    +
    +
    +

    {t('feed')}

    +
    + + {t('pinnedPosts')} + + +
    +
    + {adContent + .filter((ad: any) => ad.orgId == currentOrgId) + .filter((ad: any) => new Date(ad.endDate) > new Date()).length == 0 + ? '' + : adContent + .filter((ad: any) => ad.orgId == currentOrgId) + .filter((ad: any) => new Date(ad.endDate) > new Date()) + .map((post: any) => ( + + ))} + {loadingPosts ? ( +
    + Loading... +
    + ) : ( + <> + {posts.map((post: any) => { + const allLikes: any = []; + post.likedBy.forEach((value: any) => { + const singleLike = { + firstName: value.firstName, + lastName: value.lastName, + id: value._id, + }; + allLikes.push(singleLike); + }); + + const postComments: any = []; + post.comments.forEach((value: any) => { + const commentLikes: any = []; + + value.likedBy.forEach((commentLike: any) => { + const singleLike = { + id: commentLike._id, + }; + commentLikes.push(singleLike); + }); + + const singleCommnet: any = { + id: value._id, + creator: { + firstName: value.creator.firstName, + lastName: value.creator.lastName, + id: value.creator._id, + email: value.creator.email, + }, + likeCount: value.likeCount, + likedBy: commentLikes, + text: value.text, + }; + + postComments.push(singleCommnet); + }); + + const cardProps: InterfacePostCardProps = { + id: post._id, + creator: { + id: post.creator._id, + firstName: post.creator.firstName, + lastName: post.creator.lastName, + email: post.creator.email, + }, + image: post.imageUrl, + video: post.videoUrl, + title: post.title, + text: post.text, + likeCount: post.likeCount, + commentCount: post.commentCount, + comments: postComments, + likedBy: allLikes, + }; + + return ; + })} + + )} +
    + +
    + + ); +} diff --git a/src/screens/UserPortal/Organizations/Organizations.module.css b/src/screens/UserPortal/Organizations/Organizations.module.css new file mode 100644 index 0000000000..1f49c0d158 --- /dev/null +++ b/src/screens/UserPortal/Organizations/Organizations.module.css @@ -0,0 +1,48 @@ +.borderNone { + border: none; +} + +.colorWhite { + color: white; +} + +.maxWidth { + max-width: 300px; +} + +.colorLight { + background-color: #f5f5f5; +} + +.mainContainer { + width: 50%; + flex-grow: 3; + padding: 40px; + max-height: 100%; + overflow: auto; +} + +.content { + height: fit-content; + min-height: calc(100% - 40px); +} + +.gap { + gap: 20px; +} + +.paddingY { + padding: 30px 0px; +} + +.containerHeight { + height: calc(100vh - 66px); +} + +.colorPrimary { + background: #31bb6b; +} + +.backgroundWhite { + background-color: white; +} diff --git a/src/screens/UserPortal/Organizations/Organizations.test.tsx b/src/screens/UserPortal/Organizations/Organizations.test.tsx new file mode 100644 index 0000000000..6d92831940 --- /dev/null +++ b/src/screens/UserPortal/Organizations/Organizations.test.tsx @@ -0,0 +1,221 @@ +import React from 'react'; +import { act, render, screen } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider } from 'react-i18next'; + +import { + USER_CREATED_ORGANIZATIONS, + USER_JOINED_ORGANIZATIONS, + USER_ORGANIZATION_CONNECTION, +} from 'GraphQl/Queries/Queries'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import Organizations from './Organizations'; +import userEvent from '@testing-library/user-event'; + +const MOCKS = [ + { + request: { + query: USER_CREATED_ORGANIZATIONS, + variables: { + id: localStorage.getItem('userId'), + }, + }, + result: { + data: { + users: [ + { + createdOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + name: 'createdOrganization', + image: '', + description: 'New Desc', + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: USER_ORGANIZATION_CONNECTION, + variables: { + filter: '', + }, + }, + result: { + data: { + organizationsConnection: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + image: '', + name: 'anyOrganization1', + description: 'desc', + isPublic: true, + creator: { __typename: 'User', firstName: 'John', lastName: 'Doe' }, + }, + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af3', + image: '', + name: 'anyOrganization2', + description: 'desc', + isPublic: true, + creator: { __typename: 'User', firstName: 'John', lastName: 'Doe' }, + }, + ], + }, + }, + }, + { + request: { + query: USER_JOINED_ORGANIZATIONS, + variables: { + id: localStorage.getItem('userId'), + }, + }, + result: { + data: { + users: [ + { + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + name: 'joinedOrganization', + image: '', + description: 'New Desc', + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: USER_ORGANIZATION_CONNECTION, + variables: { + filter: '2', + }, + }, + result: { + data: { + organizationsConnection: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af3', + image: '', + name: 'anyOrganization2', + description: 'desc', + isPublic: true, + creator: { __typename: 'User', firstName: 'John', lastName: 'Doe' }, + }, + ], + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Testing Organizations Screen [User Portal]', () => { + test('Screen should be rendered properly', async () => { + render( + + + + + + + + + + ); + + await wait(); + }); + + test('Search works properly', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.type(screen.getByTestId('searchInput'), '2'); + await wait(); + + expect(screen.queryByText('anyOrganization2')).toBeInTheDocument(); + expect(screen.queryByText('anyOrganization1')).not.toBeInTheDocument(); + }); + + test('Mode is changed to joined organizations', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('modeChangeBtn')); + await wait(); + userEvent.click(screen.getByTestId('modeBtn1')); + await wait(); + + expect(screen.queryAllByText('joinedOrganization')).not.toBe([]); + }); + + test('Mode is changed to created organizations', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('modeChangeBtn')); + await wait(); + userEvent.click(screen.getByTestId('modeBtn2')); + await wait(); + + expect(screen.queryAllByText('createdOrganization')).not.toBe([]); + }); +}); diff --git a/src/screens/UserPortal/Organizations/Organizations.tsx b/src/screens/UserPortal/Organizations/Organizations.tsx new file mode 100644 index 0000000000..c0b77f805e --- /dev/null +++ b/src/screens/UserPortal/Organizations/Organizations.tsx @@ -0,0 +1,221 @@ +import React from 'react'; +import UserNavbar from 'components/UserPortal/UserNavbar/UserNavbar'; +import OrganizationCard from 'components/UserPortal/OrganizationCard/OrganizationCard'; +import UserSidebar from 'components/UserPortal/UserSidebar/UserSidebar'; +import { Dropdown, Form, InputGroup } from 'react-bootstrap'; +import PaginationList from 'components/PaginationList/PaginationList'; +import { + USER_CREATED_ORGANIZATIONS, + USER_JOINED_ORGANIZATIONS, + USER_ORGANIZATION_CONNECTION, +} from 'GraphQl/Queries/Queries'; +import { useQuery } from '@apollo/client'; +import { SearchOutlined } from '@mui/icons-material'; +import styles from './Organizations.module.css'; +import { useTranslation } from 'react-i18next'; +import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; + +interface InterfaceOrganizationCardProps { + id: string; + name: string; + image: string; + description: string; +} +export default function organizations(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'userOrganizations', + }); + + const [page, setPage] = React.useState(0); + const [rowsPerPage, setRowsPerPage] = React.useState(5); + const [organizations, setOrganizations] = React.useState([]); + const [filterName, setFilterName] = React.useState(''); + const [mode, setMode] = React.useState(0); + + const modes = [ + t('allOrganizations'), + t('joinedOrganizations'), + t('createdOrganizations'), + ]; + + const userId: string | null = localStorage.getItem('userId'); + + const { + data, + refetch, + loading: loadingOrganizations, + } = useQuery(USER_ORGANIZATION_CONNECTION, { + variables: { filter: filterName }, + }); + + const { data: data2 } = useQuery(USER_JOINED_ORGANIZATIONS, { + variables: { id: userId }, + }); + + const { data: data3 } = useQuery(USER_CREATED_ORGANIZATIONS, { + variables: { id: userId }, + }); + + /* istanbul ignore next */ + const handleChangePage = ( + _event: React.MouseEvent | null, + newPage: number + ): void => { + setPage(newPage); + }; + + /* istanbul ignore next */ + const handleChangeRowsPerPage = ( + event: React.ChangeEvent + ): void => { + const newRowsPerPage = event.target.value; + + setRowsPerPage(parseInt(newRowsPerPage, 10)); + setPage(0); + }; + + const handleSearch = ( + event: React.ChangeEvent + ): void => { + const newFilter = event.target.value; + setFilterName(newFilter); + + const filter = { + filter: newFilter, + }; + + refetch(filter); + }; + + /* istanbul ignore next */ + React.useEffect(() => { + if (data) { + setOrganizations(data.organizationsConnection); + } + }, [data]); + + /* istanbul ignore next */ + React.useEffect(() => { + if (mode == 0) { + if (data) { + setOrganizations(data.organizationsConnection); + } + } else if (mode == 1) { + if (data2) { + setOrganizations(data2.users[0].joinedOrganizations); + } + } else if (mode == 2) { + if (data3) { + setOrganizations(data3.users[0].createdOrganizations); + } + } + }, [mode]); + + return ( + <> + +
    + +
    +

    {t('selectOrganization')}

    +
    + + + + + + + + + {modes[mode]} + + + {modes.map((value, index) => { + return ( + setMode(index)} + > + {value} + + ); + })} + + +
    + +
    +
    + {loadingOrganizations ? ( +
    + Loading... +
    + ) : ( + <> + {' '} + {organizations && organizations.length > 0 ? ( + (rowsPerPage > 0 + ? organizations.slice( + page * rowsPerPage, + page * rowsPerPage + rowsPerPage + ) + : /* istanbul ignore next */ + organizations + ).map((organization: any, index) => { + const cardProps: InterfaceOrganizationCardProps = { + name: organization.name, + image: organization.image, + id: organization._id, + description: organization.description, + }; + return ; + }) + ) : ( + {t('nothingToShow')} + )} + + )} +
    + + + + + + +
    +
    +
    +
    + + ); +} diff --git a/src/screens/UserPortal/People/People.module.css b/src/screens/UserPortal/People/People.module.css new file mode 100644 index 0000000000..f67df3b23f --- /dev/null +++ b/src/screens/UserPortal/People/People.module.css @@ -0,0 +1,48 @@ +.borderNone { + border: none; +} + +.colorWhite { + color: white; +} + +.backgroundWhite { + background-color: white; +} + +.maxWidth { + max-width: 300px; +} + +.colorLight { + background-color: #f5f5f5; +} + +.mainContainer { + width: 50%; + flex-grow: 3; + padding: 40px; + max-height: 100%; + overflow: auto; +} + +.content { + height: fit-content; + min-height: calc(100% - 40px); +} + +.gap { + gap: 20px; +} + +.paddingY { + padding: 30px 0px; +} + +.containerHeight { + height: calc(100vh - 66px); +} + +.colorPrimary { + background: #31bb6b; +} diff --git a/src/screens/UserPortal/People/People.test.tsx b/src/screens/UserPortal/People/People.test.tsx new file mode 100644 index 0000000000..b373a68e98 --- /dev/null +++ b/src/screens/UserPortal/People/People.test.tsx @@ -0,0 +1,206 @@ +import React from 'react'; +import { act, render, screen } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider } from 'react-i18next'; + +import { + ORGANIZATIONS_MEMBER_CONNECTION_LIST, + ORGANIZATION_ADMINS_LIST, +} from 'GraphQl/Queries/Queries'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import People from './People'; +import userEvent from '@testing-library/user-event'; +import * as getOrganizationId from 'utils/getOrganizationId'; + +const MOCKS = [ + { + request: { + query: ORGANIZATIONS_MEMBER_CONNECTION_LIST, + variables: { + orgId: '', + firstName_contains: '', + }, + }, + result: { + data: { + organizationsMemberConnection: { + edges: [ + { + _id: '64001660a711c62d5b4076a2', + firstName: 'Noble', + lastName: 'Mittal', + image: null, + email: 'noble@gmail.com', + createdAt: '2023-03-02T03:22:08.101Z', + }, + { + _id: '64001660a711c62d5b4076a3', + firstName: 'Noble', + lastName: 'Mittal', + image: 'mockImage', + email: 'noble@gmail.com', + createdAt: '2023-03-02T03:22:08.101Z', + }, + ], + }, + }, + }, + }, + { + request: { + query: ORGANIZATION_ADMINS_LIST, + variables: { + id: '', + }, + }, + result: { + data: { + organizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + admins: [ + { + _id: '64001660a711c62d5b4076a2', + firstName: 'Noble', + lastName: 'Admin', + image: null, + email: 'noble@gmail.com', + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: ORGANIZATIONS_MEMBER_CONNECTION_LIST, + variables: { + orgId: '', + firstName_contains: 'j', + }, + }, + result: { + data: { + organizationsMemberConnection: { + edges: [ + { + _id: '64001660a711c62d5b4076a2', + firstName: 'John', + lastName: 'Cena', + image: null, + email: 'john@gmail.com', + createdAt: '2023-03-02T03:22:08.101Z', + }, + ], + }, + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Testing People Screen [User Portal]', () => { + jest.mock('utils/getOrganizationId'); + + Object.defineProperty(window, 'matchMedia', { + writable: true, + value: jest.fn().mockImplementation((query) => ({ + matches: false, + media: query, + onchange: null, + addListener: jest.fn(), // Deprecated + removeListener: jest.fn(), // Deprecated + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn(), + })), + }); + + const getOrganizationIdSpy = jest + .spyOn(getOrganizationId, 'default') + .mockImplementation(() => { + return ''; + }); + + test('Screen should be rendered properly', async () => { + render( + + + + + + + + + + ); + + await wait(); + + expect(getOrganizationIdSpy).toHaveBeenCalled(); + expect(screen.queryAllByText('Noble Mittal')).not.toBe([]); + }); + + test('Search works properly', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.type(screen.getByTestId('searchInput'), 'j'); + await wait(); + + expect(getOrganizationIdSpy).toHaveBeenCalled(); + expect(screen.queryByText('John Cena')).toBeInTheDocument(); + expect(screen.queryByText('Noble Mittal')).not.toBeInTheDocument(); + }); + + test('Mode is changed to Admins', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('modeChangeBtn')); + await wait(); + userEvent.click(screen.getByTestId('modeBtn1')); + await wait(); + + expect(getOrganizationIdSpy).toHaveBeenCalled(); + expect(screen.queryByText('Noble Admin')).toBeInTheDocument(); + expect(screen.queryByText('Noble Mittal')).not.toBeInTheDocument(); + }); +}); diff --git a/src/screens/UserPortal/People/People.tsx b/src/screens/UserPortal/People/People.tsx new file mode 100644 index 0000000000..f8b4d7ca3d --- /dev/null +++ b/src/screens/UserPortal/People/People.tsx @@ -0,0 +1,217 @@ +import React from 'react'; +import OrganizationNavbar from 'components/UserPortal/OrganizationNavbar/OrganizationNavbar'; +import OrganizationSidebar from 'components/UserPortal/OrganizationSidebar/OrganizationSidebar'; +import PeopleCard from 'components/UserPortal/PeopleCard/PeopleCard'; +import UserSidebar from 'components/UserPortal/UserSidebar/UserSidebar'; +import { Dropdown, Form, InputGroup } from 'react-bootstrap'; +import PaginationList from 'components/PaginationList/PaginationList'; +import { + ORGANIZATIONS_MEMBER_CONNECTION_LIST, + ORGANIZATION_ADMINS_LIST, +} from 'GraphQl/Queries/Queries'; +import { useQuery } from '@apollo/client'; +import { SearchOutlined } from '@mui/icons-material'; +import styles from './People.module.css'; +import { useTranslation } from 'react-i18next'; +import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; +import getOrganizationId from 'utils/getOrganizationId'; + +interface InterfaceOrganizationCardProps { + id: string; + name: string; + image: string; + email: string; +} + +export default function people(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'userOrganizations', + }); + + const [page, setPage] = React.useState(0); + const [rowsPerPage, setRowsPerPage] = React.useState(5); + const [members, setMembers] = React.useState([]); + const [filterName, setFilterName] = React.useState(''); + const [mode, setMode] = React.useState(0); + + const organizationId = getOrganizationId(window.location.href); + + const modes = ['All Members', 'Admins']; + + const { data, loading, refetch } = useQuery( + ORGANIZATIONS_MEMBER_CONNECTION_LIST, + { + variables: { + orgId: organizationId, + firstName_contains: '', + }, + } + ); + + const { data: data2 } = useQuery(ORGANIZATION_ADMINS_LIST, { + variables: { id: organizationId }, + }); + + /* istanbul ignore next */ + const handleChangePage = ( + _event: React.MouseEvent | null, + newPage: number + ): void => { + setPage(newPage); + }; + + /* istanbul ignore next */ + const handleChangeRowsPerPage = ( + event: React.ChangeEvent + ): void => { + const newRowsPerPage = event.target.value; + + setRowsPerPage(parseInt(newRowsPerPage, 10)); + setPage(0); + }; + + const handleSearch = ( + event: React.ChangeEvent + ): void => { + const newFilter = event.target.value; + setFilterName(newFilter); + + const filter = { + firstName_contains: newFilter, + }; + + refetch(filter); + }; + + /* istanbul ignore next */ + React.useEffect(() => { + if (data) { + setMembers(data.organizationsMemberConnection.edges); + } + }, [data]); + + /* istanbul ignore next */ + React.useEffect(() => { + if (mode == 0) { + if (data) { + setMembers(data.organizationsMemberConnection.edges); + } + } else if (mode == 1) { + if (data2) { + setMembers(data2.organizations[0].admins); + } + } + }, [mode]); + + const navbarProps = { + currentPage: 'people', + }; + + return ( + <> + +
    + +
    +
    + + + + + + + + + {modes[mode]} + + + {modes.map((value, index) => { + return ( + setMode(index)} + > + {value} + + ); + })} + + +
    +
    +
    + {loading ? ( +
    + Loading... +
    + ) : ( + <> + {members && members.length > 0 ? ( + (rowsPerPage > 0 + ? members.slice( + page * rowsPerPage, + page * rowsPerPage + rowsPerPage + ) + : /* istanbul ignore next */ + members + ).map((member: any, index) => { + const name = `${member.firstName} ${member.lastName}`; + + const cardProps: InterfaceOrganizationCardProps = { + name, + image: member.image, + id: member._id, + email: member.email, + }; + return ; + }) + ) : ( + {t('nothingToShow')} + )} + + )} +
    + + + + + + +
    +
    +
    + +
    + + ); +} diff --git a/src/screens/UserPortal/Settings/Settings.module.css b/src/screens/UserPortal/Settings/Settings.module.css new file mode 100644 index 0000000000..c8ca1e6091 --- /dev/null +++ b/src/screens/UserPortal/Settings/Settings.module.css @@ -0,0 +1,26 @@ +.mainContainer { + width: 50%; + flex-grow: 3; + padding: 40px; + max-height: 100%; + overflow: auto; +} + +.containerHeight { + height: calc(100vh - 66px); +} + +.content { + display: flex; + flex-direction: column; + max-width: 300px; + gap: 15px; +} + +.imageInput { + background-color: white; +} + +.colorLight { + background-color: white; +} diff --git a/src/screens/UserPortal/Settings/Settings.test.tsx b/src/screens/UserPortal/Settings/Settings.test.tsx new file mode 100644 index 0000000000..faec179acc --- /dev/null +++ b/src/screens/UserPortal/Settings/Settings.test.tsx @@ -0,0 +1,139 @@ +import React from 'react'; +import { act, render, screen } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider } from 'react-i18next'; + +import { UPDATE_USER_MUTATION } from 'GraphQl/Mutations/mutations'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import Settings from './Settings'; +import userEvent from '@testing-library/user-event'; + +const MOCKS = [ + { + request: { + query: UPDATE_USER_MUTATION, + variables: { + firstName: 'Noble', + lastName: 'Mittal', + }, + result: { + data: { + updateUserProfile: { + _id: '453', + }, + }, + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Testing Settings Screen [User Portal]', () => { + Object.defineProperty(window, 'matchMedia', { + writable: true, + value: jest.fn().mockImplementation((query) => ({ + matches: false, + media: query, + onchange: null, + addListener: jest.fn(), // Deprecated + removeListener: jest.fn(), // Deprecated + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn(), + })), + }); + + test('Screen should be rendered properly', async () => { + render( + + + + + + + + + + ); + + await wait(); + + expect(screen.queryAllByText('Settings')).not.toBe([]); + }); + + test('First name input works properly', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.type(screen.getByTestId('inputFirstName'), 'Noble'); + await wait(); + }); + + test('Last name input works properly', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.type(screen.getByTestId('inputLastName'), 'Mittal'); + await wait(); + }); + + test('updateUserDetails Mutation is triggered on button click', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.type(screen.getByTestId('inputFirstName'), 'Noble'); + await wait(); + + userEvent.type(screen.getByTestId('inputLastName'), 'Mittal'); + await wait(); + + userEvent.click(screen.getByTestId('updateUserBtn')); + await wait(); + }); +}); diff --git a/src/screens/UserPortal/Settings/Settings.tsx b/src/screens/UserPortal/Settings/Settings.tsx new file mode 100644 index 0000000000..35afd78790 --- /dev/null +++ b/src/screens/UserPortal/Settings/Settings.tsx @@ -0,0 +1,144 @@ +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import styles from './Settings.module.css'; +import UserSidebar from 'components/UserPortal/UserSidebar/UserSidebar'; +import UserNavbar from 'components/UserPortal/UserNavbar/UserNavbar'; +import { Button, Form } from 'react-bootstrap'; +import convertToBase64 from 'utils/convertToBase64'; +import { UPDATE_USER_MUTATION } from 'GraphQl/Mutations/mutations'; +import { useMutation, useQuery } from '@apollo/client'; +import { errorHandler } from 'utils/errorHandler'; +import { toast } from 'react-toastify'; +import { CHECK_AUTH } from 'GraphQl/Queries/Queries'; + +export default function settings(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'settings', + }); + + const { data } = useQuery(CHECK_AUTH); + const [image, setImage] = React.useState(''); + const [updateUserDetails] = useMutation(UPDATE_USER_MUTATION); + const [firstName, setFirstName] = React.useState(''); + const [lastName, setLastName] = React.useState(''); + const [email, setEmail] = React.useState(''); + + const handleUpdateUserDetails = async (): Promise => { + let variables: any = { + firstName, + lastName, + }; + + /* istanbul ignore next */ + if (image) { + variables = { + ...variables, + file: image, + }; + } + try { + const { data } = await updateUserDetails({ + variables, + }); + + /* istanbul ignore next */ + if (data) { + setImage(''); + toast.success('Your details have been updated.'); + setTimeout(() => { + window.location.reload(); + }, 500); + + const userFullName = `${firstName} ${lastName}`; + localStorage.setItem('name', userFullName); + } + } catch (error: any) { + errorHandler(t, error); + } + }; + + const handleFirstNameChange = (e: any): void => { + const { value } = e.target; + setFirstName(value); + }; + + const handleLastNameChange = (e: any): void => { + const { value } = e.target; + setLastName(value); + }; + + React.useEffect(() => { + /* istanbul ignore next */ + if (data) { + setFirstName(data.checkAuth.firstName); + setLastName(data.checkAuth.lastName); + setEmail(data.checkAuth.email); + } + }, [data]); + + return ( + <> + +
    + +
    +

    {t('profileSettings')}

    +
    + {t('firstName')} + + {t('lastName')} + + {t('emailAddress')} + + {t('updateImage')} + => { + const target = e.target as HTMLInputElement; + const file = target.files && target.files[0]; + if (file) { + const image = await convertToBase64(file); + setImage(image); + } + } + } + /> + +
    +
    +
    + + ); +} diff --git a/src/screens/UserPortal/Tasks/Tasks.module.css b/src/screens/UserPortal/Tasks/Tasks.module.css new file mode 100644 index 0000000000..1f49c0d158 --- /dev/null +++ b/src/screens/UserPortal/Tasks/Tasks.module.css @@ -0,0 +1,48 @@ +.borderNone { + border: none; +} + +.colorWhite { + color: white; +} + +.maxWidth { + max-width: 300px; +} + +.colorLight { + background-color: #f5f5f5; +} + +.mainContainer { + width: 50%; + flex-grow: 3; + padding: 40px; + max-height: 100%; + overflow: auto; +} + +.content { + height: fit-content; + min-height: calc(100% - 40px); +} + +.gap { + gap: 20px; +} + +.paddingY { + padding: 30px 0px; +} + +.containerHeight { + height: calc(100vh - 66px); +} + +.colorPrimary { + background: #31bb6b; +} + +.backgroundWhite { + background-color: white; +} diff --git a/src/screens/UserPortal/Tasks/Tasks.test.tsx b/src/screens/UserPortal/Tasks/Tasks.test.tsx new file mode 100644 index 0000000000..208a1ca4e8 --- /dev/null +++ b/src/screens/UserPortal/Tasks/Tasks.test.tsx @@ -0,0 +1,130 @@ +import React from 'react'; +import { act, render, screen } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider } from 'react-i18next'; + +import { UPDATE_USER_MUTATION } from 'GraphQl/Mutations/mutations'; +import { USER_TASKS_LIST } from 'GraphQl/Queries/Queries'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import Tasks from './Tasks'; + +const MOCKS = [ + { + request: { + query: UPDATE_USER_MUTATION, + variables: { + firstName: 'Noble', + lastName: 'Mittal', + }, + result: { + data: { + updateUserProfile: { + _id: '453', + }, + }, + }, + }, + }, + { + request: { + query: USER_TASKS_LIST, + variables: { + id: localStorage.getItem('userId'), + }, + }, + result: { + data: { + user: { + _id: '63d6064458fce20ee25c3bf7', + assignedTasks: [ + { + _id: '650c440f2b5f121b9ceeaa88', + title: 'Volunteer catering system', + description: 'Lorem ipsum dolor sit amet', + deadline: '2023-09-28T16:25:47.000Z', + volunteers: [ + { + _id: '63d6064458fce20ee25c3bf7', + firstName: 'Noble', + lastName: 'Mittal', + email: 'test@gmail.com', + __typename: 'User', + }, + ], + createdAt: '2023-09-21T13:24:31.217Z', + completed: false, + event: { + _id: '650982592328d374ba2881bc', + title: 'sadas', + organization: { + _id: '6493e4570ee6c913d7199291', + name: 'Test Organization', + image: null, + __typename: 'Organization', + }, + __typename: 'Event', + }, + creator: { + _id: '63d6064458fce20ee25c3bf7', + firstName: 'Noble', + lastName: 'Mittal', + __typename: 'User', + }, + __typename: 'Task', + }, + ], + __typename: 'User', + }, + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Testing Tasks Screen [User Portal]', () => { + // Mocks required for media queries for UserNavbar + Object.defineProperty(window, 'matchMedia', { + writable: true, + value: jest.fn().mockImplementation((query) => ({ + matches: false, + media: query, + onchange: null, + addListener: jest.fn(), // Deprecated + removeListener: jest.fn(), // Deprecated + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn(), + })), + }); + + test('Screen should be rendered properly', async () => { + render( + + + + + + + + + + ); + + await wait(); + + expect(screen.queryAllByText('Your assigned tasks')).not.toBe([]); + }); +}); diff --git a/src/screens/UserPortal/Tasks/Tasks.tsx b/src/screens/UserPortal/Tasks/Tasks.tsx new file mode 100644 index 0000000000..af02593b38 --- /dev/null +++ b/src/screens/UserPortal/Tasks/Tasks.tsx @@ -0,0 +1,173 @@ +import React from 'react'; +import UserNavbar from 'components/UserPortal/UserNavbar/UserNavbar'; +import TaskCard from 'components/UserPortal/TaskCard/TaskCard'; +import UserSidebar from 'components/UserPortal/UserSidebar/UserSidebar'; +import PaginationList from 'components/PaginationList/PaginationList'; +import { USER_TASKS_LIST } from 'GraphQl/Queries/Queries'; +import { useQuery } from '@apollo/client'; +import styles from './Tasks.module.css'; +import { useTranslation } from 'react-i18next'; +import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; + +interface InterfaceTaskCardProps { + id: string; + title: string; + deadline: string; + description: string; + volunteers: { + id: string; + firstName: string; + lastName: string; + email: string; + }[]; + creator: { + id: string; + firstName: string; + lastName: string; + }; + event: { + id: string; + title: string; + organization: { + id: string; + name: string; + image: string | null; + }; + }; + createdAt: string; + completed: boolean; +} + +export default function tasks(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'userTasks', + }); + + const [page, setPage] = React.useState(0); + const [rowsPerPage, setRowsPerPage] = React.useState(5); + const [tasks, setTasks] = React.useState([]); + + const userId: string | null = localStorage.getItem('userId'); + + const { data: tasksData, loading: loadingTasks } = useQuery(USER_TASKS_LIST, { + variables: { id: userId }, + }); + + /* istanbul ignore next */ + const handleChangePage = ( + _event: React.MouseEvent | null, + newPage: number + ): void => { + setPage(newPage); + }; + + /* istanbul ignore next */ + const handleChangeRowsPerPage = ( + event: React.ChangeEvent + ): void => { + const newRowsPerPage = event.target.value; + + setRowsPerPage(parseInt(newRowsPerPage, 10)); + setPage(0); + }; + + /* istanbul ignore next */ + React.useEffect(() => { + if (tasksData) { + setTasks(tasksData.user.assignedTasks); + } + }, [tasksData]); + + return ( + <> + +
    + +
    +

    {t('yourAssignedTasks')}

    +
    +
    + {loadingTasks ? ( +
    + Loading... +
    + ) : ( + <> + {tasks && tasks.length > 0 ? ( + (rowsPerPage > 0 + ? tasks.slice( + page * rowsPerPage, + page * rowsPerPage + rowsPerPage + ) + : /* istanbul ignore next */ + tasks + ).map((task: any, index) => { + const volunteers: any = task.volunteers.map( + (volunteer: any) => { + return { + id: volunteer._id, + firstName: volunteer.firstName, + lastName: volunteer.lastName, + email: volunteer.email, + }; + } + ); + + const cardProps: InterfaceTaskCardProps = { + title: task.title, + id: task._id, + description: task.description, + deadline: task.deadline, + volunteers, + createdAt: task.createdAt, + completed: task.completed, + creator: { + id: task.creator._id, + firstName: task.creator.firstName, + lastName: task.creator.lastName, + }, + event: { + id: task.event._id, + title: task.event.title, + organization: { + id: task.event.organization._id, + name: task.event.organization.name, + image: task.event.organization.image, + }, + }, + }; + + return ; + }) + ) : ( + {t('nothingToShow')} + )} + + )} +
    + + + + + + +
    +
    +
    +
    + + ); +} diff --git a/src/screens/UserPortal/UserLoginPage/UserLoginPage.module.css b/src/screens/UserPortal/UserLoginPage/UserLoginPage.module.css new file mode 100644 index 0000000000..840ceb8a0b --- /dev/null +++ b/src/screens/UserPortal/UserLoginPage/UserLoginPage.module.css @@ -0,0 +1,48 @@ +body::before { + content: none !important; +} + +.leftPane { + align-items: center; + width: 60%; + min-width: 300px; + display: flex; + flex-direction: column; + justify-content: center; +} + +.palisadoesImage { + width: 100%; + height: auto; + max-width: 700px; +} + +.talawaImage { + width: 40%; + height: auto; + margin-left: 50%; + transform: translateX(-50%); +} + +.mainContainer { + display: flex; + flex-direction: row; + flex-wrap: wrap; + gap: 10px; + min-height: 100vh; +} + +.contentContainer { + flex-grow: 1; + display: flex; + flex-direction: column; + justify-content: center; + padding: 20px 50px; + background-color: var(--bs-white); +} + +@media only screen and (max-width: 800px) { + .leftPane { + width: 100%; + } +} diff --git a/src/screens/UserPortal/UserLoginPage/UserLoginPage.test.tsx b/src/screens/UserPortal/UserLoginPage/UserLoginPage.test.tsx new file mode 100644 index 0000000000..d60e37c682 --- /dev/null +++ b/src/screens/UserPortal/UserLoginPage/UserLoginPage.test.tsx @@ -0,0 +1,39 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { act, render } from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18nForTest from 'utils/i18nForTest'; + +import UserLoginPage from './UserLoginPage'; + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +const link = new StaticMockLink([], true); + +describe('Testing User Login Page Screen [User Portal]', () => { + test('Screen should be rendered properly', async () => { + render( + + + + + + + + + + ); + + await wait(); + }); +}); diff --git a/src/screens/UserPortal/UserLoginPage/UserLoginPage.tsx b/src/screens/UserPortal/UserLoginPage/UserLoginPage.tsx new file mode 100644 index 0000000000..ca4915d691 --- /dev/null +++ b/src/screens/UserPortal/UserLoginPage/UserLoginPage.tsx @@ -0,0 +1,49 @@ +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +import PalisadoesImage from 'assets/images/palisadoes_logo.png'; +import TalawaImage from 'assets/images/talawa-logo-200x200.png'; +import ChangeLanguageDropDown from 'components/ChangeLanguageDropdown/ChangeLanguageDropDown'; +import Login from 'components/UserPortal/Login/Login'; +import Register from 'components/UserPortal/Register/Register'; +import styles from './UserLoginPage.module.css'; + +export default function userLoginPage(): JSX.Element { + const { t } = useTranslation('translation', { keyPrefix: 'loginPage' }); + + const [currentMode, setCurrentMode] = React.useState('login'); + const loginRegisterProps = { + setCurrentMode: setCurrentMode, + }; + + return ( +
    +
    + Palisadoes Branding +
    +

    {t('fromPalisadoes')}

    +
    +
    +
    + + Talawa Branding + { + /* istanbul ignore next */ + currentMode === 'login' ? ( + + ) : ( + + ) + } +
    +
    + ); +} diff --git a/src/screens/Users/Users.module.css b/src/screens/Users/Users.module.css new file mode 100644 index 0000000000..0750dba108 --- /dev/null +++ b/src/screens/Users/Users.module.css @@ -0,0 +1,95 @@ +.btnsContainer { + display: flex; + margin: 2.5rem 0 2.5rem 0; +} + +.btnsContainer .btnsBlock { + display: flex; +} + +.btnsContainer .btnsBlock button { + margin-left: 1rem; + display: flex; + justify-content: center; + align-items: center; +} + +.btnsContainer .inputContainer { + flex: 1; + position: relative; +} +.btnsContainer .input { + width: 70%; + position: relative; +} + +.btnsContainer input { + outline: 1px solid var(--bs-gray-400); +} + +.btnsContainer .inputContainer button { + width: 52px; +} + +.listBox { + width: 100%; + flex: 1; +} + +.notFound { + flex: 1; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; +} + +@media (max-width: 1020px) { + .btnsContainer { + flex-direction: column; + margin: 1.5rem 0; + } + .btnsContainer .input { + width: 100%; + } + .btnsContainer .btnsBlock { + margin: 1.5rem 0 0 0; + justify-content: space-between; + } + + .btnsContainer .btnsBlock button { + margin: 0; + } + + .btnsContainer .btnsBlock div button { + margin-right: 1.5rem; + } +} + +/* For mobile devices */ + +@media (max-width: 520px) { + .btnsContainer { + margin-bottom: 0; + } + + .btnsContainer .btnsBlock { + display: block; + margin-top: 1rem; + margin-right: 0; + } + + .btnsContainer .btnsBlock div { + flex: 1; + } + + .btnsContainer .btnsBlock div[title='Sort organizations'] { + margin-right: 0.5rem; + } + + .btnsContainer .btnsBlock button { + margin-bottom: 1rem; + margin-right: 0; + width: 100%; + } +} diff --git a/src/screens/Users/Users.test.tsx b/src/screens/Users/Users.test.tsx new file mode 100644 index 0000000000..4484518529 --- /dev/null +++ b/src/screens/Users/Users.test.tsx @@ -0,0 +1,216 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { act, fireEvent, render, screen } from '@testing-library/react'; +import 'jest-localstorage-mock'; +import 'jest-location-mock'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { ToastContainer } from 'react-toastify'; +import userEvent from '@testing-library/user-event'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18nForTest from 'utils/i18nForTest'; +import Users from './Users'; +import { EMPTY_MOCKS, MOCKS } from './UsersMocks'; + +const link = new StaticMockLink(MOCKS, true); +const link2 = new StaticMockLink(EMPTY_MOCKS, true); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} +beforeEach(() => { + localStorage.setItem('id', '123'); + localStorage.setItem('UserType', 'SUPERADMIN'); + localStorage.setItem('FirstName', 'John'); + localStorage.setItem('LastName', 'Doe'); +}); + +afterEach(() => { + localStorage.clear(); +}); + +describe('Testing Users screen', () => { + test('Component should be rendered properly', async () => { + render( + + + + + + + + + + ); + + await wait(); + expect(screen.getAllByText(/Users/i)).toBeTruthy(); + }); + + test(`Component should be rendered properly when user is not superAdmin + and or userId does not exists in localstorage`, async () => { + localStorage.setItem('UserType', 'ADMIN'); + localStorage.setItem('id', ''); + render( + + + + + + + + + + ); + + await wait(); + }); + + test('Component should be rendered properly when user is superAdmin', async () => { + render( + + + + + + + + + + ); + + await wait(); + }); + + test('Testing seach by name functionality', async () => { + render( + + + + + + + + + + ); + + await wait(); + + const search1 = 'John{backspace}{backspace}{backspace}{backspace}'; + userEvent.type(screen.getByTestId(/searchByName/i), search1); + + const search2 = 'Pete{backspace}{backspace}{backspace}{backspace}'; + userEvent.type(screen.getByTestId(/searchByName/i), search2); + + const search3 = + 'John{backspace}{backspace}{backspace}{backspace}Sam{backspace}{backspace}{backspace}'; + userEvent.type(screen.getByTestId(/searchByName/i), search3); + + const search4 = 'Sam{backspace}{backspace}P{backspace}'; + userEvent.type(screen.getByTestId(/searchByName/i), search4); + + const search5 = 'Xe'; + userEvent.type(screen.getByTestId(/searchByName/i), search5); + userEvent.type(screen.getByTestId(/searchByName/i), ''); + }); + + test('Testing User data is not present', async () => { + render( + + + + + + + + + + ); + + await wait(); + expect(screen.getByText(/No User Found/i)).toBeTruthy(); + }); + + test('Should render warning alert when there are no organizations', async () => { + const { container } = render( + + + + + + + + + + + ); + + await wait(200); + expect(container.textContent).toMatch( + 'Organizations not found, please create an organization through dashboard' + ); + }); + + test('Should not render warning alert when there are organizations present', async () => { + const { container } = render( + + + + + + + + + + + ); + + await wait(); + + expect(container.textContent).not.toMatch( + 'Organizations not found, please create an organization through dashboard' + ); + }); + + test('Testing sort Newest and oldest toggle', async () => { + await act(async () => { + render( + + + + + + + + + + + ); + + await wait(); + + const searchInput = screen.getByTestId('sort'); + expect(searchInput).toBeInTheDocument(); + + const inputText = screen.getByTestId('sortUsers'); + + fireEvent.click(inputText); + const toggleText = screen.getByTestId('newest'); + + fireEvent.click(toggleText); + + expect(searchInput).toBeInTheDocument(); + fireEvent.click(inputText); + const toggleTite = screen.getByTestId('oldest'); + fireEvent.click(toggleTite); + expect(searchInput).toBeInTheDocument(); + }); + }); +}); diff --git a/src/screens/Users/Users.tsx b/src/screens/Users/Users.tsx new file mode 100644 index 0000000000..64a9be1735 --- /dev/null +++ b/src/screens/Users/Users.tsx @@ -0,0 +1,350 @@ +import type { ApolloError } from '@apollo/client'; +import { useQuery } from '@apollo/client'; +import React, { useEffect, useState } from 'react'; +import { Dropdown, Form, Table } from 'react-bootstrap'; +import Button from 'react-bootstrap/Button'; +import { useTranslation } from 'react-i18next'; +import { toast } from 'react-toastify'; + +import { Search } from '@mui/icons-material'; +import FilterListIcon from '@mui/icons-material/FilterList'; +import SortIcon from '@mui/icons-material/Sort'; +import { + ORGANIZATION_CONNECTION_LIST, + USER_LIST, +} from 'GraphQl/Queries/Queries'; +import SuperAdminScreen from 'components/SuperAdminScreen/SuperAdminScreen'; +import TableLoader from 'components/TableLoader/TableLoader'; +import UsersTableItem from 'components/UsersTableItem/UsersTableItem'; +import InfiniteScroll from 'react-infinite-scroll-component'; +import debounce from 'utils/debounce'; +import type { InterfaceQueryUserListItem } from 'utils/interfaces'; +import styles from './Users.module.css'; + +const Users = (): JSX.Element => { + const { t } = useTranslation('translation', { keyPrefix: 'users' }); + + document.title = t('title'); + + const perPageResult = 12; + const [isLoading, setIsLoading] = useState(true); + const [hasMore, setHasMore] = useState(true); + const [isLoadingMore, setIsLoadingMore] = useState(false); + const [searchByName, setSearchByName] = useState(''); + const [sortingOption, setSortingOption] = useState('newest'); + + const userType = localStorage.getItem('UserType'); + const loggedInUserId = localStorage.getItem('id'); + + const { + data: usersData, + loading: loading, + fetchMore, + refetch: refetchUsers, + }: { + data?: { users: InterfaceQueryUserListItem[] }; + loading: boolean; + fetchMore: any; + refetch: any; + error?: ApolloError; + } = useQuery(USER_LIST, { + variables: { + first: perPageResult, + skip: 0, + firstName_contains: '', + lastName_contains: '', + }, + notifyOnNetworkStatusChange: true, + }); + + const { data: dataOrgs } = useQuery(ORGANIZATION_CONNECTION_LIST); + const [displayedUsers, setDisplayedUsers] = useState(usersData?.users || []); + + // Manage loading more state + useEffect(() => { + if (!usersData) { + return; + } + if (usersData.users.length < perPageResult) { + setHasMore(false); + } + if (usersData && usersData.users) { + const newDisplayedUsers = sortUsers(usersData.users, sortingOption); + setDisplayedUsers(newDisplayedUsers); + } + }, [usersData, sortingOption]); + + // To clear the search when the component is unmounted + useEffect(() => { + return () => { + setSearchByName(''); + }; + }, []); + + // Warn if there is no organization + useEffect(() => { + if (!dataOrgs) { + return; + } + + if (dataOrgs.organizationsConnection.length === 0) { + toast.warning(t('noOrgError')); + } + }, [dataOrgs]); + + // Send to orgList page if user is not superadmin + useEffect(() => { + if (userType != 'SUPERADMIN') { + window.location.assign('/orglist'); + } + }, []); + + // Manage the loading state + useEffect(() => { + if (loading && isLoadingMore == false) { + setIsLoading(true); + } else { + setIsLoading(false); + } + }, [loading]); + + const handleSearchByName = (e: any): void => { + const { value } = e.target; + setSearchByName(value); + /* istanbul ignore next */ + if (value.length === 0) { + resetAndRefetch(); + return; + } + refetchUsers({ + firstName_contains: value, + lastName_contains: '', + // Later on we can add several search and filter options + }); + }; + /* istanbul ignore next */ + const resetAndRefetch = (): void => { + refetchUsers({ + first: perPageResult, + skip: 0, + firstName_contains: '', + lastName_contains: '', + }); + setHasMore(true); + }; + /* istanbul ignore next */ + const loadMoreUsers = (): void => { + setIsLoadingMore(true); + fetchMore({ + variables: { + skip: usersData?.users.length || 0, + userType: 'ADMIN', + filter: searchByName, + }, + updateQuery: ( + prev: { users: InterfaceQueryUserListItem[] } | undefined, + { + fetchMoreResult, + }: { + fetchMoreResult: { users: InterfaceQueryUserListItem[] } | undefined; + } + ): { users: InterfaceQueryUserListItem[] } | undefined => { + setIsLoadingMore(false); + if (!fetchMoreResult) return prev; + if (fetchMoreResult.users.length < perPageResult) { + setHasMore(false); + } + return { + users: [...(prev?.users || []), ...(fetchMoreResult.users || [])], + }; + }, + }); + }; + const debouncedHandleSearchByName = debounce(handleSearchByName); + // console.log(usersData); + + const handleSorting = (option: string): void => { + setSortingOption(option); + }; + + const sortUsers = ( + allUsers: InterfaceQueryUserListItem[], + sortingOption: string + ): InterfaceQueryUserListItem[] => { + const sortedUsers = [...allUsers]; + + if (sortingOption === 'newest') { + sortedUsers.sort( + (a, b) => + new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime() + ); + } else if (sortingOption === 'oldest') { + sortedUsers.sort( + (a, b) => + new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime() + ); + } + + return sortedUsers; + }; + + const headerTitles: string[] = [ + '#', + t('name'), + t('email'), + t('roles_userType'), + t('joined_organizations'), + t('blocked_organizations'), + ]; + + return ( + <> + + {/* Buttons Container */} +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    + {isLoading == false && + usersData && + displayedUsers.length === 0 && + searchByName.length > 0 ? ( +
    +

    + {t('noResultsFoundFor')} "{searchByName}" +

    +
    + ) : isLoading == false && usersData && displayedUsers.length === 0 ? ( + // eslint-disable-next-line react/jsx-indent +
    +

    {t('noUserFound')}

    +
    + ) : ( +
    + {isLoading ? ( + + ) : ( + + } + hasMore={hasMore} + className={styles.listBox} + data-testid="users-list" + endMessage={ +
    +
    {t('endOfResults')}
    +
    + } + > + + + + {headerTitles.map((title: string, index: number) => { + return ( + + ); + })} + + + + {usersData && + displayedUsers.map((user, index) => { + return ( + + ); + })} + +
    + {title} +
    +
    + )} +
    + )} +
    + + ); +}; + +export default Users; diff --git a/src/screens/Users/UsersMocks.ts b/src/screens/Users/UsersMocks.ts new file mode 100644 index 0000000000..2ee589fd2f --- /dev/null +++ b/src/screens/Users/UsersMocks.ts @@ -0,0 +1,216 @@ +import { + ORGANIZATION_CONNECTION_LIST, + USER_LIST, + USER_ORGANIZATION_LIST, +} from 'GraphQl/Queries/Queries'; + +export const MOCKS = [ + { + request: { + query: USER_ORGANIZATION_LIST, + variables: { id: 'user1' }, + }, + result: { + data: { + user: { + _id: 'user1', + userType: 'SUPERADMIN', + firstName: 'John', + lastName: 'Doe', + image: '', + email: 'John_Does_Palasidoes@gmail.com', + adminFor: [ + { + _id: 1, + name: 'Palisadoes', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: USER_LIST, + variables: { + first: 12, + skip: 0, + firstName_contains: '', + lastName_contains: '', + }, + }, + result: { + data: { + users: [ + { + _id: 'user1', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + userType: 'SUPERADMIN', + adminApproved: true, + adminFor: [ + { + _id: '123', + }, + ], + createdAt: '20/06/2022', + organizationsBlockedBy: [ + { + _id: 'xyz', + name: 'ABC', + image: null, + location: 'Jamaica', + createdAt: '20/06/2022', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + createdAt: '20/06/2022', + }, + }, + ], + joinedOrganizations: [ + { + _id: 'abc', + name: 'Joined Organization 1', + image: null, + location: 'Jamaica', + createdAt: '20/06/2022', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + createdAt: '20/06/2022', + }, + }, + ], + }, + { + _id: 'user2', + firstName: 'Jane', + lastName: 'Doe', + image: null, + email: 'john@example.com', + userType: 'SUPERADMIN', + adminApproved: true, + adminFor: [ + { + _id: '123', + }, + ], + createdAt: '20/06/2022', + organizationsBlockedBy: [ + { + _id: '456', + name: 'ABC', + image: null, + location: 'Jamaica', + createdAt: '20/06/2022', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + createdAt: '20/06/2022', + }, + }, + ], + joinedOrganizations: [ + { + _id: '123', + name: 'Palisadoes', + image: null, + location: 'Jamaica', + createdAt: '20/06/2022', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + createdAt: '20/06/2022', + }, + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: ORGANIZATION_CONNECTION_LIST, + }, + result: { + data: { + organizationsConnection: [ + { + _id: 123, + image: null, + creator: { + firstName: 'John', + lastName: 'Doe', + }, + name: 'Palisadoes', + members: [ + { + _id: 'user1', + }, + { + _id: 'user2', + }, + ], + admins: [ + { + _id: 'user1', + }, + { + _id: 'user2', + }, + ], + createdAt: '09/11/2001', + location: 'Twin Tower', + }, + ], + }, + }, + }, +]; + +export const EMPTY_MOCKS = [ + { + request: { + query: USER_LIST, + + variables: { + first: 12, + skip: 0, + firstName_contains: '', + lastName_contains: '', + }, + }, + result: { + data: { + users: [], + }, + }, + }, + { + request: { + query: ORGANIZATION_CONNECTION_LIST, + }, + result: { + data: { + organizationsConnection: [], + }, + }, + }, +]; diff --git a/src/setupTests.ts b/src/setupTests.ts index 8f2609b7b3..0e9f48386b 100644 --- a/src/setupTests.ts +++ b/src/setupTests.ts @@ -1,5 +1,40 @@ +/* eslint-disable @typescript-eslint/no-empty-function */ // jest-dom adds custom jest matchers for asserting on DOM nodes. // allows you to do things like: // expect(element).toHaveTextContent(/react/i) // learn more: https://github.com/testing-library/jest-dom import '@testing-library/jest-dom'; + +global.fetch = jest.fn(); + +import { format } from 'util'; + +global.console.error = function (...args): void { + throw new Error(format(...args)); +}; + +global.console.warn = function (...args): void { + throw new Error(format(...args)); +}; +Object.defineProperty(HTMLMediaElement.prototype, 'muted', { + set: () => {}, +}); + +import { jestPreviewConfigure } from 'jest-preview'; +import { configure } from 'enzyme'; +import Adapter from '@wojtekmaj/enzyme-adapter-react-17'; + +// Global CSS here +import 'bootstrap/dist/css/bootstrap.css'; +import 'bootstrap/dist/js/bootstrap.min.js'; +import 'react-datepicker/dist/react-datepicker.css'; +import 'flag-icons/css/flag-icons.min.css'; + +configure({ adapter: new Adapter() }); + +jestPreviewConfigure({ + // Opt-in to automatic mode to preview failed test case automatically. + autoPreview: true, +}); + +jest.setTimeout(15000); diff --git a/src/state/action-creators/index.test.ts b/src/state/action-creators/index.test.ts new file mode 100644 index 0000000000..33aa642b8a --- /dev/null +++ b/src/state/action-creators/index.test.ts @@ -0,0 +1,47 @@ +import { + updateInstalled, + installPlugin, + removePlugin, + updatePluginLinks, +} from './index'; +describe('Testing rc/state/action-creators/index.ts', () => { + test('updateInstalled Should call the dispatch function provided', () => { + //checking if the updateInstalled returns a valid function or not + const temp = updateInstalled('testPlug'); + expect(typeof temp).toBe('function'); + //stubbing the childfunction to check execution + const childFunction = jest.fn(); + temp(childFunction); + expect(childFunction).toHaveBeenCalled(); + }); + + test('installPlugin Should call the dispatch function provided', () => { + //checking if the installPlugin returns a valid function or not + const temp = installPlugin('testPlug'); + expect(typeof temp).toBe('function'); + //stubbing the childfunction to check execution + const childFunction = jest.fn(); + temp(childFunction); + expect(childFunction).toHaveBeenCalled(); + }); + + test('removePlugin Should call the dispatch function provided', () => { + //checking if the removePlugin returns a valid function or not + const temp = removePlugin('testPlug'); + expect(typeof temp).toBe('function'); + //stubbing the childfunction to check execution + const childFunction = jest.fn(); + temp(childFunction); + expect(childFunction).toHaveBeenCalled(); + }); + + test('updatePluginLinks Should call the dispatch function provided', () => { + //checking if the updatePluginLinks returns a valid function or not + const temp = updatePluginLinks('testPlug'); + expect(typeof temp).toBe('function'); + //stubbing the childfunction to check execution + const childFunction = jest.fn(); + temp(childFunction); + expect(childFunction).toHaveBeenCalled(); + }); +}); diff --git a/src/state/action-creators/index.ts b/src/state/action-creators/index.ts new file mode 100644 index 0000000000..f0ce7264e1 --- /dev/null +++ b/src/state/action-creators/index.ts @@ -0,0 +1,35 @@ +export const updateInstalled = (plugin: any) => { + return (dispatch: any): void => { + dispatch({ + type: 'UPDATE_INSTALLED', + payload: plugin, + }); + }; +}; + +export const installPlugin = (plugin: any) => { + return (dispatch: any): void => { + dispatch({ + type: 'INSTALL_PLUGIN', + payload: plugin, + }); + }; +}; + +export const removePlugin = (plugin: any) => { + return (dispatch: any): void => { + dispatch({ + type: 'REMOVE_PLUGIN', + payload: plugin, + }); + }; +}; + +export const updatePluginLinks = (plugins: any) => { + return (dispatch: any): void => { + dispatch({ + type: 'UPDATE_P_TARGETS', + payload: plugins, + }); + }; +}; diff --git a/src/state/helpers/Action.test.ts b/src/state/helpers/Action.test.ts new file mode 100644 index 0000000000..a971c6c160 --- /dev/null +++ b/src/state/helpers/Action.test.ts @@ -0,0 +1,8 @@ +import type { InterfaceAction } from './Action'; + +test('Testing Reducer Action Interface', () => { + ({ + type: 'STRING_ACTION_TYPE', + payload: 'ANY_PAYLOAD', + }) as InterfaceAction; +}); diff --git a/src/state/helpers/Action.ts b/src/state/helpers/Action.ts new file mode 100644 index 0000000000..469612441f --- /dev/null +++ b/src/state/helpers/Action.ts @@ -0,0 +1,4 @@ +export interface InterfaceAction { + type: string; + payload: any; +} diff --git a/src/state/index.ts b/src/state/index.ts new file mode 100644 index 0000000000..f35a3d6d46 --- /dev/null +++ b/src/state/index.ts @@ -0,0 +1 @@ +export * as actionCreators from './action-creators/index'; diff --git a/src/state/reducers/index.ts b/src/state/reducers/index.ts new file mode 100644 index 0000000000..3ab9725f7c --- /dev/null +++ b/src/state/reducers/index.ts @@ -0,0 +1,10 @@ +import { combineReducers } from 'redux'; +import routesReducer from './routesReducer'; +import pluginReducer from './pluginReducer'; + +export const reducers = combineReducers({ + appRoutes: routesReducer, + plugins: pluginReducer, +}); + +export type RootState = ReturnType; diff --git a/src/state/reducers/pluginReducer.test.ts b/src/state/reducers/pluginReducer.test.ts new file mode 100644 index 0000000000..ddef5b9c7f --- /dev/null +++ b/src/state/reducers/pluginReducer.test.ts @@ -0,0 +1,102 @@ +import reducer from './pluginReducer'; +import expect from 'expect'; + +describe('Testing Plugin Reducer', () => { + it('should return the initial state', () => { + expect( + reducer(undefined, { + type: '', + payload: undefined, + }) + ).toEqual({ + installed: [], + addonStore: [], + extras: [], + }); + }); + it('should handle INSTALL_PLUGIN', () => { + expect( + reducer( + { installed: [], addonStore: [], extras: [] }, + { + type: 'INSTALL_PLUGIN', + payload: { name: 'testplug' }, + } + ) + ).toEqual({ + installed: [{ name: 'testplug' }], + addonStore: [], + extras: [], + }); + }); + it('should handle REMOVE_PLUGIN', () => { + expect( + reducer( + { + installed: [ + { name: 'testplug2', id: 3 }, + { name: 'testplug3', id: 5 }, + ], + addonStore: [], + extras: [], + }, + { + type: 'REMOVE_PLUGIN', + payload: { id: 3 }, + } + ) + ).toEqual({ + installed: [{ name: 'testplug3', id: 5 }], + addonStore: [], + extras: [], + }); + }); + it('should handle UPDATE_INSTALLED', () => { + expect( + reducer( + { installed: [], addonStore: [], extras: [] }, + { + type: 'UPDATE_INSTALLED', + //Here payload is expected to be as array + payload: [{ name: 'testplug-updated' }], + } + ) + ).toEqual({ + installed: [{ name: 'testplug-updated' }], + addonStore: [], + extras: [], + }); + }); + it('should handle UPDATE_STORE', () => { + expect( + reducer( + { installed: [], addonStore: [], extras: [] }, + { + type: 'UPDATE_STORE', + //Here payload is expected to be as array + payload: [{ name: 'sample-addon' }], + } + ) + ).toEqual({ + installed: [], + addonStore: [{ name: 'sample-addon' }], + extras: [], + }); + }); + it('should handle UPDATE_EXTRAS', () => { + expect( + reducer( + { installed: [], addonStore: [], extras: [] }, + { + type: 'UPDATE_EXTRAS', + //Here payload is expected to be as array + payload: [{ name: 'sample-addon-extra' }], + } + ) + ).toEqual({ + installed: [], + addonStore: [{ name: 'sample-addon-extra' }], + extras: [], + }); + }); +}); diff --git a/src/state/reducers/pluginReducer.ts b/src/state/reducers/pluginReducer.ts new file mode 100644 index 0000000000..483b357e16 --- /dev/null +++ b/src/state/reducers/pluginReducer.ts @@ -0,0 +1,43 @@ +import type { InterfaceAction } from 'state/helpers/Action'; + +const reducer = ( + state = INITIAL_STATE, + action: InterfaceAction +): typeof INITIAL_STATE => { + switch (action.type) { + case 'UPDATE_INSTALLED': + return Object.assign({}, state, { + installed: [...action.payload], + }); + case 'INSTALL_PLUGIN': + return Object.assign({}, state, { + installed: [...state.installed, action.payload], + }); + case 'REMOVE_PLUGIN': + return Object.assign({}, state, { + installed: [ + ...state.installed.filter( + (plugin: any) => plugin.id !== action.payload.id + ), + ], + }); + case 'UPDATE_STORE': + return Object.assign({}, state, { + addonStore: [...action.payload], + }); + case 'UPDATE_EXTRAS': + return Object.assign({}, state, { + addonStore: [...action.payload], + }); + default: + return state; + } +}; + +const INITIAL_STATE: any = { + installed: [], + addonStore: [], + extras: [], +}; + +export default reducer; diff --git a/src/state/reducers/routesReducer.test.ts b/src/state/reducers/routesReducer.test.ts new file mode 100644 index 0000000000..765920e6f3 --- /dev/null +++ b/src/state/reducers/routesReducer.test.ts @@ -0,0 +1,228 @@ +import reducer from './routesReducer'; +import expect from 'expect'; + +describe('Testing Routes reducer', () => { + it('should return the initial state', () => { + expect( + reducer(undefined, { + type: '', + payload: undefined, + }) + ).toEqual({ + targets: [ + { name: 'Dashboard', url: '/orgdash/id=undefined' }, + { name: 'People', url: '/orgpeople/id=undefined' }, + { name: 'Events', url: '/orgevents/id=undefined' }, + { name: 'Posts', url: '/orgpost/id=undefined' }, + { + name: 'Block/Unblock', + url: '/blockuser/id=undefined', + }, + { name: 'Advertisement', url: '/orgads/id=undefined' }, + { + name: 'Plugins', + subTargets: [ + { + icon: 'fa-store', + name: 'Plugin Store', + url: '/orgstore/id=undefined', + }, + ], + }, + { name: 'Settings', url: '/orgsetting/id=undefined' }, + { name: 'All Organizations', url: '/orglist/id=undefined' }, + ], + configUrl: 'undefined', + components: [ + { + name: 'Dashboard', + comp_id: 'orgdash', + component: 'OrganizationDashboard', + }, + { + name: 'People', + comp_id: 'orgpeople', + component: 'OrganizationPeople', + }, + { + name: 'Events', + comp_id: 'orgevents', + component: 'OrganizationEvents', + }, + { name: 'Posts', comp_id: 'orgpost', component: 'OrgPost' }, + { name: 'Block/Unblock', comp_id: 'blockuser', component: 'BlockUser' }, + { + name: 'Advertisement', + comp_id: 'orgads', + component: 'Advertisements', + }, + { + name: 'Plugins', + comp_id: null, + component: 'AddOnStore', + subTargets: [ + { + comp_id: 'orgstore', + component: 'AddOnStore', + icon: 'fa-store', + name: 'Plugin Store', + }, + ], + }, + { name: 'Settings', comp_id: 'orgsetting', component: 'OrgSettings' }, + { name: 'All Organizations', comp_id: 'orglist', component: 'OrgList' }, + { name: '', comp_id: 'member', component: 'MemberDetail' }, + ], + }); + }); + + it('should handle UPDATE_TARGETS', () => { + expect( + reducer(undefined, { + type: 'UPDATE_TARGETS', + payload: { test: 'testupdate' }, + }) + ).toEqual({ + targets: [ + { name: 'Dashboard', url: '/orgdash/id=undefined' }, + { name: 'People', url: '/orgpeople/id=undefined' }, + { name: 'Events', url: '/orgevents/id=undefined' }, + { name: 'Posts', url: '/orgpost/id=undefined' }, + { name: 'Block/Unblock', url: '/blockuser/id=undefined' }, + { name: 'Advertisement', url: '/orgads/id=undefined' }, + { + name: 'Plugins', + subTargets: [ + { + icon: 'fa-store', + name: 'Plugin Store', + url: '/orgstore/id=undefined', + }, + ], + }, + { name: 'Settings', url: '/orgsetting/id=undefined' }, + { name: 'All Organizations', url: '/orglist/id=undefined' }, + { test: 'testupdate' }, + ], + configUrl: 'undefined', + components: [ + { + name: 'Dashboard', + comp_id: 'orgdash', + component: 'OrganizationDashboard', + }, + { + name: 'People', + comp_id: 'orgpeople', + component: 'OrganizationPeople', + }, + { + name: 'Events', + comp_id: 'orgevents', + component: 'OrganizationEvents', + }, + { name: 'Posts', comp_id: 'orgpost', component: 'OrgPost' }, + { name: 'Block/Unblock', comp_id: 'blockuser', component: 'BlockUser' }, + { + name: 'Advertisement', + comp_id: 'orgads', + component: 'Advertisements', + }, + { + name: 'Plugins', + comp_id: null, + component: 'AddOnStore', + subTargets: [ + { + comp_id: 'orgstore', + component: 'AddOnStore', + icon: 'fa-store', + name: 'Plugin Store', + }, + ], + }, + { name: 'Settings', comp_id: 'orgsetting', component: 'OrgSettings' }, + { name: 'All Organizations', comp_id: 'orglist', component: 'OrgList' }, + { name: '', comp_id: 'member', component: 'MemberDetail' }, + ], + }); + }); + + it('should handle UPDATE_P_TARGETS', () => { + expect( + reducer(undefined, { + type: 'UPDATE_P_TARGETS', + payload: [{ name: 'test-target-plugin', content: 'plugin-new' }], + }) + ).toEqual({ + targets: [ + { name: 'Dashboard', url: '/orgdash/id=undefined' }, + { name: 'People', url: '/orgpeople/id=undefined' }, + { name: 'Events', url: '/orgevents/id=undefined' }, + { name: 'Posts', url: '/orgpost/id=undefined' }, + { + name: 'Block/Unblock', + url: '/blockuser/id=undefined', + }, + { name: 'Advertisement', url: '/orgads/id=undefined' }, + { name: 'Settings', url: '/orgsetting/id=undefined' }, + { name: 'All Organizations', url: '/orglist/id=undefined' }, + { + comp_id: null, + component: null, + name: 'Plugins', + subTargets: [ + { name: 'test-target-plugin', content: 'plugin-new' }, + { + icon: 'fa-store', + name: 'Plugin Store', + url: '/orgstore/id=undefined', + }, + ], + }, + ], + configUrl: 'undefined', + components: [ + { + name: 'Dashboard', + comp_id: 'orgdash', + component: 'OrganizationDashboard', + }, + { + name: 'People', + comp_id: 'orgpeople', + component: 'OrganizationPeople', + }, + { + name: 'Events', + comp_id: 'orgevents', + component: 'OrganizationEvents', + }, + + { name: 'Posts', comp_id: 'orgpost', component: 'OrgPost' }, + { name: 'Block/Unblock', comp_id: 'blockuser', component: 'BlockUser' }, + { + name: 'Advertisement', + comp_id: 'orgads', + component: 'Advertisements', + }, + { + name: 'Plugins', + comp_id: null, + component: 'AddOnStore', + subTargets: [ + { + comp_id: 'orgstore', + component: 'AddOnStore', + icon: 'fa-store', + name: 'Plugin Store', + }, + ], + }, + { name: 'Settings', comp_id: 'orgsetting', component: 'OrgSettings' }, + { name: 'All Organizations', comp_id: 'orglist', component: 'OrgList' }, + { name: '', comp_id: 'member', component: 'MemberDetail' }, + ], + }); + }); +}); diff --git a/src/state/reducers/routesReducer.ts b/src/state/reducers/routesReducer.ts new file mode 100644 index 0000000000..4fafbd1ebb --- /dev/null +++ b/src/state/reducers/routesReducer.ts @@ -0,0 +1,117 @@ +import type { InterfaceAction } from 'state/helpers/Action'; + +const currentOrg = window.location.href.split('=')[1]; + +const reducer = ( + state = INITIAL_STATE, + action: InterfaceAction +): typeof INITIAL_STATE => { + switch (action.type) { + case 'UPDATE_TARGETS': { + return Object.assign({}, INITIAL_STATE, { + targets: [...INITIAL_STATE.targets, action.payload], + }); + } + case 'UPDATE_P_TARGETS': { + const oldTargets: any = INITIAL_STATE.targets.filter( + (target: any) => target.name === 'Plugins' + )[0].subTargets; + return Object.assign({}, INITIAL_STATE, { + targets: [ + ...INITIAL_STATE.targets.filter( + (target: any) => target.name !== 'Plugins' + ), + Object.assign( + {}, + { + name: 'Plugins', + comp_id: null, + component: null, + subTargets: [...action.payload, ...oldTargets], + } + ), + ], + }); + } + default: { + return state; + } + } +}; + +export type ComponentType = { + name: string; + comp_id: string | null; + component: string | null; + subTargets?: { + name: string; + comp_id: string; + component: string; + icon?: string; + }[]; +}; + +export type TargetsType = { + name: string; + url?: string; + subTargets?: { + name: any; + url: string; + icon: any; + }[]; +}; + +// Note: Routes with names appear on NavBar +const components: ComponentType[] = [ + { name: 'Dashboard', comp_id: 'orgdash', component: 'OrganizationDashboard' }, + { name: 'People', comp_id: 'orgpeople', component: 'OrganizationPeople' }, + { name: 'Events', comp_id: 'orgevents', component: 'OrganizationEvents' }, + { name: 'Posts', comp_id: 'orgpost', component: 'OrgPost' }, + { name: 'Block/Unblock', comp_id: 'blockuser', component: 'BlockUser' }, + { name: 'Advertisement', comp_id: 'orgads', component: 'Advertisements' }, + { + name: 'Plugins', + comp_id: null, + component: 'AddOnStore', // Default + subTargets: [ + { + name: 'Plugin Store', + comp_id: 'orgstore', + component: 'AddOnStore', + icon: 'fa-store', + }, + ], + }, + + { name: 'Settings', comp_id: 'orgsetting', component: 'OrgSettings' }, + { name: 'All Organizations', comp_id: 'orglist', component: 'OrgList' }, + { name: '', comp_id: 'member', component: 'MemberDetail' }, +]; + +const generateRoutes = (comps: ComponentType[]): TargetsType[] => { + return comps + .filter((comp) => comp.name && comp.name !== '') + .map((comp) => { + const entry: TargetsType = comp.comp_id + ? { name: comp.name, url: `/${comp.comp_id}/id=${currentOrg}` } + : { + name: comp.name, + subTargets: comp.subTargets?.map((subTarget: any) => { + return { + name: subTarget.name, + url: `/${subTarget.comp_id}/id=${currentOrg}`, + icon: subTarget.icon ? subTarget.icon : null, + }; + }), + }; + return entry; + }); +}; + +const INITIAL_STATE = { + targets: generateRoutes(components), + configUrl: `${currentOrg}`, + components, +}; + +export default reducer; diff --git a/src/state/store.test.tsx b/src/state/store.test.tsx new file mode 100644 index 0000000000..81e2831224 --- /dev/null +++ b/src/state/store.test.tsx @@ -0,0 +1,28 @@ +import { store } from './store'; +describe('Testing src/state/store.ts', () => { + const state = store.getState(); + test('State should contain the properties appRoutes and plugins', () => { + expect(state).toHaveProperty('appRoutes'); + expect(state).toHaveProperty('plugins'); + }); + test('State schema should contain appRoutes and plugins', () => { + expect(state).toMatchObject({ + appRoutes: expect.any(Object), + plugins: expect.any(Object), + }); + }); + test('appRoutes schema should contain targets, configUrl and components', () => { + expect(state.appRoutes).toMatchObject({ + targets: expect.any(Array), + configUrl: expect.any(String), + components: expect.any(Array), + }); + }); + test('plugins schema should contain installed, addOnStore and extras', () => { + expect(state.plugins).toMatchObject({ + installed: expect.any(Array), + addonStore: expect.any(Array), + extras: expect.any(Array), + }); + }); +}); diff --git a/src/state/store.ts b/src/state/store.ts new file mode 100644 index 0000000000..4ec777453a --- /dev/null +++ b/src/state/store.ts @@ -0,0 +1,5 @@ +import { applyMiddleware, createStore } from 'redux'; +import thunk from 'redux-thunk'; +import { reducers } from './reducers/index'; + +export const store = createStore(reducers, {}, applyMiddleware(thunk)); diff --git a/src/utils/StaticMockLink.ts b/src/utils/StaticMockLink.ts new file mode 100644 index 0000000000..79bbb57bae --- /dev/null +++ b/src/utils/StaticMockLink.ts @@ -0,0 +1,174 @@ +import { print } from 'graphql'; +import { equal } from '@wry/equality'; +import { invariant } from 'ts-invariant'; + +import type { Operation, FetchResult } from '@apollo/client/link/core'; +import { ApolloLink } from '@apollo/client/link/core'; + +import { + Observable, + addTypenameToDocument, + removeClientSetsFromDocument, + removeConnectionDirectiveFromDocument, + cloneDeep, +} from '@apollo/client/utilities'; + +import type { MockedResponse, ResultFunction } from '@apollo/react-testing'; + +function requestToKey(request: any, addTypename: boolean): string { + const queryString = + request.query && + print(addTypename ? addTypenameToDocument(request.query) : request.query); + const requestKey = { query: queryString }; + return JSON.stringify(requestKey); +} + +/** + * Similar to the standard Apollo MockLink, but doesn't consume a mock + * when it is used allowing it to be used in places like Storybook. + */ +export class StaticMockLink extends ApolloLink { + public operation?: Operation; + public addTypename = true; + private _mockedResponsesByKey: { [key: string]: MockedResponse[] } = {}; + + constructor(mockedResponses: readonly MockedResponse[], addTypename = true) { + super(); + this.addTypename = addTypename; + if (mockedResponses) { + mockedResponses.forEach((mockedResponse) => { + this.addMockedResponse(mockedResponse); + }); + } + } + + public addMockedResponse(mockedResponse: MockedResponse): void { + const normalizedMockedResponse = + this._normalizeMockedResponse(mockedResponse); + const key = requestToKey( + normalizedMockedResponse.request, + this.addTypename + ); + let mockedResponses = this._mockedResponsesByKey[key]; + if (!mockedResponses) { + mockedResponses = []; + this._mockedResponsesByKey[key] = mockedResponses; + } + mockedResponses.push(normalizedMockedResponse); + } + + public request(operation: any): Observable | null { + this.operation = operation; + const key = requestToKey(operation, this.addTypename); + let responseIndex = 0; + const response = (this._mockedResponsesByKey[key] || []).find( + (res, index) => { + const requestVariables = operation.variables || {}; + const mockedResponseVariables = res.request.variables || {}; + if (equal(requestVariables, mockedResponseVariables)) { + responseIndex = index; + return true; + } + return false; + } + ); + + let configError: Error; + + if (!response || typeof responseIndex === 'undefined') { + configError = new Error( + `No more mocked responses for the query: ${print( + operation.query + )}, variables: ${JSON.stringify(operation.variables)}` + ); + } else { + const { newData } = response; + if (newData) { + response.result = newData(); + this._mockedResponsesByKey[key].push(response); + } + + if (!response.result && !response.error) { + configError = new Error( + `Mocked response should contain either result or error: ${key}` + ); + } + } + + return new Observable((observer) => { + const timer = setTimeout(() => { + if (configError) { + try { + // The onError function can return false to indicate that + // configError need not be passed to observer.error. For + // example, the default implementation of onError calls + // observer.error(configError) and then returns false to + // prevent this extra (harmless) observer.error call. + if (this.onError(configError, observer) !== false) { + throw configError; + } + } catch (error) { + observer.error(error); + } + } else if (response) { + if (response.error) { + observer.error(response.error); + } else { + if (response.result) { + observer.next( + typeof response.result === 'function' + ? (response.result as ResultFunction)() + : response.result + ); + } + observer.complete(); + } + } + }, (response && response.delay) || 0); + + return () => { + clearTimeout(timer); + }; + }); + } + + private _normalizeMockedResponse( + mockedResponse: MockedResponse + ): MockedResponse { + const newMockedResponse = cloneDeep(mockedResponse); + const queryWithoutConnection = removeConnectionDirectiveFromDocument( + newMockedResponse.request.query + ); + invariant(queryWithoutConnection, 'query is required'); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + newMockedResponse.request.query = queryWithoutConnection!; + const query = removeClientSetsFromDocument(newMockedResponse.request.query); + if (query) { + newMockedResponse.request.query = query; + } + return newMockedResponse; + } +} + +export interface InterfaceMockApolloLink extends ApolloLink { + operation?: Operation; +} + +// Pass in multiple mocked responses, so that you can test flows that end up +// making multiple queries to the server. +// NOTE: The last arg can optionally be an `addTypename` arg. +export function mockSingleLink( + ...mockedResponses: any[] +): InterfaceMockApolloLink { + // To pull off the potential typename. If this isn't a boolean, we'll just + // set it true later. + let maybeTypename = mockedResponses[mockedResponses.length - 1]; + let mocks = mockedResponses.slice(0, mockedResponses.length - 1); + + if (typeof maybeTypename !== 'boolean') { + mocks = mockedResponses; + maybeTypename = true; + } + + return new StaticMockLink(mocks, maybeTypename); +} diff --git a/src/utils/convertToBase64.test.ts b/src/utils/convertToBase64.test.ts new file mode 100644 index 0000000000..51198ccc29 --- /dev/null +++ b/src/utils/convertToBase64.test.ts @@ -0,0 +1,33 @@ +import convertToBase64 from './convertToBase64'; + +describe('convertToBase64', () => { + it('should return a base64-encoded string when given a file', async () => { + const file = new File(['hello'], 'hello.txt', { type: 'text/plain' }); + const result = await convertToBase64(file); + expect(result).toMatch(/^data:text\/plain;base64,[a-zA-Z0-9+/]+={0,2}$/); + }); + + it('should return an empty string when given an invalid file', async () => { + const file = {} as File; + const result = await convertToBase64(file); + expect(result).toBe(''); + }); + + it('should handle errors thrown by FileReader', async () => { + // Arrange + const file = new File(['hello'], 'hello.txt', { type: 'text/plain' }); + const mockFileReader = jest + .spyOn(global, 'FileReader') + .mockImplementationOnce(() => { + throw new Error('Test error'); + }); + + // Act + const result = await convertToBase64(file); + + // Assert + expect(mockFileReader).toHaveBeenCalledTimes(1); + expect(mockFileReader).toHaveBeenCalledWith(); + expect(result).toBe(''); + }); +}); diff --git a/src/utils/convertToBase64.ts b/src/utils/convertToBase64.ts new file mode 100644 index 0000000000..2264d04d58 --- /dev/null +++ b/src/utils/convertToBase64.ts @@ -0,0 +1,15 @@ +const convertToBase64 = async (file: File): Promise => { + try { + const res = await new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.readAsDataURL(file); + reader.onload = (): void => resolve(reader.result); + reader.onerror = (error): void => reject(error); + }); + return `${res}`; + } catch (error) { + return ''; + } +}; + +export default convertToBase64; diff --git a/src/utils/debounce.ts b/src/utils/debounce.ts new file mode 100644 index 0000000000..8388364ad2 --- /dev/null +++ b/src/utils/debounce.ts @@ -0,0 +1,9 @@ +const debounce = (fn: any, ms = 600): any => { + let timeoutId: ReturnType; + return function (this: any, ...args: any[]): any { + clearTimeout(timeoutId); + timeoutId = setTimeout(() => fn.apply(this, args), ms); + }; +}; + +export default debounce; diff --git a/src/utils/errorHandler.test.tsx b/src/utils/errorHandler.test.tsx new file mode 100644 index 0000000000..a90ab859c7 --- /dev/null +++ b/src/utils/errorHandler.test.tsx @@ -0,0 +1,34 @@ +import type { TFunction } from 'react-i18next'; +import { errorHandler } from './errorHandler'; +import { toast } from 'react-toastify'; + +jest.mock('react-toastify', () => ({ + toast: { + error: jest.fn(), + }, +})); + +describe('Test if errorHandler is working properly', () => { + const t: TFunction<'translation', string> = (key: string) => key; + + it('should call toast.error with the correct message if error message is "Failed to fetch"', () => { + const error = { message: 'Failed to fetch' }; + errorHandler(t, error); + + expect(toast.error).toHaveBeenCalledWith(t('talawaApiUnavailable')); + }); + + it('should call toast.error with the error message if it is not "Failed to fetch"', () => { + const error = { message: 'Some other error message' }; + errorHandler(t, error); + + expect(toast.error).toHaveBeenCalledWith(error.message); + }); + + it('should call toast.error with the error message if error object is falsy', () => { + const error = null; + errorHandler(t, error); + + expect(toast.error).toHaveBeenCalledWith(undefined); + }); +}); diff --git a/src/utils/errorHandler.tsx b/src/utils/errorHandler.tsx new file mode 100644 index 0000000000..4ec1fb4ccb --- /dev/null +++ b/src/utils/errorHandler.tsx @@ -0,0 +1,17 @@ +import type { TFunction } from 'react-i18next'; +import { toast } from 'react-toastify'; +/* + This function is used to handle api errors in the application. + It takes in the error object and displays the error message to the user. + If the error is due to the Talawa API being unavailable, it displays a custom message. +*/ +export const errorHandler = ( + t: TFunction<'translation', string>, + error: any +): void => { + if (error?.message === 'Failed to fetch') { + toast.error(t('talawaApiUnavailable')); + } else { + toast.error(error?.message); + } +}; diff --git a/src/utils/getOrganizationId.ts b/src/utils/getOrganizationId.ts new file mode 100644 index 0000000000..cee92613ab --- /dev/null +++ b/src/utils/getOrganizationId.ts @@ -0,0 +1,8 @@ +/* istanbul ignore next */ +const getOrganizationId = (url: string): string => { + const id = url.split('=')[1]; + + return id.split('#')[0]; +}; + +export default getOrganizationId; diff --git a/src/utils/getRefreshToken.test.ts b/src/utils/getRefreshToken.test.ts new file mode 100644 index 0000000000..12d8448b76 --- /dev/null +++ b/src/utils/getRefreshToken.test.ts @@ -0,0 +1,52 @@ +import { refreshToken } from './getRefreshToken'; + +jest.mock('@apollo/client', () => { + const originalModule = jest.requireActual('@apollo/client'); + + return { + __esModule: true, + ...originalModule, + ApolloClient: jest.fn(() => ({ + mutate: jest.fn(() => + Promise.resolve({ + data: { + refreshToken: { + accessToken: 'newAccessToken', + refreshToken: 'newRefreshToken', + }, + }, + }) + ), + })), + }; +}); + +describe('refreshToken', () => { + // Mock window.location.reload() + const { location } = window; + delete (global.window as any).location; + global.window.location = { ...location, reload: jest.fn() }; + + // Mock localStorage.setItem() and localStorage.clear() + Storage.prototype.setItem = jest.fn(); + Storage.prototype.clear = jest.fn(); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('returns true when the token is refreshed successfully', async () => { + const result = await refreshToken(); + + expect(localStorage.setItem).toHaveBeenCalledWith( + 'token', + 'newAccessToken' + ); + expect(localStorage.setItem).toHaveBeenCalledWith( + 'refreshToken', + 'newRefreshToken' + ); + expect(result).toBe(true); + expect(window.location.reload).toHaveBeenCalled(); + }); +}); diff --git a/src/utils/getRefreshToken.ts b/src/utils/getRefreshToken.ts new file mode 100644 index 0000000000..f3145c4b48 --- /dev/null +++ b/src/utils/getRefreshToken.ts @@ -0,0 +1,31 @@ +import { ApolloClient, InMemoryCache, HttpLink } from '@apollo/client'; +import { BACKEND_URL } from 'Constant/constant'; +import { REFRESH_TOKEN_MUTATION } from 'GraphQl/Mutations/mutations'; + +export async function refreshToken(): Promise { + const client = new ApolloClient({ + link: new HttpLink({ + uri: BACKEND_URL, + }), + cache: new InMemoryCache(), + }); + + const refreshToken = localStorage.getItem('refreshToken'); + /* istanbul ignore next */ + try { + const { data } = await client.mutate({ + mutation: REFRESH_TOKEN_MUTATION, + variables: { + refreshToken: refreshToken, + }, + }); + + localStorage.setItem('token', data.refreshToken.accessToken); + localStorage.setItem('refreshToken', data.refreshToken.refreshToken); + window.location.reload(); + return true; + } catch (error) { + console.error('Failed to refresh token', error); + return false; + } +} diff --git a/src/utils/i18n.ts b/src/utils/i18n.ts new file mode 100644 index 0000000000..6fb7cd4ff0 --- /dev/null +++ b/src/utils/i18n.ts @@ -0,0 +1,25 @@ +import i18n from 'i18next'; +import { initReactI18next } from 'react-i18next'; +import LanguageDetector from 'i18next-browser-languagedetector'; +import HttpApi from 'i18next-http-backend'; + +import { languageArray } from './languages'; + +i18n + .use(initReactI18next) + .use(LanguageDetector) + .use(HttpApi) + .init({ + fallbackLng: 'en', + supportedLngs: languageArray, + detection: { + order: ['cookie', 'htmlTag', 'localStorage', 'path', 'subdomain'], + caches: ['cookie'], + }, + backend: { + loadPath: '/locales/{{lng}}.json', + }, + // debug: true, + }); + +export default i18n; diff --git a/src/utils/i18nForTest.ts b/src/utils/i18nForTest.ts new file mode 100644 index 0000000000..527b96b5f9 --- /dev/null +++ b/src/utils/i18nForTest.ts @@ -0,0 +1,28 @@ +import i18n from 'i18next'; +import { initReactI18next } from 'react-i18next'; +import LanguageDetector from 'i18next-browser-languagedetector'; +import HttpApi from 'i18next-http-backend'; + +import { languageArray } from './languages'; +import translationEnglish from '../../public/locales/en.json'; + +i18n + .use(LanguageDetector) + .use(HttpApi) + .use(initReactI18next) + .init({ + fallbackLng: 'en', + supportedLngs: languageArray, + detection: { + order: ['cookie', 'htmlTag', 'localStorage', 'path', 'subdomain'], + caches: ['cookie'], + }, + resources: { + en: { + translation: translationEnglish, + }, + }, + react: { useSuspense: false }, + }); + +export default i18n; diff --git a/src/utils/interfaces.ts b/src/utils/interfaces.ts new file mode 100644 index 0000000000..e90711028f --- /dev/null +++ b/src/utils/interfaces.ts @@ -0,0 +1,167 @@ +export interface InterfaceUserType { + user: { + firstName: string; + lastName: string; + image: string | null; + email: string; + userType: string; + adminFor: { + _id: string; + name: string; + image: string | null; + }[]; + }; +} + +export interface InterfaceOrgConnectionInfoType { + _id: string; + image: string | null; + creator: { + _id: string; + firstName: string; + lastName: string; + }; + name: string; + members: { + _id: string; + }[]; + admins: { + _id: string; + }[]; + createdAt: string; + location: string; +} +export interface InterfaceOrgConnectionType { + organizationsConnection: InterfaceOrgConnectionInfoType[]; +} + +export interface InterfaceQueryOrganizationsListObject { + _id: string; + image: string | null; + creator: { + firstName: string; + lastName: string; + email: string; + }; + name: string; + description: string; + location: string; + isPublic: boolean; + visibleInSearch: boolean; + members: { + _id: string; + firstName: string; + lastName: string; + email: string; + }[]; + admins: { + _id: string; + firstName: string; + lastName: string; + email: string; + }[]; + membershipRequests: { + _id: string; + user: { + firstName: string; + lastName: string; + email: string; + }; + }[]; + blockedUsers: { + _id: string; + firstName: string; + lastName: string; + email: string; + }[]; +} + +export interface InterfaceQueryOrganizationPostListItem { + _id: string; + title: string; + text: string; + imageUrl: null; + videoUrl: null; + createdAt: string; + creator: { + _id: string; + firstName: string; + lastName: string; + email: string; + }[]; +} +export interface InterfaceQueryOrganizationEventListItem { + _id: string; + title: string; + description: string; + startDate: string; + endDate: string; + location: string; + startTime: string; + endTime: string; + allDay: boolean; + recurring: boolean; + isPublic: boolean; + isRegisterable: boolean; +} + +export interface InterfaceQueryBlockPageMemberListItem { + _id: string; + firstName: string; + lastName: string; + email: string; + organizationsBlockedBy: { + _id: string; + }[]; +} + +export interface InterfaceQueryUserListItem { + _id: string; + firstName: string; + lastName: string; + image: string | null; + email: string; + userType: string; + adminFor: { _id: string }[]; + adminApproved: boolean; + organizationsBlockedBy: { + _id: string; + name: string; + location: string; + image: string | null; + createdAt: string; + creator: { + _id: string; + firstName: string; + lastName: string; + email: string; + image: string | null; + }; + }[]; + joinedOrganizations: { + _id: string; + name: string; + location: string; + image: string | null; + createdAt: string; + creator: { + _id: string; + firstName: string; + lastName: string; + email: string; + image: string | null; + }; + }[]; + createdAt: string; +} + +export interface InterfaceQueryRequestListItem { + _id: string; + firstName: string; + lastName: string; + image: string; + email: string; + userType: string; + adminApproved: boolean; + createdAt: string; +} diff --git a/src/utils/languages.ts b/src/utils/languages.ts new file mode 100644 index 0000000000..9e8e019784 --- /dev/null +++ b/src/utils/languages.ts @@ -0,0 +1,31 @@ +const languageArray = ['en', 'fr', 'hi', 'sp', 'zh']; + +const languages = [ + { + code: 'en', + name: 'English', // english + country_code: 'gb', + }, + { + code: 'fr', + name: 'Français', // french + country_code: 'fr', + }, + { + code: 'hi', + name: 'हिन्दी', // hindi + country_code: 'in', + }, + { + code: 'sp', + name: 'Español', // spanish + country_code: 'ar', + }, + { + code: 'zh', + name: '中國人', // chinese (traditional) + country_code: 'cn', + }, +]; + +export { languageArray, languages }; diff --git a/talawa-admin-docs/.nojekyll b/talawa-admin-docs/.nojekyll new file mode 100644 index 0000000000..e2ac6616ad --- /dev/null +++ b/talawa-admin-docs/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/talawa-admin-docs/README.md b/talawa-admin-docs/README.md new file mode 100644 index 0000000000..fb964eb868 --- /dev/null +++ b/talawa-admin-docs/README.md @@ -0,0 +1,40 @@ +talawa-admin / [Modules](modules.md) + +# Talawa Admin +💬 Join the community on Slack. The link can be found in the `Talawa` [README.md](https://github.com/PalisadoesFoundation/talawa) file. + +[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) +[![GitHub stars](https://img.shields.io/github/stars/PalisadoesFoundation/talawa-admin.svg?style=social&label=Star&maxAge=2592000)](https://github.com/PalisadoesFoundation/talawa-admin) +[![GitHub forks](https://img.shields.io/github/forks/PalisadoesFoundation/talawa-admin.svg?style=social&label=Fork&maxAge=2592000)](https://github.com/PalisadoesFoundation/talawa-admin) +[![codecov](https://codecov.io/gh/PalisadoesFoundation/talawa-admin/branch/develop/graph/badge.svg?token=II0R0RREES)](https://codecov.io/gh/PalisadoesFoundation/talawa-admin) + +Talawa is a modular open source project to manage group activities of both non-profit organizations and businesses. + +Core features include: + +1. Membership management +2. Groups management +3. Event registrations +4. Recurring meetings +5. Facilities registrations + +`talawa` is based on the original `quito` code created by the [Palisadoes Foundation][pfd] as part of its annual Calico Challenge program. Calico provides paid summer internships for Jamaican university students to work on selected open source projects. They are mentored by software professionals and receive stipends based on the completion of predefined milestones. Calico was started in 2015. Visit [The Palisadoes Foundation's website](http://www.palisadoes.org/) for more details on its origin and activities. + +# Talawa Components + +`talawa` has these major software components: + +1. **talawa**: [A mobile application with social media features](https://github.com/PalisadoesFoundation/talawa) +1. **talawa-api**: [An API providing access to user data and features](https://github.com/PalisadoesFoundation/talawa-api) +1. **talawa-admin**: [A web based administrative portal](https://github.com/PalisadoesFoundation/talawa-admin) +1. **talawa-docs**: [The online documentation website](https://github.com/PalisadoesFoundation/talawa-docs) + +# Documentation + +- The `talawa` documentation can be found [here](https://docs.talawa.io). +- Want to contribute? Look at [CONTRIBUTING.md](https://github.com/PalisadoesFoundation/talawa-admin/blob/develop/CONTRIBUTING.md) to get started. +- Visit the [Talawa-Docs GitHub](https://github.com/PalisadoesFoundation/talawa-docs) to see the code. + +# Installation + +[Follow this guide](https://github.com/PalisadoesFoundation/talawa-admin/blob/develop/INSTALLATION.md) diff --git a/talawa-admin-docs/classes/components_AddOn_support_services_Plugin_helper.default.md b/talawa-admin-docs/classes/components_AddOn_support_services_Plugin_helper.default.md new file mode 100644 index 0000000000..46b911318b --- /dev/null +++ b/talawa-admin-docs/classes/components_AddOn_support_services_Plugin_helper.default.md @@ -0,0 +1,71 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / [components/AddOn/support/services/Plugin.helper](../modules/components_AddOn_support_services_Plugin_helper.md) / default + +# Class: default + +[components/AddOn/support/services/Plugin.helper](../modules/components_AddOn_support_services_Plugin_helper.md).default + +## Table of contents + +### Constructors + +- [constructor](components_AddOn_support_services_Plugin_helper.default.md#constructor) + +### Methods + +- [fetchInstalled](components_AddOn_support_services_Plugin_helper.default.md#fetchinstalled) +- [fetchStore](components_AddOn_support_services_Plugin_helper.default.md#fetchstore) +- [generateLinks](components_AddOn_support_services_Plugin_helper.default.md#generatelinks) + +## Constructors + +### constructor + +• **new default**() + +## Methods + +### fetchInstalled + +▸ **fetchInstalled**(): `Promise`<`any`\> + +#### Returns + +`Promise`<`any`\> + +#### Defined in + +[src/components/AddOn/support/services/Plugin.helper.ts:7](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/AddOn/support/services/Plugin.helper.ts#L7) + +___ + +### fetchStore + +▸ **fetchStore**(): `Promise`<`any`\> + +#### Returns + +`Promise`<`any`\> + +#### Defined in + +[src/components/AddOn/support/services/Plugin.helper.ts:2](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/AddOn/support/services/Plugin.helper.ts#L2) + +___ + +### generateLinks + +▸ **generateLinks**(`plugins`): { `name`: `string` ; `url`: `string` }[] + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `plugins` | `any`[] | + +#### Returns + +{ `name`: `string` ; `url`: `string` }[] + +#### Defined in + +[src/components/AddOn/support/services/Plugin.helper.ts:12](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/AddOn/support/services/Plugin.helper.ts#L12) diff --git a/talawa-admin-docs/classes/components_AddOn_support_services_Render_helper.default.md b/talawa-admin-docs/classes/components_AddOn_support_services_Render_helper.default.md new file mode 100644 index 0000000000..5c184eb819 --- /dev/null +++ b/talawa-admin-docs/classes/components_AddOn_support_services_Render_helper.default.md @@ -0,0 +1,17 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / [components/AddOn/support/services/Render.helper](../modules/components_AddOn_support_services_Render_helper.md) / default + +# Class: default + +[components/AddOn/support/services/Render.helper](../modules/components_AddOn_support_services_Render_helper.md).default + +## Table of contents + +### Constructors + +- [constructor](components_AddOn_support_services_Render_helper.default.md#constructor) + +## Constructors + +### constructor + +• **new default**() diff --git a/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceAttendeeCheckIn.md b/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceAttendeeCheckIn.md new file mode 100644 index 0000000000..b3aff6bcbb --- /dev/null +++ b/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceAttendeeCheckIn.md @@ -0,0 +1,43 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / [components/CheckIn/types](../modules/components_CheckIn_types.md) / InterfaceAttendeeCheckIn + +# Interface: InterfaceAttendeeCheckIn + +[components/CheckIn/types](../modules/components_CheckIn_types.md).InterfaceAttendeeCheckIn + +## Table of contents + +### Properties + +- [\_id](components_CheckIn_types.InterfaceAttendeeCheckIn.md#_id) +- [checkIn](components_CheckIn_types.InterfaceAttendeeCheckIn.md#checkin) +- [user](components_CheckIn_types.InterfaceAttendeeCheckIn.md#user) + +## Properties + +### \_id + +• **\_id**: `string` + +#### Defined in + +[src/components/CheckIn/types.ts:8](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/CheckIn/types.ts#L8) + +___ + +### checkIn + +• **checkIn**: ``null`` \| { `_id`: `string` ; `allotedRoom`: `string` ; `allotedSeat`: `string` ; `time`: `string` } + +#### Defined in + +[src/components/CheckIn/types.ts:10](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/CheckIn/types.ts#L10) + +___ + +### user + +• **user**: [`InterfaceUser`](components_CheckIn_types.InterfaceUser.md) + +#### Defined in + +[src/components/CheckIn/types.ts:9](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/CheckIn/types.ts#L9) diff --git a/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceAttendeeQueryResponse.md b/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceAttendeeQueryResponse.md new file mode 100644 index 0000000000..fa7063e500 --- /dev/null +++ b/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceAttendeeQueryResponse.md @@ -0,0 +1,28 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / [components/CheckIn/types](../modules/components_CheckIn_types.md) / InterfaceAttendeeQueryResponse + +# Interface: InterfaceAttendeeQueryResponse + +[components/CheckIn/types](../modules/components_CheckIn_types.md).InterfaceAttendeeQueryResponse + +## Table of contents + +### Properties + +- [event](components_CheckIn_types.InterfaceAttendeeQueryResponse.md#event) + +## Properties + +### event + +• **event**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `_id` | `string` | +| `attendeesCheckInStatus` | [`InterfaceAttendeeCheckIn`](components_CheckIn_types.InterfaceAttendeeCheckIn.md)[] | + +#### Defined in + +[src/components/CheckIn/types.ts:19](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/CheckIn/types.ts#L19) diff --git a/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceModalProp.md b/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceModalProp.md new file mode 100644 index 0000000000..9091e555bb --- /dev/null +++ b/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceModalProp.md @@ -0,0 +1,51 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / [components/CheckIn/types](../modules/components_CheckIn_types.md) / InterfaceModalProp + +# Interface: InterfaceModalProp + +[components/CheckIn/types](../modules/components_CheckIn_types.md).InterfaceModalProp + +## Table of contents + +### Properties + +- [eventId](components_CheckIn_types.InterfaceModalProp.md#eventid) +- [handleClose](components_CheckIn_types.InterfaceModalProp.md#handleclose) +- [show](components_CheckIn_types.InterfaceModalProp.md#show) + +## Properties + +### eventId + +• **eventId**: `string` + +#### Defined in + +[src/components/CheckIn/types.ts:27](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/CheckIn/types.ts#L27) + +___ + +### handleClose + +• **handleClose**: () => `void` + +#### Type declaration + +▸ (): `void` + +##### Returns + +`void` + +#### Defined in + +[src/components/CheckIn/types.ts:28](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/CheckIn/types.ts#L28) + +___ + +### show + +• **show**: `boolean` + +#### Defined in + +[src/components/CheckIn/types.ts:26](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/CheckIn/types.ts#L26) diff --git a/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceTableCheckIn.md b/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceTableCheckIn.md new file mode 100644 index 0000000000..f44d4747f4 --- /dev/null +++ b/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceTableCheckIn.md @@ -0,0 +1,65 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / [components/CheckIn/types](../modules/components_CheckIn_types.md) / InterfaceTableCheckIn + +# Interface: InterfaceTableCheckIn + +[components/CheckIn/types](../modules/components_CheckIn_types.md).InterfaceTableCheckIn + +## Table of contents + +### Properties + +- [checkIn](components_CheckIn_types.InterfaceTableCheckIn.md#checkin) +- [eventId](components_CheckIn_types.InterfaceTableCheckIn.md#eventid) +- [id](components_CheckIn_types.InterfaceTableCheckIn.md#id) +- [name](components_CheckIn_types.InterfaceTableCheckIn.md#name) +- [userId](components_CheckIn_types.InterfaceTableCheckIn.md#userid) + +## Properties + +### checkIn + +• **checkIn**: ``null`` \| { `_id`: `string` ; `allotedRoom`: `string` ; `allotedSeat`: `string` ; `time`: `string` } + +#### Defined in + +[src/components/CheckIn/types.ts:35](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/CheckIn/types.ts#L35) + +___ + +### eventId + +• **eventId**: `string` + +#### Defined in + +[src/components/CheckIn/types.ts:41](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/CheckIn/types.ts#L41) + +___ + +### id + +• **id**: `string` + +#### Defined in + +[src/components/CheckIn/types.ts:32](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/CheckIn/types.ts#L32) + +___ + +### name + +• **name**: `string` + +#### Defined in + +[src/components/CheckIn/types.ts:33](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/CheckIn/types.ts#L33) + +___ + +### userId + +• **userId**: `string` + +#### Defined in + +[src/components/CheckIn/types.ts:34](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/CheckIn/types.ts#L34) diff --git a/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceTableData.md b/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceTableData.md new file mode 100644 index 0000000000..a7cbac4758 --- /dev/null +++ b/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceTableData.md @@ -0,0 +1,43 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / [components/CheckIn/types](../modules/components_CheckIn_types.md) / InterfaceTableData + +# Interface: InterfaceTableData + +[components/CheckIn/types](../modules/components_CheckIn_types.md).InterfaceTableData + +## Table of contents + +### Properties + +- [checkInData](components_CheckIn_types.InterfaceTableData.md#checkindata) +- [id](components_CheckIn_types.InterfaceTableData.md#id) +- [userName](components_CheckIn_types.InterfaceTableData.md#username) + +## Properties + +### checkInData + +• **checkInData**: [`InterfaceTableCheckIn`](components_CheckIn_types.InterfaceTableCheckIn.md) + +#### Defined in + +[src/components/CheckIn/types.ts:47](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/CheckIn/types.ts#L47) + +___ + +### id + +• **id**: `string` + +#### Defined in + +[src/components/CheckIn/types.ts:46](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/CheckIn/types.ts#L46) + +___ + +### userName + +• **userName**: `string` + +#### Defined in + +[src/components/CheckIn/types.ts:45](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/CheckIn/types.ts#L45) diff --git a/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceUser.md b/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceUser.md new file mode 100644 index 0000000000..eb26dccce1 --- /dev/null +++ b/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceUser.md @@ -0,0 +1,43 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / [components/CheckIn/types](../modules/components_CheckIn_types.md) / InterfaceUser + +# Interface: InterfaceUser + +[components/CheckIn/types](../modules/components_CheckIn_types.md).InterfaceUser + +## Table of contents + +### Properties + +- [\_id](components_CheckIn_types.InterfaceUser.md#_id) +- [firstName](components_CheckIn_types.InterfaceUser.md#firstname) +- [lastName](components_CheckIn_types.InterfaceUser.md#lastname) + +## Properties + +### \_id + +• **\_id**: `string` + +#### Defined in + +[src/components/CheckIn/types.ts:2](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/CheckIn/types.ts#L2) + +___ + +### firstName + +• **firstName**: `string` + +#### Defined in + +[src/components/CheckIn/types.ts:3](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/CheckIn/types.ts#L3) + +___ + +### lastName + +• **lastName**: `string` + +#### Defined in + +[src/components/CheckIn/types.ts:4](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/CheckIn/types.ts#L4) diff --git a/talawa-admin-docs/interfaces/components_CollapsibleDropdown_CollapsibleDropdown.InterfaceCollapsibleDropdown.md b/talawa-admin-docs/interfaces/components_CollapsibleDropdown_CollapsibleDropdown.InterfaceCollapsibleDropdown.md new file mode 100644 index 0000000000..8e2a4c5569 --- /dev/null +++ b/talawa-admin-docs/interfaces/components_CollapsibleDropdown_CollapsibleDropdown.InterfaceCollapsibleDropdown.md @@ -0,0 +1,32 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / [components/CollapsibleDropdown/CollapsibleDropdown](../modules/components_CollapsibleDropdown_CollapsibleDropdown.md) / InterfaceCollapsibleDropdown + +# Interface: InterfaceCollapsibleDropdown + +[components/CollapsibleDropdown/CollapsibleDropdown](../modules/components_CollapsibleDropdown_CollapsibleDropdown.md).InterfaceCollapsibleDropdown + +## Table of contents + +### Properties + +- [screenName](components_CollapsibleDropdown_CollapsibleDropdown.InterfaceCollapsibleDropdown.md#screenname) +- [target](components_CollapsibleDropdown_CollapsibleDropdown.InterfaceCollapsibleDropdown.md#target) + +## Properties + +### screenName + +• **screenName**: `string` + +#### Defined in + +[src/components/CollapsibleDropdown/CollapsibleDropdown.tsx:9](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/CollapsibleDropdown/CollapsibleDropdown.tsx#L9) + +___ + +### target + +• **target**: `TargetsType` + +#### Defined in + +[src/components/CollapsibleDropdown/CollapsibleDropdown.tsx:10](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/CollapsibleDropdown/CollapsibleDropdown.tsx#L10) diff --git a/talawa-admin-docs/interfaces/components_IconComponent_IconComponent.InterfaceIconComponent.md b/talawa-admin-docs/interfaces/components_IconComponent_IconComponent.InterfaceIconComponent.md new file mode 100644 index 0000000000..124a3ae0d2 --- /dev/null +++ b/talawa-admin-docs/interfaces/components_IconComponent_IconComponent.InterfaceIconComponent.md @@ -0,0 +1,54 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / [components/IconComponent/IconComponent](../modules/components_IconComponent_IconComponent.md) / InterfaceIconComponent + +# Interface: InterfaceIconComponent + +[components/IconComponent/IconComponent](../modules/components_IconComponent_IconComponent.md).InterfaceIconComponent + +## Table of contents + +### Properties + +- [fill](components_IconComponent_IconComponent.InterfaceIconComponent.md#fill) +- [height](components_IconComponent_IconComponent.InterfaceIconComponent.md#height) +- [name](components_IconComponent_IconComponent.InterfaceIconComponent.md#name) +- [width](components_IconComponent_IconComponent.InterfaceIconComponent.md#width) + +## Properties + +### fill + +• `Optional` **fill**: `string` + +#### Defined in + +[src/components/IconComponent/IconComponent.tsx:14](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/IconComponent/IconComponent.tsx#L14) + +___ + +### height + +• `Optional` **height**: `string` + +#### Defined in + +[src/components/IconComponent/IconComponent.tsx:15](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/IconComponent/IconComponent.tsx#L15) + +___ + +### name + +• **name**: `string` + +#### Defined in + +[src/components/IconComponent/IconComponent.tsx:13](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/IconComponent/IconComponent.tsx#L13) + +___ + +### width + +• `Optional` **width**: `string` + +#### Defined in + +[src/components/IconComponent/IconComponent.tsx:16](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/IconComponent/IconComponent.tsx#L16) diff --git a/talawa-admin-docs/interfaces/components_LeftDrawerOrg_LeftDrawerOrg.InterfaceLeftDrawerProps.md b/talawa-admin-docs/interfaces/components_LeftDrawerOrg_LeftDrawerOrg.InterfaceLeftDrawerProps.md new file mode 100644 index 0000000000..a087afb658 --- /dev/null +++ b/talawa-admin-docs/interfaces/components_LeftDrawerOrg_LeftDrawerOrg.InterfaceLeftDrawerProps.md @@ -0,0 +1,65 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / [components/LeftDrawerOrg/LeftDrawerOrg](../modules/components_LeftDrawerOrg_LeftDrawerOrg.md) / InterfaceLeftDrawerProps + +# Interface: InterfaceLeftDrawerProps + +[components/LeftDrawerOrg/LeftDrawerOrg](../modules/components_LeftDrawerOrg_LeftDrawerOrg.md).InterfaceLeftDrawerProps + +## Table of contents + +### Properties + +- [hideDrawer](components_LeftDrawerOrg_LeftDrawerOrg.InterfaceLeftDrawerProps.md#hidedrawer) +- [orgId](components_LeftDrawerOrg_LeftDrawerOrg.InterfaceLeftDrawerProps.md#orgid) +- [screenName](components_LeftDrawerOrg_LeftDrawerOrg.InterfaceLeftDrawerProps.md#screenname) +- [setHideDrawer](components_LeftDrawerOrg_LeftDrawerOrg.InterfaceLeftDrawerProps.md#sethidedrawer) +- [targets](components_LeftDrawerOrg_LeftDrawerOrg.InterfaceLeftDrawerProps.md#targets) + +## Properties + +### hideDrawer + +• **hideDrawer**: ``null`` \| `boolean` + +#### Defined in + +[src/components/LeftDrawerOrg/LeftDrawerOrg.tsx:22](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/LeftDrawerOrg/LeftDrawerOrg.tsx#L22) + +___ + +### orgId + +• **orgId**: `string` + +#### Defined in + +[src/components/LeftDrawerOrg/LeftDrawerOrg.tsx:19](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/LeftDrawerOrg/LeftDrawerOrg.tsx#L19) + +___ + +### screenName + +• **screenName**: `string` + +#### Defined in + +[src/components/LeftDrawerOrg/LeftDrawerOrg.tsx:20](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/LeftDrawerOrg/LeftDrawerOrg.tsx#L20) + +___ + +### setHideDrawer + +• **setHideDrawer**: `Dispatch`<`SetStateAction`<``null`` \| `boolean`\>\> + +#### Defined in + +[src/components/LeftDrawerOrg/LeftDrawerOrg.tsx:23](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/LeftDrawerOrg/LeftDrawerOrg.tsx#L23) + +___ + +### targets + +• **targets**: `TargetsType`[] + +#### Defined in + +[src/components/LeftDrawerOrg/LeftDrawerOrg.tsx:21](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/LeftDrawerOrg/LeftDrawerOrg.tsx#L21) diff --git a/talawa-admin-docs/interfaces/components_LeftDrawer_LeftDrawer.InterfaceLeftDrawerProps.md b/talawa-admin-docs/interfaces/components_LeftDrawer_LeftDrawer.InterfaceLeftDrawerProps.md new file mode 100644 index 0000000000..8150b80c64 --- /dev/null +++ b/talawa-admin-docs/interfaces/components_LeftDrawer_LeftDrawer.InterfaceLeftDrawerProps.md @@ -0,0 +1,43 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / [components/LeftDrawer/LeftDrawer](../modules/components_LeftDrawer_LeftDrawer.md) / InterfaceLeftDrawerProps + +# Interface: InterfaceLeftDrawerProps + +[components/LeftDrawer/LeftDrawer](../modules/components_LeftDrawer_LeftDrawer.md).InterfaceLeftDrawerProps + +## Table of contents + +### Properties + +- [hideDrawer](components_LeftDrawer_LeftDrawer.InterfaceLeftDrawerProps.md#hidedrawer) +- [screenName](components_LeftDrawer_LeftDrawer.InterfaceLeftDrawerProps.md#screenname) +- [setHideDrawer](components_LeftDrawer_LeftDrawer.InterfaceLeftDrawerProps.md#sethidedrawer) + +## Properties + +### hideDrawer + +• **hideDrawer**: ``null`` \| `boolean` + +#### Defined in + +[src/components/LeftDrawer/LeftDrawer.tsx:15](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/LeftDrawer/LeftDrawer.tsx#L15) + +___ + +### screenName + +• **screenName**: `string` + +#### Defined in + +[src/components/LeftDrawer/LeftDrawer.tsx:17](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/LeftDrawer/LeftDrawer.tsx#L17) + +___ + +### setHideDrawer + +• **setHideDrawer**: `Dispatch`<`SetStateAction`<``null`` \| `boolean`\>\> + +#### Defined in + +[src/components/LeftDrawer/LeftDrawer.tsx:16](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/LeftDrawer/LeftDrawer.tsx#L16) diff --git a/talawa-admin-docs/interfaces/components_OrgListCard_OrgListCard.InterfaceOrgListCardProps.md b/talawa-admin-docs/interfaces/components_OrgListCard_OrgListCard.InterfaceOrgListCardProps.md new file mode 100644 index 0000000000..3d9ac12569 --- /dev/null +++ b/talawa-admin-docs/interfaces/components_OrgListCard_OrgListCard.InterfaceOrgListCardProps.md @@ -0,0 +1,21 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / [components/OrgListCard/OrgListCard](../modules/components_OrgListCard_OrgListCard.md) / InterfaceOrgListCardProps + +# Interface: InterfaceOrgListCardProps + +[components/OrgListCard/OrgListCard](../modules/components_OrgListCard_OrgListCard.md).InterfaceOrgListCardProps + +## Table of contents + +### Properties + +- [data](components_OrgListCard_OrgListCard.InterfaceOrgListCardProps.md#data) + +## Properties + +### data + +• **data**: `InterfaceOrgConnectionInfoType` + +#### Defined in + +[src/components/OrgListCard/OrgListCard.tsx:10](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/OrgListCard/OrgListCard.tsx#L10) diff --git a/talawa-admin-docs/interfaces/components_OrganizationScreen_OrganizationScreen.InterfaceOrganizationScreenProps.md b/talawa-admin-docs/interfaces/components_OrganizationScreen_OrganizationScreen.InterfaceOrganizationScreenProps.md new file mode 100644 index 0000000000..3314985607 --- /dev/null +++ b/talawa-admin-docs/interfaces/components_OrganizationScreen_OrganizationScreen.InterfaceOrganizationScreenProps.md @@ -0,0 +1,43 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / [components/OrganizationScreen/OrganizationScreen](../modules/components_OrganizationScreen_OrganizationScreen.md) / InterfaceOrganizationScreenProps + +# Interface: InterfaceOrganizationScreenProps + +[components/OrganizationScreen/OrganizationScreen](../modules/components_OrganizationScreen_OrganizationScreen.md).InterfaceOrganizationScreenProps + +## Table of contents + +### Properties + +- [children](components_OrganizationScreen_OrganizationScreen.InterfaceOrganizationScreenProps.md#children) +- [screenName](components_OrganizationScreen_OrganizationScreen.InterfaceOrganizationScreenProps.md#screenname) +- [title](components_OrganizationScreen_OrganizationScreen.InterfaceOrganizationScreenProps.md#title) + +## Properties + +### children + +• **children**: `ReactNode` + +#### Defined in + +[src/components/OrganizationScreen/OrganizationScreen.tsx:13](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/OrganizationScreen/OrganizationScreen.tsx#L13) + +___ + +### screenName + +• **screenName**: `string` + +#### Defined in + +[src/components/OrganizationScreen/OrganizationScreen.tsx:12](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/OrganizationScreen/OrganizationScreen.tsx#L12) + +___ + +### title + +• **title**: `string` + +#### Defined in + +[src/components/OrganizationScreen/OrganizationScreen.tsx:11](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/OrganizationScreen/OrganizationScreen.tsx#L11) diff --git a/talawa-admin-docs/interfaces/components_SuperAdminScreen_SuperAdminScreen.InterfaceSuperAdminScreenProps.md b/talawa-admin-docs/interfaces/components_SuperAdminScreen_SuperAdminScreen.InterfaceSuperAdminScreenProps.md new file mode 100644 index 0000000000..d3258252bc --- /dev/null +++ b/talawa-admin-docs/interfaces/components_SuperAdminScreen_SuperAdminScreen.InterfaceSuperAdminScreenProps.md @@ -0,0 +1,43 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / [components/SuperAdminScreen/SuperAdminScreen](../modules/components_SuperAdminScreen_SuperAdminScreen.md) / InterfaceSuperAdminScreenProps + +# Interface: InterfaceSuperAdminScreenProps + +[components/SuperAdminScreen/SuperAdminScreen](../modules/components_SuperAdminScreen_SuperAdminScreen.md).InterfaceSuperAdminScreenProps + +## Table of contents + +### Properties + +- [children](components_SuperAdminScreen_SuperAdminScreen.InterfaceSuperAdminScreenProps.md#children) +- [screenName](components_SuperAdminScreen_SuperAdminScreen.InterfaceSuperAdminScreenProps.md#screenname) +- [title](components_SuperAdminScreen_SuperAdminScreen.InterfaceSuperAdminScreenProps.md#title) + +## Properties + +### children + +• **children**: `ReactNode` + +#### Defined in + +[src/components/SuperAdminScreen/SuperAdminScreen.tsx:10](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/SuperAdminScreen/SuperAdminScreen.tsx#L10) + +___ + +### screenName + +• **screenName**: `string` + +#### Defined in + +[src/components/SuperAdminScreen/SuperAdminScreen.tsx:9](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/SuperAdminScreen/SuperAdminScreen.tsx#L9) + +___ + +### title + +• **title**: `string` + +#### Defined in + +[src/components/SuperAdminScreen/SuperAdminScreen.tsx:8](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/SuperAdminScreen/SuperAdminScreen.tsx#L8) diff --git a/talawa-admin-docs/modules.md b/talawa-admin-docs/modules.md new file mode 100644 index 0000000000..803e9dfe69 --- /dev/null +++ b/talawa-admin-docs/modules.md @@ -0,0 +1,181 @@ +[talawa-admin](README.md) / Modules + +# talawa-admin + +## Table of contents + +### Modules + +- [components/AddOn/AddOn](modules/components_AddOn_AddOn.md) +- [components/AddOn/AddOn.test](modules/components_AddOn_AddOn_test.md) +- [components/AddOn/core/AddOnEntry/AddOnEntry](modules/components_AddOn_core_AddOnEntry_AddOnEntry.md) +- [components/AddOn/core/AddOnEntry/AddOnEntry.test](modules/components_AddOn_core_AddOnEntry_AddOnEntry_test.md) +- [components/AddOn/core/AddOnRegister/AddOnRegister](modules/components_AddOn_core_AddOnRegister_AddOnRegister.md) +- [components/AddOn/core/AddOnRegister/AddOnRegister.test](modules/components_AddOn_core_AddOnRegister_AddOnRegister_test.md) +- [components/AddOn/core/AddOnStore/AddOnStore](modules/components_AddOn_core_AddOnStore_AddOnStore.md) +- [components/AddOn/core/AddOnStore/AddOnStore.test](modules/components_AddOn_core_AddOnStore_AddOnStore_test.md) +- [components/AddOn/support/components/Action/Action](modules/components_AddOn_support_components_Action_Action.md) +- [components/AddOn/support/components/Action/Action.test](modules/components_AddOn_support_components_Action_Action_test.md) +- [components/AddOn/support/components/MainContent/MainContent](modules/components_AddOn_support_components_MainContent_MainContent.md) +- [components/AddOn/support/components/MainContent/MainContent.test](modules/components_AddOn_support_components_MainContent_MainContent_test.md) +- [components/AddOn/support/components/SidePanel/SidePanel](modules/components_AddOn_support_components_SidePanel_SidePanel.md) +- [components/AddOn/support/components/SidePanel/SidePanel.test](modules/components_AddOn_support_components_SidePanel_SidePanel_test.md) +- [components/AddOn/support/services/Plugin.helper](modules/components_AddOn_support_services_Plugin_helper.md) +- [components/AddOn/support/services/Render.helper](modules/components_AddOn_support_services_Render_helper.md) +- [components/ChangeLanguageDropdown/ChangeLanguageDropDown](modules/components_ChangeLanguageDropdown_ChangeLanguageDropDown.md) +- [components/ChangeLanguageDropdown/ChangeLanguageDropdown.test](modules/components_ChangeLanguageDropdown_ChangeLanguageDropdown_test.md) +- [components/CheckIn/CheckInModal](modules/components_CheckIn_CheckInModal.md) +- [components/CheckIn/CheckInModal.test](modules/components_CheckIn_CheckInModal_test.md) +- [components/CheckIn/CheckInWrapper](modules/components_CheckIn_CheckInWrapper.md) +- [components/CheckIn/CheckInWrapper.test](modules/components_CheckIn_CheckInWrapper_test.md) +- [components/CheckIn/TableRow](modules/components_CheckIn_TableRow.md) +- [components/CheckIn/TableRow.test](modules/components_CheckIn_TableRow_test.md) +- [components/CheckIn/mocks](modules/components_CheckIn_mocks.md) +- [components/CheckIn/tagTemplate](modules/components_CheckIn_tagTemplate.md) +- [components/CheckIn/types](modules/components_CheckIn_types.md) +- [components/CollapsibleDropdown/CollapsibleDropdown](modules/components_CollapsibleDropdown_CollapsibleDropdown.md) +- [components/CollapsibleDropdown/CollapsibleDropdown.test](modules/components_CollapsibleDropdown_CollapsibleDropdown_test.md) +- [components/ContriStats/ContriStats](modules/components_ContriStats_ContriStats.md) +- [components/ContriStats/ContriStats.test](modules/components_ContriStats_ContriStats_test.md) +- [components/EventCalendar/EventCalendar](modules/components_EventCalendar_EventCalendar.md) +- [components/EventCalendar/EventCalendar.test](modules/components_EventCalendar_EventCalendar_test.md) +- [components/EventListCard/EventListCard](modules/components_EventListCard_EventListCard.md) +- [components/EventListCard/EventListCard.test](modules/components_EventListCard_EventListCard_test.md) +- [components/EventProjectModals/AddEventProjectModal](modules/components_EventProjectModals_AddEventProjectModal.md) +- [components/EventProjectModals/AddEventProjectModal.test](modules/components_EventProjectModals_AddEventProjectModal_test.md) +- [components/EventProjectModals/DeleteEventProjectModal](modules/components_EventProjectModals_DeleteEventProjectModal.md) +- [components/EventProjectModals/DeleteEventProjectModal.test](modules/components_EventProjectModals_DeleteEventProjectModal_test.md) +- [components/EventProjectModals/UpdateEventProjectModal](modules/components_EventProjectModals_UpdateEventProjectModal.md) +- [components/EventProjectModals/UpdateEventProjectModal.test](modules/components_EventProjectModals_UpdateEventProjectModal_test.md) +- [components/EventRegistrantsModal/EventRegistrantsModal](modules/components_EventRegistrantsModal_EventRegistrantsModal.md) +- [components/EventRegistrantsModal/EventRegistrantsModal.test](modules/components_EventRegistrantsModal_EventRegistrantsModal_test.md) +- [components/EventRegistrantsModal/EventRegistrantsWrapper](modules/components_EventRegistrantsModal_EventRegistrantsWrapper.md) +- [components/EventRegistrantsModal/EventRegistrantsWrapper.test](modules/components_EventRegistrantsModal_EventRegistrantsWrapper_test.md) +- [components/IconComponent/IconComponent](modules/components_IconComponent_IconComponent.md) +- [components/IconComponent/IconComponent.test](modules/components_IconComponent_IconComponent_test.md) +- [components/LandingPage/LandingPage](modules/components_LandingPage_LandingPage.md) +- [components/LandingPage/LandingPage.test](modules/components_LandingPage_LandingPage_test.md) +- [components/LeftDrawer/LeftDrawer](modules/components_LeftDrawer_LeftDrawer.md) +- [components/LeftDrawer/LeftDrawer.test](modules/components_LeftDrawer_LeftDrawer_test.md) +- [components/LeftDrawerOrg/LeftDrawerOrg](modules/components_LeftDrawerOrg_LeftDrawerOrg.md) +- [components/LeftDrawerOrg/LeftDrawerOrg.test](modules/components_LeftDrawerOrg_LeftDrawerOrg_test.md) +- [components/Loader/Loader](modules/components_Loader_Loader.md) +- [components/Loader/Loader.test](modules/components_Loader_Loader_test.md) +- [components/MemberRequestCard/MemberRequestCard](modules/components_MemberRequestCard_MemberRequestCard.md) +- [components/MemberRequestCard/MemberRequestCard.test](modules/components_MemberRequestCard_MemberRequestCard_test.md) +- [components/NotFound/NotFound](modules/components_NotFound_NotFound.md) +- [components/NotFound/NotFound.test](modules/components_NotFound_NotFound_test.md) +- [components/OrgAdminListCard/OrgAdminListCard](modules/components_OrgAdminListCard_OrgAdminListCard.md) +- [components/OrgAdminListCard/OrgAdminListCard.test](modules/components_OrgAdminListCard_OrgAdminListCard_test.md) +- [components/OrgContriCards/OrgContriCards](modules/components_OrgContriCards_OrgContriCards.md) +- [components/OrgContriCards/OrgContriCards.test](modules/components_OrgContriCards_OrgContriCards_test.md) +- [components/OrgDelete/OrgDelete](modules/components_OrgDelete_OrgDelete.md) +- [components/OrgDelete/OrgDelete.test](modules/components_OrgDelete_OrgDelete_test.md) +- [components/OrgListCard/OrgListCard](modules/components_OrgListCard_OrgListCard.md) +- [components/OrgListCard/OrgListCard.test](modules/components_OrgListCard_OrgListCard_test.md) +- [components/OrgPeopleListCard/OrgPeopleListCard](modules/components_OrgPeopleListCard_OrgPeopleListCard.md) +- [components/OrgPeopleListCard/OrgPeopleListCard.test](modules/components_OrgPeopleListCard_OrgPeopleListCard_test.md) +- [components/OrgPostCard/OrgPostCard](modules/components_OrgPostCard_OrgPostCard.md) +- [components/OrgPostCard/OrgPostCard.test](modules/components_OrgPostCard_OrgPostCard_test.md) +- [components/OrgUpdate/OrgUpdate](modules/components_OrgUpdate_OrgUpdate.md) +- [components/OrgUpdate/OrgUpdate.test](modules/components_OrgUpdate_OrgUpdate_test.md) +- [components/OrganizationCard/OrganizationCard](modules/components_OrganizationCard_OrganizationCard.md) +- [components/OrganizationCard/OrganizationCard.test](modules/components_OrganizationCard_OrganizationCard_test.md) +- [components/OrganizationCardStart/OrganizationCardStart](modules/components_OrganizationCardStart_OrganizationCardStart.md) +- [components/OrganizationCardStart/OrganizationCardStart.test](modules/components_OrganizationCardStart_OrganizationCardStart_test.md) +- [components/OrganizationScreen/OrganizationScreen](modules/components_OrganizationScreen_OrganizationScreen.md) +- [components/OrganizationScreen/OrganizationScreen.test](modules/components_OrganizationScreen_OrganizationScreen_test.md) +- [components/Pagination/Pagination](modules/components_Pagination_Pagination.md) +- [components/Pagination/Pagination.test](modules/components_Pagination_Pagination_test.md) +- [components/PaginationList/PaginationList](modules/components_PaginationList_PaginationList.md) +- [components/SecuredRoute/SecuredRoute](modules/components_SecuredRoute_SecuredRoute.md) +- [components/SuperAdminScreen/SuperAdminScreen](modules/components_SuperAdminScreen_SuperAdminScreen.md) +- [components/SuperAdminScreen/SuperAdminScreen.test](modules/components_SuperAdminScreen_SuperAdminScreen_test.md) +- [components/TableLoader/TableLoader](modules/components_TableLoader_TableLoader.md) +- [components/TableLoader/TableLoader.test](modules/components_TableLoader_TableLoader_test.md) +- [components/TaskListItem/TaskListItem](modules/components_TaskListItem_TaskListItem.md) +- [components/TaskListItem/TaskListItem.test](modules/components_TaskListItem_TaskListItem_test.md) +- [components/TaskModals/AddTaskModal](modules/components_TaskModals_AddTaskModal.md) +- [components/TaskModals/AddTaskModal.test](modules/components_TaskModals_AddTaskModal_test.md) +- [components/TaskModals/DeleteTaskModal](modules/components_TaskModals_DeleteTaskModal.md) +- [components/TaskModals/DeleteTaskModal.test](modules/components_TaskModals_DeleteTaskModal_test.md) +- [components/TaskModals/ManageVolunteerModal](modules/components_TaskModals_ManageVolunteerModal.md) +- [components/TaskModals/ManageVolunteerModal.test](modules/components_TaskModals_ManageVolunteerModal_test.md) +- [components/TaskModals/UpdateTaskModal](modules/components_TaskModals_UpdateTaskModal.md) +- [components/TaskModals/UpdateTaskModal.test](modules/components_TaskModals_UpdateTaskModal_test.md) +- [components/UserListCard/UserListCard](modules/components_UserListCard_UserListCard.md) +- [components/UserListCard/UserListCard.test](modules/components_UserListCard_UserListCard_test.md) +- [components/UserPasswordUpdate/UserPasswordUpdate](modules/components_UserPasswordUpdate_UserPasswordUpdate.md) +- [components/UserPasswordUpdate/UserPasswordUpdate.test](modules/components_UserPasswordUpdate_UserPasswordUpdate_test.md) +- [components/UserPortal/DonationCard/DonationCard](modules/components_UserPortal_DonationCard_DonationCard.md) +- [components/UserPortal/Login/Login](modules/components_UserPortal_Login_Login.md) +- [components/UserPortal/Login/Login.test](modules/components_UserPortal_Login_Login_test.md) +- [components/UserPortal/OrganizationCard/OrganizationCard](modules/components_UserPortal_OrganizationCard_OrganizationCard.md) +- [components/UserPortal/OrganizationCard/OrganizationCard.test](modules/components_UserPortal_OrganizationCard_OrganizationCard_test.md) +- [components/UserPortal/OrganizationNavbar/OrganizationNavbar](modules/components_UserPortal_OrganizationNavbar_OrganizationNavbar.md) +- [components/UserPortal/OrganizationNavbar/OrganizationNavbar.test](modules/components_UserPortal_OrganizationNavbar_OrganizationNavbar_test.md) +- [components/UserPortal/OrganizationSidebar/OrganizationSidebar](modules/components_UserPortal_OrganizationSidebar_OrganizationSidebar.md) +- [components/UserPortal/OrganizationSidebar/OrganizationSidebar.test](modules/components_UserPortal_OrganizationSidebar_OrganizationSidebar_test.md) +- [components/UserPortal/PeopleCard/PeopleCard](modules/components_UserPortal_PeopleCard_PeopleCard.md) +- [components/UserPortal/PeopleCard/PeopleCard.test](modules/components_UserPortal_PeopleCard_PeopleCard_test.md) +- [components/UserPortal/PostCard/PostCard](modules/components_UserPortal_PostCard_PostCard.md) +- [components/UserPortal/PostCard/PostCard.test](modules/components_UserPortal_PostCard_PostCard_test.md) +- [components/UserPortal/Register/Register](modules/components_UserPortal_Register_Register.md) +- [components/UserPortal/Register/Register.test](modules/components_UserPortal_Register_Register_test.md) +- [components/UserPortal/SecuredRouteForUser/SecuredRouteForUser](modules/components_UserPortal_SecuredRouteForUser_SecuredRouteForUser.md) +- [components/UserPortal/UserNavbar/UserNavbar](modules/components_UserPortal_UserNavbar_UserNavbar.md) +- [components/UserPortal/UserNavbar/UserNavbar.test](modules/components_UserPortal_UserNavbar_UserNavbar_test.md) +- [components/UserPortal/UserSidebar/UserSidebar](modules/components_UserPortal_UserSidebar_UserSidebar.md) +- [components/UserPortal/UserSidebar/UserSidebar.test](modules/components_UserPortal_UserSidebar_UserSidebar_test.md) +- [components/UserUpdate/UserUpdate](modules/components_UserUpdate_UserUpdate.md) +- [components/UserUpdate/UserUpdate.test](modules/components_UserUpdate_UserUpdate_test.md) +- [components/plugins](modules/components_plugins.md) +- [components/plugins/DummyPlugin/DummyPlugin](modules/components_plugins_DummyPlugin_DummyPlugin.md) +- [components/plugins/DummyPlugin/DummyPlugin.test](modules/components_plugins_DummyPlugin_DummyPlugin_test.md) +- [components/plugins/DummyPlugin2/DummyPlugin2](modules/components_plugins_DummyPlugin2_DummyPlugin2.md) +- [components/plugins/DummyPlugin2/DummyPlugin2.test](modules/components_plugins_DummyPlugin2_DummyPlugin2_test.md) +- [screens/BlockUser/BlockUser](modules/screens_BlockUser_BlockUser.md) +- [screens/BlockUser/BlockUser.test](modules/screens_BlockUser_BlockUser_test.md) +- [screens/EventDashboard/EventDashboard](modules/screens_EventDashboard_EventDashboard.md) +- [screens/EventDashboard/EventDashboard.mocks](modules/screens_EventDashboard_EventDashboard_mocks.md) +- [screens/EventDashboard/EventDashboard.test](modules/screens_EventDashboard_EventDashboard_test.md) +- [screens/ForgotPassword/ForgotPassword](modules/screens_ForgotPassword_ForgotPassword.md) +- [screens/ForgotPassword/ForgotPassword.test](modules/screens_ForgotPassword_ForgotPassword_test.md) +- [screens/LoginPage/LoginPage](modules/screens_LoginPage_LoginPage.md) +- [screens/LoginPage/LoginPage.test](modules/screens_LoginPage_LoginPage_test.md) +- [screens/MemberDetail/MemberDetail](modules/screens_MemberDetail_MemberDetail.md) +- [screens/MemberDetail/MemberDetail.test](modules/screens_MemberDetail_MemberDetail_test.md) +- [screens/OrgContribution/OrgContribution](modules/screens_OrgContribution_OrgContribution.md) +- [screens/OrgContribution/OrgContribution.test](modules/screens_OrgContribution_OrgContribution_test.md) +- [screens/OrgList/OrgList](modules/screens_OrgList_OrgList.md) +- [screens/OrgList/OrgList.test](modules/screens_OrgList_OrgList_test.md) +- [screens/OrgList/OrgListMocks](modules/screens_OrgList_OrgListMocks.md) +- [screens/OrgPost/OrgPost](modules/screens_OrgPost_OrgPost.md) +- [screens/OrgPost/OrgPost.test](modules/screens_OrgPost_OrgPost_test.md) +- [screens/OrgSettings/OrgSettings](modules/screens_OrgSettings_OrgSettings.md) +- [screens/OrgSettings/OrgSettings.test](modules/screens_OrgSettings_OrgSettings_test.md) +- [screens/OrganizationDashboard/OrganizationDashboard](modules/screens_OrganizationDashboard_OrganizationDashboard.md) +- [screens/OrganizationDashboard/OrganizationDashboard.test](modules/screens_OrganizationDashboard_OrganizationDashboard_test.md) +- [screens/OrganizationDashboard/OrganizationDashboardMocks](modules/screens_OrganizationDashboard_OrganizationDashboardMocks.md) +- [screens/OrganizationEvents/OrganizationEvents](modules/screens_OrganizationEvents_OrganizationEvents.md) +- [screens/OrganizationEvents/OrganizationEvents.test](modules/screens_OrganizationEvents_OrganizationEvents_test.md) +- [screens/OrganizationPeople/OrganizationPeople](modules/screens_OrganizationPeople_OrganizationPeople.md) +- [screens/OrganizationPeople/OrganizationPeople.test](modules/screens_OrganizationPeople_OrganizationPeople_test.md) +- [screens/PageNotFound/PageNotFound](modules/screens_PageNotFound_PageNotFound.md) +- [screens/PageNotFound/PageNotFound.test](modules/screens_PageNotFound_PageNotFound_test.md) +- [screens/Requests/Requests](modules/screens_Requests_Requests.md) +- [screens/Requests/Requests.test](modules/screens_Requests_Requests_test.md) +- [screens/UserPortal/Donate/Donate](modules/screens_UserPortal_Donate_Donate.md) +- [screens/UserPortal/Donate/Donate.test](modules/screens_UserPortal_Donate_Donate_test.md) +- [screens/UserPortal/Home/Home](modules/screens_UserPortal_Home_Home.md) +- [screens/UserPortal/Home/Home.test](modules/screens_UserPortal_Home_Home_test.md) +- [screens/UserPortal/Organizations/Organizations](modules/screens_UserPortal_Organizations_Organizations.md) +- [screens/UserPortal/Organizations/Organizations.test](modules/screens_UserPortal_Organizations_Organizations_test.md) +- [screens/UserPortal/People/People](modules/screens_UserPortal_People_People.md) +- [screens/UserPortal/People/People.test](modules/screens_UserPortal_People_People_test.md) +- [screens/UserPortal/Settings/Settings](modules/screens_UserPortal_Settings_Settings.md) +- [screens/UserPortal/Settings/Settings.test](modules/screens_UserPortal_Settings_Settings_test.md) +- [screens/UserPortal/UserLoginPage/UserLoginPage](modules/screens_UserPortal_UserLoginPage_UserLoginPage.md) +- [screens/UserPortal/UserLoginPage/UserLoginPage.test](modules/screens_UserPortal_UserLoginPage_UserLoginPage_test.md) +- [screens/Users/Users](modules/screens_Users_Users.md) +- [screens/Users/Users.test](modules/screens_Users_Users_test.md) diff --git a/talawa-admin-docs/modules/components_AddOn_AddOn.default.md b/talawa-admin-docs/modules/components_AddOn_AddOn.default.md new file mode 100644 index 0000000000..1ae4e3dd2e --- /dev/null +++ b/talawa-admin-docs/modules/components_AddOn_AddOn.default.md @@ -0,0 +1,48 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / [components/AddOn/AddOn](components_AddOn_AddOn.md) / default + +# Namespace: default + +[components/AddOn/AddOn](components_AddOn_AddOn.md).default + +## Table of contents + +### Variables + +- [defaultProps](components_AddOn_AddOn.default.md#defaultprops) +- [propTypes](components_AddOn_AddOn.default.md#proptypes) + +## Variables + +### defaultProps + +• **defaultProps**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `children` | ``null`` | +| `extras` | {} | +| `name` | `string` | + +#### Defined in + +[src/components/AddOn/AddOn.tsx:21](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/AddOn/AddOn.tsx#L21) + +___ + +### propTypes + +• **propTypes**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `children` | `Requireable`<`any`\> | +| `extras` | `Requireable`<`InferProps`<{ `actions`: `Requireable`<`InferProps`<{}\>\> ; `components`: `Requireable`<`InferProps`<{}\>\> }\>\> | +| `name` | `Requireable`<`string`\> | + +#### Defined in + +[src/components/AddOn/AddOn.tsx:27](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/AddOn/AddOn.tsx#L27) diff --git a/talawa-admin-docs/modules/components_AddOn_AddOn.md b/talawa-admin-docs/modules/components_AddOn_AddOn.md new file mode 100644 index 0000000000..ad376d81f5 --- /dev/null +++ b/talawa-admin-docs/modules/components_AddOn_AddOn.md @@ -0,0 +1,33 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/AddOn/AddOn + +# Module: components/AddOn/AddOn + +## Table of contents + +### Namespaces + +- [default](components_AddOn_AddOn.default.md) + +### Functions + +- [default](components_AddOn_AddOn.md#default) + +## Functions + +### default + +▸ **default**(`«destructured»`): `JSX.Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `«destructured»` | `InterfaceAddOnProps` | + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/AddOn/AddOn.tsx:11](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/AddOn/AddOn.tsx#L11) diff --git a/talawa-admin-docs/modules/components_AddOn_AddOn_test.md b/talawa-admin-docs/modules/components_AddOn_AddOn_test.md new file mode 100644 index 0000000000..fc00b6659e --- /dev/null +++ b/talawa-admin-docs/modules/components_AddOn_AddOn_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/AddOn/AddOn.test + +# Module: components/AddOn/AddOn.test diff --git a/talawa-admin-docs/modules/components_AddOn_core_AddOnEntry_AddOnEntry.default.md b/talawa-admin-docs/modules/components_AddOn_core_AddOnEntry_AddOnEntry.default.md new file mode 100644 index 0000000000..a0331db813 --- /dev/null +++ b/talawa-admin-docs/modules/components_AddOn_core_AddOnEntry_AddOnEntry.default.md @@ -0,0 +1,52 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / [components/AddOn/core/AddOnEntry/AddOnEntry](components_AddOn_core_AddOnEntry_AddOnEntry.md) / default + +# Namespace: default + +[components/AddOn/core/AddOnEntry/AddOnEntry](components_AddOn_core_AddOnEntry_AddOnEntry.md).default + +## Table of contents + +### Variables + +- [defaultProps](components_AddOn_core_AddOnEntry_AddOnEntry.default.md#defaultprops) +- [propTypes](components_AddOn_core_AddOnEntry_AddOnEntry.default.md#proptypes) + +## Variables + +### defaultProps + +• **defaultProps**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `configurable` | `boolean` | +| `description` | `string` | +| `enabled` | `boolean` | +| `isInstalled` | `boolean` | +| `title` | `string` | + +#### Defined in + +[src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx:190](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx#L190) + +___ + +### propTypes + +• **propTypes**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `configurable` | `Requireable`<`boolean`\> | +| `description` | `Requireable`<`string`\> | +| `enabled` | `Requireable`<`boolean`\> | +| `isInstalled` | `Requireable`<`boolean`\> | +| `title` | `Requireable`<`string`\> | + +#### Defined in + +[src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx:198](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx#L198) diff --git a/talawa-admin-docs/modules/components_AddOn_core_AddOnEntry_AddOnEntry.md b/talawa-admin-docs/modules/components_AddOn_core_AddOnEntry_AddOnEntry.md new file mode 100644 index 0000000000..118b367b09 --- /dev/null +++ b/talawa-admin-docs/modules/components_AddOn_core_AddOnEntry_AddOnEntry.md @@ -0,0 +1,33 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/AddOn/core/AddOnEntry/AddOnEntry + +# Module: components/AddOn/core/AddOnEntry/AddOnEntry + +## Table of contents + +### Namespaces + +- [default](components_AddOn_core_AddOnEntry_AddOnEntry.default.md) + +### Functions + +- [default](components_AddOn_core_AddOnEntry_AddOnEntry.md#default) + +## Functions + +### default + +▸ **default**(`«destructured»`): `JSX.Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `«destructured»` | `InterfaceAddOnEntryProps` | + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx:26](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx#L26) diff --git a/talawa-admin-docs/modules/components_AddOn_core_AddOnEntry_AddOnEntry_test.md b/talawa-admin-docs/modules/components_AddOn_core_AddOnEntry_AddOnEntry_test.md new file mode 100644 index 0000000000..6190c7df8d --- /dev/null +++ b/talawa-admin-docs/modules/components_AddOn_core_AddOnEntry_AddOnEntry_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/AddOn/core/AddOnEntry/AddOnEntry.test + +# Module: components/AddOn/core/AddOnEntry/AddOnEntry.test diff --git a/talawa-admin-docs/modules/components_AddOn_core_AddOnRegister_AddOnRegister.default.md b/talawa-admin-docs/modules/components_AddOn_core_AddOnRegister_AddOnRegister.default.md new file mode 100644 index 0000000000..07f216c14c --- /dev/null +++ b/talawa-admin-docs/modules/components_AddOn_core_AddOnRegister_AddOnRegister.default.md @@ -0,0 +1,44 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / [components/AddOn/core/AddOnRegister/AddOnRegister](components_AddOn_core_AddOnRegister_AddOnRegister.md) / default + +# Namespace: default + +[components/AddOn/core/AddOnRegister/AddOnRegister](components_AddOn_core_AddOnRegister_AddOnRegister.md).default + +## Table of contents + +### Variables + +- [defaultProps](components_AddOn_core_AddOnRegister_AddOnRegister.default.md#defaultprops) +- [propTypes](components_AddOn_core_AddOnRegister_AddOnRegister.default.md#proptypes) + +## Variables + +### defaultProps + +• **defaultProps**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `createdBy` | `string` | + +#### Defined in + +[src/components/AddOn/core/AddOnRegister/AddOnRegister.tsx:151](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/AddOn/core/AddOnRegister/AddOnRegister.tsx#L151) + +___ + +### propTypes + +• **propTypes**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `createdBy` | `Requireable`<`string`\> | + +#### Defined in + +[src/components/AddOn/core/AddOnRegister/AddOnRegister.tsx:155](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/AddOn/core/AddOnRegister/AddOnRegister.tsx#L155) diff --git a/talawa-admin-docs/modules/components_AddOn_core_AddOnRegister_AddOnRegister.md b/talawa-admin-docs/modules/components_AddOn_core_AddOnRegister_AddOnRegister.md new file mode 100644 index 0000000000..810ecc9829 --- /dev/null +++ b/talawa-admin-docs/modules/components_AddOn_core_AddOnRegister_AddOnRegister.md @@ -0,0 +1,33 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/AddOn/core/AddOnRegister/AddOnRegister + +# Module: components/AddOn/core/AddOnRegister/AddOnRegister + +## Table of contents + +### Namespaces + +- [default](components_AddOn_core_AddOnRegister_AddOnRegister.default.md) + +### Functions + +- [default](components_AddOn_core_AddOnRegister_AddOnRegister.md#default) + +## Functions + +### default + +▸ **default**(`«destructured»`): `JSX.Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `«destructured»` | `InterfaceAddOnRegisterProps` | + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/AddOn/core/AddOnRegister/AddOnRegister.tsx:24](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/AddOn/core/AddOnRegister/AddOnRegister.tsx#L24) diff --git a/talawa-admin-docs/modules/components_AddOn_core_AddOnRegister_AddOnRegister_test.md b/talawa-admin-docs/modules/components_AddOn_core_AddOnRegister_AddOnRegister_test.md new file mode 100644 index 0000000000..2a3008d564 --- /dev/null +++ b/talawa-admin-docs/modules/components_AddOn_core_AddOnRegister_AddOnRegister_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/AddOn/core/AddOnRegister/AddOnRegister.test + +# Module: components/AddOn/core/AddOnRegister/AddOnRegister.test diff --git a/talawa-admin-docs/modules/components_AddOn_core_AddOnStore_AddOnStore.default.md b/talawa-admin-docs/modules/components_AddOn_core_AddOnStore_AddOnStore.default.md new file mode 100644 index 0000000000..5f9275d3b5 --- /dev/null +++ b/talawa-admin-docs/modules/components_AddOn_core_AddOnStore_AddOnStore.default.md @@ -0,0 +1,32 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / [components/AddOn/core/AddOnStore/AddOnStore](components_AddOn_core_AddOnStore_AddOnStore.md) / default + +# Namespace: default + +[components/AddOn/core/AddOnStore/AddOnStore](components_AddOn_core_AddOnStore_AddOnStore.md).default + +## Table of contents + +### Variables + +- [defaultProps](components_AddOn_core_AddOnStore_AddOnStore.default.md#defaultprops) +- [propTypes](components_AddOn_core_AddOnStore_AddOnStore.default.md#proptypes) + +## Variables + +### defaultProps + +• **defaultProps**: `Object` + +#### Defined in + +[src/components/AddOn/core/AddOnStore/AddOnStore.tsx:354](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/AddOn/core/AddOnStore/AddOnStore.tsx#L354) + +___ + +### propTypes + +• **propTypes**: `Object` + +#### Defined in + +[src/components/AddOn/core/AddOnStore/AddOnStore.tsx:356](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/AddOn/core/AddOnStore/AddOnStore.tsx#L356) diff --git a/talawa-admin-docs/modules/components_AddOn_core_AddOnStore_AddOnStore.md b/talawa-admin-docs/modules/components_AddOn_core_AddOnStore_AddOnStore.md new file mode 100644 index 0000000000..c0550d8a9b --- /dev/null +++ b/talawa-admin-docs/modules/components_AddOn_core_AddOnStore_AddOnStore.md @@ -0,0 +1,27 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/AddOn/core/AddOnStore/AddOnStore + +# Module: components/AddOn/core/AddOnStore/AddOnStore + +## Table of contents + +### Namespaces + +- [default](components_AddOn_core_AddOnStore_AddOnStore.default.md) + +### Functions + +- [default](components_AddOn_core_AddOnStore_AddOnStore.md#default) + +## Functions + +### default + +▸ **default**(): `JSX.Element` + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/AddOn/core/AddOnStore/AddOnStore.tsx:26](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/AddOn/core/AddOnStore/AddOnStore.tsx#L26) diff --git a/talawa-admin-docs/modules/components_AddOn_core_AddOnStore_AddOnStore_test.md b/talawa-admin-docs/modules/components_AddOn_core_AddOnStore_AddOnStore_test.md new file mode 100644 index 0000000000..81c941f51d --- /dev/null +++ b/talawa-admin-docs/modules/components_AddOn_core_AddOnStore_AddOnStore_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/AddOn/core/AddOnStore/AddOnStore.test + +# Module: components/AddOn/core/AddOnStore/AddOnStore.test diff --git a/talawa-admin-docs/modules/components_AddOn_support_components_Action_Action.md b/talawa-admin-docs/modules/components_AddOn_support_components_Action_Action.md new file mode 100644 index 0000000000..66bde03656 --- /dev/null +++ b/talawa-admin-docs/modules/components_AddOn_support_components_Action_Action.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/AddOn/support/components/Action/Action + +# Module: components/AddOn/support/components/Action/Action + +## Table of contents + +### Functions + +- [default](components_AddOn_support_components_Action_Action.md#default) + +## Functions + +### default + +▸ **default**(`props`): `JSX.Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `InterfaceActionProps` | + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/AddOn/support/components/Action/Action.tsx:10](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/AddOn/support/components/Action/Action.tsx#L10) diff --git a/talawa-admin-docs/modules/components_AddOn_support_components_Action_Action_test.md b/talawa-admin-docs/modules/components_AddOn_support_components_Action_Action_test.md new file mode 100644 index 0000000000..411e01b71c --- /dev/null +++ b/talawa-admin-docs/modules/components_AddOn_support_components_Action_Action_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/AddOn/support/components/Action/Action.test + +# Module: components/AddOn/support/components/Action/Action.test diff --git a/talawa-admin-docs/modules/components_AddOn_support_components_MainContent_MainContent.md b/talawa-admin-docs/modules/components_AddOn_support_components_MainContent_MainContent.md new file mode 100644 index 0000000000..2a0134ef66 --- /dev/null +++ b/talawa-admin-docs/modules/components_AddOn_support_components_MainContent_MainContent.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/AddOn/support/components/MainContent/MainContent + +# Module: components/AddOn/support/components/MainContent/MainContent + +## Table of contents + +### Functions + +- [default](components_AddOn_support_components_MainContent_MainContent.md#default) + +## Functions + +### default + +▸ **default**(`«destructured»`): `JSX.Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `«destructured»` | `InterfaceMainContentProps` | + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/AddOn/support/components/MainContent/MainContent.tsx:10](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/AddOn/support/components/MainContent/MainContent.tsx#L10) diff --git a/talawa-admin-docs/modules/components_AddOn_support_components_MainContent_MainContent_test.md b/talawa-admin-docs/modules/components_AddOn_support_components_MainContent_MainContent_test.md new file mode 100644 index 0000000000..9374ee4ed1 --- /dev/null +++ b/talawa-admin-docs/modules/components_AddOn_support_components_MainContent_MainContent_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/AddOn/support/components/MainContent/MainContent.test + +# Module: components/AddOn/support/components/MainContent/MainContent.test diff --git a/talawa-admin-docs/modules/components_AddOn_support_components_SidePanel_SidePanel.md b/talawa-admin-docs/modules/components_AddOn_support_components_SidePanel_SidePanel.md new file mode 100644 index 0000000000..ae5cb247c8 --- /dev/null +++ b/talawa-admin-docs/modules/components_AddOn_support_components_SidePanel_SidePanel.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/AddOn/support/components/SidePanel/SidePanel + +# Module: components/AddOn/support/components/SidePanel/SidePanel + +## Table of contents + +### Functions + +- [default](components_AddOn_support_components_SidePanel_SidePanel.md#default) + +## Functions + +### default + +▸ **default**(`«destructured»`): `JSX.Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `«destructured»` | `InterfaceSidePanelProps` | + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/AddOn/support/components/SidePanel/SidePanel.tsx:10](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/AddOn/support/components/SidePanel/SidePanel.tsx#L10) diff --git a/talawa-admin-docs/modules/components_AddOn_support_components_SidePanel_SidePanel_test.md b/talawa-admin-docs/modules/components_AddOn_support_components_SidePanel_SidePanel_test.md new file mode 100644 index 0000000000..7f2017c98d --- /dev/null +++ b/talawa-admin-docs/modules/components_AddOn_support_components_SidePanel_SidePanel_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/AddOn/support/components/SidePanel/SidePanel.test + +# Module: components/AddOn/support/components/SidePanel/SidePanel.test diff --git a/talawa-admin-docs/modules/components_AddOn_support_services_Plugin_helper.md b/talawa-admin-docs/modules/components_AddOn_support_services_Plugin_helper.md new file mode 100644 index 0000000000..07b4879af6 --- /dev/null +++ b/talawa-admin-docs/modules/components_AddOn_support_services_Plugin_helper.md @@ -0,0 +1,9 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/AddOn/support/services/Plugin.helper + +# Module: components/AddOn/support/services/Plugin.helper + +## Table of contents + +### Classes + +- [default](../classes/components_AddOn_support_services_Plugin_helper.default.md) diff --git a/talawa-admin-docs/modules/components_AddOn_support_services_Render_helper.md b/talawa-admin-docs/modules/components_AddOn_support_services_Render_helper.md new file mode 100644 index 0000000000..845a9a0e7d --- /dev/null +++ b/talawa-admin-docs/modules/components_AddOn_support_services_Render_helper.md @@ -0,0 +1,9 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/AddOn/support/services/Render.helper + +# Module: components/AddOn/support/services/Render.helper + +## Table of contents + +### Classes + +- [default](../classes/components_AddOn_support_services_Render_helper.default.md) diff --git a/talawa-admin-docs/modules/components_ChangeLanguageDropdown_ChangeLanguageDropDown.md b/talawa-admin-docs/modules/components_ChangeLanguageDropdown_ChangeLanguageDropDown.md new file mode 100644 index 0000000000..7ce929fecd --- /dev/null +++ b/talawa-admin-docs/modules/components_ChangeLanguageDropdown_ChangeLanguageDropDown.md @@ -0,0 +1,50 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/ChangeLanguageDropdown/ChangeLanguageDropDown + +# Module: components/ChangeLanguageDropdown/ChangeLanguageDropDown + +## Table of contents + +### Functions + +- [changeLanguage](components_ChangeLanguageDropdown_ChangeLanguageDropDown.md#changelanguage) +- [default](components_ChangeLanguageDropdown_ChangeLanguageDropDown.md#default) + +## Functions + +### changeLanguage + +▸ **changeLanguage**(`languageCode`): `Promise`<`void`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `languageCode` | `string` | + +#### Returns + +`Promise`<`void`\> + +#### Defined in + +[src/components/ChangeLanguageDropdown/ChangeLanguageDropDown.tsx:14](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/ChangeLanguageDropdown/ChangeLanguageDropDown.tsx#L14) + +___ + +### default + +▸ **default**(`props`): `Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `InterfaceChangeLanguageDropDownProps` | + +#### Returns + +`Element` + +#### Defined in + +[src/components/ChangeLanguageDropdown/ChangeLanguageDropDown.tsx:18](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/ChangeLanguageDropdown/ChangeLanguageDropDown.tsx#L18) diff --git a/talawa-admin-docs/modules/components_ChangeLanguageDropdown_ChangeLanguageDropdown_test.md b/talawa-admin-docs/modules/components_ChangeLanguageDropdown_ChangeLanguageDropdown_test.md new file mode 100644 index 0000000000..205cda0fc2 --- /dev/null +++ b/talawa-admin-docs/modules/components_ChangeLanguageDropdown_ChangeLanguageDropdown_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/ChangeLanguageDropdown/ChangeLanguageDropdown.test + +# Module: components/ChangeLanguageDropdown/ChangeLanguageDropdown.test diff --git a/talawa-admin-docs/modules/components_CheckIn_CheckInModal.md b/talawa-admin-docs/modules/components_CheckIn_CheckInModal.md new file mode 100644 index 0000000000..211a200bf0 --- /dev/null +++ b/talawa-admin-docs/modules/components_CheckIn_CheckInModal.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/CheckIn/CheckInModal + +# Module: components/CheckIn/CheckInModal + +## Table of contents + +### Functions + +- [CheckInModal](components_CheckIn_CheckInModal.md#checkinmodal) + +## Functions + +### CheckInModal + +▸ **CheckInModal**(`props`): `Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | [`InterfaceModalProp`](../interfaces/components_CheckIn_types.InterfaceModalProp.md) | + +#### Returns + +`Element` + +#### Defined in + +[src/components/CheckIn/CheckInModal.tsx:16](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/CheckIn/CheckInModal.tsx#L16) diff --git a/talawa-admin-docs/modules/components_CheckIn_CheckInModal_test.md b/talawa-admin-docs/modules/components_CheckIn_CheckInModal_test.md new file mode 100644 index 0000000000..b1e389bc6f --- /dev/null +++ b/talawa-admin-docs/modules/components_CheckIn_CheckInModal_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/CheckIn/CheckInModal.test + +# Module: components/CheckIn/CheckInModal.test diff --git a/talawa-admin-docs/modules/components_CheckIn_CheckInWrapper.md b/talawa-admin-docs/modules/components_CheckIn_CheckInWrapper.md new file mode 100644 index 0000000000..dae7e45724 --- /dev/null +++ b/talawa-admin-docs/modules/components_CheckIn_CheckInWrapper.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/CheckIn/CheckInWrapper + +# Module: components/CheckIn/CheckInWrapper + +## Table of contents + +### Functions + +- [CheckInWrapper](components_CheckIn_CheckInWrapper.md#checkinwrapper) + +## Functions + +### CheckInWrapper + +▸ **CheckInWrapper**(`props`): `Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `PropType` | + +#### Returns + +`Element` + +#### Defined in + +[src/components/CheckIn/CheckInWrapper.tsx:9](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/CheckIn/CheckInWrapper.tsx#L9) diff --git a/talawa-admin-docs/modules/components_CheckIn_CheckInWrapper_test.md b/talawa-admin-docs/modules/components_CheckIn_CheckInWrapper_test.md new file mode 100644 index 0000000000..ba4052472f --- /dev/null +++ b/talawa-admin-docs/modules/components_CheckIn_CheckInWrapper_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/CheckIn/CheckInWrapper.test + +# Module: components/CheckIn/CheckInWrapper.test diff --git a/talawa-admin-docs/modules/components_CheckIn_TableRow.md b/talawa-admin-docs/modules/components_CheckIn_TableRow.md new file mode 100644 index 0000000000..34921ffd77 --- /dev/null +++ b/talawa-admin-docs/modules/components_CheckIn_TableRow.md @@ -0,0 +1,31 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/CheckIn/TableRow + +# Module: components/CheckIn/TableRow + +## Table of contents + +### Functions + +- [TableRow](components_CheckIn_TableRow.md#tablerow) + +## Functions + +### TableRow + +▸ **TableRow**(`«destructured»`): `Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `«destructured»` | `Object` | +| › `data` | [`InterfaceTableCheckIn`](../interfaces/components_CheckIn_types.InterfaceTableCheckIn.md) | +| › `refetch` | () => `void` | + +#### Returns + +`Element` + +#### Defined in + +[src/components/CheckIn/TableRow.tsx:10](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/CheckIn/TableRow.tsx#L10) diff --git a/talawa-admin-docs/modules/components_CheckIn_TableRow_test.md b/talawa-admin-docs/modules/components_CheckIn_TableRow_test.md new file mode 100644 index 0000000000..2d26732b41 --- /dev/null +++ b/talawa-admin-docs/modules/components_CheckIn_TableRow_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/CheckIn/TableRow.test + +# Module: components/CheckIn/TableRow.test diff --git a/talawa-admin-docs/modules/components_CheckIn_mocks.md b/talawa-admin-docs/modules/components_CheckIn_mocks.md new file mode 100644 index 0000000000..67d7a2b123 --- /dev/null +++ b/talawa-admin-docs/modules/components_CheckIn_mocks.md @@ -0,0 +1,41 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/CheckIn/mocks + +# Module: components/CheckIn/mocks + +## Table of contents + +### Variables + +- [checkInMutationSuccess](components_CheckIn_mocks.md#checkinmutationsuccess) +- [checkInMutationUnsuccess](components_CheckIn_mocks.md#checkinmutationunsuccess) +- [checkInQueryMock](components_CheckIn_mocks.md#checkinquerymock) + +## Variables + +### checkInMutationSuccess + +• `Const` **checkInMutationSuccess**: { `request`: { `query`: `DocumentNode` = MARK\_CHECKIN; `variables`: { `allotedRoom`: `string` = ''; `allotedSeat`: `string` = ''; `eventId`: `string` = 'event123'; `userId`: `string` = 'user123' } } ; `result`: { `data`: { `checkIn`: { `_id`: `string` = '123' } } } }[] + +#### Defined in + +[src/components/CheckIn/mocks.ts:48](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/CheckIn/mocks.ts#L48) + +___ + +### checkInMutationUnsuccess + +• `Const` **checkInMutationUnsuccess**: { `error`: `Error` ; `request`: { `query`: `DocumentNode` = MARK\_CHECKIN; `variables`: { `allotedRoom`: `string` = ''; `allotedSeat`: `string` = ''; `eventId`: `string` = 'event123'; `userId`: `string` = 'user123' } } }[] + +#### Defined in + +[src/components/CheckIn/mocks.ts:69](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/CheckIn/mocks.ts#L69) + +___ + +### checkInQueryMock + +• `Const` **checkInQueryMock**: { `request`: { `query`: `DocumentNode` = EVENT\_CHECKINS; `variables`: { `id`: `string` = 'event123' } } ; `result`: { `data`: [`InterfaceAttendeeQueryResponse`](../interfaces/components_CheckIn_types.InterfaceAttendeeQueryResponse.md) = checkInQueryData } }[] + +#### Defined in + +[src/components/CheckIn/mocks.ts:36](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/CheckIn/mocks.ts#L36) diff --git a/talawa-admin-docs/modules/components_CheckIn_tagTemplate.md b/talawa-admin-docs/modules/components_CheckIn_tagTemplate.md new file mode 100644 index 0000000000..efb1198865 --- /dev/null +++ b/talawa-admin-docs/modules/components_CheckIn_tagTemplate.md @@ -0,0 +1,19 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/CheckIn/tagTemplate + +# Module: components/CheckIn/tagTemplate + +## Table of contents + +### Variables + +- [tagTemplate](components_CheckIn_tagTemplate.md#tagtemplate) + +## Variables + +### tagTemplate + +• `Const` **tagTemplate**: `Template` + +#### Defined in + +[src/components/CheckIn/tagTemplate.ts:3](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/CheckIn/tagTemplate.ts#L3) diff --git a/talawa-admin-docs/modules/components_CheckIn_types.md b/talawa-admin-docs/modules/components_CheckIn_types.md new file mode 100644 index 0000000000..5b47904381 --- /dev/null +++ b/talawa-admin-docs/modules/components_CheckIn_types.md @@ -0,0 +1,14 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/CheckIn/types + +# Module: components/CheckIn/types + +## Table of contents + +### Interfaces + +- [InterfaceAttendeeCheckIn](../interfaces/components_CheckIn_types.InterfaceAttendeeCheckIn.md) +- [InterfaceAttendeeQueryResponse](../interfaces/components_CheckIn_types.InterfaceAttendeeQueryResponse.md) +- [InterfaceModalProp](../interfaces/components_CheckIn_types.InterfaceModalProp.md) +- [InterfaceTableCheckIn](../interfaces/components_CheckIn_types.InterfaceTableCheckIn.md) +- [InterfaceTableData](../interfaces/components_CheckIn_types.InterfaceTableData.md) +- [InterfaceUser](../interfaces/components_CheckIn_types.InterfaceUser.md) diff --git a/talawa-admin-docs/modules/components_CollapsibleDropdown_CollapsibleDropdown.md b/talawa-admin-docs/modules/components_CollapsibleDropdown_CollapsibleDropdown.md new file mode 100644 index 0000000000..249c1fc758 --- /dev/null +++ b/talawa-admin-docs/modules/components_CollapsibleDropdown_CollapsibleDropdown.md @@ -0,0 +1,33 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/CollapsibleDropdown/CollapsibleDropdown + +# Module: components/CollapsibleDropdown/CollapsibleDropdown + +## Table of contents + +### Interfaces + +- [InterfaceCollapsibleDropdown](../interfaces/components_CollapsibleDropdown_CollapsibleDropdown.InterfaceCollapsibleDropdown.md) + +### Functions + +- [default](components_CollapsibleDropdown_CollapsibleDropdown.md#default) + +## Functions + +### default + +▸ **default**(`«destructured»`): `Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `«destructured»` | [`InterfaceCollapsibleDropdown`](../interfaces/components_CollapsibleDropdown_CollapsibleDropdown.InterfaceCollapsibleDropdown.md) | + +#### Returns + +`Element` + +#### Defined in + +[src/components/CollapsibleDropdown/CollapsibleDropdown.tsx:13](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/CollapsibleDropdown/CollapsibleDropdown.tsx#L13) diff --git a/talawa-admin-docs/modules/components_CollapsibleDropdown_CollapsibleDropdown_test.md b/talawa-admin-docs/modules/components_CollapsibleDropdown_CollapsibleDropdown_test.md new file mode 100644 index 0000000000..e5eb033261 --- /dev/null +++ b/talawa-admin-docs/modules/components_CollapsibleDropdown_CollapsibleDropdown_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/CollapsibleDropdown/CollapsibleDropdown.test + +# Module: components/CollapsibleDropdown/CollapsibleDropdown.test diff --git a/talawa-admin-docs/modules/components_ContriStats_ContriStats.md b/talawa-admin-docs/modules/components_ContriStats_ContriStats.md new file mode 100644 index 0000000000..a7cc9e6d75 --- /dev/null +++ b/talawa-admin-docs/modules/components_ContriStats_ContriStats.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/ContriStats/ContriStats + +# Module: components/ContriStats/ContriStats + +## Table of contents + +### Functions + +- [default](components_ContriStats_ContriStats.md#default) + +## Functions + +### default + +▸ **default**(`props`): `JSX.Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `InterfaceContriStatsProps` | + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/ContriStats/ContriStats.tsx:14](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/ContriStats/ContriStats.tsx#L14) diff --git a/talawa-admin-docs/modules/components_ContriStats_ContriStats_test.md b/talawa-admin-docs/modules/components_ContriStats_ContriStats_test.md new file mode 100644 index 0000000000..b1faeb7015 --- /dev/null +++ b/talawa-admin-docs/modules/components_ContriStats_ContriStats_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/ContriStats/ContriStats.test + +# Module: components/ContriStats/ContriStats.test diff --git a/talawa-admin-docs/modules/components_EventCalendar_EventCalendar.md b/talawa-admin-docs/modules/components_EventCalendar_EventCalendar.md new file mode 100644 index 0000000000..a6d00af0cb --- /dev/null +++ b/talawa-admin-docs/modules/components_EventCalendar_EventCalendar.md @@ -0,0 +1,30 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/EventCalendar/EventCalendar + +# Module: components/EventCalendar/EventCalendar + +## Table of contents + +### Functions + +- [default](components_EventCalendar_EventCalendar.md#default) + +## Functions + +### default + +▸ **default**(`props`, `context?`): ``null`` \| `ReactElement`<`any`, `any`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `PropsWithChildren`<`InterfaceCalendarProps`\> | +| `context?` | `any` | + +#### Returns + +``null`` \| `ReactElement`<`any`, `any`\> + +#### Defined in + +node_modules/@types/react/index.d.ts:543 diff --git a/talawa-admin-docs/modules/components_EventCalendar_EventCalendar_test.md b/talawa-admin-docs/modules/components_EventCalendar_EventCalendar_test.md new file mode 100644 index 0000000000..4a30c73ee9 --- /dev/null +++ b/talawa-admin-docs/modules/components_EventCalendar_EventCalendar_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/EventCalendar/EventCalendar.test + +# Module: components/EventCalendar/EventCalendar.test diff --git a/talawa-admin-docs/modules/components_EventListCard_EventListCard.md b/talawa-admin-docs/modules/components_EventListCard_EventListCard.md new file mode 100644 index 0000000000..d6c9251acf --- /dev/null +++ b/talawa-admin-docs/modules/components_EventListCard_EventListCard.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/EventListCard/EventListCard + +# Module: components/EventListCard/EventListCard + +## Table of contents + +### Functions + +- [default](components_EventListCard_EventListCard.md#default) + +## Functions + +### default + +▸ **default**(`props`): `JSX.Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `InterfaceEventListCardProps` | + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/EventListCard/EventListCard.tsx:32](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/EventListCard/EventListCard.tsx#L32) diff --git a/talawa-admin-docs/modules/components_EventListCard_EventListCard_test.md b/talawa-admin-docs/modules/components_EventListCard_EventListCard_test.md new file mode 100644 index 0000000000..768a6041a2 --- /dev/null +++ b/talawa-admin-docs/modules/components_EventListCard_EventListCard_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/EventListCard/EventListCard.test + +# Module: components/EventListCard/EventListCard.test diff --git a/talawa-admin-docs/modules/components_EventProjectModals_AddEventProjectModal.md b/talawa-admin-docs/modules/components_EventProjectModals_AddEventProjectModal.md new file mode 100644 index 0000000000..ca1dd3aa24 --- /dev/null +++ b/talawa-admin-docs/modules/components_EventProjectModals_AddEventProjectModal.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/EventProjectModals/AddEventProjectModal + +# Module: components/EventProjectModals/AddEventProjectModal + +## Table of contents + +### Functions + +- [AddEventProjectModal](components_EventProjectModals_AddEventProjectModal.md#addeventprojectmodal) + +## Functions + +### AddEventProjectModal + +▸ **AddEventProjectModal**(`«destructured»`): `Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `«destructured»` | `ModalPropType` | + +#### Returns + +`Element` + +#### Defined in + +[src/components/EventProjectModals/AddEventProjectModal.tsx:14](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/EventProjectModals/AddEventProjectModal.tsx#L14) diff --git a/talawa-admin-docs/modules/components_EventProjectModals_AddEventProjectModal_test.md b/talawa-admin-docs/modules/components_EventProjectModals_AddEventProjectModal_test.md new file mode 100644 index 0000000000..f690026c0a --- /dev/null +++ b/talawa-admin-docs/modules/components_EventProjectModals_AddEventProjectModal_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/EventProjectModals/AddEventProjectModal.test + +# Module: components/EventProjectModals/AddEventProjectModal.test diff --git a/talawa-admin-docs/modules/components_EventProjectModals_DeleteEventProjectModal.md b/talawa-admin-docs/modules/components_EventProjectModals_DeleteEventProjectModal.md new file mode 100644 index 0000000000..7c87827aa7 --- /dev/null +++ b/talawa-admin-docs/modules/components_EventProjectModals_DeleteEventProjectModal.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/EventProjectModals/DeleteEventProjectModal + +# Module: components/EventProjectModals/DeleteEventProjectModal + +## Table of contents + +### Functions + +- [DeleteEventProjectModal](components_EventProjectModals_DeleteEventProjectModal.md#deleteeventprojectmodal) + +## Functions + +### DeleteEventProjectModal + +▸ **DeleteEventProjectModal**(`props`): `Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `ModalPropType` | + +#### Returns + +`Element` + +#### Defined in + +[src/components/EventProjectModals/DeleteEventProjectModal.tsx:18](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/EventProjectModals/DeleteEventProjectModal.tsx#L18) diff --git a/talawa-admin-docs/modules/components_EventProjectModals_DeleteEventProjectModal_test.md b/talawa-admin-docs/modules/components_EventProjectModals_DeleteEventProjectModal_test.md new file mode 100644 index 0000000000..383f71341f --- /dev/null +++ b/talawa-admin-docs/modules/components_EventProjectModals_DeleteEventProjectModal_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/EventProjectModals/DeleteEventProjectModal.test + +# Module: components/EventProjectModals/DeleteEventProjectModal.test diff --git a/talawa-admin-docs/modules/components_EventProjectModals_UpdateEventProjectModal.md b/talawa-admin-docs/modules/components_EventProjectModals_UpdateEventProjectModal.md new file mode 100644 index 0000000000..b087f83aee --- /dev/null +++ b/talawa-admin-docs/modules/components_EventProjectModals_UpdateEventProjectModal.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/EventProjectModals/UpdateEventProjectModal + +# Module: components/EventProjectModals/UpdateEventProjectModal + +## Table of contents + +### Functions + +- [UpdateEventProjectModal](components_EventProjectModals_UpdateEventProjectModal.md#updateeventprojectmodal) + +## Functions + +### UpdateEventProjectModal + +▸ **UpdateEventProjectModal**(`props`): `Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `ModalPropType` | + +#### Returns + +`Element` + +#### Defined in + +[src/components/EventProjectModals/UpdateEventProjectModal.tsx:18](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/EventProjectModals/UpdateEventProjectModal.tsx#L18) diff --git a/talawa-admin-docs/modules/components_EventProjectModals_UpdateEventProjectModal_test.md b/talawa-admin-docs/modules/components_EventProjectModals_UpdateEventProjectModal_test.md new file mode 100644 index 0000000000..d4e38295c3 --- /dev/null +++ b/talawa-admin-docs/modules/components_EventProjectModals_UpdateEventProjectModal_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/EventProjectModals/UpdateEventProjectModal.test + +# Module: components/EventProjectModals/UpdateEventProjectModal.test diff --git a/talawa-admin-docs/modules/components_EventRegistrantsModal_EventRegistrantsModal.md b/talawa-admin-docs/modules/components_EventRegistrantsModal_EventRegistrantsModal.md new file mode 100644 index 0000000000..7f672723fd --- /dev/null +++ b/talawa-admin-docs/modules/components_EventRegistrantsModal_EventRegistrantsModal.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/EventRegistrantsModal/EventRegistrantsModal + +# Module: components/EventRegistrantsModal/EventRegistrantsModal + +## Table of contents + +### Functions + +- [EventRegistrantsModal](components_EventRegistrantsModal_EventRegistrantsModal.md#eventregistrantsmodal) + +## Functions + +### EventRegistrantsModal + +▸ **EventRegistrantsModal**(`props`): `Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `ModalPropType` | + +#### Returns + +`Element` + +#### Defined in + +[src/components/EventRegistrantsModal/EventRegistrantsModal.tsx:31](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/EventRegistrantsModal/EventRegistrantsModal.tsx#L31) diff --git a/talawa-admin-docs/modules/components_EventRegistrantsModal_EventRegistrantsModal_test.md b/talawa-admin-docs/modules/components_EventRegistrantsModal_EventRegistrantsModal_test.md new file mode 100644 index 0000000000..f755a4e6d5 --- /dev/null +++ b/talawa-admin-docs/modules/components_EventRegistrantsModal_EventRegistrantsModal_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/EventRegistrantsModal/EventRegistrantsModal.test + +# Module: components/EventRegistrantsModal/EventRegistrantsModal.test diff --git a/talawa-admin-docs/modules/components_EventRegistrantsModal_EventRegistrantsWrapper.md b/talawa-admin-docs/modules/components_EventRegistrantsModal_EventRegistrantsWrapper.md new file mode 100644 index 0000000000..c7d0744c33 --- /dev/null +++ b/talawa-admin-docs/modules/components_EventRegistrantsModal_EventRegistrantsWrapper.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/EventRegistrantsModal/EventRegistrantsWrapper + +# Module: components/EventRegistrantsModal/EventRegistrantsWrapper + +## Table of contents + +### Functions + +- [EventRegistrantsWrapper](components_EventRegistrantsModal_EventRegistrantsWrapper.md#eventregistrantswrapper) + +## Functions + +### EventRegistrantsWrapper + +▸ **EventRegistrantsWrapper**(`props`): `Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `PropType` | + +#### Returns + +`Element` + +#### Defined in + +[src/components/EventRegistrantsModal/EventRegistrantsWrapper.tsx:10](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/EventRegistrantsModal/EventRegistrantsWrapper.tsx#L10) diff --git a/talawa-admin-docs/modules/components_EventRegistrantsModal_EventRegistrantsWrapper_test.md b/talawa-admin-docs/modules/components_EventRegistrantsModal_EventRegistrantsWrapper_test.md new file mode 100644 index 0000000000..e952929703 --- /dev/null +++ b/talawa-admin-docs/modules/components_EventRegistrantsModal_EventRegistrantsWrapper_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/EventRegistrantsModal/EventRegistrantsWrapper.test + +# Module: components/EventRegistrantsModal/EventRegistrantsWrapper.test diff --git a/talawa-admin-docs/modules/components_IconComponent_IconComponent.md b/talawa-admin-docs/modules/components_IconComponent_IconComponent.md new file mode 100644 index 0000000000..0d43d06cf2 --- /dev/null +++ b/talawa-admin-docs/modules/components_IconComponent_IconComponent.md @@ -0,0 +1,33 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/IconComponent/IconComponent + +# Module: components/IconComponent/IconComponent + +## Table of contents + +### Interfaces + +- [InterfaceIconComponent](../interfaces/components_IconComponent_IconComponent.InterfaceIconComponent.md) + +### Functions + +- [default](components_IconComponent_IconComponent.md#default) + +## Functions + +### default + +▸ **default**(`props`): `Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | [`InterfaceIconComponent`](../interfaces/components_IconComponent_IconComponent.InterfaceIconComponent.md) | + +#### Returns + +`Element` + +#### Defined in + +[src/components/IconComponent/IconComponent.tsx:19](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/IconComponent/IconComponent.tsx#L19) diff --git a/talawa-admin-docs/modules/components_IconComponent_IconComponent_test.md b/talawa-admin-docs/modules/components_IconComponent_IconComponent_test.md new file mode 100644 index 0000000000..4753149ae6 --- /dev/null +++ b/talawa-admin-docs/modules/components_IconComponent_IconComponent_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/IconComponent/IconComponent.test + +# Module: components/IconComponent/IconComponent.test diff --git a/talawa-admin-docs/modules/components_LandingPage_LandingPage.md b/talawa-admin-docs/modules/components_LandingPage_LandingPage.md new file mode 100644 index 0000000000..d74f17edb5 --- /dev/null +++ b/talawa-admin-docs/modules/components_LandingPage_LandingPage.md @@ -0,0 +1,23 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/LandingPage/LandingPage + +# Module: components/LandingPage/LandingPage + +## Table of contents + +### Functions + +- [default](components_LandingPage_LandingPage.md#default) + +## Functions + +### default + +▸ **default**(): `JSX.Element` + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/LandingPage/LandingPage.tsx:6](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/LandingPage/LandingPage.tsx#L6) diff --git a/talawa-admin-docs/modules/components_LandingPage_LandingPage_test.md b/talawa-admin-docs/modules/components_LandingPage_LandingPage_test.md new file mode 100644 index 0000000000..039cbf1ff6 --- /dev/null +++ b/talawa-admin-docs/modules/components_LandingPage_LandingPage_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/LandingPage/LandingPage.test + +# Module: components/LandingPage/LandingPage.test diff --git a/talawa-admin-docs/modules/components_LeftDrawerOrg_LeftDrawerOrg.md b/talawa-admin-docs/modules/components_LeftDrawerOrg_LeftDrawerOrg.md new file mode 100644 index 0000000000..e8da5ad34f --- /dev/null +++ b/talawa-admin-docs/modules/components_LeftDrawerOrg_LeftDrawerOrg.md @@ -0,0 +1,33 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/LeftDrawerOrg/LeftDrawerOrg + +# Module: components/LeftDrawerOrg/LeftDrawerOrg + +## Table of contents + +### Interfaces + +- [InterfaceLeftDrawerProps](../interfaces/components_LeftDrawerOrg_LeftDrawerOrg.InterfaceLeftDrawerProps.md) + +### Functions + +- [default](components_LeftDrawerOrg_LeftDrawerOrg.md#default) + +## Functions + +### default + +▸ **default**(`«destructured»`): `Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `«destructured»` | [`InterfaceLeftDrawerProps`](../interfaces/components_LeftDrawerOrg_LeftDrawerOrg.InterfaceLeftDrawerProps.md) | + +#### Returns + +`Element` + +#### Defined in + +[src/components/LeftDrawerOrg/LeftDrawerOrg.tsx:26](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/LeftDrawerOrg/LeftDrawerOrg.tsx#L26) diff --git a/talawa-admin-docs/modules/components_LeftDrawerOrg_LeftDrawerOrg_test.md b/talawa-admin-docs/modules/components_LeftDrawerOrg_LeftDrawerOrg_test.md new file mode 100644 index 0000000000..8923adc0c2 --- /dev/null +++ b/talawa-admin-docs/modules/components_LeftDrawerOrg_LeftDrawerOrg_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/LeftDrawerOrg/LeftDrawerOrg.test + +# Module: components/LeftDrawerOrg/LeftDrawerOrg.test diff --git a/talawa-admin-docs/modules/components_LeftDrawer_LeftDrawer.md b/talawa-admin-docs/modules/components_LeftDrawer_LeftDrawer.md new file mode 100644 index 0000000000..67af4bdfa5 --- /dev/null +++ b/talawa-admin-docs/modules/components_LeftDrawer_LeftDrawer.md @@ -0,0 +1,33 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/LeftDrawer/LeftDrawer + +# Module: components/LeftDrawer/LeftDrawer + +## Table of contents + +### Interfaces + +- [InterfaceLeftDrawerProps](../interfaces/components_LeftDrawer_LeftDrawer.InterfaceLeftDrawerProps.md) + +### Functions + +- [default](components_LeftDrawer_LeftDrawer.md#default) + +## Functions + +### default + +▸ **default**(`«destructured»`): `Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `«destructured»` | [`InterfaceLeftDrawerProps`](../interfaces/components_LeftDrawer_LeftDrawer.InterfaceLeftDrawerProps.md) | + +#### Returns + +`Element` + +#### Defined in + +[src/components/LeftDrawer/LeftDrawer.tsx:20](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/LeftDrawer/LeftDrawer.tsx#L20) diff --git a/talawa-admin-docs/modules/components_LeftDrawer_LeftDrawer_test.md b/talawa-admin-docs/modules/components_LeftDrawer_LeftDrawer_test.md new file mode 100644 index 0000000000..91d8b23c78 --- /dev/null +++ b/talawa-admin-docs/modules/components_LeftDrawer_LeftDrawer_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/LeftDrawer/LeftDrawer.test + +# Module: components/LeftDrawer/LeftDrawer.test diff --git a/talawa-admin-docs/modules/components_Loader_Loader.md b/talawa-admin-docs/modules/components_Loader_Loader.md new file mode 100644 index 0000000000..11141a8c7a --- /dev/null +++ b/talawa-admin-docs/modules/components_Loader_Loader.md @@ -0,0 +1,23 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/Loader/Loader + +# Module: components/Loader/Loader + +## Table of contents + +### Functions + +- [default](components_Loader_Loader.md#default) + +## Functions + +### default + +▸ **default**(): `Element` + +#### Returns + +`Element` + +#### Defined in + +[src/components/Loader/Loader.tsx:5](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/Loader/Loader.tsx#L5) diff --git a/talawa-admin-docs/modules/components_Loader_Loader_test.md b/talawa-admin-docs/modules/components_Loader_Loader_test.md new file mode 100644 index 0000000000..97f48de7d6 --- /dev/null +++ b/talawa-admin-docs/modules/components_Loader_Loader_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/Loader/Loader.test + +# Module: components/Loader/Loader.test diff --git a/talawa-admin-docs/modules/components_MemberRequestCard_MemberRequestCard.md b/talawa-admin-docs/modules/components_MemberRequestCard_MemberRequestCard.md new file mode 100644 index 0000000000..c47491fab3 --- /dev/null +++ b/talawa-admin-docs/modules/components_MemberRequestCard_MemberRequestCard.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/MemberRequestCard/MemberRequestCard + +# Module: components/MemberRequestCard/MemberRequestCard + +## Table of contents + +### Functions + +- [default](components_MemberRequestCard_MemberRequestCard.md#default) + +## Functions + +### default + +▸ **default**(`props`): `JSX.Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `InterfaceMemberRequestCardProps` | + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/MemberRequestCard/MemberRequestCard.tsx:26](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/MemberRequestCard/MemberRequestCard.tsx#L26) diff --git a/talawa-admin-docs/modules/components_MemberRequestCard_MemberRequestCard_test.md b/talawa-admin-docs/modules/components_MemberRequestCard_MemberRequestCard_test.md new file mode 100644 index 0000000000..467f66899c --- /dev/null +++ b/talawa-admin-docs/modules/components_MemberRequestCard_MemberRequestCard_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/MemberRequestCard/MemberRequestCard.test + +# Module: components/MemberRequestCard/MemberRequestCard.test diff --git a/talawa-admin-docs/modules/components_NotFound_NotFound.md b/talawa-admin-docs/modules/components_NotFound_NotFound.md new file mode 100644 index 0000000000..201dc29d3d --- /dev/null +++ b/talawa-admin-docs/modules/components_NotFound_NotFound.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/NotFound/NotFound + +# Module: components/NotFound/NotFound + +## Table of contents + +### Functions + +- [default](components_NotFound_NotFound.md#default) + +## Functions + +### default + +▸ **default**(`props`): `JSX.Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `InterfaceNotFoundProps` | + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/NotFound/NotFound.tsx:11](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/NotFound/NotFound.tsx#L11) diff --git a/talawa-admin-docs/modules/components_NotFound_NotFound_test.md b/talawa-admin-docs/modules/components_NotFound_NotFound_test.md new file mode 100644 index 0000000000..27f07457d2 --- /dev/null +++ b/talawa-admin-docs/modules/components_NotFound_NotFound_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/NotFound/NotFound.test + +# Module: components/NotFound/NotFound.test diff --git a/talawa-admin-docs/modules/components_OrgAdminListCard_OrgAdminListCard.md b/talawa-admin-docs/modules/components_OrgAdminListCard_OrgAdminListCard.md new file mode 100644 index 0000000000..becb2ee57b --- /dev/null +++ b/talawa-admin-docs/modules/components_OrgAdminListCard_OrgAdminListCard.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/OrgAdminListCard/OrgAdminListCard + +# Module: components/OrgAdminListCard/OrgAdminListCard + +## Table of contents + +### Functions + +- [default](components_OrgAdminListCard_OrgAdminListCard.md#default) + +## Functions + +### default + +▸ **default**(`props`): `JSX.Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `InterfaceOrgPeopleListCardProps` | + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/OrgAdminListCard/OrgAdminListCard.tsx:26](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/OrgAdminListCard/OrgAdminListCard.tsx#L26) diff --git a/talawa-admin-docs/modules/components_OrgAdminListCard_OrgAdminListCard_test.md b/talawa-admin-docs/modules/components_OrgAdminListCard_OrgAdminListCard_test.md new file mode 100644 index 0000000000..4c74c02867 --- /dev/null +++ b/talawa-admin-docs/modules/components_OrgAdminListCard_OrgAdminListCard_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/OrgAdminListCard/OrgAdminListCard.test + +# Module: components/OrgAdminListCard/OrgAdminListCard.test diff --git a/talawa-admin-docs/modules/components_OrgContriCards_OrgContriCards.md b/talawa-admin-docs/modules/components_OrgContriCards_OrgContriCards.md new file mode 100644 index 0000000000..92da0a07c0 --- /dev/null +++ b/talawa-admin-docs/modules/components_OrgContriCards_OrgContriCards.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/OrgContriCards/OrgContriCards + +# Module: components/OrgContriCards/OrgContriCards + +## Table of contents + +### Functions + +- [default](components_OrgContriCards_OrgContriCards.md#default) + +## Functions + +### default + +▸ **default**(`props`): `JSX.Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `InterfaceOrgContriCardsProps` | + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/OrgContriCards/OrgContriCards.tsx:17](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/OrgContriCards/OrgContriCards.tsx#L17) diff --git a/talawa-admin-docs/modules/components_OrgContriCards_OrgContriCards_test.md b/talawa-admin-docs/modules/components_OrgContriCards_OrgContriCards_test.md new file mode 100644 index 0000000000..32030428bb --- /dev/null +++ b/talawa-admin-docs/modules/components_OrgContriCards_OrgContriCards_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/OrgContriCards/OrgContriCards.test + +# Module: components/OrgContriCards/OrgContriCards.test diff --git a/talawa-admin-docs/modules/components_OrgDelete_OrgDelete.md b/talawa-admin-docs/modules/components_OrgDelete_OrgDelete.md new file mode 100644 index 0000000000..4d5b157c3f --- /dev/null +++ b/talawa-admin-docs/modules/components_OrgDelete_OrgDelete.md @@ -0,0 +1,23 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/OrgDelete/OrgDelete + +# Module: components/OrgDelete/OrgDelete + +## Table of contents + +### Functions + +- [default](components_OrgDelete_OrgDelete.md#default) + +## Functions + +### default + +▸ **default**(): `JSX.Element` + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/OrgDelete/OrgDelete.tsx:4](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/OrgDelete/OrgDelete.tsx#L4) diff --git a/talawa-admin-docs/modules/components_OrgDelete_OrgDelete_test.md b/talawa-admin-docs/modules/components_OrgDelete_OrgDelete_test.md new file mode 100644 index 0000000000..574934084f --- /dev/null +++ b/talawa-admin-docs/modules/components_OrgDelete_OrgDelete_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/OrgDelete/OrgDelete.test + +# Module: components/OrgDelete/OrgDelete.test diff --git a/talawa-admin-docs/modules/components_OrgListCard_OrgListCard.md b/talawa-admin-docs/modules/components_OrgListCard_OrgListCard.md new file mode 100644 index 0000000000..899f502836 --- /dev/null +++ b/talawa-admin-docs/modules/components_OrgListCard_OrgListCard.md @@ -0,0 +1,33 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/OrgListCard/OrgListCard + +# Module: components/OrgListCard/OrgListCard + +## Table of contents + +### Interfaces + +- [InterfaceOrgListCardProps](../interfaces/components_OrgListCard_OrgListCard.InterfaceOrgListCardProps.md) + +### Functions + +- [default](components_OrgListCard_OrgListCard.md#default) + +## Functions + +### default + +▸ **default**(`props`): `JSX.Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | [`InterfaceOrgListCardProps`](../interfaces/components_OrgListCard_OrgListCard.InterfaceOrgListCardProps.md) | + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/OrgListCard/OrgListCard.tsx:13](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/OrgListCard/OrgListCard.tsx#L13) diff --git a/talawa-admin-docs/modules/components_OrgListCard_OrgListCard_test.md b/talawa-admin-docs/modules/components_OrgListCard_OrgListCard_test.md new file mode 100644 index 0000000000..07415ddf2d --- /dev/null +++ b/talawa-admin-docs/modules/components_OrgListCard_OrgListCard_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/OrgListCard/OrgListCard.test + +# Module: components/OrgListCard/OrgListCard.test diff --git a/talawa-admin-docs/modules/components_OrgPeopleListCard_OrgPeopleListCard.md b/talawa-admin-docs/modules/components_OrgPeopleListCard_OrgPeopleListCard.md new file mode 100644 index 0000000000..2f9298e315 --- /dev/null +++ b/talawa-admin-docs/modules/components_OrgPeopleListCard_OrgPeopleListCard.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/OrgPeopleListCard/OrgPeopleListCard + +# Module: components/OrgPeopleListCard/OrgPeopleListCard + +## Table of contents + +### Functions + +- [default](components_OrgPeopleListCard_OrgPeopleListCard.md#default) + +## Functions + +### default + +▸ **default**(`props`): `JSX.Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `InterfaceOrgPeopleListCardProps` | + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/OrgPeopleListCard/OrgPeopleListCard.tsx:24](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/OrgPeopleListCard/OrgPeopleListCard.tsx#L24) diff --git a/talawa-admin-docs/modules/components_OrgPeopleListCard_OrgPeopleListCard_test.md b/talawa-admin-docs/modules/components_OrgPeopleListCard_OrgPeopleListCard_test.md new file mode 100644 index 0000000000..0195d958b6 --- /dev/null +++ b/talawa-admin-docs/modules/components_OrgPeopleListCard_OrgPeopleListCard_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/OrgPeopleListCard/OrgPeopleListCard.test + +# Module: components/OrgPeopleListCard/OrgPeopleListCard.test diff --git a/talawa-admin-docs/modules/components_OrgPostCard_OrgPostCard.md b/talawa-admin-docs/modules/components_OrgPostCard_OrgPostCard.md new file mode 100644 index 0000000000..856ad3bb1c --- /dev/null +++ b/talawa-admin-docs/modules/components_OrgPostCard_OrgPostCard.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/OrgPostCard/OrgPostCard + +# Module: components/OrgPostCard/OrgPostCard + +## Table of contents + +### Functions + +- [default](components_OrgPostCard_OrgPostCard.md#default) + +## Functions + +### default + +▸ **default**(`props`): `JSX.Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `InterfaceOrgPostCardProps` | + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/OrgPostCard/OrgPostCard.tsx:28](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/OrgPostCard/OrgPostCard.tsx#L28) diff --git a/talawa-admin-docs/modules/components_OrgPostCard_OrgPostCard_test.md b/talawa-admin-docs/modules/components_OrgPostCard_OrgPostCard_test.md new file mode 100644 index 0000000000..77ac86c214 --- /dev/null +++ b/talawa-admin-docs/modules/components_OrgPostCard_OrgPostCard_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/OrgPostCard/OrgPostCard.test + +# Module: components/OrgPostCard/OrgPostCard.test diff --git a/talawa-admin-docs/modules/components_OrgUpdate_OrgUpdate.md b/talawa-admin-docs/modules/components_OrgUpdate_OrgUpdate.md new file mode 100644 index 0000000000..12f1fb6b3b --- /dev/null +++ b/talawa-admin-docs/modules/components_OrgUpdate_OrgUpdate.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/OrgUpdate/OrgUpdate + +# Module: components/OrgUpdate/OrgUpdate + +## Table of contents + +### Functions + +- [default](components_OrgUpdate_OrgUpdate.md#default) + +## Functions + +### default + +▸ **default**(`props`): `JSX.Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `InterfaceOrgUpdateProps` | + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/OrgUpdate/OrgUpdate.tsx:20](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/OrgUpdate/OrgUpdate.tsx#L20) diff --git a/talawa-admin-docs/modules/components_OrgUpdate_OrgUpdate_test.md b/talawa-admin-docs/modules/components_OrgUpdate_OrgUpdate_test.md new file mode 100644 index 0000000000..e619c0f075 --- /dev/null +++ b/talawa-admin-docs/modules/components_OrgUpdate_OrgUpdate_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/OrgUpdate/OrgUpdate.test + +# Module: components/OrgUpdate/OrgUpdate.test diff --git a/talawa-admin-docs/modules/components_OrganizationCardStart_OrganizationCardStart.md b/talawa-admin-docs/modules/components_OrganizationCardStart_OrganizationCardStart.md new file mode 100644 index 0000000000..98aec646d0 --- /dev/null +++ b/talawa-admin-docs/modules/components_OrganizationCardStart_OrganizationCardStart.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/OrganizationCardStart/OrganizationCardStart + +# Module: components/OrganizationCardStart/OrganizationCardStart + +## Table of contents + +### Functions + +- [default](components_OrganizationCardStart_OrganizationCardStart.md#default) + +## Functions + +### default + +▸ **default**(`props`): `JSX.Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `InterfaceOrganizationCardStartProps` | + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/OrganizationCardStart/OrganizationCardStart.tsx:11](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/OrganizationCardStart/OrganizationCardStart.tsx#L11) diff --git a/talawa-admin-docs/modules/components_OrganizationCardStart_OrganizationCardStart_test.md b/talawa-admin-docs/modules/components_OrganizationCardStart_OrganizationCardStart_test.md new file mode 100644 index 0000000000..6071b1a57e --- /dev/null +++ b/talawa-admin-docs/modules/components_OrganizationCardStart_OrganizationCardStart_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/OrganizationCardStart/OrganizationCardStart.test + +# Module: components/OrganizationCardStart/OrganizationCardStart.test diff --git a/talawa-admin-docs/modules/components_OrganizationCard_OrganizationCard.md b/talawa-admin-docs/modules/components_OrganizationCard_OrganizationCard.md new file mode 100644 index 0000000000..360ee52b37 --- /dev/null +++ b/talawa-admin-docs/modules/components_OrganizationCard_OrganizationCard.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/OrganizationCard/OrganizationCard + +# Module: components/OrganizationCard/OrganizationCard + +## Table of contents + +### Functions + +- [default](components_OrganizationCard_OrganizationCard.md#default) + +## Functions + +### default + +▸ **default**(`props`): `JSX.Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `InterfaceOrganizationCardProps` | + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/OrganizationCard/OrganizationCard.tsx:13](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/OrganizationCard/OrganizationCard.tsx#L13) diff --git a/talawa-admin-docs/modules/components_OrganizationCard_OrganizationCard_test.md b/talawa-admin-docs/modules/components_OrganizationCard_OrganizationCard_test.md new file mode 100644 index 0000000000..ab6e5c8712 --- /dev/null +++ b/talawa-admin-docs/modules/components_OrganizationCard_OrganizationCard_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/OrganizationCard/OrganizationCard.test + +# Module: components/OrganizationCard/OrganizationCard.test diff --git a/talawa-admin-docs/modules/components_OrganizationScreen_OrganizationScreen.md b/talawa-admin-docs/modules/components_OrganizationScreen_OrganizationScreen.md new file mode 100644 index 0000000000..f13a9bc770 --- /dev/null +++ b/talawa-admin-docs/modules/components_OrganizationScreen_OrganizationScreen.md @@ -0,0 +1,33 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/OrganizationScreen/OrganizationScreen + +# Module: components/OrganizationScreen/OrganizationScreen + +## Table of contents + +### Interfaces + +- [InterfaceOrganizationScreenProps](../interfaces/components_OrganizationScreen_OrganizationScreen.InterfaceOrganizationScreenProps.md) + +### Functions + +- [default](components_OrganizationScreen_OrganizationScreen.md#default) + +## Functions + +### default + +▸ **default**(`«destructured»`): `Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `«destructured»` | [`InterfaceOrganizationScreenProps`](../interfaces/components_OrganizationScreen_OrganizationScreen.InterfaceOrganizationScreenProps.md) | + +#### Returns + +`Element` + +#### Defined in + +[src/components/OrganizationScreen/OrganizationScreen.tsx:15](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/OrganizationScreen/OrganizationScreen.tsx#L15) diff --git a/talawa-admin-docs/modules/components_OrganizationScreen_OrganizationScreen_test.md b/talawa-admin-docs/modules/components_OrganizationScreen_OrganizationScreen_test.md new file mode 100644 index 0000000000..1965da619e --- /dev/null +++ b/talawa-admin-docs/modules/components_OrganizationScreen_OrganizationScreen_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/OrganizationScreen/OrganizationScreen.test + +# Module: components/OrganizationScreen/OrganizationScreen.test diff --git a/talawa-admin-docs/modules/components_PaginationList_PaginationList.md b/talawa-admin-docs/modules/components_PaginationList_PaginationList.md new file mode 100644 index 0000000000..05ced10e30 --- /dev/null +++ b/talawa-admin-docs/modules/components_PaginationList_PaginationList.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/PaginationList/PaginationList + +# Module: components/PaginationList/PaginationList + +## Table of contents + +### Functions + +- [default](components_PaginationList_PaginationList.md#default) + +## Functions + +### default + +▸ **default**(`props`): `Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `InterfacePropsInterface` | + +#### Returns + +`Element` + +#### Defined in + +[src/components/PaginationList/PaginationList.tsx:21](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/PaginationList/PaginationList.tsx#L21) diff --git a/talawa-admin-docs/modules/components_Pagination_Pagination.md b/talawa-admin-docs/modules/components_Pagination_Pagination.md new file mode 100644 index 0000000000..16ed2d4b99 --- /dev/null +++ b/talawa-admin-docs/modules/components_Pagination_Pagination.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/Pagination/Pagination + +# Module: components/Pagination/Pagination + +## Table of contents + +### Functions + +- [default](components_Pagination_Pagination.md#default) + +## Functions + +### default + +▸ **default**(`props`): `JSX.Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `InterfaceTablePaginationActionsProps` | + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/Pagination/Pagination.tsx:20](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/Pagination/Pagination.tsx#L20) diff --git a/talawa-admin-docs/modules/components_Pagination_Pagination_test.md b/talawa-admin-docs/modules/components_Pagination_Pagination_test.md new file mode 100644 index 0000000000..b663353b05 --- /dev/null +++ b/talawa-admin-docs/modules/components_Pagination_Pagination_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/Pagination/Pagination.test + +# Module: components/Pagination/Pagination.test diff --git a/talawa-admin-docs/modules/components_SecuredRoute_SecuredRoute.md b/talawa-admin-docs/modules/components_SecuredRoute_SecuredRoute.md new file mode 100644 index 0000000000..274114319e --- /dev/null +++ b/talawa-admin-docs/modules/components_SecuredRoute_SecuredRoute.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/SecuredRoute/SecuredRoute + +# Module: components/SecuredRoute/SecuredRoute + +## Table of contents + +### Functions + +- [default](components_SecuredRoute_SecuredRoute.md#default) + +## Functions + +### default + +▸ **default**(`props`): `Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `any` | + +#### Returns + +`Element` + +#### Defined in + +[src/components/SecuredRoute/SecuredRoute.tsx:5](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/SecuredRoute/SecuredRoute.tsx#L5) diff --git a/talawa-admin-docs/modules/components_SuperAdminScreen_SuperAdminScreen.md b/talawa-admin-docs/modules/components_SuperAdminScreen_SuperAdminScreen.md new file mode 100644 index 0000000000..7b32fb59e9 --- /dev/null +++ b/talawa-admin-docs/modules/components_SuperAdminScreen_SuperAdminScreen.md @@ -0,0 +1,33 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/SuperAdminScreen/SuperAdminScreen + +# Module: components/SuperAdminScreen/SuperAdminScreen + +## Table of contents + +### Interfaces + +- [InterfaceSuperAdminScreenProps](../interfaces/components_SuperAdminScreen_SuperAdminScreen.InterfaceSuperAdminScreenProps.md) + +### Functions + +- [default](components_SuperAdminScreen_SuperAdminScreen.md#default) + +## Functions + +### default + +▸ **default**(`«destructured»`): `Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `«destructured»` | [`InterfaceSuperAdminScreenProps`](../interfaces/components_SuperAdminScreen_SuperAdminScreen.InterfaceSuperAdminScreenProps.md) | + +#### Returns + +`Element` + +#### Defined in + +[src/components/SuperAdminScreen/SuperAdminScreen.tsx:12](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/SuperAdminScreen/SuperAdminScreen.tsx#L12) diff --git a/talawa-admin-docs/modules/components_SuperAdminScreen_SuperAdminScreen_test.md b/talawa-admin-docs/modules/components_SuperAdminScreen_SuperAdminScreen_test.md new file mode 100644 index 0000000000..09367d5fab --- /dev/null +++ b/talawa-admin-docs/modules/components_SuperAdminScreen_SuperAdminScreen_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/SuperAdminScreen/SuperAdminScreen.test + +# Module: components/SuperAdminScreen/SuperAdminScreen.test diff --git a/talawa-admin-docs/modules/components_TableLoader_TableLoader.md b/talawa-admin-docs/modules/components_TableLoader_TableLoader.md new file mode 100644 index 0000000000..3ac894cea3 --- /dev/null +++ b/talawa-admin-docs/modules/components_TableLoader_TableLoader.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/TableLoader/TableLoader + +# Module: components/TableLoader/TableLoader + +## Table of contents + +### Functions + +- [default](components_TableLoader_TableLoader.md#default) + +## Functions + +### default + +▸ **default**(`props`): `Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `InterfaceTableLoader` | + +#### Returns + +`Element` + +#### Defined in + +[src/components/TableLoader/TableLoader.tsx:10](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/TableLoader/TableLoader.tsx#L10) diff --git a/talawa-admin-docs/modules/components_TableLoader_TableLoader_test.md b/talawa-admin-docs/modules/components_TableLoader_TableLoader_test.md new file mode 100644 index 0000000000..8bdff07dba --- /dev/null +++ b/talawa-admin-docs/modules/components_TableLoader_TableLoader_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/TableLoader/TableLoader.test + +# Module: components/TableLoader/TableLoader.test diff --git a/talawa-admin-docs/modules/components_TaskListItem_TaskListItem.md b/talawa-admin-docs/modules/components_TaskListItem_TaskListItem.md new file mode 100644 index 0000000000..1550e23597 --- /dev/null +++ b/talawa-admin-docs/modules/components_TaskListItem_TaskListItem.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/TaskListItem/TaskListItem + +# Module: components/TaskListItem/TaskListItem + +## Table of contents + +### Functions + +- [TaskListItem](components_TaskListItem_TaskListItem.md#tasklistitem) + +## Functions + +### TaskListItem + +▸ **TaskListItem**(`«destructured»`): `Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `«destructured»` | `PropType` | + +#### Returns + +`Element` + +#### Defined in + +[src/components/TaskListItem/TaskListItem.tsx:38](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/TaskListItem/TaskListItem.tsx#L38) diff --git a/talawa-admin-docs/modules/components_TaskListItem_TaskListItem_test.md b/talawa-admin-docs/modules/components_TaskListItem_TaskListItem_test.md new file mode 100644 index 0000000000..601f36689f --- /dev/null +++ b/talawa-admin-docs/modules/components_TaskListItem_TaskListItem_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/TaskListItem/TaskListItem.test + +# Module: components/TaskListItem/TaskListItem.test diff --git a/talawa-admin-docs/modules/components_TaskModals_AddTaskModal.md b/talawa-admin-docs/modules/components_TaskModals_AddTaskModal.md new file mode 100644 index 0000000000..f4676b390d --- /dev/null +++ b/talawa-admin-docs/modules/components_TaskModals_AddTaskModal.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/TaskModals/AddTaskModal + +# Module: components/TaskModals/AddTaskModal + +## Table of contents + +### Functions + +- [AddTaskModal](components_TaskModals_AddTaskModal.md#addtaskmodal) + +## Functions + +### AddTaskModal + +▸ **AddTaskModal**(`«destructured»`): `Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `«destructured»` | `ModalPropType` | + +#### Returns + +`Element` + +#### Defined in + +[src/components/TaskModals/AddTaskModal.tsx:17](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/TaskModals/AddTaskModal.tsx#L17) diff --git a/talawa-admin-docs/modules/components_TaskModals_AddTaskModal_test.md b/talawa-admin-docs/modules/components_TaskModals_AddTaskModal_test.md new file mode 100644 index 0000000000..9fc6d4f85c --- /dev/null +++ b/talawa-admin-docs/modules/components_TaskModals_AddTaskModal_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/TaskModals/AddTaskModal.test + +# Module: components/TaskModals/AddTaskModal.test diff --git a/talawa-admin-docs/modules/components_TaskModals_DeleteTaskModal.md b/talawa-admin-docs/modules/components_TaskModals_DeleteTaskModal.md new file mode 100644 index 0000000000..b8e1b78b3c --- /dev/null +++ b/talawa-admin-docs/modules/components_TaskModals_DeleteTaskModal.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/TaskModals/DeleteTaskModal + +# Module: components/TaskModals/DeleteTaskModal + +## Table of contents + +### Functions + +- [DeleteTaskModal](components_TaskModals_DeleteTaskModal.md#deletetaskmodal) + +## Functions + +### DeleteTaskModal + +▸ **DeleteTaskModal**(`props`): `Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `ModalPropType` | + +#### Returns + +`Element` + +#### Defined in + +[src/components/TaskModals/DeleteTaskModal.tsx:14](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/TaskModals/DeleteTaskModal.tsx#L14) diff --git a/talawa-admin-docs/modules/components_TaskModals_DeleteTaskModal_test.md b/talawa-admin-docs/modules/components_TaskModals_DeleteTaskModal_test.md new file mode 100644 index 0000000000..9a35d7741c --- /dev/null +++ b/talawa-admin-docs/modules/components_TaskModals_DeleteTaskModal_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/TaskModals/DeleteTaskModal.test + +# Module: components/TaskModals/DeleteTaskModal.test diff --git a/talawa-admin-docs/modules/components_TaskModals_ManageVolunteerModal.md b/talawa-admin-docs/modules/components_TaskModals_ManageVolunteerModal.md new file mode 100644 index 0000000000..3ce0f430fd --- /dev/null +++ b/talawa-admin-docs/modules/components_TaskModals_ManageVolunteerModal.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/TaskModals/ManageVolunteerModal + +# Module: components/TaskModals/ManageVolunteerModal + +## Table of contents + +### Functions + +- [ManageVolunteerModal](components_TaskModals_ManageVolunteerModal.md#managevolunteermodal) + +## Functions + +### ManageVolunteerModal + +▸ **ManageVolunteerModal**(`props`): `Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `ModalPropType` | + +#### Returns + +`Element` + +#### Defined in + +[src/components/TaskModals/ManageVolunteerModal.tsx:29](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/TaskModals/ManageVolunteerModal.tsx#L29) diff --git a/talawa-admin-docs/modules/components_TaskModals_ManageVolunteerModal_test.md b/talawa-admin-docs/modules/components_TaskModals_ManageVolunteerModal_test.md new file mode 100644 index 0000000000..f587cab1db --- /dev/null +++ b/talawa-admin-docs/modules/components_TaskModals_ManageVolunteerModal_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/TaskModals/ManageVolunteerModal.test + +# Module: components/TaskModals/ManageVolunteerModal.test diff --git a/talawa-admin-docs/modules/components_TaskModals_UpdateTaskModal.md b/talawa-admin-docs/modules/components_TaskModals_UpdateTaskModal.md new file mode 100644 index 0000000000..593edf1a85 --- /dev/null +++ b/talawa-admin-docs/modules/components_TaskModals_UpdateTaskModal.md @@ -0,0 +1,55 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/TaskModals/UpdateTaskModal + +# Module: components/TaskModals/UpdateTaskModal + +## Table of contents + +### Type Aliases + +- [ModalPropType](components_TaskModals_UpdateTaskModal.md#modalproptype) + +### Functions + +- [UpdateTaskModal](components_TaskModals_UpdateTaskModal.md#updatetaskmodal) + +## Type Aliases + +### ModalPropType + +Ƭ **ModalPropType**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `handleClose` | () => `void` | +| `organization` | { `_id`: `string` ; `members`: `InterfaceUser`[] } | +| `organization._id` | `string` | +| `organization.members` | `InterfaceUser`[] | +| `refetchData` | () => `void` | +| `show` | `boolean` | +| `task` | `InterfaceTask` | + +#### Defined in + +[src/components/TaskModals/UpdateTaskModal.tsx:31](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/TaskModals/UpdateTaskModal.tsx#L31) + +## Functions + +### UpdateTaskModal + +▸ **UpdateTaskModal**(`props`): `Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | [`ModalPropType`](components_TaskModals_UpdateTaskModal.md#modalproptype) | + +#### Returns + +`Element` + +#### Defined in + +[src/components/TaskModals/UpdateTaskModal.tsx:42](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/TaskModals/UpdateTaskModal.tsx#L42) diff --git a/talawa-admin-docs/modules/components_TaskModals_UpdateTaskModal_test.md b/talawa-admin-docs/modules/components_TaskModals_UpdateTaskModal_test.md new file mode 100644 index 0000000000..9d8c0895f7 --- /dev/null +++ b/talawa-admin-docs/modules/components_TaskModals_UpdateTaskModal_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/TaskModals/UpdateTaskModal.test + +# Module: components/TaskModals/UpdateTaskModal.test diff --git a/talawa-admin-docs/modules/components_UserListCard_UserListCard.md b/talawa-admin-docs/modules/components_UserListCard_UserListCard.md new file mode 100644 index 0000000000..7de393f44a --- /dev/null +++ b/talawa-admin-docs/modules/components_UserListCard_UserListCard.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/UserListCard/UserListCard + +# Module: components/UserListCard/UserListCard + +## Table of contents + +### Functions + +- [default](components_UserListCard_UserListCard.md#default) + +## Functions + +### default + +▸ **default**(`props`): `JSX.Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `InterfaceUserListCardProps` | + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/UserListCard/UserListCard.tsx:24](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/UserListCard/UserListCard.tsx#L24) diff --git a/talawa-admin-docs/modules/components_UserListCard_UserListCard_test.md b/talawa-admin-docs/modules/components_UserListCard_UserListCard_test.md new file mode 100644 index 0000000000..6e6b1eb973 --- /dev/null +++ b/talawa-admin-docs/modules/components_UserListCard_UserListCard_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/UserListCard/UserListCard.test + +# Module: components/UserListCard/UserListCard.test diff --git a/talawa-admin-docs/modules/components_UserPasswordUpdate_UserPasswordUpdate.md b/talawa-admin-docs/modules/components_UserPasswordUpdate_UserPasswordUpdate.md new file mode 100644 index 0000000000..8402744885 --- /dev/null +++ b/talawa-admin-docs/modules/components_UserPasswordUpdate_UserPasswordUpdate.md @@ -0,0 +1,30 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/UserPasswordUpdate/UserPasswordUpdate + +# Module: components/UserPasswordUpdate/UserPasswordUpdate + +## Table of contents + +### Functions + +- [default](components_UserPasswordUpdate_UserPasswordUpdate.md#default) + +## Functions + +### default + +▸ **default**(`props`, `context?`): ``null`` \| `ReactElement`<`any`, `any`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `PropsWithChildren`<`InterfaceUserPasswordUpdateProps`\> | +| `context?` | `any` | + +#### Returns + +``null`` \| `ReactElement`<`any`, `any`\> + +#### Defined in + +node_modules/@types/react/index.d.ts:543 diff --git a/talawa-admin-docs/modules/components_UserPasswordUpdate_UserPasswordUpdate_test.md b/talawa-admin-docs/modules/components_UserPasswordUpdate_UserPasswordUpdate_test.md new file mode 100644 index 0000000000..55647dc09e --- /dev/null +++ b/talawa-admin-docs/modules/components_UserPasswordUpdate_UserPasswordUpdate_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/UserPasswordUpdate/UserPasswordUpdate.test + +# Module: components/UserPasswordUpdate/UserPasswordUpdate.test diff --git a/talawa-admin-docs/modules/components_UserPortal_DonationCard_DonationCard.md b/talawa-admin-docs/modules/components_UserPortal_DonationCard_DonationCard.md new file mode 100644 index 0000000000..f6276c967c --- /dev/null +++ b/talawa-admin-docs/modules/components_UserPortal_DonationCard_DonationCard.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/UserPortal/DonationCard/DonationCard + +# Module: components/UserPortal/DonationCard/DonationCard + +## Table of contents + +### Functions + +- [default](components_UserPortal_DonationCard_DonationCard.md#default) + +## Functions + +### default + +▸ **default**(`props`): `JSX.Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `InterfaceDonationCardProps` | + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/UserPortal/DonationCard/DonationCard.tsx:12](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/UserPortal/DonationCard/DonationCard.tsx#L12) diff --git a/talawa-admin-docs/modules/components_UserPortal_Login_Login.md b/talawa-admin-docs/modules/components_UserPortal_Login_Login.md new file mode 100644 index 0000000000..56bdc5753c --- /dev/null +++ b/talawa-admin-docs/modules/components_UserPortal_Login_Login.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/UserPortal/Login/Login + +# Module: components/UserPortal/Login/Login + +## Table of contents + +### Functions + +- [default](components_UserPortal_Login_Login.md#default) + +## Functions + +### default + +▸ **default**(`props`): `JSX.Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `InterfaceLoginProps` | + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/UserPortal/Login/Login.tsx:19](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/UserPortal/Login/Login.tsx#L19) diff --git a/talawa-admin-docs/modules/components_UserPortal_Login_Login_test.md b/talawa-admin-docs/modules/components_UserPortal_Login_Login_test.md new file mode 100644 index 0000000000..373cee75b5 --- /dev/null +++ b/talawa-admin-docs/modules/components_UserPortal_Login_Login_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/UserPortal/Login/Login.test + +# Module: components/UserPortal/Login/Login.test diff --git a/talawa-admin-docs/modules/components_UserPortal_OrganizationCard_OrganizationCard.md b/talawa-admin-docs/modules/components_UserPortal_OrganizationCard_OrganizationCard.md new file mode 100644 index 0000000000..8bd259d646 --- /dev/null +++ b/talawa-admin-docs/modules/components_UserPortal_OrganizationCard_OrganizationCard.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/UserPortal/OrganizationCard/OrganizationCard + +# Module: components/UserPortal/OrganizationCard/OrganizationCard + +## Table of contents + +### Functions + +- [default](components_UserPortal_OrganizationCard_OrganizationCard.md#default) + +## Functions + +### default + +▸ **default**(`props`): `JSX.Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `InterfaceOrganizationCardProps` | + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/UserPortal/OrganizationCard/OrganizationCard.tsx:13](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/UserPortal/OrganizationCard/OrganizationCard.tsx#L13) diff --git a/talawa-admin-docs/modules/components_UserPortal_OrganizationCard_OrganizationCard_test.md b/talawa-admin-docs/modules/components_UserPortal_OrganizationCard_OrganizationCard_test.md new file mode 100644 index 0000000000..141b8155d9 --- /dev/null +++ b/talawa-admin-docs/modules/components_UserPortal_OrganizationCard_OrganizationCard_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/UserPortal/OrganizationCard/OrganizationCard.test + +# Module: components/UserPortal/OrganizationCard/OrganizationCard.test diff --git a/talawa-admin-docs/modules/components_UserPortal_OrganizationNavbar_OrganizationNavbar.md b/talawa-admin-docs/modules/components_UserPortal_OrganizationNavbar_OrganizationNavbar.md new file mode 100644 index 0000000000..55602bbcb9 --- /dev/null +++ b/talawa-admin-docs/modules/components_UserPortal_OrganizationNavbar_OrganizationNavbar.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/UserPortal/OrganizationNavbar/OrganizationNavbar + +# Module: components/UserPortal/OrganizationNavbar/OrganizationNavbar + +## Table of contents + +### Functions + +- [default](components_UserPortal_OrganizationNavbar_OrganizationNavbar.md#default) + +## Functions + +### default + +▸ **default**(`props`): `JSX.Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `InterfaceNavbarProps` | + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/UserPortal/OrganizationNavbar/OrganizationNavbar.tsx:21](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/UserPortal/OrganizationNavbar/OrganizationNavbar.tsx#L21) diff --git a/talawa-admin-docs/modules/components_UserPortal_OrganizationNavbar_OrganizationNavbar_test.md b/talawa-admin-docs/modules/components_UserPortal_OrganizationNavbar_OrganizationNavbar_test.md new file mode 100644 index 0000000000..41bd01b6c2 --- /dev/null +++ b/talawa-admin-docs/modules/components_UserPortal_OrganizationNavbar_OrganizationNavbar_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/UserPortal/OrganizationNavbar/OrganizationNavbar.test + +# Module: components/UserPortal/OrganizationNavbar/OrganizationNavbar.test diff --git a/talawa-admin-docs/modules/components_UserPortal_OrganizationSidebar_OrganizationSidebar.md b/talawa-admin-docs/modules/components_UserPortal_OrganizationSidebar_OrganizationSidebar.md new file mode 100644 index 0000000000..0694a5aef8 --- /dev/null +++ b/talawa-admin-docs/modules/components_UserPortal_OrganizationSidebar_OrganizationSidebar.md @@ -0,0 +1,23 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/UserPortal/OrganizationSidebar/OrganizationSidebar + +# Module: components/UserPortal/OrganizationSidebar/OrganizationSidebar + +## Table of contents + +### Functions + +- [default](components_UserPortal_OrganizationSidebar_OrganizationSidebar.md#default) + +## Functions + +### default + +▸ **default**(): `JSX.Element` + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.tsx:18](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.tsx#L18) diff --git a/talawa-admin-docs/modules/components_UserPortal_OrganizationSidebar_OrganizationSidebar_test.md b/talawa-admin-docs/modules/components_UserPortal_OrganizationSidebar_OrganizationSidebar_test.md new file mode 100644 index 0000000000..2d7163c537 --- /dev/null +++ b/talawa-admin-docs/modules/components_UserPortal_OrganizationSidebar_OrganizationSidebar_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/UserPortal/OrganizationSidebar/OrganizationSidebar.test + +# Module: components/UserPortal/OrganizationSidebar/OrganizationSidebar.test diff --git a/talawa-admin-docs/modules/components_UserPortal_PeopleCard_PeopleCard.md b/talawa-admin-docs/modules/components_UserPortal_PeopleCard_PeopleCard.md new file mode 100644 index 0000000000..cc4ecd4ca3 --- /dev/null +++ b/talawa-admin-docs/modules/components_UserPortal_PeopleCard_PeopleCard.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/UserPortal/PeopleCard/PeopleCard + +# Module: components/UserPortal/PeopleCard/PeopleCard + +## Table of contents + +### Functions + +- [default](components_UserPortal_PeopleCard_PeopleCard.md#default) + +## Functions + +### default + +▸ **default**(`props`): `JSX.Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `InterfaceOrganizationCardProps` | + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/UserPortal/PeopleCard/PeopleCard.tsx:12](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/UserPortal/PeopleCard/PeopleCard.tsx#L12) diff --git a/talawa-admin-docs/modules/components_UserPortal_PeopleCard_PeopleCard_test.md b/talawa-admin-docs/modules/components_UserPortal_PeopleCard_PeopleCard_test.md new file mode 100644 index 0000000000..d874dc3b00 --- /dev/null +++ b/talawa-admin-docs/modules/components_UserPortal_PeopleCard_PeopleCard_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/UserPortal/PeopleCard/PeopleCard.test + +# Module: components/UserPortal/PeopleCard/PeopleCard.test diff --git a/talawa-admin-docs/modules/components_UserPortal_PostCard_PostCard.md b/talawa-admin-docs/modules/components_UserPortal_PostCard_PostCard.md new file mode 100644 index 0000000000..2e18dfc8b3 --- /dev/null +++ b/talawa-admin-docs/modules/components_UserPortal_PostCard_PostCard.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/UserPortal/PostCard/PostCard + +# Module: components/UserPortal/PostCard/PostCard + +## Table of contents + +### Functions + +- [default](components_UserPortal_PostCard_PostCard.md#default) + +## Functions + +### default + +▸ **default**(`props`): `JSX.Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `InterfacePostCardProps` | + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/UserPortal/PostCard/PostCard.tsx:35](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/UserPortal/PostCard/PostCard.tsx#L35) diff --git a/talawa-admin-docs/modules/components_UserPortal_PostCard_PostCard_test.md b/talawa-admin-docs/modules/components_UserPortal_PostCard_PostCard_test.md new file mode 100644 index 0000000000..03b9f9b2ea --- /dev/null +++ b/talawa-admin-docs/modules/components_UserPortal_PostCard_PostCard_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/UserPortal/PostCard/PostCard.test + +# Module: components/UserPortal/PostCard/PostCard.test diff --git a/talawa-admin-docs/modules/components_UserPortal_Register_Register.md b/talawa-admin-docs/modules/components_UserPortal_Register_Register.md new file mode 100644 index 0000000000..400008de6d --- /dev/null +++ b/talawa-admin-docs/modules/components_UserPortal_Register_Register.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/UserPortal/Register/Register + +# Module: components/UserPortal/Register/Register + +## Table of contents + +### Functions + +- [default](components_UserPortal_Register_Register.md#default) + +## Functions + +### default + +▸ **default**(`props`): `JSX.Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `InterfaceRegisterProps` | + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/UserPortal/Register/Register.tsx:19](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/UserPortal/Register/Register.tsx#L19) diff --git a/talawa-admin-docs/modules/components_UserPortal_Register_Register_test.md b/talawa-admin-docs/modules/components_UserPortal_Register_Register_test.md new file mode 100644 index 0000000000..e82f244ca2 --- /dev/null +++ b/talawa-admin-docs/modules/components_UserPortal_Register_Register_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/UserPortal/Register/Register.test + +# Module: components/UserPortal/Register/Register.test diff --git a/talawa-admin-docs/modules/components_UserPortal_SecuredRouteForUser_SecuredRouteForUser.md b/talawa-admin-docs/modules/components_UserPortal_SecuredRouteForUser_SecuredRouteForUser.md new file mode 100644 index 0000000000..6fee00ab23 --- /dev/null +++ b/talawa-admin-docs/modules/components_UserPortal_SecuredRouteForUser_SecuredRouteForUser.md @@ -0,0 +1,29 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/UserPortal/SecuredRouteForUser/SecuredRouteForUser + +# Module: components/UserPortal/SecuredRouteForUser/SecuredRouteForUser + +## Table of contents + +### Functions + +- [default](components_UserPortal_SecuredRouteForUser_SecuredRouteForUser.md#default) + +## Functions + +### default + +▸ **default**(`props`): `Element` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `any` | + +#### Returns + +`Element` + +#### Defined in + +[src/components/UserPortal/SecuredRouteForUser/SecuredRouteForUser.tsx:4](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/UserPortal/SecuredRouteForUser/SecuredRouteForUser.tsx#L4) diff --git a/talawa-admin-docs/modules/components_UserPortal_UserNavbar_UserNavbar.md b/talawa-admin-docs/modules/components_UserPortal_UserNavbar_UserNavbar.md new file mode 100644 index 0000000000..052b822f8a --- /dev/null +++ b/talawa-admin-docs/modules/components_UserPortal_UserNavbar_UserNavbar.md @@ -0,0 +1,23 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/UserPortal/UserNavbar/UserNavbar + +# Module: components/UserPortal/UserNavbar/UserNavbar + +## Table of contents + +### Functions + +- [default](components_UserPortal_UserNavbar_UserNavbar.md#default) + +## Functions + +### default + +▸ **default**(): `JSX.Element` + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/UserPortal/UserNavbar/UserNavbar.tsx:13](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/UserPortal/UserNavbar/UserNavbar.tsx#L13) diff --git a/talawa-admin-docs/modules/components_UserPortal_UserNavbar_UserNavbar_test.md b/talawa-admin-docs/modules/components_UserPortal_UserNavbar_UserNavbar_test.md new file mode 100644 index 0000000000..c6d86ea6b2 --- /dev/null +++ b/talawa-admin-docs/modules/components_UserPortal_UserNavbar_UserNavbar_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/UserPortal/UserNavbar/UserNavbar.test + +# Module: components/UserPortal/UserNavbar/UserNavbar.test diff --git a/talawa-admin-docs/modules/components_UserPortal_UserSidebar_UserSidebar.md b/talawa-admin-docs/modules/components_UserPortal_UserSidebar_UserSidebar.md new file mode 100644 index 0000000000..e9f6ad4bc0 --- /dev/null +++ b/talawa-admin-docs/modules/components_UserPortal_UserSidebar_UserSidebar.md @@ -0,0 +1,23 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/UserPortal/UserSidebar/UserSidebar + +# Module: components/UserPortal/UserSidebar/UserSidebar + +## Table of contents + +### Functions + +- [default](components_UserPortal_UserSidebar_UserSidebar.md#default) + +## Functions + +### default + +▸ **default**(): `JSX.Element` + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/UserPortal/UserSidebar/UserSidebar.tsx:15](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/UserPortal/UserSidebar/UserSidebar.tsx#L15) diff --git a/talawa-admin-docs/modules/components_UserPortal_UserSidebar_UserSidebar_test.md b/talawa-admin-docs/modules/components_UserPortal_UserSidebar_UserSidebar_test.md new file mode 100644 index 0000000000..f4eee6091e --- /dev/null +++ b/talawa-admin-docs/modules/components_UserPortal_UserSidebar_UserSidebar_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/UserPortal/UserSidebar/UserSidebar.test + +# Module: components/UserPortal/UserSidebar/UserSidebar.test diff --git a/talawa-admin-docs/modules/components_UserUpdate_UserUpdate.md b/talawa-admin-docs/modules/components_UserUpdate_UserUpdate.md new file mode 100644 index 0000000000..4285a73143 --- /dev/null +++ b/talawa-admin-docs/modules/components_UserUpdate_UserUpdate.md @@ -0,0 +1,30 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/UserUpdate/UserUpdate + +# Module: components/UserUpdate/UserUpdate + +## Table of contents + +### Functions + +- [default](components_UserUpdate_UserUpdate.md#default) + +## Functions + +### default + +▸ **default**(`props`, `context?`): ``null`` \| `ReactElement`<`any`, `any`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `PropsWithChildren`<`InterfaceUserUpdateProps`\> | +| `context?` | `any` | + +#### Returns + +``null`` \| `ReactElement`<`any`, `any`\> + +#### Defined in + +node_modules/@types/react/index.d.ts:543 diff --git a/talawa-admin-docs/modules/components_UserUpdate_UserUpdate_test.md b/talawa-admin-docs/modules/components_UserUpdate_UserUpdate_test.md new file mode 100644 index 0000000000..b5d37bf7fe --- /dev/null +++ b/talawa-admin-docs/modules/components_UserUpdate_UserUpdate_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/UserUpdate/UserUpdate.test + +# Module: components/UserUpdate/UserUpdate.test diff --git a/talawa-admin-docs/modules/components_plugins.md b/talawa-admin-docs/modules/components_plugins.md new file mode 100644 index 0000000000..a72385a04b --- /dev/null +++ b/talawa-admin-docs/modules/components_plugins.md @@ -0,0 +1,22 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/plugins + +# Module: components/plugins + +## Table of contents + +### References + +- [DummyPlugin](components_plugins.md#dummyplugin) +- [DummyPlugin2](components_plugins.md#dummyplugin2) + +## References + +### DummyPlugin + +Renames and re-exports [default](components_plugins_DummyPlugin_DummyPlugin.md#default) + +___ + +### DummyPlugin2 + +Renames and re-exports [default](components_plugins_DummyPlugin2_DummyPlugin2.md#default) diff --git a/talawa-admin-docs/modules/components_plugins_DummyPlugin2_DummyPlugin2.default.md b/talawa-admin-docs/modules/components_plugins_DummyPlugin2_DummyPlugin2.default.md new file mode 100644 index 0000000000..43f1316236 --- /dev/null +++ b/talawa-admin-docs/modules/components_plugins_DummyPlugin2_DummyPlugin2.default.md @@ -0,0 +1,32 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / [components/plugins/DummyPlugin2/DummyPlugin2](components_plugins_DummyPlugin2_DummyPlugin2.md) / default + +# Namespace: default + +[components/plugins/DummyPlugin2/DummyPlugin2](components_plugins_DummyPlugin2_DummyPlugin2.md).default + +## Table of contents + +### Variables + +- [defaultProps](components_plugins_DummyPlugin2_DummyPlugin2.default.md#defaultprops) +- [propTypes](components_plugins_DummyPlugin2_DummyPlugin2.default.md#proptypes) + +## Variables + +### defaultProps + +• **defaultProps**: `Object` + +#### Defined in + +[src/components/plugins/DummyPlugin2/DummyPlugin2.tsx:8](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/plugins/DummyPlugin2/DummyPlugin2.tsx#L8) + +___ + +### propTypes + +• **propTypes**: `Object` + +#### Defined in + +[src/components/plugins/DummyPlugin2/DummyPlugin2.tsx:10](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/plugins/DummyPlugin2/DummyPlugin2.tsx#L10) diff --git a/talawa-admin-docs/modules/components_plugins_DummyPlugin2_DummyPlugin2.md b/talawa-admin-docs/modules/components_plugins_DummyPlugin2_DummyPlugin2.md new file mode 100644 index 0000000000..8e30500c3f --- /dev/null +++ b/talawa-admin-docs/modules/components_plugins_DummyPlugin2_DummyPlugin2.md @@ -0,0 +1,27 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/plugins/DummyPlugin2/DummyPlugin2 + +# Module: components/plugins/DummyPlugin2/DummyPlugin2 + +## Table of contents + +### Namespaces + +- [default](components_plugins_DummyPlugin2_DummyPlugin2.default.md) + +### Functions + +- [default](components_plugins_DummyPlugin2_DummyPlugin2.md#default) + +## Functions + +### default + +▸ **default**(): `JSX.Element` + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/plugins/DummyPlugin2/DummyPlugin2.tsx:4](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/plugins/DummyPlugin2/DummyPlugin2.tsx#L4) diff --git a/talawa-admin-docs/modules/components_plugins_DummyPlugin2_DummyPlugin2_test.md b/talawa-admin-docs/modules/components_plugins_DummyPlugin2_DummyPlugin2_test.md new file mode 100644 index 0000000000..10b1e69c6b --- /dev/null +++ b/talawa-admin-docs/modules/components_plugins_DummyPlugin2_DummyPlugin2_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/plugins/DummyPlugin2/DummyPlugin2.test + +# Module: components/plugins/DummyPlugin2/DummyPlugin2.test diff --git a/talawa-admin-docs/modules/components_plugins_DummyPlugin_DummyPlugin.default.md b/talawa-admin-docs/modules/components_plugins_DummyPlugin_DummyPlugin.default.md new file mode 100644 index 0000000000..4ff63cd0a8 --- /dev/null +++ b/talawa-admin-docs/modules/components_plugins_DummyPlugin_DummyPlugin.default.md @@ -0,0 +1,32 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / [components/plugins/DummyPlugin/DummyPlugin](components_plugins_DummyPlugin_DummyPlugin.md) / default + +# Namespace: default + +[components/plugins/DummyPlugin/DummyPlugin](components_plugins_DummyPlugin_DummyPlugin.md).default + +## Table of contents + +### Variables + +- [defaultProps](components_plugins_DummyPlugin_DummyPlugin.default.md#defaultprops) +- [propTypes](components_plugins_DummyPlugin_DummyPlugin.default.md#proptypes) + +## Variables + +### defaultProps + +• **defaultProps**: `Object` + +#### Defined in + +[src/components/plugins/DummyPlugin/DummyPlugin.tsx:13](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/plugins/DummyPlugin/DummyPlugin.tsx#L13) + +___ + +### propTypes + +• **propTypes**: `Object` + +#### Defined in + +[src/components/plugins/DummyPlugin/DummyPlugin.tsx:15](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/plugins/DummyPlugin/DummyPlugin.tsx#L15) diff --git a/talawa-admin-docs/modules/components_plugins_DummyPlugin_DummyPlugin.md b/talawa-admin-docs/modules/components_plugins_DummyPlugin_DummyPlugin.md new file mode 100644 index 0000000000..089dbc414b --- /dev/null +++ b/talawa-admin-docs/modules/components_plugins_DummyPlugin_DummyPlugin.md @@ -0,0 +1,27 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/plugins/DummyPlugin/DummyPlugin + +# Module: components/plugins/DummyPlugin/DummyPlugin + +## Table of contents + +### Namespaces + +- [default](components_plugins_DummyPlugin_DummyPlugin.default.md) + +### Functions + +- [default](components_plugins_DummyPlugin_DummyPlugin.md#default) + +## Functions + +### default + +▸ **default**(): `JSX.Element` + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/components/plugins/DummyPlugin/DummyPlugin.tsx:5](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/components/plugins/DummyPlugin/DummyPlugin.tsx#L5) diff --git a/talawa-admin-docs/modules/components_plugins_DummyPlugin_DummyPlugin_test.md b/talawa-admin-docs/modules/components_plugins_DummyPlugin_DummyPlugin_test.md new file mode 100644 index 0000000000..91fbe5a40b --- /dev/null +++ b/talawa-admin-docs/modules/components_plugins_DummyPlugin_DummyPlugin_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / components/plugins/DummyPlugin/DummyPlugin.test + +# Module: components/plugins/DummyPlugin/DummyPlugin.test diff --git a/talawa-admin-docs/modules/screens_BlockUser_BlockUser.md b/talawa-admin-docs/modules/screens_BlockUser_BlockUser.md new file mode 100644 index 0000000000..f4900b2c0a --- /dev/null +++ b/talawa-admin-docs/modules/screens_BlockUser_BlockUser.md @@ -0,0 +1,23 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/BlockUser/BlockUser + +# Module: screens/BlockUser/BlockUser + +## Table of contents + +### Functions + +- [default](screens_BlockUser_BlockUser.md#default) + +## Functions + +### default + +▸ **default**(): `Element` + +#### Returns + +`Element` + +#### Defined in + +[src/screens/BlockUser/BlockUser.tsx:32](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/BlockUser/BlockUser.tsx#L32) diff --git a/talawa-admin-docs/modules/screens_BlockUser_BlockUser_test.md b/talawa-admin-docs/modules/screens_BlockUser_BlockUser_test.md new file mode 100644 index 0000000000..f37cc5c5ba --- /dev/null +++ b/talawa-admin-docs/modules/screens_BlockUser_BlockUser_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/BlockUser/BlockUser.test + +# Module: screens/BlockUser/BlockUser.test diff --git a/talawa-admin-docs/modules/screens_EventDashboard_EventDashboard.md b/talawa-admin-docs/modules/screens_EventDashboard_EventDashboard.md new file mode 100644 index 0000000000..536a3222b8 --- /dev/null +++ b/talawa-admin-docs/modules/screens_EventDashboard_EventDashboard.md @@ -0,0 +1,23 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/EventDashboard/EventDashboard + +# Module: screens/EventDashboard/EventDashboard + +## Table of contents + +### Functions + +- [default](screens_EventDashboard_EventDashboard.md#default) + +## Functions + +### default + +▸ **default**(): `Element` + +#### Returns + +`Element` + +#### Defined in + +[src/screens/EventDashboard/EventDashboard.tsx:38](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/EventDashboard/EventDashboard.tsx#L38) diff --git a/talawa-admin-docs/modules/screens_EventDashboard_EventDashboard_mocks.md b/talawa-admin-docs/modules/screens_EventDashboard_EventDashboard_mocks.md new file mode 100644 index 0000000000..d5ef0c33f7 --- /dev/null +++ b/talawa-admin-docs/modules/screens_EventDashboard_EventDashboard_mocks.md @@ -0,0 +1,52 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/EventDashboard/EventDashboard.mocks + +# Module: screens/EventDashboard/EventDashboard.mocks + +## Table of contents + +### Variables + +- [queryMockWithProject](screens_EventDashboard_EventDashboard_mocks.md#querymockwithproject) +- [queryMockWithProjectAndTask](screens_EventDashboard_EventDashboard_mocks.md#querymockwithprojectandtask) +- [queryMockWithTime](screens_EventDashboard_EventDashboard_mocks.md#querymockwithtime) +- [queryMockWithoutTime](screens_EventDashboard_EventDashboard_mocks.md#querymockwithouttime) + +## Variables + +### queryMockWithProject + +• `Const` **queryMockWithProject**: { `request`: { `query`: `DocumentNode` = EVENT\_DETAILS; `variables`: { `id`: `string` = 'event123' } } ; `result`: { `data`: { `event`: { `allDay`: `boolean` = false; `attendees`: { `_id`: `string` = 'user1' }[] ; `description`: `string` = 'Event Description'; `endDate`: `string` = '2/2/23'; `endTime`: `string` = '09:00:00'; `location`: `string` = 'India'; `organization`: { `_id`: `string` = 'org1'; `members`: { `_id`: `string` = 'user1'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' }[] } ; `projects`: { `_id`: `string` = 'project1'; `description`: `string` = 'Project Description 1'; `tasks`: `never`[] = []; `title`: `string` = 'Project 1' }[] ; `startDate`: `string` = '1/1/23'; `startTime`: `string` = '08:00:00'; `title`: `string` = 'Event Title' } } } }[] + +#### Defined in + +[src/screens/EventDashboard/EventDashboard.mocks.ts:68](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/EventDashboard/EventDashboard.mocks.ts#L68) + +___ + +### queryMockWithProjectAndTask + +• `Const` **queryMockWithProjectAndTask**: { `request`: { `query`: `DocumentNode` = EVENT\_DETAILS; `variables`: { `id`: `string` = 'event123' } } ; `result`: { `data`: { `event`: { `allDay`: `boolean` = false; `attendees`: { `_id`: `string` = 'user1' }[] ; `description`: `string` = 'Event Description'; `endDate`: `string` = '2/2/23'; `endTime`: `string` = '09:00:00'; `location`: `string` = 'India'; `organization`: { `_id`: `string` = 'org1'; `members`: { `_id`: `string` = 'user1'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' }[] } ; `projects`: { `_id`: `string` = 'project1'; `description`: `string` = 'Project Description 1'; `tasks`: { `_id`: `string` = 'task1'; `completed`: `boolean` = false; `deadline`: `string` = '22/12/23'; `description`: `string` = 'Description 1'; `title`: `string` = 'Task 1'; `volunteers`: `never`[] = [] }[] ; `title`: `string` = 'Project 1' }[] ; `startDate`: `string` = '1/1/23'; `startTime`: `string` = '08:00:00'; `title`: `string` = 'Event Title' } } } }[] + +#### Defined in + +[src/screens/EventDashboard/EventDashboard.mocks.ts:107](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/EventDashboard/EventDashboard.mocks.ts#L107) + +___ + +### queryMockWithTime + +• `Const` **queryMockWithTime**: { `request`: { `query`: `DocumentNode` = EVENT\_DETAILS; `variables`: { `id`: `string` = 'event123' } } ; `result`: { `data`: { `event`: { `allDay`: `boolean` = false; `attendees`: { `_id`: `string` = 'user1' }[] ; `description`: `string` = 'Event Description'; `endDate`: `string` = '2/2/23'; `endTime`: `string` = '09:00:00'; `location`: `string` = 'India'; `organization`: { `_id`: `string` = 'org1'; `members`: { `_id`: `string` = 'user1'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' }[] } ; `projects`: `never`[] = []; `startDate`: `string` = '1/1/23'; `startTime`: `string` = '08:00:00'; `title`: `string` = 'Event Title' } } } }[] + +#### Defined in + +[src/screens/EventDashboard/EventDashboard.mocks.ts:4](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/EventDashboard/EventDashboard.mocks.ts#L4) + +___ + +### queryMockWithoutTime + +• `Const` **queryMockWithoutTime**: { `request`: { `query`: `DocumentNode` = EVENT\_DETAILS; `variables`: { `id`: `string` = 'event123' } } ; `result`: { `data`: { `event`: { `allDay`: `boolean` = false; `attendees`: { `_id`: `string` = 'user1' }[] ; `description`: `string` = 'Event Description'; `endDate`: `string` = '2/2/23'; `endTime`: ``null`` = null; `location`: `string` = 'India'; `organization`: { `_id`: `string` = 'org1'; `members`: { `_id`: `string` = 'user1'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' }[] } ; `projects`: `never`[] = []; `startDate`: `string` = '1/1/23'; `startTime`: ``null`` = null; `title`: `string` = 'Event Title' } } } }[] + +#### Defined in + +[src/screens/EventDashboard/EventDashboard.mocks.ts:36](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/EventDashboard/EventDashboard.mocks.ts#L36) diff --git a/talawa-admin-docs/modules/screens_EventDashboard_EventDashboard_test.md b/talawa-admin-docs/modules/screens_EventDashboard_EventDashboard_test.md new file mode 100644 index 0000000000..56f57626c3 --- /dev/null +++ b/talawa-admin-docs/modules/screens_EventDashboard_EventDashboard_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/EventDashboard/EventDashboard.test + +# Module: screens/EventDashboard/EventDashboard.test diff --git a/talawa-admin-docs/modules/screens_ForgotPassword_ForgotPassword.md b/talawa-admin-docs/modules/screens_ForgotPassword_ForgotPassword.md new file mode 100644 index 0000000000..3ba539ee00 --- /dev/null +++ b/talawa-admin-docs/modules/screens_ForgotPassword_ForgotPassword.md @@ -0,0 +1,23 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/ForgotPassword/ForgotPassword + +# Module: screens/ForgotPassword/ForgotPassword + +## Table of contents + +### Functions + +- [default](screens_ForgotPassword_ForgotPassword.md#default) + +## Functions + +### default + +▸ **default**(): `Element` + +#### Returns + +`Element` + +#### Defined in + +[src/screens/ForgotPassword/ForgotPassword.tsx:18](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/ForgotPassword/ForgotPassword.tsx#L18) diff --git a/talawa-admin-docs/modules/screens_ForgotPassword_ForgotPassword_test.md b/talawa-admin-docs/modules/screens_ForgotPassword_ForgotPassword_test.md new file mode 100644 index 0000000000..8748876204 --- /dev/null +++ b/talawa-admin-docs/modules/screens_ForgotPassword_ForgotPassword_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/ForgotPassword/ForgotPassword.test + +# Module: screens/ForgotPassword/ForgotPassword.test diff --git a/talawa-admin-docs/modules/screens_LoginPage_LoginPage.md b/talawa-admin-docs/modules/screens_LoginPage_LoginPage.md new file mode 100644 index 0000000000..1d820b928e --- /dev/null +++ b/talawa-admin-docs/modules/screens_LoginPage_LoginPage.md @@ -0,0 +1,23 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/LoginPage/LoginPage + +# Module: screens/LoginPage/LoginPage + +## Table of contents + +### Functions + +- [default](screens_LoginPage_LoginPage.md#default) + +## Functions + +### default + +▸ **default**(): `JSX.Element` + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/screens/LoginPage/LoginPage.tsx:27](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/LoginPage/LoginPage.tsx#L27) diff --git a/talawa-admin-docs/modules/screens_LoginPage_LoginPage_test.md b/talawa-admin-docs/modules/screens_LoginPage_LoginPage_test.md new file mode 100644 index 0000000000..f269edc1ac --- /dev/null +++ b/talawa-admin-docs/modules/screens_LoginPage_LoginPage_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/LoginPage/LoginPage.test + +# Module: screens/LoginPage/LoginPage.test diff --git a/talawa-admin-docs/modules/screens_MemberDetail_MemberDetail.md b/talawa-admin-docs/modules/screens_MemberDetail_MemberDetail.md new file mode 100644 index 0000000000..775b3e0dcd --- /dev/null +++ b/talawa-admin-docs/modules/screens_MemberDetail_MemberDetail.md @@ -0,0 +1,72 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/MemberDetail/MemberDetail + +# Module: screens/MemberDetail/MemberDetail + +## Table of contents + +### Functions + +- [default](screens_MemberDetail_MemberDetail.md#default) +- [getLanguageName](screens_MemberDetail_MemberDetail.md#getlanguagename) +- [prettyDate](screens_MemberDetail_MemberDetail.md#prettydate) + +## Functions + +### default + +▸ **default**(`props`, `context?`): ``null`` \| `ReactElement`<`any`, `any`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `props` | `PropsWithChildren`<`MemberDetailProps`\> | +| `context?` | `any` | + +#### Returns + +``null`` \| `ReactElement`<`any`, `any`\> + +#### Defined in + +node_modules/@types/react/index.d.ts:543 + +___ + +### getLanguageName + +▸ **getLanguageName**(`code`): `string` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `code` | `string` | + +#### Returns + +`string` + +#### Defined in + +[src/screens/MemberDetail/MemberDetail.tsx:303](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/MemberDetail/MemberDetail.tsx#L303) + +___ + +### prettyDate + +▸ **prettyDate**(`param`): `string` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `param` | `string` | + +#### Returns + +`string` + +#### Defined in + +[src/screens/MemberDetail/MemberDetail.tsx:295](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/MemberDetail/MemberDetail.tsx#L295) diff --git a/talawa-admin-docs/modules/screens_MemberDetail_MemberDetail_test.md b/talawa-admin-docs/modules/screens_MemberDetail_MemberDetail_test.md new file mode 100644 index 0000000000..fceb473c26 --- /dev/null +++ b/talawa-admin-docs/modules/screens_MemberDetail_MemberDetail_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/MemberDetail/MemberDetail.test + +# Module: screens/MemberDetail/MemberDetail.test diff --git a/talawa-admin-docs/modules/screens_OrgContribution_OrgContribution.md b/talawa-admin-docs/modules/screens_OrgContribution_OrgContribution.md new file mode 100644 index 0000000000..87dcea8f66 --- /dev/null +++ b/talawa-admin-docs/modules/screens_OrgContribution_OrgContribution.md @@ -0,0 +1,23 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/OrgContribution/OrgContribution + +# Module: screens/OrgContribution/OrgContribution + +## Table of contents + +### Functions + +- [default](screens_OrgContribution_OrgContribution.md#default) + +## Functions + +### default + +▸ **default**(): `JSX.Element` + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/screens/OrgContribution/OrgContribution.tsx:11](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/OrgContribution/OrgContribution.tsx#L11) diff --git a/talawa-admin-docs/modules/screens_OrgContribution_OrgContribution_test.md b/talawa-admin-docs/modules/screens_OrgContribution_OrgContribution_test.md new file mode 100644 index 0000000000..588e0253be --- /dev/null +++ b/talawa-admin-docs/modules/screens_OrgContribution_OrgContribution_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/OrgContribution/OrgContribution.test + +# Module: screens/OrgContribution/OrgContribution.test diff --git a/talawa-admin-docs/modules/screens_OrgList_OrgList.md b/talawa-admin-docs/modules/screens_OrgList_OrgList.md new file mode 100644 index 0000000000..98b197b2f9 --- /dev/null +++ b/talawa-admin-docs/modules/screens_OrgList_OrgList.md @@ -0,0 +1,23 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/OrgList/OrgList + +# Module: screens/OrgList/OrgList + +## Table of contents + +### Functions + +- [default](screens_OrgList_OrgList.md#default) + +## Functions + +### default + +▸ **default**(): `JSX.Element` + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/screens/OrgList/OrgList.tsx:29](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/OrgList/OrgList.tsx#L29) diff --git a/talawa-admin-docs/modules/screens_OrgList_OrgListMocks.md b/talawa-admin-docs/modules/screens_OrgList_OrgListMocks.md new file mode 100644 index 0000000000..3cee071055 --- /dev/null +++ b/talawa-admin-docs/modules/screens_OrgList_OrgListMocks.md @@ -0,0 +1,41 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/OrgList/OrgListMocks + +# Module: screens/OrgList/OrgListMocks + +## Table of contents + +### Variables + +- [MOCKS](screens_OrgList_OrgListMocks.md#mocks) +- [MOCKS\_ADMIN](screens_OrgList_OrgListMocks.md#mocks_admin) +- [MOCKS\_EMPTY](screens_OrgList_OrgListMocks.md#mocks_empty) + +## Variables + +### MOCKS + +• `Const` **MOCKS**: ({ `request`: { `query`: `DocumentNode` = ORGANIZATION\_CONNECTION\_LIST; `variables?`: `undefined` } ; `result`: { `data`: { `organizationsConnection`: `InterfaceOrgConnectionInfoType`[] = organizations } } } \| { `request`: { `query`: `DocumentNode` = USER\_ORGANIZATION\_LIST; `variables`: { `id`: `string` = '123' } } ; `result`: { `data`: `InterfaceUserType` = superAdminUser } })[] + +#### Defined in + +[src/screens/OrgList/OrgListMocks.ts:79](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/OrgList/OrgListMocks.ts#L79) + +___ + +### MOCKS\_ADMIN + +• `Const` **MOCKS\_ADMIN**: ({ `request`: { `query`: `DocumentNode` = ORGANIZATION\_CONNECTION\_LIST; `variables?`: `undefined` } ; `result`: { `data`: { `organizationsConnection`: `InterfaceOrgConnectionInfoType`[] = organizations } } } \| { `request`: { `query`: `DocumentNode` = USER\_ORGANIZATION\_LIST; `variables`: { `id`: `string` = '123' } } ; `result`: { `data`: `InterfaceUserType` = adminUser } })[] + +#### Defined in + +[src/screens/OrgList/OrgListMocks.ts:123](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/OrgList/OrgListMocks.ts#L123) + +___ + +### MOCKS\_EMPTY + +• `Const` **MOCKS\_EMPTY**: ({ `request`: { `query`: `DocumentNode` = ORGANIZATION\_CONNECTION\_LIST; `variables?`: `undefined` } ; `result`: { `data`: { `organizationsConnection`: `never`[] = [] } } } \| { `request`: { `query`: `DocumentNode` = USER\_ORGANIZATION\_LIST; `variables`: { `id`: `string` = '123' } } ; `result`: { `data`: `InterfaceUserType` = superAdminUser } })[] + +#### Defined in + +[src/screens/OrgList/OrgListMocks.ts:100](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/OrgList/OrgListMocks.ts#L100) diff --git a/talawa-admin-docs/modules/screens_OrgList_OrgList_test.md b/talawa-admin-docs/modules/screens_OrgList_OrgList_test.md new file mode 100644 index 0000000000..97033df2f3 --- /dev/null +++ b/talawa-admin-docs/modules/screens_OrgList_OrgList_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/OrgList/OrgList.test + +# Module: screens/OrgList/OrgList.test diff --git a/talawa-admin-docs/modules/screens_OrgPost_OrgPost.md b/talawa-admin-docs/modules/screens_OrgPost_OrgPost.md new file mode 100644 index 0000000000..cdc5d0b854 --- /dev/null +++ b/talawa-admin-docs/modules/screens_OrgPost_OrgPost.md @@ -0,0 +1,23 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/OrgPost/OrgPost + +# Module: screens/OrgPost/OrgPost + +## Table of contents + +### Functions + +- [default](screens_OrgPost_OrgPost.md#default) + +## Functions + +### default + +▸ **default**(): `JSX.Element` + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/screens/OrgPost/OrgPost.tsx:25](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/OrgPost/OrgPost.tsx#L25) diff --git a/talawa-admin-docs/modules/screens_OrgPost_OrgPost_test.md b/talawa-admin-docs/modules/screens_OrgPost_OrgPost_test.md new file mode 100644 index 0000000000..7bbf3988e6 --- /dev/null +++ b/talawa-admin-docs/modules/screens_OrgPost_OrgPost_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/OrgPost/OrgPost.test + +# Module: screens/OrgPost/OrgPost.test diff --git a/talawa-admin-docs/modules/screens_OrgSettings_OrgSettings.md b/talawa-admin-docs/modules/screens_OrgSettings_OrgSettings.md new file mode 100644 index 0000000000..c20c2e6ad8 --- /dev/null +++ b/talawa-admin-docs/modules/screens_OrgSettings_OrgSettings.md @@ -0,0 +1,23 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/OrgSettings/OrgSettings + +# Module: screens/OrgSettings/OrgSettings + +## Table of contents + +### Functions + +- [default](screens_OrgSettings_OrgSettings.md#default) + +## Functions + +### default + +▸ **default**(): `JSX.Element` + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/screens/OrgSettings/OrgSettings.tsx:18](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/OrgSettings/OrgSettings.tsx#L18) diff --git a/talawa-admin-docs/modules/screens_OrgSettings_OrgSettings_test.md b/talawa-admin-docs/modules/screens_OrgSettings_OrgSettings_test.md new file mode 100644 index 0000000000..58f2a07074 --- /dev/null +++ b/talawa-admin-docs/modules/screens_OrgSettings_OrgSettings_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/OrgSettings/OrgSettings.test + +# Module: screens/OrgSettings/OrgSettings.test diff --git a/talawa-admin-docs/modules/screens_OrganizationDashboard_OrganizationDashboard.md b/talawa-admin-docs/modules/screens_OrganizationDashboard_OrganizationDashboard.md new file mode 100644 index 0000000000..eb89824a56 --- /dev/null +++ b/talawa-admin-docs/modules/screens_OrganizationDashboard_OrganizationDashboard.md @@ -0,0 +1,23 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/OrganizationDashboard/OrganizationDashboard + +# Module: screens/OrganizationDashboard/OrganizationDashboard + +## Table of contents + +### Functions + +- [default](screens_OrganizationDashboard_OrganizationDashboard.md#default) + +## Functions + +### default + +▸ **default**(): `JSX.Element` + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/screens/OrganizationDashboard/OrganizationDashboard.tsx:25](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/OrganizationDashboard/OrganizationDashboard.tsx#L25) diff --git a/talawa-admin-docs/modules/screens_OrganizationDashboard_OrganizationDashboardMocks.md b/talawa-admin-docs/modules/screens_OrganizationDashboard_OrganizationDashboardMocks.md new file mode 100644 index 0000000000..eeee46963b --- /dev/null +++ b/talawa-admin-docs/modules/screens_OrganizationDashboard_OrganizationDashboardMocks.md @@ -0,0 +1,41 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/OrganizationDashboard/OrganizationDashboardMocks + +# Module: screens/OrganizationDashboard/OrganizationDashboardMocks + +## Table of contents + +### Variables + +- [MOCKS\_NO\_TAGS](screens_OrganizationDashboard_OrganizationDashboardMocks.md#mocks_no_tags) +- [MOCKS\_WITHOUT\_IMAGE](screens_OrganizationDashboard_OrganizationDashboardMocks.md#mocks_without_image) +- [MOCKS\_WITH\_IMAGE](screens_OrganizationDashboard_OrganizationDashboardMocks.md#mocks_with_image) + +## Variables + +### MOCKS\_NO\_TAGS + +• `Const` **MOCKS\_NO\_TAGS**: ({ `request`: { `query`: `DocumentNode` = ORGANIZATIONS\_LIST } ; `result`: { `data`: { `eventsByOrganization?`: `undefined` ; `organizations`: { `_id`: `number` = 1; `admins`: { `_id`: `string` = '123'; `email`: `string` = 'johndoe@gmail.com'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' } ; `blockedUsers`: { `_id`: `string` = '789'; `email`: `string` = 'stevesmith@gmail.com'; `firstName`: `string` = 'Steve'; `lastName`: `string` = 'Smith' } ; `creator`: { `email`: `string` = ''; `firstName`: `string` = ''; `lastName`: `string` = '' } ; `description`: `string` = 'This is a Dummy Organization'; `image`: `string` = ''; `location`: `string` = 'New Delhi'; `members`: { `_id`: `string` = '123'; `email`: `string` = 'johndoe@gmail.com'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' } ; `membershipRequests`: { `_id`: `string` = '456'; `user`: { `email`: `string` = 'samsmith@gmail.com'; `firstName`: `string` = 'Sam'; `lastName`: `string` = 'Smith' } } ; `name`: `string` = 'Dummy Organization'; `spamCount`: { `_id`: `string` = '6954'; `groupchat`: { `_id`: `string` = '321'; `title`: `string` = 'Dummy' } ; `isReaded`: `boolean` = false; `user`: { `_id`: `string` = '878'; `email`: `string` = 'joeroot@gmail.com'; `firstName`: `string` = 'Joe'; `lastName`: `string` = 'Root' } }[] }[] ; `postsByOrganization?`: `undefined` } } } \| { `request`: { `query`: `DocumentNode` = ORGANIZATION\_POST\_LIST } ; `result`: { `data`: { `eventsByOrganization?`: `undefined` ; `organizations?`: `undefined` ; `postsByOrganization`: { `_id`: `number` = 1; `creator`: { `_id`: `string` = '583'; `email`: `string` = 'johndoe@gmail.com'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' } ; `imageUrl`: `string` = ''; `text`: `string` = 'Capture Jinchuriki'; `title`: `string` = 'Akatsuki'; `videoUrl`: `string` = '' }[] } } } \| { `request`: { `query`: `DocumentNode` = ORGANIZATION\_EVENT\_LIST } ; `result`: { `data`: { `eventsByOrganization`: { `_id`: `number` = 1; `allDay`: `boolean` = false; `description`: `string` = 'Event Test'; `endDate`: `string` = ''; `endTime`: `string` = '06:00'; `isPublic`: `boolean` = true; `isRegisterable`: `boolean` = true; `location`: `string` = 'New Delhi'; `recurring`: `boolean` = false; `startDate`: `string` = ''; `startTime`: `string` = '02:00'; `title`: `string` = 'Event' }[] ; `organizations?`: `undefined` ; `postsByOrganization?`: `undefined` } } })[] + +#### Defined in + +[src/screens/OrganizationDashboard/OrganizationDashboardMocks.ts:139](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/OrganizationDashboard/OrganizationDashboardMocks.ts#L139) + +___ + +### MOCKS\_WITHOUT\_IMAGE + +• `Const` **MOCKS\_WITHOUT\_IMAGE**: ({ `request`: { `query`: `DocumentNode` = ORGANIZATIONS\_LIST } ; `result`: { `data`: { `eventsByOrganization?`: `undefined` ; `organizations`: { `_id`: `number` = 1; `admins`: { `_id`: `string` = '123'; `email`: `string` = 'johndoe@gmail.com'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' } ; `blockedUsers`: { `_id`: `string` = '789'; `email`: `string` = 'stevesmith@gmail.com'; `firstName`: `string` = 'Steve'; `lastName`: `string` = 'Smith' } ; `creator`: { `email`: `string` = ''; `firstName`: `string` = ''; `lastName`: `string` = '' } ; `description`: `string` = 'This is a Dummy Organization'; `image`: `string` = ''; `location`: `string` = 'New Delhi'; `members`: { `_id`: `string` = '123'; `email`: `string` = 'johndoe@gmail.com'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' } ; `membershipRequests`: { `_id`: `string` = '456'; `user`: { `email`: `string` = 'samsmith@gmail.com'; `firstName`: `string` = 'Sam'; `lastName`: `string` = 'Smith' } } ; `name`: `string` = 'Dummy Organization'; `spamCount`: { `_id`: `string` = '6954'; `groupchat`: { `_id`: `string` = '321'; `title`: `string` = 'Dummy' } ; `isReaded`: `boolean` = false; `user`: { `_id`: `string` = '878'; `email`: `string` = 'joeroot@gmail.com'; `firstName`: `string` = 'Joe'; `lastName`: `string` = 'Root' } }[] }[] ; `postsByOrganization?`: `undefined` ; `removeOrganization?`: `undefined` } } } \| { `request`: { `query`: `DocumentNode` = ORGANIZATION\_POST\_LIST } ; `result`: { `data`: { `eventsByOrganization?`: `undefined` ; `organizations?`: `undefined` ; `postsByOrganization`: { `_id`: `number` = 1; `creator`: { `_id`: `string` = '583'; `email`: `string` = 'johndoe@gmail.com'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' } ; `imageUrl`: `string` = ''; `text`: `string` = 'Capture Jinchuriki'; `title`: `string` = 'Akatsuki'; `videoUrl`: `string` = '' }[] ; `removeOrganization?`: `undefined` } } } \| { `request`: { `query`: `DocumentNode` = DELETE\_ORGANIZATION\_MUTATION } ; `result`: { `data`: { `eventsByOrganization?`: `undefined` ; `organizations?`: `undefined` ; `postsByOrganization?`: `undefined` ; `removeOrganization`: { `_id`: `number` = 1 }[] } } } \| { `request`: { `query`: `DocumentNode` = ORGANIZATION\_EVENT\_LIST } ; `result`: { `data`: { `eventsByOrganization`: { `_id`: `number` = 1; `allDay`: `boolean` = false; `description`: `string` = 'Event Test'; `endDate`: `string` = ''; `endTime`: `string` = '06:00'; `isPublic`: `boolean` = true; `isRegisterable`: `boolean` = true; `location`: `string` = 'New Delhi'; `recurring`: `boolean` = false; `startDate`: `string` = ''; `startTime`: `string` = '02:00'; `title`: `string` = 'Event' }[] ; `organizations?`: `undefined` ; `postsByOrganization?`: `undefined` ; `removeOrganization?`: `undefined` } } })[] + +#### Defined in + +[src/screens/OrganizationDashboard/OrganizationDashboardMocks.ts:8](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/OrganizationDashboard/OrganizationDashboardMocks.ts#L8) + +___ + +### MOCKS\_WITH\_IMAGE + +• `Const` **MOCKS\_WITH\_IMAGE**: ({ `request`: { `query`: `DocumentNode` = ORGANIZATIONS\_LIST } ; `result`: { `data`: { `eventsByOrganization?`: `undefined` ; `organizations`: { `_id`: `number` = 1; `admins`: { `_id`: `string` = '123'; `email`: `string` = 'johndoe@gmail.com'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' } ; `blockedUsers`: { `_id`: `string` = '789'; `email`: `string` = 'stevesmith@gmail.com'; `firstName`: `string` = 'Steve'; `lastName`: `string` = 'Smith' } ; `creator`: { `email`: `string` = ''; `firstName`: `string` = ''; `lastName`: `string` = '' } ; `description`: `string` = 'This is a Dummy Organization'; `image`: `string` = 'https://via.placeholder.com/200x200'; `location`: `string` = 'New Delhi'; `members`: { `_id`: `string` = '123'; `email`: `string` = 'johndoe@gmail.com'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' } ; `membershipRequests`: { `_id`: `string` = '456'; `user`: { `email`: `string` = 'samsmith@gmail.com'; `firstName`: `string` = 'Sam'; `lastName`: `string` = 'Smith' } } ; `name`: `string` = 'Dummy Organization'; `spamCount`: { `_id`: `string` = '6954'; `groupchat`: { `_id`: `string` = '321'; `title`: `string` = 'Dummy' } ; `isReaded`: `boolean` = false; `user`: { `_id`: `string` = '878'; `email`: `string` = 'joeroot@gmail.com'; `firstName`: `string` = 'Joe'; `lastName`: `string` = 'Root' } }[] }[] ; `postsByOrganization?`: `undefined` } } } \| { `request`: { `query`: `DocumentNode` = ORGANIZATION\_POST\_LIST } ; `result`: { `data`: { `eventsByOrganization?`: `undefined` ; `organizations?`: `undefined` ; `postsByOrganization`: { `_id`: `number` = 1; `creator`: { `_id`: `string` = '583'; `email`: `string` = 'johndoe@gmail.com'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' } ; `imageUrl`: `string` = ''; `text`: `string` = 'Capture Jinchuriki'; `title`: `string` = 'Akatsuki'; `videoUrl`: `string` = '' }[] } } } \| { `request`: { `query`: `DocumentNode` = ORGANIZATION\_EVENT\_LIST } ; `result`: { `data`: { `eventsByOrganization`: { `_id`: `number` = 1; `allDay`: `boolean` = false; `description`: `string` = 'Event Test'; `endDate`: `string` = ''; `endTime`: `string` = '06:00'; `isPublic`: `boolean` = true; `isRegisterable`: `boolean` = true; `location`: `string` = 'New Delhi'; `recurring`: `boolean` = false; `startDate`: `string` = ''; `startTime`: `string` = '02:00'; `title`: `string` = 'Event' }[] ; `organizations?`: `undefined` ; `postsByOrganization?`: `undefined` } } })[] + +#### Defined in + +[src/screens/OrganizationDashboard/OrganizationDashboardMocks.ts:256](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/OrganizationDashboard/OrganizationDashboardMocks.ts#L256) diff --git a/talawa-admin-docs/modules/screens_OrganizationDashboard_OrganizationDashboard_test.md b/talawa-admin-docs/modules/screens_OrganizationDashboard_OrganizationDashboard_test.md new file mode 100644 index 0000000000..59b308b2c3 --- /dev/null +++ b/talawa-admin-docs/modules/screens_OrganizationDashboard_OrganizationDashboard_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/OrganizationDashboard/OrganizationDashboard.test + +# Module: screens/OrganizationDashboard/OrganizationDashboard.test diff --git a/talawa-admin-docs/modules/screens_OrganizationEvents_OrganizationEvents.md b/talawa-admin-docs/modules/screens_OrganizationEvents_OrganizationEvents.md new file mode 100644 index 0000000000..a360d62602 --- /dev/null +++ b/talawa-admin-docs/modules/screens_OrganizationEvents_OrganizationEvents.md @@ -0,0 +1,23 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/OrganizationEvents/OrganizationEvents + +# Module: screens/OrganizationEvents/OrganizationEvents + +## Table of contents + +### Functions + +- [default](screens_OrganizationEvents_OrganizationEvents.md#default) + +## Functions + +### default + +▸ **default**(): `JSX.Element` + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/screens/OrganizationEvents/OrganizationEvents.tsx:27](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/OrganizationEvents/OrganizationEvents.tsx#L27) diff --git a/talawa-admin-docs/modules/screens_OrganizationEvents_OrganizationEvents_test.md b/talawa-admin-docs/modules/screens_OrganizationEvents_OrganizationEvents_test.md new file mode 100644 index 0000000000..6cbca3f09b --- /dev/null +++ b/talawa-admin-docs/modules/screens_OrganizationEvents_OrganizationEvents_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/OrganizationEvents/OrganizationEvents.test + +# Module: screens/OrganizationEvents/OrganizationEvents.test diff --git a/talawa-admin-docs/modules/screens_OrganizationPeople_OrganizationPeople.md b/talawa-admin-docs/modules/screens_OrganizationPeople_OrganizationPeople.md new file mode 100644 index 0000000000..8944e2fa18 --- /dev/null +++ b/talawa-admin-docs/modules/screens_OrganizationPeople_OrganizationPeople.md @@ -0,0 +1,23 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/OrganizationPeople/OrganizationPeople + +# Module: screens/OrganizationPeople/OrganizationPeople + +## Table of contents + +### Functions + +- [default](screens_OrganizationPeople_OrganizationPeople.md#default) + +## Functions + +### default + +▸ **default**(): `JSX.Element` + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/screens/OrganizationPeople/OrganizationPeople.tsx:24](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/OrganizationPeople/OrganizationPeople.tsx#L24) diff --git a/talawa-admin-docs/modules/screens_OrganizationPeople_OrganizationPeople_test.md b/talawa-admin-docs/modules/screens_OrganizationPeople_OrganizationPeople_test.md new file mode 100644 index 0000000000..e0879da4b3 --- /dev/null +++ b/talawa-admin-docs/modules/screens_OrganizationPeople_OrganizationPeople_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/OrganizationPeople/OrganizationPeople.test + +# Module: screens/OrganizationPeople/OrganizationPeople.test diff --git a/talawa-admin-docs/modules/screens_PageNotFound_PageNotFound.md b/talawa-admin-docs/modules/screens_PageNotFound_PageNotFound.md new file mode 100644 index 0000000000..18cd057b40 --- /dev/null +++ b/talawa-admin-docs/modules/screens_PageNotFound_PageNotFound.md @@ -0,0 +1,23 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/PageNotFound/PageNotFound + +# Module: screens/PageNotFound/PageNotFound + +## Table of contents + +### Functions + +- [default](screens_PageNotFound_PageNotFound.md#default) + +## Functions + +### default + +▸ **default**(): `Element` + +#### Returns + +`Element` + +#### Defined in + +[src/screens/PageNotFound/PageNotFound.tsx:8](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/PageNotFound/PageNotFound.tsx#L8) diff --git a/talawa-admin-docs/modules/screens_PageNotFound_PageNotFound_test.md b/talawa-admin-docs/modules/screens_PageNotFound_PageNotFound_test.md new file mode 100644 index 0000000000..b63137770c --- /dev/null +++ b/talawa-admin-docs/modules/screens_PageNotFound_PageNotFound_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/PageNotFound/PageNotFound.test + +# Module: screens/PageNotFound/PageNotFound.test diff --git a/talawa-admin-docs/modules/screens_Requests_Requests.md b/talawa-admin-docs/modules/screens_Requests_Requests.md new file mode 100644 index 0000000000..bc869b3bdf --- /dev/null +++ b/talawa-admin-docs/modules/screens_Requests_Requests.md @@ -0,0 +1,23 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/Requests/Requests + +# Module: screens/Requests/Requests + +## Table of contents + +### Functions + +- [default](screens_Requests_Requests.md#default) + +## Functions + +### default + +▸ **default**(): `Element` + +#### Returns + +`Element` + +#### Defined in + +[src/screens/Requests/Requests.tsx:30](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/Requests/Requests.tsx#L30) diff --git a/talawa-admin-docs/modules/screens_Requests_Requests_test.md b/talawa-admin-docs/modules/screens_Requests_Requests_test.md new file mode 100644 index 0000000000..62f8ec88e0 --- /dev/null +++ b/talawa-admin-docs/modules/screens_Requests_Requests_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/Requests/Requests.test + +# Module: screens/Requests/Requests.test diff --git a/talawa-admin-docs/modules/screens_UserPortal_Donate_Donate.md b/talawa-admin-docs/modules/screens_UserPortal_Donate_Donate.md new file mode 100644 index 0000000000..44a76a5d36 --- /dev/null +++ b/talawa-admin-docs/modules/screens_UserPortal_Donate_Donate.md @@ -0,0 +1,23 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/UserPortal/Donate/Donate + +# Module: screens/UserPortal/Donate/Donate + +## Table of contents + +### Functions + +- [default](screens_UserPortal_Donate_Donate.md#default) + +## Functions + +### default + +▸ **default**(): `JSX.Element` + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/screens/UserPortal/Donate/Donate.tsx:27](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/UserPortal/Donate/Donate.tsx#L27) diff --git a/talawa-admin-docs/modules/screens_UserPortal_Donate_Donate_test.md b/talawa-admin-docs/modules/screens_UserPortal_Donate_Donate_test.md new file mode 100644 index 0000000000..5fd12c96d5 --- /dev/null +++ b/talawa-admin-docs/modules/screens_UserPortal_Donate_Donate_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/UserPortal/Donate/Donate.test + +# Module: screens/UserPortal/Donate/Donate.test diff --git a/talawa-admin-docs/modules/screens_UserPortal_Home_Home.md b/talawa-admin-docs/modules/screens_UserPortal_Home_Home.md new file mode 100644 index 0000000000..ed3f409426 --- /dev/null +++ b/talawa-admin-docs/modules/screens_UserPortal_Home_Home.md @@ -0,0 +1,23 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/UserPortal/Home/Home + +# Module: screens/UserPortal/Home/Home + +## Table of contents + +### Functions + +- [default](screens_UserPortal_Home_Home.md#default) + +## Functions + +### default + +▸ **default**(): `JSX.Element` + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/screens/UserPortal/Home/Home.tsx:43](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/UserPortal/Home/Home.tsx#L43) diff --git a/talawa-admin-docs/modules/screens_UserPortal_Home_Home_test.md b/talawa-admin-docs/modules/screens_UserPortal_Home_Home_test.md new file mode 100644 index 0000000000..024a7960f4 --- /dev/null +++ b/talawa-admin-docs/modules/screens_UserPortal_Home_Home_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/UserPortal/Home/Home.test + +# Module: screens/UserPortal/Home/Home.test diff --git a/talawa-admin-docs/modules/screens_UserPortal_Organizations_Organizations.md b/talawa-admin-docs/modules/screens_UserPortal_Organizations_Organizations.md new file mode 100644 index 0000000000..42ab891319 --- /dev/null +++ b/talawa-admin-docs/modules/screens_UserPortal_Organizations_Organizations.md @@ -0,0 +1,23 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/UserPortal/Organizations/Organizations + +# Module: screens/UserPortal/Organizations/Organizations + +## Table of contents + +### Functions + +- [default](screens_UserPortal_Organizations_Organizations.md#default) + +## Functions + +### default + +▸ **default**(): `JSX.Element` + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/screens/UserPortal/Organizations/Organizations.tsx:25](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/UserPortal/Organizations/Organizations.tsx#L25) diff --git a/talawa-admin-docs/modules/screens_UserPortal_Organizations_Organizations_test.md b/talawa-admin-docs/modules/screens_UserPortal_Organizations_Organizations_test.md new file mode 100644 index 0000000000..71d42b41fc --- /dev/null +++ b/talawa-admin-docs/modules/screens_UserPortal_Organizations_Organizations_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/UserPortal/Organizations/Organizations.test + +# Module: screens/UserPortal/Organizations/Organizations.test diff --git a/talawa-admin-docs/modules/screens_UserPortal_People_People.md b/talawa-admin-docs/modules/screens_UserPortal_People_People.md new file mode 100644 index 0000000000..0212686009 --- /dev/null +++ b/talawa-admin-docs/modules/screens_UserPortal_People_People.md @@ -0,0 +1,23 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/UserPortal/People/People + +# Module: screens/UserPortal/People/People + +## Table of contents + +### Functions + +- [default](screens_UserPortal_People_People.md#default) + +## Functions + +### default + +▸ **default**(): `JSX.Element` + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/screens/UserPortal/People/People.tsx:26](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/UserPortal/People/People.tsx#L26) diff --git a/talawa-admin-docs/modules/screens_UserPortal_People_People_test.md b/talawa-admin-docs/modules/screens_UserPortal_People_People_test.md new file mode 100644 index 0000000000..2e500bc348 --- /dev/null +++ b/talawa-admin-docs/modules/screens_UserPortal_People_People_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/UserPortal/People/People.test + +# Module: screens/UserPortal/People/People.test diff --git a/talawa-admin-docs/modules/screens_UserPortal_Settings_Settings.md b/talawa-admin-docs/modules/screens_UserPortal_Settings_Settings.md new file mode 100644 index 0000000000..1940359b75 --- /dev/null +++ b/talawa-admin-docs/modules/screens_UserPortal_Settings_Settings.md @@ -0,0 +1,23 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/UserPortal/Settings/Settings + +# Module: screens/UserPortal/Settings/Settings + +## Table of contents + +### Functions + +- [default](screens_UserPortal_Settings_Settings.md#default) + +## Functions + +### default + +▸ **default**(): `JSX.Element` + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/screens/UserPortal/Settings/Settings.tsx:14](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/UserPortal/Settings/Settings.tsx#L14) diff --git a/talawa-admin-docs/modules/screens_UserPortal_Settings_Settings_test.md b/talawa-admin-docs/modules/screens_UserPortal_Settings_Settings_test.md new file mode 100644 index 0000000000..89bc26e757 --- /dev/null +++ b/talawa-admin-docs/modules/screens_UserPortal_Settings_Settings_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/UserPortal/Settings/Settings.test + +# Module: screens/UserPortal/Settings/Settings.test diff --git a/talawa-admin-docs/modules/screens_UserPortal_UserLoginPage_UserLoginPage.md b/talawa-admin-docs/modules/screens_UserPortal_UserLoginPage_UserLoginPage.md new file mode 100644 index 0000000000..ea6c9b5c69 --- /dev/null +++ b/talawa-admin-docs/modules/screens_UserPortal_UserLoginPage_UserLoginPage.md @@ -0,0 +1,23 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/UserPortal/UserLoginPage/UserLoginPage + +# Module: screens/UserPortal/UserLoginPage/UserLoginPage + +## Table of contents + +### Functions + +- [default](screens_UserPortal_UserLoginPage_UserLoginPage.md#default) + +## Functions + +### default + +▸ **default**(): `JSX.Element` + +#### Returns + +`JSX.Element` + +#### Defined in + +[src/screens/UserPortal/UserLoginPage/UserLoginPage.tsx:11](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/UserPortal/UserLoginPage/UserLoginPage.tsx#L11) diff --git a/talawa-admin-docs/modules/screens_UserPortal_UserLoginPage_UserLoginPage_test.md b/talawa-admin-docs/modules/screens_UserPortal_UserLoginPage_UserLoginPage_test.md new file mode 100644 index 0000000000..186ddd1caf --- /dev/null +++ b/talawa-admin-docs/modules/screens_UserPortal_UserLoginPage_UserLoginPage_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/UserPortal/UserLoginPage/UserLoginPage.test + +# Module: screens/UserPortal/UserLoginPage/UserLoginPage.test diff --git a/talawa-admin-docs/modules/screens_Users_Users.md b/talawa-admin-docs/modules/screens_Users_Users.md new file mode 100644 index 0000000000..08fdfc77b8 --- /dev/null +++ b/talawa-admin-docs/modules/screens_Users_Users.md @@ -0,0 +1,23 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/Users/Users + +# Module: screens/Users/Users + +## Table of contents + +### Functions + +- [default](screens_Users_Users.md#default) + +## Functions + +### default + +▸ **default**(): `Element` + +#### Returns + +`Element` + +#### Defined in + +[src/screens/Users/Users.tsx:24](https://github.com/PalisadoesFoundation/talawa-admin/blob/b619a0d/src/screens/Users/Users.tsx#L24) diff --git a/talawa-admin-docs/modules/screens_Users_Users_test.md b/talawa-admin-docs/modules/screens_Users_Users_test.md new file mode 100644 index 0000000000..c8069af122 --- /dev/null +++ b/talawa-admin-docs/modules/screens_Users_Users_test.md @@ -0,0 +1,3 @@ +[talawa-admin](../README.md) / [Modules](../modules.md) / screens/Users/Users.test + +# Module: screens/Users/Users.test diff --git a/tsconfig.json b/tsconfig.json index 9d379a3c4a..6aeebd66d6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "baseUrl": "src", "target": "es5", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, @@ -16,5 +17,5 @@ "noEmit": true, "jsx": "react-jsx" }, - "include": ["src"] + "include": ["src", "src/App.tsx"] } diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index b9f81e8c57..0000000000 --- a/yarn.lock +++ /dev/null @@ -1,11845 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@babel/code-frame@7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" - integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== - dependencies: - "@babel/highlight" "^7.10.4" - -"@babel/code-frame@7.12.11": - version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" - integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== - dependencies: - "@babel/highlight" "^7.10.4" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.5.5": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658" - integrity sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g== - dependencies: - "@babel/highlight" "^7.12.13" - -"@babel/compat-data@^7.12.1", "@babel/compat-data@^7.13.11", "@babel/compat-data@^7.13.15", "@babel/compat-data@^7.14.0": - version "7.14.0" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.14.0.tgz#a901128bce2ad02565df95e6ecbf195cf9465919" - integrity sha512-vu9V3uMM/1o5Hl5OekMUowo3FqXLJSw+s+66nt0fSWVWTtmosdzn45JHOB3cPtZoe6CTBDzvSw0RdOY85Q37+Q== - -"@babel/core@7.12.3": - version "7.12.3" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.3.tgz#1b436884e1e3bff6fb1328dc02b208759de92ad8" - integrity sha512-0qXcZYKZp3/6N2jKYVxZv0aNCsxTSVCiK72DTiTYZAu7sjg73W0/aynWjMbiGd87EQL4WyA8reiJVh92AVla9g== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.12.1" - "@babel/helper-module-transforms" "^7.12.1" - "@babel/helpers" "^7.12.1" - "@babel/parser" "^7.12.3" - "@babel/template" "^7.10.4" - "@babel/traverse" "^7.12.1" - "@babel/types" "^7.12.1" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.1" - json5 "^2.1.2" - lodash "^4.17.19" - resolve "^1.3.2" - semver "^5.4.1" - source-map "^0.5.0" - -"@babel/core@^7.1.0", "@babel/core@^7.12.3", "@babel/core@^7.7.5", "@babel/core@^7.8.4": - version "7.14.3" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.14.3.tgz#5395e30405f0776067fbd9cf0884f15bfb770a38" - integrity sha512-jB5AmTKOCSJIZ72sd78ECEhuPiDMKlQdDI/4QRI6lzYATx5SSogS1oQA2AoPecRCknm30gHi2l+QVvNUu3wZAg== - dependencies: - "@babel/code-frame" "^7.12.13" - "@babel/generator" "^7.14.3" - "@babel/helper-compilation-targets" "^7.13.16" - "@babel/helper-module-transforms" "^7.14.2" - "@babel/helpers" "^7.14.0" - "@babel/parser" "^7.14.3" - "@babel/template" "^7.12.13" - "@babel/traverse" "^7.14.2" - "@babel/types" "^7.14.2" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.1.2" - semver "^6.3.0" - source-map "^0.5.0" - -"@babel/generator@^7.12.1", "@babel/generator@^7.14.2", "@babel/generator@^7.14.3": - version "7.14.3" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.14.3.tgz#0c2652d91f7bddab7cccc6ba8157e4f40dcedb91" - integrity sha512-bn0S6flG/j0xtQdz3hsjJ624h3W0r3llttBMfyHX3YrZ/KtLYr15bjA0FXkgW7FpvrDuTuElXeVjiKlYRpnOFA== - dependencies: - "@babel/types" "^7.14.2" - jsesc "^2.5.1" - source-map "^0.5.0" - -"@babel/helper-annotate-as-pure@^7.10.4", "@babel/helper-annotate-as-pure@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.13.tgz#0f58e86dfc4bb3b1fcd7db806570e177d439b6ab" - integrity sha512-7YXfX5wQ5aYM/BOlbSccHDbuXXFPxeoUmfWtz8le2yTkTZc+BxsiEnENFoi2SlmA8ewDkG2LgIMIVzzn2h8kfw== - dependencies: - "@babel/types" "^7.12.13" - -"@babel/helper-builder-binary-assignment-operator-visitor@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.12.13.tgz#6bc20361c88b0a74d05137a65cac8d3cbf6f61fc" - integrity sha512-CZOv9tGphhDRlVjVkAgm8Nhklm9RzSmWpX2my+t7Ua/KT616pEzXsQCjinzvkRvHWJ9itO4f296efroX23XCMA== - dependencies: - "@babel/helper-explode-assignable-expression" "^7.12.13" - "@babel/types" "^7.12.13" - -"@babel/helper-compilation-targets@^7.12.1", "@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.13.16": - version "7.13.16" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.16.tgz#6e91dccf15e3f43e5556dffe32d860109887563c" - integrity sha512-3gmkYIrpqsLlieFwjkGgLaSHmhnvlAYzZLlYVjlW+QwI+1zE17kGxuJGmIqDQdYp56XdmGeD+Bswx0UTyG18xA== - dependencies: - "@babel/compat-data" "^7.13.15" - "@babel/helper-validator-option" "^7.12.17" - browserslist "^4.14.5" - semver "^6.3.0" - -"@babel/helper-create-class-features-plugin@^7.12.1", "@babel/helper-create-class-features-plugin@^7.13.0", "@babel/helper-create-class-features-plugin@^7.14.0", "@babel/helper-create-class-features-plugin@^7.14.3": - version "7.14.3" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.3.tgz#832111bcf4f57ca57a4c5b1a000fc125abc6554a" - integrity sha512-BnEfi5+6J2Lte9LeiL6TxLWdIlEv9Woacc1qXzXBgbikcOzMRM2Oya5XGg/f/ngotv1ej2A/b+3iJH8wbS1+lQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.12.13" - "@babel/helper-function-name" "^7.14.2" - "@babel/helper-member-expression-to-functions" "^7.13.12" - "@babel/helper-optimise-call-expression" "^7.12.13" - "@babel/helper-replace-supers" "^7.14.3" - "@babel/helper-split-export-declaration" "^7.12.13" - -"@babel/helper-create-regexp-features-plugin@^7.12.13": - version "7.14.3" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.14.3.tgz#149aa6d78c016e318c43e2409a0ae9c136a86688" - integrity sha512-JIB2+XJrb7v3zceV2XzDhGIB902CmKGSpSl4q2C6agU9SNLG/2V1RtFRGPG1Ajh9STj3+q6zJMOC+N/pp2P9DA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.12.13" - regexpu-core "^4.7.1" - -"@babel/helper-define-polyfill-provider@^0.2.1": - version "0.2.1" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.1.tgz#e6f5f4a6edc3722152c21359190de67fc6cf664d" - integrity sha512-x3AUTVZNPunaw1opRTa5OwVA5N0YxGlIad9xQ5QflK1uIS7PnAGGU5O2Dj/G183fR//N8AzTq+Q8+oiu9m0VFg== - dependencies: - "@babel/helper-compilation-targets" "^7.13.0" - "@babel/helper-module-imports" "^7.12.13" - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/traverse" "^7.13.0" - debug "^4.1.1" - lodash.debounce "^4.0.8" - resolve "^1.14.2" - semver "^6.1.2" - -"@babel/helper-explode-assignable-expression@^7.12.13": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.13.0.tgz#17b5c59ff473d9f956f40ef570cf3a76ca12657f" - integrity sha512-qS0peLTDP8kOisG1blKbaoBg/o9OSa1qoumMjTK5pM+KDTtpxpsiubnCGP34vK8BXGcb2M9eigwgvoJryrzwWA== - dependencies: - "@babel/types" "^7.13.0" - -"@babel/helper-function-name@^7.12.13", "@babel/helper-function-name@^7.14.2": - version "7.14.2" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.14.2.tgz#397688b590760b6ef7725b5f0860c82427ebaac2" - integrity sha512-NYZlkZRydxw+YT56IlhIcS8PAhb+FEUiOzuhFTfqDyPmzAhRge6ua0dQYT/Uh0t/EDHq05/i+e5M2d4XvjgarQ== - dependencies: - "@babel/helper-get-function-arity" "^7.12.13" - "@babel/template" "^7.12.13" - "@babel/types" "^7.14.2" - -"@babel/helper-get-function-arity@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz#bc63451d403a3b3082b97e1d8b3fe5bd4091e583" - integrity sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg== - dependencies: - "@babel/types" "^7.12.13" - -"@babel/helper-hoist-variables@^7.13.0": - version "7.13.16" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.13.16.tgz#1b1651249e94b51f8f0d33439843e33e39775b30" - integrity sha512-1eMtTrXtrwscjcAeO4BVK+vvkxaLJSPFz1w1KLawz6HLNi9bPFGBNwwDyVfiu1Tv/vRRFYfoGaKhmAQPGPn5Wg== - dependencies: - "@babel/traverse" "^7.13.15" - "@babel/types" "^7.13.16" - -"@babel/helper-member-expression-to-functions@^7.13.12": - version "7.13.12" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.12.tgz#dfe368f26d426a07299d8d6513821768216e6d72" - integrity sha512-48ql1CLL59aKbU94Y88Xgb2VFy7a95ykGRbJJaaVv+LX5U8wFpLfiGXJJGUozsmA1oEh/o5Bp60Voq7ACyA/Sw== - dependencies: - "@babel/types" "^7.13.12" - -"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.12.1", "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.13.12": - version "7.13.12" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.13.12.tgz#c6a369a6f3621cb25da014078684da9196b61977" - integrity sha512-4cVvR2/1B693IuOvSI20xqqa/+bl7lqAMR59R4iu39R9aOX8/JoYY1sFaNvUMyMBGnHdwvJgUrzNLoUZxXypxA== - dependencies: - "@babel/types" "^7.13.12" - -"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.13.0", "@babel/helper-module-transforms@^7.14.0", "@babel/helper-module-transforms@^7.14.2": - version "7.14.2" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.14.2.tgz#ac1cc30ee47b945e3e0c4db12fa0c5389509dfe5" - integrity sha512-OznJUda/soKXv0XhpvzGWDnml4Qnwp16GN+D/kZIdLsWoHj05kyu8Rm5kXmMef+rVJZ0+4pSGLkeixdqNUATDA== - dependencies: - "@babel/helper-module-imports" "^7.13.12" - "@babel/helper-replace-supers" "^7.13.12" - "@babel/helper-simple-access" "^7.13.12" - "@babel/helper-split-export-declaration" "^7.12.13" - "@babel/helper-validator-identifier" "^7.14.0" - "@babel/template" "^7.12.13" - "@babel/traverse" "^7.14.2" - "@babel/types" "^7.14.2" - -"@babel/helper-optimise-call-expression@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.13.tgz#5c02d171b4c8615b1e7163f888c1c81c30a2aaea" - integrity sha512-BdWQhoVJkp6nVjB7nkFWcn43dkprYauqtk++Py2eaf/GRDFm5BxRqEIZCiHlZUGAVmtwKcsVL1dC68WmzeFmiA== - dependencies: - "@babel/types" "^7.12.13" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz#806526ce125aed03373bc416a828321e3a6a33af" - integrity sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ== - -"@babel/helper-remap-async-to-generator@^7.13.0": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.13.0.tgz#376a760d9f7b4b2077a9dd05aa9c3927cadb2209" - integrity sha512-pUQpFBE9JvC9lrQbpX0TmeNIy5s7GnZjna2lhhcHC7DzgBs6fWn722Y5cfwgrtrqc7NAJwMvOa0mKhq6XaE4jg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.12.13" - "@babel/helper-wrap-function" "^7.13.0" - "@babel/types" "^7.13.0" - -"@babel/helper-replace-supers@^7.12.13", "@babel/helper-replace-supers@^7.13.12", "@babel/helper-replace-supers@^7.14.3": - version "7.14.3" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.14.3.tgz#ca17b318b859d107f0e9b722d58cf12d94436600" - integrity sha512-Rlh8qEWZSTfdz+tgNV/N4gz1a0TMNwCUcENhMjHTHKp3LseYH5Jha0NSlyTQWMnjbYcwFt+bqAMqSLHVXkQ6UA== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.13.12" - "@babel/helper-optimise-call-expression" "^7.12.13" - "@babel/traverse" "^7.14.2" - "@babel/types" "^7.14.2" - -"@babel/helper-simple-access@^7.13.12": - version "7.13.12" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.13.12.tgz#dd6c538afb61819d205a012c31792a39c7a5eaf6" - integrity sha512-7FEjbrx5SL9cWvXioDbnlYTppcZGuCY6ow3/D5vMggb2Ywgu4dMrpTJX0JdQAIcRRUElOIxF3yEooa9gUb9ZbA== - dependencies: - "@babel/types" "^7.13.12" - -"@babel/helper-skip-transparent-expression-wrappers@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz#462dc63a7e435ade8468385c63d2b84cce4b3cbf" - integrity sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA== - dependencies: - "@babel/types" "^7.12.1" - -"@babel/helper-split-export-declaration@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz#e9430be00baf3e88b0e13e6f9d4eaf2136372b05" - integrity sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg== - dependencies: - "@babel/types" "^7.12.13" - -"@babel/helper-validator-identifier@^7.12.11", "@babel/helper-validator-identifier@^7.14.0": - version "7.14.0" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz#d26cad8a47c65286b15df1547319a5d0bcf27288" - integrity sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A== - -"@babel/helper-validator-option@^7.12.1", "@babel/helper-validator-option@^7.12.17": - version "7.12.17" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz#d1fbf012e1a79b7eebbfdc6d270baaf8d9eb9831" - integrity sha512-TopkMDmLzq8ngChwRlyjR6raKD6gMSae4JdYDB8bByKreQgG0RBTuKe9LRxW3wFtUnjxOPRKBDwEH6Mg5KeDfw== - -"@babel/helper-wrap-function@^7.13.0": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.13.0.tgz#bdb5c66fda8526ec235ab894ad53a1235c79fcc4" - integrity sha512-1UX9F7K3BS42fI6qd2A4BjKzgGjToscyZTdp1DjknHLCIvpgne6918io+aL5LXFcER/8QWiwpoY902pVEqgTXA== - dependencies: - "@babel/helper-function-name" "^7.12.13" - "@babel/template" "^7.12.13" - "@babel/traverse" "^7.13.0" - "@babel/types" "^7.13.0" - -"@babel/helpers@^7.12.1", "@babel/helpers@^7.14.0": - version "7.14.0" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.14.0.tgz#ea9b6be9478a13d6f961dbb5f36bf75e2f3b8f62" - integrity sha512-+ufuXprtQ1D1iZTO/K9+EBRn+qPWMJjZSw/S0KlFrxCw4tkrzv9grgpDHkY9MeQTjTY8i2sp7Jep8DfU6tN9Mg== - dependencies: - "@babel/template" "^7.12.13" - "@babel/traverse" "^7.14.0" - "@babel/types" "^7.14.0" - -"@babel/highlight@^7.10.4", "@babel/highlight@^7.12.13": - version "7.14.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.0.tgz#3197e375711ef6bf834e67d0daec88e4f46113cf" - integrity sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg== - dependencies: - "@babel/helper-validator-identifier" "^7.14.0" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/parser@^7.1.0", "@babel/parser@^7.12.13", "@babel/parser@^7.12.3", "@babel/parser@^7.14.2", "@babel/parser@^7.14.3", "@babel/parser@^7.7.0": - version "7.14.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.14.3.tgz#9b530eecb071fd0c93519df25c5ff9f14759f298" - integrity sha512-7MpZDIfI7sUC5zWo2+foJ50CSI5lcqDehZ0lVgIhSi4bFEk94fLAKlF3Q0nzSQQ+ca0lm+O6G9ztKVBeu8PMRQ== - -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.13.12": - version "7.13.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.13.12.tgz#a3484d84d0b549f3fc916b99ee4783f26fabad2a" - integrity sha512-d0u3zWKcoZf379fOeJdr1a5WPDny4aOFZ6hlfKivgK0LY7ZxNfoaHL2fWwdGtHyVvra38FC+HVYkO+byfSA8AQ== - dependencies: - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" - "@babel/plugin-proposal-optional-chaining" "^7.13.12" - -"@babel/plugin-proposal-async-generator-functions@^7.12.1", "@babel/plugin-proposal-async-generator-functions@^7.14.2": - version "7.14.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.2.tgz#3a2085abbf5d5f962d480dbc81347385ed62eb1e" - integrity sha512-b1AM4F6fwck4N8ItZ/AtC4FP/cqZqmKRQ4FaTDutwSYyjuhtvsGEMLK4N/ztV/ImP40BjIDyMgBQAeAMsQYVFQ== - dependencies: - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/helper-remap-async-to-generator" "^7.13.0" - "@babel/plugin-syntax-async-generators" "^7.8.4" - -"@babel/plugin-proposal-class-properties@7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz#a082ff541f2a29a4821065b8add9346c0c16e5de" - integrity sha512-cKp3dlQsFsEs5CWKnN7BnSHOd0EOW8EKpEjkoz1pO2E5KzIDNV9Ros1b0CnmbVgAGXJubOYVBOGCT1OmJwOI7w== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.12.1" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-proposal-class-properties@^7.12.1", "@babel/plugin-proposal-class-properties@^7.13.0": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.13.0.tgz#146376000b94efd001e57a40a88a525afaab9f37" - integrity sha512-KnTDjFNC1g+45ka0myZNvSBFLhNCLN+GeGYLDEA8Oq7MZ6yMgfLoIRh86GRT0FjtJhZw8JyUskP9uvj5pHM9Zg== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.13.0" - "@babel/helper-plugin-utils" "^7.13.0" - -"@babel/plugin-proposal-class-static-block@^7.13.11": - version "7.14.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.14.3.tgz#5a527e2cae4a4753119c3a3e7f64ecae8ccf1360" - integrity sha512-HEjzp5q+lWSjAgJtSluFDrGGosmwTgKwCXdDQZvhKsRlwv3YdkUEqxNrrjesJd+B9E9zvr1PVPVBvhYZ9msjvQ== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.14.3" - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/plugin-syntax-class-static-block" "^7.12.13" - -"@babel/plugin-proposal-decorators@7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.12.1.tgz#59271439fed4145456c41067450543aee332d15f" - integrity sha512-knNIuusychgYN8fGJHONL0RbFxLGawhXOJNLBk75TniTsZZeA+wdkDuv6wp4lGwzQEKjZi6/WYtnb3udNPmQmQ== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.12.1" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-decorators" "^7.12.1" - -"@babel/plugin-proposal-dynamic-import@^7.12.1", "@babel/plugin-proposal-dynamic-import@^7.14.2": - version "7.14.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.14.2.tgz#01ebabd7c381cff231fa43e302939a9de5be9d9f" - integrity sha512-oxVQZIWFh91vuNEMKltqNsKLFWkOIyJc95k2Gv9lWVyDfPUQGSSlbDEgWuJUU1afGE9WwlzpucMZ3yDRHIItkA== - dependencies: - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - -"@babel/plugin-proposal-export-namespace-from@^7.12.1", "@babel/plugin-proposal-export-namespace-from@^7.14.2": - version "7.14.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.14.2.tgz#62542f94aa9ce8f6dba79eec698af22112253791" - integrity sha512-sRxW3z3Zp3pFfLAgVEvzTFutTXax837oOatUIvSG9o5gRj9mKwm3br1Se5f4QalTQs9x4AzlA/HrCWbQIHASUQ== - dependencies: - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - -"@babel/plugin-proposal-json-strings@^7.12.1", "@babel/plugin-proposal-json-strings@^7.14.2": - version "7.14.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.14.2.tgz#830b4e2426a782e8b2878fbfe2cba85b70cbf98c" - integrity sha512-w2DtsfXBBJddJacXMBhElGEYqCZQqN99Se1qeYn8DVLB33owlrlLftIbMzn5nz1OITfDVknXF433tBrLEAOEjA== - dependencies: - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/plugin-syntax-json-strings" "^7.8.3" - -"@babel/plugin-proposal-logical-assignment-operators@^7.12.1", "@babel/plugin-proposal-logical-assignment-operators@^7.14.2": - version "7.14.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.14.2.tgz#222348c080a1678e0e74ea63fe76f275882d1fd7" - integrity sha512-1JAZtUrqYyGsS7IDmFeaem+/LJqujfLZ2weLR9ugB0ufUPjzf8cguyVT1g5im7f7RXxuLq1xUxEzvm68uYRtGg== - dependencies: - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - -"@babel/plugin-proposal-nullish-coalescing-operator@7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.1.tgz#3ed4fff31c015e7f3f1467f190dbe545cd7b046c" - integrity sha512-nZY0ESiaQDI1y96+jk6VxMOaL4LPo/QDHBqL+SF3/vl6dHkTwHlOI8L4ZwuRBHgakRBw5zsVylel7QPbbGuYgg== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" - -"@babel/plugin-proposal-nullish-coalescing-operator@^7.12.1", "@babel/plugin-proposal-nullish-coalescing-operator@^7.14.2": - version "7.14.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.14.2.tgz#425b11dc62fc26939a2ab42cbba680bdf5734546" - integrity sha512-ebR0zU9OvI2N4qiAC38KIAK75KItpIPTpAtd2r4OZmMFeKbKJpUFLYP2EuDut82+BmYi8sz42B+TfTptJ9iG5Q== - dependencies: - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - -"@babel/plugin-proposal-numeric-separator@7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.1.tgz#0e2c6774c4ce48be412119b4d693ac777f7685a6" - integrity sha512-MR7Ok+Af3OhNTCxYVjJZHS0t97ydnJZt/DbR4WISO39iDnhiD8XHrY12xuSJ90FFEGjir0Fzyyn7g/zY6hxbxA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - -"@babel/plugin-proposal-numeric-separator@^7.12.1", "@babel/plugin-proposal-numeric-separator@^7.14.2": - version "7.14.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.14.2.tgz#82b4cc06571143faf50626104b335dd71baa4f9e" - integrity sha512-DcTQY9syxu9BpU3Uo94fjCB3LN9/hgPS8oUL7KrSW3bA2ePrKZZPJcc5y0hoJAM9dft3pGfErtEUvxXQcfLxUg== - dependencies: - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - -"@babel/plugin-proposal-object-rest-spread@^7.12.1", "@babel/plugin-proposal-object-rest-spread@^7.14.2": - version "7.14.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.2.tgz#e17d418f81cc103fedd4ce037e181c8056225abc" - integrity sha512-hBIQFxwZi8GIp934+nj5uV31mqclC1aYDhctDu5khTi9PCCUOczyy0b34W0oE9U/eJXiqQaKyVsmjeagOaSlbw== - dependencies: - "@babel/compat-data" "^7.14.0" - "@babel/helper-compilation-targets" "^7.13.16" - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.14.2" - -"@babel/plugin-proposal-optional-catch-binding@^7.12.1", "@babel/plugin-proposal-optional-catch-binding@^7.14.2": - version "7.14.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.2.tgz#150d4e58e525b16a9a1431bd5326c4eed870d717" - integrity sha512-XtkJsmJtBaUbOxZsNk0Fvrv8eiqgneug0A6aqLFZ4TSkar2L5dSXWcnUKHgmjJt49pyB/6ZHvkr3dPgl9MOWRQ== - dependencies: - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - -"@babel/plugin-proposal-optional-chaining@7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.1.tgz#cce122203fc8a32794296fc377c6dedaf4363797" - integrity sha512-c2uRpY6WzaVDzynVY9liyykS+kVU+WRZPMPYpkelXH8KBt1oXoI89kPbZKKG/jDT5UK92FTW2fZkZaJhdiBabw== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" - "@babel/plugin-syntax-optional-chaining" "^7.8.0" - -"@babel/plugin-proposal-optional-chaining@^7.12.1", "@babel/plugin-proposal-optional-chaining@^7.13.12", "@babel/plugin-proposal-optional-chaining@^7.14.2": - version "7.14.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.2.tgz#df8171a8b9c43ebf4c1dabe6311b432d83e1b34e" - integrity sha512-qQByMRPwMZJainfig10BoaDldx/+VDtNcrA7qdNaEOAj6VXud+gfrkA8j4CRAU5HjnWREXqIpSpH30qZX1xivA== - dependencies: - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - -"@babel/plugin-proposal-private-methods@^7.12.1", "@babel/plugin-proposal-private-methods@^7.13.0": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.13.0.tgz#04bd4c6d40f6e6bbfa2f57e2d8094bad900ef787" - integrity sha512-MXyyKQd9inhx1kDYPkFRVOBXQ20ES8Pto3T7UZ92xj2mY0EVD8oAVzeyYuVfy/mxAdTSIayOvg+aVzcHV2bn6Q== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.13.0" - "@babel/helper-plugin-utils" "^7.13.0" - -"@babel/plugin-proposal-private-property-in-object@^7.14.0": - version "7.14.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.14.0.tgz#b1a1f2030586b9d3489cc26179d2eb5883277636" - integrity sha512-59ANdmEwwRUkLjB7CRtwJxxwtjESw+X2IePItA+RGQh+oy5RmpCh/EvVVvh5XQc3yxsm5gtv0+i9oBZhaDNVTg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.12.13" - "@babel/helper-create-class-features-plugin" "^7.14.0" - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/plugin-syntax-private-property-in-object" "^7.14.0" - -"@babel/plugin-proposal-unicode-property-regex@^7.12.1", "@babel/plugin-proposal-unicode-property-regex@^7.12.13", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.13.tgz#bebde51339be829c17aaaaced18641deb62b39ba" - integrity sha512-XyJmZidNfofEkqFV5VC/bLabGmO5QzenPO/YOfGuEbgU+2sSwMmio3YLb4WtBgcmmdwZHyVyv8on77IUjQ5Gvg== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-syntax-async-generators@^7.8.0", "@babel/plugin-syntax-async-generators@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" - integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-bigint@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" - integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-class-properties@^7.12.1", "@babel/plugin-syntax-class-properties@^7.12.13", "@babel/plugin-syntax-class-properties@^7.8.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" - integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-syntax-class-static-block@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.12.13.tgz#8e3d674b0613e67975ceac2776c97b60cafc5c9c" - integrity sha512-ZmKQ0ZXR0nYpHZIIuj9zE7oIqCx2hw9TKi+lIo73NNrMPAZGHfS92/VRV0ZmPj6H2ffBgyFHXvJ5NYsNeEaP2A== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-syntax-decorators@^7.12.1": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.12.13.tgz#fac829bf3c7ef4a1bc916257b403e58c6bdaf648" - integrity sha512-Rw6aIXGuqDLr6/LoBBYE57nKOzQpz/aDkKlMqEwH+Vp0MXbG6H/TfRjaY343LKxzAKAMXIHsQ8JzaZKuDZ9MwA== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-syntax-dynamic-import@^7.8.0", "@babel/plugin-syntax-dynamic-import@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" - integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-export-namespace-from@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" - integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-syntax-flow@^7.12.1": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.12.13.tgz#5df9962503c0a9c918381c929d51d4d6949e7e86" - integrity sha512-J/RYxnlSLXZLVR7wTRsozxKT8qbsx1mNKJzXEEjQ0Kjx1ZACcyHgbanNWNCFtc36IzuWhYWPpvJFFoexoOWFmA== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-syntax-import-meta@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" - integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-json-strings@^7.8.0", "@babel/plugin-syntax-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" - integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-jsx@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.13.tgz#044fb81ebad6698fe62c478875575bcbb9b70f15" - integrity sha512-d4HM23Q1K7oq/SLNmG6mRt85l2csmQ0cHRaxRXjKW0YFdEXqlZ5kzFQKH5Uc3rDJECgu+yCRgPkG04Mm98R/1g== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" - integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0", "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" - integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-numeric-separator@^7.10.4", "@babel/plugin-syntax-numeric-separator@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" - integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-object-rest-spread@^7.8.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" - integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-catch-binding@^7.8.0", "@babel/plugin-syntax-optional-catch-binding@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" - integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-chaining@^7.8.0", "@babel/plugin-syntax-optional-chaining@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" - integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-private-property-in-object@^7.14.0": - version "7.14.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.0.tgz#762a4babec61176fec6c88480dec40372b140c0b" - integrity sha512-bda3xF8wGl5/5btF794utNOL0Jw+9jE5C1sLZcoK7c4uonE/y3iQiyG+KbkF3WBV/paX58VCpjhxLPkdj5Fe4w== - dependencies: - "@babel/helper-plugin-utils" "^7.13.0" - -"@babel/plugin-syntax-top-level-await@^7.12.1", "@babel/plugin-syntax-top-level-await@^7.12.13", "@babel/plugin-syntax-top-level-await@^7.8.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.13.tgz#c5f0fa6e249f5b739727f923540cf7a806130178" - integrity sha512-A81F9pDwyS7yM//KwbCSDqy3Uj4NMIurtplxphWxoYtNPov7cJsDkAFNNyVlIZ3jwGycVsurZ+LtOA8gZ376iQ== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-syntax-typescript@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.12.13.tgz#9dff111ca64154cef0f4dc52cf843d9f12ce4474" - integrity sha512-cHP3u1JiUiG2LFDKbXnwVad81GvfyIOmCD6HIEId6ojrY0Drfy2q1jw7BwN7dE84+kTnBjLkXoL3IEy/3JPu2w== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-arrow-functions@^7.12.1", "@babel/plugin-transform-arrow-functions@^7.13.0": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.13.0.tgz#10a59bebad52d637a027afa692e8d5ceff5e3dae" - integrity sha512-96lgJagobeVmazXFaDrbmCLQxBysKu7U6Do3mLsx27gf5Dk85ezysrs2BZUpXD703U/Su1xTBDxxar2oa4jAGg== - dependencies: - "@babel/helper-plugin-utils" "^7.13.0" - -"@babel/plugin-transform-async-to-generator@^7.12.1", "@babel/plugin-transform-async-to-generator@^7.13.0": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.13.0.tgz#8e112bf6771b82bf1e974e5e26806c5c99aa516f" - integrity sha512-3j6E004Dx0K3eGmhxVJxwwI89CTJrce7lg3UrtFuDAVQ/2+SJ/h/aSFOeE6/n0WB1GsOffsJp6MnPQNQ8nmwhg== - dependencies: - "@babel/helper-module-imports" "^7.12.13" - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/helper-remap-async-to-generator" "^7.13.0" - -"@babel/plugin-transform-block-scoped-functions@^7.12.1", "@babel/plugin-transform-block-scoped-functions@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.13.tgz#a9bf1836f2a39b4eb6cf09967739de29ea4bf4c4" - integrity sha512-zNyFqbc3kI/fVpqwfqkg6RvBgFpC4J18aKKMmv7KdQ/1GgREapSJAykLMVNwfRGO3BtHj3YQZl8kxCXPcVMVeg== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-block-scoping@^7.12.1", "@babel/plugin-transform-block-scoping@^7.14.2": - version "7.14.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.14.2.tgz#761cb12ab5a88d640ad4af4aa81f820e6b5fdf5c" - integrity sha512-neZZcP19NugZZqNwMTH+KoBjx5WyvESPSIOQb4JHpfd+zPfqcH65RMu5xJju5+6q/Y2VzYrleQTr+b6METyyxg== - dependencies: - "@babel/helper-plugin-utils" "^7.13.0" - -"@babel/plugin-transform-classes@^7.12.1", "@babel/plugin-transform-classes@^7.14.2": - version "7.14.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.2.tgz#3f1196c5709f064c252ad056207d87b7aeb2d03d" - integrity sha512-7oafAVcucHquA/VZCsXv/gmuiHeYd64UJyyTYU+MPfNu0KeNlxw06IeENBO8bJjXVbolu+j1MM5aKQtH1OMCNg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.12.13" - "@babel/helper-function-name" "^7.14.2" - "@babel/helper-optimise-call-expression" "^7.12.13" - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/helper-replace-supers" "^7.13.12" - "@babel/helper-split-export-declaration" "^7.12.13" - globals "^11.1.0" - -"@babel/plugin-transform-computed-properties@^7.12.1", "@babel/plugin-transform-computed-properties@^7.13.0": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.13.0.tgz#845c6e8b9bb55376b1fa0b92ef0bdc8ea06644ed" - integrity sha512-RRqTYTeZkZAz8WbieLTvKUEUxZlUTdmL5KGMyZj7FnMfLNKV4+r5549aORG/mgojRmFlQMJDUupwAMiF2Q7OUg== - dependencies: - "@babel/helper-plugin-utils" "^7.13.0" - -"@babel/plugin-transform-destructuring@^7.12.1", "@babel/plugin-transform-destructuring@^7.13.17": - version "7.13.17" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.13.17.tgz#678d96576638c19d5b36b332504d3fd6e06dea27" - integrity sha512-UAUqiLv+uRLO+xuBKKMEpC+t7YRNVRqBsWWq1yKXbBZBje/t3IXCiSinZhjn/DC3qzBfICeYd2EFGEbHsh5RLA== - dependencies: - "@babel/helper-plugin-utils" "^7.13.0" - -"@babel/plugin-transform-dotall-regex@^7.12.1", "@babel/plugin-transform-dotall-regex@^7.12.13", "@babel/plugin-transform-dotall-regex@^7.4.4": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.13.tgz#3f1601cc29905bfcb67f53910f197aeafebb25ad" - integrity sha512-foDrozE65ZFdUC2OfgeOCrEPTxdB3yjqxpXh8CH+ipd9CHd4s/iq81kcUpyH8ACGNEPdFqbtzfgzbT/ZGlbDeQ== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-duplicate-keys@^7.12.1", "@babel/plugin-transform-duplicate-keys@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.13.tgz#6f06b87a8b803fd928e54b81c258f0a0033904de" - integrity sha512-NfADJiiHdhLBW3pulJlJI2NB0t4cci4WTZ8FtdIuNc2+8pslXdPtRRAEWqUY+m9kNOk2eRYbTAOipAxlrOcwwQ== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-exponentiation-operator@^7.12.1", "@babel/plugin-transform-exponentiation-operator@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.13.tgz#4d52390b9a273e651e4aba6aee49ef40e80cd0a1" - integrity sha512-fbUelkM1apvqez/yYx1/oICVnGo2KM5s63mhGylrmXUxK/IAXSIf87QIxVfZldWf4QsOafY6vV3bX8aMHSvNrA== - dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-flow-strip-types@7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.12.1.tgz#8430decfa7eb2aea5414ed4a3fa6e1652b7d77c4" - integrity sha512-8hAtkmsQb36yMmEtk2JZ9JnVyDSnDOdlB+0nEGzIDLuK4yR3JcEjfuFPYkdEPSh8Id+rAMeBEn+X0iVEyho6Hg== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-flow" "^7.12.1" - -"@babel/plugin-transform-for-of@^7.12.1", "@babel/plugin-transform-for-of@^7.13.0": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.13.0.tgz#c799f881a8091ac26b54867a845c3e97d2696062" - integrity sha512-IHKT00mwUVYE0zzbkDgNRP6SRzvfGCYsOxIRz8KsiaaHCcT9BWIkO+H9QRJseHBLOGBZkHUdHiqj6r0POsdytg== - dependencies: - "@babel/helper-plugin-utils" "^7.13.0" - -"@babel/plugin-transform-function-name@^7.12.1", "@babel/plugin-transform-function-name@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.13.tgz#bb024452f9aaed861d374c8e7a24252ce3a50051" - integrity sha512-6K7gZycG0cmIwwF7uMK/ZqeCikCGVBdyP2J5SKNCXO5EOHcqi+z7Jwf8AmyDNcBgxET8DrEtCt/mPKPyAzXyqQ== - dependencies: - "@babel/helper-function-name" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-literals@^7.12.1", "@babel/plugin-transform-literals@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.13.tgz#2ca45bafe4a820197cf315794a4d26560fe4bdb9" - integrity sha512-FW+WPjSR7hiUxMcKqyNjP05tQ2kmBCdpEpZHY1ARm96tGQCCBvXKnpjILtDplUnJ/eHZ0lALLM+d2lMFSpYJrQ== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-member-expression-literals@^7.12.1", "@babel/plugin-transform-member-expression-literals@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.13.tgz#5ffa66cd59b9e191314c9f1f803b938e8c081e40" - integrity sha512-kxLkOsg8yir4YeEPHLuO2tXP9R/gTjpuTOjshqSpELUN3ZAg2jfDnKUvzzJxObun38sw3wm4Uu69sX/zA7iRvg== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-modules-amd@^7.12.1", "@babel/plugin-transform-modules-amd@^7.14.2": - version "7.14.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.2.tgz#6622806fe1a7c07a1388444222ef9535f2ca17b0" - integrity sha512-hPC6XBswt8P3G2D1tSV2HzdKvkqOpmbyoy+g73JG0qlF/qx2y3KaMmXb1fLrpmWGLZYA0ojCvaHdzFWjlmV+Pw== - dependencies: - "@babel/helper-module-transforms" "^7.14.2" - "@babel/helper-plugin-utils" "^7.13.0" - babel-plugin-dynamic-import-node "^2.3.3" - -"@babel/plugin-transform-modules-commonjs@^7.12.1", "@babel/plugin-transform-modules-commonjs@^7.14.0": - version "7.14.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.14.0.tgz#52bc199cb581e0992edba0f0f80356467587f161" - integrity sha512-EX4QePlsTaRZQmw9BsoPeyh5OCtRGIhwfLquhxGp5e32w+dyL8htOcDwamlitmNFK6xBZYlygjdye9dbd9rUlQ== - dependencies: - "@babel/helper-module-transforms" "^7.14.0" - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/helper-simple-access" "^7.13.12" - babel-plugin-dynamic-import-node "^2.3.3" - -"@babel/plugin-transform-modules-systemjs@^7.12.1", "@babel/plugin-transform-modules-systemjs@^7.13.8": - version "7.13.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.13.8.tgz#6d066ee2bff3c7b3d60bf28dec169ad993831ae3" - integrity sha512-hwqctPYjhM6cWvVIlOIe27jCIBgHCsdH2xCJVAYQm7V5yTMoilbVMi9f6wKg0rpQAOn6ZG4AOyvCqFF/hUh6+A== - dependencies: - "@babel/helper-hoist-variables" "^7.13.0" - "@babel/helper-module-transforms" "^7.13.0" - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/helper-validator-identifier" "^7.12.11" - babel-plugin-dynamic-import-node "^2.3.3" - -"@babel/plugin-transform-modules-umd@^7.12.1", "@babel/plugin-transform-modules-umd@^7.14.0": - version "7.14.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.0.tgz#2f8179d1bbc9263665ce4a65f305526b2ea8ac34" - integrity sha512-nPZdnWtXXeY7I87UZr9VlsWme3Y0cfFFE41Wbxz4bbaexAjNMInXPFUpRRUJ8NoMm0Cw+zxbqjdPmLhcjfazMw== - dependencies: - "@babel/helper-module-transforms" "^7.14.0" - "@babel/helper-plugin-utils" "^7.13.0" - -"@babel/plugin-transform-named-capturing-groups-regex@^7.12.1", "@babel/plugin-transform-named-capturing-groups-regex@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.13.tgz#2213725a5f5bbbe364b50c3ba5998c9599c5c9d9" - integrity sha512-Xsm8P2hr5hAxyYblrfACXpQKdQbx4m2df9/ZZSQ8MAhsadw06+jW7s9zsSw6he+mJZXRlVMyEnVktJo4zjk1WA== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.12.13" - -"@babel/plugin-transform-new-target@^7.12.1", "@babel/plugin-transform-new-target@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.13.tgz#e22d8c3af24b150dd528cbd6e685e799bf1c351c" - integrity sha512-/KY2hbLxrG5GTQ9zzZSc3xWiOy379pIETEhbtzwZcw9rvuaVV4Fqy7BYGYOWZnaoXIQYbbJ0ziXLa/sKcGCYEQ== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-object-super@^7.12.1", "@babel/plugin-transform-object-super@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.13.tgz#b4416a2d63b8f7be314f3d349bd55a9c1b5171f7" - integrity sha512-JzYIcj3XtYspZDV8j9ulnoMPZZnF/Cj0LUxPOjR89BdBVx+zYJI9MdMIlUZjbXDX+6YVeS6I3e8op+qQ3BYBoQ== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - "@babel/helper-replace-supers" "^7.12.13" - -"@babel/plugin-transform-parameters@^7.12.1", "@babel/plugin-transform-parameters@^7.14.2": - version "7.14.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.14.2.tgz#e4290f72e0e9e831000d066427c4667098decc31" - integrity sha512-NxoVmA3APNCC1JdMXkdYXuQS+EMdqy0vIwyDHeKHiJKRxmp1qGSdb0JLEIoPRhkx6H/8Qi3RJ3uqOCYw8giy9A== - dependencies: - "@babel/helper-plugin-utils" "^7.13.0" - -"@babel/plugin-transform-property-literals@^7.12.1", "@babel/plugin-transform-property-literals@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.13.tgz#4e6a9e37864d8f1b3bc0e2dce7bf8857db8b1a81" - integrity sha512-nqVigwVan+lR+g8Fj8Exl0UQX2kymtjcWfMOYM1vTYEKujeyv2SkMgazf2qNcK7l4SDiKyTA/nHCPqL4e2zo1A== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-react-constant-elements@^7.12.1": - version "7.13.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.13.13.tgz#0208b1d942bf939cd4f7aa5b255d42602aa4a920" - integrity sha512-SNJU53VM/SjQL0bZhyU+f4kJQz7bQQajnrZRSaU21hruG/NWY41AEM9AWXeXX90pYr/C2yAmTgI6yW3LlLrAUQ== - dependencies: - "@babel/helper-plugin-utils" "^7.13.0" - -"@babel/plugin-transform-react-display-name@7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.12.1.tgz#1cbcd0c3b1d6648c55374a22fc9b6b7e5341c00d" - integrity sha512-cAzB+UzBIrekfYxyLlFqf/OagTvHLcVBb5vpouzkYkBclRPraiygVnafvAoipErZLI8ANv8Ecn6E/m5qPXD26w== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-react-display-name@^7.12.1", "@babel/plugin-transform-react-display-name@^7.12.13": - version "7.14.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.14.2.tgz#2e854544d42ab3bb9c21f84e153d62e800fbd593" - integrity sha512-zCubvP+jjahpnFJvPaHPiGVfuVUjXHhFvJKQdNnsmSsiU9kR/rCZ41jHc++tERD2zV+p7Hr6is+t5b6iWTCqSw== - dependencies: - "@babel/helper-plugin-utils" "^7.13.0" - -"@babel/plugin-transform-react-jsx-development@^7.12.1", "@babel/plugin-transform-react-jsx-development@^7.12.17": - version "7.12.17" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.17.tgz#f510c0fa7cd7234153539f9a362ced41a5ca1447" - integrity sha512-BPjYV86SVuOaudFhsJR1zjgxxOhJDt6JHNoD48DxWEIxUCAMjV1ys6DYw4SDYZh0b1QsS2vfIA9t/ZsQGsDOUQ== - dependencies: - "@babel/plugin-transform-react-jsx" "^7.12.17" - -"@babel/plugin-transform-react-jsx-self@^7.12.1": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.12.13.tgz#422d99d122d592acab9c35ea22a6cfd9bf189f60" - integrity sha512-FXYw98TTJ125GVCCkFLZXlZ1qGcsYqNQhVBQcZjyrwf8FEUtVfKIoidnO8S0q+KBQpDYNTmiGo1gn67Vti04lQ== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-react-jsx-source@^7.12.1": - version "7.14.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.14.2.tgz#2620b57e7de775c0687f65d464026d15812941da" - integrity sha512-OMorspVyjxghAjzgeAWc6O7W7vHbJhV69NeTGdl9Mxgz6PaweAuo7ffB9T5A1OQ9dGcw0As4SYMUhyNC4u7mVg== - dependencies: - "@babel/helper-plugin-utils" "^7.13.0" - -"@babel/plugin-transform-react-jsx@^7.12.1", "@babel/plugin-transform-react-jsx@^7.12.17", "@babel/plugin-transform-react-jsx@^7.13.12": - version "7.14.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.14.3.tgz#0e26597805cf0862da735f264550933c38babb66" - integrity sha512-uuxuoUNVhdgYzERiHHFkE4dWoJx+UFVyuAl0aqN8P2/AKFHwqgUC5w2+4/PjpKXJsFgBlYAFXlUmDQ3k3DUkXw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.12.13" - "@babel/helper-module-imports" "^7.13.12" - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/plugin-syntax-jsx" "^7.12.13" - "@babel/types" "^7.14.2" - -"@babel/plugin-transform-react-pure-annotations@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.12.1.tgz#05d46f0ab4d1339ac59adf20a1462c91b37a1a42" - integrity sha512-RqeaHiwZtphSIUZ5I85PEH19LOSzxfuEazoY7/pWASCAIBuATQzpSVD+eT6MebeeZT2F4eSL0u4vw6n4Nm0Mjg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-regenerator@^7.12.1", "@babel/plugin-transform-regenerator@^7.13.15": - version "7.13.15" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.13.15.tgz#e5eb28945bf8b6563e7f818945f966a8d2997f39" - integrity sha512-Bk9cOLSz8DiurcMETZ8E2YtIVJbFCPGW28DJWUakmyVWtQSm6Wsf0p4B4BfEr/eL2Nkhe/CICiUiMOCi1TPhuQ== - dependencies: - regenerator-transform "^0.14.2" - -"@babel/plugin-transform-reserved-words@^7.12.1", "@babel/plugin-transform-reserved-words@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.13.tgz#7d9988d4f06e0fe697ea1d9803188aa18b472695" - integrity sha512-xhUPzDXxZN1QfiOy/I5tyye+TRz6lA7z6xaT4CLOjPRMVg1ldRf0LHw0TDBpYL4vG78556WuHdyO9oi5UmzZBg== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-runtime@7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.1.tgz#04b792057eb460389ff6a4198e377614ea1e7ba5" - integrity sha512-Ac/H6G9FEIkS2tXsZjL4RAdS3L3WHxci0usAnz7laPWUmFiGtj7tIASChqKZMHTSQTQY6xDbOq+V1/vIq3QrWg== - dependencies: - "@babel/helper-module-imports" "^7.12.1" - "@babel/helper-plugin-utils" "^7.10.4" - resolve "^1.8.1" - semver "^5.5.1" - -"@babel/plugin-transform-shorthand-properties@^7.12.1", "@babel/plugin-transform-shorthand-properties@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.13.tgz#db755732b70c539d504c6390d9ce90fe64aff7ad" - integrity sha512-xpL49pqPnLtf0tVluuqvzWIgLEhuPpZzvs2yabUHSKRNlN7ScYU7aMlmavOeyXJZKgZKQRBlh8rHbKiJDraTSw== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-spread@^7.12.1", "@babel/plugin-transform-spread@^7.13.0": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.13.0.tgz#84887710e273c1815ace7ae459f6f42a5d31d5fd" - integrity sha512-V6vkiXijjzYeFmQTr3dBxPtZYLPcUfY34DebOU27jIl2M/Y8Egm52Hw82CSjjPqd54GTlJs5x+CR7HeNr24ckg== - dependencies: - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" - -"@babel/plugin-transform-sticky-regex@^7.12.1", "@babel/plugin-transform-sticky-regex@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.13.tgz#760ffd936face73f860ae646fb86ee82f3d06d1f" - integrity sha512-Jc3JSaaWT8+fr7GRvQP02fKDsYk4K/lYwWq38r/UGfaxo89ajud321NH28KRQ7xy1Ybc0VUE5Pz8psjNNDUglg== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-template-literals@^7.12.1", "@babel/plugin-transform-template-literals@^7.13.0": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.13.0.tgz#a36049127977ad94438dee7443598d1cefdf409d" - integrity sha512-d67umW6nlfmr1iehCcBv69eSUSySk1EsIS8aTDX4Xo9qajAh6mYtcl4kJrBkGXuxZPEgVr7RVfAvNW6YQkd4Mw== - dependencies: - "@babel/helper-plugin-utils" "^7.13.0" - -"@babel/plugin-transform-typeof-symbol@^7.12.1", "@babel/plugin-transform-typeof-symbol@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.13.tgz#785dd67a1f2ea579d9c2be722de8c84cb85f5a7f" - integrity sha512-eKv/LmUJpMnu4npgfvs3LiHhJua5fo/CysENxa45YCQXZwKnGCQKAg87bvoqSW1fFT+HA32l03Qxsm8ouTY3ZQ== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-typescript@^7.12.1": - version "7.14.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.14.3.tgz#44f67f725a60cccee33d9d6fee5e4f338258f34f" - integrity sha512-G5Bb5pY6tJRTC4ag1visSgiDoGgJ1u1fMUgmc2ijLkcIdzP83Q1qyZX4ggFQ/SkR+PNOatkaYC+nKcTlpsX4ag== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.14.3" - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/plugin-syntax-typescript" "^7.12.13" - -"@babel/plugin-transform-unicode-escapes@^7.12.1", "@babel/plugin-transform-unicode-escapes@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.13.tgz#840ced3b816d3b5127dd1d12dcedc5dead1a5e74" - integrity sha512-0bHEkdwJ/sN/ikBHfSmOXPypN/beiGqjo+o4/5K+vxEFNPRPdImhviPakMKG4x96l85emoa0Z6cDflsdBusZbw== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-unicode-regex@^7.12.1", "@babel/plugin-transform-unicode-regex@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.13.tgz#b52521685804e155b1202e83fc188d34bb70f5ac" - integrity sha512-mDRzSNY7/zopwisPZ5kM9XKCfhchqIYwAKRERtEnhYscZB79VRekuRSoYbN0+KVe3y8+q1h6A4svXtP7N+UoCA== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/preset-env@7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.12.1.tgz#9c7e5ca82a19efc865384bb4989148d2ee5d7ac2" - integrity sha512-H8kxXmtPaAGT7TyBvSSkoSTUK6RHh61So05SyEbpmr0MCZrsNYn7mGMzzeYoOUCdHzww61k8XBft2TaES+xPLg== - dependencies: - "@babel/compat-data" "^7.12.1" - "@babel/helper-compilation-targets" "^7.12.1" - "@babel/helper-module-imports" "^7.12.1" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-validator-option" "^7.12.1" - "@babel/plugin-proposal-async-generator-functions" "^7.12.1" - "@babel/plugin-proposal-class-properties" "^7.12.1" - "@babel/plugin-proposal-dynamic-import" "^7.12.1" - "@babel/plugin-proposal-export-namespace-from" "^7.12.1" - "@babel/plugin-proposal-json-strings" "^7.12.1" - "@babel/plugin-proposal-logical-assignment-operators" "^7.12.1" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.12.1" - "@babel/plugin-proposal-numeric-separator" "^7.12.1" - "@babel/plugin-proposal-object-rest-spread" "^7.12.1" - "@babel/plugin-proposal-optional-catch-binding" "^7.12.1" - "@babel/plugin-proposal-optional-chaining" "^7.12.1" - "@babel/plugin-proposal-private-methods" "^7.12.1" - "@babel/plugin-proposal-unicode-property-regex" "^7.12.1" - "@babel/plugin-syntax-async-generators" "^7.8.0" - "@babel/plugin-syntax-class-properties" "^7.12.1" - "@babel/plugin-syntax-dynamic-import" "^7.8.0" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - "@babel/plugin-syntax-json-strings" "^7.8.0" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" - "@babel/plugin-syntax-optional-chaining" "^7.8.0" - "@babel/plugin-syntax-top-level-await" "^7.12.1" - "@babel/plugin-transform-arrow-functions" "^7.12.1" - "@babel/plugin-transform-async-to-generator" "^7.12.1" - "@babel/plugin-transform-block-scoped-functions" "^7.12.1" - "@babel/plugin-transform-block-scoping" "^7.12.1" - "@babel/plugin-transform-classes" "^7.12.1" - "@babel/plugin-transform-computed-properties" "^7.12.1" - "@babel/plugin-transform-destructuring" "^7.12.1" - "@babel/plugin-transform-dotall-regex" "^7.12.1" - "@babel/plugin-transform-duplicate-keys" "^7.12.1" - "@babel/plugin-transform-exponentiation-operator" "^7.12.1" - "@babel/plugin-transform-for-of" "^7.12.1" - "@babel/plugin-transform-function-name" "^7.12.1" - "@babel/plugin-transform-literals" "^7.12.1" - "@babel/plugin-transform-member-expression-literals" "^7.12.1" - "@babel/plugin-transform-modules-amd" "^7.12.1" - "@babel/plugin-transform-modules-commonjs" "^7.12.1" - "@babel/plugin-transform-modules-systemjs" "^7.12.1" - "@babel/plugin-transform-modules-umd" "^7.12.1" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.12.1" - "@babel/plugin-transform-new-target" "^7.12.1" - "@babel/plugin-transform-object-super" "^7.12.1" - "@babel/plugin-transform-parameters" "^7.12.1" - "@babel/plugin-transform-property-literals" "^7.12.1" - "@babel/plugin-transform-regenerator" "^7.12.1" - "@babel/plugin-transform-reserved-words" "^7.12.1" - "@babel/plugin-transform-shorthand-properties" "^7.12.1" - "@babel/plugin-transform-spread" "^7.12.1" - "@babel/plugin-transform-sticky-regex" "^7.12.1" - "@babel/plugin-transform-template-literals" "^7.12.1" - "@babel/plugin-transform-typeof-symbol" "^7.12.1" - "@babel/plugin-transform-unicode-escapes" "^7.12.1" - "@babel/plugin-transform-unicode-regex" "^7.12.1" - "@babel/preset-modules" "^0.1.3" - "@babel/types" "^7.12.1" - core-js-compat "^3.6.2" - semver "^5.5.0" - -"@babel/preset-env@^7.12.1", "@babel/preset-env@^7.8.4": - version "7.14.2" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.14.2.tgz#e80612965da73579c84ad2f963c2359c71524ed5" - integrity sha512-7dD7lVT8GMrE73v4lvDEb85cgcQhdES91BSD7jS/xjC6QY8PnRhux35ac+GCpbiRhp8crexBvZZqnaL6VrY8TQ== - dependencies: - "@babel/compat-data" "^7.14.0" - "@babel/helper-compilation-targets" "^7.13.16" - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/helper-validator-option" "^7.12.17" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.13.12" - "@babel/plugin-proposal-async-generator-functions" "^7.14.2" - "@babel/plugin-proposal-class-properties" "^7.13.0" - "@babel/plugin-proposal-class-static-block" "^7.13.11" - "@babel/plugin-proposal-dynamic-import" "^7.14.2" - "@babel/plugin-proposal-export-namespace-from" "^7.14.2" - "@babel/plugin-proposal-json-strings" "^7.14.2" - "@babel/plugin-proposal-logical-assignment-operators" "^7.14.2" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.14.2" - "@babel/plugin-proposal-numeric-separator" "^7.14.2" - "@babel/plugin-proposal-object-rest-spread" "^7.14.2" - "@babel/plugin-proposal-optional-catch-binding" "^7.14.2" - "@babel/plugin-proposal-optional-chaining" "^7.14.2" - "@babel/plugin-proposal-private-methods" "^7.13.0" - "@babel/plugin-proposal-private-property-in-object" "^7.14.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.12.13" - "@babel/plugin-syntax-async-generators" "^7.8.4" - "@babel/plugin-syntax-class-properties" "^7.12.13" - "@babel/plugin-syntax-class-static-block" "^7.12.13" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-private-property-in-object" "^7.14.0" - "@babel/plugin-syntax-top-level-await" "^7.12.13" - "@babel/plugin-transform-arrow-functions" "^7.13.0" - "@babel/plugin-transform-async-to-generator" "^7.13.0" - "@babel/plugin-transform-block-scoped-functions" "^7.12.13" - "@babel/plugin-transform-block-scoping" "^7.14.2" - "@babel/plugin-transform-classes" "^7.14.2" - "@babel/plugin-transform-computed-properties" "^7.13.0" - "@babel/plugin-transform-destructuring" "^7.13.17" - "@babel/plugin-transform-dotall-regex" "^7.12.13" - "@babel/plugin-transform-duplicate-keys" "^7.12.13" - "@babel/plugin-transform-exponentiation-operator" "^7.12.13" - "@babel/plugin-transform-for-of" "^7.13.0" - "@babel/plugin-transform-function-name" "^7.12.13" - "@babel/plugin-transform-literals" "^7.12.13" - "@babel/plugin-transform-member-expression-literals" "^7.12.13" - "@babel/plugin-transform-modules-amd" "^7.14.2" - "@babel/plugin-transform-modules-commonjs" "^7.14.0" - "@babel/plugin-transform-modules-systemjs" "^7.13.8" - "@babel/plugin-transform-modules-umd" "^7.14.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.12.13" - "@babel/plugin-transform-new-target" "^7.12.13" - "@babel/plugin-transform-object-super" "^7.12.13" - "@babel/plugin-transform-parameters" "^7.14.2" - "@babel/plugin-transform-property-literals" "^7.12.13" - "@babel/plugin-transform-regenerator" "^7.13.15" - "@babel/plugin-transform-reserved-words" "^7.12.13" - "@babel/plugin-transform-shorthand-properties" "^7.12.13" - "@babel/plugin-transform-spread" "^7.13.0" - "@babel/plugin-transform-sticky-regex" "^7.12.13" - "@babel/plugin-transform-template-literals" "^7.13.0" - "@babel/plugin-transform-typeof-symbol" "^7.12.13" - "@babel/plugin-transform-unicode-escapes" "^7.12.13" - "@babel/plugin-transform-unicode-regex" "^7.12.13" - "@babel/preset-modules" "^0.1.4" - "@babel/types" "^7.14.2" - babel-plugin-polyfill-corejs2 "^0.2.0" - babel-plugin-polyfill-corejs3 "^0.2.0" - babel-plugin-polyfill-regenerator "^0.2.0" - core-js-compat "^3.9.0" - semver "^6.3.0" - -"@babel/preset-modules@^0.1.3", "@babel/preset-modules@^0.1.4": - version "0.1.4" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.4.tgz#362f2b68c662842970fdb5e254ffc8fc1c2e415e" - integrity sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" - "@babel/plugin-transform-dotall-regex" "^7.4.4" - "@babel/types" "^7.4.4" - esutils "^2.0.2" - -"@babel/preset-react@7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.12.1.tgz#7f022b13f55b6dd82f00f16d1c599ae62985358c" - integrity sha512-euCExymHCi0qB9u5fKw7rvlw7AZSjw/NaB9h7EkdTt5+yHRrXdiRTh7fkG3uBPpJg82CqLfp1LHLqWGSCrab+g== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-transform-react-display-name" "^7.12.1" - "@babel/plugin-transform-react-jsx" "^7.12.1" - "@babel/plugin-transform-react-jsx-development" "^7.12.1" - "@babel/plugin-transform-react-jsx-self" "^7.12.1" - "@babel/plugin-transform-react-jsx-source" "^7.12.1" - "@babel/plugin-transform-react-pure-annotations" "^7.12.1" - -"@babel/preset-react@^7.12.5": - version "7.13.13" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.13.13.tgz#fa6895a96c50763fe693f9148568458d5a839761" - integrity sha512-gx+tDLIE06sRjKJkVtpZ/t3mzCDOnPG+ggHZG9lffUbX8+wC739x20YQc9V35Do6ZAxaUc/HhVHIiOzz5MvDmA== - dependencies: - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/helper-validator-option" "^7.12.17" - "@babel/plugin-transform-react-display-name" "^7.12.13" - "@babel/plugin-transform-react-jsx" "^7.13.12" - "@babel/plugin-transform-react-jsx-development" "^7.12.17" - "@babel/plugin-transform-react-pure-annotations" "^7.12.1" - -"@babel/preset-typescript@7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.12.1.tgz#86480b483bb97f75036e8864fe404cc782cc311b" - integrity sha512-hNK/DhmoJPsksdHuI/RVrcEws7GN5eamhi28JkO52MqIxU8Z0QpmiSOQxZHWOHV7I3P4UjHV97ay4TcamMA6Kw== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-transform-typescript" "^7.12.1" - -"@babel/runtime-corejs3@^7.10.2": - version "7.14.0" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.14.0.tgz#6bf5fbc0b961f8e3202888cb2cd0fb7a0a9a3f66" - integrity sha512-0R0HTZWHLk6G8jIk0FtoX+AatCtKnswS98VhXwGImFc759PJRp4Tru0PQYZofyijTFUr+gT8Mu7sgXVJLQ0ceg== - dependencies: - core-js-pure "^3.0.0" - regenerator-runtime "^0.13.4" - -"@babel/runtime@7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.1.tgz#b4116a6b6711d010b2dad3b7b6e43bf1b9954740" - integrity sha512-J5AIf3vPj3UwXaAzb5j1xM4WAQDX3EMgemF8rjCP3SoW09LfRKAXQKt6CoVYl230P6iWdRcBbnLDDdnqWxZSCA== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.8", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": - version "7.14.0" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.0.tgz#46794bc20b612c5f75e62dd071e24dfd95f1cbe6" - integrity sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/template@^7.10.4", "@babel/template@^7.12.13", "@babel/template@^7.3.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.13.tgz#530265be8a2589dbb37523844c5bcb55947fb327" - integrity sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA== - dependencies: - "@babel/code-frame" "^7.12.13" - "@babel/parser" "^7.12.13" - "@babel/types" "^7.12.13" - -"@babel/traverse@^7.1.0", "@babel/traverse@^7.12.1", "@babel/traverse@^7.13.0", "@babel/traverse@^7.13.15", "@babel/traverse@^7.14.0", "@babel/traverse@^7.14.2", "@babel/traverse@^7.7.0": - version "7.14.2" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.14.2.tgz#9201a8d912723a831c2679c7ebbf2fe1416d765b" - integrity sha512-TsdRgvBFHMyHOOzcP9S6QU0QQtjxlRpEYOy3mcCO5RgmC305ki42aSAmfZEMSSYBla2oZ9BMqYlncBaKmD/7iA== - dependencies: - "@babel/code-frame" "^7.12.13" - "@babel/generator" "^7.14.2" - "@babel/helper-function-name" "^7.14.2" - "@babel/helper-split-export-declaration" "^7.12.13" - "@babel/parser" "^7.14.2" - "@babel/types" "^7.14.2" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/types@^7.0.0", "@babel/types@^7.12.1", "@babel/types@^7.12.13", "@babel/types@^7.12.6", "@babel/types@^7.13.0", "@babel/types@^7.13.12", "@babel/types@^7.13.16", "@babel/types@^7.14.0", "@babel/types@^7.14.2", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0": - version "7.14.2" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.14.2.tgz#4208ae003107ef8a057ea8333e56eb64d2f6a2c3" - integrity sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw== - dependencies: - "@babel/helper-validator-identifier" "^7.14.0" - to-fast-properties "^2.0.0" - -"@bcoe/v8-coverage@^0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" - integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== - -"@cnakazawa/watch@^1.0.3": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a" - integrity sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ== - dependencies: - exec-sh "^0.3.2" - minimist "^1.2.0" - -"@csstools/convert-colors@^1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@csstools/convert-colors/-/convert-colors-1.4.0.tgz#ad495dc41b12e75d588c6db8b9834f08fa131eb7" - integrity sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw== - -"@csstools/normalize.css@^10.1.0": - version "10.1.0" - resolved "https://registry.yarnpkg.com/@csstools/normalize.css/-/normalize.css-10.1.0.tgz#f0950bba18819512d42f7197e56c518aa491cf18" - integrity sha512-ij4wRiunFfaJxjB0BdrYHIH8FxBJpOwNPhhAcunlmPdXudL1WQV1qoP9un6JsEBAgQH+7UXyyjh0g7jTxXK6tg== - -"@eslint/eslintrc@^0.4.1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.1.tgz#442763b88cecbe3ee0ec7ca6d6dd6168550cbf14" - integrity sha512-5v7TDE9plVhvxQeWLXDTvFvJBdH6pEsdnl2g/dAptmuFEPedQ4Erq5rsDsX+mvAM610IhNaO2W5V1dOOnDKxkQ== - dependencies: - ajv "^6.12.4" - debug "^4.1.1" - espree "^7.3.0" - globals "^12.1.0" - ignore "^4.0.6" - import-fresh "^3.2.1" - js-yaml "^3.13.1" - minimatch "^3.0.4" - strip-json-comments "^3.1.1" - -"@hapi/address@2.x.x": - version "2.1.4" - resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.1.4.tgz#5d67ed43f3fd41a69d4b9ff7b56e7c0d1d0a81e5" - integrity sha512-QD1PhQk+s31P1ixsX0H0Suoupp3VMXzIVMSwobR3F3MSUO2YCV0B7xqLcUw/Bh8yuvd3LhpyqLQWTNcRmp6IdQ== - -"@hapi/bourne@1.x.x": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@hapi/bourne/-/bourne-1.3.2.tgz#0a7095adea067243ce3283e1b56b8a8f453b242a" - integrity sha512-1dVNHT76Uu5N3eJNTYcvxee+jzX4Z9lfciqRRHCU27ihbUcYi+iSc2iml5Ke1LXe1SyJCLA0+14Jh4tXJgOppA== - -"@hapi/hoek@8.x.x", "@hapi/hoek@^8.3.0": - version "8.5.1" - resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-8.5.1.tgz#fde96064ca446dec8c55a8c2f130957b070c6e06" - integrity sha512-yN7kbciD87WzLGc5539Tn0sApjyiGHAJgKvG9W8C7O+6c7qmoQMfVs0W4bX17eqz6C78QJqqFrtgdK5EWf6Qow== - -"@hapi/joi@^15.1.0": - version "15.1.1" - resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-15.1.1.tgz#c675b8a71296f02833f8d6d243b34c57b8ce19d7" - integrity sha512-entf8ZMOK8sc+8YfeOlM8pCfg3b5+WZIKBfUaaJT8UsjAAPjartzxIYm3TIbjvA4u+u++KbcXD38k682nVHDAQ== - dependencies: - "@hapi/address" "2.x.x" - "@hapi/bourne" "1.x.x" - "@hapi/hoek" "8.x.x" - "@hapi/topo" "3.x.x" - -"@hapi/topo@3.x.x": - version "3.1.6" - resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-3.1.6.tgz#68d935fa3eae7fdd5ab0d7f953f3205d8b2bfc29" - integrity sha512-tAag0jEcjwH+P2quUfipd7liWCNX2F8NvYjQp2wtInsZxnMlypdw0FtAOLxtvvkO+GSRRbmNi8m/5y42PQJYCQ== - dependencies: - "@hapi/hoek" "^8.3.0" - -"@istanbuljs/load-nyc-config@^1.0.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" - integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== - dependencies: - camelcase "^5.3.1" - find-up "^4.1.0" - get-package-type "^0.1.0" - js-yaml "^3.13.1" - resolve-from "^5.0.0" - -"@istanbuljs/schema@^0.1.2": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" - integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== - -"@jest/console@^26.6.2": - version "26.6.2" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-26.6.2.tgz#4e04bc464014358b03ab4937805ee36a0aeb98f2" - integrity sha512-IY1R2i2aLsLr7Id3S6p2BA82GNWryt4oSvEXLAKc+L2zdi89dSkE8xC1C+0kpATG4JhBJREnQOH7/zmccM2B0g== - dependencies: - "@jest/types" "^26.6.2" - "@types/node" "*" - chalk "^4.0.0" - jest-message-util "^26.6.2" - jest-util "^26.6.2" - slash "^3.0.0" - -"@jest/core@^26.6.0", "@jest/core@^26.6.3": - version "26.6.3" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-26.6.3.tgz#7639fcb3833d748a4656ada54bde193051e45fad" - integrity sha512-xvV1kKbhfUqFVuZ8Cyo+JPpipAHHAV3kcDBftiduK8EICXmTFddryy3P7NfZt8Pv37rA9nEJBKCCkglCPt/Xjw== - dependencies: - "@jest/console" "^26.6.2" - "@jest/reporters" "^26.6.2" - "@jest/test-result" "^26.6.2" - "@jest/transform" "^26.6.2" - "@jest/types" "^26.6.2" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - exit "^0.1.2" - graceful-fs "^4.2.4" - jest-changed-files "^26.6.2" - jest-config "^26.6.3" - jest-haste-map "^26.6.2" - jest-message-util "^26.6.2" - jest-regex-util "^26.0.0" - jest-resolve "^26.6.2" - jest-resolve-dependencies "^26.6.3" - jest-runner "^26.6.3" - jest-runtime "^26.6.3" - jest-snapshot "^26.6.2" - jest-util "^26.6.2" - jest-validate "^26.6.2" - jest-watcher "^26.6.2" - micromatch "^4.0.2" - p-each-series "^2.1.0" - rimraf "^3.0.0" - slash "^3.0.0" - strip-ansi "^6.0.0" - -"@jest/environment@^26.6.0", "@jest/environment@^26.6.2": - version "26.6.2" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-26.6.2.tgz#ba364cc72e221e79cc8f0a99555bf5d7577cf92c" - integrity sha512-nFy+fHl28zUrRsCeMB61VDThV1pVTtlEokBRgqPrcT1JNq4yRNIyTHfyht6PqtUvY9IsuLGTrbG8kPXjSZIZwA== - dependencies: - "@jest/fake-timers" "^26.6.2" - "@jest/types" "^26.6.2" - "@types/node" "*" - jest-mock "^26.6.2" - -"@jest/fake-timers@^26.6.2": - version "26.6.2" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-26.6.2.tgz#459c329bcf70cee4af4d7e3f3e67848123535aad" - integrity sha512-14Uleatt7jdzefLPYM3KLcnUl1ZNikaKq34enpb5XG9i81JpppDb5muZvonvKyrl7ftEHkKS5L5/eB/kxJ+bvA== - dependencies: - "@jest/types" "^26.6.2" - "@sinonjs/fake-timers" "^6.0.1" - "@types/node" "*" - jest-message-util "^26.6.2" - jest-mock "^26.6.2" - jest-util "^26.6.2" - -"@jest/globals@^26.6.2": - version "26.6.2" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-26.6.2.tgz#5b613b78a1aa2655ae908eba638cc96a20df720a" - integrity sha512-85Ltnm7HlB/KesBUuALwQ68YTU72w9H2xW9FjZ1eL1U3lhtefjjl5c2MiUbpXt/i6LaPRvoOFJ22yCBSfQ0JIA== - dependencies: - "@jest/environment" "^26.6.2" - "@jest/types" "^26.6.2" - expect "^26.6.2" - -"@jest/reporters@^26.6.2": - version "26.6.2" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-26.6.2.tgz#1f518b99637a5f18307bd3ecf9275f6882a667f6" - integrity sha512-h2bW53APG4HvkOnVMo8q3QXa6pcaNt1HkwVsOPMBV6LD/q9oSpxNSYZQYkAnjdMjrJ86UuYeLo+aEZClV6opnw== - dependencies: - "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^26.6.2" - "@jest/test-result" "^26.6.2" - "@jest/transform" "^26.6.2" - "@jest/types" "^26.6.2" - chalk "^4.0.0" - collect-v8-coverage "^1.0.0" - exit "^0.1.2" - glob "^7.1.2" - graceful-fs "^4.2.4" - istanbul-lib-coverage "^3.0.0" - istanbul-lib-instrument "^4.0.3" - istanbul-lib-report "^3.0.0" - istanbul-lib-source-maps "^4.0.0" - istanbul-reports "^3.0.2" - jest-haste-map "^26.6.2" - jest-resolve "^26.6.2" - jest-util "^26.6.2" - jest-worker "^26.6.2" - slash "^3.0.0" - source-map "^0.6.0" - string-length "^4.0.1" - terminal-link "^2.0.0" - v8-to-istanbul "^7.0.0" - optionalDependencies: - node-notifier "^8.0.0" - -"@jest/source-map@^26.6.2": - version "26.6.2" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-26.6.2.tgz#29af5e1e2e324cafccc936f218309f54ab69d535" - integrity sha512-YwYcCwAnNmOVsZ8mr3GfnzdXDAl4LaenZP5z+G0c8bzC9/dugL8zRmxZzdoTl4IaS3CryS1uWnROLPFmb6lVvA== - dependencies: - callsites "^3.0.0" - graceful-fs "^4.2.4" - source-map "^0.6.0" - -"@jest/test-result@^26.6.0", "@jest/test-result@^26.6.2": - version "26.6.2" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-26.6.2.tgz#55da58b62df134576cc95476efa5f7949e3f5f18" - integrity sha512-5O7H5c/7YlojphYNrK02LlDIV2GNPYisKwHm2QTKjNZeEzezCbwYs9swJySv2UfPMyZ0VdsmMv7jIlD/IKYQpQ== - dependencies: - "@jest/console" "^26.6.2" - "@jest/types" "^26.6.2" - "@types/istanbul-lib-coverage" "^2.0.0" - collect-v8-coverage "^1.0.0" - -"@jest/test-sequencer@^26.6.3": - version "26.6.3" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-26.6.3.tgz#98e8a45100863886d074205e8ffdc5a7eb582b17" - integrity sha512-YHlVIjP5nfEyjlrSr8t/YdNfU/1XEt7c5b4OxcXCjyRhjzLYu/rO69/WHPuYcbCWkz8kAeZVZp2N2+IOLLEPGw== - dependencies: - "@jest/test-result" "^26.6.2" - graceful-fs "^4.2.4" - jest-haste-map "^26.6.2" - jest-runner "^26.6.3" - jest-runtime "^26.6.3" - -"@jest/transform@^26.6.2": - version "26.6.2" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-26.6.2.tgz#5ac57c5fa1ad17b2aae83e73e45813894dcf2e4b" - integrity sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA== - dependencies: - "@babel/core" "^7.1.0" - "@jest/types" "^26.6.2" - babel-plugin-istanbul "^6.0.0" - chalk "^4.0.0" - convert-source-map "^1.4.0" - fast-json-stable-stringify "^2.0.0" - graceful-fs "^4.2.4" - jest-haste-map "^26.6.2" - jest-regex-util "^26.0.0" - jest-util "^26.6.2" - micromatch "^4.0.2" - pirates "^4.0.1" - slash "^3.0.0" - source-map "^0.6.1" - write-file-atomic "^3.0.0" - -"@jest/types@^26.6.0", "@jest/types@^26.6.2": - version "26.6.2" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" - integrity sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ== - dependencies: - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^15.0.0" - chalk "^4.0.0" - -"@nodelib/fs.scandir@2.1.4": - version "2.1.4" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz#d4b3549a5db5de2683e0c1071ab4f140904bbf69" - integrity sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA== - dependencies: - "@nodelib/fs.stat" "2.0.4" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.4", "@nodelib/fs.stat@^2.0.2": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz#a3f2dd61bab43b8db8fa108a121cfffe4c676655" - integrity sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q== - -"@nodelib/fs.walk@^1.2.3": - version "1.2.6" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz#cce9396b30aa5afe9e3756608f5831adcb53d063" - integrity sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow== - dependencies: - "@nodelib/fs.scandir" "2.1.4" - fastq "^1.6.0" - -"@npmcli/move-file@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.1.2.tgz#1a82c3e372f7cae9253eb66d72543d6b8685c674" - integrity sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg== - dependencies: - mkdirp "^1.0.4" - rimraf "^3.0.2" - -"@pmmmwh/react-refresh-webpack-plugin@0.4.3": - version "0.4.3" - resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.4.3.tgz#1eec460596d200c0236bf195b078a5d1df89b766" - integrity sha512-br5Qwvh8D2OQqSXpd1g/xqXKnK0r+Jz6qVKBbWmpUcrbGOxUrf39V5oZ1876084CGn18uMdR5uvPqBv9UqtBjQ== - dependencies: - ansi-html "^0.0.7" - error-stack-parser "^2.0.6" - html-entities "^1.2.1" - native-url "^0.2.6" - schema-utils "^2.6.5" - source-map "^0.7.3" - -"@popperjs/core@^2.8.6": - version "2.9.2" - resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.9.2.tgz#adea7b6953cbb34651766b0548468e743c6a2353" - integrity sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q== - -"@restart/context@^2.1.4": - version "2.1.4" - resolved "https://registry.yarnpkg.com/@restart/context/-/context-2.1.4.tgz#a99d87c299a34c28bd85bb489cb07bfd23149c02" - integrity sha512-INJYZQJP7g+IoDUh/475NlGiTeMfwTXUEr3tmRneckHIxNolGOW9CTq83S8cxq0CgJwwcMzMJFchxvlwe7Rk8Q== - -"@restart/hooks@^0.3.26": - version "0.3.26" - resolved "https://registry.yarnpkg.com/@restart/hooks/-/hooks-0.3.26.tgz#ade155a7b0b014ef1073391dda46972c3a14a129" - integrity sha512-7Hwk2ZMYm+JLWcb7R9qIXk1OoUg1Z+saKWqZXlrvFwT3w6UArVNWgxYOzf+PJoK9zZejp8okPAKTctthhXLt5g== - dependencies: - lodash "^4.17.20" - lodash-es "^4.17.20" - -"@rollup/plugin-node-resolve@^7.1.1": - version "7.1.3" - resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-7.1.3.tgz#80de384edfbd7bfc9101164910f86078151a3eca" - integrity sha512-RxtSL3XmdTAE2byxekYLnx+98kEUOrPHF/KRVjLH+DEIHy6kjIw7YINQzn+NXiH/NTrQLAwYs0GWB+csWygA9Q== - dependencies: - "@rollup/pluginutils" "^3.0.8" - "@types/resolve" "0.0.8" - builtin-modules "^3.1.0" - is-module "^1.0.0" - resolve "^1.14.2" - -"@rollup/plugin-replace@^2.3.1": - version "2.4.2" - resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz#a2d539314fbc77c244858faa523012825068510a" - integrity sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg== - dependencies: - "@rollup/pluginutils" "^3.1.0" - magic-string "^0.25.7" - -"@rollup/pluginutils@^3.0.8", "@rollup/pluginutils@^3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" - integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg== - dependencies: - "@types/estree" "0.0.39" - estree-walker "^1.0.1" - picomatch "^2.2.2" - -"@sinonjs/commons@^1.7.0": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d" - integrity sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ== - dependencies: - type-detect "4.0.8" - -"@sinonjs/fake-timers@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz#293674fccb3262ac782c7aadfdeca86b10c75c40" - integrity sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA== - dependencies: - "@sinonjs/commons" "^1.7.0" - -"@surma/rollup-plugin-off-main-thread@^1.1.1": - version "1.4.2" - resolved "https://registry.yarnpkg.com/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-1.4.2.tgz#e6786b6af5799f82f7ab3a82e53f6182d2b91a58" - integrity sha512-yBMPqmd1yEJo/280PAMkychuaALyQ9Lkb5q1ck3mjJrFuEobIfhnQ4J3mbvBoISmR3SWMWV+cGB/I0lCQee79A== - dependencies: - ejs "^2.6.1" - magic-string "^0.25.0" - -"@svgr/babel-plugin-add-jsx-attribute@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz#81ef61947bb268eb9d50523446f9c638fb355906" - integrity sha512-ZFf2gs/8/6B8PnSofI0inYXr2SDNTDScPXhN7k5EqD4aZ3gi6u+rbmZHVB8IM3wDyx8ntKACZbtXSm7oZGRqVg== - -"@svgr/babel-plugin-remove-jsx-attribute@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-5.4.0.tgz#6b2c770c95c874654fd5e1d5ef475b78a0a962ef" - integrity sha512-yaS4o2PgUtwLFGTKbsiAy6D0o3ugcUhWK0Z45umJ66EPWunAz9fuFw2gJuje6wqQvQWOTJvIahUwndOXb7QCPg== - -"@svgr/babel-plugin-remove-jsx-empty-expression@^5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-5.0.1.tgz#25621a8915ed7ad70da6cea3d0a6dbc2ea933efd" - integrity sha512-LA72+88A11ND/yFIMzyuLRSMJ+tRKeYKeQ+mR3DcAZ5I4h5CPWN9AHyUzJbWSYp/u2u0xhmgOe0+E41+GjEueA== - -"@svgr/babel-plugin-replace-jsx-attribute-value@^5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-5.0.1.tgz#0b221fc57f9fcd10e91fe219e2cd0dd03145a897" - integrity sha512-PoiE6ZD2Eiy5mK+fjHqwGOS+IXX0wq/YDtNyIgOrc6ejFnxN4b13pRpiIPbtPwHEc+NT2KCjteAcq33/F1Y9KQ== - -"@svgr/babel-plugin-svg-dynamic-title@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-5.4.0.tgz#139b546dd0c3186b6e5db4fefc26cb0baea729d7" - integrity sha512-zSOZH8PdZOpuG1ZVx/cLVePB2ibo3WPpqo7gFIjLV9a0QsuQAzJiwwqmuEdTaW2pegyBE17Uu15mOgOcgabQZg== - -"@svgr/babel-plugin-svg-em-dimensions@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-5.4.0.tgz#6543f69526632a133ce5cabab965deeaea2234a0" - integrity sha512-cPzDbDA5oT/sPXDCUYoVXEmm3VIoAWAPT6mSPTJNbQaBNUuEKVKyGH93oDY4e42PYHRW67N5alJx/eEol20abw== - -"@svgr/babel-plugin-transform-react-native-svg@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-5.4.0.tgz#00bf9a7a73f1cad3948cdab1f8dfb774750f8c80" - integrity sha512-3eYP/SaopZ41GHwXma7Rmxcv9uRslRDTY1estspeB1w1ueZWd/tPlMfEOoccYpEMZU3jD4OU7YitnXcF5hLW2Q== - -"@svgr/babel-plugin-transform-svg-component@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-5.5.0.tgz#583a5e2a193e214da2f3afeb0b9e8d3250126b4a" - integrity sha512-q4jSH1UUvbrsOtlo/tKcgSeiCHRSBdXoIoqX1pgcKK/aU3JD27wmMKwGtpB8qRYUYoyXvfGxUVKchLuR5pB3rQ== - -"@svgr/babel-preset@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-5.5.0.tgz#8af54f3e0a8add7b1e2b0fcd5a882c55393df327" - integrity sha512-4FiXBjvQ+z2j7yASeGPEi8VD/5rrGQk4Xrq3EdJmoZgz/tpqChpo5hgXDvmEauwtvOc52q8ghhZK4Oy7qph4ig== - dependencies: - "@svgr/babel-plugin-add-jsx-attribute" "^5.4.0" - "@svgr/babel-plugin-remove-jsx-attribute" "^5.4.0" - "@svgr/babel-plugin-remove-jsx-empty-expression" "^5.0.1" - "@svgr/babel-plugin-replace-jsx-attribute-value" "^5.0.1" - "@svgr/babel-plugin-svg-dynamic-title" "^5.4.0" - "@svgr/babel-plugin-svg-em-dimensions" "^5.4.0" - "@svgr/babel-plugin-transform-react-native-svg" "^5.4.0" - "@svgr/babel-plugin-transform-svg-component" "^5.5.0" - -"@svgr/core@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@svgr/core/-/core-5.5.0.tgz#82e826b8715d71083120fe8f2492ec7d7874a579" - integrity sha512-q52VOcsJPvV3jO1wkPtzTuKlvX7Y3xIcWRpCMtBF3MrteZJtBfQw/+u0B1BHy5ColpQc1/YVTrPEtSYIMNZlrQ== - dependencies: - "@svgr/plugin-jsx" "^5.5.0" - camelcase "^6.2.0" - cosmiconfig "^7.0.0" - -"@svgr/hast-util-to-babel-ast@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-5.5.0.tgz#5ee52a9c2533f73e63f8f22b779f93cd432a5461" - integrity sha512-cAaR/CAiZRB8GP32N+1jocovUtvlj0+e65TB50/6Lcime+EA49m/8l+P2ko+XPJ4dw3xaPS3jOL4F2X4KWxoeQ== - dependencies: - "@babel/types" "^7.12.6" - -"@svgr/plugin-jsx@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-5.5.0.tgz#1aa8cd798a1db7173ac043466d7b52236b369000" - integrity sha512-V/wVh33j12hGh05IDg8GpIUXbjAPnTdPTKuP4VNLggnwaHMPNQNae2pRnyTAILWCQdz5GyMqtO488g7CKM8CBA== - dependencies: - "@babel/core" "^7.12.3" - "@svgr/babel-preset" "^5.5.0" - "@svgr/hast-util-to-babel-ast" "^5.5.0" - svg-parser "^2.0.2" - -"@svgr/plugin-svgo@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-5.5.0.tgz#02da55d85320549324e201c7b2e53bf431fcc246" - integrity sha512-r5swKk46GuQl4RrVejVwpeeJaydoxkdwkM1mBKOgJLBUJPGaLci6ylg/IjhrRsREKDkr4kbMWdgOtbXEh0fyLQ== - dependencies: - cosmiconfig "^7.0.0" - deepmerge "^4.2.2" - svgo "^1.2.2" - -"@svgr/webpack@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@svgr/webpack/-/webpack-5.5.0.tgz#aae858ee579f5fa8ce6c3166ef56c6a1b381b640" - integrity sha512-DOBOK255wfQxguUta2INKkzPj6AIS6iafZYiYmHn6W3pHlycSRRlvWKCfLDG10fXfLWqE3DJHgRUOyJYmARa7g== - dependencies: - "@babel/core" "^7.12.3" - "@babel/plugin-transform-react-constant-elements" "^7.12.1" - "@babel/preset-env" "^7.12.1" - "@babel/preset-react" "^7.12.5" - "@svgr/core" "^5.5.0" - "@svgr/plugin-jsx" "^5.5.0" - "@svgr/plugin-svgo" "^5.5.0" - loader-utils "^2.0.0" - -"@testing-library/dom@^7.28.1": - version "7.31.0" - resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.31.0.tgz#938451abd3ca27e1b69bb395d4a40759fd7f5b3b" - integrity sha512-0X7ACg4YvTRDFMIuTOEj6B4NpN7i3F/4j5igOcTI5NC5J+N4TribNdErCHOZF1LBWhhcyfwxelVwvoYNMUXTOA== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/runtime" "^7.12.5" - "@types/aria-query" "^4.2.0" - aria-query "^4.2.2" - chalk "^4.1.0" - dom-accessibility-api "^0.5.4" - lz-string "^1.4.4" - pretty-format "^26.6.2" - -"@testing-library/jest-dom@^5.11.4": - version "5.12.0" - resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.12.0.tgz#6a5d340b092c44b7bce17a4791b47d9bc2c61443" - integrity sha512-N9Y82b2Z3j6wzIoAqajlKVF1Zt7sOH0pPee0sUHXHc5cv2Fdn23r+vpWm0MBBoGJtPOly5+Bdx1lnc3CD+A+ow== - dependencies: - "@babel/runtime" "^7.9.2" - "@types/testing-library__jest-dom" "^5.9.1" - aria-query "^4.2.2" - chalk "^3.0.0" - css "^3.0.0" - css.escape "^1.5.1" - lodash "^4.17.15" - redent "^3.0.0" - -"@testing-library/react@^11.1.0": - version "11.2.7" - resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-11.2.7.tgz#b29e2e95c6765c815786c0bc1d5aed9cb2bf7818" - integrity sha512-tzRNp7pzd5QmbtXNG/mhdcl7Awfu/Iz1RaVHY75zTdOkmHCuzMhRL83gWHSgOAcjS3CCbyfwUHMZgRJb4kAfpA== - dependencies: - "@babel/runtime" "^7.12.5" - "@testing-library/dom" "^7.28.1" - -"@testing-library/user-event@^12.1.10": - version "12.8.3" - resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-12.8.3.tgz#1aa3ed4b9f79340a1e1836bc7f57c501e838704a" - integrity sha512-IR0iWbFkgd56Bu5ZI/ej8yQwrkCv8Qydx6RzwbKz9faXazR/+5tvYKsZQgyXJiwgpcva127YO6JcWy7YlCfofQ== - dependencies: - "@babel/runtime" "^7.12.5" - -"@types/aria-query@^4.2.0": - version "4.2.1" - resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.1.tgz#78b5433344e2f92e8b306c06a5622c50c245bf6b" - integrity sha512-S6oPal772qJZHoRZLFc/XoZW2gFvwXusYUmXPXkgxJLuEk2vOt7jc4Yo6z/vtI0EBkbPBVrJJ0B+prLIKiWqHg== - -"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.7": - version "7.1.14" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.14.tgz#faaeefc4185ec71c389f4501ee5ec84b170cc402" - integrity sha512-zGZJzzBUVDo/eV6KgbE0f0ZI7dInEYvo12Rb70uNQDshC3SkRMb67ja0GgRHZgAX3Za6rhaWlvbDO8rrGyAb1g== - dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" - "@types/babel__generator" "*" - "@types/babel__template" "*" - "@types/babel__traverse" "*" - -"@types/babel__generator@*": - version "7.6.2" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.2.tgz#f3d71178e187858f7c45e30380f8f1b7415a12d8" - integrity sha512-MdSJnBjl+bdwkLskZ3NGFp9YcXGx5ggLpQQPqtgakVhsWK0hTtNYhjpZLlWQTviGTvF8at+Bvli3jV7faPdgeQ== - dependencies: - "@babel/types" "^7.0.0" - -"@types/babel__template@*": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.0.tgz#0c888dd70b3ee9eebb6e4f200e809da0076262be" - integrity sha512-NTPErx4/FiPCGScH7foPyr+/1Dkzkni+rHiYHHoTjvwou7AQzJkNeD60A9CXRy+ZEN2B1bggmkTMCDb+Mv5k+A== - dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" - -"@types/babel__traverse@*", "@types/babel__traverse@^7.0.4", "@types/babel__traverse@^7.0.6": - version "7.11.1" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.11.1.tgz#654f6c4f67568e24c23b367e947098c6206fa639" - integrity sha512-Vs0hm0vPahPMYi9tDjtP66llufgO3ST16WXaSTtDGEl9cewAl3AibmxWw6TINOqHPT9z0uABKAYjT9jNSg4npw== - dependencies: - "@babel/types" "^7.3.0" - -"@types/classnames@^2.2.10": - version "2.3.1" - resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.3.1.tgz#3c2467aa0f1a93f1f021e3b9bcf938bd5dfdc0dd" - integrity sha512-zeOWb0JGBoVmlQoznvqXbE0tEC/HONsnoUNH19Hc96NFsTAwTXbTqb8FMYkru1F/iqp7a18Ws3nWJvtA1sHD1A== - dependencies: - classnames "*" - -"@types/eslint@^7.2.6": - version "7.2.11" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.2.11.tgz#180b58f5bb7d7376e39d22496e2b08901aa52fd2" - integrity sha512-WYhv//5K8kQtsSc9F1Kn2vHzhYor6KpwPbARH7hwYe3C3ETD0EVx/3P5qQybUoaBEuUa9f/02JjBiXFWalYUmw== - dependencies: - "@types/estree" "*" - "@types/json-schema" "*" - -"@types/estree@*": - version "0.0.47" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.47.tgz#d7a51db20f0650efec24cd04994f523d93172ed4" - integrity sha512-c5ciR06jK8u9BstrmJyO97m+klJrrhCf9u3rLu3DEAJBirxRqSCvDQoYKmxuYwQI5SZChAWu+tq9oVlGRuzPAg== - -"@types/estree@0.0.39": - version "0.0.39" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" - integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== - -"@types/glob@^7.1.1": - version "7.1.3" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183" - integrity sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w== - dependencies: - "@types/minimatch" "*" - "@types/node" "*" - -"@types/graceful-fs@^4.1.2": - version "4.1.5" - resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" - integrity sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw== - dependencies: - "@types/node" "*" - -"@types/html-minifier-terser@^5.0.0": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#3c9ee980f1a10d6021ae6632ca3e79ca2ec4fb50" - integrity sha512-giAlZwstKbmvMk1OO7WXSj4OZ0keXAcl2TQq4LWHiiPH2ByaH7WeUzng+Qej8UPxxv+8lRTuouo0iaNDBuzIBA== - -"@types/invariant@^2.2.33": - version "2.2.34" - resolved "https://registry.yarnpkg.com/@types/invariant/-/invariant-2.2.34.tgz#05e4f79f465c2007884374d4795452f995720bbe" - integrity sha512-lYUtmJ9BqUN688fGY1U1HZoWT1/Jrmgigx2loq4ZcJpICECm/Om3V314BxdzypO0u5PORKGMM6x0OXaljV1YFg== - -"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762" - integrity sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw== - -"@types/istanbul-lib-report@*": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" - integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== - dependencies: - "@types/istanbul-lib-coverage" "*" - -"@types/istanbul-reports@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz#508b13aa344fa4976234e75dddcc34925737d821" - integrity sha512-nwKNbvnwJ2/mndE9ItP/zc2TCzw6uuodnF4EHYWD+gCQDVBuRQL5UzbZD0/ezy1iKsFU2ZQiDqg4M9dN4+wZgA== - dependencies: - "@types/istanbul-lib-report" "*" - -"@types/jest@*", "@types/jest@^26.0.15": - version "26.0.23" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.23.tgz#a1b7eab3c503b80451d019efb588ec63522ee4e7" - integrity sha512-ZHLmWMJ9jJ9PTiT58juykZpL7KjwJywFN3Rr2pTSkyQfydf/rk22yS7W8p5DaVUMQ2BQC7oYiU3FjbTM/mYrOA== - dependencies: - jest-diff "^26.0.0" - pretty-format "^26.0.0" - -"@types/json-schema@*", "@types/json-schema@^7.0.3", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6": - version "7.0.7" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad" - integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA== - -"@types/json5@^0.0.29": - version "0.0.29" - resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" - integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= - -"@types/minimatch@*": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.4.tgz#f0ec25dbf2f0e4b18647313ac031134ca5b24b21" - integrity sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA== - -"@types/node@*": - version "15.6.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-15.6.0.tgz#f0ddca5a61e52627c9dcb771a6039d44694597bc" - integrity sha512-gCYSfQpy+LYhOFTKAeE8BkyGqaxmlFxe+n4DKM6DR0wzw/HISUE/hAmkC/KT8Sw5PCJblqg062b3z9gucv3k0A== - -"@types/node@^12.0.0": - version "12.20.13" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.13.tgz#e743bae112bd779ac9650f907197dd2caa7f0364" - integrity sha512-1x8W5OpxPq+T85OUsHRP6BqXeosKmeXRtjoF39STcdf/UWLqUsoehstZKOi0CunhVqHG17AyZgpj20eRVooK6A== - -"@types/normalize-package-data@^2.4.0": - version "2.4.0" - resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" - integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== - -"@types/parse-json@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" - integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== - -"@types/prettier@^2.0.0": - version "2.2.3" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.2.3.tgz#ef65165aea2924c9359205bf748865b8881753c0" - integrity sha512-PijRCG/K3s3w1We6ynUKdxEc5AcuuH3NBmMDP8uvKVp6X43UY7NQlTzczakXP3DJR0F4dfNQIGjU2cUeRYs2AA== - -"@types/prop-types@*", "@types/prop-types@^15.7.3": - version "15.7.3" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" - integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== - -"@types/q@^1.5.1": - version "1.5.4" - resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24" - integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug== - -"@types/react-dom@^17.0.0": - version "17.0.5" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.5.tgz#df44eed5b8d9e0b13bb0cd38e0ea6572a1231227" - integrity sha512-ikqukEhH4H9gr4iJCmQVNzTB307kROe3XFfHAOTxOXPOw7lAoEXnM5KWTkzeANGL5Ce6ABfiMl/zJBYNi7ObmQ== - dependencies: - "@types/react" "*" - -"@types/react-transition-group@^4.4.1": - version "4.4.1" - resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.1.tgz#e1a3cb278df7f47f17b5082b1b3da17170bd44b1" - integrity sha512-vIo69qKKcYoJ8wKCJjwSgCTM+z3chw3g18dkrDfVX665tMH7tmbDxEAnPdey4gTlwZz5QuHGzd+hul0OVZDqqQ== - dependencies: - "@types/react" "*" - -"@types/react@*", "@types/react@>=16.9.11", "@types/react@>=16.9.35", "@types/react@^17.0.0": - version "17.0.6" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.6.tgz#0ec564566302c562bf497d73219797a5e0297013" - integrity sha512-u/TtPoF/hrvb63LdukET6ncaplYsvCvmkceasx8oG84/ZCsoLxz9Z/raPBP4lTAiWW1Jb889Y9svHmv8R26dWw== - dependencies: - "@types/prop-types" "*" - "@types/scheduler" "*" - csstype "^3.0.2" - -"@types/resolve@0.0.8": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.8.tgz#f26074d238e02659e323ce1a13d041eee280e194" - integrity sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ== - dependencies: - "@types/node" "*" - -"@types/scheduler@*": - version "0.16.1" - resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.1.tgz#18845205e86ff0038517aab7a18a62a6b9f71275" - integrity sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA== - -"@types/source-list-map@*": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9" - integrity sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA== - -"@types/stack-utils@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.0.tgz#7036640b4e21cc2f259ae826ce843d277dad8cff" - integrity sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw== - -"@types/tapable@^1", "@types/tapable@^1.0.5": - version "1.0.7" - resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.7.tgz#545158342f949e8fd3bfd813224971ecddc3fac4" - integrity sha512-0VBprVqfgFD7Ehb2vd8Lh9TG3jP98gvr8rgehQqzztZNI7o8zS8Ad4jyZneKELphpuE212D8J70LnSNQSyO6bQ== - -"@types/testing-library__jest-dom@^5.9.1": - version "5.9.5" - resolved "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.9.5.tgz#5bf25c91ad2d7b38f264b12275e5c92a66d849b0" - integrity sha512-ggn3ws+yRbOHog9GxnXiEZ/35Mow6YtPZpd7Z5mKDeZS/o7zx3yAle0ov/wjhVB5QT4N2Dt+GNoGCdqkBGCajQ== - dependencies: - "@types/jest" "*" - -"@types/uglify-js@*": - version "3.13.0" - resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.13.0.tgz#1cad8df1fb0b143c5aba08de5712ea9d1ff71124" - integrity sha512-EGkrJD5Uy+Pg0NUR8uA4bJ5WMfljyad0G+784vLCNUkD+QwOJXUbBYExXfVGf7YtyzdQp3L/XMYcliB987kL5Q== - dependencies: - source-map "^0.6.1" - -"@types/warning@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/warning/-/warning-3.0.0.tgz#0d2501268ad8f9962b740d387c4654f5f8e23e52" - integrity sha1-DSUBJorY+ZYrdA04fEZU9fjiPlI= - -"@types/webpack-sources@*": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-2.1.0.tgz#8882b0bd62d1e0ce62f183d0d01b72e6e82e8c10" - integrity sha512-LXn/oYIpBeucgP1EIJbKQ2/4ZmpvRl+dlrFdX7+94SKRUV3Evy3FsfMZY318vGhkWUS5MPhtOM3w1/hCOAOXcg== - dependencies: - "@types/node" "*" - "@types/source-list-map" "*" - source-map "^0.7.3" - -"@types/webpack@^4.41.8": - version "4.41.29" - resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.29.tgz#2e66c1de8223c440366469415c50a47d97625773" - integrity sha512-6pLaORaVNZxiB3FSHbyBiWM7QdazAWda1zvAq4SbZObZqHSDbWLi62iFdblVea6SK9eyBIVp5yHhKt/yNQdR7Q== - dependencies: - "@types/node" "*" - "@types/tapable" "^1" - "@types/uglify-js" "*" - "@types/webpack-sources" "*" - anymatch "^3.0.0" - source-map "^0.6.0" - -"@types/yargs-parser@*": - version "20.2.0" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.0.tgz#dd3e6699ba3237f0348cd085e4698780204842f9" - integrity sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA== - -"@types/yargs@^15.0.0": - version "15.0.13" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.13.tgz#34f7fec8b389d7f3c1fd08026a5763e072d3c6dc" - integrity sha512-kQ5JNTrbDv3Rp5X2n/iUu37IJBDU2gsZ5R/g1/KHOOEc5IKfUFjXT6DENPGduh08I/pamwtEq4oul7gUqKTQDQ== - dependencies: - "@types/yargs-parser" "*" - -"@typescript-eslint/eslint-plugin@^4.24.0", "@typescript-eslint/eslint-plugin@^4.5.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.24.0.tgz#03801ffc25b2af9d08f3dc9bccfc0b7ce3780d0f" - integrity sha512-qbCgkPM7DWTsYQGjx9RTuQGswi+bEt0isqDBeo+CKV0953zqI0Tp7CZ7Fi9ipgFA6mcQqF4NOVNwS/f2r6xShw== - dependencies: - "@typescript-eslint/experimental-utils" "4.24.0" - "@typescript-eslint/scope-manager" "4.24.0" - debug "^4.1.1" - functional-red-black-tree "^1.0.1" - lodash "^4.17.15" - regexpp "^3.0.0" - semver "^7.3.2" - tsutils "^3.17.1" - -"@typescript-eslint/experimental-utils@4.24.0", "@typescript-eslint/experimental-utils@^4.0.1": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.24.0.tgz#c23ead9de44b99c3a5fd925c33a106b00165e172" - integrity sha512-IwTT2VNDKH1h8RZseMH4CcYBz6lTvRoOLDuuqNZZoThvfHEhOiZPQCow+5El3PtyxJ1iDr6UXZwYtE3yZQjhcw== - dependencies: - "@types/json-schema" "^7.0.3" - "@typescript-eslint/scope-manager" "4.24.0" - "@typescript-eslint/types" "4.24.0" - "@typescript-eslint/typescript-estree" "4.24.0" - eslint-scope "^5.0.0" - eslint-utils "^2.0.0" - -"@typescript-eslint/experimental-utils@^3.10.1": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-3.10.1.tgz#e179ffc81a80ebcae2ea04e0332f8b251345a686" - integrity sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw== - dependencies: - "@types/json-schema" "^7.0.3" - "@typescript-eslint/types" "3.10.1" - "@typescript-eslint/typescript-estree" "3.10.1" - eslint-scope "^5.0.0" - eslint-utils "^2.0.0" - -"@typescript-eslint/parser@^4.24.0", "@typescript-eslint/parser@^4.5.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.24.0.tgz#2e5f1cc78ffefe43bfac7e5659309a92b09a51bd" - integrity sha512-dj1ZIh/4QKeECLb2f/QjRwMmDArcwc2WorWPRlB8UNTZlY1KpTVsbX7e3ZZdphfRw29aTFUSNuGB8w9X5sS97w== - dependencies: - "@typescript-eslint/scope-manager" "4.24.0" - "@typescript-eslint/types" "4.24.0" - "@typescript-eslint/typescript-estree" "4.24.0" - debug "^4.1.1" - -"@typescript-eslint/scope-manager@4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.24.0.tgz#38088216f0eaf235fa30ed8cabf6948ec734f359" - integrity sha512-9+WYJGDnuC9VtYLqBhcSuM7du75fyCS/ypC8c5g7Sdw7pGL4NDTbeH38eJPfzIydCHZDoOgjloxSAA3+4l/zsA== - dependencies: - "@typescript-eslint/types" "4.24.0" - "@typescript-eslint/visitor-keys" "4.24.0" - -"@typescript-eslint/types@3.10.1": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.10.1.tgz#1d7463fa7c32d8a23ab508a803ca2fe26e758727" - integrity sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ== - -"@typescript-eslint/types@4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.24.0.tgz#6d0cca2048cbda4e265e0c4db9c2a62aaad8228c" - integrity sha512-tkZUBgDQKdvfs8L47LaqxojKDE+mIUmOzdz7r+u+U54l3GDkTpEbQ1Jp3cNqqAU9vMUCBA1fitsIhm7yN0vx9Q== - -"@typescript-eslint/typescript-estree@3.10.1": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz#fd0061cc38add4fad45136d654408569f365b853" - integrity sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w== - dependencies: - "@typescript-eslint/types" "3.10.1" - "@typescript-eslint/visitor-keys" "3.10.1" - debug "^4.1.1" - glob "^7.1.6" - is-glob "^4.0.1" - lodash "^4.17.15" - semver "^7.3.2" - tsutils "^3.17.1" - -"@typescript-eslint/typescript-estree@4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.24.0.tgz#b49249679a98014d8b03e8d4b70864b950e3c90f" - integrity sha512-kBDitL/by/HK7g8CYLT7aKpAwlR8doshfWz8d71j97n5kUa5caHWvY0RvEUEanL/EqBJoANev8Xc/mQ6LLwXGA== - dependencies: - "@typescript-eslint/types" "4.24.0" - "@typescript-eslint/visitor-keys" "4.24.0" - debug "^4.1.1" - globby "^11.0.1" - is-glob "^4.0.1" - semver "^7.3.2" - tsutils "^3.17.1" - -"@typescript-eslint/visitor-keys@3.10.1": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz#cd4274773e3eb63b2e870ac602274487ecd1e931" - integrity sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ== - dependencies: - eslint-visitor-keys "^1.1.0" - -"@typescript-eslint/visitor-keys@4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.24.0.tgz#a8fafdc76cad4e04a681a945fbbac4e35e98e297" - integrity sha512-4ox1sjmGHIxjEDBnMCtWFFhErXtKA1Ec0sBpuz0fqf3P+g3JFGyTxxbF06byw0FRsPnnbq44cKivH7Ks1/0s6g== - dependencies: - "@typescript-eslint/types" "4.24.0" - eslint-visitor-keys "^2.0.0" - -"@webassemblyjs/ast@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" - integrity sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA== - dependencies: - "@webassemblyjs/helper-module-context" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/wast-parser" "1.9.0" - -"@webassemblyjs/floating-point-hex-parser@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz#3c3d3b271bddfc84deb00f71344438311d52ffb4" - integrity sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA== - -"@webassemblyjs/helper-api-error@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz#203f676e333b96c9da2eeab3ccef33c45928b6a2" - integrity sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw== - -"@webassemblyjs/helper-buffer@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz#a1442d269c5feb23fcbc9ef759dac3547f29de00" - integrity sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA== - -"@webassemblyjs/helper-code-frame@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz#647f8892cd2043a82ac0c8c5e75c36f1d9159f27" - integrity sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA== - dependencies: - "@webassemblyjs/wast-printer" "1.9.0" - -"@webassemblyjs/helper-fsm@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz#c05256b71244214671f4b08ec108ad63b70eddb8" - integrity sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw== - -"@webassemblyjs/helper-module-context@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz#25d8884b76839871a08a6c6f806c3979ef712f07" - integrity sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g== - dependencies: - "@webassemblyjs/ast" "1.9.0" - -"@webassemblyjs/helper-wasm-bytecode@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz#4fed8beac9b8c14f8c58b70d124d549dd1fe5790" - integrity sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw== - -"@webassemblyjs/helper-wasm-section@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz#5a4138d5a6292ba18b04c5ae49717e4167965346" - integrity sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-buffer" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/wasm-gen" "1.9.0" - -"@webassemblyjs/ieee754@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz#15c7a0fbaae83fb26143bbacf6d6df1702ad39e4" - integrity sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg== - dependencies: - "@xtuc/ieee754" "^1.2.0" - -"@webassemblyjs/leb128@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.9.0.tgz#f19ca0b76a6dc55623a09cffa769e838fa1e1c95" - integrity sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw== - dependencies: - "@xtuc/long" "4.2.2" - -"@webassemblyjs/utf8@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.9.0.tgz#04d33b636f78e6a6813227e82402f7637b6229ab" - integrity sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w== - -"@webassemblyjs/wasm-edit@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz#3fe6d79d3f0f922183aa86002c42dd256cfee9cf" - integrity sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-buffer" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/helper-wasm-section" "1.9.0" - "@webassemblyjs/wasm-gen" "1.9.0" - "@webassemblyjs/wasm-opt" "1.9.0" - "@webassemblyjs/wasm-parser" "1.9.0" - "@webassemblyjs/wast-printer" "1.9.0" - -"@webassemblyjs/wasm-gen@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz#50bc70ec68ded8e2763b01a1418bf43491a7a49c" - integrity sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/ieee754" "1.9.0" - "@webassemblyjs/leb128" "1.9.0" - "@webassemblyjs/utf8" "1.9.0" - -"@webassemblyjs/wasm-opt@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz#2211181e5b31326443cc8112eb9f0b9028721a61" - integrity sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-buffer" "1.9.0" - "@webassemblyjs/wasm-gen" "1.9.0" - "@webassemblyjs/wasm-parser" "1.9.0" - -"@webassemblyjs/wasm-parser@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz#9d48e44826df4a6598294aa6c87469d642fff65e" - integrity sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-api-error" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/ieee754" "1.9.0" - "@webassemblyjs/leb128" "1.9.0" - "@webassemblyjs/utf8" "1.9.0" - -"@webassemblyjs/wast-parser@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz#3031115d79ac5bd261556cecc3fa90a3ef451914" - integrity sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/floating-point-hex-parser" "1.9.0" - "@webassemblyjs/helper-api-error" "1.9.0" - "@webassemblyjs/helper-code-frame" "1.9.0" - "@webassemblyjs/helper-fsm" "1.9.0" - "@xtuc/long" "4.2.2" - -"@webassemblyjs/wast-printer@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz#4935d54c85fef637b00ce9f52377451d00d47899" - integrity sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/wast-parser" "1.9.0" - "@xtuc/long" "4.2.2" - -"@xtuc/ieee754@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" - integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== - -"@xtuc/long@4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" - integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== - -abab@^2.0.3, abab@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" - integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== - -accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== - dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" - -acorn-globals@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" - integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg== - dependencies: - acorn "^7.1.1" - acorn-walk "^7.1.1" - -acorn-jsx@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" - integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== - -acorn-walk@^7.1.1: - version "7.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" - integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== - -acorn@^6.4.1: - version "6.4.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" - integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== - -acorn@^7.1.0, acorn@^7.1.1, acorn@^7.4.0: - version "7.4.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" - integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== - -acorn@^8.1.0: - version "8.2.4" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.2.4.tgz#caba24b08185c3b56e3168e97d15ed17f4d31fd0" - integrity sha512-Ibt84YwBDDA890eDiDCEqcbwvHlBvzzDkU2cGBBDDI1QWT12jTiXIOn2CIw5KK4i6N5Z2HUxwYjzriDyqaqqZg== - -address@1.1.2, address@^1.0.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6" - integrity sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA== - -adjust-sourcemap-loader@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/adjust-sourcemap-loader/-/adjust-sourcemap-loader-3.0.0.tgz#5ae12fb5b7b1c585e80bbb5a63ec163a1a45e61e" - integrity sha512-YBrGyT2/uVQ/c6Rr+t6ZJXniY03YtHGMJQYal368burRGYKqhx9qGTWqcBU5s1CwYY9E/ri63RYyG1IacMZtqw== - dependencies: - loader-utils "^2.0.0" - regex-parser "^2.2.11" - -aggregate-error@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" - integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== - dependencies: - clean-stack "^2.0.0" - indent-string "^4.0.0" - -ajv-errors@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" - integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== - -ajv-keywords@^3.1.0, ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: - version "3.5.2" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" - integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== - -ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ajv@^8.0.1: - version "8.5.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.5.0.tgz#695528274bcb5afc865446aa275484049a18ae4b" - integrity sha512-Y2l399Tt1AguU3BPRP9Fn4eN+Or+StUGWCUpbnFyXSo8NZ9S4uj+AG2pjs5apK+ZMOwYOz1+a+VKvKH7CudXgQ== - dependencies: - fast-deep-equal "^3.1.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - uri-js "^4.2.2" - -alphanum-sort@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" - integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= - -ansi-colors@^3.0.0: - version "3.2.4" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" - integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== - -ansi-colors@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" - integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== - -ansi-escapes@^4.2.1, ansi-escapes@^4.3.1: - version "4.3.2" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" - integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== - dependencies: - type-fest "^0.21.3" - -ansi-html@0.0.7, ansi-html@^0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" - integrity sha1-gTWEAhliqenm/QOflA0S9WynhZ4= - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - -ansi-regex@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" - integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== - -ansi-regex@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" - integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== - -ansi-styles@^3.2.0, ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -anymatch@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" - integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== - dependencies: - micromatch "^3.1.4" - normalize-path "^2.1.1" - -anymatch@^3.0.0, anymatch@^3.0.3, anymatch@~3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" - integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -aproba@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -aria-query@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b" - integrity sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA== - dependencies: - "@babel/runtime" "^7.10.2" - "@babel/runtime-corejs3" "^7.10.2" - -arity-n@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/arity-n/-/arity-n-1.0.4.tgz#d9e76b11733e08569c0847ae7b39b2860b30b745" - integrity sha1-2edrEXM+CFacCEeuezmyhgswt0U= - -arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= - -arr-flatten@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - -arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= - -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= - -array-flatten@^2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" - integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== - -array-includes@^3.1.1, array-includes@^3.1.2, array-includes@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.3.tgz#c7f619b382ad2afaf5326cddfdc0afc61af7690a" - integrity sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.18.0-next.2" - get-intrinsic "^1.1.1" - is-string "^1.0.5" - -array-union@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= - dependencies: - array-uniq "^1.0.1" - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -array-uniq@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= - -array-unique@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= - -array.prototype.flat@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz#6ef638b43312bd401b4c6199fdec7e2dc9e9a123" - integrity sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - es-abstract "^1.18.0-next.1" - -array.prototype.flatmap@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.4.tgz#94cfd47cc1556ec0747d97f7c7738c58122004c9" - integrity sha512-r9Z0zYoxqHz60vvQbWEdXIEtCwHF0yxaWfno9qzXeNHvfyl3BZqygmGzb84dsubyaXLH4husF+NFgMSdpZhk2Q== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - es-abstract "^1.18.0-next.1" - function-bind "^1.1.1" - -arrify@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" - integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== - -asap@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= - -asn1.js@^5.2.0: - version "5.4.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" - integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== - dependencies: - bn.js "^4.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - safer-buffer "^2.1.0" - -asn1@~0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" - integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== - dependencies: - safer-buffer "~2.1.0" - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= - -assert@^1.1.1: - version "1.5.0" - resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" - integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== - dependencies: - object-assign "^4.1.1" - util "0.10.3" - -assign-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= - -ast-types-flow@^0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" - integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= - -astral-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" - integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== - -async-each@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" - integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== - -async-limiter@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" - integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== - -async@^2.6.2: - version "2.6.3" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" - integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== - dependencies: - lodash "^4.17.14" - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= - -at-least-node@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" - integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== - -atob@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" - integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== - -autoprefixer@^9.6.1: - version "9.8.6" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.6.tgz#3b73594ca1bf9266320c5acf1588d74dea74210f" - integrity sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg== - dependencies: - browserslist "^4.12.0" - caniuse-lite "^1.0.30001109" - colorette "^1.2.1" - normalize-range "^0.1.2" - num2fraction "^1.2.2" - postcss "^7.0.32" - postcss-value-parser "^4.1.0" - -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= - -aws4@^1.8.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" - integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== - -axe-core@^4.0.2: - version "4.2.1" - resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.2.1.tgz#2e50bcf10ee5b819014f6e342e41e45096239e34" - integrity sha512-evY7DN8qSIbsW2H/TWQ1bX3sXN1d4MNb5Vb4n7BzPuCwRHdkZ1H2eNLuSh73EoQqkGKUtju2G2HCcjCfhvZIAA== - -axobject-query@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" - integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA== - -babel-eslint@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" - integrity sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.7.0" - "@babel/traverse" "^7.7.0" - "@babel/types" "^7.7.0" - eslint-visitor-keys "^1.0.0" - resolve "^1.12.0" - -babel-extract-comments@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/babel-extract-comments/-/babel-extract-comments-1.0.0.tgz#0a2aedf81417ed391b85e18b4614e693a0351a21" - integrity sha512-qWWzi4TlddohA91bFwgt6zO/J0X+io7Qp184Fw0m2JYRSTZnJbFR8+07KmzudHCZgOiKRCrjhylwv9Xd8gfhVQ== - dependencies: - babylon "^6.18.0" - -babel-jest@^26.6.0, babel-jest@^26.6.3: - version "26.6.3" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.6.3.tgz#d87d25cb0037577a0c89f82e5755c5d293c01056" - integrity sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA== - dependencies: - "@jest/transform" "^26.6.2" - "@jest/types" "^26.6.2" - "@types/babel__core" "^7.1.7" - babel-plugin-istanbul "^6.0.0" - babel-preset-jest "^26.6.2" - chalk "^4.0.0" - graceful-fs "^4.2.4" - slash "^3.0.0" - -babel-loader@8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.1.0.tgz#c611d5112bd5209abe8b9fa84c3e4da25275f1c3" - integrity sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw== - dependencies: - find-cache-dir "^2.1.0" - loader-utils "^1.4.0" - mkdirp "^0.5.3" - pify "^4.0.1" - schema-utils "^2.6.5" - -babel-plugin-dynamic-import-node@^2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" - integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== - dependencies: - object.assign "^4.1.0" - -babel-plugin-istanbul@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz#e159ccdc9af95e0b570c75b4573b7c34d671d765" - integrity sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@istanbuljs/load-nyc-config" "^1.0.0" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-instrument "^4.0.0" - test-exclude "^6.0.0" - -babel-plugin-jest-hoist@^26.6.2: - version "26.6.2" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.6.2.tgz#8185bd030348d254c6d7dd974355e6a28b21e62d" - integrity sha512-PO9t0697lNTmcEHH69mdtYiOIkkOlj9fySqfO3K1eCcdISevLAE0xY59VLLUj0SoiPiTX/JU2CYFpILydUa5Lw== - dependencies: - "@babel/template" "^7.3.3" - "@babel/types" "^7.3.3" - "@types/babel__core" "^7.0.0" - "@types/babel__traverse" "^7.0.6" - -babel-plugin-macros@2.8.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz#0f958a7cc6556b1e65344465d99111a1e5e10138" - integrity sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg== - dependencies: - "@babel/runtime" "^7.7.2" - cosmiconfig "^6.0.0" - resolve "^1.12.0" - -babel-plugin-named-asset-import@^0.3.7: - version "0.3.7" - resolved "https://registry.yarnpkg.com/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.7.tgz#156cd55d3f1228a5765774340937afc8398067dd" - integrity sha512-squySRkf+6JGnvjoUtDEjSREJEBirnXi9NqP6rjSYsylxQxqBTz+pkmf395i9E2zsvmYUaI40BHo6SqZUdydlw== - -babel-plugin-polyfill-corejs2@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.1.tgz#ae2cf6d6f1aa7c0edcf04a25180e8856a6d1184f" - integrity sha512-hXGSPbr6IbjeMyGew+3uGIAkRjBFSOJ9FLDZNOfHuyJZCcoia4nd/72J0bSgvfytcVfUcP/dxEVcUhVJuQRtSw== - dependencies: - "@babel/compat-data" "^7.13.11" - "@babel/helper-define-polyfill-provider" "^0.2.1" - semver "^6.1.1" - -babel-plugin-polyfill-corejs3@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.1.tgz#786f40218040030f0edecfd48e6e59f1ee9bef53" - integrity sha512-WZCqF3DLUhdTD/P381MDJfuP18hdCZ+iqJ+wHtzhWENpsiof284JJ1tMQg1CE+hfCWyG48F7e5gDMk2c3Laz7w== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.2.1" - core-js-compat "^3.9.1" - -babel-plugin-polyfill-regenerator@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.1.tgz#ca9595d7d5f3afefec2d83126148b90db751a091" - integrity sha512-T3bYyL3Sll2EtC94v3f+fA8M28q7YPTOZdB++SRHjvYZTvtd+WorMUq3tDTD4Q7Kjk1LG0gGromslKjcO5p2TA== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.2.1" - -babel-plugin-syntax-object-rest-spread@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" - integrity sha1-/WU28rzhODb/o6VFjEkDpZe7O/U= - -babel-plugin-transform-object-rest-spread@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06" - integrity sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY= - dependencies: - babel-plugin-syntax-object-rest-spread "^6.8.0" - babel-runtime "^6.26.0" - -babel-plugin-transform-react-remove-prop-types@0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz#f2edaf9b4c6a5fbe5c1d678bfb531078c1555f3a" - integrity sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA== - -babel-preset-current-node-syntax@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" - integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== - dependencies: - "@babel/plugin-syntax-async-generators" "^7.8.4" - "@babel/plugin-syntax-bigint" "^7.8.3" - "@babel/plugin-syntax-class-properties" "^7.8.3" - "@babel/plugin-syntax-import-meta" "^7.8.3" - "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.8.3" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-top-level-await" "^7.8.3" - -babel-preset-jest@^26.6.2: - version "26.6.2" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-26.6.2.tgz#747872b1171df032252426586881d62d31798fee" - integrity sha512-YvdtlVm9t3k777c5NPQIv6cxFFFapys25HiUmuSgHwIZhfifweR5c5Sf5nwE3MAbfu327CYSvps8Yx6ANLyleQ== - dependencies: - babel-plugin-jest-hoist "^26.6.2" - babel-preset-current-node-syntax "^1.0.0" - -babel-preset-react-app@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/babel-preset-react-app/-/babel-preset-react-app-10.0.0.tgz#689b60edc705f8a70ce87f47ab0e560a317d7045" - integrity sha512-itL2z8v16khpuKutx5IH8UdCdSTuzrOhRFTEdIhveZ2i1iBKDrVE0ATa4sFVy+02GLucZNVBWtoarXBy0Msdpg== - dependencies: - "@babel/core" "7.12.3" - "@babel/plugin-proposal-class-properties" "7.12.1" - "@babel/plugin-proposal-decorators" "7.12.1" - "@babel/plugin-proposal-nullish-coalescing-operator" "7.12.1" - "@babel/plugin-proposal-numeric-separator" "7.12.1" - "@babel/plugin-proposal-optional-chaining" "7.12.1" - "@babel/plugin-transform-flow-strip-types" "7.12.1" - "@babel/plugin-transform-react-display-name" "7.12.1" - "@babel/plugin-transform-runtime" "7.12.1" - "@babel/preset-env" "7.12.1" - "@babel/preset-react" "7.12.1" - "@babel/preset-typescript" "7.12.1" - "@babel/runtime" "7.12.1" - babel-plugin-macros "2.8.0" - babel-plugin-transform-react-remove-prop-types "0.4.24" - -babel-runtime@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - -babylon@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -base64-js@^1.0.2: - version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - -base@^0.11.1: - version "0.11.2" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== - dependencies: - cache-base "^1.0.1" - class-utils "^0.3.5" - component-emitter "^1.2.1" - define-property "^1.0.0" - isobject "^3.0.1" - mixin-deep "^1.2.0" - pascalcase "^0.1.1" - -batch@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" - integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY= - -bcrypt-pbkdf@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= - dependencies: - tweetnacl "^0.14.3" - -bfj@^7.0.2: - version "7.0.2" - resolved "https://registry.yarnpkg.com/bfj/-/bfj-7.0.2.tgz#1988ce76f3add9ac2913fd8ba47aad9e651bfbb2" - integrity sha512-+e/UqUzwmzJamNF50tBV6tZPTORow7gQ96iFow+8b562OdMpEK0BcJEq2OSPEDmAbSMBQ7PKZ87ubFkgxpYWgw== - dependencies: - bluebird "^3.5.5" - check-types "^11.1.1" - hoopy "^0.1.4" - tryer "^1.0.1" - -big.js@^5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" - integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== - -binary-extensions@^1.0.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" - integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== - -binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== - -bindings@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" - integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== - dependencies: - file-uri-to-path "1.0.0" - -bluebird@^3.5.5: - version "3.7.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" - integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== - -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: - version "4.12.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" - integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== - -bn.js@^5.0.0, bn.js@^5.1.1: - version "5.2.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" - integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== - -body-parser@1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== - dependencies: - bytes "3.1.0" - content-type "~1.0.4" - debug "2.6.9" - depd "~1.1.2" - http-errors "1.7.2" - iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.7.0" - raw-body "2.4.0" - type-is "~1.6.17" - -bonjour@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5" - integrity sha1-jokKGD2O6aI5OzhExpGkK897yfU= - dependencies: - array-flatten "^2.1.0" - deep-equal "^1.0.1" - dns-equal "^1.0.0" - dns-txt "^2.0.2" - multicast-dns "^6.0.1" - multicast-dns-service-types "^1.1.0" - -boolbase@^1.0.0, boolbase@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" - integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^2.3.1, braces@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - -braces@^3.0.1, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -brorand@^1.0.1, brorand@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= - -browser-process-hrtime@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" - integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== - -browserify-aes@^1.0.0, browserify-aes@^1.0.4: - version "1.2.0" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== - dependencies: - buffer-xor "^1.0.3" - cipher-base "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.3" - inherits "^2.0.1" - safe-buffer "^5.0.1" - -browserify-cipher@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" - integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== - dependencies: - browserify-aes "^1.0.4" - browserify-des "^1.0.0" - evp_bytestokey "^1.0.0" - -browserify-des@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" - integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== - dependencies: - cipher-base "^1.0.1" - des.js "^1.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" - integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== - dependencies: - bn.js "^5.0.0" - randombytes "^2.0.1" - -browserify-sign@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" - integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== - dependencies: - bn.js "^5.1.1" - browserify-rsa "^4.0.1" - create-hash "^1.2.0" - create-hmac "^1.1.7" - elliptic "^6.5.3" - inherits "^2.0.4" - parse-asn1 "^5.1.5" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" - -browserify-zlib@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" - integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== - dependencies: - pako "~1.0.5" - -browserslist@4.14.2: - version "4.14.2" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.2.tgz#1b3cec458a1ba87588cc5e9be62f19b6d48813ce" - integrity sha512-HI4lPveGKUR0x2StIz+2FXfDk9SfVMrxn6PLh1JeGUwcuoDkdKZebWiyLRJ68iIPDpMI4JLVDf7S7XzslgWOhw== - dependencies: - caniuse-lite "^1.0.30001125" - electron-to-chromium "^1.3.564" - escalade "^3.0.2" - node-releases "^1.1.61" - -browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.16.6, browserslist@^4.6.2, browserslist@^4.6.4: - version "4.16.6" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.6.tgz#d7901277a5a88e554ed305b183ec9b0c08f66fa2" - integrity sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ== - dependencies: - caniuse-lite "^1.0.30001219" - colorette "^1.2.2" - electron-to-chromium "^1.3.723" - escalade "^3.1.1" - node-releases "^1.1.71" - -bser@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" - integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== - dependencies: - node-int64 "^0.4.0" - -buffer-from@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== - -buffer-indexof@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" - integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g== - -buffer-xor@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= - -buffer@^4.3.0: - version "4.9.2" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" - integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - isarray "^1.0.0" - -builtin-modules@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.2.0.tgz#45d5db99e7ee5e6bc4f362e008bf917ab5049887" - integrity sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA== - -builtin-status-codes@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" - integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= - -bytes@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= - -bytes@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" - integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== - -cacache@^12.0.2: - version "12.0.4" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c" - integrity sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ== - dependencies: - bluebird "^3.5.5" - chownr "^1.1.1" - figgy-pudding "^3.5.1" - glob "^7.1.4" - graceful-fs "^4.1.15" - infer-owner "^1.0.3" - lru-cache "^5.1.1" - mississippi "^3.0.0" - mkdirp "^0.5.1" - move-concurrently "^1.0.1" - promise-inflight "^1.0.1" - rimraf "^2.6.3" - ssri "^6.0.1" - unique-filename "^1.1.1" - y18n "^4.0.0" - -cacache@^15.0.5: - version "15.1.0" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.1.0.tgz#164c2f857ee606e4cc793c63018fefd0ea5eba7b" - integrity sha512-mfx0C+mCfWjD1PnwQ9yaOrwG1ou9FkKnx0SvzUHWdFt7r7GaRtzT+9M8HAvLu62zIHtnpQ/1m93nWNDCckJGXQ== - dependencies: - "@npmcli/move-file" "^1.0.1" - chownr "^2.0.0" - fs-minipass "^2.0.0" - glob "^7.1.4" - infer-owner "^1.0.4" - lru-cache "^6.0.0" - minipass "^3.1.1" - minipass-collect "^1.0.2" - minipass-flush "^1.0.5" - minipass-pipeline "^1.2.2" - mkdirp "^1.0.3" - p-map "^4.0.0" - promise-inflight "^1.0.1" - rimraf "^3.0.2" - ssri "^8.0.1" - tar "^6.0.2" - unique-filename "^1.1.1" - -cache-base@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== - dependencies: - collection-visit "^1.0.0" - component-emitter "^1.2.1" - get-value "^2.0.6" - has-value "^1.0.0" - isobject "^3.0.1" - set-value "^2.0.0" - to-object-path "^0.3.0" - union-value "^1.0.0" - unset-value "^1.0.0" - -call-bind@^1.0.0, call-bind@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== - dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" - -caller-callsite@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" - integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= - dependencies: - callsites "^2.0.0" - -caller-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" - integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= - dependencies: - caller-callsite "^2.0.0" - -callsites@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" - integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camel-case@^4.1.1: - version "4.1.2" - resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" - integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw== - dependencies: - pascal-case "^3.1.2" - tslib "^2.0.3" - -camelcase@5.3.1, camelcase@^5.0.0, camelcase@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -camelcase@^6.0.0, camelcase@^6.1.0, camelcase@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" - integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== - -caniuse-api@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" - integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== - dependencies: - browserslist "^4.0.0" - caniuse-lite "^1.0.0" - lodash.memoize "^4.1.2" - lodash.uniq "^4.5.0" - -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001125, caniuse-lite@^1.0.30001219: - version "1.0.30001228" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001228.tgz#bfdc5942cd3326fa51ee0b42fbef4da9d492a7fa" - integrity sha512-QQmLOGJ3DEgokHbMSA8cj2a+geXqmnpyOFT0lhQV6P3/YOJvGDEwoedcwxEQ30gJIwIIunHIicunJ2rzK5gB2A== - -capture-exit@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" - integrity sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g== - dependencies: - rsvp "^4.8.4" - -case-sensitive-paths-webpack-plugin@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.3.0.tgz#23ac613cc9a856e4f88ff8bb73bbb5e989825cf7" - integrity sha512-/4YgnZS8y1UXXmC02xD5rRrBEu6T5ub+mQHLNRj0fzTRbgdBYhsNo2V5EqwgqrExjxsjtF/OpAKAMkKsxbD5XQ== - -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= - -chalk@2.4.2, chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" - integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -chalk@^4.0.0, chalk@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.1.tgz#c80b3fab28bf6371e6863325eee67e618b77e6ad" - integrity sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -char-regex@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" - integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== - -check-types@^11.1.1: - version "11.1.2" - resolved "https://registry.yarnpkg.com/check-types/-/check-types-11.1.2.tgz#86a7c12bf5539f6324eb0e70ca8896c0e38f3e2f" - integrity sha512-tzWzvgePgLORb9/3a0YenggReLKAIb2owL03H2Xdoe5pKcUyWRSEQ8xfCar8t2SIAuEDwtmx2da1YB52YuHQMQ== - -chokidar@^2.1.8: - version "2.1.8" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" - integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== - dependencies: - anymatch "^2.0.0" - async-each "^1.0.1" - braces "^2.3.2" - glob-parent "^3.1.0" - inherits "^2.0.3" - is-binary-path "^1.0.0" - is-glob "^4.0.0" - normalize-path "^3.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.2.1" - upath "^1.1.1" - optionalDependencies: - fsevents "^1.2.7" - -chokidar@^3.4.1: - version "3.5.1" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" - integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== - dependencies: - anymatch "~3.1.1" - braces "~3.0.2" - glob-parent "~5.1.0" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.5.0" - optionalDependencies: - fsevents "~2.3.1" - -chownr@^1.1.1: - version "1.1.4" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" - integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== - -chownr@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" - integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== - -chrome-trace-event@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" - integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== - -ci-info@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" - integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== - -cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -cjs-module-lexer@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-0.6.0.tgz#4186fcca0eae175970aee870b9fe2d6cf8d5655f" - integrity sha512-uc2Vix1frTfnuzxxu1Hp4ktSvM3QaI4oXl4ZUqL1wjTu/BGki9TrCWoqLTg/drR1KwAEarXuRFCG2Svr1GxPFw== - -class-utils@^0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== - dependencies: - arr-union "^3.1.0" - define-property "^0.2.5" - isobject "^3.0.0" - static-extend "^0.1.1" - -classnames@*, classnames@^2.2.6: - version "2.3.1" - resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e" - integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA== - -clean-css@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78" - integrity sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA== - dependencies: - source-map "~0.6.0" - -clean-stack@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" - integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== - -cliui@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" - integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== - dependencies: - string-width "^3.1.0" - strip-ansi "^5.2.0" - wrap-ansi "^5.1.0" - -cliui@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" - integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.0" - wrap-ansi "^6.2.0" - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= - -coa@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" - integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA== - dependencies: - "@types/q" "^1.5.1" - chalk "^2.4.1" - q "^1.1.2" - -collect-v8-coverage@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" - integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== - -collection-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= - dependencies: - map-visit "^1.0.0" - object-visit "^1.0.0" - -color-convert@^1.9.0, color-convert@^1.9.1: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= - -color-name@^1.0.0, color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -color-string@^1.5.4: - version "1.5.5" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.5.tgz#65474a8f0e7439625f3d27a6a19d89fc45223014" - integrity sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg== - dependencies: - color-name "^1.0.0" - simple-swizzle "^0.2.2" - -color@^3.0.0: - version "3.1.3" - resolved "https://registry.yarnpkg.com/color/-/color-3.1.3.tgz#ca67fb4e7b97d611dcde39eceed422067d91596e" - integrity sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ== - dependencies: - color-convert "^1.9.1" - color-string "^1.5.4" - -colorette@^1.2.1, colorette@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94" - integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w== - -combined-stream@^1.0.6, combined-stream@~1.0.6: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - -commander@^2.20.0: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - -commander@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" - integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== - -common-tags@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937" - integrity sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw== - -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= - -component-emitter@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" - integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== - -compose-function@3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/compose-function/-/compose-function-3.0.3.tgz#9ed675f13cc54501d30950a486ff6a7ba3ab185f" - integrity sha1-ntZ18TzFRQHTCVCkhv9qe6OrGF8= - dependencies: - arity-n "^1.0.4" - -compressible@~2.0.16: - version "2.0.18" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" - integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== - dependencies: - mime-db ">= 1.43.0 < 2" - -compression@^1.7.4: - version "1.7.4" - resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" - integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== - dependencies: - accepts "~1.3.5" - bytes "3.0.0" - compressible "~2.0.16" - debug "2.6.9" - on-headers "~1.0.2" - safe-buffer "5.1.2" - vary "~1.1.2" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -concat-stream@^1.5.0: - version "1.6.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - -confusing-browser-globals@^1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.10.tgz#30d1e7f3d1b882b25ec4933d1d1adac353d20a59" - integrity sha512-gNld/3lySHwuhaVluJUKLePYirM3QNCKzVxqAdhJII9/WXKVX5PURzMVJspS1jTslSqjeuG4KMVTSouit5YPHA== - -connect-history-api-fallback@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" - integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== - -console-browserify@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" - integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== - -constants-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" - integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= - -content-disposition@0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" - integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== - dependencies: - safe-buffer "5.1.2" - -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== - -convert-source-map@1.7.0, convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" - integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== - dependencies: - safe-buffer "~5.1.1" - -convert-source-map@^0.3.3: - version "0.3.5" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-0.3.5.tgz#f1d802950af7dd2631a1febe0596550c86ab3190" - integrity sha1-8dgClQr33SYxof6+BZZVDIarMZA= - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= - -cookie@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" - integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== - -copy-concurrently@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" - integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A== - dependencies: - aproba "^1.1.1" - fs-write-stream-atomic "^1.0.8" - iferr "^0.1.5" - mkdirp "^0.5.1" - rimraf "^2.5.4" - run-queue "^1.0.0" - -copy-descriptor@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= - -core-js-compat@^3.6.2, core-js-compat@^3.9.0, core-js-compat@^3.9.1: - version "3.12.1" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.12.1.tgz#2c302c4708505fa7072b0adb5156d26f7801a18b" - integrity sha512-i6h5qODpw6EsHAoIdQhKoZdWn+dGBF3dSS8m5tif36RlWvW3A6+yu2S16QHUo3CrkzrnEskMAt9f8FxmY9fhWQ== - dependencies: - browserslist "^4.16.6" - semver "7.0.0" - -core-js-pure@^3.0.0: - version "3.12.1" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.12.1.tgz#934da8b9b7221e2a2443dc71dfa5bd77a7ea00b8" - integrity sha512-1cch+qads4JnDSWsvc7d6nzlKAippwjUlf6vykkTLW53VSV+NkE6muGBToAjEA8pG90cSfcud3JgVmW2ds5TaQ== - -core-js@^2.4.0: - version "2.6.12" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" - integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== - -core-js@^3.6.5: - version "3.12.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.12.1.tgz#6b5af4ff55616c08a44d386f1f510917ff204112" - integrity sha512-Ne9DKPHTObRuB09Dru5AjwKjY4cJHVGu+y5f7coGn1E9Grkc3p2iBwE9AI/nJzsE29mQF7oq+mhYYRqOMFN1Bw== - -core-util-is@1.0.2, core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - -cosmiconfig@^5.0.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" - integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== - dependencies: - import-fresh "^2.0.0" - is-directory "^0.3.1" - js-yaml "^3.13.1" - parse-json "^4.0.0" - -cosmiconfig@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" - integrity sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg== - dependencies: - "@types/parse-json" "^4.0.0" - import-fresh "^3.1.0" - parse-json "^5.0.0" - path-type "^4.0.0" - yaml "^1.7.2" - -cosmiconfig@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.0.tgz#ef9b44d773959cae63ddecd122de23853b60f8d3" - integrity sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA== - dependencies: - "@types/parse-json" "^4.0.0" - import-fresh "^3.2.1" - parse-json "^5.0.0" - path-type "^4.0.0" - yaml "^1.10.0" - -create-ecdh@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" - integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== - dependencies: - bn.js "^4.1.0" - elliptic "^6.5.3" - -create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== - dependencies: - cipher-base "^1.0.1" - inherits "^2.0.1" - md5.js "^1.3.4" - ripemd160 "^2.0.1" - sha.js "^2.4.0" - -create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" - integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== - dependencies: - cipher-base "^1.0.3" - create-hash "^1.1.0" - inherits "^2.0.1" - ripemd160 "^2.0.0" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -cross-spawn@7.0.3, cross-spawn@^7.0.0, cross-spawn@^7.0.2: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -cross-spawn@^6.0.0: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - -crypto-browserify@^3.11.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== - dependencies: - browserify-cipher "^1.0.0" - browserify-sign "^4.0.0" - create-ecdh "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.0" - diffie-hellman "^5.0.0" - inherits "^2.0.1" - pbkdf2 "^3.0.3" - public-encrypt "^4.0.0" - randombytes "^2.0.0" - randomfill "^1.0.3" - -crypto-random-string@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" - integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4= - -css-blank-pseudo@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz#dfdefd3254bf8a82027993674ccf35483bfcb3c5" - integrity sha512-LHz35Hr83dnFeipc7oqFDmsjHdljj3TQtxGGiNWSOsTLIAubSm4TEz8qCaKFpk7idaQ1GfWscF4E6mgpBysA1w== - dependencies: - postcss "^7.0.5" - -css-color-names@0.0.4, css-color-names@^0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" - integrity sha1-gIrcLnnPhHOAabZGyyDsJ762KeA= - -css-declaration-sorter@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz#c198940f63a76d7e36c1e71018b001721054cb22" - integrity sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA== - dependencies: - postcss "^7.0.1" - timsort "^0.3.0" - -css-has-pseudo@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz#3c642ab34ca242c59c41a125df9105841f6966ee" - integrity sha512-Z8hnfsZu4o/kt+AuFzeGpLVhFOGO9mluyHBaA2bA8aCGTwah5sT3WV/fTHH8UNZUytOIImuGPrl/prlb4oX4qQ== - dependencies: - postcss "^7.0.6" - postcss-selector-parser "^5.0.0-rc.4" - -css-loader@4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-4.3.0.tgz#c888af64b2a5b2e85462c72c0f4a85c7e2e0821e" - integrity sha512-rdezjCjScIrsL8BSYszgT4s476IcNKt6yX69t0pHjJVnPUTDpn4WfIpDQTN3wCJvUvfsz/mFjuGOekf3PY3NUg== - dependencies: - camelcase "^6.0.0" - cssesc "^3.0.0" - icss-utils "^4.1.1" - loader-utils "^2.0.0" - postcss "^7.0.32" - postcss-modules-extract-imports "^2.0.0" - postcss-modules-local-by-default "^3.0.3" - postcss-modules-scope "^2.2.0" - postcss-modules-values "^3.0.0" - postcss-value-parser "^4.1.0" - schema-utils "^2.7.1" - semver "^7.3.2" - -css-prefers-color-scheme@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz#6f830a2714199d4f0d0d0bb8a27916ed65cff1f4" - integrity sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg== - dependencies: - postcss "^7.0.5" - -css-select-base-adapter@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" - integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== - -css-select@^2.0.0, css-select@^2.0.2: - version "2.1.0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.1.0.tgz#6a34653356635934a81baca68d0255432105dbef" - integrity sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ== - dependencies: - boolbase "^1.0.0" - css-what "^3.2.1" - domutils "^1.7.0" - nth-check "^1.0.2" - -css-tree@1.0.0-alpha.37: - version "1.0.0-alpha.37" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.37.tgz#98bebd62c4c1d9f960ec340cf9f7522e30709a22" - integrity sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg== - dependencies: - mdn-data "2.0.4" - source-map "^0.6.1" - -css-tree@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" - integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== - dependencies: - mdn-data "2.0.14" - source-map "^0.6.1" - -css-what@^3.2.1: - version "3.4.2" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.4.2.tgz#ea7026fcb01777edbde52124e21f327e7ae950e4" - integrity sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ== - -css.escape@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" - integrity sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s= - -css@^2.0.0: - version "2.2.4" - resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929" - integrity sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw== - dependencies: - inherits "^2.0.3" - source-map "^0.6.1" - source-map-resolve "^0.5.2" - urix "^0.1.0" - -css@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/css/-/css-3.0.0.tgz#4447a4d58fdd03367c516ca9f64ae365cee4aa5d" - integrity sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ== - dependencies: - inherits "^2.0.4" - source-map "^0.6.1" - source-map-resolve "^0.6.0" - -cssdb@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-4.4.0.tgz#3bf2f2a68c10f5c6a08abd92378331ee803cddb0" - integrity sha512-LsTAR1JPEM9TpGhl/0p3nQecC2LJ0kD8X5YARu1hk/9I1gril5vDtMZyNxcEpxxDj34YNck/ucjuoUd66K03oQ== - -cssesc@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" - integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg== - -cssesc@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" - integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== - -cssnano-preset-default@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.8.tgz#920622b1fc1e95a34e8838203f1397a504f2d3ff" - integrity sha512-LdAyHuq+VRyeVREFmuxUZR1TXjQm8QQU/ktoo/x7bz+SdOge1YKc5eMN6pRW7YWBmyq59CqYba1dJ5cUukEjLQ== - dependencies: - css-declaration-sorter "^4.0.1" - cssnano-util-raw-cache "^4.0.1" - postcss "^7.0.0" - postcss-calc "^7.0.1" - postcss-colormin "^4.0.3" - postcss-convert-values "^4.0.1" - postcss-discard-comments "^4.0.2" - postcss-discard-duplicates "^4.0.2" - postcss-discard-empty "^4.0.1" - postcss-discard-overridden "^4.0.1" - postcss-merge-longhand "^4.0.11" - postcss-merge-rules "^4.0.3" - postcss-minify-font-values "^4.0.2" - postcss-minify-gradients "^4.0.2" - postcss-minify-params "^4.0.2" - postcss-minify-selectors "^4.0.2" - postcss-normalize-charset "^4.0.1" - postcss-normalize-display-values "^4.0.2" - postcss-normalize-positions "^4.0.2" - postcss-normalize-repeat-style "^4.0.2" - postcss-normalize-string "^4.0.2" - postcss-normalize-timing-functions "^4.0.2" - postcss-normalize-unicode "^4.0.1" - postcss-normalize-url "^4.0.1" - postcss-normalize-whitespace "^4.0.2" - postcss-ordered-values "^4.1.2" - postcss-reduce-initial "^4.0.3" - postcss-reduce-transforms "^4.0.2" - postcss-svgo "^4.0.3" - postcss-unique-selectors "^4.0.1" - -cssnano-util-get-arguments@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz#ed3a08299f21d75741b20f3b81f194ed49cc150f" - integrity sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8= - -cssnano-util-get-match@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz#c0e4ca07f5386bb17ec5e52250b4f5961365156d" - integrity sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0= - -cssnano-util-raw-cache@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz#b26d5fd5f72a11dfe7a7846fb4c67260f96bf282" - integrity sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA== - dependencies: - postcss "^7.0.0" - -cssnano-util-same-parent@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz#574082fb2859d2db433855835d9a8456ea18bbf3" - integrity sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q== - -cssnano@^4.1.10: - version "4.1.11" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.1.11.tgz#c7b5f5b81da269cb1fd982cb960c1200910c9a99" - integrity sha512-6gZm2htn7xIPJOHY824ERgj8cNPgPxyCSnkXc4v7YvNW+TdVfzgngHcEhy/8D11kUWRUMbke+tC+AUcUsnMz2g== - dependencies: - cosmiconfig "^5.0.0" - cssnano-preset-default "^4.0.8" - is-resolvable "^1.0.0" - postcss "^7.0.0" - -csso@^4.0.2: - version "4.2.0" - resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" - integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA== - dependencies: - css-tree "^1.1.2" - -cssom@^0.4.4: - version "0.4.4" - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" - integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw== - -cssom@~0.3.6: - version "0.3.8" - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" - integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== - -cssstyle@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" - integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== - dependencies: - cssom "~0.3.6" - -csstype@^3.0.2: - version "3.0.8" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.8.tgz#d2266a792729fb227cd216fb572f43728e1ad340" - integrity sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw== - -cyclist@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" - integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= - -d@1, d@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" - integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== - dependencies: - es5-ext "^0.10.50" - type "^1.0.1" - -damerau-levenshtein@^1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz#64368003512a1a6992593741a09a9d31a836f55d" - integrity sha512-VvdQIPGdWP0SqFXghj79Wf/5LArmreyMsGLa6FG6iC4t3j7j5s71TrwWmT/4akbDQIqjfACkLZmjXhA7g2oUZw== - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= - dependencies: - assert-plus "^1.0.0" - -data-urls@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" - integrity sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ== - dependencies: - abab "^2.0.3" - whatwg-mimetype "^2.3.0" - whatwg-url "^8.0.0" - -debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@^3.1.1, debug@^3.2.6, debug@^3.2.7: - version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - -debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" - integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== - dependencies: - ms "2.1.2" - -decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= - -decimal.js@^10.2.1: - version "10.2.1" - resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.1.tgz#238ae7b0f0c793d3e3cea410108b35a2c01426a3" - integrity sha512-KaL7+6Fw6i5A2XSnsbhm/6B+NuEA7TZ4vqxnd5tXz9sbKtrN9Srj8ab4vKVdK8YAqZO9P1kg45Y6YLoduPf+kw== - -decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= - -dedent@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" - integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= - -deep-equal@^1.0.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" - integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== - dependencies: - is-arguments "^1.0.4" - is-date-object "^1.0.1" - is-regex "^1.0.4" - object-is "^1.0.1" - object-keys "^1.1.1" - regexp.prototype.flags "^1.2.0" - -deep-is@^0.1.3, deep-is@~0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" - integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= - -deepmerge@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" - integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== - -default-gateway@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b" - integrity sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA== - dependencies: - execa "^1.0.0" - ip-regex "^2.1.0" - -define-properties@^1.1.2, define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== - dependencies: - object-keys "^1.0.12" - -define-property@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= - dependencies: - is-descriptor "^0.1.0" - -define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= - dependencies: - is-descriptor "^1.0.0" - -define-property@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== - dependencies: - is-descriptor "^1.0.2" - isobject "^3.0.1" - -del@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4" - integrity sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ== - dependencies: - "@types/glob" "^7.1.1" - globby "^6.1.0" - is-path-cwd "^2.0.0" - is-path-in-cwd "^2.0.0" - p-map "^2.0.0" - pify "^4.0.1" - rimraf "^2.6.3" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= - -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= - -des.js@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" - integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== - dependencies: - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= - -detect-newline@^3.0.0: - version "3.1.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: - version "2.1.0" - resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" - integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== - -detect-port-alt@1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/detect-port-alt/-/detect-port-alt-1.1.6.tgz#24707deabe932d4a3cf621302027c2b266568275" - integrity sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q== - dependencies: - address "^1.0.1" - debug "^2.6.0" - -diff-sequences@^26.6.2: - version "26.6.2" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.6.2.tgz#48ba99157de1923412eed41db6b6d4aa9ca7c0b1" - integrity sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q== - -diffie-hellman@^5.0.0: - version "5.0.3" - resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" - integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== - dependencies: - bn.js "^4.1.0" - miller-rabin "^4.0.0" - randombytes "^2.0.0" - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -dns-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" - integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0= - -dns-packet@^1.3.1: - version "1.3.4" - resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.4.tgz#e3455065824a2507ba886c55a89963bb107dec6f" - integrity sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA== - dependencies: - ip "^1.1.0" - safe-buffer "^5.0.1" - -dns-txt@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/dns-txt/-/dns-txt-2.0.2.tgz#b91d806f5d27188e4ab3e7d107d881a1cc4642b6" - integrity sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY= - dependencies: - buffer-indexof "^1.0.0" - -doctrine@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" - integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== - dependencies: - esutils "^2.0.2" - -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - -dom-accessibility-api@^0.5.4: - version "0.5.4" - resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.4.tgz#b06d059cdd4a4ad9a79275f9d414a5c126241166" - integrity sha512-TvrjBckDy2c6v6RLxPv5QXOnU+SmF9nBII5621Ve5fu6Z/BDrENurBEvlC1f44lKEUVqOpK4w9E5Idc5/EgkLQ== - -dom-converter@^0.2: - version "0.2.0" - resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" - integrity sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA== - dependencies: - utila "~0.4" - -dom-helpers@^5.0.1, dom-helpers@^5.1.2, dom-helpers@^5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902" - integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA== - dependencies: - "@babel/runtime" "^7.8.7" - csstype "^3.0.2" - -dom-serializer@0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" - integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== - dependencies: - domelementtype "^2.0.1" - entities "^2.0.0" - -domain-browser@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" - integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== - -domelementtype@1, domelementtype@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" - integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== - -domelementtype@^2.0.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57" - integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A== - -domexception@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" - integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg== - dependencies: - webidl-conversions "^5.0.0" - -domhandler@^2.3.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" - integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== - dependencies: - domelementtype "1" - -domutils@^1.5.1, domutils@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" - integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== - dependencies: - dom-serializer "0" - domelementtype "1" - -dot-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" - integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== - dependencies: - no-case "^3.0.4" - tslib "^2.0.3" - -dot-prop@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" - integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== - dependencies: - is-obj "^2.0.0" - -dotenv-expand@5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0" - integrity sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA== - -dotenv@8.2.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a" - integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw== - -duplexer@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" - integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== - -duplexify@^3.4.2, duplexify@^3.6.0: - version "3.7.1" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" - integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== - dependencies: - end-of-stream "^1.0.0" - inherits "^2.0.1" - readable-stream "^2.0.0" - stream-shift "^1.0.0" - -ecc-jsbn@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= - dependencies: - jsbn "~0.1.0" - safer-buffer "^2.1.0" - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= - -ejs@^2.6.1: - version "2.7.4" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba" - integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== - -electron-to-chromium@^1.3.564, electron-to-chromium@^1.3.723: - version "1.3.735" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.735.tgz#fa1a8660f2790662291cb2136f0e446a444cdfdc" - integrity sha512-cp7MWzC3NseUJV2FJFgaiesdrS+A8ZUjX5fLAxdRlcaPDkaPGFplX930S5vf84yqDp4LjuLdKouWuVOTwUfqHQ== - -elliptic@^6.5.3: - version "6.5.4" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" - integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== - dependencies: - bn.js "^4.11.9" - brorand "^1.1.0" - hash.js "^1.0.0" - hmac-drbg "^1.0.1" - inherits "^2.0.4" - minimalistic-assert "^1.0.1" - minimalistic-crypto-utils "^1.0.1" - -emittery@^0.7.1: - version "0.7.2" - resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.7.2.tgz#25595908e13af0f5674ab419396e2fb394cdfa82" - integrity sha512-A8OG5SR/ij3SsJdWDJdkkSYUjQdCUx6APQXem0SaEePBSRg4eymGYwBkKo1Y6DU+af/Jn2dBQqDBvjnr9Vi8nQ== - -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -emoji-regex@^9.0.0: - version "9.2.2" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" - integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== - -emojis-list@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" - integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= - -emojis-list@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" - integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== - -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= - -end-of-stream@^1.0.0, end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - -enhanced-resolve@^4.3.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec" - integrity sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg== - dependencies: - graceful-fs "^4.1.2" - memory-fs "^0.5.0" - tapable "^1.0.0" - -enquirer@^2.3.5: - version "2.3.6" - resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" - integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== - dependencies: - ansi-colors "^4.1.1" - -entities@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" - integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== - -entities@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" - integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== - -errno@^0.1.3, errno@~0.1.7: - version "0.1.8" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" - integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== - dependencies: - prr "~1.0.1" - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -error-stack-parser@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.0.6.tgz#5a99a707bd7a4c58a797902d48d82803ede6aad8" - integrity sha512-d51brTeqC+BHlwF0BhPtcYgF5nlzf9ZZ0ZIUQNZpc9ZB9qw5IJ2diTrBY9jlCJkTLITYPjmiX6OWCwH+fuyNgQ== - dependencies: - stackframe "^1.1.1" - -es-abstract@^1.17.2, es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2: - version "1.18.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0.tgz#ab80b359eecb7ede4c298000390bc5ac3ec7b5a4" - integrity sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw== - dependencies: - call-bind "^1.0.2" - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - get-intrinsic "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.2" - is-callable "^1.2.3" - is-negative-zero "^2.0.1" - is-regex "^1.1.2" - is-string "^1.0.5" - object-inspect "^1.9.0" - object-keys "^1.1.1" - object.assign "^4.1.2" - string.prototype.trimend "^1.0.4" - string.prototype.trimstart "^1.0.4" - unbox-primitive "^1.0.0" - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -es5-ext@^0.10.35, es5-ext@^0.10.50: - version "0.10.53" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1" - integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== - dependencies: - es6-iterator "~2.0.3" - es6-symbol "~3.1.3" - next-tick "~1.0.0" - -es6-iterator@2.0.3, es6-iterator@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" - integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= - dependencies: - d "1" - es5-ext "^0.10.35" - es6-symbol "^3.1.1" - -es6-symbol@^3.1.1, es6-symbol@~3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" - integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== - dependencies: - d "^1.0.1" - ext "^1.1.2" - -escalade@^3.0.2, escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= - -escape-string-regexp@2.0.0, escape-string-regexp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" - integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -escodegen@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd" - integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw== - dependencies: - esprima "^4.0.1" - estraverse "^5.2.0" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.6.1" - -eslint-config-prettier@^8.3.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz#f7471b20b6fe8a9a9254cc684454202886a2dd7a" - integrity sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew== - -eslint-config-react-app@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/eslint-config-react-app/-/eslint-config-react-app-6.0.0.tgz#ccff9fc8e36b322902844cbd79197982be355a0e" - integrity sha512-bpoAAC+YRfzq0dsTk+6v9aHm/uqnDwayNAXleMypGl6CpxI9oXXscVHo4fk3eJPIn+rsbtNetB4r/ZIidFIE8A== - dependencies: - confusing-browser-globals "^1.0.10" - -eslint-import-resolver-node@^0.3.4: - version "0.3.4" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz#85ffa81942c25012d8231096ddf679c03042c717" - integrity sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA== - dependencies: - debug "^2.6.9" - resolve "^1.13.1" - -eslint-module-utils@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.1.tgz#b51be1e473dd0de1c5ea638e22429c2490ea8233" - integrity sha512-ZXI9B8cxAJIH4nfkhTwcRTEAnrVfobYqwjWy/QMCZ8rHkZHFjf9yO4BzpiF9kCSfNlMG54eKigISHpX0+AaT4A== - dependencies: - debug "^3.2.7" - pkg-dir "^2.0.0" - -eslint-plugin-flowtype@^5.2.0: - version "5.7.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-5.7.2.tgz#482a42fe5d15ee614652ed256d37543d584d7bc0" - integrity sha512-7Oq/N0+3nijBnYWQYzz/Mp/7ZCpwxYvClRyW/PLAmimY9uLCBvoXsNsERcJdkKceyOjgRbFhhxs058KTrne9Mg== - dependencies: - lodash "^4.17.15" - string-natural-compare "^3.0.1" - -eslint-plugin-import@^2.22.1: - version "2.23.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.23.3.tgz#8a1b073289fff03c4af0f04b6df956b7d463e191" - integrity sha512-wDxdYbSB55F7T5CC7ucDjY641VvKmlRwT0Vxh7PkY1mI4rclVRFWYfsrjDgZvwYYDZ5ee0ZtfFKXowWjqvEoRQ== - dependencies: - array-includes "^3.1.3" - array.prototype.flat "^1.2.4" - debug "^2.6.9" - doctrine "^2.1.0" - eslint-import-resolver-node "^0.3.4" - eslint-module-utils "^2.6.1" - find-up "^2.0.0" - has "^1.0.3" - is-core-module "^2.4.0" - minimatch "^3.0.4" - object.values "^1.1.3" - pkg-up "^2.0.0" - read-pkg-up "^3.0.0" - resolve "^1.20.0" - tsconfig-paths "^3.9.0" - -eslint-plugin-jest@^24.1.0: - version "24.3.6" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-24.3.6.tgz#5f0ca019183c3188c5ad3af8e80b41de6c8e9173" - integrity sha512-WOVH4TIaBLIeCX576rLcOgjNXqP+jNlCiEmRgFTfQtJ52DpwnIQKAVGlGPAN7CZ33bW6eNfHD6s8ZbEUTQubJg== - dependencies: - "@typescript-eslint/experimental-utils" "^4.0.1" - -eslint-plugin-jsx-a11y@^6.3.1: - version "6.4.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.4.1.tgz#a2d84caa49756942f42f1ffab9002436391718fd" - integrity sha512-0rGPJBbwHoGNPU73/QCLP/vveMlM1b1Z9PponxO87jfr6tuH5ligXbDT6nHSSzBC8ovX2Z+BQu7Bk5D/Xgq9zg== - dependencies: - "@babel/runtime" "^7.11.2" - aria-query "^4.2.2" - array-includes "^3.1.1" - ast-types-flow "^0.0.7" - axe-core "^4.0.2" - axobject-query "^2.2.0" - damerau-levenshtein "^1.0.6" - emoji-regex "^9.0.0" - has "^1.0.3" - jsx-ast-utils "^3.1.0" - language-tags "^1.0.5" - -eslint-plugin-prettier@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.0.tgz#cdbad3bf1dbd2b177e9825737fe63b476a08f0c7" - integrity sha512-UDK6rJT6INSfcOo545jiaOwB701uAIt2/dR7WnFQoGCVl1/EMqdANBmwUaqqQ45aXprsTGzSa39LI1PyuRBxxw== - dependencies: - prettier-linter-helpers "^1.0.0" - -eslint-plugin-react-hooks@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz#8c229c268d468956334c943bb45fc860280f5556" - integrity sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ== - -eslint-plugin-react@^7.21.5: - version "7.23.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.23.2.tgz#2d2291b0f95c03728b55869f01102290e792d494" - integrity sha512-AfjgFQB+nYszudkxRkTFu0UR1zEQig0ArVMPloKhxwlwkzaw/fBiH0QWcBBhZONlXqQC51+nfqFrkn4EzHcGBw== - dependencies: - array-includes "^3.1.3" - array.prototype.flatmap "^1.2.4" - doctrine "^2.1.0" - has "^1.0.3" - jsx-ast-utils "^2.4.1 || ^3.0.0" - minimatch "^3.0.4" - object.entries "^1.1.3" - object.fromentries "^2.0.4" - object.values "^1.1.3" - prop-types "^15.7.2" - resolve "^2.0.0-next.3" - string.prototype.matchall "^4.0.4" - -eslint-plugin-testing-library@^3.9.2: - version "3.10.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-testing-library/-/eslint-plugin-testing-library-3.10.2.tgz#609ec2b0369da7cf2e6d9edff5da153cc31d87bd" - integrity sha512-WAmOCt7EbF1XM8XfbCKAEzAPnShkNSwcIsAD2jHdsMUT9mZJPjLCG7pMzbcC8kK366NOuGip8HKLDC+Xk4yIdA== - dependencies: - "@typescript-eslint/experimental-utils" "^3.10.1" - -eslint-scope@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" - integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== - dependencies: - esrecurse "^4.1.0" - estraverse "^4.1.1" - -eslint-scope@^5.0.0, eslint-scope@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" - -eslint-utils@^2.0.0, eslint-utils@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" - integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== - dependencies: - eslint-visitor-keys "^1.1.0" - -eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" - integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== - -eslint-visitor-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" - integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== - -eslint-webpack-plugin@^2.5.2: - version "2.5.4" - resolved "https://registry.yarnpkg.com/eslint-webpack-plugin/-/eslint-webpack-plugin-2.5.4.tgz#473b84932f1a8e2c2b8e66a402d0497bf440b986" - integrity sha512-7rYh0m76KyKSDE+B+2PUQrlNS4HJ51t3WKpkJg6vo2jFMbEPTG99cBV0Dm7LXSHucN4WGCG65wQcRiTFrj7iWw== - dependencies: - "@types/eslint" "^7.2.6" - arrify "^2.0.1" - jest-worker "^26.6.2" - micromatch "^4.0.2" - normalize-path "^3.0.0" - schema-utils "^3.0.0" - -eslint@^7.11.0: - version "7.27.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.27.0.tgz#665a1506d8f95655c9274d84bd78f7166b07e9c7" - integrity sha512-JZuR6La2ZF0UD384lcbnd0Cgg6QJjiCwhMD6eU4h/VGPcVGwawNNzKU41tgokGXnfjOOyI6QIffthhJTPzzuRA== - dependencies: - "@babel/code-frame" "7.12.11" - "@eslint/eslintrc" "^0.4.1" - ajv "^6.10.0" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.0.1" - doctrine "^3.0.0" - enquirer "^2.3.5" - escape-string-regexp "^4.0.0" - eslint-scope "^5.1.1" - eslint-utils "^2.1.0" - eslint-visitor-keys "^2.0.0" - espree "^7.3.1" - esquery "^1.4.0" - esutils "^2.0.2" - fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" - functional-red-black-tree "^1.0.1" - glob-parent "^5.0.0" - globals "^13.6.0" - ignore "^4.0.6" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - js-yaml "^3.13.1" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash.merge "^4.6.2" - minimatch "^3.0.4" - natural-compare "^1.4.0" - optionator "^0.9.1" - progress "^2.0.0" - regexpp "^3.1.0" - semver "^7.2.1" - strip-ansi "^6.0.0" - strip-json-comments "^3.1.0" - table "^6.0.9" - text-table "^0.2.0" - v8-compile-cache "^2.0.3" - -espree@^7.3.0, espree@^7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" - integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== - dependencies: - acorn "^7.4.0" - acorn-jsx "^5.3.1" - eslint-visitor-keys "^1.3.0" - -esprima@^4.0.0, esprima@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esquery@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" - integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.1.0, esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.1.0, estraverse@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" - integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== - -estree-walker@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362" - integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w== - -estree-walker@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" - integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= - -eventemitter3@^4.0.0: - version "4.0.7" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" - integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== - -events@^3.0.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" - integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== - -eventsource@^1.0.7: - version "1.1.0" - resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-1.1.0.tgz#00e8ca7c92109e94b0ddf32dac677d841028cfaf" - integrity sha512-VSJjT5oCNrFvCS6igjzPAt5hBzQ2qPBFIbJ03zLI9SE0mxwZpMw6BfJrbFHm1a141AavMEB8JHmBhWAd66PfCg== - dependencies: - original "^1.0.0" - -evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== - dependencies: - md5.js "^1.3.4" - safe-buffer "^5.1.1" - -exec-sh@^0.3.2: - version "0.3.6" - resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.6.tgz#ff264f9e325519a60cb5e273692943483cca63bc" - integrity sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w== - -execa@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" - integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== - dependencies: - cross-spawn "^6.0.0" - get-stream "^4.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - -execa@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" - integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA== - dependencies: - cross-spawn "^7.0.0" - get-stream "^5.0.0" - human-signals "^1.1.1" - is-stream "^2.0.0" - merge-stream "^2.0.0" - npm-run-path "^4.0.0" - onetime "^5.1.0" - signal-exit "^3.0.2" - strip-final-newline "^2.0.0" - -exit@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" - integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= - -expand-brackets@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= - dependencies: - debug "^2.3.3" - define-property "^0.2.5" - extend-shallow "^2.0.1" - posix-character-classes "^0.1.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -expect@^26.6.0, expect@^26.6.2: - version "26.6.2" - resolved "https://registry.yarnpkg.com/expect/-/expect-26.6.2.tgz#c6b996bf26bf3fe18b67b2d0f51fc981ba934417" - integrity sha512-9/hlOBkQl2l/PLHJx6JjoDF6xPKcJEsUlWKb23rKE7KzeDqUZKXKNMW27KIue5JMdBV9HgmoJPcc8HtO85t9IA== - dependencies: - "@jest/types" "^26.6.2" - ansi-styles "^4.0.0" - jest-get-type "^26.3.0" - jest-matcher-utils "^26.6.2" - jest-message-util "^26.6.2" - jest-regex-util "^26.0.0" - -express@^4.17.1: - version "4.17.1" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" - integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== - dependencies: - accepts "~1.3.7" - array-flatten "1.1.1" - body-parser "1.19.0" - content-disposition "0.5.3" - content-type "~1.0.4" - cookie "0.4.0" - cookie-signature "1.0.6" - debug "2.6.9" - depd "~1.1.2" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "~1.1.2" - fresh "0.5.2" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "~2.3.0" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.5" - qs "6.7.0" - range-parser "~1.2.1" - safe-buffer "5.1.2" - send "0.17.1" - serve-static "1.14.1" - setprototypeof "1.1.1" - statuses "~1.5.0" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - -ext@^1.1.2: - version "1.4.0" - resolved "https://registry.yarnpkg.com/ext/-/ext-1.4.0.tgz#89ae7a07158f79d35517882904324077e4379244" - integrity sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A== - dependencies: - type "^2.0.0" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= - dependencies: - is-extendable "^0.1.0" - -extend-shallow@^3.0.0, extend-shallow@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= - dependencies: - assign-symbols "^1.0.0" - is-extendable "^1.0.1" - -extend@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -extglob@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= - -extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-diff@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" - integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== - -fast-glob@^3.1.1: - version "3.2.5" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.5.tgz#7939af2a656de79a4f1901903ee8adcaa7cb9661" - integrity sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.0" - merge2 "^1.3.0" - micromatch "^4.0.2" - picomatch "^2.2.1" - -fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= - -fastq@^1.6.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.11.0.tgz#bb9fb955a07130a918eb63c1f5161cc32a5d0858" - integrity sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g== - dependencies: - reusify "^1.0.4" - -faye-websocket@^0.11.3: - version "0.11.3" - resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.3.tgz#5c0e9a8968e8912c286639fde977a8b209f2508e" - integrity sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA== - dependencies: - websocket-driver ">=0.5.1" - -fb-watchman@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" - integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg== - dependencies: - bser "2.1.1" - -figgy-pudding@^3.5.1: - version "3.5.2" - resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" - integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw== - -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== - dependencies: - flat-cache "^3.0.4" - -file-loader@6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.1.1.tgz#a6f29dfb3f5933a1c350b2dbaa20ac5be0539baa" - integrity sha512-Klt8C4BjWSXYQAfhpYYkG4qHNTna4toMHEbWrI5IuVoxbU6uiDKeKAP99R8mmbJi3lvewn/jQBOgU4+NS3tDQw== - dependencies: - loader-utils "^2.0.0" - schema-utils "^3.0.0" - -file-uri-to-path@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" - integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== - -filesize@6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/filesize/-/filesize-6.1.0.tgz#e81bdaa780e2451d714d71c0d7a4f3238d37ad00" - integrity sha512-LpCHtPQ3sFx67z+uh2HnSyWSLLu5Jxo21795uRDuar/EOuYWXib5EmPaGIBuSnRqH2IODiKA2k5re/K9OnN/Yg== - -fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= - dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -finalhandler@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.3" - statuses "~1.5.0" - unpipe "~1.0.0" - -find-cache-dir@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" - integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== - dependencies: - commondir "^1.0.1" - make-dir "^2.0.0" - pkg-dir "^3.0.0" - -find-cache-dir@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" - integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== - dependencies: - commondir "^1.0.1" - make-dir "^3.0.2" - pkg-dir "^4.1.0" - -find-up@4.1.0, find-up@^4.0.0, find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -find-up@^2.0.0, find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= - dependencies: - locate-path "^2.0.0" - -find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - -flat-cache@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" - integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== - dependencies: - flatted "^3.1.0" - rimraf "^3.0.2" - -flatted@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469" - integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA== - -flatten@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b" - integrity sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg== - -flush-write-stream@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" - integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w== - dependencies: - inherits "^2.0.3" - readable-stream "^2.3.6" - -follow-redirects@^1.0.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.1.tgz#d9114ded0a1cfdd334e164e6662ad02bfd91ff43" - integrity sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg== - -for-in@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= - -fork-ts-checker-webpack-plugin@4.1.6: - version "4.1.6" - resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-4.1.6.tgz#5055c703febcf37fa06405d400c122b905167fc5" - integrity sha512-DUxuQaKoqfNne8iikd14SAkh5uw4+8vNifp6gmA73yYNS6ywLIWSLD/n/mBzHQRpW3J7rbATEakmiA8JvkTyZw== - dependencies: - "@babel/code-frame" "^7.5.5" - chalk "^2.4.1" - micromatch "^3.1.10" - minimatch "^3.0.4" - semver "^5.6.0" - tapable "^1.0.0" - worker-rpc "^0.1.0" - -form-data@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" - integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - -forwarded@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" - integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= - -fragment-cache@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= - dependencies: - map-cache "^0.2.2" - -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= - -from2@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" - integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= - dependencies: - inherits "^2.0.1" - readable-stream "^2.0.0" - -fs-extra@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" - integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs-extra@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" - integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs-extra@^9.0.1: - version "9.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" - integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== - dependencies: - at-least-node "^1.0.0" - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - -fs-minipass@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" - integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== - dependencies: - minipass "^3.0.0" - -fs-write-stream-atomic@^1.0.8: - version "1.0.10" - resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" - integrity sha1-tH31NJPvkR33VzHnCp3tAYnbQMk= - dependencies: - graceful-fs "^4.1.2" - iferr "^0.1.5" - imurmurhash "^0.1.4" - readable-stream "1 || 2" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -fsevents@^1.2.7: - version "1.2.13" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" - integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== - dependencies: - bindings "^1.5.0" - nan "^2.12.1" - -fsevents@^2.1.2, fsevents@^2.1.3, fsevents@~2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -functional-red-black-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= - -gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2: - version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" - integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== - -get-caller-file@^2.0.1: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" - integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - -get-own-enumerable-property-symbols@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" - integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g== - -get-package-type@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" - integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== - -get-stream@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" - -get-stream@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" - integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== - dependencies: - pump "^3.0.0" - -get-value@^2.0.3, get-value@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= - dependencies: - assert-plus "^1.0.0" - -glob-parent@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - -glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@~5.1.0: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: - version "7.1.7" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" - integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -global-modules@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" - integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== - dependencies: - global-prefix "^3.0.0" - -global-prefix@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" - integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== - dependencies: - ini "^1.3.5" - kind-of "^6.0.2" - which "^1.3.1" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globals@^12.1.0: - version "12.4.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8" - integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== - dependencies: - type-fest "^0.8.1" - -globals@^13.6.0: - version "13.8.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.8.0.tgz#3e20f504810ce87a8d72e55aecf8435b50f4c1b3" - integrity sha512-rHtdA6+PDBIjeEvA91rpqzEvk/k3/i7EeNQiryiWuJH0Hw9cpyJMAt2jtbAwUaRdhD+573X4vWw6IcjKPasi9Q== - dependencies: - type-fest "^0.20.2" - -globby@11.0.1: - version "11.0.1" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.1.tgz#9a2bf107a068f3ffeabc49ad702c79ede8cfd357" - integrity sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.1.1" - ignore "^5.1.4" - merge2 "^1.3.0" - slash "^3.0.0" - -globby@^11.0.1: - version "11.0.3" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.3.tgz#9b1f0cb523e171dd1ad8c7b2a9fb4b644b9593cb" - integrity sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.1.1" - ignore "^5.1.4" - merge2 "^1.3.0" - slash "^3.0.0" - -globby@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" - integrity sha1-9abXDoOV4hyFj7BInWTfAkJNUGw= - dependencies: - array-union "^1.0.1" - glob "^7.0.3" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4: - version "4.2.6" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" - integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== - -growly@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" - integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= - -gzip-size@5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274" - integrity sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA== - dependencies: - duplexer "^0.1.1" - pify "^4.0.1" - -handle-thing@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" - integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== - -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= - -har-validator@~5.1.3: - version "5.1.5" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" - integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== - dependencies: - ajv "^6.12.3" - har-schema "^2.0.0" - -harmony-reflect@^1.4.6: - version "1.6.2" - resolved "https://registry.yarnpkg.com/harmony-reflect/-/harmony-reflect-1.6.2.tgz#31ecbd32e648a34d030d86adb67d4d47547fe710" - integrity sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g== - -has-bigints@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" - integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-symbols@^1.0.1, has-symbols@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" - integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== - -has-value@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= - dependencies: - get-value "^2.0.3" - has-values "^0.1.4" - isobject "^2.0.0" - -has-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= - dependencies: - get-value "^2.0.6" - has-values "^1.0.0" - isobject "^3.0.0" - -has-values@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= - -has-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - -has@^1.0.0, has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -hash-base@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" - integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== - dependencies: - inherits "^2.0.4" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" - -hash.js@^1.0.0, hash.js@^1.0.3: - version "1.1.7" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" - integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.1" - -he@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== - -hex-color-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" - integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== - -history@^4.9.0: - version "4.10.1" - resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3" - integrity sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew== - dependencies: - "@babel/runtime" "^7.1.2" - loose-envify "^1.2.0" - resolve-pathname "^3.0.0" - tiny-invariant "^1.0.2" - tiny-warning "^1.0.0" - value-equal "^1.0.1" - -hmac-drbg@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= - dependencies: - hash.js "^1.0.3" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.1" - -hoist-non-react-statics@^3.1.0: - version "3.3.2" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" - integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== - dependencies: - react-is "^16.7.0" - -hoopy@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d" - integrity sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ== - -hosted-git-info@^2.1.4: - version "2.8.9" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" - integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== - -hpack.js@^2.1.6: - version "2.1.6" - resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" - integrity sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI= - dependencies: - inherits "^2.0.1" - obuf "^1.0.0" - readable-stream "^2.0.1" - wbuf "^1.1.0" - -hsl-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e" - integrity sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4= - -hsla-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" - integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg= - -html-encoding-sniffer@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" - integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ== - dependencies: - whatwg-encoding "^1.0.5" - -html-entities@^1.2.1, html-entities@^1.3.1: - version "1.4.0" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.4.0.tgz#cfbd1b01d2afaf9adca1b10ae7dffab98c71d2dc" - integrity sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA== - -html-escaper@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" - integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== - -html-minifier-terser@^5.0.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#922e96f1f3bb60832c2634b79884096389b1f054" - integrity sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg== - dependencies: - camel-case "^4.1.1" - clean-css "^4.2.3" - commander "^4.1.1" - he "^1.2.0" - param-case "^3.0.3" - relateurl "^0.2.7" - terser "^4.6.3" - -html-webpack-plugin@4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.5.0.tgz#625097650886b97ea5dae331c320e3238f6c121c" - integrity sha512-MouoXEYSjTzCrjIxWwg8gxL5fE2X2WZJLmBYXlaJhQUH5K/b5OrqmV7T4dB7iu0xkmJ6JlUuV6fFVtnqbPopZw== - dependencies: - "@types/html-minifier-terser" "^5.0.0" - "@types/tapable" "^1.0.5" - "@types/webpack" "^4.41.8" - html-minifier-terser "^5.0.1" - loader-utils "^1.2.3" - lodash "^4.17.15" - pretty-error "^2.1.1" - tapable "^1.1.3" - util.promisify "1.0.0" - -htmlparser2@^3.10.1: - version "3.10.1" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" - integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== - dependencies: - domelementtype "^1.3.1" - domhandler "^2.3.0" - domutils "^1.5.1" - entities "^1.1.1" - inherits "^2.0.1" - readable-stream "^3.1.1" - -http-deceiver@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" - integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc= - -http-errors@1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" - integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -http-errors@~1.6.2: - version "1.6.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.0" - statuses ">= 1.4.0 < 2" - -http-errors@~1.7.2: - version "1.7.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" - integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -http-parser-js@>=0.5.1: - version "0.5.3" - resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.3.tgz#01d2709c79d41698bb01d4decc5e9da4e4a033d9" - integrity sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg== - -http-proxy-middleware@0.19.1: - version "0.19.1" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a" - integrity sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q== - dependencies: - http-proxy "^1.17.0" - is-glob "^4.0.0" - lodash "^4.17.11" - micromatch "^3.1.10" - -http-proxy@^1.17.0: - version "1.18.1" - resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" - integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== - dependencies: - eventemitter3 "^4.0.0" - follow-redirects "^1.0.0" - requires-port "^1.0.0" - -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -https-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" - integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= - -human-signals@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" - integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== - -iconv-lite@0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -icss-utils@^4.0.0, icss-utils@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467" - integrity sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA== - dependencies: - postcss "^7.0.14" - -identity-obj-proxy@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz#94d2bda96084453ef36fbc5aaec37e0f79f1fc14" - integrity sha1-lNK9qWCERT7zb7xarsN+D3nx/BQ= - dependencies: - harmony-reflect "^1.4.6" - -ieee754@^1.1.4: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - -iferr@^0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" - integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= - -ignore@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" - integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== - -ignore@^5.1.4: - version "5.1.8" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" - integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== - -immer@8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/immer/-/immer-8.0.1.tgz#9c73db683e2b3975c424fb0572af5889877ae656" - integrity sha512-aqXhGP7//Gui2+UrEtvxZxSquQVXTpZ7KDxfCcKAF3Vysvw0CViVaW9RZ1j1xlIYqaaaipBoqdqeibkc18PNvA== - -import-cwd@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9" - integrity sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk= - dependencies: - import-from "^2.1.0" - -import-fresh@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" - integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= - dependencies: - caller-path "^2.0.0" - resolve-from "^3.0.0" - -import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -import-from@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1" - integrity sha1-M1238qev/VOqpHHUuAId7ja387E= - dependencies: - resolve-from "^3.0.0" - -import-local@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" - integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== - dependencies: - pkg-dir "^3.0.0" - resolve-cwd "^2.0.0" - -import-local@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.2.tgz#a8cfd0431d1de4a2199703d003e3e62364fa6db6" - integrity sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA== - dependencies: - pkg-dir "^4.2.0" - resolve-cwd "^3.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= - -indent-string@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" - integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== - -indexes-of@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" - integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= - -infer-owner@^1.0.3, infer-owner@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" - integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -inherits@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" - integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= - -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - -ini@^1.3.5: - version "1.3.8" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" - integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== - -internal-ip@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907" - integrity sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg== - dependencies: - default-gateway "^4.2.0" - ipaddr.js "^1.9.0" - -internal-slot@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" - integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== - dependencies: - get-intrinsic "^1.1.0" - has "^1.0.3" - side-channel "^1.0.4" - -invariant@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - -ip-regex@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" - integrity sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk= - -ip@^1.1.0, ip@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" - integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= - -ipaddr.js@1.9.1, ipaddr.js@^1.9.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" - integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== - -is-absolute-url@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" - integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY= - -is-absolute-url@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698" - integrity sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q== - -is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= - dependencies: - kind-of "^3.0.2" - -is-accessor-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== - dependencies: - kind-of "^6.0.0" - -is-arguments@^1.0.4: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.0.tgz#62353031dfbee07ceb34656a6bde59efecae8dd9" - integrity sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg== - dependencies: - call-bind "^1.0.0" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= - -is-arrayish@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" - integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== - -is-bigint@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.2.tgz#ffb381442503235ad245ea89e45b3dbff040ee5a" - integrity sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA== - -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= - dependencies: - binary-extensions "^1.0.0" - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-boolean-object@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.1.tgz#3c0878f035cb821228d350d2e1e36719716a3de8" - integrity sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng== - dependencies: - call-bind "^1.0.2" - -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - -is-callable@^1.1.4, is-callable@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.3.tgz#8b1e0500b73a1d76c70487636f368e519de8db8e" - integrity sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ== - -is-ci@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" - integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== - dependencies: - ci-info "^2.0.0" - -is-color-stop@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" - integrity sha1-z/9HGu5N1cnhWFmPvhKWe1za00U= - dependencies: - css-color-names "^0.0.4" - hex-color-regex "^1.1.0" - hsl-regex "^1.0.0" - hsla-regex "^1.0.0" - rgb-regex "^1.0.1" - rgba-regex "^1.0.0" - -is-core-module@^2.0.0, is-core-module@^2.2.0, is-core-module@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.4.0.tgz#8e9fc8e15027b011418026e98f0e6f4d86305cc1" - integrity sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A== - dependencies: - has "^1.0.3" - -is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= - dependencies: - kind-of "^3.0.2" - -is-data-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== - dependencies: - kind-of "^6.0.0" - -is-date-object@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.4.tgz#550cfcc03afada05eea3dd30981c7b09551f73e5" - integrity sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A== - -is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== - dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" - -is-descriptor@^1.0.0, is-descriptor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== - dependencies: - is-accessor-descriptor "^1.0.0" - is-data-descriptor "^1.0.0" - kind-of "^6.0.2" - -is-directory@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" - integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= - -is-docker@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" - integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= - -is-extendable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== - dependencies: - is-plain-object "^2.0.4" - -is-extglob@^2.1.0, is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-generator-fn@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" - integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== - -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= - dependencies: - is-extglob "^2.1.0" - -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" - integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== - dependencies: - is-extglob "^2.1.1" - -is-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" - integrity sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE= - -is-negative-zero@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" - integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== - -is-number-object@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.5.tgz#6edfaeed7950cff19afedce9fbfca9ee6dd289eb" - integrity sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw== - -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= - dependencies: - kind-of "^3.0.2" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-obj@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= - -is-obj@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" - integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== - -is-path-cwd@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" - integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== - -is-path-in-cwd@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz#bfe2dca26c69f397265a4009963602935a053acb" - integrity sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ== - dependencies: - is-path-inside "^2.1.0" - -is-path-inside@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-2.1.0.tgz#7c9810587d659a40d27bcdb4d5616eab059494b2" - integrity sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg== - dependencies: - path-is-inside "^1.0.2" - -is-plain-obj@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= - -is-plain-object@^2.0.3, is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - -is-potential-custom-element-name@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" - integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== - -is-regex@^1.0.4, is-regex@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.3.tgz#d029f9aff6448b93ebbe3f33dac71511fdcbef9f" - integrity sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ== - dependencies: - call-bind "^1.0.2" - has-symbols "^1.0.2" - -is-regexp@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" - integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= - -is-resolvable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" - integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== - -is-root@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.1.0.tgz#809e18129cf1129644302a4f8544035d51984a9c" - integrity sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg== - -is-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= - -is-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" - integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== - -is-string@^1.0.5: - version "1.0.6" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.6.tgz#3fe5d5992fb0d93404f32584d4b0179a71b54a5f" - integrity sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w== - -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== - dependencies: - has-symbols "^1.0.2" - -is-typedarray@^1.0.0, is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - -is-windows@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== - -is-wsl@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" - integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= - -is-wsl@^2.1.1, is-wsl@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" - integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== - dependencies: - is-docker "^2.0.0" - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= - -isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= - -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= - dependencies: - isarray "1.0.0" - -isobject@^3.0.0, isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= - -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= - -istanbul-lib-coverage@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" - integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== - -istanbul-lib-instrument@^4.0.0, istanbul-lib-instrument@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" - integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ== - dependencies: - "@babel/core" "^7.7.5" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-coverage "^3.0.0" - semver "^6.3.0" - -istanbul-lib-report@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" - integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== - dependencies: - istanbul-lib-coverage "^3.0.0" - make-dir "^3.0.0" - supports-color "^7.1.0" - -istanbul-lib-source-maps@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz#75743ce6d96bb86dc7ee4352cf6366a23f0b1ad9" - integrity sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg== - dependencies: - debug "^4.1.1" - istanbul-lib-coverage "^3.0.0" - source-map "^0.6.1" - -istanbul-reports@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.0.2.tgz#d593210e5000683750cb09fc0644e4b6e27fd53b" - integrity sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw== - dependencies: - html-escaper "^2.0.0" - istanbul-lib-report "^3.0.0" - -jest-changed-files@^26.6.2: - version "26.6.2" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-26.6.2.tgz#f6198479e1cc66f22f9ae1e22acaa0b429c042d0" - integrity sha512-fDS7szLcY9sCtIip8Fjry9oGf3I2ht/QT21bAHm5Dmf0mD4X3ReNUf17y+bO6fR8WgbIZTlbyG1ak/53cbRzKQ== - dependencies: - "@jest/types" "^26.6.2" - execa "^4.0.0" - throat "^5.0.0" - -jest-circus@26.6.0: - version "26.6.0" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-26.6.0.tgz#7d9647b2e7f921181869faae1f90a2629fd70705" - integrity sha512-L2/Y9szN6FJPWFK8kzWXwfp+FOR7xq0cUL4lIsdbIdwz3Vh6P1nrpcqOleSzr28zOtSHQNV9Z7Tl+KkuK7t5Ng== - dependencies: - "@babel/traverse" "^7.1.0" - "@jest/environment" "^26.6.0" - "@jest/test-result" "^26.6.0" - "@jest/types" "^26.6.0" - "@types/babel__traverse" "^7.0.4" - "@types/node" "*" - chalk "^4.0.0" - co "^4.6.0" - dedent "^0.7.0" - expect "^26.6.0" - is-generator-fn "^2.0.0" - jest-each "^26.6.0" - jest-matcher-utils "^26.6.0" - jest-message-util "^26.6.0" - jest-runner "^26.6.0" - jest-runtime "^26.6.0" - jest-snapshot "^26.6.0" - jest-util "^26.6.0" - pretty-format "^26.6.0" - stack-utils "^2.0.2" - throat "^5.0.0" - -jest-cli@^26.6.0: - version "26.6.3" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-26.6.3.tgz#43117cfef24bc4cd691a174a8796a532e135e92a" - integrity sha512-GF9noBSa9t08pSyl3CY4frMrqp+aQXFGFkf5hEPbh/pIUFYWMK6ZLTfbmadxJVcJrdRoChlWQsA2VkJcDFK8hg== - dependencies: - "@jest/core" "^26.6.3" - "@jest/test-result" "^26.6.2" - "@jest/types" "^26.6.2" - chalk "^4.0.0" - exit "^0.1.2" - graceful-fs "^4.2.4" - import-local "^3.0.2" - is-ci "^2.0.0" - jest-config "^26.6.3" - jest-util "^26.6.2" - jest-validate "^26.6.2" - prompts "^2.0.1" - yargs "^15.4.1" - -jest-config@^26.6.3: - version "26.6.3" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-26.6.3.tgz#64f41444eef9eb03dc51d5c53b75c8c71f645349" - integrity sha512-t5qdIj/bCj2j7NFVHb2nFB4aUdfucDn3JRKgrZnplb8nieAirAzRSHP8uDEd+qV6ygzg9Pz4YG7UTJf94LPSyg== - dependencies: - "@babel/core" "^7.1.0" - "@jest/test-sequencer" "^26.6.3" - "@jest/types" "^26.6.2" - babel-jest "^26.6.3" - chalk "^4.0.0" - deepmerge "^4.2.2" - glob "^7.1.1" - graceful-fs "^4.2.4" - jest-environment-jsdom "^26.6.2" - jest-environment-node "^26.6.2" - jest-get-type "^26.3.0" - jest-jasmine2 "^26.6.3" - jest-regex-util "^26.0.0" - jest-resolve "^26.6.2" - jest-util "^26.6.2" - jest-validate "^26.6.2" - micromatch "^4.0.2" - pretty-format "^26.6.2" - -jest-diff@^26.0.0, jest-diff@^26.6.2: - version "26.6.2" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.6.2.tgz#1aa7468b52c3a68d7d5c5fdcdfcd5e49bd164394" - integrity sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA== - dependencies: - chalk "^4.0.0" - diff-sequences "^26.6.2" - jest-get-type "^26.3.0" - pretty-format "^26.6.2" - -jest-docblock@^26.0.0: - version "26.0.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-26.0.0.tgz#3e2fa20899fc928cb13bd0ff68bd3711a36889b5" - integrity sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w== - dependencies: - detect-newline "^3.0.0" - -jest-each@^26.6.0, jest-each@^26.6.2: - version "26.6.2" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-26.6.2.tgz#02526438a77a67401c8a6382dfe5999952c167cb" - integrity sha512-Mer/f0KaATbjl8MCJ+0GEpNdqmnVmDYqCTJYTvoo7rqmRiDllmp2AYN+06F93nXcY3ur9ShIjS+CO/uD+BbH4A== - dependencies: - "@jest/types" "^26.6.2" - chalk "^4.0.0" - jest-get-type "^26.3.0" - jest-util "^26.6.2" - pretty-format "^26.6.2" - -jest-environment-jsdom@^26.6.2: - version "26.6.2" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-26.6.2.tgz#78d09fe9cf019a357009b9b7e1f101d23bd1da3e" - integrity sha512-jgPqCruTlt3Kwqg5/WVFyHIOJHsiAvhcp2qiR2QQstuG9yWox5+iHpU3ZrcBxW14T4fe5Z68jAfLRh7joCSP2Q== - dependencies: - "@jest/environment" "^26.6.2" - "@jest/fake-timers" "^26.6.2" - "@jest/types" "^26.6.2" - "@types/node" "*" - jest-mock "^26.6.2" - jest-util "^26.6.2" - jsdom "^16.4.0" - -jest-environment-node@^26.6.2: - version "26.6.2" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-26.6.2.tgz#824e4c7fb4944646356f11ac75b229b0035f2b0c" - integrity sha512-zhtMio3Exty18dy8ee8eJ9kjnRyZC1N4C1Nt/VShN1apyXc8rWGtJ9lI7vqiWcyyXS4BVSEn9lxAM2D+07/Tag== - dependencies: - "@jest/environment" "^26.6.2" - "@jest/fake-timers" "^26.6.2" - "@jest/types" "^26.6.2" - "@types/node" "*" - jest-mock "^26.6.2" - jest-util "^26.6.2" - -jest-get-type@^26.3.0: - version "26.3.0" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0" - integrity sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig== - -jest-haste-map@^26.6.2: - version "26.6.2" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.6.2.tgz#dd7e60fe7dc0e9f911a23d79c5ff7fb5c2cafeaa" - integrity sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w== - dependencies: - "@jest/types" "^26.6.2" - "@types/graceful-fs" "^4.1.2" - "@types/node" "*" - anymatch "^3.0.3" - fb-watchman "^2.0.0" - graceful-fs "^4.2.4" - jest-regex-util "^26.0.0" - jest-serializer "^26.6.2" - jest-util "^26.6.2" - jest-worker "^26.6.2" - micromatch "^4.0.2" - sane "^4.0.3" - walker "^1.0.7" - optionalDependencies: - fsevents "^2.1.2" - -jest-jasmine2@^26.6.3: - version "26.6.3" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-26.6.3.tgz#adc3cf915deacb5212c93b9f3547cd12958f2edd" - integrity sha512-kPKUrQtc8aYwBV7CqBg5pu+tmYXlvFlSFYn18ev4gPFtrRzB15N2gW/Roew3187q2w2eHuu0MU9TJz6w0/nPEg== - dependencies: - "@babel/traverse" "^7.1.0" - "@jest/environment" "^26.6.2" - "@jest/source-map" "^26.6.2" - "@jest/test-result" "^26.6.2" - "@jest/types" "^26.6.2" - "@types/node" "*" - chalk "^4.0.0" - co "^4.6.0" - expect "^26.6.2" - is-generator-fn "^2.0.0" - jest-each "^26.6.2" - jest-matcher-utils "^26.6.2" - jest-message-util "^26.6.2" - jest-runtime "^26.6.3" - jest-snapshot "^26.6.2" - jest-util "^26.6.2" - pretty-format "^26.6.2" - throat "^5.0.0" - -jest-leak-detector@^26.6.2: - version "26.6.2" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-26.6.2.tgz#7717cf118b92238f2eba65054c8a0c9c653a91af" - integrity sha512-i4xlXpsVSMeKvg2cEKdfhh0H39qlJlP5Ex1yQxwF9ubahboQYMgTtz5oML35AVA3B4Eu+YsmwaiKVev9KCvLxg== - dependencies: - jest-get-type "^26.3.0" - pretty-format "^26.6.2" - -jest-matcher-utils@^26.6.0, jest-matcher-utils@^26.6.2: - version "26.6.2" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz#8e6fd6e863c8b2d31ac6472eeb237bc595e53e7a" - integrity sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw== - dependencies: - chalk "^4.0.0" - jest-diff "^26.6.2" - jest-get-type "^26.3.0" - pretty-format "^26.6.2" - -jest-message-util@^26.6.0, jest-message-util@^26.6.2: - version "26.6.2" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.6.2.tgz#58173744ad6fc0506b5d21150b9be56ef001ca07" - integrity sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA== - dependencies: - "@babel/code-frame" "^7.0.0" - "@jest/types" "^26.6.2" - "@types/stack-utils" "^2.0.0" - chalk "^4.0.0" - graceful-fs "^4.2.4" - micromatch "^4.0.2" - pretty-format "^26.6.2" - slash "^3.0.0" - stack-utils "^2.0.2" - -jest-mock@^26.6.2: - version "26.6.2" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-26.6.2.tgz#d6cb712b041ed47fe0d9b6fc3474bc6543feb302" - integrity sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew== - dependencies: - "@jest/types" "^26.6.2" - "@types/node" "*" - -jest-pnp-resolver@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" - integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== - -jest-regex-util@^26.0.0: - version "26.0.0" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-26.0.0.tgz#d25e7184b36e39fd466c3bc41be0971e821fee28" - integrity sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A== - -jest-resolve-dependencies@^26.6.3: - version "26.6.3" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-26.6.3.tgz#6680859ee5d22ee5dcd961fe4871f59f4c784fb6" - integrity sha512-pVwUjJkxbhe4RY8QEWzN3vns2kqyuldKpxlxJlzEYfKSvY6/bMvxoFrYYzUO1Gx28yKWN37qyV7rIoIp2h8fTg== - dependencies: - "@jest/types" "^26.6.2" - jest-regex-util "^26.0.0" - jest-snapshot "^26.6.2" - -jest-resolve@26.6.0: - version "26.6.0" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-26.6.0.tgz#070fe7159af87b03e50f52ea5e17ee95bbee40e1" - integrity sha512-tRAz2bwraHufNp+CCmAD8ciyCpXCs1NQxB5EJAmtCFy6BN81loFEGWKzYu26Y62lAJJe4X4jg36Kf+NsQyiStQ== - dependencies: - "@jest/types" "^26.6.0" - chalk "^4.0.0" - graceful-fs "^4.2.4" - jest-pnp-resolver "^1.2.2" - jest-util "^26.6.0" - read-pkg-up "^7.0.1" - resolve "^1.17.0" - slash "^3.0.0" - -jest-resolve@^26.6.2: - version "26.6.2" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-26.6.2.tgz#a3ab1517217f469b504f1b56603c5bb541fbb507" - integrity sha512-sOxsZOq25mT1wRsfHcbtkInS+Ek7Q8jCHUB0ZUTP0tc/c41QHriU/NunqMfCUWsL4H3MHpvQD4QR9kSYhS7UvQ== - dependencies: - "@jest/types" "^26.6.2" - chalk "^4.0.0" - graceful-fs "^4.2.4" - jest-pnp-resolver "^1.2.2" - jest-util "^26.6.2" - read-pkg-up "^7.0.1" - resolve "^1.18.1" - slash "^3.0.0" - -jest-runner@^26.6.0, jest-runner@^26.6.3: - version "26.6.3" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-26.6.3.tgz#2d1fed3d46e10f233fd1dbd3bfaa3fe8924be159" - integrity sha512-atgKpRHnaA2OvByG/HpGA4g6CSPS/1LK0jK3gATJAoptC1ojltpmVlYC3TYgdmGp+GLuhzpH30Gvs36szSL2JQ== - dependencies: - "@jest/console" "^26.6.2" - "@jest/environment" "^26.6.2" - "@jest/test-result" "^26.6.2" - "@jest/types" "^26.6.2" - "@types/node" "*" - chalk "^4.0.0" - emittery "^0.7.1" - exit "^0.1.2" - graceful-fs "^4.2.4" - jest-config "^26.6.3" - jest-docblock "^26.0.0" - jest-haste-map "^26.6.2" - jest-leak-detector "^26.6.2" - jest-message-util "^26.6.2" - jest-resolve "^26.6.2" - jest-runtime "^26.6.3" - jest-util "^26.6.2" - jest-worker "^26.6.2" - source-map-support "^0.5.6" - throat "^5.0.0" - -jest-runtime@^26.6.0, jest-runtime@^26.6.3: - version "26.6.3" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-26.6.3.tgz#4f64efbcfac398331b74b4b3c82d27d401b8fa2b" - integrity sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw== - dependencies: - "@jest/console" "^26.6.2" - "@jest/environment" "^26.6.2" - "@jest/fake-timers" "^26.6.2" - "@jest/globals" "^26.6.2" - "@jest/source-map" "^26.6.2" - "@jest/test-result" "^26.6.2" - "@jest/transform" "^26.6.2" - "@jest/types" "^26.6.2" - "@types/yargs" "^15.0.0" - chalk "^4.0.0" - cjs-module-lexer "^0.6.0" - collect-v8-coverage "^1.0.0" - exit "^0.1.2" - glob "^7.1.3" - graceful-fs "^4.2.4" - jest-config "^26.6.3" - jest-haste-map "^26.6.2" - jest-message-util "^26.6.2" - jest-mock "^26.6.2" - jest-regex-util "^26.0.0" - jest-resolve "^26.6.2" - jest-snapshot "^26.6.2" - jest-util "^26.6.2" - jest-validate "^26.6.2" - slash "^3.0.0" - strip-bom "^4.0.0" - yargs "^15.4.1" - -jest-serializer@^26.6.2: - version "26.6.2" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-26.6.2.tgz#d139aafd46957d3a448f3a6cdabe2919ba0742d1" - integrity sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g== - dependencies: - "@types/node" "*" - graceful-fs "^4.2.4" - -jest-snapshot@^26.6.0, jest-snapshot@^26.6.2: - version "26.6.2" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-26.6.2.tgz#f3b0af1acb223316850bd14e1beea9837fb39c84" - integrity sha512-OLhxz05EzUtsAmOMzuupt1lHYXCNib0ECyuZ/PZOx9TrZcC8vL0x+DUG3TL+GLX3yHG45e6YGjIm0XwDc3q3og== - dependencies: - "@babel/types" "^7.0.0" - "@jest/types" "^26.6.2" - "@types/babel__traverse" "^7.0.4" - "@types/prettier" "^2.0.0" - chalk "^4.0.0" - expect "^26.6.2" - graceful-fs "^4.2.4" - jest-diff "^26.6.2" - jest-get-type "^26.3.0" - jest-haste-map "^26.6.2" - jest-matcher-utils "^26.6.2" - jest-message-util "^26.6.2" - jest-resolve "^26.6.2" - natural-compare "^1.4.0" - pretty-format "^26.6.2" - semver "^7.3.2" - -jest-util@^26.6.0, jest-util@^26.6.2: - version "26.6.2" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.6.2.tgz#907535dbe4d5a6cb4c47ac9b926f6af29576cbc1" - integrity sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q== - dependencies: - "@jest/types" "^26.6.2" - "@types/node" "*" - chalk "^4.0.0" - graceful-fs "^4.2.4" - is-ci "^2.0.0" - micromatch "^4.0.2" - -jest-validate@^26.6.2: - version "26.6.2" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-26.6.2.tgz#23d380971587150467342911c3d7b4ac57ab20ec" - integrity sha512-NEYZ9Aeyj0i5rQqbq+tpIOom0YS1u2MVu6+euBsvpgIme+FOfRmoC4R5p0JiAUpaFvFy24xgrpMknarR/93XjQ== - dependencies: - "@jest/types" "^26.6.2" - camelcase "^6.0.0" - chalk "^4.0.0" - jest-get-type "^26.3.0" - leven "^3.1.0" - pretty-format "^26.6.2" - -jest-watch-typeahead@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/jest-watch-typeahead/-/jest-watch-typeahead-0.6.1.tgz#45221b86bb6710b7e97baaa1640ae24a07785e63" - integrity sha512-ITVnHhj3Jd/QkqQcTqZfRgjfyRhDFM/auzgVo2RKvSwi18YMvh0WvXDJFoFED6c7jd/5jxtu4kSOb9PTu2cPVg== - dependencies: - ansi-escapes "^4.3.1" - chalk "^4.0.0" - jest-regex-util "^26.0.0" - jest-watcher "^26.3.0" - slash "^3.0.0" - string-length "^4.0.1" - strip-ansi "^6.0.0" - -jest-watcher@^26.3.0, jest-watcher@^26.6.2: - version "26.6.2" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-26.6.2.tgz#a5b683b8f9d68dbcb1d7dae32172d2cca0592975" - integrity sha512-WKJob0P/Em2csiVthsI68p6aGKTIcsfjH9Gsx1f0A3Italz43e3ho0geSAVsmj09RWOELP1AZ/DXyJgOgDKxXQ== - dependencies: - "@jest/test-result" "^26.6.2" - "@jest/types" "^26.6.2" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - jest-util "^26.6.2" - string-length "^4.0.1" - -jest-worker@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.9.0.tgz#5dbfdb5b2d322e98567898238a9697bcce67b3e5" - integrity sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw== - dependencies: - merge-stream "^2.0.0" - supports-color "^6.1.0" - -jest-worker@^26.5.0, jest-worker@^26.6.2: - version "26.6.2" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" - integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== - dependencies: - "@types/node" "*" - merge-stream "^2.0.0" - supports-color "^7.0.0" - -jest@26.6.0: - version "26.6.0" - resolved "https://registry.yarnpkg.com/jest/-/jest-26.6.0.tgz#546b25a1d8c888569dbbe93cae131748086a4a25" - integrity sha512-jxTmrvuecVISvKFFhOkjsWRZV7sFqdSUAd1ajOKY+/QE/aLBVstsJ/dX8GczLzwiT6ZEwwmZqtCUHLHHQVzcfA== - dependencies: - "@jest/core" "^26.6.0" - import-local "^3.0.2" - jest-cli "^26.6.0" - -"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" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^3.13.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= - -jsdom@^16.4.0: - version "16.5.3" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.5.3.tgz#13a755b3950eb938b4482c407238ddf16f0d2136" - integrity sha512-Qj1H+PEvUsOtdPJ056ewXM4UJPCi4hhLA8wpiz9F2YvsRBhuFsXxtrIFAgGBDynQA9isAMGE91PfUYbdMPXuTA== - dependencies: - abab "^2.0.5" - acorn "^8.1.0" - acorn-globals "^6.0.0" - cssom "^0.4.4" - cssstyle "^2.3.0" - data-urls "^2.0.0" - decimal.js "^10.2.1" - domexception "^2.0.1" - escodegen "^2.0.0" - html-encoding-sniffer "^2.0.1" - is-potential-custom-element-name "^1.0.0" - nwsapi "^2.2.0" - parse5 "6.0.1" - request "^2.88.2" - request-promise-native "^1.0.9" - saxes "^5.0.1" - symbol-tree "^3.2.4" - tough-cookie "^4.0.0" - w3c-hr-time "^1.0.2" - w3c-xmlserializer "^2.0.0" - webidl-conversions "^6.1.0" - whatwg-encoding "^1.0.5" - whatwg-mimetype "^2.3.0" - whatwg-url "^8.5.0" - ws "^7.4.4" - xml-name-validator "^3.0.0" - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= - -json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - -json-parse-even-better-errors@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-schema-traverse@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" - integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== - -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= - -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= - -json3@^3.3.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81" - integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA== - -json5@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== - dependencies: - minimist "^1.2.0" - -json5@^2.1.2: - version "2.2.0" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" - integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== - dependencies: - minimist "^1.2.5" - -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= - optionalDependencies: - graceful-fs "^4.1.6" - -jsonfile@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" - integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== - dependencies: - universalify "^2.0.0" - optionalDependencies: - graceful-fs "^4.1.6" - -jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.2.3" - verror "1.10.0" - -"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz#41108d2cec408c3453c1bbe8a4aae9e1e2bd8f82" - integrity sha512-EIsmt3O3ljsU6sot/J4E1zDRxfBNrhjyf/OKjlydwgEimQuznlM4Wv7U+ueONJMyEn1WRE0K8dhi3dVAXYT24Q== - dependencies: - array-includes "^3.1.2" - object.assign "^4.1.2" - -killable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" - integrity sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg== - -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= - dependencies: - is-buffer "^1.1.5" - -kind-of@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== - -kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - -kleur@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" - integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== - -klona@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.4.tgz#7bb1e3affb0cb8624547ef7e8f6708ea2e39dfc0" - integrity sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA== - -language-subtag-registry@~0.3.2: - version "0.3.21" - resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz#04ac218bea46f04cb039084602c6da9e788dd45a" - integrity sha512-L0IqwlIXjilBVVYKFT37X9Ih11Um5NEl9cbJIuU/SwP/zEEAbBPOnEeeuxVMf45ydWQRDQN3Nqc96OgbH1K+Pg== - -language-tags@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.5.tgz#d321dbc4da30ba8bf3024e040fa5c14661f9193a" - integrity sha1-0yHbxNowuovzAk4ED6XBRmH5GTo= - dependencies: - language-subtag-registry "~0.3.2" - -last-call-webpack-plugin@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz#9742df0e10e3cf46e5c0381c2de90d3a7a2d7555" - integrity sha512-7KI2l2GIZa9p2spzPIVZBYyNKkN+e/SQPpnjlTiPhdbDW3F86tdKKELxKpzJ5sgU19wQWsACULZmpTPYHeWO5w== - dependencies: - lodash "^4.17.5" - webpack-sources "^1.1.0" - -leven@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" - integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== - -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - -levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - -lines-and-columns@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" - integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= - -load-json-file@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" - integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= - dependencies: - graceful-fs "^4.1.2" - parse-json "^4.0.0" - pify "^3.0.0" - strip-bom "^3.0.0" - -loader-runner@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" - integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== - -loader-utils@1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" - integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA== - dependencies: - big.js "^5.2.2" - emojis-list "^2.0.0" - json5 "^1.0.1" - -loader-utils@2.0.0, loader-utils@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0" - integrity sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ== - dependencies: - big.js "^5.2.2" - emojis-list "^3.0.0" - json5 "^2.1.2" - -loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" - integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== - dependencies: - big.js "^5.2.2" - emojis-list "^3.0.0" - json5 "^1.0.1" - -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - -locate-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== - dependencies: - p-locate "^3.0.0" - path-exists "^3.0.0" - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -lodash-es@^4.17.20: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" - integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== - -lodash._reinterpolate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" - integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= - -lodash.clonedeep@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" - integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= - -lodash.debounce@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= - -lodash.memoize@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= - -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -lodash.template@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" - integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A== - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.templatesettings "^4.0.0" - -lodash.templatesettings@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33" - integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ== - dependencies: - lodash._reinterpolate "^3.0.0" - -lodash.truncate@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" - integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM= - -lodash.uniq@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" - integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= - -"lodash@>=3.5 <5", lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.5, lodash@^4.7.0: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -loglevel@^1.6.8: - version "1.7.1" - resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.1.tgz#005fde2f5e6e47068f935ff28573e125ef72f197" - integrity sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw== - -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -lower-case@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" - integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== - dependencies: - tslib "^2.0.3" - -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -lz-string@^1.4.4: - version "1.4.4" - resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26" - integrity sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY= - -magic-string@^0.25.0, magic-string@^0.25.7: - version "0.25.7" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" - integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA== - dependencies: - sourcemap-codec "^1.4.4" - -make-dir@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" - integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== - dependencies: - pify "^4.0.1" - semver "^5.6.0" - -make-dir@^3.0.0, make-dir@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== - dependencies: - semver "^6.0.0" - -makeerror@1.0.x: - version "1.0.11" - resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" - integrity sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw= - dependencies: - tmpl "1.0.x" - -map-cache@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= - -map-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= - dependencies: - object-visit "^1.0.0" - -md5.js@^1.3.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" - integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -mdn-data@2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" - integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== - -mdn-data@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" - integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= - -memory-fs@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" - integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= - dependencies: - errno "^0.1.3" - readable-stream "^2.0.1" - -memory-fs@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c" - integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA== - dependencies: - errno "^0.1.3" - readable-stream "^2.0.1" - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -merge2@^1.3.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= - -microevent.ts@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/microevent.ts/-/microevent.ts-0.1.1.tgz#70b09b83f43df5172d0205a63025bce0f7357fa0" - integrity sha512-jo1OfR4TaEwd5HOrt5+tAZ9mqT4jmpNAusXtyfNzqVm9uiSYFZlKM1wYL4oU7azZW/PxQW53wM0S6OR1JHNa2g== - -micromatch@^3.1.10, micromatch@^3.1.4: - version "3.1.10" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.1" - define-property "^2.0.2" - extend-shallow "^3.0.2" - extglob "^2.0.4" - fragment-cache "^0.2.1" - kind-of "^6.0.2" - nanomatch "^1.2.9" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.2" - -micromatch@^4.0.2: - version "4.0.4" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" - integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== - dependencies: - braces "^3.0.1" - picomatch "^2.2.3" - -miller-rabin@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== - dependencies: - bn.js "^4.0.0" - brorand "^1.0.1" - -mime-db@1.47.0, "mime-db@>= 1.43.0 < 2": - version "1.47.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.47.0.tgz#8cb313e59965d3c05cfbf898915a267af46a335c" - integrity sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw== - -mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: - version "2.1.30" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.30.tgz#6e7be8b4c479825f85ed6326695db73f9305d62d" - integrity sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg== - dependencies: - mime-db "1.47.0" - -mime@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - -mime@^2.4.4: - version "2.5.2" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe" - integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg== - -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -min-indent@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" - integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== - -mini-create-react-context@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz#072171561bfdc922da08a60c2197a497cc2d1d5e" - integrity sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ== - dependencies: - "@babel/runtime" "^7.12.1" - tiny-warning "^1.0.3" - -mini-css-extract-plugin@0.11.3: - version "0.11.3" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.11.3.tgz#15b0910a7f32e62ffde4a7430cfefbd700724ea6" - integrity sha512-n9BA8LonkOkW1/zn+IbLPQmovsL0wMb9yx75fMJQZf2X1Zoec9yTZtyMePcyu19wPkmFbzZZA6fLTotpFhQsOA== - dependencies: - loader-utils "^1.1.0" - normalize-url "1.9.1" - schema-utils "^1.0.0" - webpack-sources "^1.1.0" - -minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== - -minimalistic-crypto-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= - -minimatch@3.0.4, minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== - -minipass-collect@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617" - integrity sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA== - dependencies: - minipass "^3.0.0" - -minipass-flush@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373" - integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw== - dependencies: - minipass "^3.0.0" - -minipass-pipeline@^1.2.2: - version "1.2.4" - resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" - integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== - dependencies: - minipass "^3.0.0" - -minipass@^3.0.0, minipass@^3.1.1: - version "3.1.3" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.3.tgz#7d42ff1f39635482e15f9cdb53184deebd5815fd" - integrity sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg== - dependencies: - yallist "^4.0.0" - -minizlib@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" - integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== - dependencies: - minipass "^3.0.0" - yallist "^4.0.0" - -mississippi@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" - integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA== - dependencies: - concat-stream "^1.5.0" - duplexify "^3.4.2" - end-of-stream "^1.1.0" - flush-write-stream "^1.0.0" - from2 "^2.1.0" - parallel-transform "^1.1.0" - pump "^3.0.0" - pumpify "^1.3.3" - stream-each "^1.1.0" - through2 "^2.0.0" - -mixin-deep@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" - integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== - dependencies: - for-in "^1.0.2" - is-extendable "^1.0.1" - -mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1: - version "0.5.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" - integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== - dependencies: - minimist "^1.2.5" - -mkdirp@^1.0.3, mkdirp@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== - -move-concurrently@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" - integrity sha1-viwAX9oy4LKa8fBdfEszIUxwH5I= - dependencies: - aproba "^1.1.1" - copy-concurrently "^1.0.0" - fs-write-stream-atomic "^1.0.8" - mkdirp "^0.5.1" - rimraf "^2.5.4" - run-queue "^1.0.3" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -multicast-dns-service-types@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" - integrity sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE= - -multicast-dns@^6.0.1: - version "6.2.3" - resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-6.2.3.tgz#a0ec7bd9055c4282f790c3c82f4e28db3b31b229" - integrity sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g== - dependencies: - dns-packet "^1.3.1" - thunky "^1.0.2" - -nan@^2.12.1: - version "2.14.2" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" - integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== - -nanoid@^3.1.23: - version "3.1.23" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.23.tgz#f744086ce7c2bc47ee0a8472574d5c78e4183a81" - integrity sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw== - -nanomatch@^1.2.9: - version "1.2.13" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^2.0.2" - extend-shallow "^3.0.2" - fragment-cache "^0.2.1" - is-windows "^1.0.2" - kind-of "^6.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -native-url@^0.2.6: - version "0.2.6" - resolved "https://registry.yarnpkg.com/native-url/-/native-url-0.2.6.tgz#ca1258f5ace169c716ff44eccbddb674e10399ae" - integrity sha512-k4bDC87WtgrdD362gZz6zoiXQrl40kYlBmpfmSjwRO1VU0V5ccwJTlxuE72F6m3V0vc1xOf6n3UCP9QyerRqmA== - dependencies: - querystring "^0.2.0" - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= - -negotiator@0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== - -neo-async@^2.5.0, neo-async@^2.6.1, neo-async@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" - integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== - -next-tick@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" - integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= - -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - -no-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" - integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== - dependencies: - lower-case "^2.0.2" - tslib "^2.0.3" - -node-forge@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" - integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA== - -node-int64@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" - integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= - -node-libs-browser@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" - integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== - dependencies: - assert "^1.1.1" - browserify-zlib "^0.2.0" - buffer "^4.3.0" - console-browserify "^1.1.0" - constants-browserify "^1.0.0" - crypto-browserify "^3.11.0" - domain-browser "^1.1.1" - events "^3.0.0" - https-browserify "^1.0.0" - os-browserify "^0.3.0" - path-browserify "0.0.1" - process "^0.11.10" - punycode "^1.2.4" - querystring-es3 "^0.2.0" - readable-stream "^2.3.3" - stream-browserify "^2.0.1" - stream-http "^2.7.2" - string_decoder "^1.0.0" - timers-browserify "^2.0.4" - tty-browserify "0.0.0" - url "^0.11.0" - util "^0.11.0" - vm-browserify "^1.0.1" - -node-modules-regexp@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" - integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= - -node-notifier@^8.0.0: - version "8.0.2" - resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-8.0.2.tgz#f3167a38ef0d2c8a866a83e318c1ba0efeb702c5" - integrity sha512-oJP/9NAdd9+x2Q+rfphB2RJCHjod70RcRLjosiPMMu5gjIfwVnOUGq2nbTjTUbmy0DJ/tFIVT30+Qe3nzl4TJg== - dependencies: - growly "^1.3.0" - is-wsl "^2.2.0" - semver "^7.3.2" - shellwords "^0.1.1" - uuid "^8.3.0" - which "^2.0.2" - -node-releases@^1.1.61, node-releases@^1.1.71: - version "1.1.72" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.72.tgz#14802ab6b1039a79a0c7d662b610a5bbd76eacbe" - integrity sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw== - -normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" - integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== - dependencies: - hosted-git-info "^2.1.4" - resolve "^1.10.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - -normalize-path@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= - dependencies: - remove-trailing-separator "^1.0.1" - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -normalize-range@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" - integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= - -normalize-url@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" - integrity sha1-LMDWazHqIwNkWENuNiDYWVTGbDw= - dependencies: - object-assign "^4.0.1" - prepend-http "^1.0.0" - query-string "^4.1.0" - sort-keys "^1.0.0" - -normalize-url@^3.0.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" - integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== - -npm-run-path@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= - dependencies: - path-key "^2.0.0" - -npm-run-path@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" - integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== - dependencies: - path-key "^3.0.0" - -nth-check@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" - integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== - dependencies: - boolbase "~1.0.0" - -num2fraction@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" - integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4= - -nwsapi@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" - integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== - -oauth-sign@~0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" - integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== - -object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -object-copy@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= - dependencies: - copy-descriptor "^0.1.0" - define-property "^0.2.5" - kind-of "^3.0.3" - -object-inspect@^1.9.0: - version "1.10.3" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.10.3.tgz#c2aa7d2d09f50c99375704f7a0adf24c5782d369" - integrity sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw== - -object-is@^1.0.1: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" - integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -object-keys@^1.0.12, object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object-visit@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= - dependencies: - isobject "^3.0.0" - -object.assign@^4.1.0, object.assign@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" - integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - has-symbols "^1.0.1" - object-keys "^1.1.1" - -object.entries@^1.1.0, object.entries@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.3.tgz#c601c7f168b62374541a07ddbd3e2d5e4f7711a6" - integrity sha512-ym7h7OZebNS96hn5IJeyUmaWhaSM4SVtAPPfNLQEI2MYWCO2egsITb9nab2+i/Pwibx+R0mtn+ltKJXRSeTMGg== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - es-abstract "^1.18.0-next.1" - has "^1.0.3" - -object.fromentries@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.4.tgz#26e1ba5c4571c5c6f0890cef4473066456a120b8" - integrity sha512-EsFBshs5RUUpQEY1D4q/m59kMfz4YJvxuNCJcv/jWwOJr34EaVnG11ZrZa0UHB3wnzV1wx8m58T4hQL8IuNXlQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.18.0-next.2" - has "^1.0.3" - -object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz#1bd63aeacf0d5d2d2f31b5e393b03a7c601a23f7" - integrity sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.18.0-next.2" - -object.pick@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= - dependencies: - isobject "^3.0.1" - -object.values@^1.1.0, object.values@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.3.tgz#eaa8b1e17589f02f698db093f7c62ee1699742ee" - integrity sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.18.0-next.2" - has "^1.0.3" - -obuf@^1.0.0, obuf@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" - integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== - -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= - dependencies: - ee-first "1.1.1" - -on-headers@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" - integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== - -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" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -onetime@^5.1.0: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== - dependencies: - mimic-fn "^2.1.0" - -open@^7.0.2: - version "7.4.2" - resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" - integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== - dependencies: - is-docker "^2.0.0" - is-wsl "^2.1.1" - -opn@^5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc" - integrity sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA== - dependencies: - is-wsl "^1.1.0" - -optimize-css-assets-webpack-plugin@5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.4.tgz#85883c6528aaa02e30bbad9908c92926bb52dc90" - integrity sha512-wqd6FdI2a5/FdoiCNNkEvLeA//lHHfG24Ln2Xm2qqdIk4aOlsR18jwpyOihqQ8849W3qu2DX8fOYxpvTMj+93A== - dependencies: - cssnano "^4.1.10" - last-call-webpack-plugin "^3.0.0" - -optionator@^0.8.1: - version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.6" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - word-wrap "~1.2.3" - -optionator@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" - integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== - dependencies: - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" - word-wrap "^1.2.3" - -original@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f" - integrity sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg== - dependencies: - url-parse "^1.4.3" - -os-browserify@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" - integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= - -p-each-series@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.2.0.tgz#105ab0357ce72b202a8a8b94933672657b5e2a9a" - integrity sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA== - -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= - -p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== - dependencies: - p-try "^1.0.0" - -p-limit@^2.0.0, p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-limit@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= - dependencies: - p-limit "^1.1.0" - -p-locate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== - dependencies: - p-limit "^2.0.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-map@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" - integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== - -p-map@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" - integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== - dependencies: - aggregate-error "^3.0.0" - -p-retry@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-3.0.1.tgz#316b4c8893e2c8dc1cfa891f406c4b422bebf328" - integrity sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w== - dependencies: - retry "^0.12.0" - -p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -pako@~1.0.5: - version "1.0.11" - resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" - integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== - -parallel-transform@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc" - integrity sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg== - dependencies: - cyclist "^1.0.1" - inherits "^2.0.3" - readable-stream "^2.1.5" - -param-case@^3.0.3: - version "3.0.4" - resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" - integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A== - dependencies: - dot-case "^3.0.4" - tslib "^2.0.3" - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -parse-asn1@^5.0.0, parse-asn1@^5.1.5: - version "5.1.6" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" - integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== - dependencies: - asn1.js "^5.2.0" - browserify-aes "^1.0.0" - evp_bytestokey "^1.0.0" - pbkdf2 "^3.0.3" - safe-buffer "^5.1.1" - -parse-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= - dependencies: - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - -parse-json@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== - dependencies: - "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-even-better-errors "^2.3.0" - lines-and-columns "^1.1.6" - -parse5@6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" - integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== - -parseurl@~1.3.2, parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -pascal-case@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb" - integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g== - dependencies: - no-case "^3.0.4" - tslib "^2.0.3" - -pascalcase@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= - -path-browserify@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" - integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -path-is-inside@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= - -path-key@^2.0.0, path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= - -path-key@^3.0.0, path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-parse@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== - -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= - -path-to-regexp@^1.7.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" - integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA== - dependencies: - isarray "0.0.1" - -path-type@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" - integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== - dependencies: - pify "^3.0.0" - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -pbkdf2@^3.0.3: - version "3.1.2" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" - integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== - dependencies: - create-hash "^1.1.2" - create-hmac "^1.1.4" - ripemd160 "^2.0.1" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= - -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3: - version "2.3.0" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" - integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== - -pify@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= - -pify@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" - integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= - -pify@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" - integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= - -pirates@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" - integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA== - dependencies: - node-modules-regexp "^1.0.0" - -pkg-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" - integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= - dependencies: - find-up "^2.1.0" - -pkg-dir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" - integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== - dependencies: - find-up "^3.0.0" - -pkg-dir@^4.1.0, pkg-dir@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" - integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== - dependencies: - find-up "^4.0.0" - -pkg-up@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" - integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA== - dependencies: - find-up "^3.0.0" - -pkg-up@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f" - integrity sha1-yBmscoBZpGHKscOImivjxJoATX8= - dependencies: - find-up "^2.1.0" - -pnp-webpack-plugin@1.6.4: - version "1.6.4" - resolved "https://registry.yarnpkg.com/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz#c9711ac4dc48a685dabafc86f8b6dd9f8df84149" - integrity sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg== - dependencies: - ts-pnp "^1.1.6" - -portfinder@^1.0.26: - version "1.0.28" - resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" - integrity sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA== - dependencies: - async "^2.6.2" - debug "^3.1.1" - mkdirp "^0.5.5" - -posix-character-classes@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= - -postcss-attribute-case-insensitive@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.2.tgz#d93e46b504589e94ac7277b0463226c68041a880" - integrity sha512-clkFxk/9pcdb4Vkn0hAHq3YnxBQ2p0CGD1dy24jN+reBck+EWxMbxSUqN4Yj7t0w8csl87K6p0gxBe1utkJsYA== - dependencies: - postcss "^7.0.2" - postcss-selector-parser "^6.0.2" - -postcss-browser-comments@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-browser-comments/-/postcss-browser-comments-3.0.0.tgz#1248d2d935fb72053c8e1f61a84a57292d9f65e9" - integrity sha512-qfVjLfq7HFd2e0HW4s1dvU8X080OZdG46fFbIBFjW7US7YPDcWfRvdElvwMJr2LI6hMmD+7LnH2HcmXTs+uOig== - dependencies: - postcss "^7" - -postcss-calc@^7.0.1: - version "7.0.5" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.5.tgz#f8a6e99f12e619c2ebc23cf6c486fdc15860933e" - integrity sha512-1tKHutbGtLtEZF6PT4JSihCHfIVldU72mZ8SdZHIYriIZ9fh9k9aWSppaT8rHsyI3dX+KSR+W+Ix9BMY3AODrg== - dependencies: - postcss "^7.0.27" - postcss-selector-parser "^6.0.2" - postcss-value-parser "^4.0.2" - -postcss-color-functional-notation@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz#5efd37a88fbabeb00a2966d1e53d98ced93f74e0" - integrity sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g== - dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-color-gray@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-color-gray/-/postcss-color-gray-5.0.0.tgz#532a31eb909f8da898ceffe296fdc1f864be8547" - integrity sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw== - dependencies: - "@csstools/convert-colors" "^1.4.0" - postcss "^7.0.5" - postcss-values-parser "^2.0.0" - -postcss-color-hex-alpha@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.3.tgz#a8d9ca4c39d497c9661e374b9c51899ef0f87388" - integrity sha512-PF4GDel8q3kkreVXKLAGNpHKilXsZ6xuu+mOQMHWHLPNyjiUBOr75sp5ZKJfmv1MCus5/DWUGcK9hm6qHEnXYw== - dependencies: - postcss "^7.0.14" - postcss-values-parser "^2.0.1" - -postcss-color-mod-function@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz#816ba145ac11cc3cb6baa905a75a49f903e4d31d" - integrity sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ== - dependencies: - "@csstools/convert-colors" "^1.4.0" - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-color-rebeccapurple@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-4.0.1.tgz#c7a89be872bb74e45b1e3022bfe5748823e6de77" - integrity sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g== - dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-colormin@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-4.0.3.tgz#ae060bce93ed794ac71264f08132d550956bd381" - integrity sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw== - dependencies: - browserslist "^4.0.0" - color "^3.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-convert-values@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz#ca3813ed4da0f812f9d43703584e449ebe189a7f" - integrity sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ== - dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-custom-media@^7.0.8: - version "7.0.8" - resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz#fffd13ffeffad73621be5f387076a28b00294e0c" - integrity sha512-c9s5iX0Ge15o00HKbuRuTqNndsJUbaXdiNsksnVH8H4gdc+zbLzr/UasOwNG6CTDpLFekVY4672eWdiiWu2GUg== - dependencies: - postcss "^7.0.14" - -postcss-custom-properties@^8.0.11: - version "8.0.11" - resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz#2d61772d6e92f22f5e0d52602df8fae46fa30d97" - integrity sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA== - dependencies: - postcss "^7.0.17" - postcss-values-parser "^2.0.1" - -postcss-custom-selectors@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/postcss-custom-selectors/-/postcss-custom-selectors-5.1.2.tgz#64858c6eb2ecff2fb41d0b28c9dd7b3db4de7fba" - integrity sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w== - dependencies: - postcss "^7.0.2" - postcss-selector-parser "^5.0.0-rc.3" - -postcss-dir-pseudo-class@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-5.0.0.tgz#6e3a4177d0edb3abcc85fdb6fbb1c26dabaeaba2" - integrity sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw== - dependencies: - postcss "^7.0.2" - postcss-selector-parser "^5.0.0-rc.3" - -postcss-discard-comments@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz#1fbabd2c246bff6aaad7997b2b0918f4d7af4033" - integrity sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg== - dependencies: - postcss "^7.0.0" - -postcss-discard-duplicates@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz#3fe133cd3c82282e550fc9b239176a9207b784eb" - integrity sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ== - dependencies: - postcss "^7.0.0" - -postcss-discard-empty@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz#c8c951e9f73ed9428019458444a02ad90bb9f765" - integrity sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w== - dependencies: - postcss "^7.0.0" - -postcss-discard-overridden@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz#652aef8a96726f029f5e3e00146ee7a4e755ff57" - integrity sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg== - dependencies: - postcss "^7.0.0" - -postcss-double-position-gradients@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz#fc927d52fddc896cb3a2812ebc5df147e110522e" - integrity sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA== - dependencies: - postcss "^7.0.5" - postcss-values-parser "^2.0.0" - -postcss-env-function@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/postcss-env-function/-/postcss-env-function-2.0.2.tgz#0f3e3d3c57f094a92c2baf4b6241f0b0da5365d7" - integrity sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw== - dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-flexbugs-fixes@4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-4.2.1.tgz#9218a65249f30897deab1033aced8578562a6690" - integrity sha512-9SiofaZ9CWpQWxOwRh1b/r85KD5y7GgvsNt1056k6OYLvWUun0czCvogfJgylC22uJTwW1KzY3Gz65NZRlvoiQ== - dependencies: - postcss "^7.0.26" - -postcss-focus-visible@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz#477d107113ade6024b14128317ade2bd1e17046e" - integrity sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g== - dependencies: - postcss "^7.0.2" - -postcss-focus-within@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-focus-within/-/postcss-focus-within-3.0.0.tgz#763b8788596cee9b874c999201cdde80659ef680" - integrity sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w== - dependencies: - postcss "^7.0.2" - -postcss-font-variant@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-font-variant/-/postcss-font-variant-4.0.1.tgz#42d4c0ab30894f60f98b17561eb5c0321f502641" - integrity sha512-I3ADQSTNtLTTd8uxZhtSOrTCQ9G4qUVKPjHiDk0bV75QSxXjVWiJVJ2VLdspGUi9fbW9BcjKJoRvxAH1pckqmA== - dependencies: - postcss "^7.0.2" - -postcss-gap-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-gap-properties/-/postcss-gap-properties-2.0.0.tgz#431c192ab3ed96a3c3d09f2ff615960f902c1715" - integrity sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg== - dependencies: - postcss "^7.0.2" - -postcss-image-set-function@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz#28920a2f29945bed4c3198d7df6496d410d3f288" - integrity sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw== - dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-initial@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-3.0.4.tgz#9d32069a10531fe2ecafa0b6ac750ee0bc7efc53" - integrity sha512-3RLn6DIpMsK1l5UUy9jxQvoDeUN4gP939tDcKUHD/kM8SGSKbFAnvkpFpj3Bhtz3HGk1jWY5ZNWX6mPta5M9fg== - dependencies: - postcss "^7.0.2" - -postcss-lab-function@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz#bb51a6856cd12289ab4ae20db1e3821ef13d7d2e" - integrity sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg== - dependencies: - "@csstools/convert-colors" "^1.4.0" - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-load-config@^2.0.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.1.2.tgz#c5ea504f2c4aef33c7359a34de3573772ad7502a" - integrity sha512-/rDeGV6vMUo3mwJZmeHfEDvwnTKKqQ0S7OHUi/kJvvtx3aWtyWG2/0ZWnzCt2keEclwN6Tf0DST2v9kITdOKYw== - dependencies: - cosmiconfig "^5.0.0" - import-cwd "^2.0.0" - -postcss-loader@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-3.0.0.tgz#6b97943e47c72d845fa9e03f273773d4e8dd6c2d" - integrity sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA== - dependencies: - loader-utils "^1.1.0" - postcss "^7.0.0" - postcss-load-config "^2.0.0" - schema-utils "^1.0.0" - -postcss-logical@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-logical/-/postcss-logical-3.0.0.tgz#2495d0f8b82e9f262725f75f9401b34e7b45d5b5" - integrity sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA== - dependencies: - postcss "^7.0.2" - -postcss-media-minmax@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz#b75bb6cbc217c8ac49433e12f22048814a4f5ed5" - integrity sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw== - dependencies: - postcss "^7.0.2" - -postcss-merge-longhand@^4.0.11: - version "4.0.11" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz#62f49a13e4a0ee04e7b98f42bb16062ca2549e24" - integrity sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw== - dependencies: - css-color-names "0.0.4" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - stylehacks "^4.0.0" - -postcss-merge-rules@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz#362bea4ff5a1f98e4075a713c6cb25aefef9a650" - integrity sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ== - dependencies: - browserslist "^4.0.0" - caniuse-api "^3.0.0" - cssnano-util-same-parent "^4.0.0" - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" - vendors "^1.0.0" - -postcss-minify-font-values@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz#cd4c344cce474343fac5d82206ab2cbcb8afd5a6" - integrity sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg== - dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-minify-gradients@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz#93b29c2ff5099c535eecda56c4aa6e665a663471" - integrity sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q== - dependencies: - cssnano-util-get-arguments "^4.0.0" - is-color-stop "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-minify-params@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz#6b9cef030c11e35261f95f618c90036d680db874" - integrity sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg== - dependencies: - alphanum-sort "^1.0.0" - browserslist "^4.0.0" - cssnano-util-get-arguments "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - uniqs "^2.0.0" - -postcss-minify-selectors@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz#e2e5eb40bfee500d0cd9243500f5f8ea4262fbd8" - integrity sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g== - dependencies: - alphanum-sort "^1.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" - -postcss-modules-extract-imports@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e" - integrity sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ== - dependencies: - postcss "^7.0.5" - -postcss-modules-local-by-default@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz#bb14e0cc78279d504dbdcbfd7e0ca28993ffbbb0" - integrity sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw== - dependencies: - icss-utils "^4.1.1" - postcss "^7.0.32" - postcss-selector-parser "^6.0.2" - postcss-value-parser "^4.1.0" - -postcss-modules-scope@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz#385cae013cc7743f5a7d7602d1073a89eaae62ee" - integrity sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ== - dependencies: - postcss "^7.0.6" - postcss-selector-parser "^6.0.0" - -postcss-modules-values@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10" - integrity sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg== - dependencies: - icss-utils "^4.0.0" - postcss "^7.0.6" - -postcss-nesting@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-7.0.1.tgz#b50ad7b7f0173e5b5e3880c3501344703e04c052" - integrity sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg== - dependencies: - postcss "^7.0.2" - -postcss-normalize-charset@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz#8b35add3aee83a136b0471e0d59be58a50285dd4" - integrity sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g== - dependencies: - postcss "^7.0.0" - -postcss-normalize-display-values@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz#0dbe04a4ce9063d4667ed2be476bb830c825935a" - integrity sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ== - dependencies: - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-positions@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz#05f757f84f260437378368a91f8932d4b102917f" - integrity sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA== - dependencies: - cssnano-util-get-arguments "^4.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-repeat-style@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz#c4ebbc289f3991a028d44751cbdd11918b17910c" - integrity sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q== - dependencies: - cssnano-util-get-arguments "^4.0.0" - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-string@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz#cd44c40ab07a0c7a36dc5e99aace1eca4ec2690c" - integrity sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA== - dependencies: - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-timing-functions@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz#8e009ca2a3949cdaf8ad23e6b6ab99cb5e7d28d9" - integrity sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A== - dependencies: - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-unicode@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz#841bd48fdcf3019ad4baa7493a3d363b52ae1cfb" - integrity sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg== - dependencies: - browserslist "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-url@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz#10e437f86bc7c7e58f7b9652ed878daaa95faae1" - integrity sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA== - dependencies: - is-absolute-url "^2.0.0" - normalize-url "^3.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-whitespace@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz#bf1d4070fe4fcea87d1348e825d8cc0c5faa7d82" - integrity sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA== - dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize@8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize/-/postcss-normalize-8.0.1.tgz#90e80a7763d7fdf2da6f2f0f82be832ce4f66776" - integrity sha512-rt9JMS/m9FHIRroDDBGSMsyW1c0fkvOJPy62ggxSHUldJO7B195TqFMqIf+lY5ezpDcYOV4j86aUp3/XbxzCCQ== - dependencies: - "@csstools/normalize.css" "^10.1.0" - browserslist "^4.6.2" - postcss "^7.0.17" - postcss-browser-comments "^3.0.0" - sanitize.css "^10.0.0" - -postcss-ordered-values@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz#0cf75c820ec7d5c4d280189559e0b571ebac0eee" - integrity sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw== - dependencies: - cssnano-util-get-arguments "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-overflow-shorthand@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-overflow-shorthand/-/postcss-overflow-shorthand-2.0.0.tgz#31ecf350e9c6f6ddc250a78f0c3e111f32dd4c30" - integrity sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g== - dependencies: - postcss "^7.0.2" - -postcss-page-break@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-page-break/-/postcss-page-break-2.0.0.tgz#add52d0e0a528cabe6afee8b46e2abb277df46bf" - integrity sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ== - dependencies: - postcss "^7.0.2" - -postcss-place@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-place/-/postcss-place-4.0.1.tgz#e9f39d33d2dc584e46ee1db45adb77ca9d1dcc62" - integrity sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg== - dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-preset-env@6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-6.7.0.tgz#c34ddacf8f902383b35ad1e030f178f4cdf118a5" - integrity sha512-eU4/K5xzSFwUFJ8hTdTQzo2RBLbDVt83QZrAvI07TULOkmyQlnYlpwep+2yIK+K+0KlZO4BvFcleOCCcUtwchg== - dependencies: - autoprefixer "^9.6.1" - browserslist "^4.6.4" - caniuse-lite "^1.0.30000981" - css-blank-pseudo "^0.1.4" - css-has-pseudo "^0.10.0" - css-prefers-color-scheme "^3.1.1" - cssdb "^4.4.0" - postcss "^7.0.17" - postcss-attribute-case-insensitive "^4.0.1" - postcss-color-functional-notation "^2.0.1" - postcss-color-gray "^5.0.0" - postcss-color-hex-alpha "^5.0.3" - postcss-color-mod-function "^3.0.3" - postcss-color-rebeccapurple "^4.0.1" - postcss-custom-media "^7.0.8" - postcss-custom-properties "^8.0.11" - postcss-custom-selectors "^5.1.2" - postcss-dir-pseudo-class "^5.0.0" - postcss-double-position-gradients "^1.0.0" - postcss-env-function "^2.0.2" - postcss-focus-visible "^4.0.0" - postcss-focus-within "^3.0.0" - postcss-font-variant "^4.0.0" - postcss-gap-properties "^2.0.0" - postcss-image-set-function "^3.0.1" - postcss-initial "^3.0.0" - postcss-lab-function "^2.0.1" - postcss-logical "^3.0.0" - postcss-media-minmax "^4.0.0" - postcss-nesting "^7.0.0" - postcss-overflow-shorthand "^2.0.0" - postcss-page-break "^2.0.0" - postcss-place "^4.0.1" - postcss-pseudo-class-any-link "^6.0.0" - postcss-replace-overflow-wrap "^3.0.0" - postcss-selector-matches "^4.0.0" - postcss-selector-not "^4.0.0" - -postcss-pseudo-class-any-link@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-6.0.0.tgz#2ed3eed393b3702879dec4a87032b210daeb04d1" - integrity sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew== - dependencies: - postcss "^7.0.2" - postcss-selector-parser "^5.0.0-rc.3" - -postcss-reduce-initial@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz#7fd42ebea5e9c814609639e2c2e84ae270ba48df" - integrity sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA== - dependencies: - browserslist "^4.0.0" - caniuse-api "^3.0.0" - has "^1.0.0" - postcss "^7.0.0" - -postcss-reduce-transforms@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz#17efa405eacc6e07be3414a5ca2d1074681d4e29" - integrity sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg== - dependencies: - cssnano-util-get-match "^4.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-replace-overflow-wrap@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz#61b360ffdaedca84c7c918d2b0f0d0ea559ab01c" - integrity sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw== - dependencies: - postcss "^7.0.2" - -postcss-safe-parser@5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-safe-parser/-/postcss-safe-parser-5.0.2.tgz#459dd27df6bc2ba64608824ba39e45dacf5e852d" - integrity sha512-jDUfCPJbKOABhwpUKcqCVbbXiloe/QXMcbJ6Iipf3sDIihEzTqRCeMBfRaOHxhBuTYqtASrI1KJWxzztZU4qUQ== - dependencies: - postcss "^8.1.0" - -postcss-selector-matches@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz#71c8248f917ba2cc93037c9637ee09c64436fcff" - integrity sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww== - dependencies: - balanced-match "^1.0.0" - postcss "^7.0.2" - -postcss-selector-not@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-selector-not/-/postcss-selector-not-4.0.1.tgz#263016eef1cf219e0ade9a913780fc1f48204cbf" - integrity sha512-YolvBgInEK5/79C+bdFMyzqTg6pkYqDbzZIST/PDMqa/o3qtXenD05apBG2jLgT0/BQ77d4U2UK12jWpilqMAQ== - dependencies: - balanced-match "^1.0.0" - postcss "^7.0.2" - -postcss-selector-parser@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz#b310f5c4c0fdaf76f94902bbaa30db6aa84f5270" - integrity sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA== - dependencies: - dot-prop "^5.2.0" - indexes-of "^1.0.1" - uniq "^1.0.1" - -postcss-selector-parser@^5.0.0-rc.3, postcss-selector-parser@^5.0.0-rc.4: - version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz#249044356697b33b64f1a8f7c80922dddee7195c" - integrity sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ== - dependencies: - cssesc "^2.0.0" - indexes-of "^1.0.1" - uniq "^1.0.1" - -postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2: - version "6.0.6" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz#2c5bba8174ac2f6981ab631a42ab0ee54af332ea" - integrity sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg== - dependencies: - cssesc "^3.0.0" - util-deprecate "^1.0.2" - -postcss-svgo@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.3.tgz#343a2cdbac9505d416243d496f724f38894c941e" - integrity sha512-NoRbrcMWTtUghzuKSoIm6XV+sJdvZ7GZSc3wdBN0W19FTtp2ko8NqLsgoh/m9CzNhU3KLPvQmjIwtaNFkaFTvw== - dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - svgo "^1.0.0" - -postcss-unique-selectors@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz#9446911f3289bfd64c6d680f073c03b1f9ee4bac" - integrity sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg== - dependencies: - alphanum-sort "^1.0.0" - postcss "^7.0.0" - uniqs "^2.0.0" - -postcss-value-parser@^3.0.0: - version "3.3.1" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" - integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== - -postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" - integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== - -postcss-values-parser@^2.0.0, postcss-values-parser@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz#da8b472d901da1e205b47bdc98637b9e9e550e5f" - integrity sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg== - dependencies: - flatten "^1.0.2" - indexes-of "^1.0.1" - uniq "^1.0.1" - -postcss@7.0.21: - version "7.0.21" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.21.tgz#06bb07824c19c2021c5d056d5b10c35b989f7e17" - integrity sha512-uIFtJElxJo29QC753JzhidoAhvp/e/Exezkdhfmt8AymWT6/5B7W1WmponYWkHk2eg6sONyTch0A3nkMPun3SQ== - dependencies: - chalk "^2.4.2" - source-map "^0.6.1" - supports-color "^6.1.0" - -postcss@^7, postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.26, postcss@^7.0.27, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: - version "7.0.35" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.35.tgz#d2be00b998f7f211d8a276974079f2e92b970e24" - integrity sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg== - dependencies: - chalk "^2.4.2" - source-map "^0.6.1" - supports-color "^6.1.0" - -postcss@^8.1.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.0.tgz#b1a713f6172ca427e3f05ef1303de8b65683325f" - integrity sha512-+ogXpdAjWGa+fdYY5BQ96V/6tAo+TdSSIMP5huJBIygdWwKtVoB5JWZ7yUd4xZ8r+8Kvvx4nyg/PQ071H4UtcQ== - dependencies: - colorette "^1.2.2" - nanoid "^3.1.23" - source-map-js "^0.6.2" - -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= - -prepend-http@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" - integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= - -prettier-linter-helpers@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" - integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== - dependencies: - fast-diff "^1.1.2" - -prettier@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.0.tgz#b6a5bf1284026ae640f17f7ff5658a7567fc0d18" - integrity sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w== - -pretty-bytes@^5.3.0: - version "5.6.0" - resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" - integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg== - -pretty-error@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.2.tgz#be89f82d81b1c86ec8fdfbc385045882727f93b6" - integrity sha512-EY5oDzmsX5wvuynAByrmY0P0hcp+QpnAKbJng2A2MPjVKXCxrDSUkzghVJ4ZGPIv+JC4gX8fPUWscC0RtjsWGw== - dependencies: - lodash "^4.17.20" - renderkid "^2.0.4" - -pretty-format@^26.0.0, pretty-format@^26.6.0, pretty-format@^26.6.2: - version "26.6.2" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93" - integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg== - dependencies: - "@jest/types" "^26.6.2" - ansi-regex "^5.0.0" - ansi-styles "^4.0.0" - react-is "^17.0.1" - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -process@^0.11.10: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= - -progress@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" - integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== - -promise-inflight@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" - integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= - -promise@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/promise/-/promise-8.1.0.tgz#697c25c3dfe7435dd79fcd58c38a135888eaf05e" - integrity sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q== - dependencies: - asap "~2.0.6" - -prompts@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.0.tgz#4aa5de0723a231d1ee9121c40fdf663df73f61d7" - integrity sha512-awZAKrk3vN6CroQukBL+R9051a4R3zCZBlJm/HBfrSZ8iTpYix3VX1vU4mveiLpiwmOJT4wokTF9m6HUk4KqWQ== - dependencies: - kleur "^3.0.3" - sisteransi "^1.0.5" - -prompts@^2.0.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.1.tgz#befd3b1195ba052f9fd2fde8a486c4e82ee77f61" - integrity sha512-EQyfIuO2hPDsX1L/blblV+H7I0knhgAd82cVneCwcdND9B8AuCDuRcBH6yIcG4dFzlOUqbazQqwGjx5xmsNLuQ== - dependencies: - kleur "^3.0.3" - sisteransi "^1.0.5" - -prop-types-extra@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/prop-types-extra/-/prop-types-extra-1.1.1.tgz#58c3b74cbfbb95d304625975aa2f0848329a010b" - integrity sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew== - dependencies: - react-is "^16.3.2" - warning "^4.0.0" - -prop-types@^15.6.2, prop-types@^15.7.2: - version "15.7.2" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" - integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== - dependencies: - loose-envify "^1.4.0" - object-assign "^4.1.1" - react-is "^16.8.1" - -proxy-addr@~2.0.5: - version "2.0.6" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf" - integrity sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw== - dependencies: - forwarded "~0.1.2" - ipaddr.js "1.9.1" - -prr@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" - integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= - -psl@^1.1.28, psl@^1.1.33: - version "1.8.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" - integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== - -public-encrypt@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" - integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== - dependencies: - bn.js "^4.1.0" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - parse-asn1 "^5.0.0" - randombytes "^2.0.1" - safe-buffer "^5.1.2" - -pump@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" - integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -pumpify@^1.3.3: - version "1.5.1" - resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" - integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== - dependencies: - duplexify "^3.6.0" - inherits "^2.0.3" - pump "^2.0.0" - -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= - -punycode@^1.2.4: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= - -punycode@^2.1.0, punycode@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -q@^1.1.2: - version "1.5.1" - resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" - integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= - -qs@6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" - integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== - -qs@~6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== - -query-string@^4.1.0: - version "4.3.4" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" - integrity sha1-u7aTucqRXCMlFbIosaArYJBD2+s= - dependencies: - object-assign "^4.1.0" - strict-uri-encode "^1.0.0" - -querystring-es3@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" - integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= - -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= - -querystring@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.1.tgz#40d77615bb09d16902a85c3e38aa8b5ed761c2dd" - integrity sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg== - -querystringify@^2.1.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" - integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== - -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -raf@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39" - integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA== - dependencies: - performance-now "^2.1.0" - -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -randomfill@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" - integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== - dependencies: - randombytes "^2.0.5" - safe-buffer "^5.1.0" - -range-parser@^1.2.1, range-parser@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -raw-body@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" - integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== - dependencies: - bytes "3.1.0" - http-errors "1.7.2" - iconv-lite "0.4.24" - unpipe "1.0.0" - -react-app-polyfill@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/react-app-polyfill/-/react-app-polyfill-2.0.0.tgz#a0bea50f078b8a082970a9d853dc34b6dcc6a3cf" - integrity sha512-0sF4ny9v/B7s6aoehwze9vJNWcmCemAUYBVasscVr92+UYiEqDXOxfKjXN685mDaMRNF3WdhHQs76oTODMocFA== - dependencies: - core-js "^3.6.5" - object-assign "^4.1.1" - promise "^8.1.0" - raf "^3.4.1" - regenerator-runtime "^0.13.7" - whatwg-fetch "^3.4.1" - -react-bootstrap@^1.5.2: - version "1.6.0" - resolved "https://registry.yarnpkg.com/react-bootstrap/-/react-bootstrap-1.6.0.tgz#5b4f160ce0cd22784cf4271ca90550b4891fdd42" - integrity sha512-PaeOGeRC2+JH9Uf1PukJgXcIpfGlrKKHEBZIArymjenYzSJ/RhO2UdNX+e7nalsCFFZLRRgQ0/FKkscW2LmmRg== - dependencies: - "@babel/runtime" "^7.13.8" - "@restart/context" "^2.1.4" - "@restart/hooks" "^0.3.26" - "@types/classnames" "^2.2.10" - "@types/invariant" "^2.2.33" - "@types/prop-types" "^15.7.3" - "@types/react" ">=16.9.35" - "@types/react-transition-group" "^4.4.1" - "@types/warning" "^3.0.0" - classnames "^2.2.6" - dom-helpers "^5.1.2" - invariant "^2.2.4" - prop-types "^15.7.2" - prop-types-extra "^1.1.0" - react-overlays "^5.0.0" - react-transition-group "^4.4.1" - uncontrollable "^7.2.1" - warning "^4.0.3" - -react-dev-utils@^11.0.3: - version "11.0.4" - resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-11.0.4.tgz#a7ccb60257a1ca2e0efe7a83e38e6700d17aa37a" - integrity sha512-dx0LvIGHcOPtKbeiSUM4jqpBl3TcY7CDjZdfOIcKeznE7BWr9dg0iPG90G5yfVQ+p/rGNMXdbfStvzQZEVEi4A== - dependencies: - "@babel/code-frame" "7.10.4" - address "1.1.2" - browserslist "4.14.2" - chalk "2.4.2" - cross-spawn "7.0.3" - detect-port-alt "1.1.6" - escape-string-regexp "2.0.0" - filesize "6.1.0" - find-up "4.1.0" - fork-ts-checker-webpack-plugin "4.1.6" - global-modules "2.0.0" - globby "11.0.1" - gzip-size "5.1.1" - immer "8.0.1" - is-root "2.1.0" - loader-utils "2.0.0" - open "^7.0.2" - pkg-up "3.1.0" - prompts "2.4.0" - react-error-overlay "^6.0.9" - recursive-readdir "2.2.2" - shell-quote "1.7.2" - strip-ansi "6.0.0" - text-table "0.2.0" - -react-dom@^17.0.2: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" - integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - scheduler "^0.20.2" - -react-error-overlay@^6.0.9: - version "6.0.9" - resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.9.tgz#3c743010c9359608c375ecd6bc76f35d93995b0a" - integrity sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew== - -react-is@^16.3.2, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" - integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== - -react-is@^17.0.1: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" - integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== - -react-lifecycles-compat@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" - integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== - -react-overlays@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/react-overlays/-/react-overlays-5.0.1.tgz#7e2c3cd3c0538048b0b7451d203b1289c561b7f2" - integrity sha512-plwUJieTBbLSrgvQ4OkkbTD/deXgxiJdNuKzo6n1RWE3OVnQIU5hffCGS/nvIuu6LpXFs2majbzaXY8rcUVdWA== - dependencies: - "@babel/runtime" "^7.13.8" - "@popperjs/core" "^2.8.6" - "@restart/hooks" "^0.3.26" - "@types/warning" "^3.0.0" - dom-helpers "^5.2.0" - prop-types "^15.7.2" - uncontrollable "^7.2.1" - warning "^4.0.3" - -react-refresh@^0.8.3: - version "0.8.3" - resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f" - integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg== - -react-router-dom@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.2.0.tgz#9e65a4d0c45e13289e66c7b17c7e175d0ea15662" - integrity sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA== - dependencies: - "@babel/runtime" "^7.1.2" - history "^4.9.0" - loose-envify "^1.3.1" - prop-types "^15.6.2" - react-router "5.2.0" - tiny-invariant "^1.0.2" - tiny-warning "^1.0.0" - -react-router@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.2.0.tgz#424e75641ca8747fbf76e5ecca69781aa37ea293" - integrity sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw== - dependencies: - "@babel/runtime" "^7.1.2" - history "^4.9.0" - hoist-non-react-statics "^3.1.0" - loose-envify "^1.3.1" - mini-create-react-context "^0.4.0" - path-to-regexp "^1.7.0" - prop-types "^15.6.2" - react-is "^16.6.0" - tiny-invariant "^1.0.2" - tiny-warning "^1.0.0" - -react-scripts@4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-4.0.3.tgz#b1cafed7c3fa603e7628ba0f187787964cb5d345" - integrity sha512-S5eO4vjUzUisvkIPB7jVsKtuH2HhWcASREYWHAQ1FP5HyCv3xgn+wpILAEWkmy+A+tTNbSZClhxjT3qz6g4L1A== - dependencies: - "@babel/core" "7.12.3" - "@pmmmwh/react-refresh-webpack-plugin" "0.4.3" - "@svgr/webpack" "5.5.0" - "@typescript-eslint/eslint-plugin" "^4.5.0" - "@typescript-eslint/parser" "^4.5.0" - babel-eslint "^10.1.0" - babel-jest "^26.6.0" - babel-loader "8.1.0" - babel-plugin-named-asset-import "^0.3.7" - babel-preset-react-app "^10.0.0" - bfj "^7.0.2" - camelcase "^6.1.0" - case-sensitive-paths-webpack-plugin "2.3.0" - css-loader "4.3.0" - dotenv "8.2.0" - dotenv-expand "5.1.0" - eslint "^7.11.0" - eslint-config-react-app "^6.0.0" - eslint-plugin-flowtype "^5.2.0" - eslint-plugin-import "^2.22.1" - eslint-plugin-jest "^24.1.0" - eslint-plugin-jsx-a11y "^6.3.1" - eslint-plugin-react "^7.21.5" - eslint-plugin-react-hooks "^4.2.0" - eslint-plugin-testing-library "^3.9.2" - eslint-webpack-plugin "^2.5.2" - file-loader "6.1.1" - fs-extra "^9.0.1" - html-webpack-plugin "4.5.0" - identity-obj-proxy "3.0.0" - jest "26.6.0" - jest-circus "26.6.0" - jest-resolve "26.6.0" - jest-watch-typeahead "0.6.1" - mini-css-extract-plugin "0.11.3" - optimize-css-assets-webpack-plugin "5.0.4" - pnp-webpack-plugin "1.6.4" - postcss-flexbugs-fixes "4.2.1" - postcss-loader "3.0.0" - postcss-normalize "8.0.1" - postcss-preset-env "6.7.0" - postcss-safe-parser "5.0.2" - prompts "2.4.0" - react-app-polyfill "^2.0.0" - react-dev-utils "^11.0.3" - react-refresh "^0.8.3" - resolve "1.18.1" - resolve-url-loader "^3.1.2" - sass-loader "^10.0.5" - semver "7.3.2" - style-loader "1.3.0" - terser-webpack-plugin "4.2.3" - ts-pnp "1.2.0" - url-loader "4.1.1" - webpack "4.44.2" - webpack-dev-server "3.11.1" - webpack-manifest-plugin "2.2.0" - workbox-webpack-plugin "5.1.4" - optionalDependencies: - fsevents "^2.1.3" - -react-transition-group@^4.4.1: - version "4.4.1" - resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.1.tgz#63868f9325a38ea5ee9535d828327f85773345c9" - integrity sha512-Djqr7OQ2aPUiYurhPalTrVy9ddmFCCzwhqQmtN+J3+3DzLO209Fdr70QrN8Z3DsglWql6iY1lDWAfpFiBtuKGw== - dependencies: - "@babel/runtime" "^7.5.5" - dom-helpers "^5.0.1" - loose-envify "^1.4.0" - prop-types "^15.6.2" - -react@^17.0.2: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" - integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - -read-pkg-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" - integrity sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc= - dependencies: - find-up "^2.0.0" - read-pkg "^3.0.0" - -read-pkg-up@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" - integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== - dependencies: - find-up "^4.1.0" - read-pkg "^5.2.0" - type-fest "^0.8.1" - -read-pkg@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" - integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= - dependencies: - load-json-file "^4.0.0" - normalize-package-data "^2.3.2" - path-type "^3.0.0" - -read-pkg@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" - integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== - dependencies: - "@types/normalize-package-data" "^2.4.0" - normalize-package-data "^2.5.0" - parse-json "^5.0.0" - type-fest "^0.6.0" - -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readdirp@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" - integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== - dependencies: - graceful-fs "^4.1.11" - micromatch "^3.1.10" - readable-stream "^2.0.2" - -readdirp@~3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" - integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ== - dependencies: - picomatch "^2.2.1" - -recursive-readdir@2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.2.tgz#9946fb3274e1628de6e36b2f6714953b4845094f" - integrity sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg== - dependencies: - minimatch "3.0.4" - -redent@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" - integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== - dependencies: - indent-string "^4.0.0" - strip-indent "^3.0.0" - -regenerate-unicode-properties@^8.2.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" - integrity sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA== - dependencies: - regenerate "^1.4.0" - -regenerate@^1.4.0: - version "1.4.2" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" - integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== - -regenerator-runtime@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== - -regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.7: - version "0.13.7" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" - integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== - -regenerator-transform@^0.14.2: - version "0.14.5" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4" - integrity sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw== - dependencies: - "@babel/runtime" "^7.8.4" - -regex-not@^1.0.0, regex-not@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== - dependencies: - extend-shallow "^3.0.2" - safe-regex "^1.1.0" - -regex-parser@^2.2.11: - version "2.2.11" - resolved "https://registry.yarnpkg.com/regex-parser/-/regex-parser-2.2.11.tgz#3b37ec9049e19479806e878cabe7c1ca83ccfe58" - integrity sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q== - -regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz#7ef352ae8d159e758c0eadca6f8fcb4eef07be26" - integrity sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -regexpp@^3.0.0, regexpp@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" - integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== - -regexpu-core@^4.7.1: - version "4.7.1" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.1.tgz#2dea5a9a07233298fbf0db91fa9abc4c6e0f8ad6" - integrity sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ== - dependencies: - regenerate "^1.4.0" - regenerate-unicode-properties "^8.2.0" - regjsgen "^0.5.1" - regjsparser "^0.6.4" - unicode-match-property-ecmascript "^1.0.4" - unicode-match-property-value-ecmascript "^1.2.0" - -regjsgen@^0.5.1: - version "0.5.2" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" - integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A== - -regjsparser@^0.6.4: - version "0.6.9" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.9.tgz#b489eef7c9a2ce43727627011429cf833a7183e6" - integrity sha512-ZqbNRz1SNjLAiYuwY0zoXW8Ne675IX5q+YHioAGbCw4X96Mjl2+dcX9B2ciaeyYjViDAfvIjFpQjJgLttTEERQ== - dependencies: - jsesc "~0.5.0" - -relateurl@^0.2.7: - version "0.2.7" - resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" - integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= - -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= - -renderkid@^2.0.4: - version "2.0.5" - resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-2.0.5.tgz#483b1ac59c6601ab30a7a596a5965cabccfdd0a5" - integrity sha512-ccqoLg+HLOHq1vdfYNm4TBeaCDIi1FLt3wGojTDSvdewUv65oTmI3cnT2E4hRjl1gzKZIPK+KZrXzlUYKnR+vQ== - dependencies: - css-select "^2.0.2" - dom-converter "^0.2" - htmlparser2 "^3.10.1" - lodash "^4.17.20" - strip-ansi "^3.0.0" - -repeat-element@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" - integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== - -repeat-string@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - -request-promise-core@1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f" - integrity sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw== - dependencies: - lodash "^4.17.19" - -request-promise-native@^1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28" - integrity sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g== - dependencies: - request-promise-core "1.1.4" - stealthy-require "^1.1.1" - tough-cookie "^2.3.3" - -request@^2.88.2: - version "2.88.2" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" - integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.8.0" - caseless "~0.12.0" - combined-stream "~1.0.6" - extend "~3.0.2" - forever-agent "~0.6.1" - form-data "~2.3.2" - har-validator "~5.1.3" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - oauth-sign "~0.9.0" - performance-now "^2.1.0" - qs "~6.5.2" - safe-buffer "^5.1.2" - tough-cookie "~2.5.0" - tunnel-agent "^0.6.0" - uuid "^3.3.2" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= - -require-from-string@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" - integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== - -require-main-filename@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" - integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== - -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= - -resolve-cwd@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" - integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo= - dependencies: - resolve-from "^3.0.0" - -resolve-cwd@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" - integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== - dependencies: - resolve-from "^5.0.0" - -resolve-from@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - integrity sha1-six699nWiBvItuZTM17rywoYh0g= - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - -resolve-pathname@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd" - integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng== - -resolve-url-loader@^3.1.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-3.1.3.tgz#49ec68340f67d8d2ab6b401948d5def3ab2d0367" - integrity sha512-WbDSNFiKPPLem1ln+EVTE+bFUBdTTytfQZWbmghroaFNFaAVmGq0Saqw6F/306CwgPXsGwXVxbODE+3xAo/YbA== - dependencies: - adjust-sourcemap-loader "3.0.0" - camelcase "5.3.1" - compose-function "3.0.3" - convert-source-map "1.7.0" - es6-iterator "2.0.3" - loader-utils "1.2.3" - postcss "7.0.21" - rework "1.0.1" - rework-visit "1.0.0" - source-map "0.6.1" - -resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= - -resolve@1.18.1: - version "1.18.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.18.1.tgz#018fcb2c5b207d2a6424aee361c5a266da8f4130" - integrity sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA== - dependencies: - is-core-module "^2.0.0" - path-parse "^1.0.6" - -resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.18.1, resolve@^1.20.0, resolve@^1.3.2, resolve@^1.8.1: - version "1.20.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" - integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== - dependencies: - is-core-module "^2.2.0" - path-parse "^1.0.6" - -resolve@^2.0.0-next.3: - version "2.0.0-next.3" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.3.tgz#d41016293d4a8586a39ca5d9b5f15cbea1f55e46" - integrity sha512-W8LucSynKUIDu9ylraa7ueVZ7hc0uAgJBxVsQSKOXOyle8a93qXhcz+XAXZ8bIq2d6i4Ehddn6Evt+0/UwKk6Q== - dependencies: - is-core-module "^2.2.0" - path-parse "^1.0.6" - -ret@~0.1.10: - version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== - -retry@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" - integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rework-visit@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/rework-visit/-/rework-visit-1.0.0.tgz#9945b2803f219e2f7aca00adb8bc9f640f842c9a" - integrity sha1-mUWygD8hni96ygCtuLyfZA+ELJo= - -rework@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/rework/-/rework-1.0.1.tgz#30806a841342b54510aa4110850cd48534144aa7" - integrity sha1-MIBqhBNCtUUQqkEQhQzUhTQUSqc= - dependencies: - convert-source-map "^0.3.3" - css "^2.0.0" - -rgb-regex@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" - integrity sha1-wODWiC3w4jviVKR16O3UGRX+rrE= - -rgba-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" - integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= - -rimraf@^2.5.4, rimraf@^2.6.3: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - -rimraf@^3.0.0, 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== - dependencies: - glob "^7.1.3" - -ripemd160@^2.0.0, ripemd160@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - -rollup-plugin-babel@^4.3.3: - version "4.4.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-babel/-/rollup-plugin-babel-4.4.0.tgz#d15bd259466a9d1accbdb2fe2fff17c52d030acb" - integrity sha512-Lek/TYp1+7g7I+uMfJnnSJ7YWoD58ajo6Oarhlex7lvUce+RCKRuGRSgztDO3/MF/PuGKmUL5iTHKf208UNszw== - dependencies: - "@babel/helper-module-imports" "^7.0.0" - rollup-pluginutils "^2.8.1" - -rollup-plugin-terser@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-5.3.1.tgz#8c650062c22a8426c64268548957463bf981b413" - integrity sha512-1pkwkervMJQGFYvM9nscrUoncPwiKR/K+bHdjv6PFgRo3cgPHoRT83y2Aa3GvINj4539S15t/tpFPb775TDs6w== - dependencies: - "@babel/code-frame" "^7.5.5" - jest-worker "^24.9.0" - rollup-pluginutils "^2.8.2" - serialize-javascript "^4.0.0" - terser "^4.6.2" - -rollup-pluginutils@^2.8.1, rollup-pluginutils@^2.8.2: - version "2.8.2" - resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz#72f2af0748b592364dbd3389e600e5a9444a351e" - integrity sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ== - dependencies: - estree-walker "^0.6.1" - -rollup@^1.31.1: - version "1.32.1" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-1.32.1.tgz#4480e52d9d9e2ae4b46ba0d9ddeaf3163940f9c4" - integrity sha512-/2HA0Ec70TvQnXdzynFffkjA6XN+1e2pEv/uKS5Ulca40g2L7KuOE3riasHoNVHOsFD5KKZgDsMk1CP3Tw9s+A== - dependencies: - "@types/estree" "*" - "@types/node" "*" - acorn "^7.1.0" - -rsvp@^4.8.4: - version "4.8.5" - resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" - integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== - -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -run-queue@^1.0.0, run-queue@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" - integrity sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec= - dependencies: - aproba "^1.1.1" - -safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= - dependencies: - ret "~0.1.10" - -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -sane@^4.0.3: - version "4.1.0" - resolved "https://registry.yarnpkg.com/sane/-/sane-4.1.0.tgz#ed881fd922733a6c461bc189dc2b6c006f3ffded" - integrity sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA== - dependencies: - "@cnakazawa/watch" "^1.0.3" - anymatch "^2.0.0" - capture-exit "^2.0.0" - exec-sh "^0.3.2" - execa "^1.0.0" - fb-watchman "^2.0.0" - micromatch "^3.1.4" - minimist "^1.1.1" - walker "~1.0.5" - -sanitize.css@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/sanitize.css/-/sanitize.css-10.0.0.tgz#b5cb2547e96d8629a60947544665243b1dc3657a" - integrity sha512-vTxrZz4dX5W86M6oVWVdOVe72ZiPs41Oi7Z6Km4W5Turyz28mrXSJhhEBZoRtzJWIv3833WKVwLSDWWkEfupMg== - -sass-loader@^10.0.5: - version "10.2.0" - resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-10.2.0.tgz#3d64c1590f911013b3fa48a0b22a83d5e1494716" - integrity sha512-kUceLzC1gIHz0zNJPpqRsJyisWatGYNFRmv2CKZK2/ngMJgLqxTbXwe/hJ85luyvZkgqU3VlJ33UVF2T/0g6mw== - dependencies: - klona "^2.0.4" - loader-utils "^2.0.0" - neo-async "^2.6.2" - schema-utils "^3.0.0" - semver "^7.3.2" - -sax@~1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== - -saxes@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" - integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== - dependencies: - xmlchars "^2.2.0" - -scheduler@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91" - integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - -schema-utils@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" - integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== - dependencies: - ajv "^6.1.0" - ajv-errors "^1.0.0" - ajv-keywords "^3.1.0" - -schema-utils@^2.6.5, schema-utils@^2.7.0, schema-utils@^2.7.1: - version "2.7.1" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" - integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== - dependencies: - "@types/json-schema" "^7.0.5" - ajv "^6.12.4" - ajv-keywords "^3.5.2" - -schema-utils@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.0.0.tgz#67502f6aa2b66a2d4032b4279a2944978a0913ef" - integrity sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA== - dependencies: - "@types/json-schema" "^7.0.6" - ajv "^6.12.5" - ajv-keywords "^3.5.2" - -select-hose@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" - integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo= - -selfsigned@^1.10.8: - version "1.10.11" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.11.tgz#24929cd906fe0f44b6d01fb23999a739537acbe9" - integrity sha512-aVmbPOfViZqOZPgRBT0+3u4yZFHpmnIghLMlAcb5/xhp5ZtB/RVnKhz5vl2M32CLXAqR4kha9zfhNg0Lf/sxKA== - dependencies: - node-forge "^0.10.0" - -"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" - integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== - -semver@7.3.2: - version "7.3.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" - integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== - -semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -semver@^7.2.1, semver@^7.3.2: - version "7.3.5" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" - integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== - dependencies: - lru-cache "^6.0.0" - -send@0.17.1: - version "0.17.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" - integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== - dependencies: - debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "~1.7.2" - mime "1.6.0" - ms "2.1.1" - on-finished "~2.3.0" - range-parser "~1.2.1" - statuses "~1.5.0" - -serialize-javascript@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" - integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== - dependencies: - randombytes "^2.1.0" - -serialize-javascript@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-5.0.1.tgz#7886ec848049a462467a97d3d918ebb2aaf934f4" - integrity sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA== - dependencies: - randombytes "^2.1.0" - -serve-index@^1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" - integrity sha1-03aNabHn2C5c4FD/9bRTvqEqkjk= - dependencies: - accepts "~1.3.4" - batch "0.6.1" - debug "2.6.9" - escape-html "~1.0.3" - http-errors "~1.6.2" - mime-types "~2.1.17" - parseurl "~1.3.2" - -serve-static@1.14.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" - integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.17.1" - -set-blocking@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= - -set-value@^2.0.0, set-value@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" - integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.3" - split-string "^3.0.1" - -setimmediate@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= - -setprototypeof@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" - integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== - -setprototypeof@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" - integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== - -sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.11" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= - dependencies: - shebang-regex "^1.0.0" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -shell-quote@1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2" - integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg== - -shellwords@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" - integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== - -side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" - integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== - dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" - -signal-exit@^3.0.0, signal-exit@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" - integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== - -simple-swizzle@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" - integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= - dependencies: - is-arrayish "^0.3.1" - -sisteransi@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" - integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -slice-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" - integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== - dependencies: - ansi-styles "^4.0.0" - astral-regex "^2.0.0" - is-fullwidth-code-point "^3.0.0" - -snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - -snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== - dependencies: - kind-of "^3.2.0" - -snapdragon@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== - dependencies: - base "^0.11.1" - debug "^2.2.0" - define-property "^0.2.5" - extend-shallow "^2.0.1" - map-cache "^0.2.2" - source-map "^0.5.6" - source-map-resolve "^0.5.0" - use "^3.1.0" - -sockjs-client@^1.5.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.5.1.tgz#256908f6d5adfb94dabbdbd02c66362cca0f9ea6" - integrity sha512-VnVAb663fosipI/m6pqRXakEOw7nvd7TUgdr3PlR/8V2I95QIdwT8L4nMxhyU8SmDBHYXU1TOElaKOmKLfYzeQ== - dependencies: - debug "^3.2.6" - eventsource "^1.0.7" - faye-websocket "^0.11.3" - inherits "^2.0.4" - json3 "^3.3.3" - url-parse "^1.5.1" - -sockjs@^0.3.21: - version "0.3.21" - resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.21.tgz#b34ffb98e796930b60a0cfa11904d6a339a7d417" - integrity sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw== - dependencies: - faye-websocket "^0.11.3" - uuid "^3.4.0" - websocket-driver "^0.7.4" - -sort-keys@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" - integrity sha1-RBttTTRnmPG05J6JIK37oOVD+a0= - dependencies: - is-plain-obj "^1.0.0" - -source-list-map@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" - integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== - -source-map-js@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-0.6.2.tgz#0bb5de631b41cfbda6cfba8bd05a80efdfd2385e" - integrity sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug== - -source-map-resolve@^0.5.0, source-map-resolve@^0.5.2: - version "0.5.3" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" - integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== - dependencies: - atob "^2.1.2" - decode-uri-component "^0.2.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" - -source-map-resolve@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.6.0.tgz#3d9df87e236b53f16d01e58150fc7711138e5ed2" - integrity sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w== - dependencies: - atob "^2.1.2" - decode-uri-component "^0.2.0" - -source-map-support@^0.5.6, source-map-support@~0.5.12, source-map-support@~0.5.19: - version "0.5.19" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" - integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map-url@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" - integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== - -source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -source-map@^0.5.0, source-map@^0.5.6: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - -source-map@^0.7.3, source-map@~0.7.2: - version "0.7.3" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" - integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== - -sourcemap-codec@^1.4.4: - version "1.4.8" - resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" - integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== - -spdx-correct@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" - integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" - integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== - -spdx-expression-parse@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" - integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.9" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz#8a595135def9592bda69709474f1cbeea7c2467f" - integrity sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ== - -spdy-transport@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" - integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw== - dependencies: - debug "^4.1.0" - detect-node "^2.0.4" - hpack.js "^2.1.6" - obuf "^1.1.2" - readable-stream "^3.0.6" - wbuf "^1.7.3" - -spdy@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b" - integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA== - dependencies: - debug "^4.1.0" - handle-thing "^2.0.0" - http-deceiver "^1.2.7" - select-hose "^2.0.0" - spdy-transport "^3.0.0" - -split-string@^3.0.1, split-string@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== - dependencies: - extend-shallow "^3.0.0" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= - -sshpk@^1.7.0: - version "1.16.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" - integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - bcrypt-pbkdf "^1.0.0" - dashdash "^1.12.0" - ecc-jsbn "~0.1.1" - getpass "^0.1.1" - jsbn "~0.1.0" - safer-buffer "^2.0.2" - tweetnacl "~0.14.0" - -ssri@^6.0.1: - version "6.0.2" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5" - integrity sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q== - dependencies: - figgy-pudding "^3.5.1" - -ssri@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af" - integrity sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ== - dependencies: - minipass "^3.1.1" - -stable@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" - integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== - -stack-utils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.3.tgz#cd5f030126ff116b78ccb3c027fe302713b61277" - integrity sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw== - dependencies: - escape-string-regexp "^2.0.0" - -stackframe@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.2.0.tgz#52429492d63c62eb989804c11552e3d22e779303" - integrity sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA== - -static-extend@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= - dependencies: - define-property "^0.2.5" - object-copy "^0.1.0" - -"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= - -stealthy-require@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" - integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= - -stream-browserify@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" - integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== - dependencies: - inherits "~2.0.1" - readable-stream "^2.0.2" - -stream-each@^1.1.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" - integrity sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw== - dependencies: - end-of-stream "^1.1.0" - stream-shift "^1.0.0" - -stream-http@^2.7.2: - version "2.8.3" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" - integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== - dependencies: - builtin-status-codes "^3.0.0" - inherits "^2.0.1" - readable-stream "^2.3.6" - to-arraybuffer "^1.0.0" - xtend "^4.0.0" - -stream-shift@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" - integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== - -strict-uri-encode@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" - integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= - -string-length@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" - integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== - dependencies: - char-regex "^1.0.2" - strip-ansi "^6.0.0" - -string-natural-compare@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" - integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== - -string-width@^3.0.0, string-width@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - -string-width@^4.1.0, string-width@^4.2.0: - version "4.2.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" - integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.0" - -string.prototype.matchall@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.4.tgz#608f255e93e072107f5de066f81a2dfb78cf6b29" - integrity sha512-pknFIWVachNcyqRfaQSeu/FUfpvJTe4uskUSZ9Wc1RijsPuzbZ8TyYT8WCNnntCjUEqQ3vUHMAfVj2+wLAisPQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.18.0-next.2" - has-symbols "^1.0.1" - internal-slot "^1.0.3" - regexp.prototype.flags "^1.3.1" - side-channel "^1.0.4" - -string.prototype.trimend@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" - integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -string.prototype.trimstart@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" - integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -string_decoder@^1.0.0, string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -stringify-object@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" - integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw== - dependencies: - get-own-enumerable-property-symbols "^3.0.0" - is-obj "^1.0.1" - is-regexp "^1.0.0" - -strip-ansi@6.0.0, strip-ansi@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" - integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== - dependencies: - ansi-regex "^5.0.0" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= - -strip-bom@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" - integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== - -strip-comments@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/strip-comments/-/strip-comments-1.0.2.tgz#82b9c45e7f05873bee53f37168af930aa368679d" - integrity sha512-kL97alc47hoyIQSV165tTt9rG5dn4w1dNnBhOQ3bOU1Nc1hel09jnXANaHJ7vzHLd4Ju8kseDGzlev96pghLFw== - dependencies: - babel-extract-comments "^1.0.0" - babel-plugin-transform-object-rest-spread "^6.26.0" - -strip-eof@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= - -strip-final-newline@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" - integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== - -strip-indent@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" - integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== - dependencies: - min-indent "^1.0.0" - -strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -style-loader@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.3.0.tgz#828b4a3b3b7e7aa5847ce7bae9e874512114249e" - integrity sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q== - dependencies: - loader-utils "^2.0.0" - schema-utils "^2.7.0" - -stylehacks@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5" - integrity sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g== - dependencies: - browserslist "^4.0.0" - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" - integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.0.0, supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-hyperlinks@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz#4f77b42488765891774b70c79babd87f9bd594bb" - integrity sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ== - dependencies: - has-flag "^4.0.0" - supports-color "^7.0.0" - -svg-parser@^2.0.2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5" - integrity sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ== - -svgo@^1.0.0, svgo@^1.2.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" - integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw== - dependencies: - chalk "^2.4.1" - coa "^2.0.2" - css-select "^2.0.0" - css-select-base-adapter "^0.1.1" - css-tree "1.0.0-alpha.37" - csso "^4.0.2" - js-yaml "^3.13.1" - mkdirp "~0.5.1" - object.values "^1.1.0" - sax "~1.2.4" - stable "^0.1.8" - unquote "~1.1.1" - util.promisify "~1.0.0" - -symbol-tree@^3.2.4: - version "3.2.4" - resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" - integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== - -table@^6.0.9: - version "6.7.1" - resolved "https://registry.yarnpkg.com/table/-/table-6.7.1.tgz#ee05592b7143831a8c94f3cee6aae4c1ccef33e2" - integrity sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg== - dependencies: - ajv "^8.0.1" - lodash.clonedeep "^4.5.0" - lodash.truncate "^4.4.2" - slice-ansi "^4.0.0" - string-width "^4.2.0" - strip-ansi "^6.0.0" - -tapable@^1.0.0, tapable@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" - integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== - -tar@^6.0.2: - version "6.1.0" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.0.tgz#d1724e9bcc04b977b18d5c573b333a2207229a83" - integrity sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA== - dependencies: - chownr "^2.0.0" - fs-minipass "^2.0.0" - minipass "^3.0.0" - minizlib "^2.1.1" - mkdirp "^1.0.3" - yallist "^4.0.0" - -temp-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" - integrity sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0= - -tempy@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/tempy/-/tempy-0.3.0.tgz#6f6c5b295695a16130996ad5ab01a8bd726e8bf8" - integrity sha512-WrH/pui8YCwmeiAoxV+lpRH9HpRtgBhSR2ViBPgpGb/wnYDzp21R4MN45fsCGvLROvY67o3byhJRYRONJyImVQ== - dependencies: - temp-dir "^1.0.0" - type-fest "^0.3.1" - unique-string "^1.0.0" - -terminal-link@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" - integrity sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ== - dependencies: - ansi-escapes "^4.2.1" - supports-hyperlinks "^2.0.0" - -terser-webpack-plugin@4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-4.2.3.tgz#28daef4a83bd17c1db0297070adc07fc8cfc6a9a" - integrity sha512-jTgXh40RnvOrLQNgIkwEKnQ8rmHjHK4u+6UBEi+W+FPmvb+uo+chJXntKe7/3lW5mNysgSWD60KyesnhW8D6MQ== - dependencies: - cacache "^15.0.5" - find-cache-dir "^3.3.1" - jest-worker "^26.5.0" - p-limit "^3.0.2" - schema-utils "^3.0.0" - serialize-javascript "^5.0.1" - source-map "^0.6.1" - terser "^5.3.4" - webpack-sources "^1.4.3" - -terser-webpack-plugin@^1.4.3: - version "1.4.5" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz#a217aefaea330e734ffacb6120ec1fa312d6040b" - integrity sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw== - dependencies: - cacache "^12.0.2" - find-cache-dir "^2.1.0" - is-wsl "^1.1.0" - schema-utils "^1.0.0" - serialize-javascript "^4.0.0" - source-map "^0.6.1" - terser "^4.1.2" - webpack-sources "^1.4.0" - worker-farm "^1.7.0" - -terser@^4.1.2, terser@^4.6.2, terser@^4.6.3: - version "4.8.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17" - integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw== - dependencies: - commander "^2.20.0" - source-map "~0.6.1" - source-map-support "~0.5.12" - -terser@^5.3.4: - version "5.7.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.7.0.tgz#a761eeec206bc87b605ab13029876ead938ae693" - integrity sha512-HP5/9hp2UaZt5fYkuhNBR8YyRcT8juw8+uFbAme53iN9hblvKnLUTKkmwJG6ocWpIKf8UK4DoeWG4ty0J6S6/g== - dependencies: - commander "^2.20.0" - source-map "~0.7.2" - source-map-support "~0.5.19" - -test-exclude@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" - integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== - dependencies: - "@istanbuljs/schema" "^0.1.2" - glob "^7.1.4" - minimatch "^3.0.4" - -text-table@0.2.0, text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= - -throat@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" - integrity sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA== - -through2@^2.0.0: - version "2.0.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" - integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== - dependencies: - readable-stream "~2.3.6" - xtend "~4.0.1" - -thunky@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" - integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== - -timers-browserify@^2.0.4: - version "2.0.12" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" - integrity sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ== - dependencies: - setimmediate "^1.0.4" - -timsort@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" - integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= - -tiny-invariant@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.1.0.tgz#634c5f8efdc27714b7f386c35e6760991d230875" - integrity sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw== - -tiny-warning@^1.0.0, tiny-warning@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" - integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== - -tmpl@1.0.x: - version "1.0.4" - resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" - integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE= - -to-arraybuffer@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" - integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= - -to-object-path@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= - dependencies: - kind-of "^3.0.2" - -to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -to-regex@^3.0.1, to-regex@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== - dependencies: - define-property "^2.0.2" - extend-shallow "^3.0.2" - regex-not "^1.0.2" - safe-regex "^1.1.0" - -toidentifier@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" - integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== - -tough-cookie@^2.3.3, tough-cookie@~2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" - integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== - dependencies: - psl "^1.1.28" - punycode "^2.1.1" - -tough-cookie@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4" - integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg== - dependencies: - psl "^1.1.33" - punycode "^2.1.1" - universalify "^0.1.2" - -tr46@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.0.2.tgz#03273586def1595ae08fedb38d7733cee91d2479" - integrity sha512-3n1qG+/5kg+jrbTzwAykB5yRYtQCTqOGKq5U5PE3b0a1/mzo6snDhjGS0zJVJunO0NrT3Dg1MLy5TjWP/UJppg== - dependencies: - punycode "^2.1.1" - -tryer@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" - integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA== - -ts-pnp@1.2.0, ts-pnp@^1.1.6: - version "1.2.0" - resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" - integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw== - -tsconfig-paths@^3.9.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b" - integrity sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw== - dependencies: - "@types/json5" "^0.0.29" - json5 "^1.0.1" - minimist "^1.2.0" - strip-bom "^3.0.0" - -tslib@^1.8.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - -tslib@^2.0.3: - version "2.2.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.2.0.tgz#fb2c475977e35e241311ede2693cee1ec6698f5c" - integrity sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w== - -tsutils@^3.17.1: - version "3.21.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" - integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== - dependencies: - tslib "^1.8.1" - -tty-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" - integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= - dependencies: - safe-buffer "^5.0.1" - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= - -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= - dependencies: - prelude-ls "~1.1.2" - -type-detect@4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== - -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - -type-fest@^0.21.3: - version "0.21.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" - integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== - -type-fest@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" - integrity sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ== - -type-fest@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" - integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== - -type-fest@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" - integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== - -type-is@~1.6.17, type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - -type@^1.0.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" - integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== - -type@^2.0.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/type/-/type-2.5.0.tgz#0a2e78c2e77907b252abe5f298c1b01c63f0db3d" - integrity sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw== - -typedarray-to-buffer@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== - dependencies: - is-typedarray "^1.0.0" - -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= - -typescript@^4.2.4: - version "4.2.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.4.tgz#8610b59747de028fda898a8aef0e103f156d0961" - integrity sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg== - -unbox-primitive@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" - integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== - dependencies: - function-bind "^1.1.1" - has-bigints "^1.0.1" - has-symbols "^1.0.2" - which-boxed-primitive "^1.0.2" - -uncontrollable@^7.2.1: - version "7.2.1" - resolved "https://registry.yarnpkg.com/uncontrollable/-/uncontrollable-7.2.1.tgz#1fa70ba0c57a14d5f78905d533cf63916dc75738" - integrity sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ== - dependencies: - "@babel/runtime" "^7.6.3" - "@types/react" ">=16.9.11" - invariant "^2.2.4" - react-lifecycles-compat "^3.0.4" - -unicode-canonical-property-names-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" - integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== - -unicode-match-property-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" - integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== - dependencies: - unicode-canonical-property-names-ecmascript "^1.0.4" - unicode-property-aliases-ecmascript "^1.0.4" - -unicode-match-property-value-ecmascript@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz#0d91f600eeeb3096aa962b1d6fc88876e64ea531" - integrity sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ== - -unicode-property-aliases-ecmascript@^1.0.4: - version "1.1.0" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz#dd57a99f6207bedff4628abefb94c50db941c8f4" - integrity sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg== - -union-value@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" - integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== - dependencies: - arr-union "^3.1.0" - get-value "^2.0.6" - is-extendable "^0.1.1" - set-value "^2.0.1" - -uniq@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" - integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= - -uniqs@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" - integrity sha1-/+3ks2slKQaW5uFl1KWe25mOawI= - -unique-filename@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" - integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== - dependencies: - unique-slug "^2.0.0" - -unique-slug@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" - integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== - dependencies: - imurmurhash "^0.1.4" - -unique-string@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" - integrity sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo= - dependencies: - crypto-random-string "^1.0.0" - -universalify@^0.1.0, universalify@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== - -universalify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" - integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== - -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= - -unquote@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" - integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= - -unset-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= - dependencies: - has-value "^0.3.1" - isobject "^3.0.0" - -upath@^1.1.1, upath@^1.1.2, upath@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" - integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -urix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= - -url-loader@4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-4.1.1.tgz#28505e905cae158cf07c92ca622d7f237e70a4e2" - integrity sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA== - dependencies: - loader-utils "^2.0.0" - mime-types "^2.1.27" - schema-utils "^3.0.0" - -url-parse@^1.4.3, url-parse@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.1.tgz#d5fa9890af8a5e1f274a2c98376510f6425f6e3b" - integrity sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q== - dependencies: - querystringify "^2.1.1" - requires-port "^1.0.0" - -url@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= - dependencies: - punycode "1.3.2" - querystring "0.2.0" - -use@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== - -util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -util.promisify@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" - integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA== - dependencies: - define-properties "^1.1.2" - object.getownpropertydescriptors "^2.0.3" - -util.promisify@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee" - integrity sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.2" - has-symbols "^1.0.1" - object.getownpropertydescriptors "^2.1.0" - -util@0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= - dependencies: - inherits "2.0.1" - -util@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" - integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== - dependencies: - inherits "2.0.3" - -utila@~0.4: - version "0.4.0" - resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" - integrity sha1-ihagXURWV6Oupe7MWxKk+lN5dyw= - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= - -uuid@^3.3.2, uuid@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" - integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== - -uuid@^8.3.0: - version "8.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" - integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== - -v8-compile-cache@^2.0.3: - version "2.3.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" - integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== - -v8-to-istanbul@^7.0.0: - version "7.1.2" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-7.1.2.tgz#30898d1a7fa0c84d225a2c1434fb958f290883c1" - integrity sha512-TxNb7YEUwkLXCQYeudi6lgQ/SZrzNO4kMdlqVxaZPUIUjCv6iSSypUQX70kNBSERpQ8fk48+d61FXk+tgqcWow== - dependencies: - "@types/istanbul-lib-coverage" "^2.0.1" - convert-source-map "^1.6.0" - source-map "^0.7.3" - -validate-npm-package-license@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - -value-equal@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c" - integrity sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw== - -vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= - -vendors@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e" - integrity sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w== - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - -vm-browserify@^1.0.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" - integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== - -w3c-hr-time@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" - integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ== - dependencies: - browser-process-hrtime "^1.0.0" - -w3c-xmlserializer@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" - integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA== - dependencies: - xml-name-validator "^3.0.0" - -walker@^1.0.7, walker@~1.0.5: - version "1.0.7" - resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" - integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs= - dependencies: - makeerror "1.0.x" - -warning@^4.0.0, warning@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" - integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w== - dependencies: - loose-envify "^1.0.0" - -watchpack-chokidar2@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz#38500072ee6ece66f3769936950ea1771be1c957" - integrity sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww== - dependencies: - chokidar "^2.1.8" - -watchpack@^1.7.4: - version "1.7.5" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.5.tgz#1267e6c55e0b9b5be44c2023aed5437a2c26c453" - integrity sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ== - dependencies: - graceful-fs "^4.1.2" - neo-async "^2.5.0" - optionalDependencies: - chokidar "^3.4.1" - watchpack-chokidar2 "^2.0.1" - -wbuf@^1.1.0, wbuf@^1.7.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" - integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== - dependencies: - minimalistic-assert "^1.0.0" - -web-vitals@^1.0.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-1.1.2.tgz#06535308168986096239aa84716e68b4c6ae6d1c" - integrity sha512-PFMKIY+bRSXlMxVAQ+m2aw9c/ioUYfDgrYot0YUa+/xa0sakubWhSDyxAKwzymvXVdF4CZI71g06W+mqhzu6ig== - -webidl-conversions@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" - integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== - -webidl-conversions@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" - integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== - -webpack-dev-middleware@^3.7.2: - version "3.7.3" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz#0639372b143262e2b84ab95d3b91a7597061c2c5" - integrity sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ== - dependencies: - memory-fs "^0.4.1" - mime "^2.4.4" - mkdirp "^0.5.1" - range-parser "^1.2.1" - webpack-log "^2.0.0" - -webpack-dev-server@3.11.1: - version "3.11.1" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.1.tgz#c74028bf5ba8885aaf230e48a20e8936ab8511f0" - integrity sha512-u4R3mRzZkbxQVa+MBWi2uVpB5W59H3ekZAJsQlKUTdl7Elcah2EhygTPLmeFXybQkf9i2+L0kn7ik9SnXa6ihQ== - dependencies: - ansi-html "0.0.7" - bonjour "^3.5.0" - chokidar "^2.1.8" - compression "^1.7.4" - connect-history-api-fallback "^1.6.0" - debug "^4.1.1" - del "^4.1.1" - express "^4.17.1" - html-entities "^1.3.1" - http-proxy-middleware "0.19.1" - import-local "^2.0.0" - internal-ip "^4.3.0" - ip "^1.1.5" - is-absolute-url "^3.0.3" - killable "^1.0.1" - loglevel "^1.6.8" - opn "^5.5.0" - p-retry "^3.0.1" - portfinder "^1.0.26" - schema-utils "^1.0.0" - selfsigned "^1.10.8" - semver "^6.3.0" - serve-index "^1.9.1" - sockjs "^0.3.21" - sockjs-client "^1.5.0" - spdy "^4.0.2" - strip-ansi "^3.0.1" - supports-color "^6.1.0" - url "^0.11.0" - webpack-dev-middleware "^3.7.2" - webpack-log "^2.0.0" - ws "^6.2.1" - yargs "^13.3.2" - -webpack-log@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f" - integrity sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg== - dependencies: - ansi-colors "^3.0.0" - uuid "^3.3.2" - -webpack-manifest-plugin@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/webpack-manifest-plugin/-/webpack-manifest-plugin-2.2.0.tgz#19ca69b435b0baec7e29fbe90fb4015de2de4f16" - integrity sha512-9S6YyKKKh/Oz/eryM1RyLVDVmy3NSPV0JXMRhZ18fJsq+AwGxUY34X54VNwkzYcEmEkDwNxuEOboCZEebJXBAQ== - dependencies: - fs-extra "^7.0.0" - lodash ">=3.5 <5" - object.entries "^1.1.0" - tapable "^1.0.0" - -webpack-sources@^1.1.0, webpack-sources@^1.3.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" - integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== - dependencies: - source-list-map "^2.0.0" - source-map "~0.6.1" - -webpack@4.44.2: - version "4.44.2" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.44.2.tgz#6bfe2b0af055c8b2d1e90ed2cd9363f841266b72" - integrity sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-module-context" "1.9.0" - "@webassemblyjs/wasm-edit" "1.9.0" - "@webassemblyjs/wasm-parser" "1.9.0" - acorn "^6.4.1" - ajv "^6.10.2" - ajv-keywords "^3.4.1" - chrome-trace-event "^1.0.2" - enhanced-resolve "^4.3.0" - eslint-scope "^4.0.3" - json-parse-better-errors "^1.0.2" - loader-runner "^2.4.0" - loader-utils "^1.2.3" - memory-fs "^0.4.1" - micromatch "^3.1.10" - mkdirp "^0.5.3" - neo-async "^2.6.1" - node-libs-browser "^2.2.1" - schema-utils "^1.0.0" - tapable "^1.1.3" - terser-webpack-plugin "^1.4.3" - watchpack "^1.7.4" - webpack-sources "^1.4.1" - -websocket-driver@>=0.5.1, websocket-driver@^0.7.4: - version "0.7.4" - resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" - integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== - dependencies: - http-parser-js ">=0.5.1" - safe-buffer ">=5.1.0" - websocket-extensions ">=0.1.1" - -websocket-extensions@>=0.1.1: - version "0.1.4" - resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" - integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== - -whatwg-encoding@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" - integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== - dependencies: - iconv-lite "0.4.24" - -whatwg-fetch@^3.4.1: - version "3.6.2" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" - integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA== - -whatwg-mimetype@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" - integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== - -whatwg-url@^8.0.0, whatwg-url@^8.5.0: - version "8.5.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.5.0.tgz#7752b8464fc0903fec89aa9846fc9efe07351fd3" - integrity sha512-fy+R77xWv0AiqfLl4nuGUlQ3/6b5uNfQ4WAbGQVMYshCTCCPK9psC1nWh3XHuxGVCtlcDDQPQW1csmmIQo+fwg== - dependencies: - lodash "^4.7.0" - tr46 "^2.0.2" - webidl-conversions "^6.1.0" - -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== - dependencies: - is-bigint "^1.0.1" - is-boolean-object "^1.1.0" - is-number-object "^1.0.4" - is-string "^1.0.5" - is-symbol "^1.0.3" - -which-module@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= - -which@^1.2.9, which@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -which@^2.0.1, which@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -word-wrap@^1.2.3, word-wrap@~1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== - -workbox-background-sync@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/workbox-background-sync/-/workbox-background-sync-5.1.4.tgz#5ae0bbd455f4e9c319e8d827c055bb86c894fd12" - integrity sha512-AH6x5pYq4vwQvfRDWH+vfOePfPIYQ00nCEB7dJRU1e0n9+9HMRyvI63FlDvtFT2AvXVRsXvUt7DNMEToyJLpSA== - dependencies: - workbox-core "^5.1.4" - -workbox-broadcast-update@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/workbox-broadcast-update/-/workbox-broadcast-update-5.1.4.tgz#0eeb89170ddca7f6914fa3523fb14462891f2cfc" - integrity sha512-HTyTWkqXvHRuqY73XrwvXPud/FN6x3ROzkfFPsRjtw/kGZuZkPzfeH531qdUGfhtwjmtO/ZzXcWErqVzJNdXaA== - dependencies: - workbox-core "^5.1.4" - -workbox-build@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/workbox-build/-/workbox-build-5.1.4.tgz#23d17ed5c32060c363030c8823b39d0eabf4c8c7" - integrity sha512-xUcZn6SYU8usjOlfLb9Y2/f86Gdo+fy1fXgH8tJHjxgpo53VVsqRX0lUDw8/JuyzNmXuo8vXX14pXX2oIm9Bow== - dependencies: - "@babel/core" "^7.8.4" - "@babel/preset-env" "^7.8.4" - "@babel/runtime" "^7.8.4" - "@hapi/joi" "^15.1.0" - "@rollup/plugin-node-resolve" "^7.1.1" - "@rollup/plugin-replace" "^2.3.1" - "@surma/rollup-plugin-off-main-thread" "^1.1.1" - common-tags "^1.8.0" - fast-json-stable-stringify "^2.1.0" - fs-extra "^8.1.0" - glob "^7.1.6" - lodash.template "^4.5.0" - pretty-bytes "^5.3.0" - rollup "^1.31.1" - rollup-plugin-babel "^4.3.3" - rollup-plugin-terser "^5.3.1" - source-map "^0.7.3" - source-map-url "^0.4.0" - stringify-object "^3.3.0" - strip-comments "^1.0.2" - tempy "^0.3.0" - upath "^1.2.0" - workbox-background-sync "^5.1.4" - workbox-broadcast-update "^5.1.4" - workbox-cacheable-response "^5.1.4" - workbox-core "^5.1.4" - workbox-expiration "^5.1.4" - workbox-google-analytics "^5.1.4" - workbox-navigation-preload "^5.1.4" - workbox-precaching "^5.1.4" - workbox-range-requests "^5.1.4" - workbox-routing "^5.1.4" - workbox-strategies "^5.1.4" - workbox-streams "^5.1.4" - workbox-sw "^5.1.4" - workbox-window "^5.1.4" - -workbox-cacheable-response@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/workbox-cacheable-response/-/workbox-cacheable-response-5.1.4.tgz#9ff26e1366214bdd05cf5a43da9305b274078a54" - integrity sha512-0bfvMZs0Of1S5cdswfQK0BXt6ulU5kVD4lwer2CeI+03czHprXR3V4Y8lPTooamn7eHP8Iywi5QjyAMjw0qauA== - dependencies: - workbox-core "^5.1.4" - -workbox-core@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/workbox-core/-/workbox-core-5.1.4.tgz#8bbfb2362ecdff30e25d123c82c79ac65d9264f4" - integrity sha512-+4iRQan/1D8I81nR2L5vcbaaFskZC2CL17TLbvWVzQ4qiF/ytOGF6XeV54pVxAvKUtkLANhk8TyIUMtiMw2oDg== - -workbox-expiration@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/workbox-expiration/-/workbox-expiration-5.1.4.tgz#92b5df461e8126114943a3b15c55e4ecb920b163" - integrity sha512-oDO/5iC65h2Eq7jctAv858W2+CeRW5e0jZBMNRXpzp0ZPvuT6GblUiHnAsC5W5lANs1QS9atVOm4ifrBiYY7AQ== - dependencies: - workbox-core "^5.1.4" - -workbox-google-analytics@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/workbox-google-analytics/-/workbox-google-analytics-5.1.4.tgz#b3376806b1ac7d7df8418304d379707195fa8517" - integrity sha512-0IFhKoEVrreHpKgcOoddV+oIaVXBFKXUzJVBI+nb0bxmcwYuZMdteBTp8AEDJacENtc9xbR0wa9RDCnYsCDLjA== - dependencies: - workbox-background-sync "^5.1.4" - workbox-core "^5.1.4" - workbox-routing "^5.1.4" - workbox-strategies "^5.1.4" - -workbox-navigation-preload@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/workbox-navigation-preload/-/workbox-navigation-preload-5.1.4.tgz#30d1b720d26a05efc5fa11503e5cc1ed5a78902a" - integrity sha512-Wf03osvK0wTflAfKXba//QmWC5BIaIZARU03JIhAEO2wSB2BDROWI8Q/zmianf54kdV7e1eLaIEZhth4K4MyfQ== - dependencies: - workbox-core "^5.1.4" - -workbox-precaching@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/workbox-precaching/-/workbox-precaching-5.1.4.tgz#874f7ebdd750dd3e04249efae9a1b3f48285fe6b" - integrity sha512-gCIFrBXmVQLFwvAzuGLCmkUYGVhBb7D1k/IL7pUJUO5xacjLcFUaLnnsoVepBGAiKw34HU1y/YuqvTKim9qAZA== - dependencies: - workbox-core "^5.1.4" - -workbox-range-requests@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/workbox-range-requests/-/workbox-range-requests-5.1.4.tgz#7066a12c121df65bf76fdf2b0868016aa2bab859" - integrity sha512-1HSujLjgTeoxHrMR2muDW2dKdxqCGMc1KbeyGcmjZZAizJTFwu7CWLDmLv6O1ceWYrhfuLFJO+umYMddk2XMhw== - dependencies: - workbox-core "^5.1.4" - -workbox-routing@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/workbox-routing/-/workbox-routing-5.1.4.tgz#3e8cd86bd3b6573488d1a2ce7385e547b547e970" - integrity sha512-8ljknRfqE1vEQtnMtzfksL+UXO822jJlHTIR7+BtJuxQ17+WPZfsHqvk1ynR/v0EHik4x2+826Hkwpgh4GKDCw== - dependencies: - workbox-core "^5.1.4" - -workbox-strategies@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/workbox-strategies/-/workbox-strategies-5.1.4.tgz#96b1418ccdfde5354612914964074d466c52d08c" - integrity sha512-VVS57LpaJTdjW3RgZvPwX0NlhNmscR7OQ9bP+N/34cYMDzXLyA6kqWffP6QKXSkca1OFo/v6v7hW7zrrguo6EA== - dependencies: - workbox-core "^5.1.4" - workbox-routing "^5.1.4" - -workbox-streams@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/workbox-streams/-/workbox-streams-5.1.4.tgz#05754e5e3667bdc078df2c9315b3f41210d8cac0" - integrity sha512-xU8yuF1hI/XcVhJUAfbQLa1guQUhdLMPQJkdT0kn6HP5CwiPOGiXnSFq80rAG4b1kJUChQQIGPrq439FQUNVrw== - dependencies: - workbox-core "^5.1.4" - workbox-routing "^5.1.4" - -workbox-sw@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/workbox-sw/-/workbox-sw-5.1.4.tgz#2bb34c9f7381f90d84cef644816d45150011d3db" - integrity sha512-9xKnKw95aXwSNc8kk8gki4HU0g0W6KXu+xks7wFuC7h0sembFnTrKtckqZxbSod41TDaGh+gWUA5IRXrL0ECRA== - -workbox-webpack-plugin@5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/workbox-webpack-plugin/-/workbox-webpack-plugin-5.1.4.tgz#7bfe8c16e40fe9ed8937080ac7ae9c8bde01e79c" - integrity sha512-PZafF4HpugZndqISi3rZ4ZK4A4DxO8rAqt2FwRptgsDx7NF8TVKP86/huHquUsRjMGQllsNdn4FNl8CD/UvKmQ== - dependencies: - "@babel/runtime" "^7.5.5" - fast-json-stable-stringify "^2.0.0" - source-map-url "^0.4.0" - upath "^1.1.2" - webpack-sources "^1.3.0" - workbox-build "^5.1.4" - -workbox-window@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/workbox-window/-/workbox-window-5.1.4.tgz#2740f7dea7f93b99326179a62f1cc0ca2c93c863" - integrity sha512-vXQtgTeMCUq/4pBWMfQX8Ee7N2wVC4Q7XYFqLnfbXJ2hqew/cU1uMTD2KqGEgEpE4/30luxIxgE+LkIa8glBYw== - dependencies: - workbox-core "^5.1.4" - -worker-farm@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8" - integrity sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw== - dependencies: - errno "~0.1.7" - -worker-rpc@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/worker-rpc/-/worker-rpc-0.1.1.tgz#cb565bd6d7071a8f16660686051e969ad32f54d5" - integrity sha512-P1WjMrUB3qgJNI9jfmpZ/htmBEjFh//6l/5y8SD9hg1Ef5zTTVVoRjTrTEzPrNBQvmhMxkoTsjOXN10GWU7aCg== - dependencies: - microevent.ts "~0.1.1" - -wrap-ansi@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" - integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== - dependencies: - ansi-styles "^3.2.0" - string-width "^3.0.0" - strip-ansi "^5.0.0" - -wrap-ansi@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" - integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -write-file-atomic@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" - integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== - dependencies: - imurmurhash "^0.1.4" - is-typedarray "^1.0.0" - signal-exit "^3.0.2" - typedarray-to-buffer "^3.1.5" - -ws@^6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" - integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== - dependencies: - async-limiter "~1.0.0" - -ws@^7.4.4: - version "7.4.5" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.5.tgz#a484dd851e9beb6fdb420027e3885e8ce48986c1" - integrity sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g== - -xml-name-validator@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" - integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== - -xmlchars@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" - integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== - -xtend@^4.0.0, xtend@~4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -y18n@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" - integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== - -yallist@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yaml@^1.10.0, yaml@^1.7.2: - version "1.10.2" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" - integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== - -yargs-parser@^13.1.2: - version "13.1.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" - integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yargs-parser@^18.1.2: - version "18.1.3" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" - integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yargs@^13.3.2: - version "13.3.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" - integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== - dependencies: - cliui "^5.0.0" - find-up "^3.0.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^3.0.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^13.1.2" - -yargs@^15.4.1: - version "15.4.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" - integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== - dependencies: - cliui "^6.0.0" - decamelize "^1.2.0" - find-up "^4.1.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^4.2.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^18.1.2" - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== From 1fd4105bda3f43c68109ffcb507a794c13122a8a Mon Sep 17 00:00:00 2001 From: Aditya Agarwal <132701661+adi790uu@users.noreply.github.com> Date: Sun, 10 Dec 2023 22:18:32 +0530 Subject: [PATCH 09/34] [#1123] Changes position and text of "All Organizations" button (#1124) * Changes position and text of all organization button * Made changes to the routesReducer.test file * Made changes in IconComponent.test file * Fetched changes from main repo * Fixed unnecessary changes --------- Co-authored-by: Aditya Agarwal --- src/GraphQl/Queries/Queries.ts | 2 +- src/components/IconComponent/IconComponent.test.tsx | 8 ++++---- src/components/IconComponent/IconComponent.tsx | 2 +- src/state/reducers/routesReducer.test.ts | 12 ++++++------ src/state/reducers/routesReducer.ts | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/GraphQl/Queries/Queries.ts b/src/GraphQl/Queries/Queries.ts index 7bf99d48ee..0e3f20918e 100644 --- a/src/GraphQl/Queries/Queries.ts +++ b/src/GraphQl/Queries/Queries.ts @@ -1,6 +1,6 @@ import gql from 'graphql-tag'; -//Query List +// Query List // Check Auth diff --git a/src/components/IconComponent/IconComponent.test.tsx b/src/components/IconComponent/IconComponent.test.tsx index ff83ebe57c..dbcd477b5d 100644 --- a/src/components/IconComponent/IconComponent.test.tsx +++ b/src/components/IconComponent/IconComponent.test.tsx @@ -3,6 +3,10 @@ import { render, screen } from '@testing-library/react'; import IconComponent from './IconComponent'; const screenTestIdMap: Record> = { + AllOrganizations: { + name: 'My Organizations', + testId: 'Icon-Component-AllOrganizationsIcon', + }, Dashboard: { name: 'Dashboard', testId: 'Icon-Component-DashboardIcon', @@ -31,10 +35,6 @@ const screenTestIdMap: Record> = { name: 'Settings', testId: 'Icon-Component-SettingsIcon', }, - AllOrganizations: { - name: 'All Organizations', - testId: 'Icon-Component-AllOrganizationsIcon', - }, EventProject: { name: 'Add Event Project', testId: 'Icon-Component-Add-Event-Project', diff --git a/src/components/IconComponent/IconComponent.tsx b/src/components/IconComponent/IconComponent.tsx index 4c490c9c94..90a60244b5 100644 --- a/src/components/IconComponent/IconComponent.tsx +++ b/src/components/IconComponent/IconComponent.tsx @@ -53,7 +53,7 @@ const iconComponent = (props: InterfaceIconComponent): JSX.Element => { data-testid="Icon-Component-SettingsIcon" /> ); - case 'All Organizations': + case 'My Organizations': return ( { }) ).toEqual({ targets: [ + { name: 'My Organizations', url: '/orglist/id=undefined' }, { name: 'Dashboard', url: '/orgdash/id=undefined' }, { name: 'People', url: '/orgpeople/id=undefined' }, { name: 'Events', url: '/orgevents/id=undefined' }, @@ -30,10 +31,10 @@ describe('Testing Routes reducer', () => { ], }, { name: 'Settings', url: '/orgsetting/id=undefined' }, - { name: 'All Organizations', url: '/orglist/id=undefined' }, ], configUrl: 'undefined', components: [ + { name: 'My Organizations', comp_id: 'orglist', component: 'OrgList' }, { name: 'Dashboard', comp_id: 'orgdash', @@ -70,7 +71,6 @@ describe('Testing Routes reducer', () => { ], }, { name: 'Settings', comp_id: 'orgsetting', component: 'OrgSettings' }, - { name: 'All Organizations', comp_id: 'orglist', component: 'OrgList' }, { name: '', comp_id: 'member', component: 'MemberDetail' }, ], }); @@ -84,6 +84,7 @@ describe('Testing Routes reducer', () => { }) ).toEqual({ targets: [ + { name: 'My Organizations', url: '/orglist/id=undefined' }, { name: 'Dashboard', url: '/orgdash/id=undefined' }, { name: 'People', url: '/orgpeople/id=undefined' }, { name: 'Events', url: '/orgevents/id=undefined' }, @@ -101,11 +102,11 @@ describe('Testing Routes reducer', () => { ], }, { name: 'Settings', url: '/orgsetting/id=undefined' }, - { name: 'All Organizations', url: '/orglist/id=undefined' }, { test: 'testupdate' }, ], configUrl: 'undefined', components: [ + { name: 'My Organizations', comp_id: 'orglist', component: 'OrgList' }, { name: 'Dashboard', comp_id: 'orgdash', @@ -142,7 +143,6 @@ describe('Testing Routes reducer', () => { ], }, { name: 'Settings', comp_id: 'orgsetting', component: 'OrgSettings' }, - { name: 'All Organizations', comp_id: 'orglist', component: 'OrgList' }, { name: '', comp_id: 'member', component: 'MemberDetail' }, ], }); @@ -156,6 +156,7 @@ describe('Testing Routes reducer', () => { }) ).toEqual({ targets: [ + { name: 'My Organizations', url: '/orglist/id=undefined' }, { name: 'Dashboard', url: '/orgdash/id=undefined' }, { name: 'People', url: '/orgpeople/id=undefined' }, { name: 'Events', url: '/orgevents/id=undefined' }, @@ -166,7 +167,6 @@ describe('Testing Routes reducer', () => { }, { name: 'Advertisement', url: '/orgads/id=undefined' }, { name: 'Settings', url: '/orgsetting/id=undefined' }, - { name: 'All Organizations', url: '/orglist/id=undefined' }, { comp_id: null, component: null, @@ -183,6 +183,7 @@ describe('Testing Routes reducer', () => { ], configUrl: 'undefined', components: [ + { name: 'My Organizations', comp_id: 'orglist', component: 'OrgList' }, { name: 'Dashboard', comp_id: 'orgdash', @@ -220,7 +221,6 @@ describe('Testing Routes reducer', () => { ], }, { name: 'Settings', comp_id: 'orgsetting', component: 'OrgSettings' }, - { name: 'All Organizations', comp_id: 'orglist', component: 'OrgList' }, { name: '', comp_id: 'member', component: 'MemberDetail' }, ], }); diff --git a/src/state/reducers/routesReducer.ts b/src/state/reducers/routesReducer.ts index 4fafbd1ebb..7157feb23f 100644 --- a/src/state/reducers/routesReducer.ts +++ b/src/state/reducers/routesReducer.ts @@ -63,6 +63,7 @@ export type TargetsType = { // Note: Routes with names appear on NavBar const components: ComponentType[] = [ + { name: 'My Organizations', comp_id: 'orglist', component: 'OrgList' }, { name: 'Dashboard', comp_id: 'orgdash', component: 'OrganizationDashboard' }, { name: 'People', comp_id: 'orgpeople', component: 'OrganizationPeople' }, { name: 'Events', comp_id: 'orgevents', component: 'OrganizationEvents' }, @@ -84,7 +85,6 @@ const components: ComponentType[] = [ }, { name: 'Settings', comp_id: 'orgsetting', component: 'OrgSettings' }, - { name: 'All Organizations', comp_id: 'orglist', component: 'OrgList' }, { name: '', comp_id: 'member', component: 'MemberDetail' }, ]; From 9ff2924381159729ae0f44aac939b73b03c82051 Mon Sep 17 00:00:00 2001 From: Md Noman Khan <54404474+noman2002@users.noreply.github.com> Date: Tue, 12 Dec 2023 18:21:50 +0530 Subject: [PATCH 10/34] Revert "[#1123] Changes position and text of "All Organizations" button (#1124)" (#1183) This reverts commit 1fd4105bda3f43c68109ffcb507a794c13122a8a. --- src/GraphQl/Queries/Queries.ts | 2 +- src/components/IconComponent/IconComponent.test.tsx | 8 ++++---- src/components/IconComponent/IconComponent.tsx | 2 +- src/state/reducers/routesReducer.test.ts | 12 ++++++------ src/state/reducers/routesReducer.ts | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/GraphQl/Queries/Queries.ts b/src/GraphQl/Queries/Queries.ts index 0e3f20918e..7bf99d48ee 100644 --- a/src/GraphQl/Queries/Queries.ts +++ b/src/GraphQl/Queries/Queries.ts @@ -1,6 +1,6 @@ import gql from 'graphql-tag'; -// Query List +//Query List // Check Auth diff --git a/src/components/IconComponent/IconComponent.test.tsx b/src/components/IconComponent/IconComponent.test.tsx index dbcd477b5d..ff83ebe57c 100644 --- a/src/components/IconComponent/IconComponent.test.tsx +++ b/src/components/IconComponent/IconComponent.test.tsx @@ -3,10 +3,6 @@ import { render, screen } from '@testing-library/react'; import IconComponent from './IconComponent'; const screenTestIdMap: Record> = { - AllOrganizations: { - name: 'My Organizations', - testId: 'Icon-Component-AllOrganizationsIcon', - }, Dashboard: { name: 'Dashboard', testId: 'Icon-Component-DashboardIcon', @@ -35,6 +31,10 @@ const screenTestIdMap: Record> = { name: 'Settings', testId: 'Icon-Component-SettingsIcon', }, + AllOrganizations: { + name: 'All Organizations', + testId: 'Icon-Component-AllOrganizationsIcon', + }, EventProject: { name: 'Add Event Project', testId: 'Icon-Component-Add-Event-Project', diff --git a/src/components/IconComponent/IconComponent.tsx b/src/components/IconComponent/IconComponent.tsx index 90a60244b5..4c490c9c94 100644 --- a/src/components/IconComponent/IconComponent.tsx +++ b/src/components/IconComponent/IconComponent.tsx @@ -53,7 +53,7 @@ const iconComponent = (props: InterfaceIconComponent): JSX.Element => { data-testid="Icon-Component-SettingsIcon" /> ); - case 'My Organizations': + case 'All Organizations': return ( { }) ).toEqual({ targets: [ - { name: 'My Organizations', url: '/orglist/id=undefined' }, { name: 'Dashboard', url: '/orgdash/id=undefined' }, { name: 'People', url: '/orgpeople/id=undefined' }, { name: 'Events', url: '/orgevents/id=undefined' }, @@ -31,10 +30,10 @@ describe('Testing Routes reducer', () => { ], }, { name: 'Settings', url: '/orgsetting/id=undefined' }, + { name: 'All Organizations', url: '/orglist/id=undefined' }, ], configUrl: 'undefined', components: [ - { name: 'My Organizations', comp_id: 'orglist', component: 'OrgList' }, { name: 'Dashboard', comp_id: 'orgdash', @@ -71,6 +70,7 @@ describe('Testing Routes reducer', () => { ], }, { name: 'Settings', comp_id: 'orgsetting', component: 'OrgSettings' }, + { name: 'All Organizations', comp_id: 'orglist', component: 'OrgList' }, { name: '', comp_id: 'member', component: 'MemberDetail' }, ], }); @@ -84,7 +84,6 @@ describe('Testing Routes reducer', () => { }) ).toEqual({ targets: [ - { name: 'My Organizations', url: '/orglist/id=undefined' }, { name: 'Dashboard', url: '/orgdash/id=undefined' }, { name: 'People', url: '/orgpeople/id=undefined' }, { name: 'Events', url: '/orgevents/id=undefined' }, @@ -102,11 +101,11 @@ describe('Testing Routes reducer', () => { ], }, { name: 'Settings', url: '/orgsetting/id=undefined' }, + { name: 'All Organizations', url: '/orglist/id=undefined' }, { test: 'testupdate' }, ], configUrl: 'undefined', components: [ - { name: 'My Organizations', comp_id: 'orglist', component: 'OrgList' }, { name: 'Dashboard', comp_id: 'orgdash', @@ -143,6 +142,7 @@ describe('Testing Routes reducer', () => { ], }, { name: 'Settings', comp_id: 'orgsetting', component: 'OrgSettings' }, + { name: 'All Organizations', comp_id: 'orglist', component: 'OrgList' }, { name: '', comp_id: 'member', component: 'MemberDetail' }, ], }); @@ -156,7 +156,6 @@ describe('Testing Routes reducer', () => { }) ).toEqual({ targets: [ - { name: 'My Organizations', url: '/orglist/id=undefined' }, { name: 'Dashboard', url: '/orgdash/id=undefined' }, { name: 'People', url: '/orgpeople/id=undefined' }, { name: 'Events', url: '/orgevents/id=undefined' }, @@ -167,6 +166,7 @@ describe('Testing Routes reducer', () => { }, { name: 'Advertisement', url: '/orgads/id=undefined' }, { name: 'Settings', url: '/orgsetting/id=undefined' }, + { name: 'All Organizations', url: '/orglist/id=undefined' }, { comp_id: null, component: null, @@ -183,7 +183,6 @@ describe('Testing Routes reducer', () => { ], configUrl: 'undefined', components: [ - { name: 'My Organizations', comp_id: 'orglist', component: 'OrgList' }, { name: 'Dashboard', comp_id: 'orgdash', @@ -221,6 +220,7 @@ describe('Testing Routes reducer', () => { ], }, { name: 'Settings', comp_id: 'orgsetting', component: 'OrgSettings' }, + { name: 'All Organizations', comp_id: 'orglist', component: 'OrgList' }, { name: '', comp_id: 'member', component: 'MemberDetail' }, ], }); diff --git a/src/state/reducers/routesReducer.ts b/src/state/reducers/routesReducer.ts index 7157feb23f..4fafbd1ebb 100644 --- a/src/state/reducers/routesReducer.ts +++ b/src/state/reducers/routesReducer.ts @@ -63,7 +63,6 @@ export type TargetsType = { // Note: Routes with names appear on NavBar const components: ComponentType[] = [ - { name: 'My Organizations', comp_id: 'orglist', component: 'OrgList' }, { name: 'Dashboard', comp_id: 'orgdash', component: 'OrganizationDashboard' }, { name: 'People', comp_id: 'orgpeople', component: 'OrganizationPeople' }, { name: 'Events', comp_id: 'orgevents', component: 'OrganizationEvents' }, @@ -85,6 +84,7 @@ const components: ComponentType[] = [ }, { name: 'Settings', comp_id: 'orgsetting', component: 'OrgSettings' }, + { name: 'All Organizations', comp_id: 'orglist', component: 'OrgList' }, { name: '', comp_id: 'member', component: 'MemberDetail' }, ]; From a320d35e91b2a3d10a9143384969dba0973c37f1 Mon Sep 17 00:00:00 2001 From: Peter Harrison <16875803+palisadoes@users.noreply.github.com> Date: Sun, 28 Jan 2024 15:55:39 -1000 Subject: [PATCH 11/34] Added Base branch check to main (#1515) --- .github/workflows/pull-requests.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/pull-requests.yml b/.github/workflows/pull-requests.yml index b303360aff..75f6dbda36 100644 --- a/.github/workflows/pull-requests.yml +++ b/.github/workflows/pull-requests.yml @@ -60,6 +60,7 @@ jobs: with: path: "./coverage/lcov.info" min_coverage: 95.0 + Graphql-Inspector: name: Runs Introspection on the github talawa-api repo on the schema.graphql file runs-on: ubuntu-latest @@ -80,3 +81,13 @@ jobs: - name: Validate Documents run: graphql-inspector validate './src/GraphQl/**/*.ts' './talawa-api/schema.graphql' + + Branch-check: + name: "Base branch check" + runs-on: ubuntu-latest + steps: + - name: "Check if base branch is develop" + if: github.event.pull_request.base.ref != 'develop' + run: | + echo "PR is not against develop branch. Please refer PR_GUIDELINES.md" + exit 1 From 42633e2e5eb47fa67dba88b612437cf3c77b95af Mon Sep 17 00:00:00 2001 From: Peter Harrison <16875803+palisadoes@users.noreply.github.com> Date: Sat, 27 Apr 2024 12:42:15 -0700 Subject: [PATCH 12/34] Pre-GSoC 2024 - Stable (#1934) * Added Base branch check to main * Deleted all files in the main branch in anticipation of merging develop into main cleanly * Merge develop to main * Deleted all main files * Merged develop into main --- .env.example | 10 +- .eslintrc.json | 51 +- .github/dependabot.yaml | 18 + .../authorized-changes-detection.yml | 34 - .github/workflows/codeql-codescan.yml | 2 +- .github/workflows/compare_translations.py | 170 + .github/workflows/eslint_disable_check.py | 118 + .github/workflows/md_mdx_format_adjuster.py | 97 + .github/workflows/pull-request-target.yml | 1 + .github/workflows/pull-request.yml | 244 + .github/workflows/pull-requests.yml | 93 - .github/workflows/push.yml | 107 +- .gitignore | 5 +- .husky/post-merge | 2 +- .husky/pre-commit | 6 +- .lintstagedrc.json | 5 + .node-version | 1 + CODE_OF_CONDUCT.md | 18 + CODE_STYLE.md | 36 +- CONTRIBUTING.md | 103 +- DOCUMENTATION.md | 11 + INSTALLATION.md | 135 +- ISSUE_GUIDELINES.md | 26 +- PR_GUIDELINES.md | 12 + README.md | 25 +- jest.config.js | 3 + package-lock.json | 11277 ++++++++-------- package.json | 94 +- public/images/svg/angleDown.svg | 3 + public/images/svg/profiledefault.svg | 3 + public/index.html | 11 + public/locales/en.json | 594 +- public/locales/fr.json | 586 +- public/locales/hi.json | 589 +- public/locales/sp.json | 588 +- public/locales/zh.json | 589 +- schema.graphql | 717 +- scripts/__mocks__/@dicebear/collection.ts | 1 + scripts/__mocks__/@dicebear/core.ts | 5 + scripts/config-overrides/custom_build.js | 17 + scripts/config-overrides/custom_start.js | 19 + scripts/config-overrides/index.js | 29 + scripts/config-overrides/package.json | 5 + scripts/custom-test-env.js | 1 - scripts/githooks/check-localstorage-usage.js | 96 + scripts/githooks/update-toc.js | 14 + scripts/test.js | 1 - setup.ts | 177 + src/App.test.tsx | 26 +- src/App.tsx | 184 +- src/Constant/constant.spec.ts | 4 +- src/Constant/constant.ts | 1 + .../Mutations/ActionItemCategoryMutations.ts | 39 + src/GraphQl/Mutations/ActionItemMutations.ts | 85 + src/GraphQl/Mutations/CampaignMutation.ts | 87 + src/GraphQl/Mutations/CommentMutations.ts | 58 + .../Mutations/EventAttendeeMutations.ts | 49 + src/GraphQl/Mutations/FundMutation.ts | 85 + .../Mutations/OrganizationMutations.ts | 176 + src/GraphQl/Mutations/PledgeMutation.ts | 82 + src/GraphQl/Mutations/VenueMutations.ts | 79 + src/GraphQl/Mutations/mutations.ts | 506 +- .../Queries/ActionItemCategoryQueries.ts | 18 + src/GraphQl/Queries/ActionItemQueries.ts | 103 + src/GraphQl/Queries/OrganizationQueries.ts | 320 + src/GraphQl/Queries/PlugInQueries.ts | 179 + src/GraphQl/Queries/Queries.ts | 715 +- src/GraphQl/Queries/fundQueries.ts | 67 + src/assets/css/app.css | 584 +- src/assets/css/app.css.map | 1 + src/assets/css/scrollStyles.css | 18 + src/assets/scss/components/_accordion.scss | 4 +- src/assets/scss/components/_buttons.scss | 11 +- src/assets/scss/components/_nav.scss | 6 +- src/assets/scss/components/_pagination.scss | 7 +- src/assets/scss/forms/_floating-label.scss | 4 +- src/assets/scss/forms/_form-control.scss | 4 +- src/assets/scss/forms/_range.scss | 10 +- src/assets/svgs/actionItem.svg | 6 + src/assets/svgs/addEventProject.svg | 1 - src/assets/svgs/angleLeft.svg | 5 + src/assets/svgs/article.svg | 14 + src/assets/svgs/cardItemDate.svg | 3 + src/assets/svgs/cardItemEvent.svg | 3 + src/assets/svgs/cardItemLocation.svg | 4 + src/assets/svgs/eventDashboard.svg | 7 + src/assets/svgs/eventStats.svg | 13 +- src/assets/svgs/funds.svg | 1 + src/assets/svgs/media.svg | 14 + src/assets/svgs/people.svg | 4 +- src/assets/svgs/requests.svg | 13 +- src/assets/svgs/settings.svg | 4 +- .../svgs/social-icons/Facebook-Logo.svg | 4 + src/assets/svgs/social-icons/Github-Logo.svg | 4 + .../svgs/social-icons/Instagram-Logo.svg | 23 + .../svgs/social-icons/Linkedin-Logo.svg | 4 + src/assets/svgs/social-icons/Reddit-Logo.svg | 11 + src/assets/svgs/social-icons/Slack-Logo.svg | 14 + src/assets/svgs/social-icons/Twitter-Logo.svg | 4 + src/assets/svgs/social-icons/Youtube-Logo.svg | 4 + src/assets/svgs/social-icons/index.tsx | 19 + src/assets/svgs/userEvent.svg | 14 + src/assets/svgs/venues.svg | 1 + .../ActionItemsContainer.module.css | 25 + .../ActionItems/ActionItemsContainer.test.tsx | 670 + .../ActionItems/ActionItemsContainer.tsx | 461 + .../ActionItems/ActionItemsContainerMocks.ts | 112 + .../ActionItems/ActionItemsContainerProps.ts | 131 + .../ActionItems/ActionItemsModal.test.tsx | 294 + .../ActionItems/ActionItemsModal.tsx | 42 + .../ActionItems/ActionItemsModalBody.tsx | 217 + .../ActionItems/ActionItemsWrapper.module.css | 53 + .../ActionItems/ActionItemsWrapper.test.tsx | 73 + .../ActionItems/ActionItemsWrapper.tsx | 45 + src/components/AddOn/AddOn.test.tsx | 2 +- .../AddOn/core/AddOnEntry/AddOnEntry.test.tsx | 117 +- .../AddOn/core/AddOnEntry/AddOnEntry.tsx | 11 +- .../AddOn/core/AddOnEntry/AddOnEntryMocks.ts | 25 + .../core/AddOnRegister/AddOnRegister.test.tsx | 149 +- .../core/AddOnRegister/AddOnRegister.tsx | 35 +- .../AddOn/core/AddOnStore/AddOnStore.test.tsx | 376 +- .../AddOn/core/AddOnStore/AddOnStore.tsx | 391 +- .../support/components/Action/Action.test.tsx | 2 +- .../MainContent/MainContent.test.tsx | 2 +- .../components/SidePanel/SidePanel.test.tsx | 2 +- .../AddOn/support/services/Plugin.helper.ts | 2 +- .../Advertisements/Advertisements.test.tsx | 694 +- .../Advertisements/Advertisements.tsx | 311 +- .../AdvertisementEntry.module.css | 59 +- .../AdvertisementEntry.test.tsx | 538 +- .../AdvertisementEntry/AdvertisementEntry.tsx | 189 +- .../AdvertisementRegister.module.css | 48 +- .../AdvertisementRegister.test.tsx | 540 +- .../AdvertisementRegister.tsx | 323 +- src/components/Avatar/Avatar.module.css | 11 + src/components/Avatar/Avatar.test.tsx | 50 + src/components/Avatar/Avatar.tsx | 45 + .../ChangeLanguageDropDown.tsx | 2 +- .../ChangeLanguageDropdown.test.tsx | 14 +- src/components/CheckIn/CheckInModal.test.tsx | 6 +- src/components/CheckIn/CheckInModal.tsx | 6 +- .../CheckIn/CheckInWrapper.test.tsx | 29 +- src/components/CheckIn/TableRow.test.tsx | 18 +- src/components/CheckIn/TableRow.tsx | 3 - src/components/CheckIn/mocks.ts | 6 - src/components/CheckIn/types.ts | 4 - .../CollapsibleDropdown.test.tsx | 37 +- .../CollapsibleDropdown.tsx | 85 +- .../ContriStats/ContriStats.test.tsx | 2 +- .../CurrentHourIndicator.module.css | 19 + .../CurrentHourIndicator.test.tsx | 10 + .../CurrentHourIndicator.tsx | 13 + src/components/DeleteOrg/DeleteOrg.test.tsx | 194 +- src/components/DeleteOrg/DeleteOrg.tsx | 30 +- .../DynamicDropDown.module.css | 12 + .../DynamicDropDown/DynamicDropDown.test.tsx | 64 + .../DynamicDropDown/DynamicDropDown.tsx | 55 + .../EditCustomFieldDropDown.test.tsx | 60 + .../EditCustomFieldDropDown.tsx | 53 + .../EventCalendar/EventCalendar.module.css | 310 +- .../EventCalendar/EventCalendar.test.tsx | 279 +- .../EventCalendar/EventCalendar.tsx | 592 +- .../EventCalendar/EventHeader.test.tsx | 100 + src/components/EventCalendar/EventHeader.tsx | 110 + .../YearlyEventCalender.module.css | 354 + .../EventCalendar/YearlyEventCalender.tsx | 360 + src/components/EventCalendar/constants.js | 56 + .../EventDashboardScreen.module.css | 198 + .../EventDashboardScreen.test.tsx | 166 + .../EventDashboardScreen.tsx | 144 + .../EventListCard/EventListCard.module.css | 92 +- .../EventListCard/EventListCard.test.tsx | 1093 +- .../EventListCard/EventListCard.tsx | 480 +- .../EventListCard/EventListCardMocks.ts | 201 + .../EventListCard/EventListCardModals.tsx | 810 ++ .../EventListCard/EventListCardProps.ts | 194 + .../Dashboard/EventDashboard.mocks.ts | 65 + .../Dashboard/EventDashboard.module.css | 76 + .../Dashboard/EventDashboard.test.tsx | 83 + .../Dashboard/EventDashboard.tsx | 108 + .../EventActionItems.module.css | 172 + .../EventActionItems.test.tsx | 628 + .../EventActionItems/EventActionItems.tsx | 598 + .../AddEventProjectModal.test.tsx | 132 - .../AddEventProjectModal.tsx | 99 - .../DeleteEventProjectModal.test.tsx | 108 - .../DeleteEventProjectModal.tsx | 70 - .../UpdateEventProjectModal.test.tsx | 155 - .../UpdateEventProjectModal.tsx | 103 - .../EventRegistrantsModal.test.tsx | 52 +- .../EventRegistrantsModal.tsx | 5 +- .../EventRegistrantsWrapper.test.tsx | 6 +- .../EventStats/EventStats.module.css | 35 + src/components/EventStats/EventStats.test.tsx | 4 +- src/components/EventStats/EventStats.tsx | 16 +- .../EventStats/EventStatsWrapper.test.tsx | 6 +- .../Statistics/AverageRating.test.tsx | 6 +- .../EventStats/Statistics/AverageRating.tsx | 21 +- .../EventStats/Statistics/Feedback.test.tsx | 20 +- .../EventStats/Statistics/Feedback.tsx | 3 +- .../EventStats/Statistics/Review.test.tsx | 10 +- .../EventStats/Statistics/Review.tsx | 2 +- .../HolidayCards/HolidayCard.module.css | 12 + src/components/HolidayCards/HolidayCard.tsx | 12 + .../IconComponent/IconComponent.test.tsx | 29 +- .../IconComponent/IconComponent.tsx | 71 +- .../LeftDrawer/LeftDrawer.module.css | 35 +- src/components/LeftDrawer/LeftDrawer.test.tsx | 173 +- src/components/LeftDrawer/LeftDrawer.tsx | 219 +- .../LeftDrawerEvent/LeftDrawerEvent.test.tsx | 243 - .../LeftDrawerEvent/LeftDrawerEvent.tsx | 199 - .../LeftDrawerEventWrapper.module.css | 60 - .../LeftDrawerEventWrapper.test.tsx | 94 - .../LeftDrawerEventWrapper.tsx | 62 - .../LeftDrawerOrg/LeftDrawerOrg.module.css | 161 +- .../LeftDrawerOrg/LeftDrawerOrg.test.tsx | 172 +- .../LeftDrawerOrg/LeftDrawerOrg.tsx | 149 +- src/components/Loader/Loader.tsx | 4 +- .../LoginPortalToggle.module.css | 34 + .../LoginPortalToggle.test.tsx | 33 + .../LoginPortalToggle/LoginPortalToggle.tsx | 47 + .../MemberRequestCard.test.tsx | 4 +- .../MemberRequestCard/MemberRequestCard.tsx | 2 +- src/components/NotFound/NotFound.module.css | 12 +- src/components/NotFound/NotFound.test.tsx | 4 +- .../OrgActionItemCategories.module.css | 33 + .../OrgActionItemCategories.test.tsx | 368 + .../OrgActionItemCategories.tsx | 291 + .../OrgActionItemCategoryMocks.ts | 174 + .../OrgAdminListCard.module.css | 74 - .../OrgAdminListCard.test.tsx | 102 +- .../OrgAdminListCard/OrgAdminListCard.tsx | 74 +- .../OrgContriCards/OrgContriCards.test.tsx | 2 +- src/components/OrgDelete/OrgDelete.test.tsx | 2 +- .../OrgListCard/OrgListCard.module.css | 77 +- .../OrgListCard/OrgListCard.test.tsx | 60 +- src/components/OrgListCard/OrgListCard.tsx | 74 +- .../OrgPeopleListCard.module.css | 74 - .../OrgPeopleListCard.test.tsx | 34 +- .../OrgPeopleListCard/OrgPeopleListCard.tsx | 69 +- .../OrgPostCard/OrgPostCard.test.tsx | 314 +- src/components/OrgPostCard/OrgPostCard.tsx | 94 +- .../OrgProfileFieldSettings.module.css | 24 + .../OrgProfileFieldSettings.test.tsx | 280 + .../OrgProfileFieldSettings.tsx | 173 + src/components/OrgUpdate/OrgUpdate.test.tsx | 116 +- src/components/OrgUpdate/OrgUpdate.tsx | 175 +- src/components/OrgUpdate/OrgUpdateMocks.ts | 67 +- .../OrganizationCardStart.tsx | 2 +- .../OrganizationDashCards/CardItem.module.css | 25 +- .../OrganizationDashCards/CardItem.test.tsx | 23 +- .../OrganizationDashCards/CardItem.tsx | 52 +- .../OrganizationScreen.module.css | 163 +- .../OrganizationScreen.test.tsx | 108 +- .../OrganizationScreen/OrganizationScreen.tsx | 137 +- src/components/Pagination/Pagination.test.tsx | 7 +- src/components/Pagination/Pagination.tsx | 10 +- .../PaginationList/PaginationList.tsx | 4 +- .../ProfileDropdown.module.css | 75 + .../ProfileDropdown/ProfileDropdown.test.tsx | 127 + .../ProfileDropdown/ProfileDropdown.tsx | 107 + .../CustomRecurrence.test.tsx | 721 + .../CustomRecurrenceModal.module.css | 59 + .../CustomRecurrenceModal.tsx | 398 + .../RecurrenceOptions.test.tsx | 583 + .../RecurrenceOptions/RecurrenceOptions.tsx | 228 + .../RequestsTableItem.module.css | 66 + .../RequestsTableItem.test.tsx | 147 + .../RequestsTableItem/RequestsTableItem.tsx | 109 + .../RequestsTableItemMocks.ts | 37 + src/components/SecuredRoute/SecuredRoute.tsx | 18 +- .../SuperAdminScreen.module.css | 53 +- .../SuperAdminScreen.test.tsx | 41 +- .../SuperAdminScreen/SuperAdminScreen.tsx | 90 +- .../TableLoader/TableLoader.test.tsx | 14 +- src/components/TableLoader/TableLoader.tsx | 4 +- .../TaskListItem/TaskListItem.test.tsx | 130 - src/components/TaskListItem/TaskListItem.tsx | 106 - .../TaskModals/AddTaskModal.test.tsx | 150 - src/components/TaskModals/AddTaskModal.tsx | 114 - .../TaskModals/DeleteTaskModal.test.tsx | 100 - src/components/TaskModals/DeleteTaskModal.tsx | 64 - .../TaskModals/ManageVolunteerModal.test.tsx | 135 - .../TaskModals/ManageVolunteerModal.tsx | 102 - .../TaskModals/UpdateTaskModal.test.tsx | 262 - src/components/TaskModals/UpdateTaskModal.tsx | 222 - .../UserListCard/UserListCard.test.tsx | 24 +- src/components/UserListCard/UserListCard.tsx | 51 +- .../UserPasswordUpdate.module.css | 8 +- .../UserPasswordUpdate.test.tsx | 26 +- .../UserPasswordUpdate/UserPasswordUpdate.tsx | 8 +- .../UserPortal/ChatRoom/ChatRoom.test.tsx | 72 + .../UserPortal/ChatRoom/ChatRoom.tsx | 1 + .../CommentCard/CommentCard.test.tsx | 45 +- .../UserPortal/CommentCard/CommentCard.tsx | 8 +- .../ContactCard/ContactCard.test.tsx | 8 +- .../UserPortal/ContactCard/ContactCard.tsx | 20 +- .../DonationCard/DonationCard.module.css | 29 +- .../DonationCard/DonationCard.test.tsx} | 28 +- .../UserPortal/DonationCard/DonationCard.tsx | 32 +- .../UserPortal/EventCard/EventCard.test.tsx | 43 +- .../UserPortal/EventCard/EventCard.tsx | 15 +- .../UserPortal/Login/Login.test.tsx | 62 +- src/components/UserPortal/Login/Login.tsx | 30 +- .../OrganizationCard.module.css | 155 +- .../OrganizationCard.test.tsx | 254 +- .../OrganizationCard/OrganizationCard.tsx | 188 +- .../OrganizationNavbar.test.tsx | 280 +- .../OrganizationNavbar/OrganizationNavbar.tsx | 56 +- .../OrganizationSidebar.test.tsx | 39 +- .../OrganizationSidebar.tsx | 9 +- .../PeopleCard/PeopleCard.module.css | 11 + .../UserPortal/PeopleCard/PeopleCard.test.tsx | 6 +- .../UserPortal/PeopleCard/PeopleCard.tsx | 36 +- .../UserPortal/PostCard/PostCard.test.tsx | 208 +- .../UserPortal/PostCard/PostCard.tsx | 89 +- .../PromotedPost/PromotedPost.module.css | 5 + .../PromotedPost/PromotedPost.test.tsx | 10 +- .../UserPortal/PromotedPost/PromotedPost.tsx | 2 +- .../UserPortal/Register/Register.test.tsx | 22 +- .../UserPortal/Register/Register.tsx | 2 +- .../SecuredRouteForUser.test.tsx | 92 +- .../SecuredRouteForUser.tsx | 16 +- .../StartPostModal/StartPostModal.module.css | 50 + .../StartPostModal/StartPostModal.test.tsx | 225 + .../StartPostModal/StartPostModal.tsx | 188 + .../UserPortal/TaskCard/TaskCard.module.css | 41 - .../UserPortal/TaskCard/TaskCard.test.tsx | 95 - .../UserPortal/TaskCard/TaskCard.tsx | 131 - .../UserPortal/UserNavbar/UserNavbar.test.tsx | 52 +- .../UserPortal/UserNavbar/UserNavbar.tsx | 28 +- .../UserSidebar/UserSidebar.module.css | 246 +- .../UserSidebar/UserSidebar.test.tsx | 427 +- .../UserPortal/UserSidebar/UserSidebar.tsx | 194 +- .../UserSidebarOrg/UserSidebarOrg.module.css} | 162 +- .../UserSidebarOrg/UserSidebarOrg.test.tsx | 419 + .../UserSidebarOrg/UserSidebarOrg.tsx | 171 + .../UserProfileSettings/DeleteUser.test.tsx | 28 + .../UserProfileSettings/DeleteUser.tsx | 25 + .../OtherSettings.test.tsx | 24 + .../UserProfileSettings/OtherSettings.tsx | 26 + .../UserProfileSettings/UserProfile.test.tsx | 38 + .../UserProfileSettings/UserProfile.tsx | 65 + .../UserProfileSettings.module.css | 76 + .../UserUpdate/UserUpdate.module.css | 93 - src/components/UserUpdate/UserUpdate.test.tsx | 159 - src/components/UserUpdate/UserUpdate.tsx | 257 - .../UsersTableItem/UserTableItem.test.tsx | 1327 +- .../UsersTableItem/UserTableItemMocks.ts | 19 - .../UsersTableItem/UsersTableItem.tsx | 284 +- src/components/Venues/VenueCard.tsx | 86 + src/components/Venues/VenueModal.module.css | 53 + src/components/Venues/VenueModal.test.tsx | 287 + src/components/Venues/VenueModal.tsx | 241 + .../plugins/DummyPlugin/DummyPlugin.test.jsx | 3 +- .../DummyPlugin2/DummyPlugin2.test.jsx | 3 +- src/constants.ts | 53 + src/index.tsx | 60 +- src/screens/BlockUser/BlockUser.test.tsx | 128 +- src/screens/BlockUser/BlockUser.tsx | 38 +- .../CommunityProfile.module.css | 41 + .../CommunityProfile.test.tsx | 334 + .../CommunityProfile/CommunityProfile.tsx | 377 + .../EventDashboard/EventDashboard.mocks.ts | 227 - .../EventDashboard/EventDashboard.module.css | 198 - .../EventDashboard/EventDashboard.test.tsx | 192 - src/screens/EventDashboard/EventDashboard.tsx | 252 - .../EventManagement.module.css | 8 + .../EventManagement/EventManagement.test.tsx | 108 + .../EventManagement/EventManagement.tsx | 157 + .../ForgotPassword/ForgotPassword.test.tsx | 227 +- src/screens/ForgotPassword/ForgotPassword.tsx | 15 +- .../FundCampaignPledge.module.css | 53 + .../FundCampaignPledge.test.tsx | 443 + .../FundCampaignPledge/FundCampaignPledge.tsx | 359 + .../FundCampaignPledge/PledgeCreateModal.tsx | 148 + .../FundCampaignPledge/PledgeDeleteModal.tsx | 58 + .../FundCampaignPledge/PledgeEditModal.tsx | 147 + .../FundCampaignPledge/PledgesMocks.ts | 312 + src/screens/LoginPage/LoginPage.module.css | 55 +- src/screens/LoginPage/LoginPage.test.tsx | 471 +- src/screens/LoginPage/LoginPage.tsx | 438 +- .../MemberDetail/MemberDetail.module.css | 81 +- .../MemberDetail/MemberDetail.test.tsx | 561 +- src/screens/MemberDetail/MemberDetail.tsx | 768 +- .../OrgContribution.module.css | 9 +- .../OrgContribution/OrgContribution.test.tsx | 2 +- src/screens/OrgList/OrgList.module.css | 67 +- src/screens/OrgList/OrgList.test.tsx | 458 +- src/screens/OrgList/OrgList.tsx | 687 +- src/screens/OrgList/OrgListMocks.ts | 125 +- src/screens/OrgList/OrganizationModal.tsx | 320 + src/screens/OrgPost/OrgPost.module.css | 4 +- src/screens/OrgPost/OrgPost.test.tsx | 342 +- src/screens/OrgPost/OrgPost.tsx | 592 +- .../OrgSettings/OrgSettings.module.css | 29 +- src/screens/OrgSettings/OrgSettings.test.tsx | 60 +- src/screens/OrgSettings/OrgSettings.tsx | 157 +- .../ActionItemCreateModal.tsx | 155 + .../ActionItemDeleteModal.tsx | 59 + .../ActionItemPreviewModal.tsx | 133 + .../ActionItemUpdateModal.test.tsx | 235 + .../ActionItemUpdateModal.tsx | 157 + .../OrganizationActionItemMocks.ts | 388 + .../OrganizationActionItems.module.css | 168 + .../OrganizationActionItems.test.tsx | 599 + .../OrganizationActionItems.tsx | 390 + .../OrganizationActionItemsErrorMocks.ts | 266 + .../OrganizationDashboard.module.css | 5 + .../OrganizationDashboard.test.tsx | 92 +- .../OrganizationDashboard.tsx | 517 +- .../OrganizationDashboardMocks.ts | 238 +- .../OrganizationEvents.module.css | 114 +- .../OrganizationEvents.test.tsx | 410 +- .../OrganizationEvents/OrganizationEvents.tsx | 382 +- .../OrganizationEventsMocks.ts | 241 + src/screens/OrganizationEvents/calendar.css | 146 - .../CampaignCreateModal.tsx | 158 + .../CampaignDeleteModal.tsx | 53 + .../CampaignUpdateModal.tsx | 170 + .../OrganizationFundCampagins.tsx | 444 + .../OrganizationFundCampaign.module.css | 181 + .../OrganizationFundCampaign.test.tsx | 663 + .../OrganizationFundCampaignMocks.tsx | 265 + .../OrganizationFunds/FundCreateModal.tsx | 118 + .../OrganizationFunds/FundUpdateModal.tsx | 155 + .../OrganizationFunds.module.css | 177 + .../OrganizationFunds.test.tsx | 407 + .../OrganizationFunds/OrganizationFunds.tsx | 424 + .../OrganizationFundsMocks.ts | 368 + src/screens/OrganizationPeople/AddMember.tsx | 562 + .../OrganizationPeople/MockDataTypes.ts | 77 + .../OrganizationPeople.module.css | 299 +- .../OrganizationPeople.test.tsx | 1368 +- .../OrganizationPeople/OrganizationPeople.tsx | 606 +- .../OrganizationVenues.module.css | 879 ++ .../OrganizationVenues.test.tsx | 497 + .../OrganizationVenues/OrganizationVenues.tsx | 249 + .../PageNotFound/PageNotFound.test.tsx | 35 +- src/screens/PageNotFound/PageNotFound.tsx | 25 +- src/screens/Requests/Requests.module.css | 39 +- src/screens/Requests/Requests.test.tsx | 193 +- src/screens/Requests/Requests.tsx | 496 +- src/screens/Requests/RequestsMocks.ts | 577 +- src/screens/UserPortal/Chat/Chat.module.css | 2 +- src/screens/UserPortal/Chat/Chat.test.tsx | 32 +- src/screens/UserPortal/Chat/Chat.tsx | 39 +- .../UserPortal/Donate/Donate.module.css | 51 +- src/screens/UserPortal/Donate/Donate.test.tsx | 138 +- src/screens/UserPortal/Donate/Donate.tsx | 146 +- .../UserPortal/Events/Events.module.css | 89 +- src/screens/UserPortal/Events/Events.test.tsx | 310 +- src/screens/UserPortal/Events/Events.tsx | 591 +- src/screens/UserPortal/Home/Home.module.css | 71 - src/screens/UserPortal/Home/Home.test.tsx | 285 - src/screens/UserPortal/Home/Home.tsx | 291 - .../Organizations/Organizations.module.css | 122 +- .../Organizations/Organizations.test.tsx | 360 +- .../Organizations/Organizations.tsx | 263 +- .../UserPortal/People/People.module.css | 53 +- src/screens/UserPortal/People/People.test.tsx | 53 +- src/screens/UserPortal/People/People.tsx | 111 +- src/screens/UserPortal/Posts/Posts.module.css | 164 + src/screens/UserPortal/Posts/Posts.test.tsx | 361 + src/screens/UserPortal/Posts/Posts.tsx | 356 + .../UserPortal/Settings/Settings.module.css | 174 +- .../UserPortal/Settings/Settings.test.tsx | 248 +- src/screens/UserPortal/Settings/Settings.tsx | 636 +- src/screens/UserPortal/Tasks/Tasks.module.css | 48 - src/screens/UserPortal/Tasks/Tasks.test.tsx | 130 - src/screens/UserPortal/Tasks/Tasks.tsx | 173 - .../UserLoginPage/UserLoginPage.module.css | 48 - .../UserLoginPage/UserLoginPage.tsx | 49 - .../UserScreen/UserScreen.module.css | 173 + .../UserPortal/UserScreen/UserScreen.test.tsx | 117 + .../UserPortal/UserScreen/UserScreen.tsx | 97 + src/screens/Users/Users.test.tsx | 178 +- src/screens/Users/Users.tsx | 408 +- src/screens/Users/UsersMocks.ts | 455 +- .../askForCustomPort/askForCustomPort.test.ts | 24 + .../askForCustomPort/askForCustomPort.ts | 14 + .../askForTalawaApiUrl.test.ts | 58 + .../askForTalawaApiUrl/askForTalawaApiUrl.ts | 13 + .../checkConnection/checkConnection.test.ts | 55 + src/setup/checkConnection/checkConnection.ts | 15 + src/setup/checkEnvFile/checkEnvFile.test.ts | 47 + src/setup/checkEnvFile/checkEnvFile.ts | 16 + .../validateRecaptcha.test.ts | 23 + .../validateRecaptcha/validateRecaptcha.ts | 4 + src/setupTests.ts | 7 +- src/state/action-creators/index.ts | 9 + src/state/reducers/index.ts | 2 + src/state/reducers/pluginReducer.test.ts | 22 +- src/state/reducers/pluginReducer.ts | 4 +- src/state/reducers/routesReducer.test.ts | 167 +- src/state/reducers/routesReducer.ts | 87 +- src/state/reducers/userRoutersReducer.test.ts | 68 + src/state/reducers/userRoutesReducer.ts | 81 + src/state/store.test.tsx | 1 - src/utils/StaticMockLink.ts | 72 +- src/utils/currency.ts | 330 + src/utils/debounce.ts | 9 - src/utils/errorHandler.tsx | 2 +- src/utils/fieldTypes.ts | 3 + src/utils/formEnumFields.ts | 352 + src/utils/getOrganizationId.ts | 4 +- src/utils/getRefreshToken.test.ts | 12 +- src/utils/getRefreshToken.ts | 10 +- src/utils/interfaces.ts | 372 +- src/utils/linkValid.test.tsx | 15 + src/utils/linkValidator.ts | 8 + src/utils/recurrenceUtils/index.ts | 3 + .../recurrenceUtils/recurrenceConstants.ts | 87 + src/utils/recurrenceUtils/recurrenceTypes.ts | 59 + .../recurrenceUtilityFunctions.ts | 252 + src/utils/useLocalstorage.test.ts | 137 + src/utils/useLocalstorage.ts | 72 + talawa-admin-docs/Dockerfile | 0 talawa-admin-docs/README.md | 12 + ..._support_services_Plugin_helper.default.md | 24 +- ..._support_services_Render_helper.default.md | 6 +- ...ts_EventCalendar_EventCalendar.ViewType.md | 32 + ..._CheckIn_types.InterfaceAttendeeCheckIn.md | 8 +- ...In_types.InterfaceAttendeeQueryResponse.md | 2 +- ...onents_CheckIn_types.InterfaceModalProp.md | 8 +- ...nts_CheckIn_types.InterfaceTableCheckIn.md | 12 +- ...onents_CheckIn_types.InterfaceTableData.md | 6 +- .../components_CheckIn_types.InterfaceUser.md | 6 +- ...leDropdown.InterfaceCollapsibleDropdown.md | 4 +- ...nt_IconComponent.InterfaceIconComponent.md | 8 +- ...eftDrawerEvent.InterfaceLeftDrawerProps.md | 53 + ...eftDrawerEventWrapper.InterfacePropType.md | 42 + ..._LeftDrawerOrg.InterfaceLeftDrawerProps.md | 12 +- ...wer_LeftDrawer.InterfaceLeftDrawerProps.md | 8 +- ...d_OrgListCard.InterfaceOrgListCardProps.md | 2 +- ...eFieldSettings.InterfaceCustomFieldData.md | 32 + ...ionDashCards_CardItem.InterfaceCardItem.md | 87 + ...Screen.InterfaceOrganizationScreenProps.md | 6 +- ...inScreen.InterfaceSuperAdminScreenProps.md | 6 +- ...Loader_TableLoader.InterfaceTableLoader.md | 43 + talawa-admin-docs/modules.md | 78 +- .../modules/components_AddOn_AddOn.default.md | 48 - .../modules/components_AddOn_AddOn.md | 6 +- ...ddOn_core_AddOnEntry_AddOnEntry.default.md | 52 - ...onents_AddOn_core_AddOnEntry_AddOnEntry.md | 6 +- ...s_AddOn_core_AddOnEntry_AddOnEntryMocks.md | 19 + ...ore_AddOnRegister_AddOnRegister.default.md | 44 - ..._AddOn_core_AddOnRegister_AddOnRegister.md | 6 +- ...ddOn_core_AddOnStore_AddOnStore.default.md | 32 - ...onents_AddOn_core_AddOnStore_AddOnStore.md | 6 +- ..._AddOn_support_components_Action_Action.md | 2 +- ...port_components_MainContent_MainContent.md | 2 +- ..._support_components_SidePanel_SidePanel.md | 2 +- ...omponents_Advertisements_Advertisements.md | 23 + ...ents_Advertisements_Advertisements_test.md | 3 + ...e_AdvertisementEntry_AdvertisementEntry.md | 29 + ...ertisementEntry_AdvertisementEntry_test.md | 3 + ...rtisementRegister_AdvertisementRegister.md | 29 + ...mentRegister_AdvertisementRegister_test.md | 3 + ...LanguageDropdown_ChangeLanguageDropDown.md | 8 +- .../components_CheckIn_CheckInModal.md | 2 +- .../components_CheckIn_CheckInWrapper.md | 2 +- .../modules/components_CheckIn_TableRow.md | 4 +- .../modules/components_CheckIn_mocks.md | 12 +- .../modules/components_CheckIn_tagTemplate.md | 2 +- ...CollapsibleDropdown_CollapsibleDropdown.md | 2 +- .../components_ContriStats_ContriStats.md | 2 +- ...rrentHourIndicator_CurrentHourIndicator.md | 23 + ...HourIndicator_CurrentHourIndicator_test.md | 3 + .../modules/components_DeleteOrg_DeleteOrg.md | 23 + .../components_DeleteOrg_DeleteOrg_test.md | 3 + ...omFieldDropDown_EditCustomFieldDropDown.md | 29 + ...ldDropDown_EditCustomFieldDropDown_test.md | 3 + .../components_EventCalendar_EventCalendar.md | 12 +- .../components_EventListCard_EventListCard.md | 2 +- ...EventProjectModals_AddEventProjectModal.md | 29 - ...ProjectModals_AddEventProjectModal_test.md | 3 - ...ntProjectModals_DeleteEventProjectModal.md | 29 - ...jectModals_DeleteEventProjectModal_test.md | 3 - ...ntProjectModals_UpdateEventProjectModal.md | 29 - ...jectModals_UpdateEventProjectModal_test.md | 3 - ...tRegistrantsModal_EventRegistrantsModal.md | 2 +- ...egistrantsModal_EventRegistrantsWrapper.md | 2 +- .../components_EventStats_EventStats.md | 29 + ...components_EventStats_EventStatsWrapper.md | 29 + ...nents_EventStats_EventStatsWrapper_test.md | 3 + .../components_EventStats_EventStats_test.md | 3 + ...nts_EventStats_Statistics_AverageRating.md | 29 + ...ventStats_Statistics_AverageRating_test.md | 3 + ...mponents_EventStats_Statistics_Feedback.md | 29 + ...nts_EventStats_Statistics_Feedback_test.md | 3 + ...components_EventStats_Statistics_Review.md | 29 + ...nents_EventStats_Statistics_Review_test.md | 3 + .../components_IconComponent_IconComponent.md | 2 +- .../components_LandingPage_LandingPage.md | 23 - ...components_LandingPage_LandingPage_test.md | 3 - ...ponents_LeftDrawerEvent_LeftDrawerEvent.md | 33 + ..._LeftDrawerEvent_LeftDrawerEventWrapper.md | 33 + ...DrawerEvent_LeftDrawerEventWrapper_test.md | 3 + ...ts_LeftDrawerEvent_LeftDrawerEvent_test.md | 3 + .../components_LeftDrawerOrg_LeftDrawerOrg.md | 2 +- .../components_LeftDrawer_LeftDrawer.md | 2 +- .../modules/components_Loader_Loader.md | 10 +- ...nts_LoginPortalToggle_LoginPortalToggle.md | 23 + ...oginPortalToggle_LoginPortalToggle_test.md | 3 + ...nts_MemberRequestCard_MemberRequestCard.md | 2 +- .../modules/components_NotFound_NotFound.md | 2 +- ...nents_OrgAdminListCard_OrgAdminListCard.md | 2 +- ...omponents_OrgContriCards_OrgContriCards.md | 2 +- .../modules/components_OrgDelete_OrgDelete.md | 2 +- .../components_OrgListCard_OrgListCard.md | 2 +- ...nts_OrgPeopleListCard_OrgPeopleListCard.md | 2 +- .../components_OrgPostCard_OrgPostCard.md | 2 +- ...leFieldSettings_OrgProfileFieldSettings.md | 27 + ...ldSettings_OrgProfileFieldSettings_test.md | 3 + .../modules/components_OrgUpdate_OrgUpdate.md | 2 +- .../components_OrgUpdate_OrgUpdateMocks.md | 41 + ...nizationCardStart_OrganizationCardStart.md | 2 +- ...nents_OrganizationCard_OrganizationCard.md | 2 +- ...mponents_OrganizationDashCards_CardItem.md | 33 + ...s_OrganizationDashCards_CardItemLoading.md | 23 + ...nts_OrganizationDashCards_CardItem_test.md | 3 + ...nts_OrganizationDashCards_DashboardCard.md | 32 + ...anizationDashCards_DashboardCardLoading.md | 23 + ...rganizationDashCards_DashboardCard_test.md | 3 + ...s_OrganizationScreen_OrganizationScreen.md | 2 +- ...omponents_PaginationList_PaginationList.md | 2 +- .../components_Pagination_Pagination.md | 2 +- .../components_SecuredRoute_SecuredRoute.md | 2 +- ...nents_SuperAdminScreen_SuperAdminScreen.md | 2 +- .../components_TableLoader_TableLoader.md | 8 +- .../components_TaskListItem_TaskListItem.md | 29 - ...mponents_TaskListItem_TaskListItem_test.md | 3 - .../components_TaskModals_AddTaskModal.md | 29 - ...components_TaskModals_AddTaskModal_test.md | 3 - .../components_TaskModals_DeleteTaskModal.md | 29 - ...ponents_TaskModals_DeleteTaskModal_test.md | 3 - ...ponents_TaskModals_ManageVolunteerModal.md | 29 - ...ts_TaskModals_ManageVolunteerModal_test.md | 3 - .../components_TaskModals_UpdateTaskModal.md | 55 - ...ponents_TaskModals_UpdateTaskModal_test.md | 3 - .../components_UserListCard_UserListCard.md | 2 +- ...s_UserPasswordUpdate_UserPasswordUpdate.md | 8 +- ...components_UserPortal_ChatRoom_ChatRoom.md | 29 + ...nents_UserPortal_ChatRoom_ChatRoom_test.md | 3 + ...ents_UserPortal_CommentCard_CommentCard.md | 29 + ...UserPortal_CommentCard_CommentCard_test.md | 3 + ...ents_UserPortal_ContactCard_ContactCard.md | 29 + ...UserPortal_ContactCard_ContactCard_test.md | 3 + ...ts_UserPortal_DonationCard_DonationCard.md | 2 +- ...mponents_UserPortal_EventCard_EventCard.md | 29 + ...nts_UserPortal_EventCard_EventCard_test.md | 3 + .../components_UserPortal_Login_Login.md | 2 +- ...ortal_OrganizationCard_OrganizationCard.md | 2 +- ...l_OrganizationNavbar_OrganizationNavbar.md | 2 +- ...OrganizationSidebar_OrganizationSidebar.md | 2 +- ...onents_UserPortal_PeopleCard_PeopleCard.md | 2 +- ...components_UserPortal_PostCard_PostCard.md | 2 +- ...ts_UserPortal_PromotedPost_PromotedPost.md | 29 + ...erPortal_PromotedPost_PromotedPost_test.md | 3 + ...components_UserPortal_Register_Register.md | 2 +- ...SecuredRouteForUser_SecuredRouteForUser.md | 2 +- ...edRouteForUser_SecuredRouteForUser_test.md | 3 + ...onents_UserPortal_UserNavbar_UserNavbar.md | 2 +- ...ents_UserPortal_UserSidebar_UserSidebar.md | 2 +- .../components_UserUpdate_UserUpdate.md | 8 +- ...nents_UsersTableItem_UserTableItemMocks.md | 19 + ...nents_UsersTableItem_UserTableItem_test.md | 3 + ...omponents_UsersTableItem_UsersTableItem.md | 29 + ...ugins_DummyPlugin2_DummyPlugin2.default.md | 32 - ...nents_plugins_DummyPlugin2_DummyPlugin2.md | 6 +- ...plugins_DummyPlugin_DummyPlugin.default.md | 32 - ...ponents_plugins_DummyPlugin_DummyPlugin.md | 6 +- .../modules/screens_BlockUser_BlockUser.md | 2 +- .../screens_EventDashboard_EventDashboard.md | 2 +- ...ens_EventDashboard_EventDashboard_mocks.md | 30 +- .../screens_ForgotPassword_ForgotPassword.md | 2 +- .../modules/screens_LoginPage_LoginPage.md | 2 +- .../screens_MemberDetail_MemberDetail.md | 12 +- ...screens_OrgContribution_OrgContribution.md | 2 +- .../modules/screens_OrgList_OrgList.md | 2 +- .../modules/screens_OrgList_OrgListMocks.md | 23 +- .../screens_OrgList_OrganizationModal.md | 32 + .../modules/screens_OrgPost_OrgPost.md | 2 +- .../screens_OrgSettings_OrgSettings.md | 2 +- ...nizationDashboard_OrganizationDashboard.md | 2 +- ...ionDashboard_OrganizationDashboardMocks.md | 24 +- ...s_OrganizationEvents_OrganizationEvents.md | 2 +- ...s_OrganizationPeople_OrganizationPeople.md | 2 +- .../screens_PageNotFound_PageNotFound.md | 2 +- .../modules/screens_Requests_Requests.md | 23 - .../modules/screens_Requests_Requests_test.md | 3 - .../modules/screens_UserPortal_Chat_Chat.md | 23 + .../screens_UserPortal_Chat_Chat_test.md | 3 + .../screens_UserPortal_Donate_Donate.md | 2 +- .../screens_UserPortal_Events_Events.md | 23 + .../screens_UserPortal_Events_Events_test.md | 3 + .../modules/screens_UserPortal_Home_Home.md | 2 +- ..._UserPortal_Organizations_Organizations.md | 2 +- .../screens_UserPortal_People_People.md | 2 +- .../screens_UserPortal_Settings_Settings.md | 2 +- ..._UserPortal_UserLoginPage_UserLoginPage.md | 2 +- .../modules/screens_Users_Users.md | 2 +- .../modules/screens_Users_UsersMocks.md | 41 + tsconfig.json | 2 +- 705 files changed, 63291 insertions(+), 23988 deletions(-) create mode 100644 .github/dependabot.yaml delete mode 100644 .github/workflows/authorized-changes-detection.yml create mode 100644 .github/workflows/compare_translations.py create mode 100644 .github/workflows/eslint_disable_check.py create mode 100644 .github/workflows/md_mdx_format_adjuster.py create mode 100644 .github/workflows/pull-request.yml delete mode 100644 .github/workflows/pull-requests.yml create mode 100644 .lintstagedrc.json create mode 100644 .node-version create mode 100644 public/images/svg/angleDown.svg create mode 100644 public/images/svg/profiledefault.svg create mode 100644 scripts/__mocks__/@dicebear/collection.ts create mode 100644 scripts/__mocks__/@dicebear/core.ts create mode 100644 scripts/config-overrides/custom_build.js create mode 100644 scripts/config-overrides/custom_start.js create mode 100644 scripts/config-overrides/index.js create mode 100644 scripts/config-overrides/package.json create mode 100755 scripts/githooks/check-localstorage-usage.js create mode 100644 scripts/githooks/update-toc.js create mode 100644 setup.ts create mode 100644 src/GraphQl/Mutations/ActionItemCategoryMutations.ts create mode 100644 src/GraphQl/Mutations/ActionItemMutations.ts create mode 100644 src/GraphQl/Mutations/CampaignMutation.ts create mode 100644 src/GraphQl/Mutations/CommentMutations.ts create mode 100644 src/GraphQl/Mutations/EventAttendeeMutations.ts create mode 100644 src/GraphQl/Mutations/FundMutation.ts create mode 100644 src/GraphQl/Mutations/OrganizationMutations.ts create mode 100644 src/GraphQl/Mutations/PledgeMutation.ts create mode 100644 src/GraphQl/Mutations/VenueMutations.ts create mode 100644 src/GraphQl/Queries/ActionItemCategoryQueries.ts create mode 100644 src/GraphQl/Queries/ActionItemQueries.ts create mode 100644 src/GraphQl/Queries/OrganizationQueries.ts create mode 100644 src/GraphQl/Queries/PlugInQueries.ts create mode 100644 src/GraphQl/Queries/fundQueries.ts create mode 100644 src/assets/css/app.css.map create mode 100644 src/assets/css/scrollStyles.css create mode 100644 src/assets/svgs/actionItem.svg delete mode 100644 src/assets/svgs/addEventProject.svg create mode 100644 src/assets/svgs/angleLeft.svg create mode 100644 src/assets/svgs/article.svg create mode 100644 src/assets/svgs/cardItemDate.svg create mode 100644 src/assets/svgs/cardItemEvent.svg create mode 100644 src/assets/svgs/cardItemLocation.svg create mode 100644 src/assets/svgs/eventDashboard.svg create mode 100644 src/assets/svgs/funds.svg create mode 100644 src/assets/svgs/media.svg create mode 100644 src/assets/svgs/social-icons/Facebook-Logo.svg create mode 100644 src/assets/svgs/social-icons/Github-Logo.svg create mode 100644 src/assets/svgs/social-icons/Instagram-Logo.svg create mode 100644 src/assets/svgs/social-icons/Linkedin-Logo.svg create mode 100644 src/assets/svgs/social-icons/Reddit-Logo.svg create mode 100644 src/assets/svgs/social-icons/Slack-Logo.svg create mode 100644 src/assets/svgs/social-icons/Twitter-Logo.svg create mode 100644 src/assets/svgs/social-icons/Youtube-Logo.svg create mode 100644 src/assets/svgs/social-icons/index.tsx create mode 100644 src/assets/svgs/userEvent.svg create mode 100644 src/assets/svgs/venues.svg create mode 100644 src/components/ActionItems/ActionItemsContainer.module.css create mode 100644 src/components/ActionItems/ActionItemsContainer.test.tsx create mode 100644 src/components/ActionItems/ActionItemsContainer.tsx create mode 100644 src/components/ActionItems/ActionItemsContainerMocks.ts create mode 100644 src/components/ActionItems/ActionItemsContainerProps.ts create mode 100644 src/components/ActionItems/ActionItemsModal.test.tsx create mode 100644 src/components/ActionItems/ActionItemsModal.tsx create mode 100644 src/components/ActionItems/ActionItemsModalBody.tsx create mode 100644 src/components/ActionItems/ActionItemsWrapper.module.css create mode 100644 src/components/ActionItems/ActionItemsWrapper.test.tsx create mode 100644 src/components/ActionItems/ActionItemsWrapper.tsx create mode 100644 src/components/AddOn/core/AddOnEntry/AddOnEntryMocks.ts create mode 100644 src/components/Avatar/Avatar.module.css create mode 100644 src/components/Avatar/Avatar.test.tsx create mode 100644 src/components/Avatar/Avatar.tsx create mode 100644 src/components/CurrentHourIndicator/CurrentHourIndicator.module.css create mode 100644 src/components/CurrentHourIndicator/CurrentHourIndicator.test.tsx create mode 100644 src/components/CurrentHourIndicator/CurrentHourIndicator.tsx create mode 100644 src/components/DynamicDropDown/DynamicDropDown.module.css create mode 100644 src/components/DynamicDropDown/DynamicDropDown.test.tsx create mode 100644 src/components/DynamicDropDown/DynamicDropDown.tsx create mode 100644 src/components/EditCustomFieldDropDown/EditCustomFieldDropDown.test.tsx create mode 100644 src/components/EditCustomFieldDropDown/EditCustomFieldDropDown.tsx create mode 100644 src/components/EventCalendar/EventHeader.test.tsx create mode 100644 src/components/EventCalendar/EventHeader.tsx create mode 100644 src/components/EventCalendar/YearlyEventCalender.module.css create mode 100644 src/components/EventCalendar/YearlyEventCalender.tsx create mode 100644 src/components/EventCalendar/constants.js create mode 100644 src/components/EventDashboardScreen/EventDashboardScreen.module.css create mode 100644 src/components/EventDashboardScreen/EventDashboardScreen.test.tsx create mode 100644 src/components/EventDashboardScreen/EventDashboardScreen.tsx create mode 100644 src/components/EventListCard/EventListCardMocks.ts create mode 100644 src/components/EventListCard/EventListCardModals.tsx create mode 100644 src/components/EventListCard/EventListCardProps.ts create mode 100644 src/components/EventManagement/Dashboard/EventDashboard.mocks.ts create mode 100644 src/components/EventManagement/Dashboard/EventDashboard.module.css create mode 100644 src/components/EventManagement/Dashboard/EventDashboard.test.tsx create mode 100644 src/components/EventManagement/Dashboard/EventDashboard.tsx create mode 100644 src/components/EventManagement/EventActionItems/EventActionItems.module.css create mode 100644 src/components/EventManagement/EventActionItems/EventActionItems.test.tsx create mode 100644 src/components/EventManagement/EventActionItems/EventActionItems.tsx delete mode 100644 src/components/EventProjectModals/AddEventProjectModal.test.tsx delete mode 100644 src/components/EventProjectModals/AddEventProjectModal.tsx delete mode 100644 src/components/EventProjectModals/DeleteEventProjectModal.test.tsx delete mode 100644 src/components/EventProjectModals/DeleteEventProjectModal.tsx delete mode 100644 src/components/EventProjectModals/UpdateEventProjectModal.test.tsx delete mode 100644 src/components/EventProjectModals/UpdateEventProjectModal.tsx create mode 100644 src/components/EventStats/EventStats.module.css create mode 100644 src/components/HolidayCards/HolidayCard.module.css create mode 100644 src/components/HolidayCards/HolidayCard.tsx delete mode 100644 src/components/LeftDrawerEvent/LeftDrawerEvent.test.tsx delete mode 100644 src/components/LeftDrawerEvent/LeftDrawerEvent.tsx delete mode 100644 src/components/LeftDrawerEvent/LeftDrawerEventWrapper.module.css delete mode 100644 src/components/LeftDrawerEvent/LeftDrawerEventWrapper.test.tsx delete mode 100644 src/components/LeftDrawerEvent/LeftDrawerEventWrapper.tsx create mode 100644 src/components/LoginPortalToggle/LoginPortalToggle.module.css create mode 100644 src/components/LoginPortalToggle/LoginPortalToggle.test.tsx create mode 100644 src/components/LoginPortalToggle/LoginPortalToggle.tsx create mode 100644 src/components/OrgActionItemCategories/OrgActionItemCategories.module.css create mode 100644 src/components/OrgActionItemCategories/OrgActionItemCategories.test.tsx create mode 100644 src/components/OrgActionItemCategories/OrgActionItemCategories.tsx create mode 100644 src/components/OrgActionItemCategories/OrgActionItemCategoryMocks.ts delete mode 100644 src/components/OrgAdminListCard/OrgAdminListCard.module.css delete mode 100644 src/components/OrgPeopleListCard/OrgPeopleListCard.module.css create mode 100644 src/components/OrgProfileFieldSettings/OrgProfileFieldSettings.module.css create mode 100644 src/components/OrgProfileFieldSettings/OrgProfileFieldSettings.test.tsx create mode 100644 src/components/OrgProfileFieldSettings/OrgProfileFieldSettings.tsx create mode 100644 src/components/ProfileDropdown/ProfileDropdown.module.css create mode 100644 src/components/ProfileDropdown/ProfileDropdown.test.tsx create mode 100644 src/components/ProfileDropdown/ProfileDropdown.tsx create mode 100644 src/components/RecurrenceOptions/CustomRecurrence.test.tsx create mode 100644 src/components/RecurrenceOptions/CustomRecurrenceModal.module.css create mode 100644 src/components/RecurrenceOptions/CustomRecurrenceModal.tsx create mode 100644 src/components/RecurrenceOptions/RecurrenceOptions.test.tsx create mode 100644 src/components/RecurrenceOptions/RecurrenceOptions.tsx create mode 100644 src/components/RequestsTableItem/RequestsTableItem.module.css create mode 100644 src/components/RequestsTableItem/RequestsTableItem.test.tsx create mode 100644 src/components/RequestsTableItem/RequestsTableItem.tsx create mode 100644 src/components/RequestsTableItem/RequestsTableItemMocks.ts delete mode 100644 src/components/TaskListItem/TaskListItem.test.tsx delete mode 100644 src/components/TaskListItem/TaskListItem.tsx delete mode 100644 src/components/TaskModals/AddTaskModal.test.tsx delete mode 100644 src/components/TaskModals/AddTaskModal.tsx delete mode 100644 src/components/TaskModals/DeleteTaskModal.test.tsx delete mode 100644 src/components/TaskModals/DeleteTaskModal.tsx delete mode 100644 src/components/TaskModals/ManageVolunteerModal.test.tsx delete mode 100644 src/components/TaskModals/ManageVolunteerModal.tsx delete mode 100644 src/components/TaskModals/UpdateTaskModal.test.tsx delete mode 100644 src/components/TaskModals/UpdateTaskModal.tsx create mode 100644 src/components/UserPortal/ChatRoom/ChatRoom.test.tsx rename src/{screens/UserPortal/UserLoginPage/UserLoginPage.test.tsx => components/UserPortal/DonationCard/DonationCard.test.tsx} (65%) create mode 100644 src/components/UserPortal/StartPostModal/StartPostModal.module.css create mode 100644 src/components/UserPortal/StartPostModal/StartPostModal.test.tsx create mode 100644 src/components/UserPortal/StartPostModal/StartPostModal.tsx delete mode 100644 src/components/UserPortal/TaskCard/TaskCard.module.css delete mode 100644 src/components/UserPortal/TaskCard/TaskCard.test.tsx delete mode 100644 src/components/UserPortal/TaskCard/TaskCard.tsx rename src/components/{LeftDrawerEvent/LeftDrawerEvent.module.css => UserPortal/UserSidebarOrg/UserSidebarOrg.module.css} (60%) create mode 100644 src/components/UserPortal/UserSidebarOrg/UserSidebarOrg.test.tsx create mode 100644 src/components/UserPortal/UserSidebarOrg/UserSidebarOrg.tsx create mode 100644 src/components/UserProfileSettings/DeleteUser.test.tsx create mode 100644 src/components/UserProfileSettings/DeleteUser.tsx create mode 100644 src/components/UserProfileSettings/OtherSettings.test.tsx create mode 100644 src/components/UserProfileSettings/OtherSettings.tsx create mode 100644 src/components/UserProfileSettings/UserProfile.test.tsx create mode 100644 src/components/UserProfileSettings/UserProfile.tsx create mode 100644 src/components/UserProfileSettings/UserProfileSettings.module.css delete mode 100644 src/components/UserUpdate/UserUpdate.module.css delete mode 100644 src/components/UserUpdate/UserUpdate.test.tsx delete mode 100644 src/components/UserUpdate/UserUpdate.tsx create mode 100644 src/components/Venues/VenueCard.tsx create mode 100644 src/components/Venues/VenueModal.module.css create mode 100644 src/components/Venues/VenueModal.test.tsx create mode 100644 src/components/Venues/VenueModal.tsx create mode 100644 src/constants.ts create mode 100644 src/screens/CommunityProfile/CommunityProfile.module.css create mode 100644 src/screens/CommunityProfile/CommunityProfile.test.tsx create mode 100644 src/screens/CommunityProfile/CommunityProfile.tsx delete mode 100644 src/screens/EventDashboard/EventDashboard.mocks.ts delete mode 100644 src/screens/EventDashboard/EventDashboard.module.css delete mode 100644 src/screens/EventDashboard/EventDashboard.test.tsx delete mode 100644 src/screens/EventDashboard/EventDashboard.tsx create mode 100644 src/screens/EventManagement/EventManagement.module.css create mode 100644 src/screens/EventManagement/EventManagement.test.tsx create mode 100644 src/screens/EventManagement/EventManagement.tsx create mode 100644 src/screens/FundCampaignPledge/FundCampaignPledge.module.css create mode 100644 src/screens/FundCampaignPledge/FundCampaignPledge.test.tsx create mode 100644 src/screens/FundCampaignPledge/FundCampaignPledge.tsx create mode 100644 src/screens/FundCampaignPledge/PledgeCreateModal.tsx create mode 100644 src/screens/FundCampaignPledge/PledgeDeleteModal.tsx create mode 100644 src/screens/FundCampaignPledge/PledgeEditModal.tsx create mode 100644 src/screens/FundCampaignPledge/PledgesMocks.ts create mode 100644 src/screens/OrgList/OrganizationModal.tsx create mode 100644 src/screens/OrganizationActionItems/ActionItemCreateModal.tsx create mode 100644 src/screens/OrganizationActionItems/ActionItemDeleteModal.tsx create mode 100644 src/screens/OrganizationActionItems/ActionItemPreviewModal.tsx create mode 100644 src/screens/OrganizationActionItems/ActionItemUpdateModal.test.tsx create mode 100644 src/screens/OrganizationActionItems/ActionItemUpdateModal.tsx create mode 100644 src/screens/OrganizationActionItems/OrganizationActionItemMocks.ts create mode 100644 src/screens/OrganizationActionItems/OrganizationActionItems.module.css create mode 100644 src/screens/OrganizationActionItems/OrganizationActionItems.test.tsx create mode 100644 src/screens/OrganizationActionItems/OrganizationActionItems.tsx create mode 100644 src/screens/OrganizationActionItems/OrganizationActionItemsErrorMocks.ts create mode 100644 src/screens/OrganizationEvents/OrganizationEventsMocks.ts delete mode 100644 src/screens/OrganizationEvents/calendar.css create mode 100644 src/screens/OrganizationFundCampaign/CampaignCreateModal.tsx create mode 100644 src/screens/OrganizationFundCampaign/CampaignDeleteModal.tsx create mode 100644 src/screens/OrganizationFundCampaign/CampaignUpdateModal.tsx create mode 100644 src/screens/OrganizationFundCampaign/OrganizationFundCampagins.tsx create mode 100644 src/screens/OrganizationFundCampaign/OrganizationFundCampaign.module.css create mode 100644 src/screens/OrganizationFundCampaign/OrganizationFundCampaign.test.tsx create mode 100644 src/screens/OrganizationFundCampaign/OrganizationFundCampaignMocks.tsx create mode 100644 src/screens/OrganizationFunds/FundCreateModal.tsx create mode 100644 src/screens/OrganizationFunds/FundUpdateModal.tsx create mode 100644 src/screens/OrganizationFunds/OrganizationFunds.module.css create mode 100644 src/screens/OrganizationFunds/OrganizationFunds.test.tsx create mode 100644 src/screens/OrganizationFunds/OrganizationFunds.tsx create mode 100644 src/screens/OrganizationFunds/OrganizationFundsMocks.ts create mode 100644 src/screens/OrganizationPeople/AddMember.tsx create mode 100644 src/screens/OrganizationPeople/MockDataTypes.ts create mode 100644 src/screens/OrganizationVenues/OrganizationVenues.module.css create mode 100644 src/screens/OrganizationVenues/OrganizationVenues.test.tsx create mode 100644 src/screens/OrganizationVenues/OrganizationVenues.tsx delete mode 100644 src/screens/UserPortal/Home/Home.module.css delete mode 100644 src/screens/UserPortal/Home/Home.test.tsx delete mode 100644 src/screens/UserPortal/Home/Home.tsx create mode 100644 src/screens/UserPortal/Posts/Posts.module.css create mode 100644 src/screens/UserPortal/Posts/Posts.test.tsx create mode 100644 src/screens/UserPortal/Posts/Posts.tsx delete mode 100644 src/screens/UserPortal/Tasks/Tasks.module.css delete mode 100644 src/screens/UserPortal/Tasks/Tasks.test.tsx delete mode 100644 src/screens/UserPortal/Tasks/Tasks.tsx delete mode 100644 src/screens/UserPortal/UserLoginPage/UserLoginPage.module.css delete mode 100644 src/screens/UserPortal/UserLoginPage/UserLoginPage.tsx create mode 100644 src/screens/UserPortal/UserScreen/UserScreen.module.css create mode 100644 src/screens/UserPortal/UserScreen/UserScreen.test.tsx create mode 100644 src/screens/UserPortal/UserScreen/UserScreen.tsx create mode 100644 src/setup/askForCustomPort/askForCustomPort.test.ts create mode 100644 src/setup/askForCustomPort/askForCustomPort.ts create mode 100644 src/setup/askForTalawaApiUrl/askForTalawaApiUrl.test.ts create mode 100644 src/setup/askForTalawaApiUrl/askForTalawaApiUrl.ts create mode 100644 src/setup/checkConnection/checkConnection.test.ts create mode 100644 src/setup/checkConnection/checkConnection.ts create mode 100644 src/setup/checkEnvFile/checkEnvFile.test.ts create mode 100644 src/setup/checkEnvFile/checkEnvFile.ts create mode 100644 src/setup/validateRecaptcha/validateRecaptcha.test.ts create mode 100644 src/setup/validateRecaptcha/validateRecaptcha.ts create mode 100644 src/state/reducers/userRoutersReducer.test.ts create mode 100644 src/state/reducers/userRoutesReducer.ts create mode 100644 src/utils/currency.ts delete mode 100644 src/utils/debounce.ts create mode 100644 src/utils/fieldTypes.ts create mode 100644 src/utils/formEnumFields.ts create mode 100644 src/utils/linkValid.test.tsx create mode 100644 src/utils/linkValidator.ts create mode 100644 src/utils/recurrenceUtils/index.ts create mode 100644 src/utils/recurrenceUtils/recurrenceConstants.ts create mode 100644 src/utils/recurrenceUtils/recurrenceTypes.ts create mode 100644 src/utils/recurrenceUtils/recurrenceUtilityFunctions.ts create mode 100644 src/utils/useLocalstorage.test.ts create mode 100644 src/utils/useLocalstorage.ts create mode 100644 talawa-admin-docs/Dockerfile create mode 100644 talawa-admin-docs/enums/components_EventCalendar_EventCalendar.ViewType.md create mode 100644 talawa-admin-docs/interfaces/components_LeftDrawerEvent_LeftDrawerEvent.InterfaceLeftDrawerProps.md create mode 100644 talawa-admin-docs/interfaces/components_LeftDrawerEvent_LeftDrawerEventWrapper.InterfacePropType.md create mode 100644 talawa-admin-docs/interfaces/components_OrgProfileFieldSettings_OrgProfileFieldSettings.InterfaceCustomFieldData.md create mode 100644 talawa-admin-docs/interfaces/components_OrganizationDashCards_CardItem.InterfaceCardItem.md create mode 100644 talawa-admin-docs/interfaces/components_TableLoader_TableLoader.InterfaceTableLoader.md delete mode 100644 talawa-admin-docs/modules/components_AddOn_AddOn.default.md delete mode 100644 talawa-admin-docs/modules/components_AddOn_core_AddOnEntry_AddOnEntry.default.md create mode 100644 talawa-admin-docs/modules/components_AddOn_core_AddOnEntry_AddOnEntryMocks.md delete mode 100644 talawa-admin-docs/modules/components_AddOn_core_AddOnRegister_AddOnRegister.default.md delete mode 100644 talawa-admin-docs/modules/components_AddOn_core_AddOnStore_AddOnStore.default.md create mode 100644 talawa-admin-docs/modules/components_Advertisements_Advertisements.md create mode 100644 talawa-admin-docs/modules/components_Advertisements_Advertisements_test.md create mode 100644 talawa-admin-docs/modules/components_Advertisements_core_AdvertisementEntry_AdvertisementEntry.md create mode 100644 talawa-admin-docs/modules/components_Advertisements_core_AdvertisementEntry_AdvertisementEntry_test.md create mode 100644 talawa-admin-docs/modules/components_Advertisements_core_AdvertisementRegister_AdvertisementRegister.md create mode 100644 talawa-admin-docs/modules/components_Advertisements_core_AdvertisementRegister_AdvertisementRegister_test.md create mode 100644 talawa-admin-docs/modules/components_CurrentHourIndicator_CurrentHourIndicator.md create mode 100644 talawa-admin-docs/modules/components_CurrentHourIndicator_CurrentHourIndicator_test.md create mode 100644 talawa-admin-docs/modules/components_DeleteOrg_DeleteOrg.md create mode 100644 talawa-admin-docs/modules/components_DeleteOrg_DeleteOrg_test.md create mode 100644 talawa-admin-docs/modules/components_EditCustomFieldDropDown_EditCustomFieldDropDown.md create mode 100644 talawa-admin-docs/modules/components_EditCustomFieldDropDown_EditCustomFieldDropDown_test.md delete mode 100644 talawa-admin-docs/modules/components_EventProjectModals_AddEventProjectModal.md delete mode 100644 talawa-admin-docs/modules/components_EventProjectModals_AddEventProjectModal_test.md delete mode 100644 talawa-admin-docs/modules/components_EventProjectModals_DeleteEventProjectModal.md delete mode 100644 talawa-admin-docs/modules/components_EventProjectModals_DeleteEventProjectModal_test.md delete mode 100644 talawa-admin-docs/modules/components_EventProjectModals_UpdateEventProjectModal.md delete mode 100644 talawa-admin-docs/modules/components_EventProjectModals_UpdateEventProjectModal_test.md create mode 100644 talawa-admin-docs/modules/components_EventStats_EventStats.md create mode 100644 talawa-admin-docs/modules/components_EventStats_EventStatsWrapper.md create mode 100644 talawa-admin-docs/modules/components_EventStats_EventStatsWrapper_test.md create mode 100644 talawa-admin-docs/modules/components_EventStats_EventStats_test.md create mode 100644 talawa-admin-docs/modules/components_EventStats_Statistics_AverageRating.md create mode 100644 talawa-admin-docs/modules/components_EventStats_Statistics_AverageRating_test.md create mode 100644 talawa-admin-docs/modules/components_EventStats_Statistics_Feedback.md create mode 100644 talawa-admin-docs/modules/components_EventStats_Statistics_Feedback_test.md create mode 100644 talawa-admin-docs/modules/components_EventStats_Statistics_Review.md create mode 100644 talawa-admin-docs/modules/components_EventStats_Statistics_Review_test.md delete mode 100644 talawa-admin-docs/modules/components_LandingPage_LandingPage.md delete mode 100644 talawa-admin-docs/modules/components_LandingPage_LandingPage_test.md create mode 100644 talawa-admin-docs/modules/components_LeftDrawerEvent_LeftDrawerEvent.md create mode 100644 talawa-admin-docs/modules/components_LeftDrawerEvent_LeftDrawerEventWrapper.md create mode 100644 talawa-admin-docs/modules/components_LeftDrawerEvent_LeftDrawerEventWrapper_test.md create mode 100644 talawa-admin-docs/modules/components_LeftDrawerEvent_LeftDrawerEvent_test.md create mode 100644 talawa-admin-docs/modules/components_LoginPortalToggle_LoginPortalToggle.md create mode 100644 talawa-admin-docs/modules/components_LoginPortalToggle_LoginPortalToggle_test.md create mode 100644 talawa-admin-docs/modules/components_OrgProfileFieldSettings_OrgProfileFieldSettings.md create mode 100644 talawa-admin-docs/modules/components_OrgProfileFieldSettings_OrgProfileFieldSettings_test.md create mode 100644 talawa-admin-docs/modules/components_OrgUpdate_OrgUpdateMocks.md create mode 100644 talawa-admin-docs/modules/components_OrganizationDashCards_CardItem.md create mode 100644 talawa-admin-docs/modules/components_OrganizationDashCards_CardItemLoading.md create mode 100644 talawa-admin-docs/modules/components_OrganizationDashCards_CardItem_test.md create mode 100644 talawa-admin-docs/modules/components_OrganizationDashCards_DashboardCard.md create mode 100644 talawa-admin-docs/modules/components_OrganizationDashCards_DashboardCardLoading.md create mode 100644 talawa-admin-docs/modules/components_OrganizationDashCards_DashboardCard_test.md delete mode 100644 talawa-admin-docs/modules/components_TaskListItem_TaskListItem.md delete mode 100644 talawa-admin-docs/modules/components_TaskListItem_TaskListItem_test.md delete mode 100644 talawa-admin-docs/modules/components_TaskModals_AddTaskModal.md delete mode 100644 talawa-admin-docs/modules/components_TaskModals_AddTaskModal_test.md delete mode 100644 talawa-admin-docs/modules/components_TaskModals_DeleteTaskModal.md delete mode 100644 talawa-admin-docs/modules/components_TaskModals_DeleteTaskModal_test.md delete mode 100644 talawa-admin-docs/modules/components_TaskModals_ManageVolunteerModal.md delete mode 100644 talawa-admin-docs/modules/components_TaskModals_ManageVolunteerModal_test.md delete mode 100644 talawa-admin-docs/modules/components_TaskModals_UpdateTaskModal.md delete mode 100644 talawa-admin-docs/modules/components_TaskModals_UpdateTaskModal_test.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_ChatRoom_ChatRoom.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_ChatRoom_ChatRoom_test.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_CommentCard_CommentCard.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_CommentCard_CommentCard_test.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_ContactCard_ContactCard.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_ContactCard_ContactCard_test.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_EventCard_EventCard.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_EventCard_EventCard_test.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_PromotedPost_PromotedPost.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_PromotedPost_PromotedPost_test.md create mode 100644 talawa-admin-docs/modules/components_UserPortal_SecuredRouteForUser_SecuredRouteForUser_test.md create mode 100644 talawa-admin-docs/modules/components_UsersTableItem_UserTableItemMocks.md create mode 100644 talawa-admin-docs/modules/components_UsersTableItem_UserTableItem_test.md create mode 100644 talawa-admin-docs/modules/components_UsersTableItem_UsersTableItem.md delete mode 100644 talawa-admin-docs/modules/components_plugins_DummyPlugin2_DummyPlugin2.default.md delete mode 100644 talawa-admin-docs/modules/components_plugins_DummyPlugin_DummyPlugin.default.md create mode 100644 talawa-admin-docs/modules/screens_OrgList_OrganizationModal.md delete mode 100644 talawa-admin-docs/modules/screens_Requests_Requests.md delete mode 100644 talawa-admin-docs/modules/screens_Requests_Requests_test.md create mode 100644 talawa-admin-docs/modules/screens_UserPortal_Chat_Chat.md create mode 100644 talawa-admin-docs/modules/screens_UserPortal_Chat_Chat_test.md create mode 100644 talawa-admin-docs/modules/screens_UserPortal_Events_Events.md create mode 100644 talawa-admin-docs/modules/screens_UserPortal_Events_Events_test.md create mode 100644 talawa-admin-docs/modules/screens_Users_UsersMocks.md diff --git a/.env.example b/.env.example index bd9529ea79..399d5e6aab 100644 --- a/.env.example +++ b/.env.example @@ -2,6 +2,10 @@ # file to .env or set the variables in your local environment manually. +# Custom port number for the talawa-admin development server to run on. Default is 4321. + +PORT=4321 + # Run Talawa-api locally in your system, and put its url into the same. REACT_APP_TALAWA_URL= @@ -20,4 +24,8 @@ REACT_APP_USE_RECAPTCHA= REACT_APP_RECAPTCHA_SITE_KEY= # has to be inserted in the env file to use plugins and other websocket based features. -REACT_APP_BACKEND_WEBSOCKET_URL=ws://localhost:4000/graphql \ No newline at end of file +REACT_APP_BACKEND_WEBSOCKET_URL=ws://localhost:4000/graphql + +# If you want to logs Compiletime and Runtime error , warning and info write YES or if u want to +# keep the console clean leave it blank +ALLOW_LOGS= \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json index dfb93ff263..ee118a5a58 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -11,7 +11,9 @@ "eslint:recommended", "plugin:jest/recommended", "plugin:prettier/recommended", - "plugin:@typescript-eslint/recommended" + "plugin:@typescript-eslint/recommended", + "eslint-config-prettier", + "prettier" ], "globals": { "Atomics": "readonly", @@ -27,11 +29,17 @@ }, // Specify the ESLint plugins tobe used - "plugins": ["react", "@typescript-eslint", "jest"], + "plugins": [ + "react", + "@typescript-eslint", + "jest", + "import", + "eslint-plugin-tsdoc", + "prettier" + ], "rules": { - "react/destructuring-assignment": ["off"], - "@typescript-eslint/no-explicit-any": ["off"], - "@typescript-eslint/explicit-module-boundary-types": ["off"], + "react/destructuring-assignment": "error", + "@typescript-eslint/explicit-module-boundary-types": "error", "react/no-multi-comp": [ "error", { @@ -44,6 +52,14 @@ "extensions": [".tsx"] } ], + "import/no-duplicates": "error", + "tsdoc/syntax": "error", + "@typescript-eslint/ban-ts-comment": "error", + "@typescript-eslint/no-explicit-any": "error", + "@typescript-eslint/no-inferrable-types": "error", + "@typescript-eslint/no-non-null-asserted-optional-chain": "error", + "@typescript-eslint/no-non-null-assertion": "error", + "@typescript-eslint/no-var-requires": "error", "@typescript-eslint/ban-types": "error", "@typescript-eslint/no-duplicate-enum-values": "error", "@typescript-eslint/array-type": "error", @@ -56,6 +72,7 @@ "allowTypedFunctionExpressions": true } ], + "camelcase": "off", "@typescript-eslint/naming-convention": [ "error", // Interfaces must begin with Interface or TestInterface followed by a PascalCase name @@ -76,7 +93,7 @@ }, { "selector": "variable", - "format": ["camelCase", "UPPER_CASE"], + "format": ["camelCase", "UPPER_CASE", "PascalCase"], "leadingUnderscore": "allow" }, { @@ -86,7 +103,7 @@ }, { "selector": "function", - "format": ["camelCase"] + "format": ["camelCase", "PascalCase"] }, { "selector": "memberLike", @@ -95,7 +112,11 @@ "leadingUnderscore": "require" }, - { "selector": "variable", "modifiers": ["exported"], "format": null } + { + "selector": "variable", + "modifiers": ["exported"], + "format": null + } ], // Ensures that components are always written in PascalCase "react/jsx-pascal-case": [ @@ -110,23 +131,13 @@ // All tests must need not have an assertion "jest/expect-expect": 0, - // Ensures that components are always indented by 2 spaces - "react/jsx-indent": ["warn", 2], - "react/jsx-tag-spacing": [ - "warn", - { - "afterOpening": "never", - "beforeClosing": "never", - "beforeSelfClosing": "always" - } - ], - // Enforce Strictly functional components "react/no-unstable-nested-components": ["error", { "allowAsProps": true }], "react/function-component-definition": [ 0, { "namedComponents": "function-declaration" } - ] + ], + "prettier/prettier": "error" }, // Let ESLint use the react version in the package.json diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml new file mode 100644 index 0000000000..2fc49726ff --- /dev/null +++ b/.github/dependabot.yaml @@ -0,0 +1,18 @@ +# Configuration for automated dependency updates using Dependabot +version: 2 +updates: + # Define the target package ecosystem + - package-ecosystem: "npm" + # Specify the root directory + directory: "/" + # Schedule automated updates to run weekly + schedule: + interval: "weekly" + # Labels to apply to Dependabot PRs + labels: + - "dependencies" + # Specify the target branch for PRs + target-branch: "develop" + # Customize commit message prefix + commit-message: + prefix: "chore(deps):" \ No newline at end of file diff --git a/.github/workflows/authorized-changes-detection.yml b/.github/workflows/authorized-changes-detection.yml deleted file mode 100644 index 125c474fc4..0000000000 --- a/.github/workflows/authorized-changes-detection.yml +++ /dev/null @@ -1,34 +0,0 @@ -############################################################################## -############################################################################## -# -# NOTE! -# -# Please read the README.md file in this directory that defines what should -# be placed in this file -# -############################################################################## -############################################################################## - -name: Checking workflow files -on: - pull_request: - paths: - - '.github/**' - - 'env.example' - - '.husky/**' - - 'package.json' - - 'tsconfig.json' - - '.gitignore' - - '.eslintrc.json' - - '.eslintignore ' - - 'vite.config.ts' - - 'CODEOWNERS' - - 'LICENSE' - -jobs: - Checking-for-unauthorized-file-changes: - name: Checking for unauthorized file changes - runs-on: ubuntu-latest - steps: - - name: Unauthorized file modification in PR - run: exit 1 diff --git a/.github/workflows/codeql-codescan.yml b/.github/workflows/codeql-codescan.yml index a5cc559e65..e9eb5c5d49 100644 --- a/.github/workflows/codeql-codescan.yml +++ b/.github/workflows/codeql-codescan.yml @@ -28,7 +28,7 @@ jobs: language: [ 'javascript' ] steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Initialize CodeQL uses: github/codeql-action/init@v2 diff --git a/.github/workflows/compare_translations.py b/.github/workflows/compare_translations.py new file mode 100644 index 0000000000..f6f22e843c --- /dev/null +++ b/.github/workflows/compare_translations.py @@ -0,0 +1,170 @@ +"""Script to encourage more efficient coding practices. +Methodology: + + Utility for comparing translations between default and other languages. + + This module defines a function to compare two translations + and print any missing keys in the other language's translation. +Attributes: + + FileTranslation : Named tuple to represent a combination + of file and missing translations. + + Fields: + - file (str): The file name. + - missing_translations (list): List of missing translations. + +Functions: + compare_translations(default_translation, other_translation): + Compare two translations and print missing keys. + + load_translation(filepath): + Load translation from a file. + + check_translations(): + Load the default translation and compare it with other translations. + + main(): + The main function to run the script. + Parses command-line arguments, checks for the + existence of the specified directory, and then + calls check_translations with the provided or default directory. + + +Usage: + This script can be executed to check and print missing + translations in other languages based on the default English translation. + +Example: + python compare_translations.py +NOTE: + This script complies with our python3 coding and documentation standards + and should be used as a reference guide. It complies with: + + 1) Pylint + 2) Pydocstyle + 3) Pycodestyle + 4) Flake8 + +""" +# standard imports +import argparse +import json +import os +import sys +from collections import namedtuple + +# Named tuple for file and missing +# translations combination +FileTranslation = namedtuple("FileTranslation", + ["file", "missing_translations"]) + + +def compare_translations(default_translation, + other_translation, default_file, other_file): + """Compare two translations and return detailed info about missing/mismatched keys. + + Args: + default_translation (dict): The default translation (en.json). + other_translation (dict): The other language translation. + default_file (str): The name of the default translation file. + other_file (str): The name of the other + translation file. + + Returns: + list: A list of detailed error messages for each missing/mismatched key. + """ + errors = [] + + # Check for missing keys in other_translation + for key in default_translation: + if key not in other_translation: + error_msg = f"Missing Key: '{key}' - This key from '{default_file}' is missing in '{other_file}'." + errors.append(error_msg) + # Check for keys in other_translation that don't match any in default_translation + for key in other_translation: + if key not in default_translation: + error_msg = f"Error Key: '{key}' - This key in '{other_file}' does not match any key in '{default_file}'." + errors.append(error_msg) + return errors + + +def load_translation(filepath): + """Load translation from a file. + + Args: + filepath: Path to the translation file + + Returns: + translation: Loaded translation + """ + with open(filepath, "r", encoding="utf-8") as file: + translation = json.load(file) + return translation + + +def check_translations(directory): + """Load default translation and compare with other translations. + + Args: + directory (str): The directory containing translation files. + + Returns: + None + """ + default_file = "en.json" + default_translation = load_translation(os.path.join(directory, default_file)) + translations = os.listdir(directory) + translations.remove(default_file) # Exclude default translation + + error_found = False + + for translation_file in translations: + other_file = os.path.join(directory, translation_file) + other_translation = load_translation(other_file) + + # Compare translations and get detailed error messages + errors = compare_translations( + default_translation, other_translation, default_file, translation_file + ) + if errors: + error_found = True + print(f"File {translation_file} has missing translations for:") + for error in errors: + print(f" - {error}") + + if error_found: + sys.exit(1) # Exit with an error status code + else: + print("All translations are present") + sys.exit(0) + + +def main(): + """ + + Parse command-line arguments, check for the existence of the specified directory + and call check_translations with the provided or default directory. + + """ + parser = argparse.ArgumentParser( + description="Check and print missing translations for all non-default languages." + ) + parser.add_argument( + "--directory", + type=str, + nargs="?", + default=os.path.join(os.getcwd(), "public/locales"), + help="Directory containing translation files(relative to the root directory).", + ) + args = parser.parse_args() + + if not os.path.exists(args.directory): + print(f"Error: The specified directory '{args.directory}' does not exist.") + sys.exit(1) + + check_translations(args.directory) + + +if __name__ == "__main__": + main() diff --git a/.github/workflows/eslint_disable_check.py b/.github/workflows/eslint_disable_check.py new file mode 100644 index 0000000000..1efa49feb4 --- /dev/null +++ b/.github/workflows/eslint_disable_check.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- +"""ESLint Checker Script. + +Methodology: + + Recursively analyzes TypeScript files in the 'src' directory and its subdirectories + as well as 'setup.ts' files to ensure they do not contain eslint-disable statements. + + This script enforces code quality practices in the project. + +NOTE: + + This script complies with our python3 coding and documentation standards. + It complies with: + + 1) Pylint + 2) Pydocstyle + 3) Pycodestyle + 4) Flake8 + +""" + +import os +import re +import argparse +import sys + +def has_eslint_disable(file_path): + """ + Check if a TypeScript file contains eslint-disable statements. + + Args: + file_path (str): Path to the TypeScript file. + + Returns: + bool: True if eslint-disable statement is found, False otherwise. + """ + with open(file_path, 'r') as file: + content = file.read() + return re.search(r'//\s*eslint-disable', content) + +def check_eslint(directory): + """ + Recursively check TypeScript files for eslint-disable statements in the 'src' directory. + + Args: + directory (str): Path to the directory. + + Returns: + bool: True if eslint-disable statement is found, False otherwise. + """ + eslint_found = False + + for root, dirs, files in os.walk(os.path.join(directory, 'src')): + for file_name in files: + if file_name.endswith('.tsx') and not file_name.endswith('.test.tsx'): + file_path = os.path.join(root, file_name) + if has_eslint_disable(file_path): + print(f'File {file_path} contains eslint-disable statement.') + eslint_found = True + + setup_path = os.path.join(directory, 'setup.ts') + if os.path.exists(setup_path) and has_eslint_disable(setup_path): + print(f'Setup file {setup_path} contains eslint-disable statement.') + eslint_found = True + + return eslint_found + +def arg_parser_resolver(): + """Resolve the CLI arguments provided by the user. + + Returns: + result: Parsed argument object + + """ + parser = argparse.ArgumentParser() + parser.add_argument( + "--directory", + type=str, + default=os.getcwd(), + help="Path to the directory to check (default: current directory)" + ) + return parser.parse_args() + +def main(): + """ + Execute the script's main functionality. + + This function serves as the entry point for the script. It performs + the following tasks: + 1. Validates and retrieves the directory to check from + command line arguments. + 2. Recursively checks TypeScript files for eslint-disable statements. + 3. Provides informative messages based on the analysis. + 4. Exits with an error if eslint-disable statements are found. + + Raises: + SystemExit: If an error occurs during execution. + """ + + args = arg_parser_resolver() + + if not os.path.exists(args.directory): + print(f"Error: The specified directory '{args.directory}' does not exist.") + sys.exit(1) + + # Check eslint in the specified directory + eslint_found = check_eslint(args.directory) + + if eslint_found: + print("ESLint-disable check failed. Exiting with error.") + sys.exit(1) + + print("ESLint-disable check completed successfully.") + +if __name__ == "__main__": + main() diff --git a/.github/workflows/md_mdx_format_adjuster.py b/.github/workflows/md_mdx_format_adjuster.py new file mode 100644 index 0000000000..c33ad1fa66 --- /dev/null +++ b/.github/workflows/md_mdx_format_adjuster.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- +""" +Script to make Markdown files MDX compatible. + +This script scans Markdown files and escapes special characters (<, >, {, }) +to make them compatible with the MDX standard used in Docusaurus v3. + +This script complies with: + 1) Pylint + 2) Pydocstyle + 3) Pycodestyle + 4) Flake8 +""" + +import os +import argparse +import re + +def escape_mdx_characters(text): + """ + Escape special characters in a text string for MDX compatibility. + Avoids escaping already escaped characters. + + Args: + text: A string containing the text to be processed. + + Returns: + A string with special characters (<, >, {, }) escaped, avoiding + double escaping. + """ + # Regular expressions to find unescaped special characters + patterns = { + "<": r"(?": r"(?", + "{": r"(? 100 + env: + CHANGED_FILES_COUNT: ${{ steps.changed-files.outputs.all_changed_files_count }} + run: | + echo "Error: Too many files (greater than 100) changed in the pull request." + echo "Possible issues:" + echo "- Contributor may be merging into an incorrect branch." + echo "- Source branch may be incorrect please use develop as source branch." + exit 1 + + Check-ESlint-Disable: + name: Check for eslint-disable + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: 3.9 + + - name: Run Python script + run: | + python .github/workflows/eslint_disable_check.py + + Test-Application: + name: Test Application + runs-on: ubuntu-latest + needs: [Code-Quality-Checks, Check-ESlint-Disable] + steps: + - name: Checkout the Repository + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '20.x' + + - name: Install Dependencies + run: npm install + + - name: Get changed TypeScript files + id: changed-files + uses: tj-actions/changed-files@v40 + + - name: Run tests + if: steps.changed-files.outputs.only_changed != 'true' + run: npm run test -- --watchAll=false --coverage + + - name: TypeScript compilation for changed files + run: | + for file in ${{ steps.changed-files.outputs.all_files }}; do + if [[ "$file" == *.ts || "$file" == *.tsx ]]; then + npx tsc --noEmit "$file" + fi + done + + - name: Present and Upload coverage to Codecov as ${{env.CODECOV_UNIQUE_NAME}} + uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + verbose: true + fail_ci_if_error: false + name: '${{env.CODECOV_UNIQUE_NAME}}' + + - name: Test acceptable level of code coverage + uses: VeryGoodOpenSource/very_good_coverage@v2 + with: + path: "./coverage/lcov.info" + min_coverage: 95.0 + + Graphql-Inspector: + name: Runs Introspection on the GitHub talawa-api repo on the schema.graphql file + runs-on: ubuntu-latest + steps: + - name: Checkout the Repository + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '20.x' + + - name: resolve dependency + run: npm install -g @graphql-inspector/cli + + - name: Clone API Repository + run: | + # Retrieve the complete branch name directly from the GitHub context + FULL_BRANCH_NAME=${{ github.base_ref }} + echo "FULL_Branch_NAME: $FULL_BRANCH_NAME" + + # Clone the specified repository using the extracted branch name + git clone --branch $FULL_BRANCH_NAME https://github.com/PalisadoesFoundation/talawa-api && ls -a + + - name: Validate Documents + run: graphql-inspector validate './src/GraphQl/**/*.ts' './talawa-api/schema.graphql' + + Check-Target-Branch: + name: Check Target Branch + runs-on: ubuntu-latest + steps: + - name: Check if the target branch is develop + if: github.event.pull_request.base.ref != 'develop' + run: | + echo "Error: Pull request target branch must be 'develop'. Please refer PR_GUIDELINES.md" + exit 1 + diff --git a/.github/workflows/pull-requests.yml b/.github/workflows/pull-requests.yml deleted file mode 100644 index 75f6dbda36..0000000000 --- a/.github/workflows/pull-requests.yml +++ /dev/null @@ -1,93 +0,0 @@ -############################################################################## -############################################################################## -# -# NOTE! -# -# Please read the README.md file in this directory that defines what should -# be placed in this file -# -############################################################################## -############################################################################## - -name: PR Workflow -on: - pull_request: - branches: - - '**' - -env: - CODECOV_UNIQUE_NAME: CODECOV_UNIQUE_NAME-${{ github.run_id }}-${{ github.run_number }} - -jobs: - - Continuous-Integration: - - name: Performs linting, formatting, type-checking and testing on the application - runs-on: ubuntu-latest - steps: - - name: Checkout the Repository - uses: actions/checkout@v3 - - - name: Install Dependencies - run: npm install --legacy-peer-deps - - - name: Run linting check - run: npm run lint:check - - - name: Count number of lines - run: | - chmod +x ./.github/workflows/countline.py - ./.github/workflows/countline.py --lines 1000 --exclude_files src/screens/LoginPage/LoginPage.tsx - - - name: Check formatting - run: npm run format:check - - - name: Check for type errors - run: npm run typecheck - - - name: Run tests - run: npm run test -- --watchAll=false --coverage - - - name: Present and Upload coverage to Codecov as ${{env.CODECOV_UNIQUE_NAME}} - uses: codecov/codecov-action@v3 - with: - verbose: true - fail_ci_if_error: false - name: '${{env.CODECOV_UNIQUE_NAME}}' - - - name: Test acceptable level of code coverage - uses: VeryGoodOpenSource/very_good_coverage@v2 - with: - path: "./coverage/lcov.info" - min_coverage: 95.0 - - Graphql-Inspector: - name: Runs Introspection on the github talawa-api repo on the schema.graphql file - runs-on: ubuntu-latest - steps: - - name: Checkout the Repository - uses: actions/checkout@v3 - - - name: Set up Node.js - uses: actions/setup-node@v3 - with: - node-version: '16.14.1' - - - name: resolve dependency - run: npm install -g @graphql-inspector/cli - - - name: Clone API repository - run: git clone https://github.com/PalisadoesFoundation/talawa-api && ls -a - - - name: Validate Documents - run: graphql-inspector validate './src/GraphQl/**/*.ts' './talawa-api/schema.graphql' - - Branch-check: - name: "Base branch check" - runs-on: ubuntu-latest - steps: - - name: "Check if base branch is develop" - if: github.event.pull_request.base.ref != 'develop' - run: | - echo "PR is not against develop branch. Please refer PR_GUIDELINES.md" - exit 1 diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 2169009ec0..0542490787 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -19,32 +19,79 @@ on: env: CODECOV_UNIQUE_NAME: CODECOV_UNIQUE_NAME-${{ github.run_id }}-${{ github.run_number }} -jobs: +jobs: Code-Coverage: runs-on: ubuntu-latest + strategy: + matrix: + node-version: [20.x] steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} - - run: npm install --legacy-peer-deps + + - name: Cache node modules + id: cache-npm + uses: actions/cache@v4 + env: + cache-name: cache-node-modules + with: + path: | + ~/.npm + node_modules + key: ${{ runner.os }}-code-coverage-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-code-coverage-${{ env.cache-name }}- + ${{ runner.os }}-code-coverage- + ${{ runner.os }}- + + - if: ${{ steps.cache-npm.outputs.cache-hit != 'true' }} + name: List the state of node modules + run: npm install - run: npm run test -- --watchAll=false --coverage - name: Present and upload coverage to Codecov as ${{env.CODECOV_UNIQUE_NAME}} - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 with: + token: ${{ secrets.CODECOV_TOKEN }} verbose: true fail_ci_if_error: false name: '${{env.CODECOV_UNIQUE_NAME}}' Generate-Documentation: runs-on: ubuntu-latest - if: github.ref == 'refs/heads/automated-docs' + if: github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/automated-docs' steps: - name: Checkout the Repository - uses: actions/checkout@v3 - - - name: Install Dependencies - run: yarn install --legacy-peer-deps + uses: actions/checkout@v4 + # with: + # ref: develop + + # - name: Pull latest changes from develop + # run: git pull origin develop + + - name: Node.js Version + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Restore node_modules from cache + id: cache-npm + uses: actions/cache@v4 + env: + cache-name: cache-node-modules + with: + path: | + ~/.npm + node_modules + key: ${{ runner.os }}-generate-docs-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-generate-docs-${{ env.cache-name }}- + ${{ runner.os }}-generate-docs- + ${{ runner.os }}- + + - name: Install dependencies + run: npm install - name: Install TypeScript Globally and add GraphQL tag run: yarn global add typescript @@ -55,9 +102,14 @@ jobs: - name: Generate Documentation of Markdown pages run: | - yarn global add typedoc - yarn add typedoc-plugin-markdown - yarn typedoc --entryPoints src/components src/screens --out talawa-admin-docs --plugin typedoc-plugin-markdown --theme markdown --entryPointStrategy expand --exclude "**/*.test.ts" --exclude "**/*.css" + npm install --global typedoc + npm install typedoc-plugin-markdown + npm install --save-dev @types/node + npx typedoc --entryPoints src/components src/screens --out talawa-admin-docs --plugin typedoc-plugin-markdown --theme markdown --entryPointStrategy expand --exclude "**/*.test.ts" --exclude "**/*.css" + + - name: Make Markdown Files MDX Compatible + run: python ./.github/workflows/md_mdx_format_adjuster.py --directory talawa-admin-docs + - name: Checking doc updated id: DocUpdated @@ -86,7 +138,7 @@ jobs: git config --global user.email "${{env.email}}" git add . git commit -m "Update documentation" - git push + git push origin develop:automated-docs --force echo -e "🚀${Green} Hurrah! doc updated${NoColor}" - name: Create Documentation Artifact @@ -95,13 +147,34 @@ jobs: name: documentation-admin path: talawa-admin-docs + Empty-Commit: + name: Create Empty Commit + runs-on: ubuntu-latest + if: github.ref == 'refs/heads/develop' + needs: Generate-Documentation + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + persist-credentials: false + token: ${{ secrets.TALAWA_DOCS_SYNC }} + - name: Empty Commit + run: | + git config --global user.name "${{github.actor}}" + git config --global user.email "${{env.email}}" + git config --global url.https://${{ secrets.TALAWA_DOCS_SYNC }}@github.com/.insteadOf https://github.com/ + git commit --allow-empty -m "Trigger Documentation Workflow" + git push origin develop:automated-docs --force + Copy-docs-to-talawa-docs: + if: github.ref == 'refs/heads/automated-docs' + needs: Generate-Documentation runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dmnemec/copy_file_to_another_repo_action@v1.1.1 env: - API_TOKEN_GITHUB: ${{ secrets.TALAWA_DOCS_SYNC_NEW }} + API_TOKEN_GITHUB: ${{secrets.TALAWA_DOCS_SYNC}} with: source_file: 'talawa-admin-docs/' destination_repo: 'PalisadoesFoundation/talawa-docs' @@ -110,5 +183,3 @@ jobs: user_email: '${{env.email}}' user_name: '${{github.actor}}' commit_message: 'Talawa Admin docs updated' - - diff --git a/.gitignore b/.gitignore index ecd324f3b5..80c2b97cd9 100644 --- a/.gitignore +++ b/.gitignore @@ -31,4 +31,7 @@ yarn-error.log* # express setup debug.log -.vscode \ No newline at end of file +# No editor related files +.idea +.vscode +*.swp diff --git a/.husky/post-merge b/.husky/post-merge index aa3a3a123a..c7f42c373b 100755 --- a/.husky/post-merge +++ b/.husky/post-merge @@ -1,4 +1,4 @@ #!/bin/sh . "$(dirname "$0")/_/husky.sh" -git diff HEAD^ HEAD --exit-code -- ./package.json || npm install --legacy-peer-deps \ No newline at end of file +git diff HEAD^ HEAD --exit-code -- ./package.json || npm install \ No newline at end of file diff --git a/.husky/pre-commit b/.husky/pre-commit index e4debee2be..c9c109cceb 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,8 +1,10 @@ #!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" -npm run format:fix -npm run lint:fix +# npm run format:fix +# npm run lint:fix +npm run lint-staged npm run typecheck +npm run update:toc git add . diff --git a/.lintstagedrc.json b/.lintstagedrc.json new file mode 100644 index 0000000000..36195c0491 --- /dev/null +++ b/.lintstagedrc.json @@ -0,0 +1,5 @@ +{ + "**/*.{ts,tsx,yml}": "eslint --fix", + "**/*.{ts,tsx,json,scss,css,yml}": "prettier --write", + "**/*.{ts,tsx}": "node scripts/githooks/check-localstorage-usage.js" +} diff --git a/.node-version b/.node-version new file mode 100644 index 0000000000..790e1105f2 --- /dev/null +++ b/.node-version @@ -0,0 +1 @@ +v20.10.0 diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 4a38c46419..b82fab3779 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,5 +1,23 @@ # Contributor Covenant Code of Conduct +# Table of Contents + + + +- [Our Pledge](#our-pledge) +- [Our Standards](#our-standards) +- [Enforcement Responsibilities](#enforcement-responsibilities) +- [Scope](#scope) +- [Enforcement](#enforcement) +- [Enforcement Guidelines](#enforcement-guidelines) + - [1. Correction](#1-correction) + - [2. Warning](#2-warning) + - [3. Temporary Ban](#3-temporary-ban) + - [4. Permanent Ban](#4-permanent-ban) +- [Attribution](#attribution) + + + ## Our Pledge We as members, contributors, and leaders pledge to make participation in our diff --git a/CODE_STYLE.md b/CODE_STYLE.md index b93a8c0f57..df184b12a0 100644 --- a/CODE_STYLE.md +++ b/CODE_STYLE.md @@ -1,4 +1,3 @@ - # Talawa Admin Code Style For Talawa Admin, most of the rules for the code style have been enforced with ESLint, but this document serves to provide an overview of the Code style used in Talawa Admin and the Rationale behind it. @@ -7,6 +6,21 @@ The code style must be strictly adhered to, to ensure that there is consistency code style should not be changed and must be followed. +# Table of Contents + + + +- [Tech Stack](#tech-stack) +- [Component Structure](#component-structure) +- [Code Style and Naming Conventions](#code-style-and-naming-conventions) +- [Test and Code Linting](#test-and-code-linting) +- [Folder/Directory Structure](#folderdirectory-structure) + - [Sub Directories of `src`](#sub-directories-of-src) +- [Imports](#imports) +- [Customising Bootstrap](#customising-bootstrap) + + + ## Tech Stack - Typescript @@ -21,7 +35,7 @@ code style should not be changed and must be followed. - GraphQL -- Jest & Enzyme for testing +- Jest & React Testing Library for testing ## Component Structure @@ -175,7 +189,7 @@ Follow this [link](https://getbootstrap.com/docs/5.3/customize/sass/) to learn h **File Structure** -- `src/assets/scss/components/{partialFile}.scss` - where the {partialFile} are the following files +- `src/assets/scss/components/{'{partialFile}'}.scss` - where the {'{partialFile}'} are the following files - **_accordion.scss** - **_alert.scss** - **_badge.scss** @@ -195,12 +209,12 @@ Follow this [link](https://getbootstrap.com/docs/5.3/customize/sass/) to learn h - **_progress.scss** - **_spinners.scss** -- `src/assets/scss/content/{partialFile}.scss` - where the {partialFile} are the following files +- `src/assets/scss/content/{'{partialFile}'}.scss` - where the {'{partialFile}'} are the following files - **_table.scss** - **_typography.scss** -- `src/assets/scss/forms/{partialFile}.scss` - where the {partialFile} are the following files +- `src/assets/scss/forms/{'{partialFile}'}.scss` - where the {'{partialFile}'} are the following files - **_check-radios.scss** - **_floating-label.scss** - **_form-control.scss** @@ -223,11 +237,17 @@ The compiled CSS file is `src/assets/css/app.css` and it is imported into `src/i To compile the Sass file once, run the following command in the terminal ``` -node-sass src/assets/scss/app.scss src/assets/css/app.css +npx sass src/assets/scss/app.scss src/assets/css/app.css ``` To watch the Sass file for changes and compile it automatically, run the following command in the terminal ``` -node-sass src/assets/scss/app.scss src/assets/css/app.css --watch -``` \ No newline at end of file +npx sass src/assets/scss/app.scss src/assets/css/app.css --watch +``` +The `src/assets/css/app.css.map` file associates the generated CSS code with the original SCSS code. It allows you to see your SCSS code in the browser's developer tools for debugging. + +To skip generating the map file, run +``` +npx sass --no-source-map src/assets/scss/app.scss src/assets/css/app.css +``` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fd22174634..47fa8d6e69 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,18 +6,20 @@ If you are new to contributing to open source, please read the Open Source Guide ## Table of Contents -- [Contributing to Talawa-Admin](#contributing-to-talawa-admin) - - [Table of Contents](#table-of-contents) - - [Code of Conduct](#code-of-conduct) - - [Ways to Contribute](#ways-to-contribute) - - [Our Development Process](#our-development-process) - - [Issues](#issues) - - [Pull Requests](#pull-requests) - - [Branching Strategy](#branching-strategy) - - [Conflict Resolution](#conflict-resolution) - - [Contributing Code](#contributing-code) - - [Internships](#internships) - - [Community](#community) + + +- [Code of Conduct](#code-of-conduct) +- [Ways to Contribute](#ways-to-contribute) + - [Our Development Process](#our-development-process) + - [Issues](#issues) + - [Pull Requests](#pull-requests) + - [Branching Strategy](#branching-strategy) + - [Conflict Resolution](#conflict-resolution) + - [Contributing Code](#contributing-code) +- [Internships](#internships) +- [Community](#community) + + ## Code of Conduct @@ -67,8 +69,7 @@ When multiple developers are working on issues there is bound to be a conflict o - In the cases where you feel your potential issues could be an extension or in conflict with other PRs it is important to ask the author of the PR in the slack channel or in their PRs or issues themselves why he/she did not write code for something that would require minimal effort on their part. - Based on basic courtesy, it is good practice to let the person who created a function apply and test that function when needed. - Last but not the least, communication is important make sure to talk to other contributors, in these cases, in slack channel or in a issue/PR thread. -- As a last resort the Admins would be responsible for deciding how to resolve this conflict. - +- As a last resort the Admins would be responsible for deciding how to resolve this conflict. ### Contributing Code @@ -79,44 +80,47 @@ Make sure you have read the [Documentation for Setting up the Project](https://g The process of proposing a change to Talawa Admin can be summarized as: 1. Fork the Talawa Admin repository and branch off `develop`. -1. The repository can be cloned locally using `git clone `. +1. Your newly forked repository can be cloned locally using `git clone `. +1. Make the Palisadoes Foundation's repo your `git upstream` for your local repo. 1. Make the desired changes to the Talawa Admin project. 1. Run the app and test your changes. -1. If you've added code, then test suites must be added. - 1. **_General_:** +1. If you've added code, then test suites must be added. + + 1. **_General_:** + 1. We need to get to 100% test coverage for the app. We periodically increase the desired test coverage for our pull requests to meet this goal. 1. Pull requests that don't meet the minimum test coverage levels will not be accepted. This may mean that you will have to create tests for code you did not write. You can decide which part of the code base needs additional tests if this happens to you. - + 2. **_Testing_:** 1. Test using this set of commands: ``` - npm install --legacy-peer-deps + npm install npm run test --watchAll=false --coverage ``` - - 2. Debug tests in browser - + + 2. Debug tests in browser + You can see the output of failing tests in broswer by running `jest-preview` package before running your tests ``` - npm install --legacy-peer-deps + npm install npm run jest-preview npm run test --watchAll=false --coverage ``` - + You don't need to re-run the `npm run jest-preview` command each time, simply run the `npm run test` command if the Jest Preview server is already running in the background, it'll automatically detect any failing tests and show the preview at `http://localhost:3336` as shown in this screenshot - ![Debugging Test Demo](./public/images/jest-preview.webp) - 3. **_Test Code Coverage_:** + 1. _General Information_ 1. The current code coverage of the repo is: [![codecov](https://codecov.io/gh/PalisadoesFoundation/talawa-admin/branch/develop/graph/badge.svg?token=II0R0RREES)](https://codecov.io/gh/PalisadoesFoundation/talawa-admin) 2. You can determine the percentage test coverage of your code by running these two commands in sequence: ``` - npm install --legacy-peer-deps + npm install npm run test --watchAll=false --coverage genhtml coverage/lcov.info -o coverage ``` @@ -126,32 +130,43 @@ The process of proposing a change to Talawa Admin can be summarized as: 6. The currently acceptable coverage rate can be found in the [GitHub Pull Request file](.github/workflows/pull-requests.yml). Search for the value below the line containing `min_coverage`. 2. _Testing Individual Files_ 1. You can test an individual file by running this command: - ``` - npm run test --watchAll=false /path/to/test/file - ``` + ``` + npm run test --watchAll=false /path/to/test/file + ``` 2. You can get the test coverage report for that file by running this command. The report will list all tests in the suite. Those tests that are not run will have zero values. You will need to look for the output line relevant to your test file. - ``` - npm run test --watchAll=false --coverage /path/to/test/file - ``` + ``` + npm run test --watchAll=false --coverage /path/to/test/file + ``` 3. _Creating your code coverage account_ - 1. You can also see your code coverage online for your fork of the repo. This is provided by `codecov.io` - 1. Go to this link: `https://app.codecov.io/gh/XXXX/YYYY` where XXXX is your GitHub account username and YYYY is the name of the repository - 2. Login to `codecov.io` using your GitHub account, and add your **repo** and **branches** to the `codecov.io` dashboard. - 3. Remember to add the `Repository Upload Token` for your forked repo. This can be found under `Settings` of your `codecov.io` account. - 4. Use the value of this token to create a secret named CODE_COV for your forked repo. - 5. You will see your code coverage reports with every push to your repo after following these steps -2. After making changes you can add them to git locally using `git add `(to add changes only in a particular file) or `git add .` (to add all changes). -3. After adding the changes you need to commit them using `git commit -m ''`(look at the commit guidelines below for commit messages). -4. Once you have successfully commited your changes, you need to push the changes to the forked repo on github using: `git push origin `.(Here branch name must be name of the branch you want to push the changes to.) -5. Now create a pull request to the Talawa-admin repository from your forked repo. Open an issue regarding the same and link your PR to it. -6. Ensure the test suite passes, either locally or on CI once a PR has been created. -7. Review and address comments on your pull request if requested. + + 1. You can also see your code coverage online for your fork of the repo. This is provided by `codecov.io` + + 1. Go to this link: `https://app.codecov.io/gh/XXXX/YYYY` where XXXX is your GitHub account username and YYYY is the name of the repository + 2. Login to `codecov.io` using your GitHub account, and add your **repo** and **branches** to the `codecov.io` dashboard. + ![Debugging Test Demo](/public/images/codecov/authorise-codecov-github.jpg) + 3. Remember to add the `Repository Upload Token` for your forked repo. This can be found under `Settings` of your `codecov.io` account. + + 4. Click on Setup Repo option + ![Debugging Test Demo]() + 5. Use the value of this token to create a secret named CODE_COV for your forked repo. + [![Code-cov-token.jpg](/public/images/codecov/Code-cov-token.jpg)]() + [![addd-your-key.jpg](/public/images/codecov/addd-your-key.jpg)]() + 6. You will see your code coverage reports with every push to your repo after following these steps + [![results.jpg](/public/images/codecov/results.jpg)]() + +1. After making changes you can add them to git locally using `git add `(to add changes only in a particular file) or `git add .` (to add all changes). +1. After adding the changes you need to commit them using `git commit -m ''`(look at the commit guidelines below for commit messages). +1. Once you have successfully commited your changes, you need to push the changes to the forked repo on github using: `git push origin `.(Here branch name must be name of the branch you want to push the changes to.) +1. Now create a pull request to the Talawa-admin repository from your forked repo. Open an issue regarding the same and link your PR to it. +1. Ensure the test suite passes, either locally or on CI once a PR has been created. +1. Review and address comments on your pull request if requested. ## Internships If you are participating in any of the various internship programs we are members of, then please read the [introduction guides on our documentation website](https://docs.talawa.io/docs/). ## Community + There are many ways to communicate with the community. 1. The Palisadoes Foundation has a Slack channel where members can assist with support and clarification. Visit the [Talawa GitHub repository home page](https://github.com/PalisadoesFoundation/talawa) for the link to join our slack channel. diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md index aecf8cc132..7691b5d452 100644 --- a/DOCUMENTATION.md +++ b/DOCUMENTATION.md @@ -1,5 +1,16 @@ # Documentation Welcome to our documentation guide. Here are some useful tips you need to know! + +# Table of Contents + + + +- [Where to find our documentation](#where-to-find-our-documentation) +- [How to use Docusaurus](#how-to-use-docusaurus) +- [Other information](#other-information) + + + ## Where to find our documentation Our documentation can be found in ONLY TWO PLACES: diff --git a/INSTALLATION.md b/INSTALLATION.md index c0e87d601b..a07c2fa5b8 100644 --- a/INSTALLATION.md +++ b/INSTALLATION.md @@ -4,18 +4,20 @@ This document provides instructions on how to set up and start a running instanc # Table of Contents -- [Talawa-Admin Installation](#talawa-admin-installation) -- [Table of Contents](#table-of-contents) + + - [Prerequisites for Developers](#prerequisites-for-developers) - [Installation](#installation) - - [Clone This Repository](#clone-this-repository) - - [Change Directory into the Cloned Repo](#change-directory-into-the-cloned-repo) - - [Setting up NPM](#setting-up-npm) + - [Setting up this repository](#setting-up-this-repository) + - [Setting up npm](#setting-up-npm) + - [Setting up Typescript](#setting-up-typescript) - [Installing required packages/dependencies](#installing-required-packagesdependencies) - [Configuration](#configuration) - [Creating .env file](#creating-env-file) - - [Setting up REACT\_APP\_TALAWA\_URL in .env file](#setting-up-react_app_talawa_url-in-env-file) - - [Setting up REACT\_APP\_RECAPTCHA\_SITE\_KEY in .env file](#setting-up-react_app_recaptcha_site_key-in-env-file) + - [Setting up PORT in .env file](#setting-up-port-in-env-file) + - [Setting up REACT_APP_TALAWA_URL in .env file](#setting-up-react_app_talawa_url-in-env-file) + - [Setting up REACT_APP_RECAPTCHA_SITE_KEY in .env file](#setting-up-react_app_recaptcha_site_key-in-env-file) + - [Setting up Compiletime and Runtime logs](#setting-up-compiletime-and-runtime-logs) - [Post Configuration Steps](#post-configuration-steps) - [Running Talawa-Admin](#running-talawa-admin) - [Accessing Talawa-Admin](#accessing-talawa-admin) @@ -29,50 +31,80 @@ This document provides instructions on how to set up and start a running instanc - [pre-commit hook](#pre-commit-hook) - [post-merge hook](#post-merge-hook) + + # Prerequisites for Developers -We recommend that you follow these steps before beginning development work on Talawa-Admin: +We recommend that you to follow these steps before beginning development work on Talawa-Admin: +1. You need to have `nodejs` installed in your machine. We recommend using Node version greater than 20.0.0. You can install it either through [nvm](https://github.com/nvm-sh/nvm) (Node Version Manager) or by visiting the official [Nodejs](https://nodejs.org/download/release/v16.20.2/) website. 1. [Talawa-API](https://github.com/PalisadoesFoundation/talawa-api): (**This is mandatory**) The API system that the mobile app uses for accessing data. Setup your own **_local instance_** 1. [Talawa](https://github.com/PalisadoesFoundation/talawa): (Optional) The mobile app that people will use to access Talawa's features. This may be useful if you need to verify administrative features you have added or modified. The INSTALLATION.md files in both repositories show you how. The Talawa-API INSTALLATION.md will also show you the Organization URL to use access Talawa Admin. # Installation + You will need to have copies of your code on your local system. Here's how to do that. -## Clone This Repository + +## Setting up this repository First you need a local copy of `talawa-admin`. Run the following command in the directory of choice on your local system. +1. Navigate to the folder where you want to setup the repository. Here, I will set it up in a folder called `talawa`. +2. Navigate to the folder and open a terminal in this folder (you can right-click and choose appropiate option based onn your OS). Next, we'll fork and clone the `talawa-admin` repository. +3. Navigate to [https://github.com/PalisadoesFoundation/talawa-admin/](hhttps://github.com/PalisadoesFoundation/talawa-admin/) and click on the `fork` button. It is placed on the right corner opposite the repository name `PalisadoesFoundation/talawa-admin`. +4. You should now see `talawa-admin` under your repositories. It will be marked as forked from `PalisadoesFoundation/talawa-admin` +5. Clone the repository to your local computer (replacing the values in `{{}}`): + ``` -git clone https://github.com/PalisadoesFoundation/talawa-admin +$ git clone https://github.com/{{YOUR GITHUB USERNAME}}/talawa-admin.git ``` -This will download a local copy of `talawa-admin` in that directory. +This will setup the repository and the code files locally for you. For more detailed instructions on contributing code, and managing the versions of this repository with Git, checkout [CONTRIBUTING.md here](./CONTRIBUTING.md) -## Change Directory into the Cloned Repo +**NOTE:** `All the commands we're going to execute in the following instructions will assume you are in the root directory of the cloned talawa-admin project. If you fail to do so, the commands will not work.` -Right after cloning the repo you can change the directory of your current `terminal(shell)` to the root directory of cloned repository using this command: +## Setting up npm -``` -cd talawa-admin -``` +Best way to install and manage `node.js` is making use of node version managers. Two most popular node version managers right now are [fnm](https://github.com/Schniz/fnm) and [nvm](https://github.com/nvm-sh/nvm). We'd recommend `fnm` because it's written in `rust` and is much faster than `nvm`. Install whichever one you want and follow their guide to set up `node.js` on your system. -**NOTE:** `All the commands we're going to execute in the following instructions will assume you are in the root directory of the cloned talawa-admin project. If you fail to do so, the commands will not work.` +_**NOTE**_ + +1. The repository has a `.node-version` file to help ensure you use the supported version of `node.js`. Do not edit this file. +1. We strongly recommend that you configure your node version manager of choice to automatically read `.node-version` files -## Setting up NPM +## Setting up Typescript -If you've followed the previous steps you should have already set up node.js on your system. [Click here](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) for the official setup guide for npm. +As `talawa-admin` and `talawa-api` repositories are written using [Typescript](https://www.typescriptlang.org/), you will need to install typescript on your machine. +We recommend to install `Typescript` globally on your machine by running the following command in the terminal: + +``` +npm install -g typescript +``` + +For more details please refer to the installation guidelines provided in the [official docs](https://www.typescriptlang.org/download). ## Installing required packages/dependencies Run the following command to install the packages and dependencies required by `talawa-admin`: ``` -npm install --legacy-peer-deps +npm install ``` + # Configuration + It's important to configure Talawa-Admin. Here's how to do it. + +You can use our interactive setup script for the configuration. Use the following command for the same. + +``` +npm run setup +``` + +All the options in "setup" can be done manually as well and here's how to do it. - [Creating .env file](#creating-env-file) + ## Creating .env file A file named .env is required in the root directory of talawa-admin for storing environment variables used at runtime. It is not a part of the repo and you will have to create it. For a sample of `.env` file there is a file named `.env.example` in the root directory. Create a new `.env` file by copying the contents of the `.env.example` into `.env` file. Use this command: @@ -83,17 +115,22 @@ cp .env.example .env This `.env` file must be populated with the following environment variables for `talawa-admin` to work: -| Variable | Description | -| ---------------------------- | ------------------------------------------- | -| REACT_APP_TALAWA_URL | URL endpoint for talawa-api graphql service | -| REACT_APP_USE_RECAPTCHA | Whether you want to use reCAPTCHA or not | -| REACT_APP_RECAPTCHA_SITE_KEY | Site key for authentication using reCAPTCHA | +| Variable | Description | +| ---------------------------- | ------------------------------------------------- | +| PORT | Custom port for Talawa-Admin development purposes | +| REACT_APP_TALAWA_URL | URL endpoint for talawa-api graphql service | +| REACT_APP_USE_RECAPTCHA | Whether you want to use reCAPTCHA or not | +| REACT_APP_RECAPTCHA_SITE_KEY | Site key for authentication using reCAPTCHA | -Follow the instructions from section [Setting up REACT_APP_TALAWA_URL in .env file](#setting-up-REACT_APP_TALAWA_URL-in-env-file) up to and including section [Setting up REACT_APP_RECAPTCHA_SITE_KEY in .env file](#setting-up-REACT_APP_RECAPTCHA_SITE_KEY-in-env-file) to set up these environment variables. +Follow the instructions from the sections [Setting up PORT in .env file](#setting-up-port-in-env-file), [Setting up REACT_APP_TALAWA_URL in .env file](#setting-up-REACT_APP_TALAWA_URL-in-env-file), [Setting up REACT_APP_RECAPTCHA_SITE_KEY in .env file](#setting-up-REACT_APP_RECAPTCHA_SITE_KEY-in-env-file) and [Setting up Compiletime and Runtime logs](#setting-up-compiletime-and-runtime-logs) to set up these environment variables. + +## Setting up PORT in .env file + +Add a custom port number for Talawa-Admin development purposes to the variable named `PORT` in the `.env` file. ## Setting up REACT_APP_TALAWA_URL in .env file -Add the endpoint for accessing talawa-api graphql service to the variable named `REACT_APP_TALAWA_URL` in the `.env` file. +Add the endpoint for accessing talawa-api graphql service to the variable named `REACT_APP_TALAWA_URL` in the `.env` file. ``` REACT_APP_TALAWA_URL="http://API-IP-ADRESS:4000/graphql/" @@ -105,7 +142,13 @@ If you are a software developer working on your local system, then the URL would REACT_APP_TALAWA_URL="http://localhost:4000/graphql/" ``` -For additional details, please refer to to the `How to Access the Talawa-API URL` section in the INSTALLATION.md file found in the [Talawa-API repo](https://github.com/PalisadoesFoundation/talawa-api). +If you are trying to access Talawa Admin from a remote host with the API URL containing "localhost", You will have to change the API URL to + +``` +REACT_APP_TALAWA_URL="http://YOUR-REMOTE-ADDRESS:4000/graphql/" +``` + +For additional details, please refer the `How to Access the Talawa-API URL` section in the INSTALLATION.md file found in the [Talawa-API repo](https://github.com/PalisadoesFoundation/talawa-api). ## Setting up REACT_APP_RECAPTCHA_SITE_KEY in .env file @@ -113,7 +156,7 @@ You may not want to setup reCAPTCHA since the project will still work. Moreover, Just skip to the [Post Configuration Steps](#post-configuration-steps) if you don't want to set it up. Else, read the following steps. -If you want to setup Google reCAPTCHA now, you may refer to to the `RECAPTCHA` section in the INSTALLATION.md file found in [Talawa-API repo](https://github.com/PalisadoesFoundation/talawa-api). +If you want to setup Google reCAPTCHA now, you may refer to the `RECAPTCHA` section in the INSTALLATION.md file found in [Talawa-API repo](https://github.com/PalisadoesFoundation/talawa-api). `Talawa-admin` needs the `reCAPTCHA site key` for the `reCAPTCHA` service you set up during `talawa-api` installation as shown in this screenshot: @@ -125,7 +168,12 @@ Copy/paste this `reCAPTCHA site key` to the variable named `REACT_APP_RECAPTCHA_ REACT_APP_RECAPTCHA_SITE_KEY="this_is_the_recaptcha_key" ``` +## Setting up Compiletime and Runtime logs + +Set the `ALLOW_LOGS` to "YES" if you want warnings , info and error messages in your console or leave it blank if you dont need them or want to keep the console clean + # Post Configuration Steps + It's now time to start Talawa-Admin and get it running ## Running Talawa-Admin @@ -138,22 +186,30 @@ npm run serve ## Accessing Talawa-Admin -By default `talawa-admin` runs on port `3000` on your system's localhost. It is available on the following endpoint: +By default `talawa-admin` runs on port `4321` on your system's localhost. It is available on the following endpoint: ``` -http://localhost:3000/ +http://localhost:4321/ ``` +If you have specified a custom port number in your `.env` file, Talawa-Admin will run on the following endpoint: + +``` +http://localhost:${{customPort}}/ +``` + +Replace `${{customPort}}` with the actual custom port number you have configured in your `.env` file. + ## Talawa-Admin Registration The first time you navigate to the running talawa-admin's website you'll land at talawa-admin registration page. Sign up using whatever credentials you want and create the account. Make sure to remember the email and password you entered because they'll be used to sign you in later on. - ## Talawa-Admin Login Now sign in to talawa-admin using the `email` and `password` you used to sign up. # Testing + It is important to test our code. If you are a contributor, please follow these steps. ## Running tests @@ -177,7 +233,6 @@ You don't need to re-run the `npm run jest-preview` command each time, simply ru ![Debugging Test Demo](./public/images/jest-preview.webp) - ## Linting code files You can lint your code files using this command: @@ -188,30 +243,22 @@ npm run lint:fix ## Husky for Git Hooks - We are using the package `Husky` to run git hooks that run according to different git workflows. -
    - #### pre-commit hook -We run a pre-commit hook which automatically runs code quality checks each time you make a commit and also fixes some of the issues. This way you don't have to run them manually each time. +We run a pre-commit hook which automatically runs code quality checks each time you make a commit and also fixes some of the issues. This way you don't have to run them manually each time. If you don't want these pre-commit checks running on each commit, you can manually opt out of it using the `--no-verify` flag with your commit message as shown:- git commit -m "commit message" --no-verify -
    - - #### post-merge hook -We are also running a post-merge(post-pull) hook which will automatically run "npm install --legacy-peer-deps" only if there is any change made to pakage.json file so that the developer has all the required dependencies when pulling files from remote. - +We are also running a post-merge(post-pull) hook which will automatically run "npm install" only if there is any change made to pakage.json file so that the developer has all the required dependencies when pulling files from remote. If you don't want this hook to run, you can manually opt out of this using the `no verify` flag while using the merge command(git pull): - git pull --no-verify + git pull --no-verify
    - diff --git a/ISSUE_GUIDELINES.md b/ISSUE_GUIDELINES.md index 18b93ee10b..5170de5839 100644 --- a/ISSUE_GUIDELINES.md +++ b/ISSUE_GUIDELINES.md @@ -6,18 +6,18 @@ In order to give everyone a chance to submit a issues reports and contribute to ___ ## Table of Contents - - -- [Issue Report Guidelines](#issue-report-guidelines) - - [Table of Contents](#table-of-contents) - - [Issue Management](#issue-management) - - [New Issues](#new-issues) - - [Existing Issues](#existing-issues) - - [Feature Request Issues](#feature-request-issues) - - [Monitoring the Creation of New Issues](#monitoring-the-creation-of-new-issues) - - [General Guidelines](#general-guidelines) - - + + + +- [Issue Management](#issue-management) + - [New Issues](#new-issues) + - [Existing Issues](#existing-issues) + - [Feature Request Issues](#feature-request-issues) + - [Monitoring the Creation of New Issues](#monitoring-the-creation-of-new-issues) +- [General Guidelines](#general-guidelines) + + + ___ ## Issue Management @@ -50,7 +50,7 @@ Working on these types of existing issues is a good way of getting started with Feature requests are welcome. But take a moment to find out whether your idea fits with the scope and aims of the project. It's up to you to make a strong case to convince the mentors of the merits of this feature. Please provide as much detail and context as possible. ### Monitoring the Creation of New Issues -1. Join our `#talawa-github` slack channel for automatic issue and pull request updates +1. Join our `#talawa-github` slack channel for automatic issue and pull request updates. ## General Guidelines diff --git a/PR_GUIDELINES.md b/PR_GUIDELINES.md index d1c2a0b2d9..4c904c782d 100644 --- a/PR_GUIDELINES.md +++ b/PR_GUIDELINES.md @@ -4,6 +4,18 @@ In order to give everyone a chance to submit a pull request and contribute to the Talawa project, we have put restrictions in place. This section outlines the guidelines that should be imposed upon pull requests in the Talawa project. +# Table of Contents + + + +- [Pull Requests and Issues](#pull-requests-and-issues) +- [Linting and Formatting](#linting-and-formatting) +- [Testing](#testing) +- [Pull Request Processing](#pull-request-processing) + - [Only submit PRs against our `develop` branch, not the default `main` branch](#only-submit-prs-against-our-develop-branch-not-the-default-main-branch) + + + ## Pull Requests and Issues 1. Do not start working on any open issue and raise a PR unless the issue is assigned to you. PRs that don't meet these guidelines will be closed. diff --git a/README.md b/README.md index 39be8dbb3d..e0fb3da5d4 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,16 @@ Core features include: `talawa` is based on the original `quito` code created by the [Palisadoes Foundation][pfd] as part of its annual Calico Challenge program. Calico provides paid summer internships for Jamaican university students to work on selected open source projects. They are mentored by software professionals and receive stipends based on the completion of predefined milestones. Calico was started in 2015. Visit [The Palisadoes Foundation's website](http://www.palisadoes.org/) for more details on its origin and activities. +# Table of Contents + + + +- [Talawa Components](#talawa-components) +- [Documentation](#documentation) +- [Videos](#videos) + + + # Talawa Components `talawa` has these major software components: @@ -31,10 +41,15 @@ Core features include: # Documentation -- The `talawa` documentation can be found [here](https://docs.talawa.io). -- Want to contribute? Look at [CONTRIBUTING.md](https://github.com/PalisadoesFoundation/talawa-admin/blob/develop/CONTRIBUTING.md) to get started. -- Visit the [Talawa-Docs GitHub](https://github.com/PalisadoesFoundation/talawa-docs) to see the code. +1. You can install the software for this repository using the steps in our [INSTALLATION.md](INSTALLATION.md) file. +1. Do you want to contribute to our code base? Look at our [CONTRIBUTING.md](CONTRIBUTING.md) file to get started. There you'll also find links to: + 1. Our code of conduct documentation in the [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) file. + 1. How we handle the processing of new and existing issues in our [ISSUE_GUIDELINES.md](ISSUE_GUIDELINES.md) file. + 1. The methodologies we use to manage our pull requests in our [PR_GUIDELINES.md](PR_GUIDELINES.md) file. +1. The `talawa` documentation can be found at our [docs.talawa.io](https://docs.talawa.io) site. + 1. It is automatically generated from the markdown files stored in our [Talawa-Docs GitHub repository](https://github.com/PalisadoesFoundation/talawa-docs). This makes it easy for you to update our documenation. -# Installation +# Videos -[Follow this guide](https://github.com/PalisadoesFoundation/talawa-admin/blob/develop/INSTALLATION.md) +1. Visit our [YouTube Channel playlists](https://www.youtube.com/@PalisadoesOrganization/playlists) for more insights + 1. The "Getting Started - Developers" videos are extremely helpful for new open source contributors. diff --git a/jest.config.js b/jest.config.js index 78be9e4e43..34f219ba06 100644 --- a/jest.config.js +++ b/jest.config.js @@ -25,6 +25,9 @@ export default { moduleNameMapper: { '^react-native$': 'react-native-web', '^@mui/(.*)$': '/node_modules/@mui/$1', + '^@dicebear/core$': '/scripts/__mocks__/@dicebear/core.ts', + '^@dicebear/collection$': + '/scripts/__mocks__/@dicebear/collection.ts', }, moduleFileExtensions: [ 'web.js', diff --git a/package-lock.json b/package-lock.json index f11ca8eb3f..d3e0d5e85d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,89 +11,92 @@ "@apollo/client": "^3.4.0-beta.19", "@apollo/link-error": "^2.0.0-beta.3", "@apollo/react-testing": "^4.0.0", + "@dicebear/collection": "^7.0.4", + "@dicebear/core": "^7.0.4", "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", "@mui/icons-material": "^5.8.3", "@mui/material": "^5.14.1", - "@mui/private-theming": "^5.14.13", + "@mui/private-theming": "^5.15.12", "@mui/system": "^5.14.12", "@mui/x-charts": "^6.0.0-alpha.13", "@mui/x-data-grid": "^6.8.0", "@mui/x-date-pickers": "^6.6.0", "@pdfme/generator": "^1.2.6", - "@testing-library/jest-dom": "^5.14.1", - "@testing-library/react": "^11.1.0", - "@testing-library/user-event": "^12.1.10", - "@types/enzyme-adapter-react-16": "^1.0.6", - "@types/jest": "^26.0.24", - "@types/jquery": "^3.5.6", - "@types/node": "^12.20.16", - "@types/react-bootstrap": "^0.32.32", - "@types/react-datepicker": "^4.1.4", - "@types/react-dom": "^17.0.9", - "@types/react-google-recaptcha": "^2.1.5", - "@types/react-modal": "^3.12.1", "bootstrap": "^5.3.0", + "customize-cra": "^1.0.0", "dayjs": "^1.10.7", - "detect-newline": "^4.0.0", - "enzyme": "^3.11.0", - "enzyme-adapter-react-16": "^1.15.6", - "eslint-config-prettier": "^8.3.0", - "eslint-plugin-jest": "^25.3.4", - "eslint-plugin-prettier": "^3.4.0", "flag-icons": "^6.6.6", "graphql": "^15.5.1", "graphql-tag": "^2.12.6", "graphql-ws": "^5.14.0", + "history": "^5.3.0", "i18next": "^21.8.14", "i18next-browser-languagedetector": "^6.1.4", "i18next-http-backend": "^1.4.1", - "jest-docblock": "^27.4.0", + "inquirer": "^8.0.0", "js-cookie": "^3.0.1", - "node-sass": "^9.0.0", - "prettier": "^2.3.2", + "markdown-toc": "^1.2.0", + "prettier": "^3.2.5", "react": "^17.0.2", + "react-app-rewired": "^2.2.1", "react-bootstrap": "^2.7.4", - "react-calendar": "^4.2.1", "react-datepicker": "^4.2.0", "react-dom": "^17.0.2", "react-google-recaptcha": "^2.1.0", "react-i18next": "^11.18.1", + "react-icons": "^4.12.0", "react-infinite-scroll-component": "^6.1.0", "react-redux": "^7.2.5", - "react-router-dom": "^5.2.0", + "react-router-dom": "^6.22.2", "react-scripts": "5.0.1", "react-toastify": "^9.0.3", "redux": "^4.1.1", "redux-thunk": "^2.3.0", - "typedoc": "^0.24.8", - "typedoc-plugin-markdown": "^3.16.0", + "sanitize-html": "^2.12.1", + "typedoc-plugin-markdown": "^3.17.1", "typescript": "^4.3.5", - "web-vitals": "^1.0.1", - "yarn": "^1.22.17" + "web-vitals": "^1.0.1" }, "devDependencies": { "@babel/plugin-proposal-private-property-in-object": "^7.21.11", - "@fortawesome/fontawesome-svg-core": "^1.2.35", - "@fortawesome/free-brands-svg-icons": "^5.15.3", - "@fortawesome/react-fontawesome": "^0.1.14", - "@types/enzyme": "^3.10.9", + "@testing-library/jest-dom": "^5.14.1", + "@testing-library/react": "^11.1.0", + "@testing-library/user-event": "^12.1.10", + "@types/inquirer": "^9.0.7", + "@types/jest": "^26.0.24", "@types/js-cookie": "^3.0.2", + "@types/node": "^12.20.55", + "@types/node-fetch": "^2.6.10", "@types/react": "^17.0.14", + "@types/react-bootstrap": "^0.32.32", + "@types/react-datepicker": "^4.1.4", + "@types/react-dom": "^17.0.9", + "@types/react-google-recaptcha": "^2.1.5", "@types/react-router-dom": "^5.1.8", + "@types/sanitize-html": "^2.11.0", "@typescript-eslint/eslint-plugin": "^5.9.0", "@typescript-eslint/parser": "^5.9.0", - "@wojtekmaj/enzyme-adapter-react-17": "^0.8.0", "cross-env": "^7.0.3", + "eslint-config-prettier": "^8.10.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-jest": "^25.3.4", + "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-react": "^7.34.1", + "eslint-plugin-tsdoc": "^0.2.17", "husky": "^8.0.3", "identity-obj-proxy": "^3.0.0", "jest": "^27.4.5", - "jest-enzyme": "^7.1.2", "jest-localstorage-mock": "^2.4.19", "jest-location-mock": "^1.0.9", "jest-preview": "^0.3.1", - "jquery": "^3.2.1", - "postcss-modules": "^6.0.0" + "lint-staged": "^15.2.2", + "postcss-modules": "^6.0.0", + "sass": "^1.71.1", + "tsx": "^3.11.0" + }, + "engines": { + "node": ">=20.x" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -105,9 +108,10 @@ } }, "node_modules/@adobe/css-tools": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.2.0.tgz", - "integrity": "sha512-E09FiIft46CmH5Qnjb0wsW54/YQd69LsxeKUOWawmws1XWvyFGURnAChH0mlr7YPFR1ofwvUQfcL0J3lMxXqPA==" + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.3.tgz", + "integrity": "sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==", + "dev": true }, "node_modules/@alloc/quick-lru": { "version": "5.2.0", @@ -212,20 +216,85 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", - "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dependencies": { - "@babel/highlight": "^7.22.5" + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/compat-data": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz", - "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", "engines": { "node": ">=6.9.0" } @@ -301,11 +370,11 @@ } }, "node_modules/@babel/generator": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.9.tgz", - "integrity": "sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", "dependencies": { - "@babel/types": "^7.22.5", + "@babel/types": "^7.23.6", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -326,32 +395,29 @@ } }, "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.5.tgz", - "integrity": "sha512-m1EP3lVOPptR+2DwD125gziZNcmoNSHGmJROKoy87loWUQyJaVXDgpmruWqDARZSmtYQ+Dl25okU8+qhVzuykw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", + "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.9.tgz", - "integrity": "sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", "dependencies": { - "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.5", - "browserslist": "^4.21.9", + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { @@ -363,16 +429,16 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.9.tgz", - "integrity": "sha512-Pwyi89uO4YrGKxL/eNJ8lfEH55DnRloGPOseaA8NFNL6jAUnn+KccaISiFazCj5IolPPDjGSdzQzXVzODVRqUQ==", + "version": "7.23.10", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.10.tgz", + "integrity": "sha512-2XpP2XhkXzgxecPNEEK8Vz8Asj9aRxt08oKOqtiZoqV2UGZ5T+EkyP9sXQ9nwMxBIG34a7jmasVqoMop7VdPUw==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", - "@babel/helper-member-expression-to-functions": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-member-expression-to-functions": "^7.23.0", "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.9", + "@babel/helper-replace-supers": "^7.22.20", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", "semver": "^6.3.1" @@ -393,9 +459,9 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.9.tgz", - "integrity": "sha512-+svjVa/tFwsNSG4NEy1h85+HQ5imbT92Q5/bgtS7P0GTQlP8WuFdqsiABmQouhiFGyV66oGxZFpeYHza1rNsKw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", + "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "regexpu-core": "^5.3.1", @@ -432,20 +498,20 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", - "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dependencies": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" @@ -463,37 +529,37 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.5.tgz", - "integrity": "sha512-aBiH1NKMG0H2cGZqspNvsaBe6wNGjbJjuLy29aU+eDZjSbbN53BaxlpB02xm9v34pLTZ1nIQPFYn2qMZoa5BQQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", + "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", - "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz", - "integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", "@babel/helper-simple-access": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.5" + "@babel/helper-validator-identifier": "^7.22.20" }, "engines": { "node": ">=6.9.0" @@ -522,13 +588,13 @@ } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.9.tgz", - "integrity": "sha512-8WWC4oR4Px+tr+Fp0X3RHDVfINGpF3ad1HIbrc8A77epiR6eMMc6jsgozkzT2uDiOOdoS9cLIQ+XD2XvI2WSmQ==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", + "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-wrap-function": "^7.22.9" + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-wrap-function": "^7.22.20" }, "engines": { "node": ">=6.9.0" @@ -538,12 +604,12 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.9.tgz", - "integrity": "sha512-LJIKvvpgPOPUThdYqcX6IXRuIcTkcAub0IaDRGCZH0p5GPUp7PhRU9QVgFcDDd51BaPkk77ZjqFwh6DZTAEmGg==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", + "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-member-expression-to-functions": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-member-expression-to-functions": "^7.22.15", "@babel/helper-optimise-call-expression": "^7.22.5" }, "engines": { @@ -587,37 +653,37 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", - "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", - "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.9.tgz", - "integrity": "sha512-sZ+QzfauuUEfxSEjKFmi3qDSHgLsTPK/pEpoD/qonZKOtTPTLbf59oabPQ4rKekt9lFcj/hTZaOhWwFYrgjk+Q==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", + "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", "dependencies": { "@babel/helper-function-name": "^7.22.5", - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/template": "^7.22.15", + "@babel/types": "^7.22.19" }, "engines": { "node": ">=6.9.0" @@ -637,12 +703,12 @@ } }, "node_modules/@babel/highlight": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", - "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.5", - "chalk": "^2.0.0", + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, "engines": { @@ -714,9 +780,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz", - "integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.0.tgz", + "integrity": "sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==", "bin": { "parser": "bin/babel-parser.js" }, @@ -725,9 +791,9 @@ } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.5.tgz", - "integrity": "sha512-NP1M5Rf+u2Gw9qfSO4ihjcTGW5zXTi36ITLd4/EoAcEhIZ0yjMqmftDNl3QC19CX7olhrjpyU454g/2W7X0jvQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz", + "integrity": "sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -739,13 +805,13 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.5.tgz", - "integrity": "sha512-31Bb65aZaUwqCbWMnZPduIZxCBngHFlzyN6Dq6KAJjtx+lx6ohKHubc61OomYi7XwVD4Ol0XCVz4h+pYFR048g==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz", + "integrity": "sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-transform-optional-chaining": "^7.22.5" + "@babel/plugin-transform-optional-chaining": "^7.23.3" }, "engines": { "node": ">=6.9.0" @@ -754,6 +820,21 @@ "@babel/core": "^7.13.0" } }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz", + "integrity": "sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/@babel/plugin-proposal-class-properties": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", @@ -866,21 +947,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-unicode-property-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", - "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-syntax-async-generators": { "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", @@ -979,9 +1045,9 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz", - "integrity": "sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz", + "integrity": "sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -993,9 +1059,9 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.22.5.tgz", - "integrity": "sha512-KwvoWDeNKPETmozyFE0P2rOLqh39EoQHNjqizrI5B8Vt0ZNS7M56s7dAiAqbYfiAYOuIzIh96z3iR2ktgu3tEg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz", + "integrity": "sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1029,9 +1095,9 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", - "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", + "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1137,9 +1203,9 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", - "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", + "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1166,9 +1232,9 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz", - "integrity": "sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz", + "integrity": "sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1180,13 +1246,13 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.7.tgz", - "integrity": "sha512-7HmE7pk/Fmke45TODvxvkxRMV9RazV+ZZzhOL9AG8G29TLrr3jkjwF7uJfxZ30EoXpO+LJkq4oA8NjO2DTnEDg==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.9.tgz", + "integrity": "sha512-8Q3veQEDGe14dTYuwagbRtwxQDnytyg1JFu4/HwEMETeofocrB0U0ejBJIXoeG/t2oXZ8kzCyI0ZZfbT80VFNQ==", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-remap-async-to-generator": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.20", "@babel/plugin-syntax-async-generators": "^7.8.4" }, "engines": { @@ -1197,13 +1263,13 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.22.5.tgz", - "integrity": "sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz", + "integrity": "sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==", "dependencies": { - "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-module-imports": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-remap-async-to-generator": "^7.22.5" + "@babel/helper-remap-async-to-generator": "^7.22.20" }, "engines": { "node": ">=6.9.0" @@ -1213,9 +1279,9 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz", - "integrity": "sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz", + "integrity": "sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1227,9 +1293,9 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.5.tgz", - "integrity": "sha512-EcACl1i5fSQ6bt+YGuU/XGCeZKStLmyVGytWkpyhCLeQVA0eu6Wtiw92V+I1T/hnezUv7j74dA/Ro69gWcU+hg==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz", + "integrity": "sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1241,11 +1307,11 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.22.5.tgz", - "integrity": "sha512-nDkQ0NfkOhPTq8YCLiWNxp1+f9fCobEjCb0n8WdbNUBc4IB5V7P1QnX9IjpSoquKrXF5SKojHleVNs2vGeHCHQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz", + "integrity": "sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1256,11 +1322,11 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.5.tgz", - "integrity": "sha512-SPToJ5eYZLxlnp1UzdARpOGeC2GbHvr9d/UV0EukuVx8atktg194oe+C5BqQ8jRTkgLRVOPYeXRSBg1IlMoVRA==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz", + "integrity": "sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-class-static-block": "^7.14.5" }, @@ -1272,17 +1338,16 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.6.tgz", - "integrity": "sha512-58EgM6nuPNG6Py4Z3zSuu0xWu2VfodiMi72Jt5Kj2FECmaYk1RrTXA45z6KBFsu9tRgwQDwIiY4FXTt+YsSFAQ==", + "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.8.tgz", + "integrity": "sha512-yAYslGsY1bX6Knmg46RjiCiNSwJKv2IUC8qOdYKqMMr0491SXFhcHqOdRDeCRohOOIzwN/90C6mQ9qAKgrP7dg==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", - "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20", "@babel/helper-split-export-declaration": "^7.22.6", "globals": "^11.1.0" }, @@ -1294,12 +1359,12 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz", - "integrity": "sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz", + "integrity": "sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", - "@babel/template": "^7.22.5" + "@babel/template": "^7.22.15" }, "engines": { "node": ">=6.9.0" @@ -1309,9 +1374,9 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.5.tgz", - "integrity": "sha512-GfqcFuGW8vnEqTUBM7UtPd5A4q797LTvvwKxXTgRsFjoqaJiEg9deBG6kWeQYkVEL569NpnmpC0Pkr/8BLKGnQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz", + "integrity": "sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1323,11 +1388,11 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz", - "integrity": "sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz", + "integrity": "sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-create-regexp-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1338,9 +1403,9 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.22.5.tgz", - "integrity": "sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz", + "integrity": "sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1352,9 +1417,9 @@ } }, "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.5.tgz", - "integrity": "sha512-0MC3ppTB1AMxd8fXjSrbPa7LT9hrImt+/fcj+Pg5YMD7UQyWp/02+JWpdnCymmsXwIx5Z+sYn1bwCn4ZJNvhqQ==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz", + "integrity": "sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3" @@ -1367,11 +1432,11 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz", - "integrity": "sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz", + "integrity": "sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==", "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.5", + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1382,9 +1447,9 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.5.tgz", - "integrity": "sha512-X4hhm7FRnPgd4nDA4b/5V280xCx6oL7Oob5+9qVS5C13Zq4bh1qq7LU0GgRU6b5dBWBvhGaXYVB4AcN6+ol6vg==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz", + "integrity": "sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" @@ -1412,11 +1477,12 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.5.tgz", - "integrity": "sha512-3kxQjX1dU9uudwSshyLeEipvrLjBCVthCgeTp6CzE/9JYrlAIaeekVxRpCWsDDfYTfRZRoCeZatCQvwo+wvK8A==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz", + "integrity": "sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -1426,12 +1492,12 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz", - "integrity": "sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz", + "integrity": "sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==", "dependencies": { - "@babel/helper-compilation-targets": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-function-name": "^7.23.0", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1442,9 +1508,9 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.5.tgz", - "integrity": "sha512-DuCRB7fu8MyTLbEQd1ew3R85nx/88yMoqo2uPSjevMj3yoN7CDM8jkgrY0wmVxfJZyJ/B9fE1iq7EQppWQmR5A==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz", + "integrity": "sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-json-strings": "^7.8.3" @@ -1457,9 +1523,9 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz", - "integrity": "sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz", + "integrity": "sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1471,9 +1537,9 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.5.tgz", - "integrity": "sha512-MQQOUW1KL8X0cDWfbwYP+TbVbZm16QmQXJQ+vndPtH/BoO0lOKpVoEDMI7+PskYxH+IiE0tS8xZye0qr1lGzSA==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz", + "integrity": "sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" @@ -1486,9 +1552,9 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz", - "integrity": "sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz", + "integrity": "sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1500,11 +1566,11 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.22.5.tgz", - "integrity": "sha512-R+PTfLTcYEmb1+kK7FNkhQ1gP4KgjpSO6HfH9+f8/yfp2Nt3ggBjiVpRwmwTlfqZLafYKJACy36yDXlEmI9HjQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz", + "integrity": "sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==", "dependencies": { - "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.3", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1515,11 +1581,11 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.5.tgz", - "integrity": "sha512-B4pzOXj+ONRmuaQTg05b3y/4DuFz3WcCNAXPLb2Q0GT0TrGKGxNKV4jwsXts+StaM0LQczZbOpj8o1DLPDJIiA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", + "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", "dependencies": { - "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.3", "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-simple-access": "^7.22.5" }, @@ -1531,14 +1597,14 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.22.5.tgz", - "integrity": "sha512-emtEpoaTMsOs6Tzz+nbmcePl6AKVtS1yC4YNAeMun9U8YCsgadPNxnOPQ8GhHFB2qdx+LZu9LgoC0Lthuu05DQ==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.9.tgz", + "integrity": "sha512-KDlPRM6sLo4o1FkiSlXoAa8edLXFsKKIda779fbLrvmeuc3itnjCtaO6RrtoaANsIJANj+Vk1zqbZIMhkCAHVw==", "dependencies": { "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.3", "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5" + "@babel/helper-validator-identifier": "^7.22.20" }, "engines": { "node": ">=6.9.0" @@ -1548,11 +1614,11 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz", - "integrity": "sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz", + "integrity": "sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==", "dependencies": { - "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.3", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1578,9 +1644,9 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.5.tgz", - "integrity": "sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz", + "integrity": "sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1592,9 +1658,9 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.5.tgz", - "integrity": "sha512-6CF8g6z1dNYZ/VXok5uYkkBBICHZPiGEl7oDnAx2Mt1hlHVHOSIKWJaXHjQJA5VB43KZnXZDIexMchY4y2PGdA==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz", + "integrity": "sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" @@ -1607,9 +1673,9 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.5.tgz", - "integrity": "sha512-NbslED1/6M+sXiwwtcAB/nieypGw02Ejf4KtDeMkCEpP6gWFMX1wI9WKYua+4oBneCCEmulOkRpwywypVZzs/g==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz", + "integrity": "sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-numeric-separator": "^7.10.4" @@ -1622,15 +1688,15 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.5.tgz", - "integrity": "sha512-Kk3lyDmEslH9DnvCDA1s1kkd3YWQITiBOHngOtDL9Pt6BZjzqb6hiOlb8VfjiiQJ2unmegBqZu0rx5RxJb5vmQ==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.4.tgz", + "integrity": "sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g==", "dependencies": { - "@babel/compat-data": "^7.22.5", - "@babel/helper-compilation-targets": "^7.22.5", + "@babel/compat-data": "^7.23.3", + "@babel/helper-compilation-targets": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.22.5" + "@babel/plugin-transform-parameters": "^7.23.3" }, "engines": { "node": ">=6.9.0" @@ -1640,12 +1706,12 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz", - "integrity": "sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz", + "integrity": "sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.5" + "@babel/helper-replace-supers": "^7.22.20" }, "engines": { "node": ">=6.9.0" @@ -1655,9 +1721,9 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.5.tgz", - "integrity": "sha512-pH8orJahy+hzZje5b8e2QIlBWQvGpelS76C63Z+jhZKsmzfNaPQ+LaW6dcJ9bxTpo1mtXbgHwy765Ro3jftmUg==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz", + "integrity": "sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" @@ -1670,9 +1736,9 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.6.tgz", - "integrity": "sha512-Vd5HiWml0mDVtcLHIoEU5sw6HOUW/Zk0acLs/SAeuLzkGNOPc9DB4nkUajemhCmTIz3eiaKREZn2hQQqF79YTg==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz", + "integrity": "sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", @@ -1686,9 +1752,9 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.5.tgz", - "integrity": "sha512-AVkFUBurORBREOmHRKo06FjHYgjrabpdqRSwq6+C7R5iTCZOsM4QbcB27St0a4U6fffyAOqh3s/qEfybAhfivg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz", + "integrity": "sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1700,11 +1766,11 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.22.5.tgz", - "integrity": "sha512-PPjh4gyrQnGe97JTalgRGMuU4icsZFnWkzicB/fUtzlKUqvsWBKEpPPfr5a2JiyirZkHxnAqkQMO5Z5B2kK3fA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz", + "integrity": "sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1715,12 +1781,12 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.5.tgz", - "integrity": "sha512-/9xnaTTJcVoBtSSmrVyhtSvO3kbqS2ODoh2juEU72c3aYonNF0OMGiaz2gjukyKM2wBBYJP38S4JiE0Wfb5VMQ==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz", + "integrity": "sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, @@ -1732,9 +1798,9 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz", - "integrity": "sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz", + "integrity": "sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1821,12 +1887,12 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.5.tgz", - "integrity": "sha512-rR7KePOE7gfEtNTh9Qw+iO3Q/e4DEsoQ+hdvM6QUDH7JRJ5qxq5AA52ZzBWbI5i9lfNuvySgOGP8ZN7LAmaiPw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz", + "integrity": "sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", - "regenerator-transform": "^0.15.1" + "regenerator-transform": "^0.15.2" }, "engines": { "node": ">=6.9.0" @@ -1836,9 +1902,9 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz", - "integrity": "sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz", + "integrity": "sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1877,9 +1943,9 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz", - "integrity": "sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz", + "integrity": "sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1891,9 +1957,9 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz", - "integrity": "sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz", + "integrity": "sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" @@ -1906,9 +1972,9 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.22.5.tgz", - "integrity": "sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz", + "integrity": "sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1920,9 +1986,9 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz", - "integrity": "sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz", + "integrity": "sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1934,9 +2000,9 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.22.5.tgz", - "integrity": "sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz", + "integrity": "sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1948,14 +2014,14 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.9.tgz", - "integrity": "sha512-BnVR1CpKiuD0iobHPaM1iLvcwPYN2uVFAqoLVSpEDKWuOikoCv5HbKLxclhKYUXlWkX86DoZGtqI4XhbOsyrMg==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.23.6.tgz", + "integrity": "sha512-6cBG5mBvUu4VUD04OHKnYzbuHNP8huDsD3EDqqpIpsswTDoqHCjLoHb6+QgsV1WsT2nipRqCPgxD3LXnEO7XfA==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.22.9", + "@babel/helper-create-class-features-plugin": "^7.23.6", "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-typescript": "^7.22.5" + "@babel/plugin-syntax-typescript": "^7.23.3" }, "engines": { "node": ">=6.9.0" @@ -1965,9 +2031,9 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.5.tgz", - "integrity": "sha512-biEmVg1IYB/raUO5wT1tgfacCef15Fbzhkx493D3urBI++6hpJ+RFG4SrWMn0NEZLfvilqKf3QDrRVZHo08FYg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz", + "integrity": "sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1979,11 +2045,11 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.22.5.tgz", - "integrity": "sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz", + "integrity": "sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-create-regexp-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1994,11 +2060,11 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.22.5.tgz", - "integrity": "sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz", + "integrity": "sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-create-regexp-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -2009,11 +2075,11 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.22.5.tgz", - "integrity": "sha512-lhMfi4FC15j13eKrh3DnYHjpGj6UKQHtNKTbtc1igvAhRy4+kLhV07OpLcsN0VgDEw/MjAvJO4BdMJsHwMhzCg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz", + "integrity": "sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-create-regexp-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -2024,24 +2090,25 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.22.9.tgz", - "integrity": "sha512-wNi5H/Emkhll/bqPjsjQorSykrlfY5OWakd6AulLvMEytpKasMVUpVy8RL4qBIBs5Ac6/5i0/Rv0b/Fg6Eag/g==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.9.tgz", + "integrity": "sha512-3kBGTNBBk9DQiPoXYS0g0BYlwTQYUTifqgKTjxUwEUkduRT2QOa0FPGBJ+NROQhGyYO5BuTJwGvBnqKDykac6A==", "dependencies": { - "@babel/compat-data": "^7.22.9", - "@babel/helper-compilation-targets": "^7.22.9", + "@babel/compat-data": "^7.23.5", + "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.22.5", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.5", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.22.5", + "@babel/helper-validator-option": "^7.23.5", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.23.3", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.23.3", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.23.7", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", "@babel/plugin-syntax-class-static-block": "^7.14.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.22.5", - "@babel/plugin-syntax-import-attributes": "^7.22.5", + "@babel/plugin-syntax-import-assertions": "^7.23.3", + "@babel/plugin-syntax-import-attributes": "^7.23.3", "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", @@ -2053,59 +2120,58 @@ "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.22.5", - "@babel/plugin-transform-async-generator-functions": "^7.22.7", - "@babel/plugin-transform-async-to-generator": "^7.22.5", - "@babel/plugin-transform-block-scoped-functions": "^7.22.5", - "@babel/plugin-transform-block-scoping": "^7.22.5", - "@babel/plugin-transform-class-properties": "^7.22.5", - "@babel/plugin-transform-class-static-block": "^7.22.5", - "@babel/plugin-transform-classes": "^7.22.6", - "@babel/plugin-transform-computed-properties": "^7.22.5", - "@babel/plugin-transform-destructuring": "^7.22.5", - "@babel/plugin-transform-dotall-regex": "^7.22.5", - "@babel/plugin-transform-duplicate-keys": "^7.22.5", - "@babel/plugin-transform-dynamic-import": "^7.22.5", - "@babel/plugin-transform-exponentiation-operator": "^7.22.5", - "@babel/plugin-transform-export-namespace-from": "^7.22.5", - "@babel/plugin-transform-for-of": "^7.22.5", - "@babel/plugin-transform-function-name": "^7.22.5", - "@babel/plugin-transform-json-strings": "^7.22.5", - "@babel/plugin-transform-literals": "^7.22.5", - "@babel/plugin-transform-logical-assignment-operators": "^7.22.5", - "@babel/plugin-transform-member-expression-literals": "^7.22.5", - "@babel/plugin-transform-modules-amd": "^7.22.5", - "@babel/plugin-transform-modules-commonjs": "^7.22.5", - "@babel/plugin-transform-modules-systemjs": "^7.22.5", - "@babel/plugin-transform-modules-umd": "^7.22.5", + "@babel/plugin-transform-arrow-functions": "^7.23.3", + "@babel/plugin-transform-async-generator-functions": "^7.23.9", + "@babel/plugin-transform-async-to-generator": "^7.23.3", + "@babel/plugin-transform-block-scoped-functions": "^7.23.3", + "@babel/plugin-transform-block-scoping": "^7.23.4", + "@babel/plugin-transform-class-properties": "^7.23.3", + "@babel/plugin-transform-class-static-block": "^7.23.4", + "@babel/plugin-transform-classes": "^7.23.8", + "@babel/plugin-transform-computed-properties": "^7.23.3", + "@babel/plugin-transform-destructuring": "^7.23.3", + "@babel/plugin-transform-dotall-regex": "^7.23.3", + "@babel/plugin-transform-duplicate-keys": "^7.23.3", + "@babel/plugin-transform-dynamic-import": "^7.23.4", + "@babel/plugin-transform-exponentiation-operator": "^7.23.3", + "@babel/plugin-transform-export-namespace-from": "^7.23.4", + "@babel/plugin-transform-for-of": "^7.23.6", + "@babel/plugin-transform-function-name": "^7.23.3", + "@babel/plugin-transform-json-strings": "^7.23.4", + "@babel/plugin-transform-literals": "^7.23.3", + "@babel/plugin-transform-logical-assignment-operators": "^7.23.4", + "@babel/plugin-transform-member-expression-literals": "^7.23.3", + "@babel/plugin-transform-modules-amd": "^7.23.3", + "@babel/plugin-transform-modules-commonjs": "^7.23.3", + "@babel/plugin-transform-modules-systemjs": "^7.23.9", + "@babel/plugin-transform-modules-umd": "^7.23.3", "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", - "@babel/plugin-transform-new-target": "^7.22.5", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.5", - "@babel/plugin-transform-numeric-separator": "^7.22.5", - "@babel/plugin-transform-object-rest-spread": "^7.22.5", - "@babel/plugin-transform-object-super": "^7.22.5", - "@babel/plugin-transform-optional-catch-binding": "^7.22.5", - "@babel/plugin-transform-optional-chaining": "^7.22.6", - "@babel/plugin-transform-parameters": "^7.22.5", - "@babel/plugin-transform-private-methods": "^7.22.5", - "@babel/plugin-transform-private-property-in-object": "^7.22.5", - "@babel/plugin-transform-property-literals": "^7.22.5", - "@babel/plugin-transform-regenerator": "^7.22.5", - "@babel/plugin-transform-reserved-words": "^7.22.5", - "@babel/plugin-transform-shorthand-properties": "^7.22.5", - "@babel/plugin-transform-spread": "^7.22.5", - "@babel/plugin-transform-sticky-regex": "^7.22.5", - "@babel/plugin-transform-template-literals": "^7.22.5", - "@babel/plugin-transform-typeof-symbol": "^7.22.5", - "@babel/plugin-transform-unicode-escapes": "^7.22.5", - "@babel/plugin-transform-unicode-property-regex": "^7.22.5", - "@babel/plugin-transform-unicode-regex": "^7.22.5", - "@babel/plugin-transform-unicode-sets-regex": "^7.22.5", - "@babel/preset-modules": "^0.1.5", - "@babel/types": "^7.22.5", - "babel-plugin-polyfill-corejs2": "^0.4.4", - "babel-plugin-polyfill-corejs3": "^0.8.2", - "babel-plugin-polyfill-regenerator": "^0.5.1", + "@babel/plugin-transform-new-target": "^7.23.3", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.23.4", + "@babel/plugin-transform-numeric-separator": "^7.23.4", + "@babel/plugin-transform-object-rest-spread": "^7.23.4", + "@babel/plugin-transform-object-super": "^7.23.3", + "@babel/plugin-transform-optional-catch-binding": "^7.23.4", + "@babel/plugin-transform-optional-chaining": "^7.23.4", + "@babel/plugin-transform-parameters": "^7.23.3", + "@babel/plugin-transform-private-methods": "^7.23.3", + "@babel/plugin-transform-private-property-in-object": "^7.23.4", + "@babel/plugin-transform-property-literals": "^7.23.3", + "@babel/plugin-transform-regenerator": "^7.23.3", + "@babel/plugin-transform-reserved-words": "^7.23.3", + "@babel/plugin-transform-shorthand-properties": "^7.23.3", + "@babel/plugin-transform-spread": "^7.23.3", + "@babel/plugin-transform-sticky-regex": "^7.23.3", + "@babel/plugin-transform-template-literals": "^7.23.3", + "@babel/plugin-transform-typeof-symbol": "^7.23.3", + "@babel/plugin-transform-unicode-escapes": "^7.23.3", + "@babel/plugin-transform-unicode-property-regex": "^7.23.3", + "@babel/plugin-transform-unicode-regex": "^7.23.3", + "@babel/plugin-transform-unicode-sets-regex": "^7.23.3", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.8", + "babel-plugin-polyfill-corejs3": "^0.9.0", + "babel-plugin-polyfill-regenerator": "^0.5.5", "core-js-compat": "^3.31.0", "semver": "^6.3.1" }, @@ -2116,6 +2182,21 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/preset-env/node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", + "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, "node_modules/@babel/preset-env/node_modules/@babel/plugin-proposal-private-property-in-object": { "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", @@ -2127,6 +2208,18 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.9.0.tgz", + "integrity": "sha512-7nZPG1uzK2Ymhy/NbaOWTg3uibM2BmGASS4vHS4szRZAIR8R6GwA/xAujpdrXU5iyklrimWnLWU+BLF9suPTqg==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.5.0", + "core-js-compat": "^3.34.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, "node_modules/@babel/preset-env/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -2136,18 +2229,16 @@ } }, "node_modules/@babel/preset-modules": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", - "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", "@babel/types": "^7.4.4", "esutils": "^2.0.2" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" } }, "node_modules/@babel/preset-react": { @@ -2170,15 +2261,15 @@ } }, "node_modules/@babel/preset-typescript": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.22.5.tgz", - "integrity": "sha512-YbPaal9LxztSGhmndR46FmAbkJ/1fAsw293tSU+I5E5h+cnJ3d4GTwyUgGYmOXJYdGA+uNePle4qbaRzj2NISQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.23.3.tgz", + "integrity": "sha512-17oIGVlqz6CchO9RFYn5U6ZpWRZIngayYCtrPRSgANSwC2V1Jb+iP74nVxzzXJte8b8BYxrL1yY96xfhTBrNNQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.22.5", - "@babel/plugin-syntax-jsx": "^7.22.5", - "@babel/plugin-transform-modules-commonjs": "^7.22.5", - "@babel/plugin-transform-typescript": "^7.22.5" + "@babel/helper-validator-option": "^7.22.15", + "@babel/plugin-syntax-jsx": "^7.23.3", + "@babel/plugin-transform-modules-commonjs": "^7.23.3", + "@babel/plugin-transform-typescript": "^7.23.3" }, "engines": { "node": ">=6.9.0" @@ -2193,9 +2284,9 @@ "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" }, "node_modules/@babel/runtime": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz", - "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.1.tgz", + "integrity": "sha512-+BIznRzyqBf+2wCTxcKE3wDjfGeCoVE61KSHGpkzqrLi8qxqFwBeUFyId2cxkTmm55fzDGnm0+yCxaxygrLUnQ==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -2207,6 +2298,7 @@ "version": "7.22.6", "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.22.6.tgz", "integrity": "sha512-M+37LLIRBTEVjktoJjbw4KVhupF0U/3PYUCbBwgAd9k17hoKhRu1n935QiG7Tuxv0LJOMrb2vuKEeYUlv0iyiw==", + "dev": true, "dependencies": { "core-js-pure": "^3.30.2", "regenerator-runtime": "^0.13.11" @@ -2221,32 +2313,32 @@ "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" }, "node_modules/@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", + "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.22.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz", - "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==", - "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.7", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.0.tgz", + "integrity": "sha512-HfuJlI8qq3dEDmNU5ChzzpZRWq+oxCZQyMzIMEqLho+AQnhMnKQUzH6ydo3RBl/YjPCuk68Y6s0Gx0AeyULiWw==", + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/types": "^7.22.5", - "debug": "^4.1.0", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0", + "debug": "^4.3.1", "globals": "^11.1.0" }, "engines": { @@ -2254,12 +2346,12 @@ } }, "node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, "engines": { @@ -2271,22 +2363,6 @@ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" }, - "node_modules/@cnakazawa/watch": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.4.tgz", - "integrity": "sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ==", - "dev": true, - "dependencies": { - "exec-sh": "^0.3.2", - "minimist": "^1.2.0" - }, - "bin": { - "watch": "cli.js" - }, - "engines": { - "node": ">=0.1.95" - } - }, "node_modules/@csstools/normalize.css": { "version": "12.0.0", "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-12.0.0.tgz", @@ -2557,10 +2633,399 @@ "postcss-selector-parser": "^6.0.10" } }, - "node_modules/@emotion/babel-plugin": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", - "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", + "node_modules/@dicebear/adventurer": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/adventurer/-/adventurer-7.0.4.tgz", + "integrity": "sha512-1ya9lD0S8YHaW+1+bky9HCnLWve/gjiFtZ1wjEM26nBxrFBCmvgiqPn/+L/Uf0ercHIyXMRElHylWmLxtWztfQ==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@dicebear/core": "^7.0.0" + } + }, + "node_modules/@dicebear/adventurer-neutral": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/adventurer-neutral/-/adventurer-neutral-7.0.4.tgz", + "integrity": "sha512-meAMZFLzvqf58p8Qno4vKRmwss2XdKn5osG5/xPkiXVUVhtNEtVoKSIG0KK9ukjC18UOHo6mjZab7xUclz6o4Q==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@dicebear/core": "^7.0.0" + } + }, + "node_modules/@dicebear/avataaars": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/avataaars/-/avataaars-7.0.4.tgz", + "integrity": "sha512-mkQDtGYfj4rVguuPednpKj2RQWyV1pew3GqcKfjz77HBfhHeXDDwlMqWPQkaKyYkI0V9q3LtApGECyxYiisDvA==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@dicebear/core": "^7.0.0" + } + }, + "node_modules/@dicebear/avataaars-neutral": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/avataaars-neutral/-/avataaars-neutral-7.0.4.tgz", + "integrity": "sha512-EpbeiY23G4fuL2DnZ7fjnSn8WZvdALgg/N3pQpn8yPDdulgaV4vRDOit94pvp/DjW0Zz7mPPkSEN//0zijcXvA==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@dicebear/core": "^7.0.0" + } + }, + "node_modules/@dicebear/big-ears": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/big-ears/-/big-ears-7.0.4.tgz", + "integrity": "sha512-yOvIVFOB8Wv9ulSp6vIyEHiIHkishnLEuKIPAcgGScxjlbtcAo9OmeUsgSmM03wYsV62jInaiA4hAHRPfLYzfQ==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@dicebear/core": "^7.0.0" + } + }, + "node_modules/@dicebear/big-ears-neutral": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/big-ears-neutral/-/big-ears-neutral-7.0.4.tgz", + "integrity": "sha512-kxydevCihleTG5TnIh604i/zi+1MMvPuFuecattcUoa3NIPx4zi08j2zb7gwTUX54l49ENG1ZSO058S9c03yrA==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@dicebear/core": "^7.0.0" + } + }, + "node_modules/@dicebear/big-smile": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/big-smile/-/big-smile-7.0.4.tgz", + "integrity": "sha512-vHuedMXdK5RGhXDSCY+U9vDyfby20m3eteYSgEwLKmi3ZJBLXw2xAuAb8cGMPmK7zsyj4eH50r93hKcaTaOTag==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@dicebear/core": "^7.0.0" + } + }, + "node_modules/@dicebear/bottts": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/bottts/-/bottts-7.0.4.tgz", + "integrity": "sha512-Nni2Y5rL6+CJ8/Cij1lCvV/YhI+i3cy//nWQQGqmGTqlCGZdOziDGCWuf7Ufmv8081sbKWj++QOP+ueAX8E7ZA==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@dicebear/core": "^7.0.0" + } + }, + "node_modules/@dicebear/bottts-neutral": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/bottts-neutral/-/bottts-neutral-7.0.4.tgz", + "integrity": "sha512-C9McuZSdrMypTAOSsNJMgsbb2wylHbrvkPyksyouSgeIRrr3vdJFAsa+N1UfApNj4YdsznmoBIMl2XAGktTBAg==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@dicebear/core": "^7.0.0" + } + }, + "node_modules/@dicebear/collection": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/collection/-/collection-7.0.4.tgz", + "integrity": "sha512-5jXmitM/DGwmorp9hGh5coEhrMLsygEYNJiOf6eH0loVeXjI0/X3TEmQabtXzwp/nVhBGYyvuBmPIg50fnUhxQ==", + "dependencies": { + "@dicebear/adventurer": "7.0.4", + "@dicebear/adventurer-neutral": "7.0.4", + "@dicebear/avataaars": "7.0.4", + "@dicebear/avataaars-neutral": "7.0.4", + "@dicebear/big-ears": "7.0.4", + "@dicebear/big-ears-neutral": "7.0.4", + "@dicebear/big-smile": "7.0.4", + "@dicebear/bottts": "7.0.4", + "@dicebear/bottts-neutral": "7.0.4", + "@dicebear/croodles": "7.0.4", + "@dicebear/croodles-neutral": "7.0.4", + "@dicebear/fun-emoji": "7.0.4", + "@dicebear/icons": "7.0.4", + "@dicebear/identicon": "7.0.4", + "@dicebear/initials": "7.0.4", + "@dicebear/lorelei": "7.0.4", + "@dicebear/lorelei-neutral": "7.0.4", + "@dicebear/micah": "7.0.4", + "@dicebear/miniavs": "7.0.4", + "@dicebear/notionists": "7.0.4", + "@dicebear/notionists-neutral": "7.0.4", + "@dicebear/open-peeps": "7.0.4", + "@dicebear/personas": "7.0.4", + "@dicebear/pixel-art": "7.0.4", + "@dicebear/pixel-art-neutral": "7.0.4", + "@dicebear/rings": "7.0.4", + "@dicebear/shapes": "7.0.4", + "@dicebear/thumbs": "7.0.4" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@dicebear/core": "^7.0.0" + } + }, + "node_modules/@dicebear/converter": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/converter/-/converter-7.0.4.tgz", + "integrity": "sha512-oiA2Oc5izWf6ipPtHYCi2c9W565VzyryObtSL6xB36V9MHRD8wvH5mYr9AvbViDGEOOeNE3EtIELQIMdNtB7Rg==", + "dependencies": { + "@types/json-schema": "^7.0.11", + "tmp-promise": "^3.0.3" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@resvg/resvg-js": "^2.4.1", + "exiftool-vendored": "^23.0.0", + "sharp": "^0.32.6" + }, + "peerDependenciesMeta": { + "@resvg/resvg-js": { + "optional": true + }, + "exiftool-vendored": { + "optional": true + }, + "sharp": { + "optional": true + } + } + }, + "node_modules/@dicebear/core": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/core/-/core-7.0.4.tgz", + "integrity": "sha512-Xi8Au8K4pWj61jKMKqlhqmg83DvMAG6PfDuDbp7F75ZNvrGGh0BkJt9keSHe4WpHs+BbXDXSMOivSS10QB20fA==", + "dependencies": { + "@dicebear/converter": "7.0.4", + "@types/json-schema": "^7.0.11" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@dicebear/croodles": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/croodles/-/croodles-7.0.4.tgz", + "integrity": "sha512-PMe7W2IE8R9yqEXuccfEaTF0D+1VXrCXnShw52D5C23qPDTxL1XxZKXcOoeXYi5o1jeIVagZjHiX8XaQK18ftQ==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@dicebear/core": "^7.0.0" + } + }, + "node_modules/@dicebear/croodles-neutral": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/croodles-neutral/-/croodles-neutral-7.0.4.tgz", + "integrity": "sha512-b7v1WPEDKWzJAcCMo8OQMMgRTI0c2Ae3dCLBbFXtkhJ6oqzuFUbWwcrUWsp0segBXlPAM3lZrH1gy1GJBHrSuQ==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@dicebear/core": "^7.0.0" + } + }, + "node_modules/@dicebear/fun-emoji": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/fun-emoji/-/fun-emoji-7.0.4.tgz", + "integrity": "sha512-rlaID1EQW8pj/TmM805+dA6XVLge2hkiVaQkoM+4Df/RGj/GPbDeBgu8dRKLwORPNY5ug3zfFgERStZcSyYmqQ==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@dicebear/core": "^7.0.0" + } + }, + "node_modules/@dicebear/icons": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/icons/-/icons-7.0.4.tgz", + "integrity": "sha512-wkWjjkDD43lmYKgCBDdUc54y6llCsCOSPND2RnKi6noOGpThsN6aTE6nN2Hwf0ORxWPEzBFRmgoat+frWd9a4A==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@dicebear/core": "^7.0.0" + } + }, + "node_modules/@dicebear/identicon": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/identicon/-/identicon-7.0.4.tgz", + "integrity": "sha512-Q68lP7dqqt0fMx9SONPJSi94aieNveTyrCgv/kuU3F9upeQyesmdAeQ+e2QOojOOMrEuM+ujFuPInvwwkaZF7w==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@dicebear/core": "^7.0.0" + } + }, + "node_modules/@dicebear/initials": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/initials/-/initials-7.0.4.tgz", + "integrity": "sha512-cNkuG/3cPbF4UScmLk+2nYF2LaB9N1k3Pw1gmd3PST+oUsdlkNIM6e4Wym/0fgDLGPWyxbiGsbhe371ACWJVNQ==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@dicebear/core": "^7.0.0" + } + }, + "node_modules/@dicebear/lorelei": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/lorelei/-/lorelei-7.0.4.tgz", + "integrity": "sha512-pFDNHns7lke3M+TGPHFizjsjBMM/70okdH4Y+WKg9WHe+Y0dV54OgXf9/I6A10ipdVTCtM4i2xfNkSW+QP/spQ==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@dicebear/core": "^7.0.0" + } + }, + "node_modules/@dicebear/lorelei-neutral": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/lorelei-neutral/-/lorelei-neutral-7.0.4.tgz", + "integrity": "sha512-QtyKGJhExocZse662b1W5LGh0ykFh4AFf827f5FkXiOGmAgghsm1m/0bFuF9giwqFJ7W3eZu5oTSn97+s3z17A==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@dicebear/core": "^7.0.0" + } + }, + "node_modules/@dicebear/micah": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/micah/-/micah-7.0.4.tgz", + "integrity": "sha512-c6U9iqsEsuPqHxiZuM5O7xqJIv98rIMergdi6O8jlINXacNLzF9DUHLAkxMiFeiqDDqQ34wUQq+M6qt9xBq0eQ==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@dicebear/core": "^7.0.0" + } + }, + "node_modules/@dicebear/miniavs": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/miniavs/-/miniavs-7.0.4.tgz", + "integrity": "sha512-p1sWveGT3gvtnwplhDakB6wEu5jT/EHbRzsTMOT3Lz9nqkF08sJCe7KCRsji1EVGyX4nOjA+dQcHK9yUAdqQAg==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@dicebear/core": "^7.0.0" + } + }, + "node_modules/@dicebear/notionists": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/notionists/-/notionists-7.0.4.tgz", + "integrity": "sha512-twmpHy2S6FkTiPzNd0wXuWhBv0XgkCPIuzJiUeyTadVEjlijOvPeAr9kuGuhDMO7MTHnuQoFRw1sctQmj+xbXA==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@dicebear/core": "^7.0.0" + } + }, + "node_modules/@dicebear/notionists-neutral": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/notionists-neutral/-/notionists-neutral-7.0.4.tgz", + "integrity": "sha512-tk06h7uj1IR42g/RhhLVv1rbxy+rNROhXSto5ADX0/Ovk+HaR8yQGQyO3Tt/rXpGuf5+5JK0sVAiRgGaMFSxig==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@dicebear/core": "^7.0.0" + } + }, + "node_modules/@dicebear/open-peeps": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/open-peeps/-/open-peeps-7.0.4.tgz", + "integrity": "sha512-c4oMnOvzLiMXoj+oBKILzF0DRWRd3I/ykBC7zhr3904R/dp6PXQnMDiMFIjCYeifCl8W30ggTzvNEX7nwbxJaQ==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@dicebear/core": "^7.0.0" + } + }, + "node_modules/@dicebear/personas": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/personas/-/personas-7.0.4.tgz", + "integrity": "sha512-gbWqNakXeWSKjW4s4zw4dSmuHOGF9+tgwzjwilrQvZMODOESYUCKPql/3KFJLVG9Rr00BH83QGZEn6vYiBLbVg==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@dicebear/core": "^7.0.0" + } + }, + "node_modules/@dicebear/pixel-art": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/pixel-art/-/pixel-art-7.0.4.tgz", + "integrity": "sha512-H0OZ7JyLyiBYOa9NJI6yr1x/XjXl4P17U8lvRuQhCYHntdgDvuIwv1/kulq4vLBGRK1afXBTm/NPWi0Optyg/Q==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@dicebear/core": "^7.0.0" + } + }, + "node_modules/@dicebear/pixel-art-neutral": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/pixel-art-neutral/-/pixel-art-neutral-7.0.4.tgz", + "integrity": "sha512-4hzHw7I4f4bj4C7L2xQ28oA7XS1uonwGE7jTCqjRzg3YkzjTthxf7kEE/WWiP0Lk1onPhSdB8kqDejPGvNUXLQ==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@dicebear/core": "^7.0.0" + } + }, + "node_modules/@dicebear/rings": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/rings/-/rings-7.0.4.tgz", + "integrity": "sha512-LJzSWronkeWefFLwaOWg3tr0jSOuW2hien4Uv+nG2alYSkJ6hGH4zLtGo/SRQdNWQg4j/6838fWJDdoryWQM2w==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@dicebear/core": "^7.0.0" + } + }, + "node_modules/@dicebear/shapes": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/shapes/-/shapes-7.0.4.tgz", + "integrity": "sha512-C1OhdAGwCmEK9JDjK9wERBxaZIOp2x4yWVsra/VCfba+fJSKmmorhbYIw33vE5ZV3/PseztnDB3sWOMMl/jCdw==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@dicebear/core": "^7.0.0" + } + }, + "node_modules/@dicebear/thumbs": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@dicebear/thumbs/-/thumbs-7.0.4.tgz", + "integrity": "sha512-mAOWbaNtWKLIHGtTZxHVei1UFWz/l0h4aP8h97UE71av2QTM7CEw2RpF8Q19MxxoDlHi+oZ7Jvjblzi5k96LtA==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@dicebear/core": "^7.0.0" + } + }, + "node_modules/@emotion/babel-plugin": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", + "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", "dependencies": { "@babel/helper-module-imports": "^7.16.7", "@babel/runtime": "^7.18.3", @@ -2690,6 +3155,22 @@ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" }, + "node_modules/@esbuild/linux-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -2734,6 +3215,21 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/@eslint/eslintrc/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -2764,6 +3260,11 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, "node_modules/@eslint/eslintrc/node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -2817,59 +3318,12 @@ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.6.tgz", "integrity": "sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==" }, - "node_modules/@fortawesome/fontawesome-common-types": { - "version": "0.2.36", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz", - "integrity": "sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg==", - "dev": true, - "hasInstallScript": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@fortawesome/fontawesome-svg-core": { - "version": "1.2.36", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.36.tgz", - "integrity": "sha512-YUcsLQKYb6DmaJjIHdDWpBIGCcyE/W+p/LMGvjQem55Mm2XWVAP5kWTMKWLv9lwpCVjpLxPyOMOyUocP1GxrtA==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@fortawesome/fontawesome-common-types": "^0.2.36" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@fortawesome/free-brands-svg-icons": { - "version": "5.15.4", - "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-5.15.4.tgz", - "integrity": "sha512-f1witbwycL9cTENJegcmcZRYyawAFbm8+c6IirLmwbbpqz46wyjbQYLuxOc7weXFXfB7QR8/Vd2u5R3q6JYD9g==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@fortawesome/fontawesome-common-types": "^0.2.36" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@fortawesome/react-fontawesome": { - "version": "0.1.19", - "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.19.tgz", - "integrity": "sha512-Hyb+lB8T18cvLNX0S3llz7PcSOAJMLwiVKBuuzwM/nI5uoBw+gQjnf9il0fR1C3DKOI5Kc79pkJ4/xB0Uw9aFQ==", - "dev": true, - "dependencies": { - "prop-types": "^15.8.1" - }, - "peerDependencies": { - "@fortawesome/fontawesome-svg-core": "~1 || ~6", - "react": ">=16.x" - } - }, "node_modules/@gar/promisify": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==" + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "optional": true, + "peer": true }, "node_modules/@graphql-typed-document-node/core": { "version": "3.2.0", @@ -3347,10 +3801,63 @@ "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" }, - "node_modules/@mui/base": { - "version": "5.0.0-beta.17", - "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.17.tgz", - "integrity": "sha512-xNbk7iOXrglNdIxFBN0k3ySsPIFLWCnFxqsAYl7CIcDkD9low4kJ7IUuy6ctwx/HAy2fenrT3KXHr1sGjAMgpQ==", + "node_modules/@microsoft/tsdoc": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz", + "integrity": "sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==", + "dev": true + }, + "node_modules/@microsoft/tsdoc-config": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.16.2.tgz", + "integrity": "sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==", + "dev": true, + "dependencies": { + "@microsoft/tsdoc": "0.14.2", + "ajv": "~6.12.6", + "jju": "~1.4.0", + "resolve": "~1.19.0" + } + }, + "node_modules/@microsoft/tsdoc-config/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@microsoft/tsdoc-config/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@microsoft/tsdoc-config/node_modules/resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "dependencies": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/@mui/base": { + "version": "5.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.17.tgz", + "integrity": "sha512-xNbk7iOXrglNdIxFBN0k3ySsPIFLWCnFxqsAYl7CIcDkD9low4kJ7IUuy6ctwx/HAy2fenrT3KXHr1sGjAMgpQ==", "dependencies": { "@babel/runtime": "^7.22.15", "@floating-ui/react-dom": "^2.0.2", @@ -3473,12 +3980,12 @@ } }, "node_modules/@mui/private-theming": { - "version": "5.14.15", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.14.15.tgz", - "integrity": "sha512-V2Xh+Tu6A07NoSpup0P9m29GwvNMYl5DegsGWqlOTJyAV7cuuVjmVPqxgvL8xBng4R85xqIQJRMjtYYktoPNuQ==", + "version": "5.15.14", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.14.tgz", + "integrity": "sha512-UH0EiZckOWcxiXLX3Jbb0K7rC8mxTr9L9l6QhOZxYc4r8FHUkefltV9VDGLrzCaWh30SQiJvAEd7djX3XXY6Xw==", "dependencies": { - "@babel/runtime": "^7.23.2", - "@mui/utils": "^5.14.15", + "@babel/runtime": "^7.23.9", + "@mui/utils": "^5.15.14", "prop-types": "^15.8.1" }, "engines": { @@ -3486,7 +3993,7 @@ }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0", @@ -3590,12 +4097,12 @@ } }, "node_modules/@mui/utils": { - "version": "5.14.15", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.14.15.tgz", - "integrity": "sha512-QBfHovAvTa0J1jXuYDaXGk+Yyp7+Fm8GSqx6nK2JbezGqzCFfirNdop/+bL9Flh/OQ/64PeXcW4HGDdOge+n3A==", + "version": "5.15.14", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.14.tgz", + "integrity": "sha512-0lF/7Hh/ezDv5X7Pry6enMsbYyGKjADzvHyo3Qrc/SSlTsQ1VkbDMbH0m2t3OR5iIVLwMoxwM7yGd+6FCMtTFA==", "dependencies": { - "@babel/runtime": "^7.23.2", - "@types/prop-types": "^15.7.8", + "@babel/runtime": "^7.23.9", + "@types/prop-types": "^15.7.11", "prop-types": "^15.8.1", "react-is": "^18.2.0" }, @@ -3604,7 +4111,7 @@ }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0", @@ -3755,14 +4262,6 @@ "eslint-scope": "5.1.1" } }, - "node_modules/@nicolo-ribaudo/semver-v6": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/semver-v6/-/semver-v6-6.3.3.tgz", - "integrity": "sha512-3Yc1fUTs69MG/uZbJlLSI3JISMn2UV2rg+1D/vROUqZyh3l6iYHCs7GMp+M40ZD7yOdDbYjJcU1oTJhrc+dGKg==", - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -3795,31 +4294,6 @@ "node": ">= 8" } }, - "node_modules/@npmcli/fs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", - "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", - "dependencies": { - "@gar/promisify": "^1.1.3", - "semver": "^7.3.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/@npmcli/move-file": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", - "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", - "deprecated": "This functionality has been moved to @npmcli/fs", - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "node_modules/@pdf-lib/standard-fonts": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz", @@ -3880,6 +4354,18 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/@pmmmwh/react-refresh-webpack-plugin": { "version": "0.5.10", "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.10.tgz", @@ -4041,6 +4527,14 @@ "tslib": "^2.4.0" } }, + "node_modules/@remix-run/router": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.2.tgz", + "integrity": "sha512-+Rnav+CaoTE5QJc4Jcwh5toUpnVLKYbpU6Ys0zqbakqbaLQHeglLVHPfxOiQqdNmUy5C2lXz5dwC6tQNX2JW2Q==", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@restart/hooks": { "version": "0.4.10", "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.10.tgz", @@ -4680,6 +5174,7 @@ "version": "7.31.2", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.31.2.tgz", "integrity": "sha512-3UqjCpey6HiTZT92vODYLPxTBWlM8ZOOjr3LX5F37/VRipW2M1kX6I/Cm4VXzteZqfGfagg8yXywpcOgQBlNsQ==", + "dev": true, "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", @@ -4698,6 +5193,7 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", + "dev": true, "dependencies": { "@babel/runtime": "^7.10.2", "@babel/runtime-corejs3": "^7.10.2" @@ -4710,6 +5206,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -4725,6 +5222,7 @@ "version": "5.16.5", "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz", "integrity": "sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA==", + "dev": true, "dependencies": { "@adobe/css-tools": "^4.0.1", "@babel/runtime": "^7.9.2", @@ -4746,6 +5244,7 @@ "version": "11.2.7", "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-11.2.7.tgz", "integrity": "sha512-tzRNp7pzd5QmbtXNG/mhdcl7Awfu/Iz1RaVHY75zTdOkmHCuzMhRL83gWHSgOAcjS3CCbyfwUHMZgRJb4kAfpA==", + "dev": true, "dependencies": { "@babel/runtime": "^7.12.5", "@testing-library/dom": "^7.28.1" @@ -4762,6 +5261,7 @@ "version": "12.8.3", "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-12.8.3.tgz", "integrity": "sha512-IR0iWbFkgd56Bu5ZI/ej8yQwrkCv8Qydx6RzwbKz9faXazR/+5tvYKsZQgyXJiwgpcva127YO6JcWy7YlCfofQ==", + "dev": true, "dependencies": { "@babel/runtime": "^7.12.5" }, @@ -4792,7 +5292,8 @@ "node_modules/@types/aria-query": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz", - "integrity": "sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==" + "integrity": "sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==", + "dev": true }, "node_modules/@types/babel__core": { "version": "7.20.1", @@ -4848,14 +5349,6 @@ "@types/node": "*" } }, - "node_modules/@types/cheerio": { - "version": "0.22.31", - "resolved": "https://registry.npmjs.org/@types/cheerio/-/cheerio-0.22.31.tgz", - "integrity": "sha512-Kt7Cdjjdi2XWSfrZ53v4Of0wG3ZcmaegFXjMmz9tfNrZSkzzo36G0AL1YqSdcIA78Etjt6E609pt5h1xnQkPUw==", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/connect": { "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", @@ -4873,33 +5366,6 @@ "@types/node": "*" } }, - "node_modules/@types/enzyme": { - "version": "3.10.13", - "resolved": "https://registry.npmjs.org/@types/enzyme/-/enzyme-3.10.13.tgz", - "integrity": "sha512-FCtoUhmFsud0Yx9fmZk179GkdZ4U9B0GFte64/Md+W/agx0L5SxsIIbhLBOxIb9y2UfBA4WQnaG1Od/UsUQs9Q==", - "dependencies": { - "@types/cheerio": "*", - "@types/react": "^16" - } - }, - "node_modules/@types/enzyme-adapter-react-16": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.0.6.tgz", - "integrity": "sha512-VonDkZ15jzqDWL8mPFIQnnLtjwebuL9YnDkqeCDYnB4IVgwUm0mwKkqhrxLL6mb05xm7qqa3IE95m8CZE9imCg==", - "dependencies": { - "@types/enzyme": "*" - } - }, - "node_modules/@types/enzyme/node_modules/@types/react": { - "version": "16.14.43", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.43.tgz", - "integrity": "sha512-7zdjv7jvoLLQg1tTvpQsm+hyNUMT2mPlNV1+d0I8fbGhkJl82spopMyBlu4wb1dviZAxpGdk5eHu/muacknnfw==", - "dependencies": { - "@types/prop-types": "*", - "@types/scheduler": "*", - "csstype": "^3.0.2" - } - }, "node_modules/@types/eslint": { "version": "8.44.0", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.0.tgz", @@ -4986,6 +5452,16 @@ "@types/node": "*" } }, + "node_modules/@types/inquirer": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-9.0.7.tgz", + "integrity": "sha512-Q0zyBupO6NxGRZut/JdmqYKOnN95Eg5V8Csg3PGKkP+FnvsUZx1jAyK7fztIszxxMuoBA6E3KXWvdZVXIpx60g==", + "dev": true, + "dependencies": { + "@types/through": "*", + "rxjs": "^7.2.0" + } + }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", @@ -5011,19 +5487,12 @@ "version": "26.0.24", "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.24.tgz", "integrity": "sha512-E/X5Vib8BWqZNRlDxj9vYXhsDwPYbPINqKF9BsnSoon4RQ0D9moEuLD8txgyypFLH7J4+Lho9Nr/c8H0Fi+17w==", + "dev": true, "dependencies": { "jest-diff": "^26.0.0", "pretty-format": "^26.0.0" } }, - "node_modules/@types/jquery": { - "version": "3.5.16", - "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.16.tgz", - "integrity": "sha512-bsI7y4ZgeMkmpG9OM710RRzDFp+w4P1RGiIt30C1mSBT+ExCleeh4HObwgArnDFELmRrOpXgSYN9VF1hj+f1lw==", - "dependencies": { - "@types/sizzle": "*" - } - }, "node_modules/@types/js-cookie": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.3.tgz", @@ -5040,19 +5509,6 @@ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" }, - "node_modules/@types/lodash": { - "version": "4.14.195", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.195.tgz", - "integrity": "sha512-Hwx9EUgdwf2GLarOjQp5ZH8ZmblzcbTBC2wtQWNKARBSxM9ezRIAUpeDTgoQRAFB0+8CNWXVA9+MaSOzOF3nPg==" - }, - "node_modules/@types/lodash.memoize": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@types/lodash.memoize/-/lodash.memoize-4.1.7.tgz", - "integrity": "sha512-lGN7WeO4vO6sICVpf041Q7BX/9k1Y24Zo3FY0aUezr1QlKznpjzsDk3T3wvH8ofYzoK0QupN9TWcFAFZlyPwQQ==", - "dependencies": { - "@types/lodash": "*" - } - }, "node_modules/@types/mime": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", @@ -5061,17 +5517,45 @@ "node_modules/@types/minimist": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==" + "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", + "optional": true, + "peer": true }, "node_modules/@types/node": { "version": "12.20.55", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==" }, + "node_modules/@types/node-fetch": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", + "dev": true, + "dependencies": { + "@types/node": "*", + "form-data": "^4.0.0" + } + }, + "node_modules/@types/node-fetch/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/@types/normalize-package-data": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==" + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "optional": true, + "peer": true }, "node_modules/@types/parse-json": { "version": "4.0.0", @@ -5084,9 +5568,9 @@ "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==" }, "node_modules/@types/prop-types": { - "version": "15.7.9", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.9.tgz", - "integrity": "sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g==" + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" }, "node_modules/@types/q": { "version": "1.5.5", @@ -5117,6 +5601,7 @@ "version": "0.32.32", "resolved": "https://registry.npmjs.org/@types/react-bootstrap/-/react-bootstrap-0.32.32.tgz", "integrity": "sha512-GM9UtV7v+C2F0rbqgIpMWdCKBMdX3PQURoJQobPO4vDAeFadcExNtKffi13/MjaAks+riJKVGyiMe+6OmDYT2w==", + "dev": true, "dependencies": { "@types/react": "*" } @@ -5125,6 +5610,7 @@ "version": "4.11.2", "resolved": "https://registry.npmjs.org/@types/react-datepicker/-/react-datepicker-4.11.2.tgz", "integrity": "sha512-ELYyX3lb3K1WltqdlF1hbnaDGgzlF6PIR5T4W38cSEcfrQDIrPE+Ioq5pwRe/KEJ+ihHMjvTVZQkwJx0pWMNHQ==", + "dev": true, "dependencies": { "@popperjs/core": "^2.9.2", "@types/react": "*", @@ -5136,6 +5622,7 @@ "version": "17.0.20", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.20.tgz", "integrity": "sha512-4pzIjSxDueZZ90F52mU3aPoogkHIoSIDG+oQ+wQK7Cy2B9S+MvOqY0uEA/qawKz381qrEDkvpwyt8Bm31I8sbA==", + "dev": true, "dependencies": { "@types/react": "^17" } @@ -5144,14 +5631,7 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@types/react-google-recaptcha/-/react-google-recaptcha-2.1.5.tgz", "integrity": "sha512-iWTjmVttlNgp0teyh7eBXqNOQzVq2RWNiFROWjraOptRnb1OcHJehQnji0sjqIRAk9K0z8stjyhU+OLpPb0N6w==", - "dependencies": { - "@types/react": "*" - } - }, - "node_modules/@types/react-modal": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/@types/react-modal/-/react-modal-3.16.0.tgz", - "integrity": "sha512-iphdqXAyUfByLbxJn5j6d+yh93dbMgshqGP0IuBeaKbZXx0aO+OXsvEkt6QctRdxjeM9/bR+Gp3h9F9djVWTQQ==", + "dev": true, "dependencies": { "@types/react": "*" } @@ -5209,6 +5689,15 @@ "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" }, + "node_modules/@types/sanitize-html": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@types/sanitize-html/-/sanitize-html-2.11.0.tgz", + "integrity": "sha512-7oxPGNQHXLHE48r/r/qjn7q0hlrs3kL7oZnGj0Wf/h9tj/6ibFyRkNbsDxaBBZ4XUZ0Dx5LGCyDJ04ytSofacQ==", + "dev": true, + "dependencies": { + "htmlparser2": "^8.0.0" + } + }, "node_modules/@types/scheduler": { "version": "0.16.3", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", @@ -5246,11 +5735,6 @@ "@types/node": "*" } }, - "node_modules/@types/sizzle": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", - "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==" - }, "node_modules/@types/sockjs": { "version": "0.3.33", "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", @@ -5268,10 +5752,20 @@ "version": "5.14.8", "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.8.tgz", "integrity": "sha512-NRfJE9Cgpmu4fx716q9SYmU4jxxhYRU1BQo239Txt/9N3EC745XZX1Yl7h/SBIDlo1ANVOCRB4YDXjaQdoKCHQ==", + "dev": true, "dependencies": { "@types/jest": "*" } }, + "node_modules/@types/through": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.33.tgz", + "integrity": "sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/trusted-types": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.3.tgz", @@ -5632,60 +6126,6 @@ "@xtuc/long": "4.2.2" } }, - "node_modules/@wojtekmaj/date-utils": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@wojtekmaj/date-utils/-/date-utils-1.4.1.tgz", - "integrity": "sha512-Fjs0KJz0//0AmlJVFx9AQmWpmxOTw4foDo4DKoswWVVjHsna4rdu+fXwid5YHNgzv/wHi9AkZCRPmHWsf890lg==", - "funding": { - "url": "https://github.com/wojtekmaj/date-utils?sponsor=1" - } - }, - "node_modules/@wojtekmaj/enzyme-adapter-react-17": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@wojtekmaj/enzyme-adapter-react-17/-/enzyme-adapter-react-17-0.8.0.tgz", - "integrity": "sha512-zeUGfQRziXW7R7skzNuJyi01ZwuKCH8WiBNnTgUJwdS/CURrJwAhWsfW7nG7E30ak8Pu3ZwD9PlK9skBfAoOBw==", - "dev": true, - "dependencies": { - "@wojtekmaj/enzyme-adapter-utils": "^0.2.0", - "enzyme-shallow-equal": "^1.0.0", - "has": "^1.0.0", - "prop-types": "^15.7.0", - "react-is": "^17.0.0", - "react-test-renderer": "^17.0.0" - }, - "funding": { - "url": "https://github.com/wojtekmaj/enzyme-adapter-react-17?sponsor=1" - }, - "peerDependencies": { - "enzyme": "^3.0.0", - "react": "^17.0.0-0", - "react-dom": "^17.0.0-0" - } - }, - "node_modules/@wojtekmaj/enzyme-adapter-react-17/node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - }, - "node_modules/@wojtekmaj/enzyme-adapter-utils": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@wojtekmaj/enzyme-adapter-utils/-/enzyme-adapter-utils-0.2.0.tgz", - "integrity": "sha512-ZvZm9kZxZEKAbw+M1/Q3iDuqQndVoN8uLnxZ8bzxm7KgGTBejrGRoJAp8f1EN8eoO3iAjBNEQnTDW/H4Ekb0FQ==", - "dev": true, - "dependencies": { - "function.prototype.name": "^1.1.0", - "has": "^1.0.0", - "object.fromentries": "^2.0.0", - "prop-types": "^15.7.0" - }, - "funding": { - "url": "https://github.com/wojtekmaj/enzyme-adapter-utils?sponsor=1" - }, - "peerDependencies": { - "react": "^17.0.0-0" - } - }, "node_modules/@wry/context": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/@wry/context/-/context-0.7.3.tgz", @@ -5737,7 +6177,9 @@ "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "optional": true, + "peer": true }, "node_modules/accepts": { "version": "1.3.8", @@ -5854,6 +6296,8 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.3.0.tgz", "integrity": "sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==", + "optional": true, + "peer": true, "dependencies": { "debug": "^4.1.0", "depd": "^2.0.0", @@ -5867,6 +6311,8 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "optional": true, + "peer": true, "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" @@ -5875,41 +6321,14 @@ "node": ">=8" } }, - "node_modules/airbnb-prop-types": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/airbnb-prop-types/-/airbnb-prop-types-2.16.0.tgz", - "integrity": "sha512-7WHOFolP/6cS96PhKNrslCLMYAI8yB1Pp6u6XmxozQOiZbsI5ycglZr5cHhBFfuRcQQjzCMith5ZPZdYiJCxUg==", - "dependencies": { - "array.prototype.find": "^2.1.1", - "function.prototype.name": "^1.1.2", - "is-regex": "^1.1.0", - "object-is": "^1.1.2", - "object.assign": "^4.1.0", - "object.entries": "^1.1.2", - "prop-types": "^15.7.2", - "prop-types-exact": "^1.2.0", - "react-is": "^16.13.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - }, - "peerDependencies": { - "react": "^0.14 || ^15.0.0 || ^16.0.0-alpha" - } - }, - "node_modules/airbnb-prop-types/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dependencies": { "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", "uri-js": "^4.2.2" }, "funding": { @@ -5933,34 +6352,6 @@ } } }, - "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "peerDependencies": { - "ajv": "^6.9.1" - } - }, "node_modules/ansi-align": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", @@ -5995,6 +6386,17 @@ "ansi-html": "bin/ansi-html" } }, + "node_modules/ansi-red": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", + "integrity": "sha512-ewaIr5y+9CUTGFwZfpECUbFlGcC0GCw1oqR9RI6h1gQCd9Aj2GxSckCnPsVJnmfMZbwFYE+leZGASgkWl06Jow==", + "dependencies": { + "ansi-wrap": "0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -6006,7 +6408,8 @@ "node_modules/ansi-sequence-parser": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz", - "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==" + "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==", + "peer": true }, "node_modules/ansi-styles": { "version": "4.3.0", @@ -6022,6 +6425,14 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha512-ZyznvL8k/FZeQHr2T6LzcJ/+vBApDnMNZvfVFy3At0knswWd6rJ3/0Hhmpu8oqa6C92npmozs890sX9Dl6q+Qw==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", @@ -6042,12 +6453,16 @@ "node_modules/aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "optional": true, + "peer": true }, "node_modules/are-we-there-yet": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "optional": true, + "peer": true, "dependencies": { "delegates": "^1.0.0", "readable-stream": "^3.6.0" @@ -6077,65 +6492,35 @@ "dequal": "^2.0.3" } }, - "node_modules/arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", - "dev": true, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", - "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", - "integrity": "sha512-H3LU5RLiSsGXPhN+Nipar0iR0IofH+8r89G2y1tBKxQ/agagKyAjhkAFDRBfodP2caPrNKHpAWNIM/c9yeL7uA==", - "dev": true - }, "node_modules/array-flatten": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" }, "node_modules/array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", + "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", "is-string": "^1.0.7" }, "engines": { @@ -6153,25 +6538,17 @@ "node": ">=8" } }, - "node_modules/array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array.prototype.filter": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.2.tgz", - "integrity": "sha512-us+UrmGOilqttSOgoWZTpOvHu68vZT2YCjc/H4vhu56vzZpaDFBhB+Se2UwqWzMKbDv7Myq5M5pcZLAtUvTQdQ==", + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.7" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -6180,28 +6557,32 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.find": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.2.1.tgz", - "integrity": "sha512-I2ri5Z9uMpMvnsNrHre9l3PaX+z9D0/z6F7Yt2u15q7wt0I62g5kX6xUKR1SJiefgG+u2/gJUmM8B47XRvQR6w==", + "node_modules/array.prototype.findlastindex": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", + "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", "es-shim-unscopables": "^1.0.0" }, "engines": { @@ -6212,13 +6593,13 @@ } }, "node_modules/array.prototype.flatmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", "es-shim-unscopables": "^1.0.0" }, "engines": { @@ -6246,22 +6627,56 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz", - "integrity": "sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==", + "node_modules/array.prototype.toreversed": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", + "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.1.3" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz", + "integrity": "sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==", + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.1.0", + "es-shim-unscopables": "^1.0.2" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -6275,7 +6690,8 @@ "version": "0.2.6", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dev": true, + "optional": true, + "peer": true, "dependencies": { "safer-buffer": "~2.1.0" } @@ -6284,20 +6700,12 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=0.8" } }, - "node_modules/assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/ast-types-flow": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", @@ -6312,16 +6720,12 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", "integrity": "sha512-VUeSMD8nEGBWaZK4lizI1sf3yEC7pnAQ/mrI7pC2fBz2s/tq5jWWEngTwaf0Gruu/OoXRGLGg1XFqpYBiGTYJA==", + "optional": true, + "peer": true, "engines": { "node": "*" } }, - "node_modules/async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", - "dev": true - }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -6346,6 +6750,14 @@ "node": ">= 4.5.0" } }, + "node_modules/autolinker": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/autolinker/-/autolinker-0.28.1.tgz", + "integrity": "sha512-zQAFO1Dlsn69eXaO6+7YZc+v84aquQKbwpzCE3L0stj56ERn9hutFxPopViLjo9G+rWwjozRhgS5KJ25Xy19cQ==", + "dependencies": { + "gulp-header": "^1.7.1" + } + }, "node_modules/autoprefixer": { "version": "10.4.14", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz", @@ -6379,9 +6791,12 @@ } }, "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -6393,7 +6808,8 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", - "dev": true, + "optional": true, + "peer": true, "engines": { "node": "*" } @@ -6402,7 +6818,8 @@ "version": "1.12.0", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", - "dev": true + "optional": true, + "peer": true }, "node_modules/axe-core": { "version": "4.7.2", @@ -6420,42 +6837,6 @@ "dequal": "^2.0.3" } }, - "node_modules/babel-jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", - "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", - "dependencies": { - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^27.5.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" - } - }, - "node_modules/babel-jest/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/babel-loader": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.3.0.tgz", @@ -6474,6 +6855,34 @@ "webpack": ">=2" } }, + "node_modules/babel-loader/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/babel-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/babel-loader/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, "node_modules/babel-loader/node_modules/loader-utils": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", @@ -6519,20 +6928,6 @@ "node": ">=8" } }, - "node_modules/babel-plugin-jest-hoist": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", - "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.0.0", - "@types/babel__traverse": "^7.0.6" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, "node_modules/babel-plugin-macros": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", @@ -6556,16 +6951,39 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.4.tgz", - "integrity": "sha512-9WeK9snM1BfxB38goUEv2FLnA6ja07UMfazFHzCXUb3NyDZAwfXvQiURQ6guTTMeHcOsdknULm1PDhs4uWtKyA==", + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.8.tgz", + "integrity": "sha512-OtIuQfafSzpo/LhnJaykc0R/MMnuLSSVjVYy9mHArIZ9qTCSZ6TpWCuEKZYVoN//t8HqBNScHrOtCrIK5IaGLg==", "dependencies": { "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.4.1", - "@nicolo-ribaudo/semver-v6": "^6.3.3" + "@babel/helper-define-polyfill-provider": "^0.5.0", + "semver": "^6.3.1" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", + "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" } }, "node_modules/babel-plugin-polyfill-corejs3": { @@ -6581,14 +6999,29 @@ } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.1.tgz", - "integrity": "sha512-L8OyySuI6OSQ5hFy9O+7zFjyr4WhAfRjLIOkhQGYl+emwJkd/S4XXT1JpfrgR1jrQ1NcGiOh+yAdGlF8pnC3Jw==", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.5.tgz", + "integrity": "sha512-OJGYZlhLqBh2DDHeqAxWB1XIvr49CxiJ2gIt61/PU55CQK4Z58OzMqjDe1zwQdQk+rBYsRc+1rJmdajM3gimHg==", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.4.1" + "@babel/helper-define-polyfill-provider": "^0.5.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator/node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", + "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-transform-react-remove-prop-types": { @@ -6618,21 +7051,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/babel-preset-jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", - "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", - "dependencies": { - "babel-plugin-jest-hoist": "^27.5.1", - "babel-preset-current-node-syntax": "^1.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, "node_modules/babel-preset-react-app": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/babel-preset-react-app/-/babel-preset-react-app-10.0.1.tgz", @@ -6661,36 +7079,6 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, - "node_modules/base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "dependencies": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -6719,7 +7107,8 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "dev": true, + "optional": true, + "peer": true, "dependencies": { "tweetnacl": "^0.14.3" } @@ -6754,19 +7143,42 @@ "node": ">=8" } }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "dependencies": { - "file-uri-to-path": "1.0.0" + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" } }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "node_modules/bl/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "node_modules/body-parser": { @@ -6965,9 +7377,9 @@ "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==" }, "node_modules/browserslist": { - "version": "4.21.9", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz", - "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==", + "version": "4.22.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz", + "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==", "funding": [ { "type": "opencollective", @@ -6983,10 +7395,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001503", - "electron-to-chromium": "^1.4.431", - "node-releases": "^2.0.12", - "update-browserslist-db": "^1.0.11" + "caniuse-lite": "^1.0.30001580", + "electron-to-chromium": "^1.4.648", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" }, "bin": { "browserslist": "cli.js" @@ -7058,99 +7470,6 @@ "node": ">= 0.8" } }, - "node_modules/cacache": { - "version": "16.1.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", - "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", - "dependencies": { - "@npmcli/fs": "^2.1.0", - "@npmcli/move-file": "^2.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "infer-owner": "^1.0.4", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11", - "unique-filename": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/cacache/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/cacache/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/cacache/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "engines": { - "node": ">=12" - } - }, - "node_modules/cacache/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "dependencies": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/cacheable-request": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", @@ -7203,12 +7522,18 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7251,6 +7576,8 @@ "version": "6.2.2", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "optional": true, + "peer": true, "dependencies": { "camelcase": "^5.3.1", "map-obj": "^4.0.0", @@ -7275,9 +7602,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001516", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001516.tgz", - "integrity": "sha512-Wmec9pCBY8CWbmI4HsjBeQLqDTqV91nFVR83DnZpYyRnPI1wePDsTg0bGLPC5VU/3OIZV1fmxEea1b+tFKe86g==", + "version": "1.0.30001587", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001587.tgz", + "integrity": "sha512-HMFNotUmLXn71BQxg8cijvqxnIAofforZOwGsxyXJ0qugTdspUF4sPSJ2vhgprHCB996tIDzEq1ubumPDV8ULA==", "funding": [ { "type": "opencollective", @@ -7293,18 +7620,6 @@ } ] }, - "node_modules/capture-exit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", - "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", - "dev": true, - "dependencies": { - "rsvp": "^4.8.4" - }, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, "node_modules/case-sensitive-paths-webpack-plugin": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", @@ -7317,12 +7632,14 @@ "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", - "dev": true + "optional": true, + "peer": true }, "node_modules/chalk": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -7339,47 +7656,16 @@ "node": ">=10" } }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + }, "node_modules/check-types": { "version": "11.2.2", "resolved": "https://registry.npmjs.org/check-types/-/check-types-11.2.2.tgz", "integrity": "sha512-HBiYvXvn9Z70Z88XKjz3AEKd4HJhBXsa3j7xFnITAzoS8+q6eIGi8qDB8FKPBAjtuxjI/zFpwuiCb8oDtKOYrA==" }, - "node_modules/cheerio": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", - "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", - "dependencies": { - "cheerio-select": "^2.1.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "htmlparser2": "^8.0.1", - "parse5": "^7.0.0", - "parse5-htmlparser2-tree-adapter": "^7.0.0" - }, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" - } - }, - "node_modules/cheerio-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", - "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", - "dependencies": { - "boolbase": "^1.0.0", - "css-select": "^5.1.0", - "css-what": "^6.1.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -7410,6 +7696,8 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "optional": true, + "peer": true, "engines": { "node": ">=10" } @@ -7436,157 +7724,155 @@ "node": ">=8" } }, - "node_modules/circular-json-es6": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/circular-json-es6/-/circular-json-es6-2.0.2.tgz", - "integrity": "sha512-ODYONMMNb3p658Zv+Pp+/XPa5s6q7afhz3Tzyvo+VRh9WIrJ64J76ZC4GQxnlye/NesTn09jvOiuE8+xxfpwhQ==", - "dev": true - }, "node_modules/cjs-module-lexer": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==" }, - "node_modules/class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, + "node_modules/classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + }, + "node_modules/clean-css": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.2.tgz", + "integrity": "sha512-JVJbM+f3d3Q704rF4bqQ5UUyTtuJ0JRKNbTKVEeujCCBoMdkEi+V+e8oktO9qGQNSvHrFTM6JZRXrUvGR1czww==", "dependencies": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" + "source-map": "~0.6.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 10.0" } }, - "node_modules/class-utils/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, + "node_modules/clean-css/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "engines": { "node": ">=0.10.0" } }, - "node_modules/class-utils/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "optional": true, + "peer": true, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/class-utils/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "node_modules/cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, "engines": { - "node": ">=0.10.0" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/class-utils/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", "dev": true, "dependencies": { - "kind-of": "^3.0.2" + "restore-cursor": "^4.0.0" }, "engines": { - "node": ">=0.10.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/class-utils/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", "engines": { - "node": ">=0.10.0" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/class-utils/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", "dev": true, "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/class-utils/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "node_modules/cli-truncate/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/classnames": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", - "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + "node_modules/cli-truncate/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true }, - "node_modules/clean-css": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.2.tgz", - "integrity": "sha512-JVJbM+f3d3Q704rF4bqQ5UUyTtuJ0JRKNbTKVEeujCCBoMdkEi+V+e8oktO9qGQNSvHrFTM6JZRXrUvGR1czww==", + "node_modules/cli-truncate/node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dev": true, "dependencies": { - "source-map": "~0.6.0" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">= 10.0" - } - }, - "node_modules/clean-css/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "engines": { - "node": ">=6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "node_modules/cli-truncate/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, "engines": { - "node": ">=6" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "engines": { + "node": ">= 10" } }, "node_modules/cliui": { @@ -7713,24 +7999,24 @@ "node": ">=4" } }, + "node_modules/coffee-script": { + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz", + "integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==", + "deprecated": "CoffeeScript on NPM has moved to \"coffeescript\" (no hyphen)", + "bin": { + "cake": "bin/cake", + "coffee": "bin/coffee" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/collect-v8-coverage": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==" }, - "node_modules/collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==", - "dev": true, - "dependencies": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -7751,6 +8037,8 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "optional": true, + "peer": true, "bin": { "color-support": "bin.js" } @@ -7803,12 +8091,6 @@ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==" }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, "node_modules/compressible": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", @@ -7860,6 +8142,68 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/concat-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/concat-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/concat-with-sourcemaps": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", + "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", + "dependencies": { + "source-map": "^0.6.1" + } + }, + "node_modules/concat-with-sourcemaps/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/configstore": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", @@ -7923,7 +8267,9 @@ "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "optional": true, + "peer": true }, "node_modules/content-disposition": { "version": "0.5.4", @@ -7962,15 +8308,6 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, - "node_modules/copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/core-js": { "version": "3.31.1", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.31.1.tgz", @@ -7982,11 +8319,11 @@ } }, "node_modules/core-js-compat": { - "version": "3.31.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.31.1.tgz", - "integrity": "sha512-wIDWd2s5/5aJSdpOJHfSibxNODxoGoWOBHt8JSPB41NOE94M7kuTPZCYLOlTtuoXTsBPKobpJ6T+y0SSy5L9SA==", + "version": "3.36.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.0.tgz", + "integrity": "sha512-iV9Pd/PsgjNWBXeq8XRtWVSgz2tKAfhfvBs7qxYty+RlRd+OCksaWmOnc4JKrTc1cToXL1N0s3l/vwlxPtdElw==", "dependencies": { - "browserslist": "^4.21.9" + "browserslist": "^4.22.3" }, "funding": { "type": "opencollective", @@ -8177,21 +8514,6 @@ } } }, - "node_modules/css-minimizer-webpack-plugin/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/css-minimizer-webpack-plugin/node_modules/ajv-keywords": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", @@ -8203,11 +8525,6 @@ "ajv": "^8.8.2" } }, - "node_modules/css-minimizer-webpack-plugin/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, "node_modules/css-minimizer-webpack-plugin/node_modules/schema-utils": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", @@ -8249,18 +8566,14 @@ } }, "node_modules/css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", "dependencies": { "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" } }, "node_modules/css-select-base-adapter": { @@ -8268,6 +8581,56 @@ "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==" }, + "node_modules/css-select/node_modules/css-what": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", + "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-select/node_modules/dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dependencies": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + } + }, + "node_modules/css-select/node_modules/domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dependencies": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "node_modules/css-select/node_modules/domutils/node_modules/domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, + "node_modules/css-select/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/css-select/node_modules/nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dependencies": { + "boolbase": "~1.0.0" + } + }, "node_modules/css-tree": { "version": "1.0.0-alpha.37", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", @@ -8302,7 +8665,8 @@ "node_modules/css.escape": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", - "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==" + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true }, "node_modules/cssdb": { "version": "7.6.0", @@ -8465,6 +8829,14 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" }, + "node_modules/customize-cra": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/customize-cra/-/customize-cra-1.0.0.tgz", + "integrity": "sha512-DbtaLuy59224U+xCiukkxSq8clq++MOtJ1Et7LED1fLszWe88EoblEYFBJ895sB1mC6B4uu3xPT/IjClELhMbA==", + "dependencies": { + "lodash.flow": "^3.5.0" + } + }, "node_modules/d3-array": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", @@ -8568,7 +8940,8 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", - "dev": true, + "optional": true, + "peer": true, "dependencies": { "assert-plus": "^1.0.0" }, @@ -8589,6 +8962,54 @@ "node": ">=10" } }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/date-fns": { "version": "2.30.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", @@ -8629,6 +9050,8 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -8637,6 +9060,8 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "optional": true, + "peer": true, "dependencies": { "decamelize": "^1.1.0", "map-obj": "^1.0.0" @@ -8652,6 +9077,8 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -8661,15 +9088,6 @@ "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" }, - "node_modules/decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, "node_modules/decompress-response": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", @@ -8687,25 +9105,6 @@ "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==" }, - "node_modules/deep-equal-ident": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/deep-equal-ident/-/deep-equal-ident-1.1.1.tgz", - "integrity": "sha512-aWv7VhTl/Lju1zenOD3E1w8PpUVrTDbwXCHtbSNr+p/uadr49Y1P1ld0W3Pl6gbvIbiRjoCVsqw70UupCNGh6g==", - "dev": true, - "dependencies": { - "lodash.isequal": "^3.0" - } - }, - "node_modules/deep-equal-ident/node_modules/lodash.isequal": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-3.0.4.tgz", - "integrity": "sha512-Bsu5fP9Omd+HBk2Dz8qp4BHbC+83DBykZ87Lz1JmPKTVNy4Q0XQVtUrbfXVAK/udQrWNcGStcKSA9yj/Zkm3TQ==", - "dev": true, - "dependencies": { - "lodash._baseisequal": "^3.0.0", - "lodash._bindcallback": "^3.0.0" - } - }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -8739,12 +9138,47 @@ "node": ">= 10" } }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defaults/node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "engines": { + "node": ">=0.8" + } + }, "node_modules/defer-to-connect": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", "dev": true }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", @@ -8754,10 +9188,11 @@ } }, "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dependencies": { + "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" }, @@ -8768,19 +9203,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -8792,7 +9214,9 @@ "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "optional": true, + "peer": true }, "node_modules/depd": { "version": "2.0.0", @@ -8828,17 +9252,6 @@ "node": ">=0.10.0" } }, - "node_modules/detect-newline": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-4.0.0.tgz", - "integrity": "sha512-1aXUEPdfGdzVPFpzGJJNgq9o81bGg1s09uxTWsqBlo9PI332uyJRQq13+LK/UN4JfxJbFdCXonUFQ9R/p7yCtw==", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/detect-node": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", @@ -8878,6 +9291,14 @@ "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz", "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==" }, + "node_modules/diacritics-map": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/diacritics-map/-/diacritics-map-0.1.0.tgz", + "integrity": "sha512-3omnDTYrGigU0i4cJjvaKwD52B8aoqyX/NEIkukFFkogBemsIbhSa1O414fpTp5nuszJG6lvQ5vBvDVNCbSsaQ==", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -8887,6 +9308,7 @@ "version": "26.6.2", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.6.2.tgz", "integrity": "sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==", + "dev": true, "engines": { "node": ">= 10.14.2" } @@ -8902,11 +9324,6 @@ "node": ">=8" } }, - "node_modules/discontinuous-range": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", - "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==" - }, "node_modules/dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", @@ -8942,7 +9359,8 @@ "node_modules/dom-accessibility-api": { "version": "0.5.16", "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", - "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==" + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true }, "node_modules/dom-converter": { "version": "0.2.0", @@ -9080,7 +9498,8 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "dev": true, + "optional": true, + "peer": true, "dependencies": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" @@ -9106,9 +9525,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.461", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.461.tgz", - "integrity": "sha512-1JkvV2sgEGTDXjdsaQCeSwYYuhLRphRpc+g6EHTFELJXEiznLt3/0pZ9JuAOQ5p2rI3YxKTbivtvajirIfhrEQ==" + "version": "1.4.668", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.668.tgz", + "integrity": "sha512-ZOBocMYCehr9W31+GpMclR+KBaDZOoAEabLdhpZ8oU1JFDwIaFY0UDbpXVEUFc0BIP2O2Qn3rkfCjQmMR4T/bQ==" }, "node_modules/emittery": { "version": "0.8.1", @@ -9147,6 +9566,7 @@ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", "optional": true, + "peer": true, "dependencies": { "iconv-lite": "^0.6.2" } @@ -9187,182 +9607,18 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "optional": true, + "peer": true, "engines": { "node": ">=6" } }, - "node_modules/enzyme": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.11.0.tgz", - "integrity": "sha512-Dw8/Gs4vRjxY6/6i9wU0V+utmQO9kvh9XLnz3LIudviOnVYDEe2ec+0k+NQoMamn1VrjKgCUOWj5jG/5M5M0Qw==", - "dependencies": { - "array.prototype.flat": "^1.2.3", - "cheerio": "^1.0.0-rc.3", - "enzyme-shallow-equal": "^1.0.1", - "function.prototype.name": "^1.1.2", - "has": "^1.0.3", - "html-element-map": "^1.2.0", - "is-boolean-object": "^1.0.1", - "is-callable": "^1.1.5", - "is-number-object": "^1.0.4", - "is-regex": "^1.0.5", - "is-string": "^1.0.5", - "is-subset": "^0.1.1", - "lodash.escape": "^4.0.1", - "lodash.isequal": "^4.5.0", - "object-inspect": "^1.7.0", - "object-is": "^1.0.2", - "object.assign": "^4.1.0", - "object.entries": "^1.1.1", - "object.values": "^1.1.1", - "raf": "^3.4.1", - "rst-selector-parser": "^2.2.3", - "string.prototype.trim": "^1.2.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/enzyme-adapter-react-16": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.15.7.tgz", - "integrity": "sha512-LtjKgvlTc/H7adyQcj+aq0P0H07LDL480WQl1gU512IUyaDo/sbOaNDdZsJXYW2XaoPqrLLE9KbZS+X2z6BASw==", - "dependencies": { - "enzyme-adapter-utils": "^1.14.1", - "enzyme-shallow-equal": "^1.0.5", - "has": "^1.0.3", - "object.assign": "^4.1.4", - "object.values": "^1.1.5", - "prop-types": "^15.8.1", - "react-is": "^16.13.1", - "react-test-renderer": "^16.0.0-0", - "semver": "^5.7.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - }, - "peerDependencies": { - "enzyme": "^3.0.0", - "react": "^16.0.0-0", - "react-dom": "^16.0.0-0" - } - }, - "node_modules/enzyme-adapter-react-16/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/enzyme-adapter-react-16/node_modules/react-test-renderer": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.14.0.tgz", - "integrity": "sha512-L8yPjqPE5CZO6rKsKXRO/rVPiaCOy0tQQJbC+UjPNlobl5mad59lvPjwFsQHTvL03caVDIVr9x9/OSgDe6I5Eg==", - "dependencies": { - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "react-is": "^16.8.6", - "scheduler": "^0.19.1" - }, - "peerDependencies": { - "react": "^16.14.0" - } - }, - "node_modules/enzyme-adapter-react-16/node_modules/scheduler": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", - "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, - "node_modules/enzyme-adapter-react-16/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/enzyme-adapter-utils": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/enzyme-adapter-utils/-/enzyme-adapter-utils-1.14.1.tgz", - "integrity": "sha512-JZgMPF1QOI7IzBj24EZoDpaeG/p8Os7WeBZWTJydpsH7JRStc7jYbHE4CmNQaLqazaGFyLM8ALWA3IIZvxW3PQ==", - "dependencies": { - "airbnb-prop-types": "^2.16.0", - "function.prototype.name": "^1.1.5", - "has": "^1.0.3", - "object.assign": "^4.1.4", - "object.fromentries": "^2.0.5", - "prop-types": "^15.8.1", - "semver": "^5.7.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - }, - "peerDependencies": { - "react": "0.13.x || 0.14.x || ^15.0.0-0 || ^16.0.0-0" - } - }, - "node_modules/enzyme-adapter-utils/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/enzyme-matchers": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/enzyme-matchers/-/enzyme-matchers-7.1.2.tgz", - "integrity": "sha512-03WqAg2XDl7id9rARIO97HQ1JIw9F2heJ3R4meGu/13hx0ULTDEgl0E67MGl2Uq1jq1DyRnJfto1/VSzskdV5A==", - "dev": true, - "dependencies": { - "circular-json-es6": "^2.0.1", - "deep-equal-ident": "^1.1.1" - }, - "peerDependencies": { - "enzyme": ">=3.4.0" - } - }, - "node_modules/enzyme-shallow-equal": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.5.tgz", - "integrity": "sha512-i6cwm7hN630JXenxxJFBKzgLC3hMTafFQXflvzHgPmDhOBhxUWDe8AeRv1qp2/uWJ2Y8z5yLWMzmAfkTOiOCZg==", - "dependencies": { - "has": "^1.0.3", - "object-is": "^1.1.5" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/enzyme-to-json": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/enzyme-to-json/-/enzyme-to-json-3.6.2.tgz", - "integrity": "sha512-Ynm6Z6R6iwQ0g2g1YToz6DWhxVnt8Dy1ijR2zynRKxTyBGA8rCDXU3rs2Qc4OKvUvc2Qoe1bcFK6bnPs20TrTg==", - "dev": true, - "dependencies": { - "@types/cheerio": "^0.22.22", - "lodash": "^4.17.21", - "react-is": "^16.12.0" - }, - "engines": { - "node": ">=6.0.0" - }, - "peerDependencies": { - "enzyme": "^3.4.0" - } - }, - "node_modules/enzyme-to-json/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true - }, "node_modules/err-code": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==" + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "optional": true, + "peer": true }, "node_modules/error-ex": { "version": "1.3.2", @@ -9381,45 +9637,56 @@ } }, "node_modules/es-abstract": { - "version": "1.21.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.3.tgz", - "integrity": "sha512-ZU4miiY1j3sGPFLJ34VJXEqhpmL+HGByCinGHv4HC+Fxl2fI2Z4yR6tl0mORnDr6PA8eihWo4LmSWDbvhALckg==", - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", + "version": "1.23.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.2.tgz", + "integrity": "sha512-60s3Xv2T2p1ICykc7c+DNDPLDMm9t4QxCOUU0K9JxiLjM3C1zB9YVdN7tjxrFd4+AkZ8CdX1ovUga4P2+1e+/w==", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.1", - "get-symbol-description": "^1.0.0", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", "globalthis": "^1.0.3", "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", + "is-shared-array-buffer": "^1.0.3", "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", + "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", + "object-inspect": "^1.13.1", "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.0", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.5", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.10" + "which-typed-array": "^1.1.15" }, "engines": { "node": ">= 0.4" @@ -9433,30 +9700,84 @@ "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.0.18", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.18.tgz", + "integrity": "sha512-scxAJaewsahbqTYrGKJihhViaM6DDZDDoucfvzNbK0pOren1g/daDQ3IAhzn+1G14rBG7w+i5N+qul60++zlKA==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.2", + "safe-array-concat": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-module-lexer": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.0.tgz", "integrity": "sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==" }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" } }, "node_modules/es-to-primitive": { @@ -9475,6 +9796,43 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/esbuild": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.18.20", + "@esbuild/android-arm64": "0.18.20", + "@esbuild/android-x64": "0.18.20", + "@esbuild/darwin-arm64": "0.18.20", + "@esbuild/darwin-x64": "0.18.20", + "@esbuild/freebsd-arm64": "0.18.20", + "@esbuild/freebsd-x64": "0.18.20", + "@esbuild/linux-arm": "0.18.20", + "@esbuild/linux-arm64": "0.18.20", + "@esbuild/linux-ia32": "0.18.20", + "@esbuild/linux-loong64": "0.18.20", + "@esbuild/linux-mips64el": "0.18.20", + "@esbuild/linux-ppc64": "0.18.20", + "@esbuild/linux-riscv64": "0.18.20", + "@esbuild/linux-s390x": "0.18.20", + "@esbuild/linux-x64": "0.18.20", + "@esbuild/netbsd-x64": "0.18.20", + "@esbuild/openbsd-x64": "0.18.20", + "@esbuild/sunos-x64": "0.18.20", + "@esbuild/win32-arm64": "0.18.20", + "@esbuild/win32-ia32": "0.18.20", + "@esbuild/win32-x64": "0.18.20" + } + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -9599,9 +9957,10 @@ } }, "node_modules/eslint-config-prettier": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", - "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz", + "integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==", + "dev": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -9637,13 +9996,13 @@ } }, "node_modules/eslint-import-resolver-node": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", - "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dependencies": { "debug": "^3.2.7", - "is-core-module": "^2.11.0", - "resolve": "^1.22.1" + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" } }, "node_modules/eslint-import-resolver-node/node_modules/debug": { @@ -9696,25 +10055,27 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.27.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", - "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.1", + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "dependencies": { + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", "debug": "^3.2.7", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.7", - "eslint-module-utils": "^2.7.4", - "has": "^1.0.3", - "is-core-module": "^2.11.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", - "object.values": "^1.1.6", - "resolve": "^1.22.1", - "semver": "^6.3.0", - "tsconfig-paths": "^3.14.1" + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" }, "engines": { "node": ">=4" @@ -9811,45 +10172,58 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz", - "integrity": "sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", + "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", + "dev": true, "dependencies": { - "prettier-linter-helpers": "^1.0.0" + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.6" }, "engines": { - "node": ">=6.0.0" + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" }, "peerDependencies": { - "eslint": ">=5.0.0", - "prettier": ">=1.13.0" + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" }, "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, "eslint-config-prettier": { "optional": true } } }, "node_modules/eslint-plugin-react": { - "version": "7.32.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz", - "integrity": "sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==", - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "array.prototype.tosorted": "^1.1.1", + "version": "7.34.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz", + "integrity": "sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==", + "dependencies": { + "array-includes": "^3.1.7", + "array.prototype.findlast": "^1.2.4", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.toreversed": "^1.1.2", + "array.prototype.tosorted": "^1.1.3", "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.17", "estraverse": "^5.3.0", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "object.hasown": "^1.1.2", - "object.values": "^1.1.6", + "object.entries": "^1.1.7", + "object.fromentries": "^2.0.7", + "object.hasown": "^1.1.3", + "object.values": "^1.1.7", "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.4", - "semver": "^6.3.0", - "string.prototype.matchall": "^4.0.8" + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.10" }, "engines": { "node": ">=4" @@ -9889,11 +10263,11 @@ } }, "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", - "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", "dependencies": { - "is-core-module": "^2.9.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -9927,6 +10301,16 @@ "eslint": "^7.5.0 || ^8.0.0" } }, + "node_modules/eslint-plugin-tsdoc": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.17.tgz", + "integrity": "sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA==", + "dev": true, + "dependencies": { + "@microsoft/tsdoc": "0.14.2", + "@microsoft/tsdoc-config": "0.16.2" + } + }, "node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -9973,21 +10357,6 @@ "webpack": "^5.0.0" } }, - "node_modules/eslint-webpack-plugin/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/eslint-webpack-plugin/node_modules/ajv-keywords": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", @@ -10012,11 +10381,6 @@ "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/eslint-webpack-plugin/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, "node_modules/eslint-webpack-plugin/node_modules/schema-utils": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", @@ -10049,6 +10413,21 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/eslint/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -10143,6 +10522,11 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, "node_modules/eslint/node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -10304,12 +10688,6 @@ "node": ">=0.8.x" } }, - "node_modules/exec-sh": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.6.tgz", - "integrity": "sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w==", - "dev": true - }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -10340,74 +10718,63 @@ "node": ">= 0.8.0" } }, - "node_modules/expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", - "dev": true, + "node_modules/expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha512-AFASGfIlnIbkKPQwX1yHaDjFvh/1gyKJODme52V6IORh69uEYgZp0o9C+qsIGNVEiuuhQU0CSSl++Rlegg1qvA==", "dependencies": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "fill-range": "^2.1.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/expand-brackets/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/expand-brackets/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dev": true, + "node_modules/expand-range/node_modules/fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", "dependencies": { - "is-descriptor": "^0.1.0" + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/expand-brackets/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, + "node_modules/expand-range/node_modules/is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha512-QUzH43Gfb9+5yckcrSA0VBDwEtDUchrk4F6tfJZQuNzDJbEDB9cZNzSfXGQ1jqmdDY/kl41lUOWM9syA8z8jlg==", "dependencies": { - "is-extendable": "^0.1.0" + "kind-of": "^3.0.2" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/expand-brackets/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", - "dev": true, + "node_modules/expand-range/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/expand-range/node_modules/isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", "dependencies": { - "kind-of": "^3.0.2" + "isarray": "1.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/expand-brackets/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "node_modules/expand-range/node_modules/kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, "dependencies": { "is-buffer": "^1.1.5" }, @@ -10415,75 +10782,13 @@ "node": ">=0.10.0" } }, - "node_modules/expand-brackets/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "node_modules/expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", "dev": true, "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", - "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1" + "homedir-polyfill": "^1.0.1" }, "engines": { "node": ">=0.10.0" @@ -10607,81 +10912,42 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "dependencies": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } + "optional": true, + "peer": true }, - "node_modules/extglob/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", - "dev": true, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", "dependencies": { - "is-descriptor": "^1.0.0" + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/extglob/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, + "node_modules/external-editor/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dependencies": { - "is-extendable": "^0.1.0" + "safer-buffer": ">= 2.1.2 < 3" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/extglob/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "dev": true, "engines": [ "node >=0.6.0" - ] + ], + "optional": true, + "peer": true }, "node_modules/fast-deep-equal": { "version": "3.1.3", @@ -10691,7 +10957,8 @@ "node_modules/fast-diff": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==" + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true }, "node_modules/fast-glob": { "version": "3.3.0", @@ -10745,6 +11012,28 @@ "bser": "2.1.1" } }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -10788,13 +11077,6 @@ "node": ">=8.9.0" } }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, "node_modules/filelist": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", @@ -10955,9 +11237,9 @@ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" }, "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", "funding": [ { "type": "individual", @@ -11001,7 +11283,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -11010,7 +11291,8 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", - "dev": true, + "optional": true, + "peer": true, "engines": { "node": "*" } @@ -11053,6 +11335,29 @@ } } }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -11097,6 +11402,11 @@ "node": ">=10" } }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", @@ -11155,18 +11465,6 @@ "url": "https://www.patreon.com/infusion" } }, - "node_modules/fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==", - "dev": true, - "dependencies": { - "map-cache": "^0.2.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -11192,6 +11490,8 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "optional": true, + "peer": true, "dependencies": { "minipass": "^3.0.0" }, @@ -11210,9 +11510,9 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "hasInstallScript": true, "optional": true, "os": [ @@ -11223,19 +11523,22 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" }, "engines": { "node": ">= 0.4" @@ -11256,6 +11559,8 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "optional": true, + "peer": true, "dependencies": { "aproba": "^1.0.3 || ^2.0.0", "color-support": "^1.1.3", @@ -11274,6 +11579,8 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", + "optional": true, + "peer": true, "dependencies": { "globule": "^1.0.0" }, @@ -11306,15 +11613,31 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -11337,6 +11660,8 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", "integrity": "sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw==", + "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -11353,12 +11678,13 @@ } }, "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" }, "engines": { "node": ">= 0.4" @@ -11367,32 +11693,24 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-user-locale": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/get-user-locale/-/get-user-locale-2.3.0.tgz", - "integrity": "sha512-I3rQvAUwu2nauRD9YyQBSXVFJZixNouwA+eZld51Sn4Pn0N1qFbgcgOi/nPigJPQlNY519mT95fiSPRgflQiTA==", + "node_modules/get-tsconfig": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz", + "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==", + "dev": true, "dependencies": { - "@types/lodash.memoize": "^4.1.7", - "lodash.memoize": "^4.1.1" + "resolve-pkg-maps": "^1.0.0" }, "funding": { - "url": "https://github.com/wojtekmaj/get-user-locale?sponsor=1" - } - }, - "node_modules/get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", - "dev": true, - "engines": { - "node": ">=0.10.0" + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, "node_modules/getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "dev": true, + "optional": true, + "peer": true, "dependencies": { "assert-plus": "^1.0.0" } @@ -11536,6 +11854,8 @@ "version": "1.3.4", "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.4.tgz", "integrity": "sha512-OPTIfhMBh7JbBYDpa5b+Q5ptmMWKwcNcFSR/0c6t8V4f3ZAVBEsKNY37QdVqmLRYSMhOUGYrY0QhSoEpzGr/Eg==", + "optional": true, + "peer": true, "dependencies": { "glob": "~7.1.1", "lodash": "^4.17.21", @@ -11549,6 +11869,8 @@ "version": "7.1.7", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "optional": true, + "peer": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -11568,6 +11890,8 @@ "version": "3.0.8", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", + "optional": true, + "peer": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -11663,6 +11987,51 @@ "graphql": ">=0.11 <=16" } }, + "node_modules/gray-matter": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-2.1.1.tgz", + "integrity": "sha512-vbmvP1Fe/fxuT2QuLVcqb2BfK7upGhhbLIt9/owWEvPYrZZEkelLcq2HqzxosV+PQ67dUFLaAeNpH7C4hhICAA==", + "dependencies": { + "ansi-red": "^0.1.1", + "coffee-script": "^1.12.4", + "extend-shallow": "^2.0.1", + "js-yaml": "^3.8.1", + "toml": "^2.3.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gray-matter/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gray-matter/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-header": { + "version": "1.8.12", + "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.12.tgz", + "integrity": "sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ==", + "deprecated": "Removed event-stream from gulp-header", + "dependencies": { + "concat-with-sourcemaps": "*", + "lodash.template": "^4.4.0", + "through2": "^2.0.0" + } + }, "node_modules/gzip-size": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", @@ -11714,7 +12083,8 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", - "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=4" } @@ -11724,7 +12094,8 @@ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "deprecated": "this library is no longer supported", - "dev": true, + "optional": true, + "peer": true, "dependencies": { "ajv": "^6.12.3", "har-schema": "^2.0.0" @@ -11733,10 +12104,36 @@ "node": ">=6" } }, + "node_modules/har-validator/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "optional": true, + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/har-validator/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "optional": true, + "peer": true + }, "node_modules/hard-rejection": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "optional": true, + "peer": true, "engines": { "node": ">=6" } @@ -11774,20 +12171,20 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dependencies": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "engines": { "node": ">= 0.4" }, @@ -11807,11 +12204,11 @@ } }, "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -11823,70 +12220,9 @@ "node_modules/has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" - }, - "node_modules/has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==", - "dev": true, - "dependencies": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values/node_modules/kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "optional": true, + "peer": true }, "node_modules/has-yarn": { "version": "2.1.0", @@ -11897,6 +12233,17 @@ "node": ">=8" } }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -11906,16 +12253,11 @@ } }, "node_modules/history": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", - "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/history/-/history-5.3.0.tgz", + "integrity": "sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==", "dependencies": { - "@babel/runtime": "^7.1.2", - "loose-envify": "^1.2.0", - "resolve-pathname": "^3.0.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0", - "value-equal": "^1.0.1" + "@babel/runtime": "^7.7.6" } }, "node_modules/hoist-non-react-statics": { @@ -11955,6 +12297,8 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "optional": true, + "peer": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -11966,6 +12310,8 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "optional": true, + "peer": true, "dependencies": { "yallist": "^4.0.0" }, @@ -11976,7 +12322,9 @@ "node_modules/hosted-git-info/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true, + "peer": true }, "node_modules/hpack.js": { "version": "2.1.6", @@ -12021,18 +12369,6 @@ "safe-buffer": "~5.1.0" } }, - "node_modules/html-element-map": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/html-element-map/-/html-element-map-1.3.1.tgz", - "integrity": "sha512-6XMlxrAFX4UEEGxctfFnmrFaaZFNf9i5fNuV5wZ3WWQ4FVaNP1aX1LkX9j2mfEx1NpjeE/rL3nmgEn23GdFmrg==", - "dependencies": { - "array.prototype.filter": "^1.0.0", - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/html-encoding-sniffer": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", @@ -12143,7 +12479,8 @@ "node_modules/http-cache-semantics": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "devOptional": true }, "node_modules/http-deceiver": { "version": "1.2.7", @@ -12242,7 +12579,8 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", - "dev": true, + "optional": true, + "peer": true, "dependencies": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", @@ -12277,6 +12615,8 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "optional": true, + "peer": true, "dependencies": { "ms": "^2.0.0" } @@ -12408,6 +12748,12 @@ "url": "https://opencollective.com/immer" } }, + "node_modules/immutable": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz", + "integrity": "sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==", + "devOptional": true + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -12462,6 +12808,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "devOptional": true, "engines": { "node": ">=8" } @@ -12469,7 +12816,9 @@ "node_modules/infer-owner": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==" + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "optional": true, + "peer": true }, "node_modules/inflight": { "version": "1.0.6", @@ -12490,13 +12839,89 @@ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, + "node_modules/inquirer": { + "version": "8.2.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", + "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^6.0.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/inquirer/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/inquirer/node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "hasown": "^2.0.0", "side-channel": "^1.0.4" }, "engines": { @@ -12520,9 +12945,11 @@ } }, "node_modules/ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", + "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==", + "optional": true, + "peer": true }, "node_modules/ipaddr.js": { "version": "2.1.0", @@ -12532,26 +12959,16 @@ "node": ">= 10" } }, - "node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dependencies": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -12562,6 +12979,20 @@ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" }, + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-bigint": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", @@ -12602,8 +13033,7 @@ "node_modules/is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "node_modules/is-callable": { "version": "1.2.7", @@ -12635,26 +13065,28 @@ "dev": true }, "node_modules/is-core-module": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", - "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", "dependencies": { - "kind-of": "^6.0.0" + "is-typed-array": "^1.1.13" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-date-object": { @@ -12671,20 +13103,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-docker": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", @@ -12703,7 +13121,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, "dependencies": { "is-plain-object": "^2.0.4" }, @@ -12719,6 +13136,17 @@ "node": ">=0.10.0" } }, + "node_modules/is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -12735,6 +13163,20 @@ "node": ">=6" } }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -12762,10 +13204,31 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "engines": { + "node": ">=8" + } + }, "node_modules/is-lambda": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==" + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "optional": true, + "peer": true + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/is-module": { "version": "1.0.0", @@ -12773,9 +13236,9 @@ "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==" }, "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "engines": { "node": ">= 0.4" }, @@ -12838,6 +13301,8 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -12846,7 +13311,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, "dependencies": { "isobject": "^3.0.1" }, @@ -12890,12 +13354,26 @@ "node": ">=6" } }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dependencies": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -12926,11 +13404,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-subset": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", - "integrity": "sha512-6Ybun0IkarhmEqxXCNw/C0bna6Zb/TkfUX9UbwJtK6ObwAVCxmAP308WWTHviM/zAqXk05cdhYsUsZeGQh99iw==" - }, "node_modules/is-symbol": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", @@ -12946,15 +13419,11 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -12968,6 +13437,28 @@ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -12979,6 +13470,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-weakset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -13006,10 +13512,10 @@ "dev": true }, "node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" - }, + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -13019,7 +13525,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -13028,7 +13533,8 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", - "dev": true + "optional": true, + "peer": true }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", @@ -13107,6 +13613,18 @@ "node": ">=8" } }, + "node_modules/iterator.prototype": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", + "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "dependencies": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + } + }, "node_modules/jake": { "version": "10.8.7", "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", @@ -13339,6 +13857,56 @@ } } }, + "node_modules/jest-config/node_modules/babel-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", + "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", + "dependencies": { + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/jest-config/node_modules/babel-plugin-jest-hoist": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", + "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-config/node_modules/babel-preset-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", + "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", + "dependencies": { + "babel-plugin-jest-hoist": "^27.5.1", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/jest-config/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -13354,6 +13922,22 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/jest-config/node_modules/jest-environment-node": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", + "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, "node_modules/jest-config/node_modules/pretty-format": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", @@ -13387,6 +13971,7 @@ "version": "26.6.2", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.6.2.tgz", "integrity": "sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==", + "dev": true, "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^26.6.2", @@ -13401,6 +13986,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -13416,6 +14002,7 @@ "version": "26.3.0", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.3.0.tgz", "integrity": "sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==", + "dev": true, "engines": { "node": ">= 10.14.2" } @@ -13498,1183 +14085,1084 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, - "node_modules/jest-environment-enzyme": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/jest-environment-enzyme/-/jest-environment-enzyme-7.1.2.tgz", - "integrity": "sha512-3tfaYAzO7qZSRrv+srQnfK16Vu5XwH/pHi8FpoqSHjKKngbHzXf7aBCBuWh8y3w0OtknHRfDMFrC60Khj+g1hA==", - "dev": true, + "node_modules/jest-environment-jsdom": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", + "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", "dependencies": { - "jest-environment-jsdom": "^24.0.0" + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1", + "jsdom": "^16.6.0" }, - "peerDependencies": { - "enzyme": "3.x", - "jest": ">=22.0.0", - "react": "^0.13.0 || ^0.14.0 || ^15.0.0 || >=16.x" + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/@jest/console": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", - "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", - "dev": true, - "dependencies": { - "@jest/source-map": "^24.9.0", - "chalk": "^2.0.1", - "slash": "^2.0.0" - }, + "node_modules/jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", "engines": { - "node": ">= 6" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/@jest/environment": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.9.0.tgz", - "integrity": "sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ==", - "dev": true, + "node_modules/jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", "dependencies": { - "@jest/fake-timers": "^24.9.0", - "@jest/transform": "^24.9.0", - "@jest/types": "^24.9.0", - "jest-mock": "^24.9.0" + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" }, "engines": { - "node": ">= 6" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "node_modules/jest-environment-enzyme/node_modules/@jest/fake-timers": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", - "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", - "dev": true, + "node_modules/jest-jasmine2": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", + "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", "dependencies": { - "@jest/types": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-mock": "^24.9.0" + "@jest/environment": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "throat": "^6.0.1" }, "engines": { - "node": ">= 6" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/@jest/source-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", - "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", - "dev": true, + "node_modules/jest-jasmine2/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": { - "callsites": "^3.0.0", - "graceful-fs": "^4.1.15", - "source-map": "^0.6.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-environment-enzyme/node_modules/@jest/test-result": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", - "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", - "dev": true, + "node_modules/jest-jasmine2/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dependencies": { - "@jest/console": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/istanbul-lib-coverage": "^2.0.0" + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" }, "engines": { - "node": ">= 6" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/@jest/transform": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.9.0.tgz", - "integrity": "sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ==", - "dev": true, - "dependencies": { - "@babel/core": "^7.1.0", - "@jest/types": "^24.9.0", - "babel-plugin-istanbul": "^5.1.0", - "chalk": "^2.0.1", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.1.15", - "jest-haste-map": "^24.9.0", - "jest-regex-util": "^24.9.0", - "jest-util": "^24.9.0", - "micromatch": "^3.1.10", - "pirates": "^4.0.1", - "realpath-native": "^1.1.0", - "slash": "^2.0.0", - "source-map": "^0.6.1", - "write-file-atomic": "2.4.1" - }, + "node_modules/jest-jasmine2/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "engines": { - "node": ">= 6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jest-environment-enzyme/node_modules/@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", - "dev": true, + "node_modules/jest-jasmine2/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "node_modules/jest-leak-detector": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", + "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" }, "engines": { - "node": ">= 6" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/@types/istanbul-reports": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz", - "integrity": "sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "*", - "@types/istanbul-lib-report": "*" + "node_modules/jest-leak-detector/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jest-environment-enzyme/node_modules/@types/stack-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", - "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==", - "dev": true - }, - "node_modules/jest-environment-enzyme/node_modules/@types/yargs": { - "version": "13.0.12", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.12.tgz", - "integrity": "sha512-qCxJE1qgz2y0hA4pIxjBR+PelCH0U5CK1XJXFwCNqfmliatKp47UCXXE9Dyk1OXBDLvsCF57TqQEJaeLfDYEOQ==", - "dev": true, + "node_modules/jest-leak-detector/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dependencies": { - "@types/yargs-parser": "*" + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/acorn": { - "version": "5.7.4", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", - "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", + "node_modules/jest-leak-detector/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "node_modules/jest-localstorage-mock": { + "version": "2.4.26", + "resolved": "https://registry.npmjs.org/jest-localstorage-mock/-/jest-localstorage-mock-2.4.26.tgz", + "integrity": "sha512-owAJrYnjulVlMIXOYQIPRCCn3MmqI3GzgfZCXdD3/pmwrIvFMXcKVWZ+aMc44IzaASapg0Z4SEFxR+v5qxDA2w==", "dev": true, - "bin": { - "acorn": "bin/acorn" - }, "engines": { - "node": ">=0.4.0" + "node": ">=6.16.0" } }, - "node_modules/jest-environment-enzyme/node_modules/acorn-globals": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz", - "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==", + "node_modules/jest-location-mock": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/jest-location-mock/-/jest-location-mock-1.0.10.tgz", + "integrity": "sha512-g5u0rDOaj1I/lWuPOOP6xfpY+O958IcOanwPKnHdfWm0l4Y2sdVmwXMPY9fT5s8D9nX44Zl/Ypmk6B88mDoqZQ==", "dev": true, "dependencies": { - "acorn": "^6.0.1", - "acorn-walk": "^6.0.1" + "@jedmao/location": "^3.0.0", + "jest-diff": "^27.0.1" + }, + "engines": { + "node": ">=10.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/acorn-globals/node_modules/acorn": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", - "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "node_modules/jest-location-mock/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "bin": { - "acorn": "bin/acorn" + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=0.4.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-environment-enzyme/node_modules/acorn-walk": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", - "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", + "node_modules/jest-location-mock/node_modules/diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", "dev": true, "engines": { - "node": ">=0.4.0" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/jest-location-mock/node_modules/jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", "dev": true, "dependencies": { - "color-convert": "^1.9.0" + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" }, "engines": { - "node": ">=4" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "node_modules/jest-location-mock/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, "dependencies": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/babel-plugin-istanbul": { + "node_modules/jest-location-mock/node_modules/pretty-format/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz", - "integrity": "sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw==", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "find-up": "^3.0.0", - "istanbul-lib-instrument": "^3.3.0", - "test-exclude": "^5.2.3" - }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jest-environment-enzyme/node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, + "node_modules/jest-location-mock/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" }, "engines": { - "node": ">=0.10.0" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, + "node_modules/jest-matcher-utils/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": { - "is-extendable": "^0.1.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-environment-enzyme/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, + "node_modules/jest-matcher-utils/node_modules/diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", "engines": { - "node": ">=4" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, + "node_modules/jest-matcher-utils/node_modules/jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", "dependencies": { - "color-name": "1.1.3" + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/jest-environment-enzyme/node_modules/cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - }, - "node_modules/jest-environment-enzyme/node_modules/cssstyle": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", - "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", - "dev": true, + "node_modules/jest-matcher-utils/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dependencies": { - "cssom": "0.3.x" + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/data-urls": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", - "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", - "dev": true, - "dependencies": { - "abab": "^2.0.0", - "whatwg-mimetype": "^2.2.0", - "whatwg-url": "^7.0.0" + "node_modules/jest-matcher-utils/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jest-environment-enzyme/node_modules/data-urls/node_modules/whatwg-url": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", - "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", - "dev": true, - "dependencies": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" - } + "node_modules/jest-matcher-utils/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, - "node_modules/jest-environment-enzyme/node_modules/domexception": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", - "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", - "dev": true, + "node_modules/jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", "dependencies": { - "webidl-conversions": "^4.0.2" - } - }, - "node_modules/jest-environment-enzyme/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, "engines": { - "node": ">=0.8.0" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/escodegen": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", - "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", - "dev": true, + "node_modules/jest-message-util/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": { - "esprima": "^4.0.1", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=4.0" + "node": ">=10" }, - "optionalDependencies": { - "source-map": "~0.6.1" + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-environment-enzyme/node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", - "dev": true, + "node_modules/jest-message-util/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" }, "engines": { - "node": ">=0.10.0" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, + "node_modules/jest-message-util/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "node_modules/jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", "dependencies": { - "is-extendable": "^0.1.0" + "@jest/types": "^27.5.1", + "@types/node": "*" }, "engines": { - "node": ">=0.10.0" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "engines": { "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } } }, - "node_modules/jest-environment-enzyme/node_modules/fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "deprecated": "The v1 package contains DANGEROUS / INSECURE binaries. Upgrade to safe fsevents v2", + "node_modules/jest-preview": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/jest-preview/-/jest-preview-0.3.1.tgz", + "integrity": "sha512-gRR4shnXFSh8tdNaIncJC98d1zXD7w7LA52HQC0bu0DsPb+FXVEg+NQh9GTbO+n6/SCgcZNQAVt4MeCfsIkBPA==", "dev": true, "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], "dependencies": { - "bindings": "^1.5.0", - "nan": "^2.12.1" + "@svgr/core": "^6.2.1", + "camelcase": "^6.3.0", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "commander": "^9.2.0", + "connect": "^3.7.0", + "find-node-modules": "^2.1.3", + "open": "^8.4.0", + "postcss-import": "^14.1.0", + "postcss-load-config": "^4.0.1", + "sirv": "^2.0.2", + "slash": "^3.0.0", + "string-hash": "^1.1.3", + "update-notifier": "^5.1.0", + "ws": "^8.5.0" }, - "engines": { - "node": ">= 4.0" + "bin": { + "jest-preview": "cli/index.js" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/jest-preview" } }, - "node_modules/jest-environment-enzyme/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "node_modules/jest-preview/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-environment-enzyme/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/jest-environment-enzyme/node_modules/html-encoding-sniffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", - "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "node_modules/jest-preview/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "whatwg-encoding": "^1.0.1" + "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-environment-enzyme/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "dev": true, + "node_modules/jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", "engines": { - "node": ">=0.10.0" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", - "dev": true, + "node_modules/jest-resolve": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", + "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", "dependencies": { - "kind-of": "^3.0.2" + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", + "slash": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, + "node_modules/jest-resolve-dependencies": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", + "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", "dependencies": { - "is-buffer": "^1.1.5" + "@jest/types": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-snapshot": "^27.5.1" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jest-environment-enzyme/node_modules/istanbul-lib-coverage": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", - "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", - "dev": true, - "engines": { - "node": ">=6" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/istanbul-lib-instrument": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", - "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", - "dev": true, + "node_modules/jest-resolve/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": { - "@babel/generator": "^7.4.0", - "@babel/parser": "^7.4.3", - "@babel/template": "^7.4.0", - "@babel/traverse": "^7.4.3", - "@babel/types": "^7.4.0", - "istanbul-lib-coverage": "^2.0.5", - "semver": "^6.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-environment-enzyme/node_modules/jest-environment-jsdom": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-24.9.0.tgz", - "integrity": "sha512-Zv9FV9NBRzLuALXjvRijO2351DRQeLYXtpD4xNvfoVFw21IOKNhZAEUKcbiEtjTkm2GsJ3boMVgkaR7rN8qetA==", - "dev": true, + "node_modules/jest-runner": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", + "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", "dependencies": { - "@jest/environment": "^24.9.0", - "@jest/fake-timers": "^24.9.0", - "@jest/types": "^24.9.0", - "jest-mock": "^24.9.0", - "jest-util": "^24.9.0", - "jsdom": "^11.5.1" + "@jest/console": "^27.5.1", + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-leak-detector": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "source-map-support": "^0.5.6", + "throat": "^6.0.1" }, "engines": { - "node": ">= 6" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/jest-haste-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.9.0.tgz", - "integrity": "sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==", - "dev": true, + "node_modules/jest-runner/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": { - "@jest/types": "^24.9.0", - "anymatch": "^2.0.0", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.1.15", - "invariant": "^2.2.4", - "jest-serializer": "^24.9.0", - "jest-util": "^24.9.0", - "jest-worker": "^24.9.0", - "micromatch": "^3.1.10", - "sane": "^4.0.3", - "walker": "^1.0.7" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 6" + "node": ">=10" }, - "optionalDependencies": { - "fsevents": "^1.2.7" + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-environment-enzyme/node_modules/jest-message-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", - "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", - "dev": true, + "node_modules/jest-runner/node_modules/jest-environment-node": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", + "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", "dependencies": { - "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/stack-utils": "^1.0.1", - "chalk": "^2.0.1", - "micromatch": "^3.1.10", - "slash": "^2.0.0", - "stack-utils": "^1.0.1" + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" }, "engines": { - "node": ">= 6" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/jest-mock": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", - "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", - "dev": true, + "node_modules/jest-runtime": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", + "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", "dependencies": { - "@jest/types": "^24.9.0" + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/globals": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "execa": "^5.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" }, "engines": { - "node": ">= 6" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/jest-regex-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", - "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==", - "dev": true, + "node_modules/jest-runtime/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": ">= 6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-environment-enzyme/node_modules/jest-serializer": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.9.0.tgz", - "integrity": "sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==", - "dev": true, + "node_modules/jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dependencies": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + }, "engines": { - "node": ">= 6" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/jest-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", - "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", - "dev": true, - "dependencies": { - "@jest/console": "^24.9.0", - "@jest/fake-timers": "^24.9.0", - "@jest/source-map": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "callsites": "^3.0.0", - "chalk": "^2.0.1", - "graceful-fs": "^4.1.15", - "is-ci": "^2.0.0", - "mkdirp": "^0.5.1", - "slash": "^2.0.0", - "source-map": "^0.6.0" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/jest-environment-enzyme/node_modules/jest-worker": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", - "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", - "dev": true, + "node_modules/jest-snapshot": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", + "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", "dependencies": { - "merge-stream": "^2.0.0", - "supports-color": "^6.1.0" + "@babel/core": "^7.7.2", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/traverse": "^7.7.2", + "@babel/types": "^7.0.0", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__traverse": "^7.0.4", + "@types/prettier": "^2.1.5", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^27.5.1", + "semver": "^7.3.2" }, "engines": { - "node": ">= 6" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/jest-worker/node_modules/supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, + "node_modules/jest-snapshot/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": { - "has-flag": "^3.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=6" - } - }, - "node_modules/jest-environment-enzyme/node_modules/jsdom": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", - "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", - "dev": true, - "dependencies": { - "abab": "^2.0.0", - "acorn": "^5.5.3", - "acorn-globals": "^4.1.0", - "array-equal": "^1.0.0", - "cssom": ">= 0.3.2 < 0.4.0", - "cssstyle": "^1.0.0", - "data-urls": "^1.0.0", - "domexception": "^1.0.1", - "escodegen": "^1.9.1", - "html-encoding-sniffer": "^1.0.2", - "left-pad": "^1.3.0", - "nwsapi": "^2.0.7", - "parse5": "4.0.0", - "pn": "^1.1.0", - "request": "^2.87.0", - "request-promise-native": "^1.0.5", - "sax": "^1.2.4", - "symbol-tree": "^3.2.2", - "tough-cookie": "^2.3.4", - "w3c-hr-time": "^1.0.1", - "webidl-conversions": "^4.0.2", - "whatwg-encoding": "^1.0.3", - "whatwg-mimetype": "^2.1.0", - "whatwg-url": "^6.4.1", - "ws": "^5.2.0", - "xml-name-validator": "^3.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-environment-enzyme/node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, + "node_modules/jest-snapshot/node_modules/diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", "engines": { - "node": ">= 0.8.0" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, + "node_modules/jest-snapshot/node_modules/jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" }, "engines": { - "node": ">=6" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, + "node_modules/jest-snapshot/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" }, "engines": { - "node": ">=0.10.0" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "dependencies": { - "minimist": "^1.2.6" + "node_modules/jest-snapshot/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/jest-environment-enzyme/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jest-environment-enzyme/node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } + "node_modules/jest-snapshot/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, - "node_modules/jest-environment-enzyme/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", - "dev": true, + "node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", "dependencies": { - "remove-trailing-separator": "^1.0.1" + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" }, "engines": { - "node": ">=0.10.0" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, + "node_modules/jest-util/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": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-environment-enzyme/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, + "node_modules/jest-validate": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", + "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", "dependencies": { - "p-limit": "^2.0.0" + "@jest/types": "^27.5.1", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "leven": "^3.1.0", + "pretty-format": "^27.5.1" }, "engines": { - "node": ">=6" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/parse5": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", - "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", - "dev": true - }, - "node_modules/jest-environment-enzyme/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==", - "dev": true, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-environment-enzyme/node_modules/path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, + "node_modules/jest-validate/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": { - "pify": "^3.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-environment-enzyme/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true, + "node_modules/jest-validate/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, "engines": { - "node": ">=4" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "dev": true, + "node_modules/jest-validate/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "engines": { - "node": ">= 0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jest-environment-enzyme/node_modules/read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", - "dev": true, + "node_modules/jest-validate/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "node_modules/jest-watch-typeahead": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-1.1.0.tgz", + "integrity": "sha512-Va5nLSJTN7YFtC2jd+7wsoe1pNe5K4ShLux/E5iHEwlB9AxaxmggY7to9KUqKojhaJw3aXqt5WAb4jGPOolpEw==", "dependencies": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" + "ansi-escapes": "^4.3.1", + "chalk": "^4.0.0", + "jest-regex-util": "^28.0.0", + "jest-watcher": "^28.0.0", + "slash": "^4.0.0", + "string-length": "^5.0.1", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "jest": "^27.0.0 || ^28.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/read-pkg-up": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", - "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", - "dev": true, - "dependencies": { - "find-up": "^3.0.0", - "read-pkg": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jest-environment-enzyme/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/jest-environment-enzyme/node_modules/slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/jest-environment-enzyme/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jest-environment-enzyme/node_modules/stack-utils": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.5.tgz", - "integrity": "sha512-KZiTzuV3CnSnSvgMRrARVCj+Ht7rMbauGDK0LdVFRGyenwdylpajAp4Q0i6SX8rEmbTpMMf6ryq2gb8pPq2WgQ==", - "dev": true, + "node_modules/jest-watch-typeahead/node_modules/@jest/console": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.3.tgz", + "integrity": "sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==", "dependencies": { - "escape-string-regexp": "^2.0.0" + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^28.1.3", + "jest-util": "^28.1.3", + "slash": "^3.0.0" }, "engines": { - "node": ">=8" + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, + "node_modules/jest-watch-typeahead/node_modules/@jest/console/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "engines": { "node": ">=8" } }, - "node_modules/jest-environment-enzyme/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, + "node_modules/jest-watch-typeahead/node_modules/@jest/test-result": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-28.1.3.tgz", + "integrity": "sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg==", "dependencies": { - "has-flag": "^3.0.0" + "@jest/console": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" }, "engines": { - "node": ">=4" + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/test-exclude": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", - "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", - "dev": true, + "node_modules/jest-watch-typeahead/node_modules/@jest/types": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", + "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", "dependencies": { - "glob": "^7.1.3", - "minimatch": "^3.0.4", - "read-pkg-up": "^4.0.0", - "require-main-filename": "^2.0.0" + "@jest/schemas": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" }, "engines": { - "node": ">=6" + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", - "dev": true, + "node_modules/jest-watch-typeahead/node_modules/@types/yargs": { + "version": "17.0.24", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", + "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" + "@types/yargs-parser": "*" } }, - "node_modules/jest-environment-enzyme/node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, + "node_modules/jest-watch-typeahead/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": { - "psl": "^1.1.28", - "punycode": "^2.1.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=0.8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-environment-enzyme/node_modules/tr46": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", - "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" + "node_modules/jest-watch-typeahead/node_modules/emittery": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", + "integrity": "sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" } }, - "node_modules/jest-environment-enzyme/node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dev": true, + "node_modules/jest-watch-typeahead/node_modules/jest-message-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", + "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", "dependencies": { - "prelude-ls": "~1.1.2" + "@babel/code-frame": "^7.12.13", + "@jest/types": "^28.1.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^28.1.3", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/jest-environment-enzyme/node_modules/webidl-conversions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", - "dev": true - }, - "node_modules/jest-environment-enzyme/node_modules/whatwg-url": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", - "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", - "dev": true, - "dependencies": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/jest-environment-enzyme/node_modules/write-file-atomic": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz", - "integrity": "sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" + "node_modules/jest-watch-typeahead/node_modules/jest-message-util/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" } }, - "node_modules/jest-environment-enzyme/node_modules/ws": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.3.tgz", - "integrity": "sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA==", - "dev": true, - "dependencies": { - "async-limiter": "~1.0.0" + "node_modules/jest-watch-typeahead/node_modules/jest-regex-util": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", + "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/jest-environment-jsdom": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", - "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", + "node_modules/jest-watch-typeahead/node_modules/jest-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", + "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", + "@jest/types": "^28.1.3", "@types/node": "*", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1", - "jsdom": "^16.6.0" + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/jest-environment-node": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", - "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", + "node_modules/jest-watch-typeahead/node_modules/jest-watcher": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-28.1.3.tgz", + "integrity": "sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g==", "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", + "@jest/test-result": "^28.1.3", + "@jest/types": "^28.1.3", "@types/node": "*", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1" + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.10.2", + "jest-util": "^28.1.3", + "string-length": "^4.0.1" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/jest-enzyme": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/jest-enzyme/-/jest-enzyme-7.1.2.tgz", - "integrity": "sha512-j+jkph3t5hGBS12eOldpfsnERYRCHi4c/0KWPMnqRPoJJXvCpLIc5th1MHl0xDznQDXVU0AHUXg3rqMrf8vGpA==", - "dev": true, + "node_modules/jest-watch-typeahead/node_modules/jest-watcher/node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", "dependencies": { - "enzyme-matchers": "^7.1.2", - "enzyme-to-json": "^3.3.0", - "jest-environment-enzyme": "^7.1.2" + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" }, - "peerDependencies": { - "enzyme": ">=3.4.0", - "jest": ">=22.0.0" - } - }, - "node_modules/jest-get-type": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", - "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=10" } }, - "node_modules/jest-haste-map": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", - "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "node_modules/jest-watch-typeahead/node_modules/jest-watcher/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dependencies": { - "@jest/types": "^27.5.1", - "@types/graceful-fs": "^4.1.2", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^27.5.1", - "jest-serializer": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "micromatch": "^4.0.4", - "walker": "^1.0.7" + "ansi-regex": "^5.0.1" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" + "node": ">=8" } }, - "node_modules/jest-jasmine2": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", - "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", - "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/source-map": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "expect": "^27.5.1", - "is-generator-fn": "^2.0.0", - "jest-each": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1", - "throat": "^6.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-jasmine2/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-jasmine2/node_modules/pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "node_modules/jest-watch-typeahead/node_modules/pretty-format": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", + "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", "dependencies": { + "@jest/schemas": "^28.1.3", "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" + "react-is": "^18.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/jest-jasmine2/node_modules/pretty-format/node_modules/ansi-styles": { + "node_modules/jest-watch-typeahead/node_modules/pretty-format/node_modules/ansi-styles": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", @@ -14685,161 +15173,83 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jest-jasmine2/node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" - }, - "node_modules/jest-leak-detector": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", - "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", - "dependencies": { - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-leak-detector/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "node_modules/jest-watch-typeahead/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-leak-detector/node_modules/pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", - "dependencies": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-leak-detector/node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" - }, - "node_modules/jest-localstorage-mock": { - "version": "2.4.26", - "resolved": "https://registry.npmjs.org/jest-localstorage-mock/-/jest-localstorage-mock-2.4.26.tgz", - "integrity": "sha512-owAJrYnjulVlMIXOYQIPRCCn3MmqI3GzgfZCXdD3/pmwrIvFMXcKVWZ+aMc44IzaASapg0Z4SEFxR+v5qxDA2w==", - "dev": true, - "engines": { - "node": ">=6.16.0" - } - }, - "node_modules/jest-location-mock": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/jest-location-mock/-/jest-location-mock-1.0.10.tgz", - "integrity": "sha512-g5u0rDOaj1I/lWuPOOP6xfpY+O958IcOanwPKnHdfWm0l4Y2sdVmwXMPY9fT5s8D9nX44Zl/Ypmk6B88mDoqZQ==", - "dev": true, - "dependencies": { - "@jedmao/location": "^3.0.0", - "jest-diff": "^27.0.1" - }, - "engines": { - "node": ">=10.0.0" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-location-mock/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, + "node_modules/jest-watch-typeahead/node_modules/string-length": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-5.0.1.tgz", + "integrity": "sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "char-regex": "^2.0.0", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=10" + "node": ">=12.20" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-location-mock/node_modules/diff-sequences": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", - "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", - "dev": true, + "node_modules/jest-watch-typeahead/node_modules/string-length/node_modules/char-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-2.0.1.tgz", + "integrity": "sha512-oSvEeo6ZUD7NepqAat3RqoucZ5SeqLJgOvVIwkafu6IP3V0pO38s/ypdVUmDDK6qIIHNlYHJAKX9E7R7HoKElw==", "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=12.20" } }, - "node_modules/jest-location-mock/node_modules/jest-diff": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", - "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", - "dev": true, + "node_modules/jest-watch-typeahead/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" + "ansi-regex": "^6.0.1" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-location-mock/node_modules/pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" + "node": ">=12" }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/jest-location-mock/node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, + "node_modules/jest-watch-typeahead/node_modules/strip-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/jest-location-mock/node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - }, - "node_modules/jest-matcher-utils": { + "node_modules/jest-watcher": { "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", - "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", + "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", "dependencies": { + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "jest-diff": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" + "jest-util": "^27.5.1", + "string-length": "^4.0.1" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-matcher-utils/node_modules/chalk": { + "node_modules/jest-watcher/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", @@ -14854,1427 +15264,1010 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-matcher-utils/node_modules/diff-sequences": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", - "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-matcher-utils/node_modules/jest-diff": { + "node_modules/jest-worker": { "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", - "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">= 10.13.0" } }, - "node_modules/jest-matcher-utils/node_modules/pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dependencies": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" + "has-flag": "^4.0.0" }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-matcher-utils/node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/jest-matcher-utils/node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + "node_modules/jiti": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.1.tgz", + "integrity": "sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg==", + "bin": { + "jiti": "bin/jiti.js" + } }, - "node_modules/jest-message-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", - "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.5.1", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, + "node_modules/jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", + "dev": true + }, + "node_modules/js-base64": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", + "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==", + "optional": true, + "peer": true + }, + "node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=14" } }, - "node_modules/jest-message-util/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jest-message-util/node_modules/pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "optional": true, + "peer": true + }, + "node_modules/jsdom": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", "dependencies": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-message-util/node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "engines": { "node": ">=10" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-message-util/node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" - }, - "node_modules/jest-mock": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", - "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", - "dependencies": { - "@jest/types": "^27.5.1", - "@types/node": "*" + "peerDependencies": { + "canvas": "^2.5.0" }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "peerDependenciesMeta": { + "canvas": { + "optional": true + } } }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "node_modules/jsdom/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, + "node_modules/jsdom/node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", "engines": { - "node": ">=6" + "node": ">=8.3.0" }, "peerDependencies": { - "jest-resolve": "*" + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" }, "peerDependenciesMeta": { - "jest-resolve": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { "optional": true } } }, - "node_modules/jest-preview": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/jest-preview/-/jest-preview-0.3.1.tgz", - "integrity": "sha512-gRR4shnXFSh8tdNaIncJC98d1zXD7w7LA52HQC0bu0DsPb+FXVEg+NQh9GTbO+n6/SCgcZNQAVt4MeCfsIkBPA==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@svgr/core": "^6.2.1", - "camelcase": "^6.3.0", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "commander": "^9.2.0", - "connect": "^3.7.0", - "find-node-modules": "^2.1.3", - "open": "^8.4.0", - "postcss-import": "^14.1.0", - "postcss-load-config": "^4.0.1", - "sirv": "^2.0.2", - "slash": "^3.0.0", - "string-hash": "^1.1.3", - "update-notifier": "^5.1.0", - "ws": "^8.5.0" - }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "bin": { - "jest-preview": "cli/index.js" + "jsesc": "bin/jsesc" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/jest-preview" - } - }, - "node_modules/jest-preview/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, - "node_modules/jest-preview/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "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/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", + "dev": true }, - "node_modules/jest-regex-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", - "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, - "node_modules/jest-resolve": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", - "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", - "dependencies": { - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "resolve": "^1.20.0", - "resolve.exports": "^1.1.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-resolve-dependencies": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", - "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", - "dependencies": { - "@jest/types": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-snapshot": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-resolve/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-runner": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", - "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", - "dependencies": { - "@jest/console": "^27.5.1", - "@jest/environment": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.8.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^27.5.1", - "jest-environment-jsdom": "^27.5.1", - "jest-environment-node": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-leak-detector": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "source-map-support": "^0.5.6", - "throat": "^6.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-runner/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-runtime": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", - "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", - "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/globals": "^27.5.1", - "@jest/source-map": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "execa": "^5.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-runtime/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-serializer": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", - "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", - "dependencies": { - "@types/node": "*", - "graceful-fs": "^4.2.9" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-snapshot": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", - "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", - "dependencies": { - "@babel/core": "^7.7.2", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", - "@babel/types": "^7.0.0", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/babel__traverse": "^7.0.4", - "@types/prettier": "^2.1.5", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^27.5.1", - "graceful-fs": "^4.2.9", - "jest-diff": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-util": "^27.5.1", - "natural-compare": "^1.4.0", - "pretty-format": "^27.5.1", - "semver": "^7.3.2" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-snapshot/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-snapshot/node_modules/diff-sequences": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", - "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-snapshot/node_modules/jest-diff": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", - "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-snapshot/node_modules/pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", - "dependencies": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-snapshot/node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-snapshot/node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" - }, - "node_modules/jest-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", - "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", - "dependencies": { - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-util/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-validate": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", - "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", - "dependencies": { - "@jest/types": "^27.5.1", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^27.5.1", - "leven": "^3.1.0", - "pretty-format": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-validate/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-validate/node_modules/pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", - "dependencies": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-validate/node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-validate/node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" - }, - "node_modules/jest-watch-typeahead": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-1.1.0.tgz", - "integrity": "sha512-Va5nLSJTN7YFtC2jd+7wsoe1pNe5K4ShLux/E5iHEwlB9AxaxmggY7to9KUqKojhaJw3aXqt5WAb4jGPOolpEw==", - "dependencies": { - "ansi-escapes": "^4.3.1", - "chalk": "^4.0.0", - "jest-regex-util": "^28.0.0", - "jest-watcher": "^28.0.0", - "slash": "^4.0.0", - "string-length": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "jest": "^27.0.0 || ^28.0.0" - } + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" }, - "node_modules/jest-watch-typeahead/node_modules/@jest/console": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.3.tgz", - "integrity": "sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==", - "dependencies": { - "@jest/types": "^28.1.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^28.1.3", - "jest-util": "^28.1.3", - "slash": "^3.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, - "node_modules/jest-watch-typeahead/node_modules/@jest/console/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "engines": { - "node": ">=8" - } + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" }, - "node_modules/jest-watch-typeahead/node_modules/@jest/test-result": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-28.1.3.tgz", - "integrity": "sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg==", - "dependencies": { - "@jest/console": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "optional": true, + "peer": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": ">=6" } }, - "node_modules/jest-watch-typeahead/node_modules/@jest/types": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", - "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", + "node_modules/jsonc-parser": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", + "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", + "peer": true + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dependencies": { - "@jest/schemas": "^28.1.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "universalify": "^2.0.0" }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "node_modules/jest-watch-typeahead/node_modules/@types/yargs": { - "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", - "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", - "dependencies": { - "@types/yargs-parser": "*" + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/jest-watch-typeahead/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "optional": true, + "peer": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-watch-typeahead/node_modules/emittery": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", - "integrity": "sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" + "node": ">=0.6.0" } }, - "node_modules/jest-watch-typeahead/node_modules/jest-message-util": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", - "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", + "node_modules/jsx-ast-utils": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.4.tgz", + "integrity": "sha512-fX2TVdCViod6HwKEtSWGHs57oFhVfCMwieb9PuRDgjDPh5XeqJiHFFFJCHxU5cnTc3Bu/GRL+kPiFmw8XWOfKw==", "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^28.1.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^28.1.3", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": ">=4.0" } }, - "node_modules/jest-watch-typeahead/node_modules/jest-message-util/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "engines": { - "node": ">=8" + "node_modules/keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.0" } }, - "node_modules/jest-watch-typeahead/node_modules/jest-regex-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", - "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": ">=0.10.0" } }, - "node_modules/jest-watch-typeahead/node_modules/jest-util": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", - "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", - "dependencies": { - "@jest/types": "^28.1.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": ">=6" } }, - "node_modules/jest-watch-typeahead/node_modules/jest-watcher": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-28.1.3.tgz", - "integrity": "sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g==", - "dependencies": { - "@jest/test-result": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.10.2", - "jest-util": "^28.1.3", - "string-length": "^4.0.1" - }, + "node_modules/klona": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": ">= 8" } }, - "node_modules/jest-watch-typeahead/node_modules/jest-watcher/node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "node_modules/language-subtag-registry": { + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", + "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==" + }, + "node_modules/language-tags": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", + "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" + "language-subtag-registry": "~0.3.2" } }, - "node_modules/jest-watch-typeahead/node_modules/jest-watcher/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "dev": true, "dependencies": { - "ansi-regex": "^5.0.1" + "package-json": "^6.3.0" }, "engines": { "node": ">=8" } }, - "node_modules/jest-watch-typeahead/node_modules/pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "node_modules/launch-editor": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz", + "integrity": "sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==", "dependencies": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "picocolors": "^1.0.0", + "shell-quote": "^1.7.3" } }, - "node_modules/jest-watch-typeahead/node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "engines": { - "node": ">=10" + "node_modules/lazy-cache": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz", + "integrity": "sha512-7vp2Acd2+Kz4XkzxGxaB1FWOi8KjWIWsgdfD5MCb86DWvlLqhRPM+d6Pro3iNEL5VT9mstz5hKAlcd+QR6H3aA==", + "dependencies": { + "set-getter": "^0.1.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/jest-watch-typeahead/node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/jest-watch-typeahead/node_modules/string-length": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-5.0.1.tgz", - "integrity": "sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==", + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dependencies": { - "char-regex": "^2.0.0", - "strip-ansi": "^7.0.1" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" }, "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.8.0" } }, - "node_modules/jest-watch-typeahead/node_modules/string-length/node_modules/char-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-2.0.1.tgz", - "integrity": "sha512-oSvEeo6ZUD7NepqAat3RqoucZ5SeqLJgOvVIwkafu6IP3V0pO38s/ypdVUmDDK6qIIHNlYHJAKX9E7R7HoKElw==", + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", "engines": { - "node": ">=12.20" + "node": ">=10" } }, - "node_modules/jest-watch-typeahead/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/lint-staged": { + "version": "15.2.2", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.2.tgz", + "integrity": "sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==", + "dev": true, "dependencies": { - "ansi-regex": "^6.0.1" + "chalk": "5.3.0", + "commander": "11.1.0", + "debug": "4.3.4", + "execa": "8.0.1", + "lilconfig": "3.0.0", + "listr2": "8.0.1", + "micromatch": "4.0.5", + "pidtree": "0.6.0", + "string-argv": "0.3.2", + "yaml": "2.3.4" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" }, "engines": { - "node": ">=12" + "node": ">=18.12.0" }, "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "url": "https://opencollective.com/lint-staged" } }, - "node_modules/jest-watch-typeahead/node_modules/strip-ansi/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "node_modules/lint-staged/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, "engines": { - "node": ">=12" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-watcher": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", - "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", - "dependencies": { - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "jest-util": "^27.5.1", - "string-length": "^4.0.1" - }, + "node_modules/lint-staged/node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "dev": true, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=16" } }, - "node_modules/jest-watcher/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/lint-staged/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" }, "engines": { - "node": ">=10" + "node": ">=16.17" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "node_modules/lint-staged/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, "engines": { - "node": ">= 10.13.0" + "node": ">=16.17.0" } }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dependencies": { - "has-flag": "^4.0.0" - }, + "node_modules/lint-staged/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, "engines": { - "node": ">=10" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/jiti": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.1.tgz", - "integrity": "sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg==", - "bin": { - "jiti": "bin/jiti.js" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jquery": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.0.tgz", - "integrity": "sha512-umpJ0/k8X0MvD1ds0P9SfowREz2LenHsQaxSohMZ5OMNEU2r0tf8pdeEFTHMFxWVxKNyU9rTtK3CWzUCTKJUeQ==", - "dev": true - }, - "node_modules/js-base64": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", - "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==" - }, - "node_modules/js-cookie": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", - "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "node_modules/lint-staged/node_modules/lilconfig": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", + "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", + "dev": true, "engines": { "node": ">=14" } }, - "node_modules/js-tokens": { + "node_modules/lint-staged/node_modules/mimic-fn": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", - "dev": true - }, - "node_modules/jsdom": { - "version": "16.7.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", - "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "node_modules/lint-staged/node_modules/npm-run-path": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.2.0.tgz", + "integrity": "sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==", + "dev": true, "dependencies": { - "abab": "^2.0.5", - "acorn": "^8.2.4", - "acorn-globals": "^6.0.0", - "cssom": "^0.4.4", - "cssstyle": "^2.3.0", - "data-urls": "^2.0.0", - "decimal.js": "^10.2.1", - "domexception": "^2.0.1", - "escodegen": "^2.0.0", - "form-data": "^3.0.0", - "html-encoding-sniffer": "^2.0.1", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "saxes": "^5.0.1", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.1.0", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.5.0", - "ws": "^7.4.6", - "xml-name-validator": "^3.0.0" + "path-key": "^4.0.0" }, "engines": { - "node": ">=10" - }, - "peerDependencies": { - "canvas": "^2.5.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jsdom/node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" - }, - "node_modules/jsdom/node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", - "engines": { - "node": ">=8.3.0" + "node_modules/lint-staged/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "engines": { + "node": ">=12" }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "bin": { - "jsesc": "bin/jsesc" - }, + "node_modules/lint-staged/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, "engines": { - "node": ">=4" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", - "dev": true - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true + "node_modules/lint-staged/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "bin": { - "json5": "lib/cli.js" + "node_modules/lint-staged/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/yaml": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", + "dev": true, "engines": { - "node": ">=6" + "node": ">= 14" } }, - "node_modules/jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==" + "node_modules/list-item": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/list-item/-/list-item-1.1.1.tgz", + "integrity": "sha512-S3D0WZ4J6hyM8o5SNKWaMYB1ALSacPZ2nHGEuCjmHZ+dc03gFeNZoNDcqfcnO4vDhTZmNrqrpYZCdXsRh22bzw==", + "dependencies": { + "expand-range": "^1.8.1", + "extend-shallow": "^2.0.1", + "is-number": "^2.1.0", + "repeat-string": "^1.5.2" + }, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "node_modules/list-item/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", "dependencies": { - "universalify": "^2.0.0" + "is-extendable": "^0.1.0" }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/jsonpointer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", - "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "node_modules/list-item/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", "engines": { "node": ">=0.10.0" } }, - "node_modules/jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "dev": true, + "node_modules/list-item/node_modules/is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha512-QUzH43Gfb9+5yckcrSA0VBDwEtDUchrk4F6tfJZQuNzDJbEDB9cZNzSfXGQ1jqmdDY/kl41lUOWM9syA8z8jlg==", "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" + "kind-of": "^3.0.2" }, "engines": { - "node": ">=0.6.0" + "node": ">=0.10.0" } }, - "node_modules/jsx-ast-utils": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.4.tgz", - "integrity": "sha512-fX2TVdCViod6HwKEtSWGHs57oFhVfCMwieb9PuRDgjDPh5XeqJiHFFFJCHxU5cnTc3Bu/GRL+kPiFmw8XWOfKw==", + "node_modules/list-item/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "object.assign": "^4.1.4", - "object.values": "^1.1.6" + "is-buffer": "^1.1.5" }, "engines": { - "node": ">=4.0" + "node": ">=0.10.0" } }, - "node_modules/keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "node_modules/listr2": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.0.1.tgz", + "integrity": "sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==", "dev": true, "dependencies": { - "json-buffer": "3.0.0" + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.0.0", + "rfdc": "^1.3.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18.0.0" } }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "node_modules/listr2/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "node_modules/listr2/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/klona": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", - "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", + "node_modules/listr2/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/listr2/node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true + }, + "node_modules/listr2/node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, "engines": { - "node": ">= 8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/language-subtag-registry": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", - "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==" - }, - "node_modules/language-tags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", - "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", + "node_modules/listr2/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, "dependencies": { - "language-subtag-registry": "~0.3.2" + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/latest-version": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", - "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, "dependencies": { - "package-json": "^6.3.0" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/launch-editor": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz", - "integrity": "sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==", + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", + "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==", + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dependencies": { - "picocolors": "^1.0.0", - "shell-quote": "^1.7.3" + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/left-pad": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", - "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==", - "deprecated": "use String.prototype.padStart()", + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==" + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", "dev": true }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "engines": { - "node": ">=6" + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, + "node_modules/lodash.flow": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz", + "integrity": "sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw==" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" + }, + "node_modules/lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "dependencies": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" } }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "node_modules/lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" + "lodash._reinterpolate": "^3.0.0" + } + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "node_modules/log-symbols/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/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" - }, - "node_modules/load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "node_modules/log-update": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", + "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", "dev": true, "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" + "ansi-escapes": "^6.2.0", + "cli-cursor": "^4.0.0", + "slice-ansi": "^7.0.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" }, "engines": { - "node": ">=4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/load-json-file/node_modules/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "node_modules/log-update/node_modules/ansi-escapes": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz", + "integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==", "dev": true, "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" + "type-fest": "^3.0.0" }, "engines": { - "node": ">=4" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/load-json-file/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, "engines": { - "node": ">=4" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/load-json-file/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, "engines": { - "node": ">=4" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "node_modules/log-update/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "dev": true, + "dependencies": { + "get-east-asian-width": "^1.0.0" + }, "engines": { - "node": ">=6.11.5" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/loader-utils": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", - "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==", + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, "engines": { - "node": ">= 12.13.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/log-update/node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dev": true, "dependencies": { - "p-locate": "^4.1.0" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash._baseisequal": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/lodash._baseisequal/-/lodash._baseisequal-3.0.7.tgz", - "integrity": "sha512-U+3GsNEZj9ebI03ncLC2pLmYVjgtYZEwdkAPO7UGgtGvAz36JVFPAQUufpSaVL93Cz5arc6JGRKZRhaOhyVJYA==", + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "dependencies": { - "lodash.isarray": "^3.0.0", - "lodash.istypedarray": "^3.0.0", - "lodash.keys": "^3.0.0" + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/lodash._bindcallback": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", - "integrity": "sha512-2wlI0JRAGX8WEf4Gm1p/mv/SZ+jLijpj0jyaE/AXeuQphzCgD8ZQW4oSpoN8JAopujOFGU3KMuq7qfHBWlGpjQ==", - "dev": true - }, - "node_modules/lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha512-RrL9VxMEPyDMHOd9uFbvMe8X55X16/cGM5IgOKgRElQZutpX89iS6vwl64duTV1/16w5JY7tuFNXqoekmh1EmA==", - "dev": true - }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "dev": true - }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" - }, - "node_modules/lodash.escape": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz", - "integrity": "sha512-nXEOnb/jK9g0DYMr1/Xvq6l5xMD7GDG55+GSYIYmS0G4tBk/hURD4JR9WCavs04t33WmJx9kCyp9vJ+mr4BOUw==" - }, - "node_modules/lodash.flattendeep": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==" - }, - "node_modules/lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==", - "dev": true - }, - "node_modules/lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha512-JwObCrNJuT0Nnbuecmqr5DgtuBppuCvGD9lxjFpAzwnVtdGoDQ1zig+5W8k5/6Gcn0gZ3936HDAlGd28i7sOGQ==", - "dev": true - }, - "node_modules/lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" - }, - "node_modules/lodash.istypedarray": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/lodash.istypedarray/-/lodash.istypedarray-3.0.6.tgz", - "integrity": "sha512-lGWJ6N8AA3KSv+ZZxlTdn4f6A7kMfpJboeyvbFdE7IU9YAgweODqmOgdUHOA+c6lVWeVLysdaxciFXi+foVsWw==", - "dev": true + "node_modules/log-update/node_modules/type-fest": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha512-CuBsapFjcubOGMn3VD+24HOAPxM79tH+V6ivJL3CHYjtrawauDJHUk//Yew9Hvc6e9rbCrURGk8z6PC+8WJBfQ==", + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, "dependencies": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" - }, - "node_modules/lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" - }, - "node_modules/lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" - }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -16314,12 +16307,14 @@ "node_modules/lunr": { "version": "2.3.9", "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==" + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "peer": true }, "node_modules/lz-string": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, "bin": { "lz-string": "bin/bin.js" } @@ -16354,61 +16349,6 @@ "semver": "bin/semver.js" } }, - "node_modules/make-fetch-happen": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", - "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^16.1.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.3", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "engines": { - "node": ">= 10" - } - }, - "node_modules/make-fetch-happen/node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/make-fetch-happen/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "engines": { - "node": ">=12" - } - }, "node_modules/makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", @@ -16417,19 +16357,12 @@ "tmpl": "1.0.5" } }, - "node_modules/map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/map-obj": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "optional": true, + "peer": true, "engines": { "node": ">=8" }, @@ -16437,13 +16370,34 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==", - "dev": true, - "dependencies": { - "object-visit": "^1.0.0" + "node_modules/markdown-link": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/markdown-link/-/markdown-link-0.1.1.tgz", + "integrity": "sha512-TurLymbyLyo+kAUUAV9ggR9EPcDjP/ctlv9QAFiqUH7c+t6FlsbivPo9OKTU8xdOx9oNd2drW/Fi5RRElQbUqA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/markdown-toc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/markdown-toc/-/markdown-toc-1.2.0.tgz", + "integrity": "sha512-eOsq7EGd3asV0oBfmyqngeEIhrbkc7XVP63OwcJBIhH2EpG2PzFcbZdhy1jutXSlRBBVMNXHvMtSr5LAxSUvUg==", + "dependencies": { + "concat-stream": "^1.5.2", + "diacritics-map": "^0.1.0", + "gray-matter": "^2.1.0", + "lazy-cache": "^2.0.2", + "list-item": "^1.1.1", + "markdown-link": "^0.1.1", + "minimist": "^1.2.0", + "mixin-deep": "^1.1.3", + "object.pick": "^1.2.0", + "remarkable": "^1.7.1", + "repeat-string": "^1.6.1", + "strip-color": "^0.1.0" + }, + "bin": { + "markdown-toc": "cli.js" }, "engines": { "node": ">=0.10.0" @@ -16453,6 +16407,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "peer": true, "bin": { "marked": "bin/marked.js" }, @@ -16460,6 +16415,11 @@ "node": ">= 12" } }, + "node_modules/math-random": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", + "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==" + }, "node_modules/mdn-data": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", @@ -16488,6 +16448,8 @@ "version": "9.0.0", "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", + "optional": true, + "peer": true, "dependencies": { "@types/minimist": "^1.2.0", "camelcase-keys": "^6.2.2", @@ -16513,6 +16475,8 @@ "version": "0.18.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "optional": true, + "peer": true, "engines": { "node": ">=10" }, @@ -16615,6 +16579,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "devOptional": true, "engines": { "node": ">=4" } @@ -16637,21 +16602,6 @@ "webpack": "^5.0.0" } }, - "node_modules/mini-css-extract-plugin/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/mini-css-extract-plugin/node_modules/ajv-keywords": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", @@ -16663,11 +16613,6 @@ "ajv": "^8.8.2" } }, - "node_modules/mini-css-extract-plugin/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, "node_modules/mini-css-extract-plugin/node_modules/schema-utils": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", @@ -16714,6 +16659,8 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "optional": true, + "peer": true, "dependencies": { "arrify": "^1.0.1", "is-plain-obj": "^1.1.0", @@ -16727,6 +16674,8 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "optional": true, + "peer": true, "dependencies": { "yallist": "^4.0.0" }, @@ -16738,6 +16687,8 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "optional": true, + "peer": true, "dependencies": { "minipass": "^3.0.0" }, @@ -16745,26 +16696,12 @@ "node": ">= 8" } }, - "node_modules/minipass-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", - "dependencies": { - "minipass": "^3.1.6", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, "node_modules/minipass-flush": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "optional": true, + "peer": true, "dependencies": { "minipass": "^3.0.0" }, @@ -16776,6 +16713,8 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "optional": true, + "peer": true, "dependencies": { "minipass": "^3.0.0" }, @@ -16787,6 +16726,8 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "optional": true, + "peer": true, "dependencies": { "minipass": "^3.0.0" }, @@ -16797,12 +16738,16 @@ "node_modules/minipass/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true, + "peer": true }, "node_modules/minizlib": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "optional": true, + "peer": true, "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" @@ -16814,13 +16759,14 @@ "node_modules/minizlib/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true, + "peer": true }, "node_modules/mixin-deep": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, "dependencies": { "for-in": "^1.0.2", "is-extendable": "^1.0.1" @@ -16833,6 +16779,8 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "optional": true, + "peer": true, "bin": { "mkdirp": "bin/cmd.js" }, @@ -16840,11 +16788,6 @@ "node": ">=10" } }, - "node_modules/moo": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", - "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==" - }, "node_modules/mrmime": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", @@ -16871,6 +16814,11 @@ "multicast-dns": "cli.js" } }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -16884,12 +16832,14 @@ "node_modules/nan": { "version": "2.17.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", - "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==" + "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", + "optional": true, + "peer": true }, "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "funding": [ { "type": "github", @@ -16903,28 +16853,6 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -16935,32 +16863,6 @@ "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==" }, - "node_modules/nearley": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", - "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", - "dependencies": { - "commander": "^2.19.0", - "moo": "^0.5.0", - "railroad-diagrams": "^1.0.0", - "randexp": "0.4.6" - }, - "bin": { - "nearley-railroad": "bin/nearley-railroad.js", - "nearley-test": "bin/nearley-test.js", - "nearley-unparse": "bin/nearley-unparse.js", - "nearleyc": "bin/nearleyc.js" - }, - "funding": { - "type": "individual", - "url": "https://nearley.js.org/#give-to-nearley" - } - }, - "node_modules/nearley/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -16974,12 +16876,6 @@ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, "node_modules/no-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", @@ -17039,6 +16935,8 @@ "version": "8.4.1", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "optional": true, + "peer": true, "dependencies": { "env-paths": "^2.2.0", "glob": "^7.1.4", @@ -17062,6 +16960,8 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "optional": true, + "peer": true, "dependencies": { "@gar/promisify": "^1.0.1", "semver": "^7.3.5" @@ -17072,6 +16972,8 @@ "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", "deprecated": "This functionality has been moved to @npmcli/fs", + "optional": true, + "peer": true, "dependencies": { "mkdirp": "^1.0.4", "rimraf": "^3.0.2" @@ -17084,6 +16986,8 @@ "version": "15.3.0", "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "optional": true, + "peer": true, "dependencies": { "@npmcli/fs": "^1.0.0", "@npmcli/move-file": "^1.0.1", @@ -17112,6 +17016,8 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "optional": true, + "peer": true, "dependencies": { "yallist": "^4.0.0" }, @@ -17123,6 +17029,8 @@ "version": "9.1.0", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "optional": true, + "peer": true, "dependencies": { "agentkeepalive": "^4.1.3", "cacache": "^15.2.0", @@ -17149,6 +17057,8 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "optional": true, + "peer": true, "dependencies": { "minipass": "^3.1.0", "minipass-sized": "^1.0.3", @@ -17165,6 +17075,8 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "optional": true, + "peer": true, "dependencies": { "agent-base": "^6.0.2", "debug": "^4.3.3", @@ -17178,6 +17090,8 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "optional": true, + "peer": true, "dependencies": { "minipass": "^3.1.1" }, @@ -17189,6 +17103,8 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "optional": true, + "peer": true, "dependencies": { "unique-slug": "^2.0.0" } @@ -17197,6 +17113,8 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "optional": true, + "peer": true, "dependencies": { "imurmurhash": "^0.1.4" } @@ -17204,7 +17122,9 @@ "node_modules/node-gyp/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true, + "peer": true }, "node_modules/node-int64": { "version": "0.4.0", @@ -17212,15 +17132,17 @@ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" }, "node_modules/node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==" + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" }, "node_modules/node-sass": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-9.0.0.tgz", - "integrity": "sha512-yltEuuLrfH6M7Pq2gAj5B6Zm7m+gdZoG66wTqG6mIZV/zijq3M2OO2HswtT6oBspPyFhHDcaxWpsBm0fRNDHPg==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-7.0.3.tgz", + "integrity": "sha512-8MIlsY/4dXUkJDYht9pIWBhMil3uHmE8b/AdJPjmFn1nBx9X9BASzfzmsCy0uCCb8eqI3SYYzVPDswWqSx7gjw==", "hasInstallScript": true, + "optional": true, + "peer": true, "dependencies": { "async-foreach": "^0.1.3", "chalk": "^4.1.2", @@ -17229,25 +17151,42 @@ "get-stdin": "^4.0.1", "glob": "^7.0.3", "lodash": "^4.17.15", - "make-fetch-happen": "^10.0.4", "meow": "^9.0.0", - "nan": "^2.17.0", + "nan": "^2.13.2", "node-gyp": "^8.4.1", + "npmlog": "^5.0.0", + "request": "^2.88.0", "sass-graph": "^4.0.1", "stdout-stream": "^1.4.0", - "true-case-path": "^2.2.1" + "true-case-path": "^1.0.2" }, "bin": { "node-sass": "bin/node-sass" }, "engines": { - "node": ">=16" + "node": ">=12" + } + }, + "node_modules/node-sass/node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "optional": true, + "peer": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" } }, "node_modules/node-sass/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "optional": true, + "peer": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -17259,10 +17198,46 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/node-sass/node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "optional": true, + "peer": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-sass/node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "optional": true, + "peer": true, + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "node_modules/nopt": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "optional": true, + "peer": true, "dependencies": { "abbrev": "1" }, @@ -17277,6 +17252,8 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "optional": true, + "peer": true, "dependencies": { "hosted-git-info": "^4.0.1", "is-core-module": "^2.5.0", @@ -17329,6 +17306,8 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "optional": true, + "peer": true, "dependencies": { "are-we-there-yet": "^3.0.0", "console-control-strings": "^1.1.0", @@ -17359,7 +17338,8 @@ "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true, + "optional": true, + "peer": true, "engines": { "node": "*" } @@ -17372,91 +17352,6 @@ "node": ">=0.10.0" } }, - "node_modules/object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==", - "dev": true, - "dependencies": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/object-hash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", @@ -17466,24 +17361,9 @@ } }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -17496,25 +17376,13 @@ "node": ">= 0.4" } }, - "node_modules/object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==", - "dev": true, - "dependencies": { - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, @@ -17526,26 +17394,26 @@ } }, "node_modules/object.entries": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", - "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" } }, "node_modules/object.fromentries": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", - "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", + "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "engines": { "node": ">= 0.4" @@ -17572,13 +17440,28 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object.groupby": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", + "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1" + } + }, "node_modules/object.hasown": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", - "integrity": "sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.4.tgz", + "integrity": "sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==", "dependencies": { - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -17588,7 +17471,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", - "dev": true, "dependencies": { "isobject": "^3.0.1" }, @@ -17597,13 +17479,13 @@ } }, "node_modules/object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", + "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "engines": { "node": ">= 0.4" @@ -17711,6 +17593,74 @@ "node": ">= 0.8.0" } }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/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/ora/node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ora/node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/p-cancelable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", @@ -17720,15 +17670,6 @@ "node": ">=6" } }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -17758,6 +17699,8 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "optional": true, + "peer": true, "dependencies": { "aggregate-error": "^3.0.0" }, @@ -17871,29 +17814,11 @@ "node": ">=0.10.0" } }, - "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dependencies": { - "entities": "^4.4.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", - "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", - "dependencies": { - "domhandler": "^5.0.2", - "parse5": "^7.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, + "node_modules/parse-srcset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", + "integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==" + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -17911,15 +17836,6 @@ "tslib": "^2.0.3" } }, - "node_modules/pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -17949,14 +17865,6 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, - "node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dependencies": { - "isarray": "0.0.1" - } - }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -17986,6 +17894,18 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", @@ -18066,25 +17986,18 @@ "node": ">=4" } }, - "node_modules/pn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", - "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", - "dev": true - }, - "node_modules/posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==", - "dev": true, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, "node_modules/postcss": { - "version": "8.4.26", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.26.tgz", - "integrity": "sha512-jrXHFF8iTloAenySjM/ob3gSj7pCu0Ji49hnjqzsgSRa50hkWCKD0HQ+gMNJkW38jBI68MpAAg7ZWwHwX8NMMw==", + "version": "8.4.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", + "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", "funding": [ { "type": "opencollective", @@ -18100,7 +18013,7 @@ } ], "dependencies": { - "nanoid": "^3.3.6", + "nanoid": "^3.3.7", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -19361,14 +19274,14 @@ } }, "node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", "bin": { - "prettier": "bin-prettier.js" + "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">=10.13.0" + "node": ">=14" }, "funding": { "url": "https://github.com/prettier/prettier?sponsor=1" @@ -19378,6 +19291,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, "dependencies": { "fast-diff": "^1.1.2" }, @@ -19409,6 +19323,7 @@ "version": "26.6.2", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "dev": true, "dependencies": { "@jest/types": "^26.6.2", "ansi-regex": "^5.0.0", @@ -19423,6 +19338,7 @@ "version": "26.6.2", "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "dev": true, "dependencies": { "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", @@ -19438,6 +19354,7 @@ "version": "15.0.15", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.15.tgz", "integrity": "sha512-IziEYMU9XoVj8hWg7k+UJrXALkGFjWJhn5QFEv9q4p+v40oZhSuC135M38st8XPjICL7Ey4TV64ferBGUoJhBg==", + "dev": true, "dependencies": { "@types/yargs-parser": "*" } @@ -19446,6 +19363,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -19460,7 +19378,8 @@ "node_modules/pretty-format/node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true }, "node_modules/process-nextick-args": { "version": "2.0.1", @@ -19478,12 +19397,16 @@ "node_modules/promise-inflight": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==" + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "optional": true, + "peer": true }, "node_modules/promise-retry": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "optional": true, + "peer": true, "dependencies": { "err-code": "^2.0.2", "retry": "^0.12.0" @@ -19514,16 +19437,6 @@ "react-is": "^16.13.1" } }, - "node_modules/prop-types-exact": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/prop-types-exact/-/prop-types-exact-1.2.0.tgz", - "integrity": "sha512-K+Tk3Kd9V0odiXFP9fwDHUYRyvK3Nun3GVyPapSIs5OBkITAm15W0CPFD/YKTkMUAbc0b9CUwRQp2ybiBIq+eA==", - "dependencies": { - "has": "^1.0.3", - "object.assign": "^4.1.0", - "reflect.ownkeys": "^0.2.0" - } - }, "node_modules/prop-types-extra": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz", @@ -19652,6 +19565,8 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "optional": true, + "peer": true, "engines": { "node": ">=8" } @@ -19664,21 +19579,25 @@ "performance-now": "^2.1.0" } }, - "node_modules/railroad-diagrams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", - "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==" - }, - "node_modules/randexp": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", - "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", + "node_modules/randomatic": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", "dependencies": { - "discontinuous-range": "1.0.0", - "ret": "~0.1.10" + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" }, "engines": { - "node": ">=0.12" + "node": ">= 0.10.0" + } + }, + "node_modules/randomatic/node_modules/is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "engines": { + "node": ">=0.10.0" } }, "node_modules/randombytes": { @@ -19782,6 +19701,28 @@ "node": ">=14" } }, + "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==", + "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.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, "node_modules/react-async-script": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/react-async-script/-/react-async-script-1.2.0.tgz", @@ -19823,25 +19764,6 @@ } } }, - "node_modules/react-calendar": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/react-calendar/-/react-calendar-4.3.0.tgz", - "integrity": "sha512-TyCv8NbXnqXADyXNtMG0szkGvJNH3NG/WMTEE2q6g3RqAsFNyHwYbQD5Kvb6jRV/CqO0WB+oMCtkxblprdeT5A==", - "dependencies": { - "@types/react": "*", - "@wojtekmaj/date-utils": "^1.1.3", - "clsx": "^1.2.1", - "get-user-locale": "^2.2.1", - "prop-types": "^15.6.0" - }, - "funding": { - "url": "https://github.com/wojtekmaj/react-calendar?sponsor=1" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, "node_modules/react-datepicker": { "version": "4.16.0", "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.16.0.tgz", @@ -20021,6 +19943,14 @@ } } }, + "node_modules/react-icons": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.12.0.tgz", + "integrity": "sha512-IBaDuHiShdZqmfc/TwHu6+d6k2ltNCf3AszxNmjJc1KUfXdEeRJOKyNvLmAHaarhzGmTSVygNdyu8/opXv2gaw==", + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-infinite-scroll-component": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/react-infinite-scroll-component/-/react-infinite-scroll-component-6.1.0.tgz", @@ -20107,46 +20037,35 @@ } }, "node_modules/react-router": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", - "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", + "version": "6.22.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.2.tgz", + "integrity": "sha512-YD3Dzprzpcq+tBMHBS822tCjnWD3iIZbTeSXMY9LPSG541EfoBGyZ3bS25KEnaZjLcmQpw2AVLkFyfgXY8uvcw==", "dependencies": { - "@babel/runtime": "^7.12.13", - "history": "^4.9.0", - "hoist-non-react-statics": "^3.1.0", - "loose-envify": "^1.3.1", - "path-to-regexp": "^1.7.0", - "prop-types": "^15.6.2", - "react-is": "^16.6.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" + "@remix-run/router": "1.15.2" + }, + "engines": { + "node": ">=14.0.0" }, "peerDependencies": { - "react": ">=15" + "react": ">=16.8" } }, "node_modules/react-router-dom": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.4.tgz", - "integrity": "sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ==", + "version": "6.22.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.2.tgz", + "integrity": "sha512-WgqxD2qySEIBPZ3w0sHH+PUAiamDeszls9tzqMPBDA1YYVucTBXLU7+gtRfcSnhe92A3glPnvSxK2dhNoAVOIQ==", "dependencies": { - "@babel/runtime": "^7.12.13", - "history": "^4.9.0", - "loose-envify": "^1.3.1", - "prop-types": "^15.6.2", - "react-router": "5.3.4", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" + "@remix-run/router": "1.15.2", + "react-router": "6.22.2" + }, + "engines": { + "node": ">=14.0.0" }, "peerDependencies": { - "react": ">=15" + "react": ">=16.8", + "react-dom": ">=16.8" } }, - "node_modules/react-router/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, "node_modules/react-scripts": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", @@ -20219,6 +20138,56 @@ } } }, + "node_modules/react-scripts/node_modules/babel-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", + "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", + "dependencies": { + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/react-scripts/node_modules/babel-plugin-jest-hoist": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", + "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/react-scripts/node_modules/babel-preset-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", + "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", + "dependencies": { + "babel-plugin-jest-hoist": "^27.5.1", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/react-scripts/node_modules/camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", @@ -20230,40 +20199,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/react-shallow-renderer": { - "version": "16.15.0", - "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz", - "integrity": "sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==", - "dev": true, + "node_modules/react-scripts/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": { - "object-assign": "^4.1.1", - "react-is": "^16.12.0 || ^17.0.0 || ^18.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, - "peerDependencies": { - "react": "^16.0.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/react-test-renderer": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-17.0.2.tgz", - "integrity": "sha512-yaQ9cB89c17PUb0x6UfWRs7kQCorVdHlutU1boVPEsB8IDZH6n9tHxMacc3y0JoXOJUsZb/t/Mb8FUWMKaM7iQ==", - "dev": true, - "dependencies": { - "object-assign": "^4.1.1", - "react-is": "^17.0.2", - "react-shallow-renderer": "^16.13.1", - "scheduler": "^0.20.2" + "engines": { + "node": ">=10" }, - "peerDependencies": { - "react": "17.0.2" + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/react-test-renderer/node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - }, "node_modules/react-toastify": { "version": "9.1.3", "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.1.3.tgz", @@ -20303,6 +20253,8 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "optional": true, + "peer": true, "dependencies": { "@types/normalize-package-data": "^2.4.0", "normalize-package-data": "^2.5.0", @@ -20317,6 +20269,8 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "optional": true, + "peer": true, "dependencies": { "find-up": "^4.1.0", "read-pkg": "^5.2.0", @@ -20333,6 +20287,8 @@ "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "optional": true, + "peer": true, "engines": { "node": ">=8" } @@ -20340,12 +20296,16 @@ "node_modules/read-pkg/node_modules/hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "optional": true, + "peer": true }, "node_modules/read-pkg/node_modules/normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "optional": true, + "peer": true, "dependencies": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", @@ -20357,6 +20317,8 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "optional": true, + "peer": true, "bin": { "semver": "bin/semver" } @@ -20365,6 +20327,8 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "optional": true, + "peer": true, "engines": { "node": ">=8" } @@ -20393,18 +20357,6 @@ "node": ">=8.10.0" } }, - "node_modules/realpath-native": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", - "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", - "dev": true, - "dependencies": { - "util.promisify": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/recursive-readdir": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", @@ -20420,6 +20372,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "devOptional": true, "dependencies": { "indent-string": "^4.0.0", "strip-indent": "^3.0.0" @@ -20444,10 +20397,25 @@ "redux": "^4" } }, - "node_modules/reflect.ownkeys": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz", - "integrity": "sha512-qOLsBKHCpSOFKK1NUOCGC5VyeufB6lEsFe92AL2bhIJsacZS1qdoOZSbPk3MYKuT2cFlRDnulKXuuElIrMjGUg==" + "node_modules/reflect.getprototypeof": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/regenerate": { "version": "1.4.2", @@ -20471,39 +20439,27 @@ "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, "node_modules/regenerator-transform": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.1.tgz", - "integrity": "sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==", + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", "dependencies": { "@babel/runtime": "^7.8.4" } }, - "node_modules/regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/regex-parser": { "version": "2.2.11", "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.11.tgz", "integrity": "sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q==" }, "node_modules/regexp.prototype.flags": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", - "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -20579,11 +20535,20 @@ "node": ">= 0.10" } }, - "node_modules/remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", - "dev": true + "node_modules/remarkable": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/remarkable/-/remarkable-1.7.4.tgz", + "integrity": "sha512-e6NKUXgX95whv7IgddywbeN/ItCkWbISmc2DiqHJb0wTrqZIexqdco5b8Z3XZoo/48IdNVKM9ZCvTPJ4F5uvhg==", + "dependencies": { + "argparse": "^1.0.10", + "autolinker": "~0.28.0" + }, + "bin": { + "remarkable": "bin/remarkable.js" + }, + "engines": { + "node": ">= 0.10.0" + } }, "node_modules/renderkid": { "version": "3.0.0", @@ -20682,7 +20647,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -20691,7 +20655,6 @@ "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", - "dev": true, "engines": { "node": ">=0.10" } @@ -20701,7 +20664,8 @@ "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dev": true, + "optional": true, + "peer": true, "dependencies": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", @@ -20717,68 +20681,23 @@ "json-stringify-safe": "~5.0.1", "mime-types": "~2.1.19", "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/request-promise-core": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", - "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", - "dev": true, - "dependencies": { - "lodash": "^4.17.19" - }, - "engines": { - "node": ">=0.10.0" - }, - "peerDependencies": { - "request": "^2.34" - } - }, - "node_modules/request-promise-native": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz", - "integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==", - "deprecated": "request-promise-native has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142", - "dev": true, - "dependencies": { - "request-promise-core": "1.1.4", - "stealthy-require": "^1.1.1", - "tough-cookie": "^2.3.3" - }, - "engines": { - "node": ">=0.12.0" - }, - "peerDependencies": { - "request": "^2.34" - } - }, - "node_modules/request-promise-native/node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" }, "engines": { - "node": ">=0.8" + "node": ">= 6" } }, "node_modules/request/node_modules/form-data": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, + "optional": true, + "peer": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", @@ -20792,7 +20711,8 @@ "version": "6.5.3", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=0.6" } @@ -20801,7 +20721,8 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, + "optional": true, + "peer": true, "dependencies": { "psl": "^1.1.28", "punycode": "^2.1.1" @@ -20815,7 +20736,8 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "dev": true, + "optional": true, + "peer": true, "bin": { "uuid": "bin/uuid" } @@ -20836,12 +20758,6 @@ "node": ">=0.10.0" } }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -20853,11 +20769,11 @@ "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==" }, "node_modules/resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dependencies": { - "is-core-module": "^2.11.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -20950,17 +20866,14 @@ "node": ">=4" } }, - "node_modules/resolve-pathname": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", - "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" - }, - "node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", - "deprecated": "https://github.com/lydell/resolve-url#deprecated", - "dev": true + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } }, "node_modules/resolve-url-loader": { "version": "4.0.0", @@ -21056,23 +20969,33 @@ "lowercase-keys": "^1.0.0" } }, + "node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/restructure": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/restructure/-/restructure-3.0.0.tgz", "integrity": "sha512-Xj8/MEIhhfj9X2rmD9iJ4Gga9EFqVlpMj3vfLnV2r/Mh5jRMryNV+6lWh9GdJtDBcBSPIqzRdfBQ3wDtNFv/uw==" }, - "node_modules/ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "engines": { - "node": ">=0.12" - } - }, "node_modules/retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "optional": true, + "peer": true, "engines": { "node": ">= 4" } @@ -21086,6 +21009,12 @@ "node": ">=0.10.0" } }, + "node_modules/rfdc": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", + "dev": true + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -21150,22 +21079,12 @@ "randombytes": "^2.1.0" } }, - "node_modules/rst-selector-parser": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz", - "integrity": "sha512-nDG1rZeP6oFTLN6yNDV/uiAvs1+FS/KlrEwh7+y7dpuApDBy6bI2HTBcc0/V8lv9OTqfyD34eF7au2pm8aBbhA==", - "dependencies": { - "lodash.flattendeep": "^4.4.0", - "nearley": "^2.7.10" - } - }, - "node_modules/rsvp": { - "version": "4.8.5", - "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", - "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==", - "dev": true, + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", "engines": { - "node": "6.* || >= 7.*" + "node": ">=0.12.0" } }, "node_modules/run-parallel": { @@ -21190,13 +21109,21 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/safe-array-concat": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", - "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", "has-symbols": "^1.0.3", "isarray": "^2.0.5" }, @@ -21207,11 +21134,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/safe-array-concat/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -21231,325 +21153,46 @@ } ] }, - "node_modules/safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==", - "dev": true, - "dependencies": { - "ret": "~0.1.10" - } - }, - "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/sane": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz", - "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", - "deprecated": "some dependency vulnerabilities fixed, support for node < 10 dropped, and newer ECMAScript syntax/features added", - "dev": true, - "dependencies": { - "@cnakazawa/watch": "^1.0.3", - "anymatch": "^2.0.0", - "capture-exit": "^2.0.0", - "exec-sh": "^0.3.2", - "execa": "^1.0.0", - "fb-watchman": "^2.0.0", - "micromatch": "^3.1.4", - "minimist": "^1.1.1", - "walker": "~1.0.5" - }, - "bin": { - "sane": "src/cli.js" - }, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/sane/node_modules/anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "dependencies": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, - "node_modules/sane/node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/sane/node_modules/execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "dependencies": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/sane/node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/sane/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", - "dev": true, - "dependencies": { - "remove-trailing-separator": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", - "dev": true, - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/sane/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/sane/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/sane/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "dev": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", - "dev": true, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/sane/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sanitize-html": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.12.1.tgz", + "integrity": "sha512-Plh+JAn0UVDpBRP/xEjsk+xDCoOvMBwQUf/K+/cBAVuTbtX8bj2VB7S1sL1dssVpykqp0/KPSesHrqXtokVBpA==", "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" + "deepmerge": "^4.2.2", + "escape-string-regexp": "^4.0.0", + "htmlparser2": "^8.0.0", + "is-plain-object": "^5.0.0", + "parse-srcset": "^1.0.2", + "postcss": "^8.3.11" + } + }, + "node_modules/sanitize-html/node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "engines": { + "node": ">=0.10.0" } }, "node_modules/sanitize.css": { @@ -21557,10 +21200,29 @@ "resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-13.0.0.tgz", "integrity": "sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA==" }, + "node_modules/sass": { + "version": "1.71.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.71.1.tgz", + "integrity": "sha512-wovtnV2PxzteLlfNzbgm1tFXPLoZILYAMJtvoXXkD7/+1uP41eKkIt1ypWq5/q2uT94qHjXehEYfmjKOvjL9sg==", + "devOptional": true, + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/sass-graph": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-4.0.1.tgz", "integrity": "sha512-5YCfmGBmxoIRYHnKK2AKzrAkCoQ8ozO+iumT8K4tXJXRVCPf+7s1/9KxTSW3Rbvf+7Y7b4FR3mWyLnQr3PHocA==", + "optional": true, + "peer": true, "dependencies": { "glob": "^7.0.0", "lodash": "^4.17.11", @@ -21578,6 +21240,8 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "optional": true, + "peer": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -21591,6 +21255,8 @@ "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "optional": true, + "peer": true, "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -21608,6 +21274,8 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "optional": true, + "peer": true, "engines": { "node": ">=12" } @@ -21691,10 +21359,40 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/schema-utils/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/schema-utils/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/schema-utils/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, "node_modules/scss-tokenizer": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.4.3.tgz", "integrity": "sha512-raKLgf1LI5QMQnG+RxHz6oK0sL3x3I4FN2UDLqgLOGO8hodECNnNh5BXn7fAyBxrA8zVzdQizQ6XjNJQ+uBwMw==", + "optional": true, + "peer": true, "dependencies": { "js-base64": "^2.4.9", "source-map": "^0.7.3" @@ -21704,6 +21402,8 @@ "version": "0.7.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "optional": true, + "peer": true, "engines": { "node": ">= 8" } @@ -21922,40 +21622,47 @@ "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "optional": true, + "peer": true }, - "node_modules/set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dependencies": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, - "node_modules/set-value/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dependencies": { - "is-extendable": "^0.1.0" + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, - "node_modules/set-value/node_modules/is-extendable": { + "node_modules/set-getter": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "dev": true, + "resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.1.tgz", + "integrity": "sha512-9sVWOy+gthr+0G9DzqqLaYNA7+5OKkSmcqjL9cBpDEaZrr3ShQlyX2cZ/O/ozE41oxn/Tt0LGEM/w4Rub3A3gw==", + "dependencies": { + "to-object-path": "^0.3.0" + }, "engines": { "node": ">=0.10.0" } @@ -21993,9 +21700,10 @@ } }, "node_modules/shiki": { - "version": "0.14.3", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.3.tgz", - "integrity": "sha512-U3S/a+b0KS+UkTyMjoNojvTgrBHjgp7L6ovhFVZsXmBGnVdQ4K4U9oK0z63w538S91ATngv1vXigHCSWOwnr+g==", + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.7.tgz", + "integrity": "sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg==", + "peer": true, "dependencies": { "ansi-sequence-parser": "^1.1.0", "jsonc-parser": "^3.2.0", @@ -22004,13 +21712,17 @@ } }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -22048,203 +21760,57 @@ "node": ">=8" } }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "dependencies": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "dependencies": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "dependencies": { - "kind-of": "^3.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/snapdragon/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", "dev": true, "dependencies": { - "is-extendable": "^0.1.0" + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" + "node": ">=12" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/snapdragon/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" + "node": ">=12" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/snapdragon/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "node": ">=12" }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "dev": true, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/snapdragon/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "optional": true, + "peer": true, "engines": { - "node": ">=0.10.0" + "node": ">= 6.0.0", + "npm": ">= 3.0.0" } }, - "node_modules/snapdragon/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, "node_modules/sockjs": { "version": "0.3.24", "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", @@ -22259,6 +21825,8 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "optional": true, + "peer": true, "dependencies": { "ip": "^2.0.0", "smart-buffer": "^4.2.0" @@ -22268,19 +21836,6 @@ "npm": ">= 3.0.0" } }, - "node_modules/socks-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", - "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - }, - "engines": { - "node": ">= 10" - } - }, "node_modules/source-list-map": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", @@ -22322,20 +21877,6 @@ "webpack": "^5.0.0" } }, - "node_modules/source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", - "dev": true, - "dependencies": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, "node_modules/source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", @@ -22353,13 +21894,6 @@ "node": ">=0.10.0" } }, - "node_modules/source-map-url": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", - "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", - "deprecated": "See https://github.com/lydell/source-map-url#deprecated", - "dev": true - }, "node_modules/sourcemap-codec": { "version": "1.4.8", "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", @@ -22370,6 +21904,8 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "optional": true, + "peer": true, "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -22378,12 +21914,16 @@ "node_modules/spdx-exceptions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "optional": true, + "peer": true }, "node_modules/spdx-expression-parse": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "optional": true, + "peer": true, "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -22392,7 +21932,9 @@ "node_modules/spdx-license-ids": { "version": "3.0.13", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", - "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==" + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", + "optional": true, + "peer": true }, "node_modules/spdy": { "version": "4.0.2", @@ -22422,28 +21964,17 @@ "wbuf": "^1.7.3" } }, - "node_modules/split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, "node_modules/sshpk": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", - "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", - "dev": true, + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "optional": true, + "peer": true, "dependencies": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -22464,17 +21995,6 @@ "node": ">=0.10.0" } }, - "node_modules/ssri": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "node_modules/stable": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", @@ -22505,102 +22025,6 @@ "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==" }, - "node_modules/static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==", - "dev": true, - "dependencies": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", @@ -22613,6 +22037,8 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", + "optional": true, + "peer": true, "dependencies": { "readable-stream": "^2.0.1" } @@ -22620,12 +22046,16 @@ "node_modules/stdout-stream/node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "optional": true, + "peer": true }, "node_modules/stdout-stream/node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "optional": true, + "peer": true, "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -22639,25 +22069,20 @@ "node_modules/stdout-stream/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "optional": true, + "peer": true }, "node_modules/stdout-stream/node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "optional": true, + "peer": true, "dependencies": { "safe-buffer": "~5.1.0" } }, - "node_modules/stealthy-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", - "integrity": "sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -22666,6 +22091,15 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "engines": { + "node": ">=0.6.19" + } + }, "node_modules/string-hash": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", @@ -22708,31 +22142,39 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/string.prototype.matchall": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", - "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "regexp.prototype.flags": "^1.4.3", - "side-channel": "^1.0.4" + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -22742,26 +22184,26 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -22807,6 +22249,14 @@ "node": ">=8" } }, + "node_modules/strip-color": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/strip-color/-/strip-color-0.1.0.tgz", + "integrity": "sha512-p9LsUieSjWNNAxVCXLeilaDlmuUOrDS5/dF9znM1nZc7EGX5+zEFC0bEevsNIaldjlks+2jns5Siz6F9iK6jwA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/strip-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", @@ -22815,15 +22265,6 @@ "node": ">=10" } }, - "node_modules/strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", @@ -22836,6 +22277,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "devOptional": true, "dependencies": { "min-indent": "^1.0.0" }, @@ -23040,59 +22482,6 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, - "node_modules/svgo/node_modules/css-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", - "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^3.2.1", - "domutils": "^1.7.0", - "nth-check": "^1.0.2" - } - }, - "node_modules/svgo/node_modules/css-what": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", - "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/svgo/node_modules/dom-serializer": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", - "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", - "dependencies": { - "domelementtype": "^2.0.1", - "entities": "^2.0.0" - } - }, - "node_modules/svgo/node_modules/domutils": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", - "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", - "dependencies": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "node_modules/svgo/node_modules/domutils/node_modules/domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" - }, - "node_modules/svgo/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/svgo/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -23120,14 +22509,6 @@ "mkdirp": "bin/cmd.js" } }, - "node_modules/svgo/node_modules/nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", - "dependencies": { - "boolbase": "~1.0.0" - } - }, "node_modules/svgo/node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -23152,6 +22533,22 @@ "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" }, + "node_modules/synckit": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", + "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", + "dev": true, + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/tailwindcss": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz", @@ -23227,6 +22624,8 @@ "version": "6.1.15", "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", + "optional": true, + "peer": true, "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -23243,6 +22642,8 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "optional": true, + "peer": true, "engines": { "node": ">=8" } @@ -23250,7 +22651,9 @@ "node_modules/tar/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true, + "peer": true }, "node_modules/temp-dir": { "version": "2.0.0", @@ -23408,6 +22811,52 @@ "node": ">=8" } }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/through2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/through2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/through2/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/through2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", @@ -23418,15 +22867,35 @@ "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==" }, - "node_modules/tiny-invariant": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz", - "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==" + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } }, - "node_modules/tiny-warning": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", - "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + "node_modules/tmp-promise": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", + "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", + "dependencies": { + "tmp": "^0.2.0" + } + }, + "node_modules/tmp-promise/node_modules/tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } }, "node_modules/tmpl": { "version": "1.0.5", @@ -23445,7 +22914,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", "integrity": "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==", - "dev": true, "dependencies": { "kind-of": "^3.0.2" }, @@ -23457,7 +22925,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, "dependencies": { "is-buffer": "^1.1.5" }, @@ -23474,21 +22941,6 @@ "node": ">=6" } }, - "node_modules/to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "dependencies": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -23508,6 +22960,11 @@ "node": ">=0.6" } }, + "node_modules/toml": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/toml/-/toml-2.3.6.tgz", + "integrity": "sha512-gVweAectJU3ebq//Ferr2JUY4WKSDe5N+z0FvjDncLGyHmIDoxgY/2Ie4qfEIDm4IS7OA6Rmdm7pdEEdMcV/xQ==" + }, "node_modules/totalist": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", @@ -23554,14 +23011,21 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "optional": true, + "peer": true, "engines": { "node": ">=8" } }, "node_modules/true-case-path": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-2.2.1.tgz", - "integrity": "sha512-0z3j8R7MCjy10kc/g+qg7Ln3alJTodw9aDuVWZa3uiWqfuBMKeAeP2ocWcxoyM3D73yz3Jt/Pu4qPr4wHSdB/Q==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", + "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", + "optional": true, + "peer": true, + "dependencies": { + "glob": "^7.1.2" + } }, "node_modules/tryer": { "version": "1.0.1", @@ -23585,9 +23049,9 @@ } }, "node_modules/tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", @@ -23615,9 +23079,9 @@ } }, "node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, "node_modules/tsutils": { "version": "3.21.0", @@ -23638,11 +23102,29 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, + "node_modules/tsx": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-3.14.0.tgz", + "integrity": "sha512-xHtFaKtHxM9LOklMmJdI3BEnQq/D5F73Of2E1GDrITi9sgoVkvIsrQUTY1G8FlmGtA+awCI4EBlTRRYxkL2sRg==", + "dev": true, + "dependencies": { + "esbuild": "~0.18.20", + "get-tsconfig": "^4.7.2", + "source-map-support": "^0.5.21" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "dev": true, + "optional": true, + "peer": true, "dependencies": { "safe-buffer": "^5.0.1" }, @@ -23654,7 +23136,8 @@ "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", - "dev": true + "optional": true, + "peer": true }, "node_modules/type-check": { "version": "0.4.0", @@ -23698,16 +23181,48 @@ "node": ">= 0.6" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/typed-array-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", - "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -23717,18 +23232,29 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -23738,29 +23264,30 @@ } }, "node_modules/typedoc": { - "version": "0.24.8", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.24.8.tgz", - "integrity": "sha512-ahJ6Cpcvxwaxfu4KtjA8qZNqS43wYt6JL27wYiIgl1vd38WW/KWX11YuAeZhuz9v+ttrutSsgK+XO1CjL1kA3w==", + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.7.tgz", + "integrity": "sha512-m6A6JjQRg39p2ZVRIN3NKXgrN8vzlHhOS+r9ymUYtcUP/TIQPvWSq7YgE5ZjASfv5Vd5BW5xrir6Gm2XNNcOow==", + "peer": true, "dependencies": { "lunr": "^2.3.9", "marked": "^4.3.0", - "minimatch": "^9.0.0", - "shiki": "^0.14.1" + "minimatch": "^9.0.3", + "shiki": "^0.14.7" }, "bin": { "typedoc": "bin/typedoc" }, "engines": { - "node": ">= 14.14" + "node": ">= 16" }, "peerDependencies": { - "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x" + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x" } }, "node_modules/typedoc-plugin-markdown": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-3.16.0.tgz", - "integrity": "sha512-eeiC78fDNGFwemPIHiwRC+mEC7W5jwt3fceUev2gJ2nFnXpVHo8eRrpC9BLWZDee6ehnz/sPmNjizbXwpfaTBw==", + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-3.17.1.tgz", + "integrity": "sha512-QzdU3fj0Kzw2XSdoL15ExLASt2WPqD7FbLeaqwT70+XjKyTshBnUlQA5nNREO1C2P8Uen0CDjsBLMsCQ+zd0lw==", "dependencies": { "handlebars": "^4.7.7" }, @@ -23772,6 +23299,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "peer": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -23780,6 +23308,7 @@ "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "peer": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -23901,52 +23430,6 @@ "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==" }, - "node_modules/union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/union-value/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unique-filename": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", - "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", - "dependencies": { - "unique-slug": "^3.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/unique-slug": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", - "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "node_modules/unique-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", @@ -23979,60 +23462,6 @@ "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", "integrity": "sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg==" }, - "node_modules/unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==", - "dev": true, - "dependencies": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==", - "dev": true, - "dependencies": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", - "dev": true, - "dependencies": { - "isarray": "1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, "node_modules/upath": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", @@ -24043,9 +23472,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", "funding": [ { "type": "opencollective", @@ -24123,13 +23552,6 @@ "punycode": "^2.1.0" } }, - "node_modules/urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", - "deprecated": "Please see https://github.com/lydell/urix#deprecated", - "dev": true - }, "node_modules/url-parse": { "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", @@ -24151,15 +23573,6 @@ "node": ">=4" } }, - "node_modules/use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -24225,16 +23638,13 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "optional": true, + "peer": true, "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, - "node_modules/value-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", - "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -24247,10 +23657,11 @@ "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "dev": true, "engines": [ "node >=0.6.0" ], + "optional": true, + "peer": true, "dependencies": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", @@ -24261,7 +23672,8 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", - "dev": true + "optional": true, + "peer": true }, "node_modules/void-elements": { "version": "3.1.0", @@ -24274,12 +23686,14 @@ "node_modules/vscode-oniguruma": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", - "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==" + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "peer": true }, "node_modules/vscode-textmate": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", - "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==" + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", + "peer": true }, "node_modules/w3c-hr-time": { "version": "1.0.2", @@ -24337,6 +23751,14 @@ "minimalistic-assert": "^1.0.0" } }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dependencies": { + "defaults": "^1.0.3" + } + }, "node_modules/web-vitals": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-1.1.2.tgz", @@ -24418,21 +23840,6 @@ "webpack": "^4.0.0 || ^5.0.0" } }, - "node_modules/webpack-dev-middleware/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", @@ -24444,11 +23851,6 @@ "ajv": "^8.8.2" } }, - "node_modules/webpack-dev-middleware/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, "node_modules/webpack-dev-middleware/node_modules/schema-utils": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", @@ -24525,21 +23927,6 @@ } } }, - "node_modules/webpack-dev-server/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/webpack-dev-server/node_modules/ajv-keywords": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", @@ -24551,11 +23938,6 @@ "ajv": "^8.8.2" } }, - "node_modules/webpack-dev-server/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, "node_modules/webpack-dev-server/node_modules/schema-utils": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", @@ -24709,17 +24091,58 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/which-builtin-type": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", + "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "dependencies": { + "function.prototype.name": "^1.1.5", + "has-tostringtag": "^1.0.0", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/which-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.10.tgz", - "integrity": "sha512-uxoA5vLUfRPdjCuJ1h5LlYdmTLbYfums398v3WLkM+i/Wltl2/XyZpQWKbN++ck5L64SR/grOHqtXCUKmlZPNA==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -24732,6 +24155,8 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "optional": true, + "peer": true, "dependencies": { "string-width": "^1.0.2 || 2 || 3 || 4" } @@ -24748,15 +24173,6 @@ "node": ">=8" } }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -24826,21 +24242,6 @@ "node": ">=10.0.0" } }, - "node_modules/workbox-build/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/workbox-build/node_modules/fs-extra": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", @@ -24855,11 +24256,6 @@ "node": ">=10" } }, - "node_modules/workbox-build/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, "node_modules/workbox-build/node_modules/source-map": { "version": "0.8.0-beta.0", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", @@ -25112,6 +24508,14 @@ "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -25158,19 +24562,6 @@ "node": ">=10" } }, - "node_modules/yarn": { - "version": "1.22.19", - "resolved": "https://registry.npmjs.org/yarn/-/yarn-1.22.19.tgz", - "integrity": "sha512-/0V5q0WbslqnwP91tirOvldvYISzaqhClxzyUKXYxs07yUILIs5jx/k6CFe8bvKSkds5w+eiOqta39Wk3WxdcQ==", - "hasInstallScript": true, - "bin": { - "yarn": "bin/yarn.js", - "yarnpkg": "bin/yarn.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -25196,9 +24587,9 @@ } }, "node_modules/zod": { - "version": "3.21.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz", - "integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==", + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", + "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/package.json b/package.json index 1fbc68abf3..10ddc16b1f 100644 --- a/package.json +++ b/package.json @@ -3,83 +3,74 @@ "version": "3.0.0", "private": true, "type": "module", + "config-overrides-path": "scripts/config-overrides", "dependencies": { "@apollo/client": "^3.4.0-beta.19", "@apollo/link-error": "^2.0.0-beta.3", "@apollo/react-testing": "^4.0.0", + "@dicebear/collection": "^7.0.4", + "@dicebear/core": "^7.0.4", "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", "@mui/icons-material": "^5.8.3", "@mui/material": "^5.14.1", - "@mui/private-theming": "^5.14.13", + "@mui/private-theming": "^5.15.12", "@mui/system": "^5.14.12", "@mui/x-charts": "^6.0.0-alpha.13", "@mui/x-data-grid": "^6.8.0", "@mui/x-date-pickers": "^6.6.0", "@pdfme/generator": "^1.2.6", - "@testing-library/jest-dom": "^5.14.1", - "@testing-library/react": "^11.1.0", - "@testing-library/user-event": "^12.1.10", - "@types/enzyme-adapter-react-16": "^1.0.6", - "@types/jest": "^26.0.24", - "@types/jquery": "^3.5.6", - "@types/node": "^12.20.16", - "@types/react-bootstrap": "^0.32.32", - "@types/react-datepicker": "^4.1.4", - "@types/react-dom": "^17.0.9", - "@types/react-google-recaptcha": "^2.1.5", - "@types/react-modal": "^3.12.1", "bootstrap": "^5.3.0", + "customize-cra": "^1.0.0", "dayjs": "^1.10.7", - "detect-newline": "^4.0.0", - "enzyme": "^3.11.0", - "enzyme-adapter-react-16": "^1.15.6", - "eslint-config-prettier": "^8.3.0", - "eslint-plugin-jest": "^25.3.4", - "eslint-plugin-prettier": "^3.4.0", "flag-icons": "^6.6.6", "graphql": "^15.5.1", "graphql-tag": "^2.12.6", "graphql-ws": "^5.14.0", + "history": "^5.3.0", "i18next": "^21.8.14", "i18next-browser-languagedetector": "^6.1.4", "i18next-http-backend": "^1.4.1", - "jest-docblock": "^27.4.0", + "inquirer": "^8.0.0", "js-cookie": "^3.0.1", - "node-sass": "^9.0.0", - "prettier": "^2.3.2", + "markdown-toc": "^1.2.0", + "prettier": "^3.2.5", "react": "^17.0.2", + "react-app-rewired": "^2.2.1", "react-bootstrap": "^2.7.4", - "react-calendar": "^4.2.1", "react-datepicker": "^4.2.0", "react-dom": "^17.0.2", "react-google-recaptcha": "^2.1.0", "react-i18next": "^11.18.1", + "react-icons": "^4.12.0", "react-infinite-scroll-component": "^6.1.0", "react-redux": "^7.2.5", - "react-router-dom": "^5.2.0", + "react-router-dom": "^6.22.2", "react-scripts": "5.0.1", "react-toastify": "^9.0.3", "redux": "^4.1.1", "redux-thunk": "^2.3.0", - "typedoc": "^0.24.8", - "typedoc-plugin-markdown": "^3.16.0", + "sanitize-html": "^2.12.1", + "typedoc-plugin-markdown": "^3.17.1", "typescript": "^4.3.5", - "web-vitals": "^1.0.1", - "yarn": "^1.22.17" + "web-vitals": "^1.0.1" }, "scripts": { - "serve": "react-scripts start", - "build": "react-scripts build", + "serve": "cross-env ESLINT_NO_DEV_ERRORS=true node ./scripts/config-overrides/custom_start.js", + "build": "node ./scripts/config-overrides/custom_build.js", "test": "cross-env NODE_ENV=test node scripts/test.js --env=./scripts/custom-test-env.js --watchAll --coverage", "eject": "react-scripts eject", "lint:check": "eslint \"**/*.{ts,tsx}\" --max-warnings=0", - "lint:fix": "eslint \"**/*.{ts,tsx}\" --fix", + "lint:fix": "eslint --fix \"**/*.{ts,tsx}\"", "format:fix": "prettier --write \"**/*.{ts,tsx,json,scss,css}\"", "format:check": "prettier --check \"**/*.{ts,tsx,json,scss,css}\"", "typecheck": "tsc --project tsconfig.json --noEmit", "prepare": "husky install", - "jest-preview": "jest-preview" + "jest-preview": "jest-preview", + "update:toc": "node scripts/githooks/update-toc.js", + "lint-staged": "lint-staged --concurrent false", + "setup": "tsx setup.ts", + "check-localstorage": "node scripts/githooks/check-localstorage-usage.js" }, "eslintConfig": { "extends": [ @@ -101,31 +92,54 @@ }, "devDependencies": { "@babel/plugin-proposal-private-property-in-object": "^7.21.11", - "@fortawesome/fontawesome-svg-core": "^1.2.35", - "@fortawesome/free-brands-svg-icons": "^5.15.3", - "@fortawesome/react-fontawesome": "^0.1.14", - "@types/enzyme": "^3.10.9", + "@testing-library/jest-dom": "^5.14.1", + "@testing-library/react": "^11.1.0", + "@testing-library/user-event": "^12.1.10", + "@types/inquirer": "^9.0.7", + "@types/jest": "^26.0.24", "@types/js-cookie": "^3.0.2", + "@types/node": "^12.20.55", + "@types/node-fetch": "^2.6.10", "@types/react": "^17.0.14", + "@types/react-bootstrap": "^0.32.32", + "@types/react-datepicker": "^4.1.4", + "@types/react-dom": "^17.0.9", + "@types/react-google-recaptcha": "^2.1.5", "@types/react-router-dom": "^5.1.8", + "@types/sanitize-html": "^2.11.0", "@typescript-eslint/eslint-plugin": "^5.9.0", "@typescript-eslint/parser": "^5.9.0", - "@wojtekmaj/enzyme-adapter-react-17": "^0.8.0", "cross-env": "^7.0.3", + "eslint-config-prettier": "^8.10.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-jest": "^25.3.4", + "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-react": "^7.34.1", + "eslint-plugin-tsdoc": "^0.2.17", "husky": "^8.0.3", "identity-obj-proxy": "^3.0.0", "jest": "^27.4.5", - "jest-enzyme": "^7.1.2", "jest-localstorage-mock": "^2.4.19", "jest-location-mock": "^1.0.9", "jest-preview": "^0.3.1", - "jquery": "^3.2.1", - "postcss-modules": "^6.0.0" + "lint-staged": "^15.2.2", + "postcss-modules": "^6.0.0", + "sass": "^1.71.1", + "tsx": "^3.11.0" }, "resolutions": { "@apollo/client": "^3.4.0-beta.19", "@types/react": "17.0.2", "@types/react-dom": "17.0.2", "graphql": "^16.5.0" + }, + "engines": { + "node": ">=20.x" + }, + "lint-staged": { + "**/*.{ts, tsx, json, scss, css}": [ + "prettier --write" + ], + "**/*.{ts, tsx, json}": "eslint --fix" } } diff --git a/public/images/svg/angleDown.svg b/public/images/svg/angleDown.svg new file mode 100644 index 0000000000..0dfea5e56c --- /dev/null +++ b/public/images/svg/angleDown.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/images/svg/profiledefault.svg b/public/images/svg/profiledefault.svg new file mode 100644 index 0000000000..a321caaeab --- /dev/null +++ b/public/images/svg/profiledefault.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/index.html b/public/index.html index e17b0de972..3bd6e258e7 100644 --- a/public/index.html +++ b/public/index.html @@ -7,6 +7,17 @@ + + + + Talawa Admin diff --git a/public/locales/en.json b/public/locales/en.json index bfefeec253..4dce655d45 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -4,12 +4,18 @@ "fromPalisadoes": "An open source application by Palisadoes Foundation volunteers", "talawa_portal": "Talawa Admin Portal", "login": "Login", + "userLogin": "User Login", "register": "Register", "firstName": "First Name", "lastName": "Last Name", "email": "Email", "password": "Password", "atleast_8_char_long": "Atleast 8 Character long", + "atleast_6_char_long": "Atleast 6 Character long", + "firstName_invalid": "First name should contain only lower and upper case letters", + "lastName_invalid": "Last name should contain only lower and upper case letters", + "password_invalid": "Password should contain atleast one lowercase letter, one uppercase letter, one numeric value and one special character", + "email_invalid": "Email should have atleast 8 characters", "Password_and_Confirm_password_mismatches.": "Password and Confirm password mismatches.", "confirmPassword": "Confirm Password", "forgotPassword": "Forgot Password ?", @@ -25,8 +31,13 @@ "notAuthorised": "Sorry! you are not Authorised!", "notFound": "User not found!", "successfullyRegistered": "Successfully Registered. Please wait until you will be approved.", - "login_to_admin_portal": "Admin Portal Login", - "OR": "OR" + "OR": "OR", + "admin": "ADMIN", + "user": "USER", + "lowercase_check": "Atleast one lowercase letter", + "uppercase_check": "Atleast one uppercase letter", + "numeric_value_check": "Atleaset one numeric value", + "special_char_check": "Atleast one special character" }, "latestEvents": { "eventCardTitle": "Upcoming Events", @@ -47,9 +58,10 @@ "leftDrawer": { "talawaAdminPortal": "Talawa Admin Portal", "menu": "Menu", - "organizations": "Organizations", - "requests": "Requests", + "my organizations": "My Organizations", "users": "Users", + "requests": "Requests", + "communityProfile": "Community Profile", "logout": "Logout" }, "leftDrawerOrg": { @@ -84,16 +96,27 @@ "designation": "Designation", "email": "Email", "searchByName": "Search By Name", - "organizations": "Organizations", + "my organizations": "My Organizations", "createOrganization": "Create Organization", "createSampleOrganization": "Create Sample Organization", "description": "Description", "location": "Location", - "isPublic": "Is Public", + "address": "Address", + "city": "City", + "countryCode": "Country Code", + "dependentLocality": "Dependent Locality", + "line1": "Line 1", + "line2": "Line 2", + "postalCode": "Postal Code", + "sortingCode": "Sorting code", + "state": "State / Province", + "userRegistrationRequired": "User Registration Required", "visibleInSearch": "Visible In Search", "displayImage": "Display Image", "enterName": "Enter Name", "sort": "Sort", + "Latest": "Latest", + "Earliest": "Earliest", "filter": "Filter", "cancel": "Cancel", "noOrgErrorTitle": "Organizations Not Found", @@ -118,13 +141,29 @@ "rowsPerPage": "rows per page", "all": "All" }, + "requests": { + "title": "Requests", + "sl_no": "Sl. No.", + "name": "Name", + "email": "Email", + "accept": "Accept", + "reject": "Reject", + "searchRequests": "Search requests", + "endOfResults": "End of results", + "noOrgError": "Organizations not found, please create an organization through dashboard", + "noResultsFoundFor": "No results found for ", + "noRequestsFound": "No Request Found", + "acceptedSuccessfully": "Request accepted successfully", + "rejectedSuccessfully": "Request rejected successfully", + "noOrgErrorTitle": "Organizations Not Found", + "noOrgErrorDescription": "Please create an organization through dashboard" + }, "users": { "title": "Talawa Roles", "searchByName": "Search By Name", "users": "Users", "name": "Name", "email": "Email", - "roles_userType": "Role/User-Type", "joined_organizations": "Joined Organizations", "blocked_organizations": "Blocked Organizations", "orgJoinedBy": "Organizations Joined By", @@ -147,27 +186,25 @@ "noOrgError": "Organizations not found, please create an organization through dashboard", "roleUpdated": "Role Updated.", "noResultsFoundFor": "No results found for ", - "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too." + "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too.", + "cancel": "Cancel", + "admins": "Admins", + "members": "Members", + "joinNow": "Join Now", + "visit": "Visit", + "withdraw": "Widthdraw" }, - "requests": { - "title": "Talawa Requests", - "searchByName": "Search By Name", - "requests": "Requests", - "name": "Name", - "email": "Email", - "accept": "Accept", - "reject": "Reject", - "enterName": "Enter Name", - "endOfResults": "End of results", - "loadingRequests": "Loading Requests...", - "noRequestFound": "No Request Found", - "sort": "Sort", - "filter": "Filter", - "noOrgError": "Organizations not found, please create an organization through dashboard", - "userApproved": "User Approved", - "userRejected": "User Rejected", - "noResultsFoundFor": "No results found for ", - "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too." + "communityProfile": { + "title": "Community Profile", + "editProfile": "Edit Profile", + "communityProfileInfo": "These details will appear on the login/signup screen for you and your community members", + "communityName": "Community Name", + "wesiteLink": "Website Link", + "logo": "Logo", + "social": "Social Media Links", + "url": "Enter url", + "profileChangedMsg": "Successfully updated the Profile Details.", + "resetData": "Successfully reset the Profile Details." }, "dashboard": { "title": "Dashboard", @@ -200,8 +237,27 @@ "users": "Users", "searchName": "Enter Name", "searchevent": "Enter Event", - "searchFirstName": "Enter First Name", - "searchLastName": "Enter Last Name" + "searchFullName": "Enter Full Name", + "people": "People", + "sort": "Search by Role", + "actions": "Actions", + "addMembers": "Add Members", + "existingUser": "Existing User", + "newUser": "New User", + "firstName": "First Name", + "enterFirstName": "Enter your first name", + "lastName": "Last Name", + "enterLastName": "Enter your last name", + "emailAddress": "Email Address", + "enterEmail": "Enter your email address", + "password": "Password", + "enterPassword": "Enter your password", + "confirmPassword": "Confirm Password", + "enterConfirmPassword": "Enter your password to confirm", + "organization": "Organization", + "create": "Create", + "cancel": "Cancel", + "invalidDetailsMessage": "Please enter valid details." }, "userListCard": { "joined": "Joined", @@ -230,11 +286,10 @@ "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too." }, "organizationEvents": { - "title": "Talawa Events", + "title": "Events", "filterByTitle": "Filter by Title", "filterByLocation": "Filter by Location", "filterByDescription": "Filter by Description", - "events": "Events", "addEvent": "Add Event", "eventDetails": "Event Details", "eventTitle": "Title", @@ -253,13 +308,60 @@ "enterTitle": "Enter Title", "enterDescrip": "Enter Description", "eventLocation": "Enter Location", + "searchEventName": "Search Event Name", + "eventType": "Event Type", "eventCreated": "Congratulations! The Event is created.", - "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too." + "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too.", + "customRecurrence": "Custom Recurrence", + "repeatsEvery": "Repeats Every", + "repeatsOn": "Repeats On", + "ends": "Ends", + "never": "Never", + "on": "On", + "after": "After", + "occurences": "occurences", + "done": "Done" + }, + "organizationActionItems": { + "actionItemCategory": "Action Item Category", + "actionItemDetails": "Action Item Details", + "actionItemCompleted": "Action Item Completed", + "assignee": "Assignee", + "assigner": "Assigner", + "assignmentDate": "Assignment Date", + "active": "Active", + "clearFilters": "Clear Filters", + "close": "Close", + "completed": "Completed", + "completionDate": "Completion Date", + "createActionItem": "Create", + "deleteActionItem": "Delete Action Item", + "deleteActionItemMsg": "Do you want to remove this action item?", + "details": "Details", + "dueDate": "Due Date", + "earliest": "Earliest", + "editActionItem": "Edit Action Item", + "isCompleted": "Completed", + "latest": "Latest", + "no": "No", + "noActionItems": "No Action Items", + "options": "Options", + "preCompletionNotes": "Pre Completion Notes", + "actionItemActive": "Active", + "markCompletion": "Mark Completion", + "actionItemStatus": "Action Item Status", + "postCompletionNotes": "Post Completion Notes", + "selectActionItemCategory": "Select an action item category", + "selectAssignee": "Select an assignee", + "status": "Status", + "successfulCreation": "Action Item created successfully", + "successfulUpdation": "Action Item updated successfully", + "successfulDeletion": "Action Item deleted successfully", + "title": "Action Items", + "yes": "Yes" }, "eventListCard": { - "location": "Location", - "on": "On", - "end": "End", + "location": "Event Location", "deleteEvent": "Delete Event", "deleteEventMsg": "Do you want to remove this event?", "no": "No", @@ -267,6 +369,10 @@ "editEvent": "Edit Event", "eventTitle": "Title", "description": "Description", + "startDate": "Start Date", + "endDate": "End Date", + "registerEvent": "Register", + "alreadyRegistered": "Already registered", "startTime": "Start Time", "endTime": "End Time", "allDay": "All Day", @@ -278,20 +384,113 @@ "eventDetails": "Event Details", "eventDeleted": "Event deleted successfully.", "eventUpdated": "Event updated successfully.", - "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too." + "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too.", + "thisInstance": "This Instance", + "thisAndFollowingInstances": "This & Following Instances", + "allInstances": "All Instances", + "customRecurrence": "Custom Recurrence", + "repeatsEvery": "Repeats Every", + "repeatsOn": "Repeats On", + "ends": "Ends", + "never": "Never", + "on": "On", + "after": "After", + "occurences": "occurences", + "done": "Done" + }, + "funds": { + "title": "Funds", + "createFund": "Create Fund", + "fundName": "Fund Name", + "fundId": "Fund ID", + "fundOptions": "Opitons", + "noFunds": "No Funds Found", + "fundDetails": "Fund Details", + "taxDeductible": "Tax Deductible", + "enterfundName": "Enter Fund Name", + "enterfundId": "Enter Fund ID", + "default": "Default Fund", + "archived": "Archived", + "nonArchive": "Non-Archived", + "fundCreate": "Create Fund", + "fundUpdate": "Update Fund", + "fundDelete": "Delete Fund", + "no": "No", + "yes": "Yes", + "manageFund": "Manage Fund", + "searchFullName": "Search By Name", + "filter": "Filter", + "noFundsFound": "No Funds Found", + "createdBy": "Created By", + "createdOn": "Created On", + "status": "Status", + "archiveFund": "Archive Fund", + "archiveFundMsg": "On Archiving this fund will remove it from the fund listing.Thisaction can be undone", + "fundCreated": "Fund created successfully", + "fundUpdated": "Fund updated successfully", + "fundDeleted": "Fund deleted successfully", + "fundArchived": "Fund archived successfully", + "fundUnarchived": "Fund unarchived successfully", + "deleteFundMsg": "Do you want to remove this fund?" + }, + "fundCampaign": { + "title": "Fundraising Campaigns", + "campaignName": "Campaign Name", + "startDate": "Start Date", + "endDate": "End Date", + "campaignOptions": "Options", + "fundingGoal": "Funding Goal", + "addCampaign": "Add Campaign", + "createdCampaign": "Campaign created successfully", + "updatedCampaign": "Campaign updated successfully", + "deletedCampaign": "Campaign deleted successfully", + "deleteCampaignMsg": "Are you sure you want to delete this campaign?", + "noCampaigns": "No Campaigns Found", + "createCampaign": "Create Fund Campaign", + "updateCampaign": "Update Fund Campaign", + "manageCampaign": "Manage Fund Campaign", + "deleteCampaign": "Delete Fund Campaign", + "no": "No", + "yes": "Yes", + "currency": "Currency", + "selectCurrency": "Select Currency", + "filter": "Filter", + "searchFullName": "Search By Name" + }, + "pledges": { + "title": "Fund Campaign Pledges", + "volunteers": "Volunteers", + "startDate": "Start Date", + "endDate": "End Date", + "pledgeAmount": "Pledge Amount", + "pledgeOptions": "Options", + "pledgeCreated": "Pledge created successfully", + "pledgeUpdated": "Pledge updated successfully", + "pledgeDeleted": "Pledge deleted successfully", + "addPledge": "Add Pledge", + "createPledge": "Create Pledge", + "currency": "Currency", + "selectCurrency": "Select Currency", + "updatePledge": "Update Pledge", + "deletePledge": "Delete Pledge", + "amount": "Amount", + "editPledge": "Edit Pledge", + "deletePledgeMsg": "Are you sure you want to delete this pledge?", + "no": "No", + "yes": "Yes", + "noPledges": "No Pledges Found" }, "orgPost": { - "title": "Talawa Posts", + "title": "Posts", "searchPost": "Search Post", "posts": "Posts", "createPost": "Create Post", "postDetails": "Post Details", "postTitle1": "Write title of the post", "postTitle": "Title", + "addMedia": "Upload Media", "information": "Information", "information1": "Write information of the post", - "image": "Post Image", - "video": "Post Video", "addPost": "Add Post", "searchTitle": "Search By Title", "searchText": "Search By Text", @@ -304,7 +503,11 @@ "Oldest": "Oldest First", "Latest": "Latest First", "sortPost": "Sort Post", - "tag": " Your browser does not support the video tag" + "tag": " Your browser does not support the video tag", + "postCreatedSuccess": "Congratulations! You have Posted Something.", + "pinPost": "Pin post", + "Next": "Next Page", + "Previous": "Previous Page" }, "postNotFound": { "post": "Post", @@ -333,6 +536,8 @@ "yes": "Yes", "editPost": "Edit Post", "postTitle": "Title", + "postTitle1": "Edit title of the post", + "information1": "Edit information of the post", "information": "Information", "image": "Image", "video": "Video", @@ -345,7 +550,7 @@ "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too." }, "blockUnblockUser": { - "title": "Talawa Block/Unblock User", + "title": "Block/Unblock User", "pageName": "Block/Unblock", "searchByName": "Search By Name", "listOfUsers": "List of Users who spammed", @@ -365,6 +570,14 @@ "noResultsFoundFor": "No results found for", "noSpammerFound": "No spammer found" }, + "eventManagement": { + "title": "Event Management", + "dashboard": "Dashboard", + "registrants": "Registrants", + "eventActions": "Event Actions", + "eventStats": "Event Statistics", + "to": "TO" + }, "forgotPassword": { "title": "Talawa Forgot Password", "forgotPassword": "Forgot Password", @@ -387,6 +600,7 @@ "pageNotFound": { "title": "404 Not Found", "talawaAdmin": "Talawa Admin", + "talawaUser": "Talawa User", "404": "404", "notFoundMsg": "Oops! The Page you requested was not found!", "backToHome": "Back to Home" @@ -411,14 +625,17 @@ "amount": "Amount" }, "orgSettings": { - "title": "Talawa Setting", + "title": "Settings", "pageName": "Settings", + "general": "General", + "actionItemCategories": "Action Item Categories", "updateOrganization": "Update Organization", "seeRequest": "See Request", "settings": "Settings", "noData": "No data", "otherSettings": "Other Settings", - "changeLanguage": "Change Language" + "changeLanguage": "Change Language", + "manageCustomFields": "Manage Custom Fields" }, "deleteOrg": { "deleteOrganization": "Delete Organization", @@ -426,7 +643,8 @@ "deleteMsg": "Do you want to delete this organization?", "cancel": "Cancel", "confirmDelete": "Confirm Delete", - "longDelOrgMsg": "By clicking on Delete Organization button the organization will be permanently deleted along with its events, tags and all related data." + "longDelOrgMsg": "By clicking on Delete Organization button the organization will be permanently deleted along with its events, tags and all related data.", + "successfullyDeletedSampleOrganization": "Successfully deleted sample Organization" }, "userUpdate": { "firstName": "First Name", @@ -462,8 +680,17 @@ "name": "Name", "description": "Description", "location": "Location", + "address": "Address", + "city": "City", + "countryCode": "Country Code", + "line1": "Line 1", + "line2": "Line 2", + "postalCode": "Postal Code", + "dependentLocality": "Dependent Locality", + "sortingCode": "Sorting code", + "state": "State / Province", "displayImage": "Display Image", - "isPublic": "Public", + "userRegistrationRequired": "User Registration Required", "isVisibleInSearch": "Visible in Search", "saveChanges": "Save Changes", "enterNameOrganization": "Enter Organization Name", @@ -504,6 +731,7 @@ "memberDetail": { "title": "User Details", "addAdmin": "Add Admin", + "alreadyIsAdmin": "Member is already an Admin", "organizations": "Organizations", "events": "Events", "role": "Role", @@ -512,9 +740,25 @@ "main": "Main", "firstName": "First name", "lastName": "Last name", - "memberOfOrganization": "Member of Organization", "language": "Language", - "adminApproved": "Admin approved", + "gender": "Gender", + "birthDate": "Birth Date", + "educationGrade": "Educational Grade", + "employmentStatus": "Employment Status", + "maritalStatus": "Marital Status", + "displayImage": "Display Image", + "phone": "Phone", + "address": "Address", + "countryCode": "Country Code", + "state": "State", + "city": "City", + "personalInfoHeading": "Personal Information", + "contactInfoHeading": "Contact Information", + "actionsHeading": "Actions", + "personalDetailsHeading": "Profile Details", + "appLanguageCode": "Choose Language", + "delete": "Delete User", + "saveChanges": "Save Changes", "pluginCreationAllowed": "Plugin creation allowed", "joined": "Joined", "created": "Created", @@ -522,7 +766,12 @@ "membershipRequests": "Membership requests", "adminForEvents": "Admin for events", "addedAsAdmin": "User is added as admin.", - "talawaApiUnavailable": "Talawa-API service is unavailable. Kindly check your network connection and wait for a while." + "talawaApiUnavailable": "Talawa-API service is unavailable. Kindly check your network connection and wait for a while.", + "password": "Password", + "userType": "User Type", + "admin": "Admin", + "superAdmin": "Superadmin", + "cancel": "Cancel" }, "userLogin": { "login": "Login", @@ -564,7 +813,6 @@ "events": "Events", "chat": "Chat", "donate": "Donate", - "myTasks": "My Tasks", "settings": "Settings", "language": "Language", "logout": "Logout", @@ -574,14 +822,25 @@ "allOrganizations": "All Organizations", "joinedOrganizations": "Joined Organizations", "createdOrganizations": "Created Organizations", - "search": "Search", + "selectOrganization": "Select an organization", + "search": "Search users", "nothingToShow": "Nothing to show here.", - "selectOrganization": "Select Organization" + "organizations": "Organizations", + "searchByName": "Search By Name", + "filter": "Filter" }, - "userSidebar": { + "userSidebarOrg": { "yourOrganizations": "Your Organizations", "noOrganizations": "You haven't joined any organization yet.", - "viewAll": "View all" + "viewAll": "View all", + "talawaUserPortal": "Talawa User Portal", + "menu": "Menu", + "my organizations": "My Organizations", + "users": "Users", + "requests": "Requests", + "communityProfile": "Community Profile", + "logout": "Logout", + "settings": "Settings" }, "organizationSidebar": { "viewAll": "View all", @@ -597,35 +856,90 @@ "home": { "feed": "Feed", "pinnedPosts": "View Pinned Posts", - "somethingOnYourMind": "Something on your mind?" + "somethingOnYourMind": "Something on your mind?", + "addPost": "Add Post", + "startPost": "Start a post", + "media": "Media", + "event": "Event", + "article": "Article" }, "settings": { + "settings": "Settings", "profileSettings": "Profile Settings", "firstName": "First Name", "lastName": "Last Name", + "gender": "Gender", "emailAddress": "Email Address", - "updateImage": "Update Image", - "save": "Save" + "phoneNumber": "Phone Number", + "displayImage": "Display Image", + "chooseFile": "Choose File", + "birthDate": "Birth Date", + "grade": "Educational Grade", + "empStatus": "Employment Status", + "maritalStatus": "Marital Status", + "address": "Address", + "state": "City/State", + "country": "Country", + "resetChanges": "Reset Changes", + "saveChanges": "Save Changes", + "profileDetails": "Profile Details", + "deleteUserMessage": "By clicking on Delete User button your user will be permanently deleted along with its events, tags and all related data.", + "copyLink": "Copy Profile Link", + "deleteUser": "Delete User", + "otherSettings": "Other Settings", + "changeLanguage": "Change Language", + "sgender": "Select gender", + "gradePlaceholder": "Enter Grade", + "sEmpStatus": "Select employement status", + "female": "Female", + "male": "Male", + "employed": "Employed", + "other": "Other", + "sMaritalStatus": "Select marital status", + "unemployed": "Unemployed", + "married": "Married", + "single": "Single", + "widowed": "Widowed", + "divorced": "Divorced", + "engaged": "Engaged", + "seperated": "Seperated", + "grade1": "Grade 1", + "grade2": "Grade 2", + "grade3": "Grade 3", + "grade4": "Grade 4", + "grade5": "Grade 5", + "grade6": "Grade 6", + "grade7": "Grade 7", + "grade8": "Grade 8", + "grade9": "Grade 9", + "grade10": "Grade 10", + "grade11": "Grade 11", + "grade12": "Grade 12", + "graduate": "Graduate", + "kg": "KG", + "preKg": "Pre-KG", + "noGrade": "No Grade", + "fullTime": "Full Time", + "partTime": "Part Time", + "selectCountry": "Select a country", + "enterState": "Enter City or State", + "joined": "Joined" }, "donate": { - "donateTo": "Donate to", + "donations": "Donations", + "searchDonations": "Search donations", + "donateForThe": "Donate for the", "amount": "Amount", "yourPreviousDonations": "Your Previous Donations", "donate": "Donate", - "nothingToShow": "Nothing to show here." + "nothingToShow": "Nothing to show here.", + "success": "Donation Successful" }, "userEvents": { "nothingToShow": "Nothing to show here.", "search": "Search", "createEvent": "Create Event", - "eventTitle": "Event Title", - "eventDescription": "Event Description", - "eventLocation": "Event Location", - "startDate": "Select Start Date", - "endDate": "Select End Date", - "publicEvent": "Public Event", - "registerable": "Registerable", - "recurring": "Recurring", + "recurring": "Recurring Event", "startTime": "Start Time", "endTime": "End Time", "cancel": "Cancel", @@ -633,7 +947,20 @@ "listView": "List View", "calendarView": "Calendar View", "allDay": "All Day", - "eventCreated": "Event created and posted successfully." + "eventCreated": "Event created and posted successfully.", + "eventDetails": "Event Details", + "eventTitle": "Title", + "enterTitle": "Enter Title", + "eventDescription": "Description", + "enterDescription": "Enter Description", + "eventLocation": "Location", + "enterLocation": "Enter Location", + "startDate": "Start Date", + "endDate": "End Date", + "publicEvent": "Is Public", + "registerable": "Is Registerable", + "monthlyCalendarView": "Monthly Calendar", + "yearlyCalendarView": "Yearly Calender" }, "userEventCard": { "location": "Location", @@ -643,32 +970,17 @@ "alreadyRegistered": "Already registered", "register": "Register" }, - "userTasks": { - "yourAssignedTasks": "Your assigned tasks", - "nothingToShow": "Nothing to show here." - }, - "userTaskCard": { - "description": "Description", - "deadline": "Deadline", - "created": "Created", - "assignees": "Assignees", - "completed": "Completed", - "incomplete": "Incomplete", - "taskCompleted": "The task has been completed", - "taskNotCompleted": "The task has not been completed yet", - "event": "Event", - "organization": "Organization" - }, "advertisement": { "title": "Advertisements", - "pHeading": "Manage Ads", "activeAds": "Active Campaigns", "archievedAds": "Completed Campaigns", "pMessage": "Ads not present for this campaign.", "delete": "Delete", + "validLink": "Link is valid", + "invalidLink": "Link is invalid", "Rname": "Enter name of Advertisement", "Rtype": "Select type of Advertisement", - "Rlink": "Provide a link for content to be displayed", + "Rmedia": "Provide media content to be displayed", "RstartDate": "Select Start Date", "RendDate": "Select End Date", "RClose": "Close the window", @@ -676,7 +988,16 @@ "EXname": "Ex. Cookie Shop", "EXlink": "Ex. http://yourwebsite.com/photo", "register": "Create Advertisement", - "close": "Close " + "close": "Close ", + "deleteAdvertisement": "Delete Advertisement", + "deleteAdvertisementMsg": "Do you want to remove this advertisement?", + "no": "No", + "yes": "Yes", + "view": "View", + "edit": "Edit", + "editAdvertisement": "Edit Advertisement", + "saveChanges": "Save Changes", + "endOfResults": "End of results" }, "userChat": { "chat": "Chat", @@ -686,5 +1007,106 @@ "userChatRoom": { "selectContact": "Select a contact to start conversation", "sendMessage": "Send Message" + }, + "orgProfileField": { + "loading": "Loading...", + "noCustomField": "No custom fields available", + "customFieldName": "Field Name", + "enterCustomFieldName": "Enter Field name", + "customFieldType": "Field Type", + "saveChanges": "Save Changes", + "Remove Custom Field": "Remove Custom Field", + "fieldSuccessMessage": "Field added successfully", + "fieldRemovalSuccess": "Field removed successfully" + }, + "orgActionItemCategories": { + "createButton": "Create", + "editButton": "Edit", + "enableButton": "Enable", + "disableButton": "Disable", + "updateActionItemCategory": "Update", + "actionItemCategoryName": "Name", + "actionItemCategoryDetails": "Action Item Category Details", + "enterName": "Enter Name", + "successfulCreation": "Action Item Category created successfully", + "successfulUpdation": "Action Item Category updated successfully", + "sameNameConflict": "Please change the name to make an update", + "categoryEnabled": "Action Item Category Enabled", + "categoryDisabled": "Action Item Category Disabled" + }, + "organizationVenues": { + "title": "Venues", + "addVenue": "Add Venue", + "venueDetails": "Venue Details", + "venueName": "Name of the Venue", + "enterVenueName": "Enter Venue Name", + "description": "Description of the Venue", + "enterVenueDesc": "Enter Venue Description", + "capacity": "Capacity", + "enterVenueCapacity": "Enter Venue Capacity", + "image": "Venue Image", + "uploadVenueImage": "Upload Venue Image", + "createVenue": "Create Venue", + "venueAdded": "Venue added Successfully", + "editVenue": "Update Venue", + "venueUpdated": "Venue details updated successfully", + "sort": "Sort", + "highestCapacity": "Highest Capacity", + "lowestCapacity": "Lowest Capacity", + "noVenues": "No Venues Found!", + "edit": "Edit", + "view": "View", + "delete": "Delete", + "venueTitleError": "Venue title cannot be empty!", + "venueCapacityError": "Capacity must be a positive number!", + "searchBy": "Search By", + "name": "Name", + "desc": "Description" + }, + "addMember": { + "title": "Add Member", + "addMembers": "Add Members", + "existingUser": "Existing User", + "newUser": "New User", + "searchFullName": "Search by Full Name", + "firstName": "First Name", + "enterFirstName": "Enter First Name", + "lastName": "Last Name", + "enterLastName": "Enter Last Name", + "emailAddress": "Email Address", + "enterEmail": "Enter Email", + "password": "Password", + "enterPassword": "Enter Password", + "confirmPassword": "Confirm Password", + "enterConfirmPassword": "Enter Confirm Password", + "organization": "Organization", + "cancel": "Cancel", + "create": "Create", + "invalidDetailsMessage": "Please provide all required details.", + "passwordNotMatch": "Passwords do not match.", + "user": "User", + "addMember": "Add Member" + }, + "eventActionItems": { + "title": "Action Items", + "createActionItem": "Create Action Items", + "actionItemCategory": "Action Item Category", + "selectActionItemCategory": "Select an action item category", + "selectAssignee": "Select an assignee", + "preCompletionNotes": "Pre Completion Notes", + "postCompletionNotes": "Post Completion Notes", + "actionItemDetails": "Action Item Details", + "dueDate": "Due Date", + "completionDate": "Completion Date", + "editActionItem": "Edit Action Item", + "deleteActionItem": "Delete Action Item", + "deleteActionItemMsg": "Do you want to remove this action item?", + "yes": "Yes", + "no": "No", + "successfulDeletion": "Action Item deleted successfully", + "successfulCreation": "Action Item created successfully", + "successfulUpdation": "Action Item updated successfully", + "notes": "Notes", + "save": "Save" } } diff --git a/public/locales/fr.json b/public/locales/fr.json index 818ffd6fcd..4a851b8e8d 100644 --- a/public/locales/fr.json +++ b/public/locales/fr.json @@ -4,12 +4,18 @@ "talawa_portal": "Portail D'Administrateur Talawa", "fromPalisadoes": "Une application open source par les volontaires de la Fondation Palissades", "login": "Connexion", + "userLogin": "Utilisateur en ligne", "register": "S'inscrire", "firstName": "Prénom", "lastName": "Nom de famille", "email": "E-mail", "password": "Mot de passe", "atleast_8_char_long": "Au moins 8 caractères", + "atleast_6_char_long": "Au moins 6 caractères", + "firstName_invalid": "Le prénom ne doit contenir que des lettres minuscules et majuscules", + "lastName_invalid": "Le nom de famille ne doit contenir que des lettres minuscules et majuscules", + "password_invalid": "Le mot de passe doit contenir au moins une lettre minuscule, une lettre majuscule, une valeur numérique et un caractère spécial", + "email_invalid": "L'e-mail doit contenir au moins 8 caractères", "Password_and_Confirm_password_mismatches.": "Le mot de passe et la confirmation du mot de passe ne correspondent pas.", "confirmPassword": "Confirmez le mot de passe", "forgotPassword": "Mot de passe oublié ?", @@ -25,14 +31,24 @@ "notAuthorised": "Désolé ! vous n'êtes pas autorisé !", "notFound": "Utilisateur introuvable !", "successfullyRegistered": "Enregistré avec succès. Veuillez patienter jusqu'à ce que vous soyez approuvé.", - "login_to_admin_portal": "Connexion à l'administration du portail", - "OR": "OU" + "OR": "OU", + "admin": "ADMIN", + "user": "UTILISATEUR", + "lowercase_check": "Au moins une lettre minuscule", + "uppercase_check": "Au moins une lettre majuscule", + "special_char_check": "Au moins un caractère spécial", + "numeric_value_check": "Au moins une valeur numérique" }, "latestEvents": { "eventCardTitle": "Événements à venir", "eventCardSeeAll": "Voir Tout", "noEvents": "Aucun événement à venir" }, + "latestPosts": { + "latestPostsTitle": "Dernières Publications", + "seeAllLink": "Voir Tout", + "noPostsCreated": "Aucune Publication Créée" + }, "listNavbar": { "talawa_portal": "Portail D'Administrateur Talawa", "roles": "Les rôles", @@ -42,9 +58,10 @@ "leftDrawer": { "talawaAdminPortal": "Portail d'administration Talawa", "menu": "Menu", - "organizations": "Organisations", - "requests": "Demandes", + "my organizations": "Mes Organisations", "users": "Utilisateurs", + "requests": "Demandes", + "communityProfile": "Profil de la communauté", "logout": "Déconnexion" }, "leftDrawerOrg": { @@ -78,16 +95,27 @@ "designation": "La désignation", "email": "E-mail", "searchByName": "Rechercher par nom", - "organizations": "Organisations", + "my organizations": "Mes Organisations", "createOrganization": "Créer une organisation", "createSampleOrganization": "Créer une organisation d'exemple", "description": "La description", "location": "Emplacement", - "isPublic": "Est publique", + "address": "Adresse", + "city": "Ville", + "countryCode": "Code Pays", + "line1": "Ligne 1", + "line2": "Ligne 2", + "postalCode": "Code Postal", + "dependentLocality": "Localité Dépendante", + "sortingCode": "Code de Tri", + "state": "État / Province", + "userRegistrationRequired": "enregistrement requis", "visibleInSearch": "Visible dans la recherche", "displayImage": "Afficher l'image", "enterName": "Entrez le nom", "sort": "Trier", + "Earliest": "Le plus tôt", + "Latest": "Dernière", "filter": "Filtre", "cancel": "Annuler", "endOfResults": "Fin des résultats", @@ -104,18 +132,33 @@ "manage": "Faire en sorte", "sampleOrganization": "Organisation d'exemple" }, - "paginationList": { "rowsPerPage": "lignes par page", "all": "Tout" }, + "requests": { + "title": "Demandes", + "sl_no": "Num.", + "name": "Nom", + "email": "Email", + "accept": "Accepter", + "reject": "Rejeter", + "searchRequests": "Rechercher des demandes", + "endOfResults": "Fin des résultats", + "noOrgError": "Organisations introuvables, veuillez créer une organisation via le tableau de bord", + "noResultsFoundFor": "Aucun résultat trouvé pour ", + "noRequestsFound": "Aucune demande trouvée", + "acceptedSuccessfully": "Demande acceptée avec succès", + "rejectedSuccessfully": "Demande rejetée avec succès", + "noOrgErrorTitle": "Organisations non trouvées", + "noOrgErrorDescription": "Veuillez créer une organisation via le tableau de bord" + }, "users": { "title": "Rôles Talawa", "searchByName": "Recherche par nom", "users": "Utilisateurs", "name": "Nom", "email": "E-mail", - "roles_userType": "Rôle/Type d'utilisateur", "joined_organizations": "Organisations rejointes", "blocked_organizations": "Organisations bloquées", "endOfResults": "Fin des résultats", @@ -137,26 +180,29 @@ "filter": "Filtre", "roleUpdated": "Rôle mis à jour.", "noResultsFoundFor": "Aucun résultat trouvé pour ", - "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau." + "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau.", + "cancel": "Annuler", + "admins": "Administrateurs", + "members": "Membres", + "joinNow": "Adhérer maintenant", + "visit": "visite", + "withdraw": "Retirer", + "orgJoined": "Organisation rejointe avec succès", + "MembershipRequestSent": "Demande d'adhésion envoyée avec succès", + "AlreadyJoined": "Vous êtes déjà membre de cette organisation.", + "errorOccured": "Une erreur s'est produite. Veuillez réessayer plus tard." }, - "requests": { - "title": "Demandes Talawa", - "searchByName": "Recherche par nom", - "requests": "Demandes", - "name": "Nom", - "email": "E-mail", - "accept": "Accepter", - "reject": "Rejeter", - "enterName": "Entrez le nom", - "endOfResults": "Fin des résultats", - "loadingRequests": "Chargement des demandes...", - "noRequestFound": "Aucune demande trouvée", - "sort": "Trier", - "filter": "Filtre", - "userApproved": "Approuvé par l'utilisateur", - "userRejected": "Utilisateur rejeté", - "noResultsFoundFor": "Aucun résultat trouvé pour ", - "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau." + "communityProfile": { + "title": "Profil de la communauté", + "editProfile": "Editer le profil", + "communityProfileInfo": "Ces détails apparaîtront sur l'écran de connexion/inscription pour vous et les membres de votre communauté.", + "communityName": "Nom de la communauté", + "wesiteLink": "Lien de site Web", + "logo": "Logo", + "social": "Liens vers les réseaux sociaux", + "url": "Entrer l'URL", + "profileChangedMsg": "Les détails du profil ont été mis à jour avec succès.", + "resetData": "Réinitialisez avec succès les détails du profil." }, "dashboard": { "title": "Tableau de bord", @@ -190,7 +236,26 @@ "searchName": "Entrez le nom", "searchevent": "Entrez l'événement", "searchFirstName": "Entrez votre prénom", - "searchLastName": "Entrer le nom de famille" + "searchLastName": "Entrer le nom de famille", + "people": "Personnes", + "sort": "Trier par rôle", + "actions": "Actions", + "existingUser": "utilisateur existant", + "newUser": "Nouvel Utilisateur", + "firstName": "Prénom", + "enterFirstName": "Entrez votre prénom", + "lastName": "Nom de famille", + "enterLastName": "Entrez votre nom de famille", + "emailAddress": "Email Address", + "enterEmail": "Entrez votre adresse email", + "password": "Mot de passe", + "enterPassword": "Tapez votre mot de passe", + "confirmPassword": "Confirmez le mot de passe", + "enterConfirmPassword": "Entrez votre mot de passe pour confirmer", + "organization": "Organization", + "create": "Créer", + "cancel": "Annuler", + "invalidDetailsMessage": "Veuillez entrer des détails valides." }, "userListCard": { "joined": "Inscrit", @@ -219,7 +284,7 @@ "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau." }, "organizationEvents": { - "title": "Événements Talawa", + "title": "Événements", "filterByTitle": "Filtrer par titre", "filterByLocation": "Filtrer par l'emplacement", "filterByDescription": "Filtrer par Description", @@ -243,12 +308,61 @@ "enterDescrip": "Entrez la description", "eventLocation": "Entrez l'emplacement", "eventCreated": "Toutes nos félicitations! L'événement est créé.", - "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau." + "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau.", + "searchEventName": "Rechercher le nom de l'événement", + "eventType": "Type d'événement", + "customRecurrence": "Récurrence personnalisée", + "repeatsEvery": "Se répète tous les", + "repeatsOn": "Se répète sur", + "ends": "Finit", + "never": "Jamais", + "on": "Sur", + "after": "Après", + "occurences": "Occurrences", + "done": "Fait" + }, + "organizationActionItems": { + "actionItemCategory": "Catégorie de l'élément d'action", + "actionItemActive": "Mesure de suivi active", + "actionItemCompleted": "Mesure de suivi terminée", + "actionItemDetails": "Détails de l'élément d'action", + "actionItemStatus": "État de l’action", + "assignee": "Attributaire", + "assigner": "Assignateur", + "assignmentDate": "Date d'attribution", + "active": "Actif", + "clearFilters": "Effacer les filtres", + "close": "Fermer", + "completed": "Terminé", + "completionDate": "Date d'achèvement", + "createActionItem": "Créer", + "deleteActionItem": "Supprimer l'élément d'action", + "deleteActionItemMsg": "Voulez-vous supprimer cet élément d'action?", + "details": "Détails", + "dueDate": "Date d'échéance", + "earliest": "Le plus tôt", + "editActionItem": "Modifier l'élément d'action", + "eventActionItems": "Mesures à prendre pour l’événement", + "isCompleted": "Terminé", + "latest": "Le plus récent", + "makeActive": "Rendre actif", + "markCompletion": "Marquer l'achèvement", + "no": "Non", + "noActionItems": "Pas d'éléments d'action", + "options": "Options", + "preCompletionNotes": "Notes avant achèvement", + "postCompletionNotes": "Notes après achèvement", + "selectActionItemCategory": "Sélectionnez une catégorie d'élément d'action", + "selectAssignee": "Sélectionnez un attributaire", + "status": "Statut", + "successfulCreation": "Élément d'action créé avec succès", + "successfulUpdation": "Élément d'action mis à jour avec succès", + "successfulDeletion": "Élément d'action supprimé avec succès", + "title": "Éléments d'action", + "yes": "Oui" }, "eventListCard": { - "location": "Emplacement", - "on": "Sur", - "end": "Fin", + "location": "Lieu de l'événement", "deleteEvent": "Supprimer l'événement", "deleteEventMsg": "Voulez-vous supprimer cet événement ?", "no": "Non", @@ -256,6 +370,10 @@ "editEvent": "Modifier l'événement", "eventTitle": "Titre", "description": "La description", + "startDate": "Date de début", + "endDate": "Date de fin", + "registerEvent": "Registre", + "alreadyRegistered": "Déjà enregistré", "startTime": "Heure de début", "endTime": "Heure de fin", "allDay": "Toute la journée", @@ -267,7 +385,101 @@ "eventDetails": "Détails de l'évènement", "eventDeleted": "Événement supprimé avec succès.", "eventUpdated": "Événement mis à jour avec succès.", - "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau." + "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau.", + "thisInstance": "Cette Instance", + "thisAndFollowingInstances": "Cette et les Instances Suivantes", + "allInstances": "Toutes les Instances", + "customRecurrence": "Récurrence personnalisée", + "repeatsEvery": "Se répète tous les", + "repeatsOn": "Se répète sur", + "ends": "Finit", + "never": "Jamais", + "on": "Sur", + "after": "Après", + "occurences": "Occurrences", + "done": "Fait" + }, + "funds": { + "title": "Fonds", + "createFund": "Créer un fonds", + "fundName": "Nom du fonds", + "fundId": "Identifiant du fonds", + "fundOptions": "Options de fonds", + "noFunds": "Pas de fonds", + "fundDetails": "Détails du fonds", + "taxDeductible": "Déductible d'impôt", + "enterfundName": "Entrez le nom du fonds", + "enterfundId": "Entrez l'identifiant du fonds", + "default": "Défaut", + "archived": "Archivé", + "nonArchive": "Non archivé", + "fundCreate": "Créer un fonds", + "fundUpdate": "Mettre à jour le fonds", + "fundDelete": "Supprimer le fonds", + "no": "Non", + "yes": "Oui", + "manageFund": "Gérer le fonds", + "searchFullName": "Rechercher par nom", + "filter": "Filtre", + "noFundsFound": "Aucun fonds trouvé", + "createdBy": "Créé par", + "createdOn": "Créé le", + "status": "Statut", + "archiveFund": "Archiver le fonds", + "archiveFundMsg": "Voulez-vous archiver ce fonds ?", + "fundCreated": "Fonds créé avec succès", + "fundUpdated": "Fonds mis à jour avec succès", + "fundDeleted": "Fonds supprimé avec succès", + "fundArchived": "Fonds archivé avec succès", + "fundUnarchived": "Fonds désarchivé avec succès", + "deleteFundMsg": "Voulez-vous supprimer ce fonds ?" + }, + "fundCampaign": { + "title": "Campagne de fonds", + "campaignName": "Nom de la campagne", + "startDate": "Date de début", + "endDate": "Date de fin", + "campaignOptions": " Options de campagne", + "fundingGoal": "Objectif de financement", + "addCampaign": "Ajouter une campagne", + "createdCampaign": "Campagne créée avec succès", + "updatedCampaign": "Campagne mise à jour avec succès", + "deletedCampaign": "Campagne supprimée avec succès", + "deleteCampaignMsg": "Voulez-vous supprimer cette campagne?", + "noCampaigns": "Pas de campagnes", + "createCampaign": "Créer une campagne de fonds", + "updateCampaign": "Mettre à jour la campagne de fonds", + "manageCampaign": "Gérer la campagne de fonds", + "deleteCampaign": "Supprimer la campagne de fonds", + "no": "Non", + "yes": "Oui", + "currency": "Devise", + "selectCurrency": "Sélectionnez la devise", + "filter": "Filtre", + "searchFullName": "Rechercher par nom" + }, + "pledges": { + "title": "Engagements de campagne de financement", + "volunteers": "Bénévoles", + "startDate": "Date de début", + "endDate": "Date de fin", + "pledgeAmount": "Montant de l'engagement", + "pledgeOptions": "Options", + "pledgeCreated": "Engagement créé avec succès", + "pledgeUpdated": "Engagement mis à jour avec succès", + "pledgeDeleted": "Engagement supprimé avec succès", + "addPledge": "Ajouter un engagement", + "createPledge": "Créer un engagement", + "currency": "Devise", + "selectCurrency": "Sélectionner une devise", + "updatePledge": "Mettre à jour l'engagement", + "deletePledge": "Supprimer l'engagement", + "amount": "Montant", + "editPledge": "Modifier l'engagement", + "deletePledgeMsg": "Êtes-vous sûr de vouloir supprimer cet engagement?", + "no": "Non", + "yes": "Oui", + "noPledges": "Aucun engagement trouvé" }, "orgPost": { "title": "Talawa Publications", @@ -277,10 +489,9 @@ "postDetails": "Détails de la publication", "postTitle1": "Écrire le titre de la publication", "postTitle": "Titre", + "addMedia": "Télécharger une photo ou une vidéo", "information": "Informations", "information1": "Écrire les informations de la publication", - "image": "Image de la publication", - "video": "Vidéo de la publication", "addPost": "Ajouter une publication", "searchTitle": "Rechercher par titre", "searchText": "Rechercher par texte", @@ -293,7 +504,11 @@ "Oldest": "Les plus anciennes d'abord", "Latest": "Les plus récentes d'abord", "sortPost": "Trier les publications", - "tag": "Votre navigateur ne prend pas en charge la balise vidéo" + "tag": "Votre navigateur ne prend pas en charge la balise vidéo", + "postCreatedSuccess": "Félicitations ! Vous avez publié quelque chose.", + "pinPost": "Épingler le message", + "Next": "Suivant ", + "Previous": "Précédent" }, "postNotFound": { "post": "Poste", @@ -322,6 +537,8 @@ "yes": "Oui", "editPost": "Modifier la publication", "postTitle": "Titre", + "postTitle1": "Modifier le titre du message", + "information1": "Modifier les informations du message", "information": "Informations", "image": "Image", "video": "Vidéo", @@ -354,6 +571,14 @@ "noResultsFoundFor": "Aucun résultat trouvé pour ", "noSpammerFound": "Aucun spammeur trouvé" }, + "eventManagement": { + "title": "Gestion des événements", + "dashboard": "Tableau de bord", + "registrants": "Participants inscrits", + "eventActions": "Actions d'événement", + "eventStats": "Statistiques de l'événement", + "to": "À" + }, "forgotPassword": { "title": "Mot de passe oublié Talawa", "forgotPassword": "Mot de passe oublié", @@ -376,6 +601,7 @@ "pageNotFound": { "title": "404 introuvable", "talawaAdmin": "Administrateur Talawa", + "talawaUser": "Utilisateur Talawa", "404": "404", "notFoundMsg": "Oups ! La page demandée est introuvable !", "backToHome": "De retour à la maison" @@ -402,6 +628,8 @@ "orgSettings": { "title": "Paramètre Talawa", "pageName": "Paramètres", + "general": "Général", + "actionItemCategories": "Catégories d’éléments d’action", "updateYourDetails": "Mettre à jour vos informations", "updateYourPassword": "Mettez à jour votre mot de passe", "updateOrganization": "Mettre à jour l'organisation", @@ -409,7 +637,8 @@ "settings": "Réglages", "noData": "Pas de données", "otherSettings": "Autres paramètres", - "changeLanguage": "Changer la langue" + "changeLanguage": "Changer la langue", + "manageCustomFields": "Gérer les Champs Personnalisés" }, "deleteOrg": { "deleteOrganization": "Supprimer l'organisation", @@ -417,7 +646,8 @@ "deleteMsg": "Voulez-vous supprimer cette organisation ?", "cancel": "Annuler", "confirmDelete": "Confirmer la suppression", - "longDelOrgMsg": "En cliquant sur le bouton Supprimer l'organisation, l'organisation sera définitivement supprimée ainsi que ses événements, balises et toutes les données associées." + "longDelOrgMsg": "En cliquant sur le bouton Supprimer l'organisation, l'organisation sera définitivement supprimée ainsi que ses événements, balises et toutes les données associées.", + "successfullyDeletedSampleOrganization": "Exemple d'organisation supprimé avec succès" }, "userUpdate": { "firstName": "Prénom", @@ -453,8 +683,17 @@ "name": "Nom", "description": "La description", "location": "emplacement", + "address": "Adresse", + "city": "Ville", + "countryCode": "Code Pays", + "line1": "Ligne 1", + "line2": "Ligne 2", + "postalCode": "Code Postal", + "dependentLocality": "Localité Dépendante", + "sortingCode": "Code de Tri", + "state": "État / Province", "displayImage": "Afficher l'image", - "isPublic": "Public", + "userRegistrationRequired": "enregistrement requis", "isVisibleInSearch": "Visible dans la recherche", "saveChanges": "Sauvegarder les modifications", "enterNameOrganization": "Entrez le nom de l'organisation", @@ -493,6 +732,7 @@ "memberDetail": { "title": "Détails de l'utilisateur", "addAdmin": "Ajouter un administrateur", + "alreadyIsAdmin": "Le membre est déjà un administrateur", "organizations": "Organisations", "events": "Événements", "role": "Rôle", @@ -501,9 +741,25 @@ "main": "Principal", "firstName": "Prénom", "lastName": "Nom de famille", - "memberOfOrganization": "Membre de l'organisation", "language": "Langue", - "adminApproved": "Approuvé par l'administrateur", + "gender": "Genre", + "birthDate": "Date de naissance", + "educationGrade": "Niveau d'éducation", + "employmentStatus": "Statut d'emploi", + "maritalStatus": "État civil", + "displayImage": "Image de profil", + "phone": "Téléphone", + "address": "Adresse", + "countryCode": "Code pays", + "state": "État", + "city": "Ville", + "personalInfoHeading": "Informations personnelles", + "contactInfoHeading": "Coordonnées", + "actionsHeading": "Actions", + "personalDetailsHeading": "Détails du profil", + "appLanguageCode": "Choisir la langue", + "delete": "Supprimer l'utilisateur", + "saveChanges": "Enregistrer les modifications", "pluginCreationAllowed": "Autorisation de création de plugin", "joined": "Rejoint", "created": "Créé", @@ -553,7 +809,6 @@ "events": "Événements", "chat": "Discuter", "donate": "Donner", - "myTasks": "Mes tâches", "settings": "Paramètres", "language": "Langue", "logout": "Se déconnecter", @@ -563,14 +818,25 @@ "allOrganizations": "Toutes les organisations", "joinedOrganizations": "Organisations jointes", "createdOrganizations": "Organisations créées", - "search": "Recherche", + "search": "Rechercher des utilisateurs", "nothingToShow": "Rien à montrer ici.", - "selectOrganization": "Sélectionnez une organisation" + "selectOrganization": "Sélectionnez une organisation", + "filter": "Filtre", + "organizations": "Organizations", + "searchByName": "Recherche par nom" }, - "userSidebar": { + "userSidebarOrg": { "yourOrganizations": "Vos organisations", "noOrganizations": "Vous n'avez encore rejoint aucune organisation.", - "viewAll": "Voir tout" + "viewAll": "Voir tout", + "talawaUserPortal": "Talawa portail utilisateur", + "menu": "Menu", + "my organizations": "Mes Organisations", + "users": "Utilisateurs", + "requests": "Demandes", + "communityProfile": "Profil de la communauté", + "logout": "Se déconnecter", + "settings": "Paramètres" }, "organizationSidebar": { "viewAll": "Voir tout", @@ -586,34 +852,89 @@ "home": { "feed": "Alimentation", "pinnedPosts": "Afficher les publications épinglées", - "somethingOnYourMind": "Quelque chose dans votre esprit?" + "somethingOnYourMind": "Quelque chose dans votre esprit?", + "addPost": "Ajouter une publication", + "startPost": "Commencer une publication", + "media": "Médias", + "event": "Événement", + "article": "Article" }, "settings": { + "settings": "Paramètres", "profileSettings": "Paramètres de profil", "firstName": "Prénom", "lastName": "Nom de famille", + "gender": "Genre", "emailAddress": "Adresse e-mail", - "updateImage": "Mettre à jour l'image", - "save": "Sauvegarder" + "phoneNumber": "Numéro de téléphone", + "displayImage": "Image de profil", + "chooseFile": "Choisir un fichier", + "birthDate": "Date de naissance", + "grade": "Niveau scolaire", + "empStatus": "Situation professionnelle", + "maritalStatus": "État civil", + "address": "Adresse", + "state": "Ville/État", + "country": "Pays", + "resetChanges": "Réinitialiser les modifications", + "saveChanges": "Enregistrer les modifications", + "profileDetails": "Détails du profil", + "deleteUserMessage": "En cliquant sur le bouton Supprimer l'utilisateur, votre utilisateur sera supprimé définitivement ainsi que ses événements, tags et toutes les données associées.", + "copyLink": "Copier le lien du profil", + "deleteUser": "Supprimer l'utilisateur", + "otherSettings": "Autres paramètres", + "changeLanguage": "Changer la langue", + "sgender": "Sélectionner le genre", + "gradePlaceholder": "Entrer la note", + "sEmpStatus": "Sélectionner le statut d'emploi", + "male": "Homme", + "female": "Femme", + "other": "Autre", + "employed": "Employé(e)", + "unemployed": "Sans emploi", + "sMaritalStatus": "Sélectionner l'état civil", + "single": "Célibataire", + "married": "Marié(e)", + "divorced": "Divorcé(e)", + "widowed": "Veuf(ve)", + "engaged": "Fiancé(e)", + "seperated": "Séparé(e)", + "grade1": "CP (Cours Préparatoire)", + "grade2": "CE1 (Cours Élémentaire 1ère année)", + "grade3": "CE2 (Cours Élémentaire 2ème année)", + "grade4": "CM1 (Cours Moyen 1ère année)", + "grade5": "CM2 (Cours Moyen 2ème année)", + "grade6": "6ème", + "grade7": "5ème", + "grade8": "4ème", + "grade9": "3ème", + "grade10": "Seconde", + "grade11": "Première", + "grade12": "Terminale", + "graduate": "Diplômé(e)", + "kg": "Maternelle", + "preKg": "Toute Petite Section", + "noGrade": "Pas de niveau", + "fullTime": "Temps plein", + "partTime": "Temps partiel", + "enterState": "Entrer la ville ou l'état", + "selectCountry": "Sélectionner un pays", + "joined": "Rejoint" }, "donate": { - "donateTo": "Faire un don à", + "donations": "Des dons", + "searchDonations": "Rechercher des dons", + "donateForThe": "Faites un don pour le", "amount": "Montante", "yourPreviousDonations": "Vos dons précédents", "donate": "Donner", - "nothingToShow": "Rien à montrer ici." + "nothingToShow": "Rien à montrer ici.", + "success": "Don réussi" }, "userEvents": { "nothingToShow": "Rien à montrer ici.", "search": "Recherche", "createEvent": "Créer un évènement", - "eventTitle": "Titre de l'événement", - "eventDescription": "Description de l'évenement", - "eventLocation": "Lieu de l'événement", - "startDate": "Sélectionnez la date de début", - "endDate": "Sélectionnez la date de fin", - "publicEvent": "Évennement publique", - "registerable": "Enregistrable", "recurring": "Récurrente", "startTime": "Heure de début", "endTime": "Heure de fin", @@ -622,7 +943,20 @@ "listView": "Vue en liste", "calendarView": "Vue du calendrier", "allDay": "Toute la journée", - "eventCreated": "Événement créé et publié avec succès." + "eventCreated": "Événement créé et publié avec succès.", + "eventDetails": "Détails de l'événement", + "eventTitle": "Titre", + "enterTitle": "Entrez le titre", + "eventDescription": "Description", + "enterDescription": "Entrez la description", + "eventLocation": "Emplacement", + "enterLocation": "Entrez l'emplacement", + "startDate": "Date de début", + "endDate": "Date de fin", + "publicEvent": "Est public", + "registerable": "Est enregistrable", + "monthlyCalendarView": "Calendrier mensuel", + "yearlyCalendarView": "Calendrier annuel" }, "userEventCard": { "location": "Emplacement", @@ -632,29 +966,26 @@ "alreadyRegistered": "Déjà enregistré", "register": "Registre" }, - "userTasks": { - "yourAssignedTasks": "Vos tâches assignées", - "nothingToShow": "Rien à montrer ici." - }, - "userTaskCard": { - "description": "Description", - "deadline": "Date limite", - "created": "Créé", - "assignees": "Destinataires", - "completed": "Complété", - "incomplete": "Incomplète", - "taskCompleted": "La tâche est terminée", - "taskNotCompleted": "La tâche n'est pas encore terminée", - "event": "Événement", - "organization": "Organisation" - }, "advertisement": { "title": "Publicités", "pHeading": "Gérer les publicités", "activeAds": "Campagnes actives", "archievedAds": "Campagnes terminées", "pMessage": "Aucune publicité n'est présente pour cette campagne.", - "delete": "Supprimer" + "delete": "Supprimer", + "validLink": "Le lien est valide", + "invalidLink": "Le lien n'est pas valide", + "close": "Fermer", + "deleteAdvertisement": "Supprimer l'annonce", + "deleteAdvertisementMsg": "Voulez-vous supprimer cette annonce ?", + "no": "Non", + "yes": "Oui", + "Rmedia": "Fournir du contenu multimédia à afficher", + "view": "Voir", + "edit": "Éditer", + "editAdvertisement": "Éditer l'annonce", + "saveChanges": "Enregistrer les modifications", + "endOfResults": "Fin des résultats" }, "userChat": { "chat": "Chat", @@ -664,5 +995,106 @@ "userChatRoom": { "selectContact": "Sélectionnez un contact pour démarrer la conversation", "sendMessage": "Envoyer le message" + }, + "orgProfileField": { + "loading": "Chargement...", + "noCustomField": "Aucun champ personnalisé disponible", + "customFieldName": "Nom du champ", + "enterCustomFieldName": "Entrez le nom du champ", + "customFieldType": "Type de champ", + "saveChanges": "Enregistrer les modifications", + "Supprimer le champ personnalisé": "Supprimer le champ personnalisé", + "fieldSuccessMessage": "Champ ajouté avec succès", + "fieldRemovalSuccess": "Champ supprimé avec succès" + }, + "orgActionItemCategories": { + "createButton": "Créez", + "editButton": "Éditez", + "enableButton": "Activez", + "disableButton": "Désactivez", + "updateActionItemCategory": "Mettre à jour", + "actionItemCategoryName": "Nom", + "actionItemCategoryDetails": "Détails de la catégorie d’élément d’action", + "enterName": "Entrez le nom", + "successfulCreation": "Catégorie d’élément d’action créée avec succès", + "successfulUpdation": "La catégorie d’élément d’action a été mise à jour avec succès", + "sameNameConflict": "Veuillez modifier le nom pour effectuer une mise à jour", + "categoryEnabled": "Catégorie d’action activée", + "categoryDisabled": "Catégorie d’action désactivée" + }, + "organizationVenues": { + "title": "Lieux", + "addVenue": "Ajouter un lieu", + "venueDetails": "Détails du lieu", + "venueName": "Nom du lieu", + "enterVenueName": "Entrez le nom du lieu", + "description": "Description du lieu", + "enterVenueDesc": "Entrez la description du lieu", + "capacity": "Capacité", + "enterVenueCapacity": "Entrez la capacité du lieu", + "image": "Image du lieu", + "uploadVenueImage": "Télécharger l'image du lieu", + "createVenue": "Créer un lieu", + "venueAdded": "Lieu ajouté avec succès", + "editVenue": "Mettre à jour le lieu", + "venueUpdated": "Détails du lieu mis à jour avec succès", + "sort": "Trier", + "highestCapacity": "Capacité la plus élevée", + "lowestCapacity": "Capacité la plus faible", + "noVenues": "Aucun lieu trouvé!", + "edit": "Modifier", + "view": "Voir", + "delete": "Supprimer", + "venueTitleError": "Le titre du lieu ne peut pas être vide!", + "venueCapacityError": "La capacité doit être un nombre positif!", + "searchBy": "Rechercher par", + "name": "Nom", + "desc": "Description" + }, + "addMember": { + "title": "Ajouter un membre", + "addMembers": "Ajouter des membres", + "existingUser": "Utilisateur existant", + "newUser": "Nouvel utilisateur", + "searchFullName": "Rechercher par nom complet", + "firstName": "Prénom", + "enterFirstName": "Entrez le prénom", + "lastName": "Nom de famille", + "enterLastName": "Entrez le nom de famille", + "emailAddress": "Adresse e-mail", + "enterEmail": "Entrez l'e-mail", + "password": "Mot de passe", + "enterPassword": "Entrez le mot de passe", + "confirmPassword": "Confirmer le mot de passe", + "enterConfirmPassword": "Confirmez le mot de passe", + "organization": "Organisation", + "cancel": "Annuler", + "create": "Créer", + "invalidDetailsMessage": "Veuillez fournir tous les détails requis.", + "passwordNotMatch": "Les mots de passe ne correspondent pas.", + "user": "Utilisateur", + "addMember": "Ajouter un membre" + }, + "eventActionItems": { + "title": "Éléments d'action", + "createActionItem": "Créer des éléments d'action", + "actionItemCategory": "Catégorie d'éléments d'action", + "selectActionItemCategory": "Sélectionnez une catégorie d'élément d'action", + "selectAssignee": "Sélectionner un cessionnaire", + "preCompletionNotes": "Notes de pré-achèvement", + "postCompletionNotes": "Notes post-achèvement", + "actionItemDetails": "Détails de l'élément d'action", + "dueDate": "Date d'échéance", + "completetionDate": "Date d'achèvement", + "editActionItem": "Modifier l'élément d'action", + "deleteActionItem": "Supprimer l'élément d'action", + "deleteActionItemMsg": "Voulez-vous supprimer cette action ?", + "yes": "Oui", + "no": "non", + "successfulDeletion": "Élément d'action supprimé avec succès", + "successfulCreation": "Élément d'action créé avec succès", + "successfulUpdation": "Élément d'action mis à jour avec succès", + "notes": "Remarques", + "save": "Enregistrer" } } diff --git a/public/locales/hi.json b/public/locales/hi.json index fb9ae1ab23..eddc354c5c 100644 --- a/public/locales/hi.json +++ b/public/locales/hi.json @@ -4,12 +4,18 @@ "fromPalisadoes": "पलिसाडो के स्वयंसेवकों द्वारा एक खुला स्रोत अनुप्रयोग", "talawa_portal": "तलावा प्रशासन पोर्टल", "login": "लॉग इन करें", + "userLogin": "उपयोगकर्ता लॉगिन", "register": "पंजीकरण करवाना", "firstName": "पहला नाम", "lastName": "उपनाम", "email": "ईमेल", "password": "पासवर्ड", "atleast_8_char_long": "कम से कम 8 कैरेक्टर लंबा", + "atleast_6_char_long": "कम से कम 6 अक्षर लंबा", + "firstName_invalid": "प्रथम नाम में केवल छोटे और बड़े अक्षर होने चाहिए", + "lastName_invalid": "अंतिम नाम में केवल छोटे और बड़े अक्षर होने चाहिए", + "password_invalid": "पासवर्ड में कम से कम एक लोअरकेस अक्षर, एक अपरकेस अक्षर, एक संख्यात्मक मान और एक विशेष अक्षर होना चाहिए", + "email_invalid": "ईमेल में कम से कम 8 अक्षर होने चाहिए", "Password_and_Confirm_password_mismatches.": "पासवर्ड और पुष्टि पासवर्ड बेमेल।", "confirmPassword": "पासवर्ड की पुष्टि कीजिये", "forgotPassword": "पासवर्ड भूल गए ?", @@ -25,14 +31,24 @@ "notAuthorised": "क्षमा करें! आप अधिकृत नहीं हैं!", "notFound": "उपयोगकर्ता नहीं मिला!", "successfullyRegistered": "सफलतापूर्वक पंजीकृत। कृपया स्वीकृत होने तक प्रतीक्षा करें।", - "login_to_admin_portal": "एडमिन पोर्टल लॉगिन", - "OR": "या" + "OR": "या", + "admin": "व्यवस्थापक", + "user": "उपयोगकर्ता", + "lowercase_check": "कम से कम एक छोटा अक्षर", + "uppercase_check": "कम से कम एक बड़ा अक्षर", + "numeric_value_check": "कम से कम एक संख्यात्मक मान", + "special_char_check": "कम से कम एक विशेष पात्र" }, "latestEvents": { "eventCardTitle": "आगामी घटनाएँ", "eventCardSeeAll": "सभी देखें", "noEvents": "कोई आगामी घटनाएँ नहीं" }, + "latestPosts": { + "latestPostsTitle": "नवीनतम पोस्ट", + "seeAllLink": "सभी देखें", + "noPostsCreated": "कोई पोस्ट नहीं बनाई गई" + }, "listNavbar": { "talawa_portal": "तलावा प्रशासन पोर्टल", "roles": "भूमिकाएँ", @@ -42,9 +58,10 @@ "leftDrawer": { "talawaAdminPortal": "तलावा व्यवस्थापक पोर्टल", "menu": "मेन्यू", - "organizations": "संगठन", - "requests": "अनुरोध", + "my organizations": "मेरे संगठन", "users": "उपयोगकर्ता", + "requests": "अनुरोध", + "communityProfile": "सामुदायिक प्रोफ़ाइल", "logout": "लॉग आउट" }, "leftDrawerOrg": { @@ -78,16 +95,27 @@ "designation": "पद", "email": "ईमेल", "searchByName": "नाम से खोजें", - "organizations": "संगठन", + "my organizations": "मेरे संगठन", "createOrganization": "संगठन बनाएं", "createSampleOrganization": " सैंपल संगठन बनाएं", "description": "विवरण", "location": "स्थान", - "isPublic": "सार्वजनिक है", + "address": "पता", + "city": "शहर", + "countryCode": "देश कोड", + "line1": "लाइन 1", + "line2": "लाइन 2", + "postalCode": "पोस्टल कोड", + "dependentLocality": "आश्रित स्थान", + "sortingCode": "क्रमबद्ध कोड", + "state": "राज्य / प्रांत", + "userRegistrationRequired": "उपयोगकर्ता पंजीकरण आवश्यक", "visibleInSearch": "खोज में दृश्यमान", "displayImage": "प्रदर्शन छवि", "enterName": "नाम दर्ज करें", "sort": "छांटें", + "Earliest": "सबसे पुराना", + "Latest": "सबसे नवीनतम", "filter": "फ़िल्टर", "cancel": "रद्द करना", "endOfResults": "परिणामों का अंत", @@ -108,13 +136,29 @@ "rowsPerPage": "प्रति पृष्ठ पंक्तियाँ", "all": "सभी" }, + "requests": { + "title": "अनुरोध", + "sl_no": "क्रमांक", + "name": "नाम", + "email": "ईमेल", + "accept": "स्वीकार करें", + "reject": "अस्वीकार करें", + "searchRequests": "अनुरोध खोजें", + "endOfResults": "परिणामों का समाप्ति", + "noOrgError": "संगठन नहीं मिला, कृपया डैशबोर्ड के माध्यम से एक संगठन बनाएं", + "noResultsFoundFor": "के लिए कोई परिणाम नहीं मिला ", + "noRequestsFound": "कोई अनुरोध नहीं मिला", + "acceptedSuccessfully": "अनुरोध सफलतापूर्वक स्वीकार किया गया", + "rejectedSuccessfully": "अनुरोध सफलतापूर्वक अस्वीकार किया गया", + "noOrgErrorTitle": "संगठन नहीं मिला", + "noOrgErrorDescription": "कृपया डैशबोर्ड के माध्यम से एक संगठन बनाएं" + }, "users": { "title": "तलावा भूमिकाएं", "searchByName": "नाम से खोजें", "users": "उपयोगकर्ता", "name": "नाम", "email": "ईमेल", - "roles_userType": "भूमिका/उपयोगकर्ता-प्रकार", "joined_organizations": "संगठनों में शामिल हुए", "blocked_organizations": "अवरोधित संगठन", "endOfResults": "परिणामों का अंत", @@ -136,26 +180,29 @@ "filter": "फ़िल्टर", "roleUpdated": "भूमिका अपडेट की गई।", "noResultsFoundFor": "के लिए कोई परिणाम नहीं मिला ", - "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।" + "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।", + "cancel": "रद्द करें", + "admins": "व्यवस्थापक", + "members": "सदस्य", + "joinNow": "अब शामिल हों", + "visit": "दर्शन", + "withdraw": "अनुरोध वापस लें", + "orgJoined": "संगठन सफलतापूर्वक जुड़ा गया", + "MembershipRequestSent": "सदस्यता अनुरोध सफलतापूर्वक भेजा गया", + "AlreadyJoined": "आप इस संगठन के पहले से ही सदस्य हैं।", + "errorOccured": "कुछ गड़बड़ हो गई है। कृपया बाद में पुन: प्रयास करें।" }, - "requests": { - "title": "तलवा अनुरोध", - "searchByName": "नाम से खोजें", - "requests": "अनुरोध", - "name": "नाम", - "email": "ईमेल", - "accept": "स्वीकार करना", - "reject": "अस्वीकार", - "enterName": "नाम दर्ज करें", - "endOfResults": "परिणामों का अंत", - "loadingRequests": "अनुरोध लोड हो रहा है ...", - "noRequestFound": "कोई अनुरोध नहीं मिला।", - "sort": "छांटें", - "filter": "फ़िल्टर", - "userApproved": "उपयोगकर्ता स्वीकृत", - "userRejected": "उपयोगकर्ता अस्वीकृत", - "noResultsFoundFor": "के लिए कोई परिणाम नहीं मिला ", - "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।" + "communityProfile": { + "title": "सामुदायिक प्रोफ़ाइल", + "editProfile": "प्रोफ़ाइल संपादित करें", + "communityProfileInfo": "ये विवरण आपके और आपके समुदाय के सदस्यों के लिए लॉगिन/साइनअप स्क्रीन पर दिखाई देंगे", + "communityName": "समुदाय का नाम", + "wesiteLink": "वेबसाइट की लिंक", + "logo": "प्रतीक चिन्ह", + "social": "सोशल मीडिया लिंक", + "url": "यू आर एल दर्ज करो", + "profileChangedMsg": "प्रोफ़ाइल विवरण सफलतापूर्वक अपडेट किया गया।", + "resetData": "प्रोफ़ाइल विवरण सफलतापूर्वक रीसेट किया गया।" }, "dashboard": { "title": "डैशबोर्ड", @@ -189,7 +236,26 @@ "searchName": "नाम दर्ज करें", "searchevent": "घटना दर्ज करें", "searchFirstName": "प्रथम नाम दर्ज करें", - "searchLastName": "अंतिम नाम दर्ज करो" + "searchLastName": "अंतिम नाम दर्ज करो", + "people": "लोग", + "sort": "भूमिका के आधार पर खोजें", + "actions": "क्रियाएँ", + "existingUser": "मौजूदा उपयोगकर्ता", + "newUser": "नए उपयोगकर्ता", + "firstName": "पहला नाम", + "enterFirstName": "अपना पहला नाम दर्ज करें", + "lastName": "अंतिम नाम", + "enterLastName": "अपना अंतिम नाम दर्ज करें", + "emailAddress": "ईमेल एड्रेस", + "enterEmail": "अपना ईमेल पता दर्ज करें", + "password": "पासवर्ड", + "enterPassword": "अपना पासवर्ड डालें", + "confirmPassword": "पासवर्ड की पुष्टि कीजिये", + "enterConfirmPassword": "पुष्टि करने के लिए अपना पासवर्ड दर्ज करें", + "organization": "संगठन", + "create": "बनाएं", + "cancel": "रद्द करना", + "invalidDetailsMessage": "कृपया मान्य विवरण दर्ज करें।" }, "userListCard": { "joined": "में शामिल हो गए", @@ -218,7 +284,7 @@ "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।" }, "organizationEvents": { - "title": "तलावा इवेंट्स", + "title": "आयोजन", "filterByTitle": "शीर्षक द्वारा फ़िल्टर करें", "filterByLocation": "स्थान के अनुसार फ़िल्टर करें", "filterByDescription": "विवरण द्वारा फ़िल्टर करें", @@ -242,12 +308,62 @@ "enterDescrip": "विवरण दर्ज करें", "eventLocation": "स्थान दर्ज करें", "eventCreated": "बधाई हो! इवेंट बनाया गया है।", - "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।" + "searchEventName": "ईवेंट नाम खोजें", + "eventType": "ईवेंट प्रकार", + "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।", + "customRecurrence": "कस्टम पुनरावृत्ति", + "repeatsEvery": "दोहराता है हर", + "repeatsOn": "को दोहराएगा", + "ends": "समाप्त होता", + "never": "कभी नहीं", + "on": "पर", + "after": "के बाद", + "occurences": "'घटित होता है", + "done": "समाज-सम्मत" + }, + "organizationActionItems": { + "actionItemCategory": "कार्य आइटम श्रेणी", + "actionItemActive": "क्रिया आइटम सक्रिय", + "actionItemCompleted": "क्रिया आइटम पूर्ण हुआ", + "actionItemDetails": "कार्य आइटम विवरण", + "actionItemStatus": "कार्रवाई आइटम स्थिति", + "assignee": "सौंपने वाला", + "assigner": "निर्धारक", + "assignmentDate": "सौंपने की तारीख", + "active": "सक्रिय", + "clearFilters": "फ़िल्टर हटाएं", + "close": "बंद करें", + "completed": "पूरा हुआ", + "completionDate": "समापन तिथि", + "createActionItem": "बनाएं", + "deleteActionItem": "कार्य आइटम हटाएं", + "deleteActionItemMsg": "क्या आप इस कार्य आइटम को हटाना चाहते हैं?", + "details": "विवरण", + "dueDate": "नियत तारीख", + "earliest": "सबसे पहले", + "editActionItem": "कार्य आइटम संपादित करें", + "eventActionItems": "इवेंट एक्शन आइटम", + "isCompleted": "पूरा हुआ", + "latest": "नवीनतम", + "makeActive": "सक्रिय करें", + "markCompletion": "मार्क पूर्णता", + "no": "नहीं", + "noActionItems": "कोई कार्य आइटम नहीं", + "options": "विकल्प", + "preCompletionNotes": "समापन से पहले के नोट्स", + "postCompletionNotes": "समापन के बाद के नोट्स", + "searchByName": "नाम से खोजें", + "selectActionItemCategory": "कार्य आइटम श्रेणी का चयन करें", + "selectAssignee": "सौंपने वाला चुनें", + "status": "स्थिति", + "successfulCreation": "कार्य आइटम सफलतापूर्वक बनाया गया", + "successfulUpdation": "कार्य आइटम सफलतापूर्वक अपडेट किया गया", + "successfulDeletion": "कार्य आइटम सफलतापूर्वक हटाया गया", + "title": "कार्य आइटम", + "yes": "हाँ" }, "eventListCard": { - "location": "स्थान", - "on": "पर", - "end": "समाप्त", + "location": "आयोजन स्थान", "deleteEvent": "घटना हटाएं", "deleteEventMsg": "क्या आप इस इवेंट को हटाना चाहते हैं?", "no": "नहीं", @@ -255,6 +371,10 @@ "editEvent": "घटना संपादित करें", "eventTitle": "शीर्षक", "description": "विवरण", + "startDate": "आरंभ करने की तिथि", + "endDate": "अंतिम तिथि", + "registerEvent": "रजिस्टर करें", + "alreadyRegistered": "पहले से ही पंजीकृत", "startTime": "समय शुरू", "endTime": "अंत समय", "allDay": "पूरे दिन", @@ -266,8 +386,104 @@ "eventDetails": "घटना की जानकारी", "eventDeleted": "इवेंट सफलतापूर्वक मिटाया गया.", "eventUpdated": "इवेंट सफलतापूर्वक अपडेट किया गया।", - "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।" + "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।", + "thisInstance": "यह अवसर", + "thisAndFollowingInstances": "यह और निम्नलिखित अवसर", + "allInstances": "सभी अवसर", + "customRecurrence": "कस्टम पुनरावृत्ति", + "repeatsEvery": "दोहराता है हर", + "repeatsOn": "को दोहराएगा", + "ends": "समाप्त होता", + "never": "कभी नहीं", + "on": "पर", + "after": "के बाद", + "occurences": "'घटित होता है", + "done": "समाज-सम्मत" + }, + "funds": { + "title": "फंड्स", + "createFund": "फंड बनाएँ", + "fundName": "फंड का नाम", + "fundId": "फंड आईडी", + "fundOptions": "फंड विकल्प", + "noFunds": "कोई फंड नहीं", + "fundDetails": "फंड विवरण", + "taxDeductible": "कर कटौती", + "enterfundName": " फंड का नाम दर्ज करें", + "enterfundId": " फंड आईडी दर्ज करें", + "default": "डिफ़ॉल्ट", + "archived": "संग्रहीत", + "nonArchive": "गैर संग्रहीत", + "fundCreate": "फंड बनाएँ", + "fundUpdate": "फंड अपडेट करें", + "fundDelete": "फंड हटाएं", + "no": "नहीं", + "yes": "हाँ", + "manageFund": "कोष प्रबंधित करें", + "searchFullName": "नाम से खोजें", + "filter": "फ़िल्टर", + "noFundsFound": "कोई धनराशि नहीं मिली", + "createdBy": "द्वारा बनाया गया", + "createdOn": "बनाया गया", + "status": "स्थिति", + "archiveFund": "फंड संग्रहीत करें", + "archiveFundMsg": "क्या आप इस फंड को संग्रहीत करना चाहते हैं?", + "fundCreated": "फंड सफलतापूर्वक बनाया गया", + "fundUpdated": "फंड सफलतापूर्वक अपडेट किया गया", + "fundDeleted": "फंड सफलतापूर्वक हटाया गया", + "fundArchived": "फंड सफलतापूर्वक संग्रहीत किया गया", + "fundUnarchived": "फंड सफलतापूर्वक गैर संग्रहीत किया गया", + "deleteFundMsg": "क्या आप इस फंड को हटाना चाहते हैं?" + }, + + "fundCampaign": { + "title": "तलवा फंड अभियान", + "campaignName": "अभियान का नाम", + "startDate": "प्रारंभ तिथि", + "endDate": "समाप्ति तिथि", + "campaignOptions": "अभियान विकल्प", + "fundingGoal": "वित्तीय लक्ष्य", + "addCampaign": "अभियान जोड़ें", + "createdCampaign": "अभियान सफलतापूर्वक बनाया गया", + "updatedCampaign": "अभियान सफलतापूर्वक अपडेट किया गया", + "deletedCampaign": "अभियान सफलतापूर्वक हटाया गया", + "deleteCampaignMsg": "क्या आप इस अभियान को हटाना चाहते हैं?", + "noCampaigns": "कोई अभियान नहीं", + "createCampaign": "अभियान बनाएँ", + "updateCampaign": "अभियान अपडेट करें", + "manageCampaign": "अभियान प्रबंधित करें", + "deleteCampaign": "अभियान हटाएं", + "no": "नहीं", + "yes": "हाँ", + "currency": "मुद्रा", + "selectCurrency": "मुद्रा चुनें", + "filter": "फ़िल्टर", + "searchFullName": "नाम से खोजें" + }, + "pledges": { + "title": "फंडकैम्पेन प्रतिज्ञाएं", + "volunteers": "स्वयंसेवक", + "startDate": "प्रारंभ तिथि", + "endDate": "समाप्ति तिथि", + "pledgeAmount": "प्रतिज्ञा राशि", + "pledgeOptions": "विकल्प", + "pledgeCreated": "प्रतिज्ञा सफलतापूर्वक बनाई गई", + "pledgeUpdated": "प्रतिज्ञा सफलतापूर्वक अपडेट की गई", + "pledgeDeleted": "प्रतिज्ञा सफलतापूर्वक हटा दी गई", + "addPledge": "प्रतिज्ञा जोड़ें", + "createPledge": "प्रतिज्ञा बनाएं", + "currency": "मुद्रा", + "selectCurrency": "मुद्रा चुनें", + "updatePledge": "प्रतिज्ञा अपडेट करें", + "deletePledge": "प्रतिज्ञा हटाएं", + "amount": "राशि", + "editPledge": "प्रतिज्ञा संपादित करें", + "deletePledgeMsg": "क्या आप वाकई इस प्रतिज्ञा को हटाना चाहते हैं?", + "no": "नहीं", + "yes": "हाँ", + "noPledges": "कोई प्रतिज्ञा नहीं मिली" }, + "orgPost": { "title": "तलवा पोस्ट्स", "searchPost": "पोस्ट खोजें", @@ -276,10 +492,9 @@ "postDetails": "पोस्ट विवरण", "postTitle1": "पोस्ट का शीर्षक लिखें", "postTitle": "शीर्षक", + "addMedia": "फ़ोटो या वीडियो अपलोड करें", "information": "जानकारी", "information1": "पोस्ट की जानकारी लिखें", - "image": "पोस्ट छवि", - "video": "पोस्ट वीडियो", "addPost": "पोस्ट जोड़ें", "searchTitle": "शीर्षक से खोजें", "searchText": "टेक्स्ट से खोजें", @@ -292,7 +507,11 @@ "Oldest": "सबसे पुराना पहले", "Latest": "सबसे नवीनतम पहले", "sortPost": "पोस्ट को क्रमित करें", - "tag": "आपका ब्राउज़र वीडियो टैग का समर्थन नहीं करता" + "tag": "आपका ब्राउज़र वीडियो टैग का समर्थन नहीं करता", + "postCreatedSuccess": "बधाई हो! आपने कुछ पोस्ट किया है।", + "pinPost": "पोस्ट को पिन करें", + "Next": "अगला पृष्ठ", + "Previous": "पिछला पृष्ठ" }, "postNotFound": { "post": "पोस्ट", @@ -321,6 +540,8 @@ "yes": "हाँ", "editPost": "पोस्ट संपादित करें", "postTitle": "शीर्षक", + "postTitle1": "पोस्ट का शीर्षक संपादित करें", + "information1": "पोस्ट की जानकारी संपादित करें", "information": "जानकारी", "image": "छवि", "video": "वीडियो", @@ -353,6 +574,14 @@ "noResultsFoundFor": "के लिए कोई परिणाम नहीं मिला ", "noSpammerFound": "कोई स्पैमर नहीं मिला" }, + "eventManagement": { + "title": "इवेंट मैनेजमेंट", + "dashboard": "डैशबोर्ड", + "registrants": "पंजीकृत श्रेष्ठीकरण", + "eventActions": "इवेंट कार्रवाई", + "eventStats": "इवेंट स्टैटिस्टिक्स", + "to": "से" + }, "forgotPassword": { "title": "तलवा पासवर्ड भूल गए", "forgotPassword": "पासवर्ड भूल गए", @@ -375,6 +604,7 @@ "pageNotFound": { "title": "404 नहीं मिला", "talawaAdmin": "तलावा एडमिन", + "talawaUser": "तलावा उपयोगकर्ता", "404": "404", "notFoundMsg": "ओह! आपके द्वारा अनुरोधित पृष्ठ नहीं मिला!", "backToHome": "घर वापिस जा रहा हूँ" @@ -401,6 +631,8 @@ "orgSettings": { "title": "तलावा सेटिंग", "pageName": "सेटिंग्स", + "general": "सामान्य", + "actionItemCategories": "कार्रवाई आइटम श्रेणियाँ", "updateYourDetails": "अपना विवरण अपडेट करें", "updateYourPassword": "अपना पासवर्ड अपडेट करें", "updateOrganization": "अद्यतन संगठन", @@ -408,7 +640,8 @@ "settings": "समायोजन", "noData": "कोई डेटा नहीं", "otherSettings": "अन्य सेटिंग्स", - "changeLanguage": "भाषा बदलें" + "changeLanguage": "भाषा बदलें", + "manageCustomFields": "कस्टम फ़ील्ड प्रबंधन करें" }, "deleteOrg": { "deleteOrganization": "संगठन हटाएं", @@ -416,7 +649,8 @@ "deleteMsg": "क्या आप इस संगठन को हटाना चाहते हैं?", "cancel": "रद्द करना", "confirmDelete": "हटाने की पुष्टि करें", - "longDelOrgMsg": "संगठन को हमेशा के लिए हटा देने के लिए संगठन हटाने के बटन पर क्लिक करके, उसके इवेंट्स, टैग्स और सभी संबंधित डेटा सहित सभी जानकारी हटा दी जाएगी।" + "longDelOrgMsg": "संगठन को हमेशा के लिए हटा देने के लिए संगठन हटाने के बटन पर क्लिक करके, उसके इवेंट्स, टैग्स और सभी संबंधित डेटा सहित सभी जानकारी हटा दी जाएगी।", + "successfullyDeletedSampleOrganization": "नमूना संगठन सफलतापूर्वक हटा दिया गया" }, "userUpdate": { "firstName": "पहला नाम", @@ -452,8 +686,17 @@ "name": "नाम", "description": "विवरण", "location": "जगह", + "address": "पता", + "city": "शहर", + "countryCode": "देश कोड", + "line1": "लाइन 1", + "line2": "लाइन 2", + "postalCode": "पोस्टल कोड", + "dependentLocality": "आश्रित स्थान", + "sortingCode": "क्रमबद्ध कोड", + "state": "राज्य / प्रांत", "displayImage": "प्रदर्शन छवि", - "isPublic": "सार्वजनिक", + "userRegistrationRequired": "उपयोगकर्ता पंजीकरण आवश्यक", "isVisibleInSearch": "खोज में दिखाए जा सकते हैं", "saveChanges": "परिवर्तनों को सुरक्षित करें", "cancel": "रद्द करना", @@ -493,6 +736,7 @@ "memberDetail": { "title": "उपयोगकर्ता विवरण", "addAdmin": "व्यवस्थापक जोड़ें", + "alreadyIsAdmin": "सदस्य पहले से ही एक व्यवस्थापक है", "organizations": "संगठन", "events": "घटनाएं", "role": "भूमिका", @@ -501,9 +745,25 @@ "main": "मुख्य", "firstName": "पहला नाम", "lastName": "अंतिम नाम", - "memberOfOrganization": "संगठन का सदस्य", "language": "भाषा", - "adminApproved": "व्यवस्थापक द्वारा स्वीकृत", + "gender": "लिंग", + "birthDate": "जन्म तिथि", + "educationGrade": "शैक्षिक ग्रेड", + "employmentStatus": "रोजगार की स्थिति", + "maritalStatus": "वैवाहिक स्थिति", + "displayImage": "प्रदर्शन छवि", + "phone": "फोन", + "address": "पता", + "countryCode": "देश कोड", + "state": "राज्य", + "city": "शहर", + "personalInfoHeading": "व्यक्तिगत जानकारी", + "contactInfoHeading": "संपर्क जानकारी", + "actionsHeading": "कार्रवाई", + "personalDetailsHeading": "प्रोफ़ाइल विवरण", + "appLanguageCode": "भाषा चुनें", + "delete": "उपयोगकर्ता को हटाएं", + "saveChanges": "परिवर्तन सहेजें", "pluginCreationAllowed": "प्लगइन निर्माण अनुमति दी गई", "joined": "शामिल हुए", "created": "बनाया गया", @@ -553,7 +813,6 @@ "events": "आयोजन", "chat": "बातचीत", "donate": "दान देना", - "myTasks": "मेरा काम", "settings": "समायोजन", "language": "भाषा", "logout": "लॉग आउट", @@ -563,14 +822,25 @@ "allOrganizations": "सभी संगठन", "joinedOrganizations": "संगठन शामिल हुए", "createdOrganizations": "संगठन बनाये गये", - "search": "खोज", + "search": "खोज करें", "nothingToShow": "यहां दिखाने के लिए कुछ भी नहीं है.", - "selectOrganization": "संगठन का चयन करें" + "selectOrganization": "संगठन का चयन करें", + "filter": "फिल्टर", + "organizations": "संगठन", + "searchByName": "नाम से खोजें" }, - "userSidebar": { + "userSidebarOrg": { "yourOrganizations": "आपके संगठन", "noOrganizations": "आप अभी तक किसी संगठन में शामिल नहीं हुए हैं.", - "viewAll": "सभी को देखें" + "viewAll": "सभी को देखें", + "talawaUserPortal": "तलावा उपयोगकर्ता पोर्टल", + "menu": "मेन्यू", + "my organizations": "मेरे संगठन", + "users": "उपयोगकर्ता", + "requests": "अनुरोध", + "communityProfile": "सामुदायिक प्रोफ़ाइल", + "logout": "लॉग आउट", + "settings": "समायोजन" }, "organizationSidebar": { "viewAll": "सभी को देखें", @@ -586,34 +856,90 @@ "home": { "feed": "फ़ीड", "pinnedPosts": "पिन किए गए पोस्ट देखें", - "somethingOnYourMind": "आपके मन में कुछ है?" + "somethingOnYourMind": "आपके मन में कुछ है?", + "addPost": "पोस्ट जोड़ें", + "startPost": "एक पोस्ट शुरू करें", + "media": "मीडिया", + "event": "घटना", + "article": "लेख" }, "settings": { + "settings": "सेटिंग्स", "profileSettings": "पार्श्वचित्र समायोजन", "firstName": "पहला नाम", "lastName": "उपनाम", - "emailAddress": "मेल पता", - "updateImage": "छवि अद्यतन करें", - "save": "बचाना" + "gender": "लिंग", + "emailAddress": "ईमेल पता", + "phoneNumber": "फोन नंबर", + "displayImage": "प्रदर्शन छवि", + "chooseFile": "फ़ाइल चुनें", + "birthDate": "जन्म तिथि", + "grade": "शैक्षिक ग्रेड", + "empStatus": "रोजगार की स्थिति", + "maritalStatus": "वैवाहिक स्थिति", + "address": "पता", + "state": "शहर / राज्य", + "country": "देश", + "resetChanges": "परिवर्तन रीसेट करें", + "saveChanges": "परिवर्तन सहेजें", + "profileDetails": "प्रोफ़ाइल विवरण", + "deleteUserMessage": "उपयोगकर्ता हटाएं बटन पर क्लिक करने से, आपका उपयोगकर्ता, उसकी घटनाओं, टैग्स और सभी संबंधित डेटा के साथ स्थायी रूप से हटा दिया जाएगा।", + "copyLink": "प्रोफ़ाइल लिंक कॉपी करें", + "deleteUser": "उपयोगकर्ता हटाएं", + "otherSettings": "अन्य सेटिंग्स", + "changeLanguage": "भाषा बदलें", + "sgender": "लिंग चुनें", + "gradePlaceholder": "ग्रेड दर्ज करें", + "sEmpStatus": "रोजगार की स्थिति चुनें", + "male": "पुरुष", + "female": "महिला", + "other": "अन्य", + "employed": "नियोजित", + "unemployed": "बेरोजगार", + "sMaritalStatus": "वैवाहिक स्थिति चुनें", + "single": "अविवाहित", + "married": "विवाहित", + "divorced": "तलाकशुदा", + "widowed": "विधवा", + "engaged": "सगाईशुदा", + "seperated": "अलग", + "grade1": "कक्षा 1", + "grade2": "कक्षा 2", + "grade3": "कक्षा 3", + "grade4": "कक्षा 4", + "grade5": "कक्षा 5", + "grade6": "कक्षा 6", + "grade7": "कक्षा 7", + "grade8": "कक्षा 8", + "grade9": "कक्षा 9", + "grade10": "कक्षा 10", + "grade11": "कक्षा 11", + "grade12": "कक्षा 12 ", + "graduate": "स्नातक", + "kg": "केजी", + "preKg": "प्री-केजी", + "noGrade": "कोई ग्रेड नहीं", + "fullTime": "पूर्णकालिक", + "partTime": "अंशकालिक", + "enterState": "शहर या राज्य दर्ज करें", + "selectCountry": "देश चुनें", + "joined": "शामिल हुआ" }, "donate": { + "donations": "दान", + "searchDonations": "दान खोजें", + "donateForThe": "के लिए दान करें", "donateTo": "दान दें", "amount": "मात्रा", "yourPreviousDonations": "आपका पिछला दान", "donate": "दान", - "nothingToShow": "यहां दिखाने के लिए कुछ भी नहीं है." + "nothingToShow": "यहां दिखाने के लिए कुछ भी नहीं है.", + "success": "दान सफल" }, "userEvents": { "nothingToShow": "यहां दिखाने के लिए कुछ भी नहीं है.", "search": "खोज", "createEvent": "कार्यक्रम बनाएँ", - "eventTitle": "कार्यक्रम का शीर्षक", - "eventDescription": "घटना विवरण", - "eventLocation": "घटना स्थान", - "startDate": "आरंभ तिथि चुनें", - "endDate": "अंतिम तिथि चुनें", - "publicEvent": "सार्वजनिक समारोह", - "registerable": "पंजीकरण योग्य", "recurring": "पुनरावर्ती", "startTime": "समय शुरू", "endTime": "अंत समय", @@ -622,7 +948,20 @@ "listView": "लिस्ट व्यू", "calendarView": "कैलेंडर दृश्य", "allDay": "पूरे दिन", - "eventCreated": "ईवेंट सफलतापूर्वक बनाया और पोस्ट किया गया." + "eventCreated": "इवेंट सफलतापूर्वक बनाया और पोस्ट किया गया।", + "eventDetails": "घटना विवरण", + "eventTitle": "शीर्षक", + "enterTitle": "शीर्षक दर्ज करें", + "eventDescription": "विवरण", + "enterDescription": "विवरण दर्ज करें", + "eventLocation": "स्थान", + "enterLocation": "स्थान दर्ज करें", + "startDate": "प्रारंभ तिथि", + "endDate": "अंतिम तिथि", + "publicEvent": "सार्वजनिक है", + "registerable": "पंजीकृत करने योग्य है", + "monthlyCalendarView": "मासिक कैलेंडर", + "yearlyCalendarView": "वार्षिक कैलेंडर" }, "userEventCard": { "location": "जगह", @@ -632,29 +971,26 @@ "alreadyRegistered": "पहले से ही पंजीकृत", "register": "पंजीकरण करवाना" }, - "userTasks": { - "yourAssignedTasks": "आपके असाइन किए गए कार्य", - "nothingToShow": "यहां दिखाने के लिए कुछ भी नहीं है." - }, - "userTaskCard": { - "description": "विवरण", - "deadline": "अंतिम तारीख", - "created": "बनाया", - "assignees": "असाइनी", - "completed": "पुरा", - "incomplete": "अधूरा", - "taskCompleted": "काम पूरा हो गया", - "taskNotCompleted": "कार्य अभी तक पूरा नहीं हुआ है", - "event": "आयोजन", - "organization": "संगठन" - }, "advertisement": { "title": "विज्ञापन", "pHeading": "विज्ञापन प्रबंधन", "activeAds": "सक्रिय अभियान", "archievedAds": "संपन्न अभियान", "pMessage": "इस अभियान के लिए कोई विज्ञापन नहीं हैं।", - "delete": "हटाएँ" + "delete": "हटाएँ", + "validLink": "लिंक मान्य है", + "invalidLink": "लिंक अमान्य है", + "close": "बंद करें", + "deleteAdvertisement": "विज्ञापन हटाएं", + "deleteAdvertisementMsg": "क्या आप इस विज्ञापन को हटाना चाहते हैं?", + "no": "नहीं", + "yes": "हाँ", + "Rmedia": "प्रदर्शित करने के लिए मीडिया सामग्री प्रदान करें", + "view": "देखें", + "edit": "संपादित करें", + "editAdvertisement": "विज्ञापन संपादित करें", + "saveChanges": "परिवर्तन सहेजें", + "endOfResults": "परिणामों का अंत" }, "userChat": { "chat": "बात", @@ -664,5 +1000,106 @@ "userChatRoom": { "selectContact": "बातचीत शुरू करने के लिए एक संपर्क चुनें", "sendMessage": "मेसेज भेजें" + }, + "orgProfileField": { + "loading": "लोड हो रहा है...", + "noCustomField": "कोई कस्टम फ़ील्ड उपलब्ध नहीं है", + "customFieldName": "फ़ील्ड का नाम", + "enterCustomFieldName": "फ़ील्ड का नाम दर्ज करें", + "customFieldType": "फ़ील्ड का प्रकार", + "saveChanges": "परिवर्तन सहेजें", + "Remove Custom Field": "कस्टम फ़ील्ड हटाएँ", + "fieldSuccessMessage": "फ़ील्ड सफलतापूर्वक जोड़ा गया", + "fieldRemovalSuccess": "फ़ील्ड सफलतापूर्वक हटा दिया गया" + }, + "orgActionItemCategories": { + "createButton": "बनाएं", + "editButton": "संपादित करें", + "enableButton": "सक्षम करें", + "disableButton": "अक्षम करें", + "updateActionItemCategory": "अद्यतन करें", + "actionItemCategoryName": "नाम", + "actionItemCategoryDetails": "कार्रवाई आइटम श्रेणी विवरण", + "enterName": "नाम दर्ज करें", + "successfulCreation": "कार्रवाई आइटम श्रेणी सफलतापूर्वक बनाई गई", + "successfulUpdation": "क्रिया आइटम श्रेणी सफलतापूर्वक अद्यतन की गई", + "sameNameConflict": "अपडेट करने के लिए कृपया नाम बदलें", + "categoryEnabled": "कार्रवाई आइटम श्रेणी सक्षम", + "categoryDisabled": "क्रिया आइटम श्रेणी अक्षम की गई" + }, + "organizationVenues": { + "title": "स्थलों", + "addVenue": "स्थल जोड़ें", + "venueDetails": "स्थल विवरण", + "venueName": "स्थल का नाम", + "enterVenueName": "स्थल का नाम दर्ज करें", + "description": "स्थल विवरण", + "enterVenueDesc": "स्थल विवरण दर्ज करें", + "capacity": "क्षमता", + "enterVenueCapacity": "स्थल क्षमता दर्ज करें", + "image": "स्थल इमेज", + "uploadVenueImage": "स्थल इमेज अपलोड करें", + "createVenue": "स्थल बनाएं", + "venueAdded": "स्थल सफलतापूर्वक जोड़ा गया", + "editVenue": "स्थल अपडेट करें", + "venueUpdated": "स्थल विवरण सफलतापूर्वक अपडेट किए गए", + "sort": "क्रमबद्ध करें", + "highestCapacity": "सबसे उच्च क्षमता", + "lowestCapacity": "सबसे कम क्षमता", + "noVenues": "कोई स्थल नहीं मिला!", + "edit": "संपादित करें", + "view": "देखें", + "delete": "हटाएं", + "venueTitleError": "स्थल शीर्षक खाली नहीं हो सकता!", + "venueCapacityError": "क्षमता एक धनात्मक संख्या होनी चाहिए!", + "searchBy": "से खोजें", + "name": "नाम", + "desc": "विवरण" + }, + "addMember": { + "title": "सदस्य जोड़ें", + "addMembers": "सदस्य जोड़ें", + "existingUser": "मौजूदा उपयोगकर्ता", + "newUser": "नया उपयोगकर्ता", + "searchFullName": "पूरा नाम से खोजें", + "firstName": "प्रथम नाम", + "enterFirstName": "प्रथम नाम दर्ज करें", + "lastName": "अंतिम नाम", + "enterLastName": "अंतिम नाम दर्ज करें", + "emailAddress": "ईमेल पता", + "enterEmail": "ईमेल दर्ज करें", + "password": "पासवर्ड", + "enterPassword": "पासवर्ड दर्ज करें", + "confirmPassword": "पासवर्ड की पुष्टि करें", + "enterConfirmPassword": "पासवर्ड की पुष्टि करें", + "organization": "संगठन", + "cancel": "रद्द करें", + "create": "सृजन करें", + "invalidDetailsMessage": "कृपया सभी आवश्यक विवरण प्रदान करें।", + "passwordNotMatch": "पासवर्ड मेल नहीं खाते।", + "user": "उपयोगकर्ता", + "addMember": "सदस्य जोड़ें" + }, + "eventActionItems": { + "title": "कार्रवाई आइटम", + "createActionItem": "क्रिया आइटम बनाएँ", + "actionItemCategory": "एक्शन आइटम श्रेणी", + "selectActionItemCategory": "एक क्रिया आइटम श्रेणी चुनें", + "selectAssignee": "एक असाइनी का चयन करें", + "preCompletionNotes": "पूर्व समापन नोट्स", + "postCompletionNotes": "पोस्टकंप्लीशननोट्स", + "actionItemDetails": "एक्शन आइटम विवरण", + "dueDate": "नियत तिथि", + "completionDate": "समापन तिथि", + "editActionItem": "एक्शन आइटम संपादित करें", + "deleteActionItem": "क्रिया आइटम हटाएं", + "deleteActionItemMsg": "क्या आप इस क्रिया आइटम को हटाना चाहते हैं?", + "yes": "हां", + "no": "नहीं", + "successfulDeletion": "कार्रवाई आइटम सफलतापूर्वक हटा दिया गया", + "successfulCreation": "क्रिया आइटम सफलतापूर्वक बनाया गया", + "successfulUpdation": "कार्रवाई आइटम सफलतापूर्वक अद्यतन किया गया", + "notes": "नोट्स", + "save": "सहेजें" } } diff --git a/public/locales/sp.json b/public/locales/sp.json index 09d6472753..4b25f43e6c 100644 --- a/public/locales/sp.json +++ b/public/locales/sp.json @@ -4,12 +4,18 @@ "fromPalisadoes": "Una aplicación de código abierto de los voluntarios de la Fundación palisados", "talawa_portal": "Portal De Administración Talawa", "login": "Acceso", + "userLogin": "Inicio de sesión de usuario", "register": "Registro", "firstName": "Primer nombre", "lastName": "Apellido", "email": "Correo electrónico", "password": "Clave", "atleast_8_char_long": "Al menos 8 caracteres de largo", + "atleast_6_char_long": "Al menos 6 caracteres de largo", + "firstName_invalid": "El nombre debe contener solo letras minúsculas y mayúsculas.", + "lastName_invalid": "El apellido debe contener solo letras minúsculas y mayúsculas.", + "password_invalid": "La contraseña debe contener al menos una letra minúscula, una letra mayúscula, un valor numérico y un carácter especial.", + "email_invalid": "El correo electrónico debe tener al menos 8 caracteres.", "Password_and_Confirm_password_mismatches.": "Contraseña y Confirmar contraseña no coinciden.", "confirmPassword": "Confirmar contraseña", "forgotPassword": "Has olvidado tu contraseña ?", @@ -25,14 +31,24 @@ "notAuthorised": "¡Lo siento! ¡No estás autorizado!", "notFound": "¡Usuario no encontrado!", "successfullyRegistered": "Registrado con éxito. Espere hasta que sea aprobado", - "login_to_admin_portal": "Inicio de sesión en el portal de administración", - "OR": "O" + "OR": "O", + "admin": "ADMINISTRACIÓN", + "user": "USUARIO", + "lowercase_check": "Al menos una letra mayuscula", + "uppercase_check": "Al menos una letra minúscula", + "numeric_value_check": "Al menos un valor numérico", + "special_char_check": "Al menos un carácter especial" }, "latestEvents": { "eventCardTitle": "Próximos Eventos", "eventCardSeeAll": "Ver Todos", "noEvents": "No Hay Eventos Próximos" }, + "latestPosts": { + "latestPostsTitle": "Últimas Publicaciones", + "seeAllLink": "Ver Todo", + "noPostsCreated": "No se han creado publicaciones" + }, "listNavbar": { "talawa_portal": "Portal De Administración Talawa", "roles": "Roles", @@ -42,9 +58,10 @@ "leftDrawer": { "talawaAdminPortal": "Portal de administración de Talawa", "menu": "Menú", - "organizations": "Organizaciones", - "requests": "Solicitudes", + "my organizations": "Mis Organizaciones", "users": "Usuarios", + "requests": "Solicitudes", + "communityProfile": "Perfil de la comunidad", "logout": "Cerrar sesión" }, "leftDrawerOrg": { @@ -78,16 +95,27 @@ "designation": "Designacion", "email": "Correo electrónico", "searchByName": "Buscar por nombre", - "organizations": "Organizaciones", + "my organizations": "Mis Organizaciones.", "createOrganization": "Crear organización", "createSampleOrganization": "Crear organización de muestra", "description": "Descripción", "location": "Ubicación", - "isPublic": "Es público", + "address": "Dirección", + "city": "Ciudad", + "countryCode": "Código de País", + "line1": "Línea 1", + "line2": "Línea 2", + "postalCode": "Código Postal", + "dependentLocality": "Localidad Dependiente", + "sortingCode": "Código de Ordenamiento", + "state": "Estado / Provincia", + "userRegistrationRequired": "Registro de usuario requerido", "visibleInSearch": "Visible en la búsqueda", "displayImage": "Mostrar imagen", "enterName": "Ingrese su nombre", "sort": "Ordenar", + "Earliest": "Más Temprano", + "Latest": "El último", "filter": "Filtrar", "cancel": "Cancelar", "endOfResults": "Fin de los resultados", @@ -108,13 +136,29 @@ "rowsPerPage": "filas por página", "all": "Todos" }, + "requests": { + "title": "Solicitudes", + "sl_no": "Núm.", + "name": "Nombre", + "email": "Correo electrónico", + "accept": "Aceptar", + "reject": "Rechazar", + "searchRequests": "Buscar solicitudes", + "endOfResults": "Fin de los resultados", + "noOrgError": "Organizaciones no encontradas, por favor crea una organización a través del panel", + "noResultsFoundFor": "No se encontraron resultados para ", + "noRequestsFound": "No se encontraron solicitudes", + "acceptedSuccessfully": "Solicitud aceptada exitosamente", + "rejectedSuccessfully": "Solicitud rechazada exitosamente", + "noOrgErrorTitle": "Organizaciones no encontradas", + "noOrgErrorDescription": "Por favor, crea una organización a través del panel de control" + }, "users": { "title": "Roles Talawa", "searchByName": "Buscar por nombre", "users": "Usuarios", "name": "Nombre", "email": "Correo electrónico", - "roles_userType": "Rol/Tipo de usuario", "joined_organizations": "Organizaciones unidas", "blocked_organizations": "Organizaciones bloqueadas", "endOfResults": "Fin de los resultados", @@ -136,26 +180,29 @@ "filter": "Filtrar", "roleUpdated": "Rol actualizado.", "noResultsFoundFor": "No se encontraron resultados para ", - "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está funcionando? Compruebe también la conectividad de su red." + "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está funcionando? Compruebe también la conectividad de su red.", + "cancel": "Cancelar", + "admins": "Administradores", + "members": "Miembros", + "joinNow": "Únete ahora", + "visit": "visita", + "withdraw": "retirar", + "orgJoined": "Unido a la organización exitosamente", + "MembershipRequestSent": "Solicitud de membresía enviada exitosamente", + "AlreadyJoined": "Ya eres miembro de esta organización.", + "errorOccured": "Se produjo un error. Por favor, inténtalo de nuevo más tarde." }, - "requests": { - "title": "Solicitudes Talawa", - "searchByName": "Buscar por nombre", - "requests": "Peticiones", - "name": "Nombre", - "email": "Correo electrónico", - "accept": "Aceptar", - "reject": "Rechazar", - "enterName": "Ingrese su nombre", - "endOfResults": "Fin de los resultados", - "loadingRequests": "Cargando solicitudes ...", - "noRequestFound": "No se encontró ninguna solicitud.", - "sort": "Ordenar", - "filter": "Filtrar", - "userApproved": "Aprobado por el usuario", - "userRejected": "Usuario rechazado", - "noResultsFoundFor": "No se encontraron resultados para ", - "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está funcionando? Compruebe también la conectividad de su red." + "communityProfile": { + "title": "Perfil de la comunidad", + "editProfile": "Editar perfil", + "communityProfileInfo": "Estos detalles aparecerán en la pantalla de inicio de sesión/registro para usted y los miembros de su comunidad.", + "communityName": "Nombre de la comunidad", + "wesiteLink": "Enlace de página web", + "logo": "Logo", + "social": "Enlaces de redes sociales", + "url": "Introducir URL", + "profileChangedMsg": "Se actualizaron correctamente los detalles del perfil.", + "resetData": "Restablezca correctamente los detalles del perfil." }, "dashboard": { "title": "Panel de", @@ -189,7 +236,26 @@ "searchName": "Ingrese su nombre", "searchevent": "Ingresar evento", "searchFirstName": "Ingrese el nombre", - "searchLastName": "Introduzca el apellido" + "searchLastName": "Introduzca el apellido", + "people": "Personas", + "sort": "Ordenar por Rol", + "actions": "Acciones", + "existingUser": "Usuario existente", + "newUser": "Nuevo usuario", + "firstName": "Nombre de pila", + "enterFirstName": "Ponga su primer nombre", + "lastName": "Apellido", + "enterLastName": "Ingresa tu apellido", + "emailAddress": "correo electrónico", + "enterEmail": "Ingrese su dirección de correo electrónico", + "password": "Contraseña", + "enterPassword": "Ingresa tu contraseña", + "confirmPassword": "confirmar Contraseña", + "enterConfirmPassword": "Ingrese su contraseña para confirmar", + "organization": "Organización", + "create": "Crear", + "cancel": "Cancelar", + "invalidDetailsMessage": "Ingrese detalles válidos." }, "userListCard": { "joined": "Unido", @@ -218,7 +284,7 @@ "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está funcionando? Compruebe también la conectividad de su red." }, "organizationEvents": { - "title": "Eventos Talawa", + "title": "Eventos", "filterByTitle": "Filtrar por Título", "filterByLocation": "Filtrar por Ubicación", "filterByDescription": "Filtrar por descripción", @@ -242,12 +308,61 @@ "enterDescrip": "Introduce la descripción", "eventLocation": "Introducir ubicación", "eventCreated": "¡Felicidades! Se crea el Evento.", - "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está funcionando? Compruebe también la conectividad de su red." + "eventType": "Tipo de evento", + "searchEventName": "Buscar nombre del evento", + "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está funcionando? Compruebe también la conectividad de su red.", + "customRecurrence": "Recurrencia personalizada", + "repeatsEvery": "Se repite cada", + "repeatsOn": "Se repite en", + "ends": "Finaliza", + "never": "Nunca", + "on": "En", + "after": "Después de", + "occurences": "ocurrencias", + "done": "Hecho" + }, + "organizationActionItems": { + "actionItemCategory": "Categoría del ítem de acción", + "actionItemActive": "Elemento de acción activo", + "actionItemCompleted": "Elemento de acción completado", + "actionItemDetails": "Detalles del ítem de acción", + "actionItemStatus": "Estado del elemento de acción", + "assignee": "Asignado", + "assigner": "Asignador", + "assignmentDate": "Fecha de asignación", + "active": "Activo", + "clearFilters": "Borrar filtros", + "close": "Cerrar", + "completed": "Completado", + "completionDate": "Fecha de finalización", + "createActionItem": "Crear", + "deleteActionItem": "Eliminar ítem de acción", + "deleteActionItemMsg": "¿Desea eliminar este ítem de acción?", + "details": "Detalles", + "dueDate": "Fecha de vencimiento", + "earliest": "Lo más temprano", + "editActionItem": "Editar ítem de acción", + "eventActionItems": "Elementos de acción del evento", + "isCompleted": "Completado", + "latest": "Lo más reciente", + "makeActive": "Activar", + "markCompletion": "Marcar finalización", + "no": "No", + "noActionItems": "No hay ítems de acción", + "options": "Opciones", + "preCompletionNotes": "Notas previas a la finalización", + "postCompletionNotes": "Notas posteriores a la finalización", + "selectActionItemCategory": "Seleccione una categoría de ítem de acción", + "selectAssignee": "Seleccione un asignado", + "status": "Estado", + "successfulCreation": "Ítem de acción creado con éxito", + "successfulUpdation": "Ítem de acción actualizado con éxito", + "successfulDeletion": "Ítem de acción eliminado con éxito", + "title": "Ítems de acción", + "yes": "Sí" }, "eventListCard": { - "location": "Ubicación", - "on": "En", - "end": "Final", + "location": "Lugar del evento", "deleteEvent": "Eliminar evento", "deleteEventMsg": "¿Quieres eliminar este evento?", "no": "No", @@ -255,6 +370,10 @@ "editEvent": "Editar evento", "eventTitle": "Título", "description": "Descripción", + "startDate": "Fecha de inicio", + "endDate": "Fecha final", + "registerEvent": "Registro", + "alreadyRegistered": "Ya registrado", "startTime": "Hora de inicio", "endTime": "Hora de finalización", "allDay": "Todo el dia", @@ -266,8 +385,103 @@ "eventDetails": "Detalles del evento", "eventDeleted": "Evento eliminado con éxito.", "eventUpdated": "Evento actualizado con éxito.", - "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está funcionando? Compruebe también la conectividad de su red." + "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está funcionando? Compruebe también la conectividad de su red.", + "thisInstance": "Esta Instancia", + "thisAndFollowingInstances": "Esta y las Siguientes Instancias", + "allInstances": "Todas las Instancias", + "customRecurrence": "Recurrencia personalizada", + "repeatsEvery": "Se repite cada", + "repeatsOn": "Se repite en", + "ends": "Finaliza", + "never": "Nunca", + "on": "En", + "after": "Después de", + "occurences": "ocurrencias", + "done": "Hecho" + }, + "funds": { + "title": "Fondos", + "createFund": "Crear fondo", + "fundName": "Nombre del Fondo", + "fundId": "ID del Fondo", + "fundOptions": "Opciones", + "noFunds": "No se encontraron fondos", + "fundDetails": "Detalles del Fondo", + "taxDeductible": "Deducible de impuestos", + "enterfundName": "Ingrese el nombre del fondo", + "enterfundId": "Ingrese el ID del fondo", + "default": "Fondo predeterminado", + "archived": "Archivado", + "nonArchive": "No archivado", + "fundCreate": "Crear Fondo", + "fundUpdate": "Actualizar Fondo", + "fundDelete": "Eliminar Fondo", + "no": "No", + "yes": "Sí", + "manageFund": "Administrar fondo", + "searchFullName": "Buscar por nombre", + "filter": "Filtrar", + "noFundsFound": "No se encontraron fondos", + "createdBy": "Creado por", + "createdOn": "Creado el", + "status": "Estado", + "archiveFund": "Archivar Fondo", + "archiveFundMsg": "¿Desea archivar este fondo?", + "fundCreated": "Fondo creado exitosamente", + "fundUpdated": "Fondo actualizado exitosamente", + "fundDeleted": "Fondo eliminado exitosamente", + "fundArchived": "Fondo archivado exitosamente", + "fundUnarchived": "Fondo no archivado exitosamente", + "deleteFundMsg": "¿Desea eliminar este fondo?" }, + "fundCampaign": { + "title": "Campañas de recaudación de fondos", + "campaignName": "Nombre de la campaña", + "startDate": "Fecha de inicio", + "endDate": "Fecha de finalización", + "campaignOptions": "Opciones de la campaña", + "fundingGoal": "Meta de financiamiento", + "addCampaign": "Agregar campaña", + "createdCampaign": "Campaña creada exitosamente", + "updatedCampaign": "Campaña actualizada exitosamente", + "deletedCampaign": "Campaña eliminada exitosamente", + "deleteCampaignMsg": "¿Desea eliminar esta campaña?", + "noCampaigns": "No se encontraron campañas", + "createCampaign": "Crear campaña de recaudación de fondos", + "updateCampaign": "Actualizar campaña de recaudación de fondos", + "manageCampaign": "Administrar campaña de recaudación de fondos", + "deleteCampaign": "Eliminar campaña de recaudación de fondos", + "no": "No", + "yes": "Sí", + "currency": "Moneda", + "selectCurrency": "Seleccionar moneda", + "filter": "Filtrar", + "searchFullName": "Buscar por nombre" + }, + "pledges": { + "title": "Compromisos de Campaña de Financiamiento", + "volunteers": "Voluntarios", + "startDate": "Fecha de Inicio", + "endDate": "Fecha de Finalización", + "pledgeAmount": "Monto del Compromiso", + "pledgeOptions": "Opciones", + "pledgeCreated": "Compromiso creado exitosamente", + "pledgeUpdated": "Compromiso actualizado exitosamente", + "pledgeDeleted": "Compromiso eliminado exitosamente", + "addPledge": "Agregar Compromiso", + "createPledge": "Crear Compromiso", + "currency": "Moneda", + "selectCurrency": "Seleccionar Moneda", + "updatePledge": "Actualizar Compromiso", + "deletePledge": "Eliminar Compromiso", + "amount": "Monto", + "editPledge": "Editar Compromiso", + "deletePledgeMsg": "¿Estás seguro de que quieres eliminar este compromiso?", + "no": "No", + "yes": "Sí", + "noPledges": "No se encontraron compromisos" + }, + "orgPost": { "title": "Publicaciones de Talawa", "searchPost": "Buscar Publicación", @@ -276,10 +490,9 @@ "postDetails": "Detalles de la Publicación", "postTitle1": "Escribir título de la publicación", "postTitle": "Título", + "addMedia": "Subir foto o video", "information": "Información", "information1": "Escribir información de la publicación", - "image": "Imagen de la Publicación", - "video": "Video de la Publicación", "addPost": "Agregar Publicación", "searchTitle": "Buscar por Título", "searchText": "Buscar por Texto", @@ -292,7 +505,11 @@ "Oldest": "Más Antiguas Primero", "Latest": "Más Recientes Primero", "sortPost": "Ordenar Publicaciones", - "tag": "Su navegador no admite la etiqueta de video" + "tag": "Su navegador no admite la etiqueta de video", + "postCreatedSuccess": "¡Felicidades! Has publicado algo.", + "pinPost": "Fijar publicación", + "Next": "Siguiente página", + "Previous": "Página anterior" }, "postNotFound": { "post": "Publicaciones", @@ -310,7 +527,6 @@ "admin not found!": "Administrador no encontrado!", "roles not found!": "roles no encontrados!" }, - "orgPostCard": { "author": "Autor", "imageURL": "URL de la Imagen", @@ -322,6 +538,8 @@ "yes": "Sí", "editPost": "Editar Publicación", "postTitle": "Título", + "postTitle1": "Editar título de la publicación", + "information1": "Editar información de la publicación", "information": "Información", "image": "Imagen", "video": "Video", @@ -353,6 +571,14 @@ "noResultsFoundFor": "No se encontraron resultados para ", "noSpammerFound": "No se encontró ningún spammer" }, + "eventManagement": { + "title": "Gestión de eventos", + "dashboard": "Tablero", + "registrants": "Inscritos", + "eventActions": "Acciones del evento", + "eventStats": "Estadísticas del evento", + "to": "A" + }, "forgotPassword": { "title": "Talawa olvidó su contraseña", "forgotPassword": "Has olvidado tu contraseña", @@ -375,6 +601,7 @@ "pageNotFound": { "title": "404 No encontrado", "talawaAdmin": "Administrador de Talawa", + "talawaUser": "Usuario de Talawa", "404": "404", "notFoundMsg": "¡Ups! ¡No se encontró la página que solicitaste!", "backToHome": "De vuelta a casa" @@ -401,6 +628,8 @@ "orgSettings": { "title": "Configuración Talawa", "pageName": "Configuración", + "general": "General", + "actionItemCategories": "Categorías de elementos de acción", "updateYourDetails": "Actualiza tus datos", "updateYourPassword": "Actualice su contraseña", "updateOrganization": "Actualizar Organización", @@ -408,7 +637,8 @@ "settings": "Ajustes", "noData": "Sin datos", "otherSettings": "Otras Configuraciones", - "changeLanguage": "Cambiar Idioma" + "changeLanguage": "Cambiar Idioma", + "manageCustomFields": "Gestionar Campos Personalizados" }, "deleteOrg": { "deleteOrganization": "Eliminar organización", @@ -416,7 +646,8 @@ "deleteMsg": "¿Desea eliminar esta organización?", "cancel": "Cancelar", "confirmDelete": "Confirmar eliminación", - "longDelOrgMsg": "Al hacer clic en el botón Eliminar organización, la organización se eliminará permanentemente junto con sus eventos, etiquetas y todos los datos relacionados." + "longDelOrgMsg": "Al hacer clic en el botón Eliminar organización, la organización se eliminará permanentemente junto con sus eventos, etiquetas y todos los datos relacionados.", + "successfullyDeletedSampleOrganization": "Organización de muestra eliminada correctamente" }, "userUpdate": { "firstName": "Primer nombre", @@ -452,8 +683,17 @@ "name": "Nombre", "description": "Descripción", "location": "ubicación", + "address": "Dirección", + "city": "Ciudad", + "countryCode": "Código de País", + "line1": "Línea 1", + "line2": "Línea 2", + "postalCode": "Código Postal", + "dependentLocality": "Localidad Dependiente", + "sortingCode": "Código de Ordenamiento", + "state": "Estado / Provincia", "displayImage": "Mostrar imagen", - "isPublic": "Público", + "userRegistrationRequired": "Registro de usuario requerido", "isVisibleInSearch": "Visible en la búsqueda", "saveChanges": "Guardar cambios", "cancel": "Cancelar", @@ -493,6 +733,7 @@ "memberDetail": { "title": "Detalles del usuario", "addAdmin": "Agregar administrador", + "alreadyIsAdmin": "El Miembro ya es Administrador", "organizations": "Organizaciones", "events": "Eventos", "role": "Rol", @@ -501,9 +742,25 @@ "main": "Principal", "firstName": "Nombre", "lastName": "Apellido", - "memberOfOrganization": "Miembro de la organización", "language": "Idioma", - "adminApproved": "Aprobado por el administrador", + "gender": "Género", + "birthDate": "Fecha de Nacimiento", + "educationGrade": "Nivel Educativo", + "employmentStatus": "Estado Laboral", + "maritalStatus": "Estado Civil", + "displayImage": "Imagen de Perfil", + "phone": "Teléfono", + "address": "Dirección", + "countryCode": "Código de País", + "state": "Estado", + "city": "Ciudad", + "personalInfoHeading": "Información Personal", + "contactInfoHeading": "Información de Contacto", + "actionsHeading": "Acciones", + "personalDetailsHeading": "Detalles del perfil", + "appLanguageCode": "Elegir Idioma", + "delete": "Eliminar Usuario", + "saveChanges": "Guardar Cambios", "pluginCreationAllowed": "Permitir creación de complementos", "joined": "Unido", "created": "Creado", @@ -553,7 +810,6 @@ "events": "Eventos", "chat": "Charlar", "donate": "Donar", - "myTasks": "Mis tareas", "settings": "Ajustes", "language": "Idioma", "logout": "Cerrar sesión", @@ -563,14 +819,25 @@ "allOrganizations": "Todas las organizaciones", "joinedOrganizations": "Organizaciones unidas", "createdOrganizations": "Organizaciones creadas", - "search": "Buscar", + "search": "Buscar usuarios", "nothingToShow": "Nada que mostrar aquí.", - "selectOrganization": "Seleccionar organización" + "selectOrganization": "Seleccionar organización", + "filter": "Filtrar", + "organizations": "Organizaciones", + "searchByName": "Buscar por nombre" }, - "userSidebar": { + "userSidebarOrg": { "yourOrganizations": "Tus Organizaciones", "noOrganizations": "Aún no te has unido a ninguna organización.", - "viewAll": "Ver todo" + "viewAll": "Ver todo", + "talawaUserPortal": "Talawa portal de usuario", + "menu": "Menú", + "my organizations": "Mis Organizaciones.", + "users": "Usuarios", + "requests": "Solicitudes", + "communityProfile": "Perfil de la comunidad", + "logout": "Cerrar sesión", + "settings": "Ajustes" }, "organizationSidebar": { "viewAll": "Ver todo", @@ -586,34 +853,90 @@ "home": { "feed": "Alimentar", "pinnedPosts": "Ver publicaciones fijadas", - "somethingOnYourMind": "¿Algo en tu mente?" + "somethingOnYourMind": "¿Algo en tu mente?", + "addPost": "Agregar publicación", + "startPost": "Comenzar una publicación", + "media": "Medios", + "event": "Evento", + "article": "Artículo" }, "settings": { + "settings": "Ajustes", "profileSettings": "Configuración de perfil", "firstName": "Nombre de pila", "lastName": "Apellido", - "emailAddress": "dirección de correo electrónico", - "updateImage": "Actualizar imagen", - "save": "Ahorrar" + "gender": "Género", + "emailAddress": "Dirección de correo electrónico", + "phoneNumber": "Número de teléfono", + "displayImage": "Imagen de perfil", + "chooseFile": "Elegir archivo", + "birthDate": "Fecha de nacimiento", + "grade": "Nivel educativo", + "empStatus": "Situación laboral", + "maritalStatus": "Estado civil", + "address": "Dirección", + "state": "Ciudad/Estado", + "country": "País", + "resetChanges": "Restablecer cambios", + "saveChanges": "Guardar cambios", + "profileDetails": "Detalles del perfil", + "deleteUserMessage": "Al hacer clic en el botón Eliminar usuario, su usuario se eliminará permanentemente junto con sus eventos, etiquetas y todos los datos relacionados.", + "copyLink": "Copiar enlace del perfil", + "deleteUser": "Eliminar usuario", + "otherSettings": "Otras configuraciones", + "changeLanguage": "Cambiar idioma", + "sgender": "Seleccionar género", + "gradePlaceholder": "Ingresar grado", + "sEmpStatus": "Seleccionar estado de empleo", + "male": "Masculino", + "female": "Femenino", + "other": "Otro", + "employed": "Empleado", + "unemployed": "Desempleado", + "sMaritalStatus": "Seleccionar estado civil", + "single": "Soltero", + "married": "Casado", + "divorced": "Divorciado", + "widowed": "Viudo", + "engaged": "Comprometido", + "seperated": "Separado", + "grade1": "1er Grado", + "grade2": "2do Grado", + "grade3": "3er Grado", + "grade4": "4to Grado", + "grade5": "5to Grado", + "grade6": "6to Grado", + "grade7": "7mo Grado", + "grade8": "8vo Grado", + "grade9": "9no Grado", + "grade10": "10mo Grado", + "grade11": "11vo Grado", + "grade12": "12vo Grado", + "graduate": "Graduado", + "kg": "KG", + "preKg": "Pre-KG", + "noGrade": "Sin Grado", + "fullTime": "Tiempo Completo", + "partTime": "Medio Tiempo", + "enterState": "Ingresar ciudad o estado", + "selectCountry": "Seleccionar un país", + "joined": "Unido" }, "donate": { + "donations": "Donaciones", + "searchDonations": "Buscar donaciones", + "donateForThe": "Donar para el", "donateTo": "Donar a", "amount": "Cantidad", "yourPreviousDonations": "Tus donaciones anteriores", "donate": "Donar", - "nothingToShow": "Nada que mostrar aquí." + "nothingToShow": "Nada que mostrar aquí.", + "success": "Donación exitosa" }, "userEvents": { "nothingToShow": "No hay nada que mostrar aquí.", "search": "Buscar", "createEvent": "Crear evento", - "eventTitle": "Título del evento", - "eventDescription": "Descripción del evento", - "eventLocation": "Lugar del evento", - "startDate": "Seleccione la fecha de inicio", - "endDate": "Seleccionar fecha de finalización", - "publicEvent": "Evento público", - "registerable": "Registrable", "recurring": "Periódica", "startTime": "Hora de inicio", "endTime": "Hora de finalización", @@ -622,7 +945,20 @@ "listView": "Vista de la lista", "calendarView": "Vista de calendario", "allDay": "Todo el dia", - "eventCreated": "Evento creado y publicado exitosamente." + "eventCreated": "Evento creado y publicado exitosamente.", + "eventDetails": "Detalles del evento", + "eventTitle": "Título", + "enterTitle": "Ingrese el título", + "eventDescription": "Descripción", + "enterDescription": "Ingresar descripción", + "eventLocation": "Ubicación", + "enterLocation": "Ingresar Ubicación", + "startDate": "Fecha de inicio", + "endDate": "Fecha de finalización", + "publicEvent": "Es público", + "registerable": "Es registrable", + "monthlyCalendarView": "Calendario mensual", + "yearlyCalendarView": "Calendario anual" }, "userEventCard": { "location": "Ubicación", @@ -632,29 +968,26 @@ "alreadyRegistered": "Ya registrado", "register": "Registro" }, - "userTasks": { - "yourAssignedTasks": "Tus tareas asignadas", - "nothingToShow": "No hay nada que mostrar aquí." - }, - "userTaskCard": { - "description": "Descripción", - "deadline": "Fecha límite", - "created": "Creado", - "assignees": "Cesionarias", - "completed": "Terminada", - "incomplete": "Incompleta", - "taskCompleted": "La tarea ha sido completada", - "taskNotCompleted": "La tarea aún no se ha completado", - "event": "Evento", - "organization": "Organización" - }, "advertisement": { "title": "Anuncios", "pHeading": "Gestionar anuncios", "activeAds": "Campañas activas", "archievedAds": "Campañas completadas", "pMessage": "No hay anuncios disponibles para esta campaña.", - "delete": "Eliminar" + "delete": "Eliminar", + "validLink": "El enlace es válido.", + "invalidLink": "El enlace no es válido.", + "close": "Cerrar", + "deleteAdvertisement": "Eliminar anuncio", + "deleteAdvertisementMsg": "¿Desea eliminar este anuncio?", + "no": "No", + "yes": "Sí", + "Rmedia": "Proporcionar contenido multimedia para mostrar", + "view": "Ver", + "edit": "Editar", + "editAdvertisement": "Editar Anuncio", + "saveChanges": "Guardar Cambios", + "endOfResults": "Fin de los resultados" }, "userChat": { "chat": "Charlar", @@ -664,5 +997,106 @@ "userChatRoom": { "selectContact": "Seleccione un contacto para iniciar una conversación", "sendMessage": "Enviar mensaje" + }, + "orgProfileField": { + "loading": "Cargando..", + "noCustomField": "No hay campos personalizados disponibles", + "customFieldName": "Nombre del Campo", + "enterCustomFieldName": "Ingrese el Nombre del Campo", + "customFieldType": "Tipo de Campo", + "saveChanges": "Guardar Cambios", + "Remove Custom Field": "Eliminar Campo Personalizado", + "fieldSuccessMessage": "Campo añadido exitosamente", + "fieldRemovalSuccess": "Campo eliminado exitosamente" + }, + "orgActionItemCategories": { + "createButton": "Crear", + "editButton": "Editar", + "enableButton": "Habilitar", + "disableButton": "Inhabilitar", + "updateActionItemCategory": "Actualizar", + "actionItemCategoryName": "Nombre", + "actionItemCategoryDetails": "Detalles de la categoría de elemento de acción", + "enterName": "Introduzca el nombre", + "successfulCreation": "Categoría de elemento de acción creada correctamente", + "successfulUpdation": "Categoría de elemento de acción actualizada correctamente", + "sameNameConflict": "Cambie el nombre para realizar una actualización", + "categoryEnabled": "Categoría de elemento de acción habilitada", + "categoryDisabled": "Categoría de elemento de acción deshabilitada" + }, + "organizationVenues": { + "title": "Lugares", + "addVenue": "Agregar lugar", + "venueDetails": "Detalles del lugar", + "venueName": "Nombre del lugar", + "enterVenueName": "Ingrese el nombre del lugar", + "description": "Descripción del lugar", + "enterVenueDesc": "Ingrese la descripción del lugar", + "capacity": "Capacidad", + "enterVenueCapacity": "Ingrese la capacidad del lugar", + "image": "Imagen del lugar", + "uploadVenueImage": "Subir imagen del lugar", + "createVenue": "Crear lugar", + "venueAdded": "Lugar agregado correctamente", + "editVenue": "Actualizar lugar", + "venueUpdated": "Detalles del lugar actualizados correctamente", + "sort": "Ordenar", + "highestCapacity": "Mayor capacidad", + "lowestCapacity": "Menor capacidad", + "noVenues": "¡No se encontraron lugares!", + "edit": "Editar", + "view": "Ver", + "delete": "Eliminar", + "venueTitleError": "¡El título del lugar no puede estar vacío!", + "venueCapacityError": "¡La capacidad debe ser un número positivo!", + "searchBy": "Buscar por", + "name": "Nombre", + "desc": "Descripción" + }, + "addMember": { + "title": "Agregar miembro", + "addMembers": "Agregar miembros", + "existingUser": "Usuario existente", + "newUser": "Usuario nuevo", + "searchFullName": "Buscar por nombre completo", + "firstName": "Nombre", + "enterFirstName": "Ingrese el nombre", + "lastName": "Apellido", + "enterLastName": "Ingrese el apellido", + "emailAddress": "Dirección de correo electrónico", + "enterEmail": "Ingrese el correo electrónico", + "password": "Contraseña", + "enterPassword": "Ingrese la contraseña", + "confirmPassword": "Confirmar contraseña", + "enterConfirmPassword": "Ingrese la contraseña de confirmación", + "organization": "Organización", + "cancel": "Cancelar", + "create": "Crear", + "invalidDetailsMessage": "Por favor proporcione todos los detalles requeridos.", + "passwordNotMatch": "Las contraseñas no coinciden.", + "user": "Usuario", + "addMember": "Agregar miembro" + }, + "eventActionItems": { + "title": "Elementos de acción", + "createActionItem": "Crear elementos de acción", + "actionItemCategory": "Categoría de elemento de acción", + "selectActionItemCategory": "Seleccione una categoría de elemento de acción", + "selectAssignee": "Seleccione un asignado", + "preCompletionNotes": "Notas previas a la finalización", + "postCompletionNotes": "Publicar notas de finalización", + "actionItemDetails": "Detalles del elemento de acción", + "dueDate": "Fecha de vencimiento", + "completionDate": "Fecha de finalización", + "editActionItem": "Editar elemento de acción", + "deleteActionItem": "Eliminar elemento de acción", + "deleteActionItemMsg": "¿Quieres eliminar este elemento de acción?", + "yes": "Sí", + "no": "no", + "successfulDeletion": "Elemento de acción eliminado exitosamente", + "successfulCreation": "Elemento de acción creado exitosamente", + "successfulUpdation": "Elemento de acción actualizado correctamente", + "notes": "Notas", + "save": "Guardar" } } diff --git a/public/locales/zh.json b/public/locales/zh.json index 138a345206..0d5f717b00 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -4,12 +4,18 @@ "fromPalisadoes": "柵欄 基金会志愿者的开源应用程序", "talawa_portal": "塔拉瓦管理門戶", "login": "登錄", + "userLogin": "用户登录", "register": "登記", "firstName": "名", "lastName": "姓", "email": "電子郵件", "password": "密碼", "atleast_8_char_long": "至少 8 個字符長", + "atleast_6_char_long": "至少 6 個字元長", + "firstName_invalid": "名字只能包含小寫和大寫字母", + "lastName_invalid": "姓氏只能包含小寫和大寫字母", + "password_invalid": "密碼應至少包含1個小寫字母、1個大寫字母、1個數字和1個特殊字符", + "email_invalid": "電子郵件應至少包含 8 個字符", "Password_and_Confirm_password_mismatches.": "密碼和確認密碼不匹配。", "confirmPassword": "確認密碼", "forgotPassword": "忘記密碼 ?", @@ -25,14 +31,24 @@ "notAuthorised": "抱歉!你沒有被授權!", "notFound": "找不到用戶!", "successfullyRegistered": "註冊成功,請等待審核通過。", - "login_to_admin_portal": " 管理员门户登录 ", - "OR": "或者" + "OR": "或者", + "admin": "行政", + "user": "用戶", + "lowercase_check": "至少一個小寫字母", + "uppercase_check": "至少有一個大寫字母", + "numeric_value_check": "至少一個數值", + "special_char_check": "至少一個特殊字符" }, "latestEvents": { "eventCardTitle": "即将举行的活动", "eventCardSeeAll": "查看全部", "noEvents": "暂无即将举行的活动" }, + "latestPosts": { + "latestPostsTitle": "最新文章", + "seeAllLink": "查看全部", + "noPostsCreated": "暂无文章" + }, "listNavbar": { "talawa_portal": "塔拉瓦管理門戶", "roles": "角色", @@ -42,9 +58,10 @@ "leftDrawer": { "talawaAdminPortal": "塔拉瓦管理门户", "menu": "菜单", - "organizations": "组织", - "requests": "请求", + "my organizations": "我的组织", "users": "用户", + "requests": "请求", + "communityProfile": "社区简介", "logout": "退出登录" }, "leftDrawerOrg": { @@ -71,6 +88,88 @@ "noNotifications": "沒有通知", "close": "關" }, + "funds": { + "title": "资金", + "createFund": "创建基金", + "fundName": "基金名称", + "fundId": "基金ID", + "fundOptions": "选项", + "noFunds": "未找到基金", + "fundDetails": "基金详情", + "taxDeductible": "允许税收扣除", + "enterfundName": " 输入基金名称", + "enterfundId": "输入基金ID", + "default": "默认基金", + "archived": "已归档", + "nonArchive": "未归档", + "fundCreate": "创建基金", + "fundUpdate": "更新基金", + "fundDelete": "删除基金", + "no": "否", + "yes": "是", + "manageFund": "管理基金", + "searchFullName": "按姓名搜索", + "filter": "筛选", + "noFundsFound": "找不到资金", + "createdBy": "创建人", + "createdOn": "创建日期", + "status": "状态", + "archiveFund": "归档基金", + "archiveFundMsg": "您是否要归档此基金?", + "fundCreated": "基金创建成功", + "fundUpdated": "基金更新成功", + "fundDeleted": "基金删除成功", + "fundArchived": "基金已归档", + "fundUnarchived": "基金未归档", + "deleteFundMsg": "您是否要删除此基金?" + }, + "fundCampaign": { + "title": "筹款活动", + "campaignName": "活动名称", + "startDate": "开始日期", + "endDate": "结束日期", + "campaignOptions": "活动选项", + "fundingGoal": "筹款目标", + "addCampaign": "添加活动", + "createdCampaign": "活动创建成功", + "updatedCampaign": "活动更新成功", + "deletedCampaign": "活动删除成功", + "deleteCampaignMsg": "您确定要删除此活动吗", + "noCampaigns": "未找到活动", + "createCampaign": "创建筹款活动", + "updateCampaign": "更新筹款活动", + "manageCampaign": "管理筹款活动", + "deleteCampaign": "删除筹款活动", + "no": "没有", + "yes": "是", + "currency": "货币", + "selectCurrency": "选择货币", + "filter": "筛选", + "searchFullName": "按姓名搜索" + }, + "pledges": { + "title": "资金筹款承诺", + "volunteers": "志愿者", + "startDate": "开始日期", + "endDate": "结束日期", + "pledgeAmount": "承诺金额", + "pledgeOptions": "选项", + "pledgeCreated": "承诺成功创建", + "pledgeUpdated": "承诺成功更新", + "pledgeDeleted": "承诺成功删除", + "addPledge": "添加承诺", + "createPledge": "创建承诺", + "currency": "货币", + "selectCurrency": "选择货币", + "updatePledge": "更新承诺", + "deletePledge": "删除承诺", + "amount": "数量", + "editPledge": "编辑承诺", + "deletePledgeMsg": "您确定要删除此承诺吗?", + "no": "否", + "yes": "是", + "noPledges": "未找到承诺" + }, "orgList": { "title": "塔拉瓦組織", "you": "你", @@ -78,16 +177,27 @@ "designation": "指定", "email": "電子郵件", "searchByName": "按名稱搜索", - "organizations": "组织", + "my organizations": "我的组织", "createOrganization": "創建組織", "createSampleOrganization": "创建示范组织", "description": "描述", "location": "地點", - "isPublic": "是否公開", + "address": "地址", + "city": "城市", + "countryCode": "国家代码", + "line1": "地址行 1", + "line2": "地址行 2", + "postalCode": "邮政编码", + "dependentLocality": "从属地区", + "sortingCode": "排序代码", + "state": "省 / 直辖市", + "isPubluserRegistrationRequiredic": "需要用户注册", "visibleInSearch": "在搜索中可見", "displayImage": "顯示圖像", "enterName": "输入名字", "sort": "排序", + "Earliest": "最早的", + "Latest": "最新的", "filter": "過濾", "cancel": "取消", "endOfResults": "結果結束", @@ -108,13 +218,29 @@ "rowsPerPage": "每頁行數", "all": "全部" }, + "requests": { + "title": "请求", + "sl_no": "序号", + "name": "姓名", + "email": "电子邮件", + "accept": "接受", + "reject": "拒绝", + "searchRequests": "搜索请求", + "endOfResults": "结果结束", + "noOrgError": "找不到组织,请通过仪表板创建组织", + "noResultsFoundFor": "未找到结果 ", + "noRequestsFound": "未找到请求", + "acceptedSuccessfully": "请求成功接受", + "rejectedSuccessfully": "请求成功拒绝", + "noOrgErrorTitle": "找不到组织", + "noOrgErrorDescription": "请通过仪表板创建一个组织" + }, "users": { "title": "塔拉瓦角色", "searchByName": "按名稱搜索", "users": "用户", "name": "姓名", "email": "電子郵件", - "roles_userType": "角色/用戶類型", "joined_organizations": "加入的組織", "blocked_organizations": "阻止的組織", "endOfResults": "結果結束", @@ -136,26 +262,29 @@ "filter": "過濾", "roleUpdated": "角色已更新。", "noResultsFoundFor": "未找到结果 ", - "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。" + "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。", + "cancel": "取消", + "admins": "管理員", + "members": "成員", + "joinNow": "现在加入", + "visit": "加入访问", + "withdraw": "提取", + "orgJoined": "成功加入组织", + "MembershipRequestSent": "会员申请已成功发送", + "AlreadyJoined": "您已经是该组织的成员。", + "errorOccured": "发生错误,请稍后重试。" }, - "requests": { - "title": "塔拉瓦請求", - "searchByName": "按名稱搜索", - "requests": "要求", - "name": "姓名", - "email": "電子郵件", - "accept": "接受", - "reject": "拒絕", - "enterName": "输入名字", - "endOfResults": "結果結束", - "loadingRequests": "正在加載請求...", - "noRequestFound": "找不到請求。", - "sort": "排序", - "filter": "過濾", - "userApproved": "用戶批准", - "userRejected": "用戶被拒絕", - "noResultsFoundFor": "未找到结果 ", - "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。" + "communityProfile": { + "title": "社区简介", + "editProfile": "编辑个人资料", + "communityProfileInfo": "这些详细信息将显示在您和您的社区成员的登录/注册屏幕上", + "communityName": "社区名字", + "wesiteLink": "网站链接", + "logo": "标识", + "social": "社交媒体链接", + "url": "输入网址", + "profileChangedMsg": "已成功更新个人资料详细信息。", + "resetData": "成功重置个人资料详细信息。" }, "dashboard": { "title": "儀表板", @@ -189,7 +318,26 @@ "searchName": "輸入名字", "searchevent": "輸入事件", "searchFirstName": "输入名字", - "searchLastName": "输入姓氏" + "searchLastName": "输入姓氏", + "people": "人", + "sort": "按角色搜索", + "actions": "操作", + "existingUser": "现有用户", + "newUser": "新用户", + "firstName": "名", + "enterFirstName": "輸入您的名字", + "lastName": "姓", + "enterLastName": "輸入您的姓氏", + "emailAddress": "電子郵件地址", + "enterEmail": "輸入你的電子郵箱地址", + "password": "密碼", + "enterPassword": "輸入您的密碼", + "confirmPassword": "確認密碼", + "enterConfirmPassword": "輸入您的密碼以確認", + "organization": "組織", + "create": "創造", + "cancel": "取消", + "invalidDetailsMessage": "請輸入有效的詳細信息。" }, "userListCard": { "joined": "加入", @@ -218,7 +366,7 @@ "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。" }, "organizationEvents": { - "title": "塔拉瓦事件", + "title": "活动", "filterByTitle": "按標題過濾", "filterByLocation": "按位置過濾", "filterByDescription": "按描述過濾", @@ -242,12 +390,62 @@ "enterDescrip": "輸入說明", "eventLocation": "輸入位置", "eventCreated": "恭喜!事件已創建。", - "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。" + "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。", + "searchEventName": "搜索活动名称", + "eventType": "活动类型", + "customRecurrence": "自定义重复", + "repeatsEvery": "重复每", + "repeatsOn": "重复于", + "ends": "结束", + "never": "永不", + "on": "于", + "after": "之后", + "occurences": "次数", + "done": "完成" + }, + "organizationActionItems": { + "actionItemCategory": "行动项目类别", + "actionItemActive": "活动措施项", + "actionItemCompleted": "已完成操作项", + "actionItemDetails": "行动项目详情", + "actionItemStatus": "措施项状态", + "assignee": "受让人", + "assigner": "分配者", + "assignmentDate": "分配日期", + "active": "活跃", + "clearFilters": "清除筛选器", + "close": "关闭", + "completed": "已完成", + "completionDate": "完成日期", + "createActionItem": "创建", + "deleteActionItem": "删除行动项目", + "deleteActionItemMsg": "您是否要删除此行动项目?", + "details": "详情", + "dueDate": "到期日", + "earliest": "最早", + "editActionItem": "编辑行动项目", + "eventActionItems": "事件操作项", + "isCompleted": "已完成", + "latest": "最新", + "makeActive": "激活", + "markCompletion": "标记完成", + "no": "否", + "noActionItems": "无行动项目", + "options": "选项", + "preCompletionNotes": "完成前的笔记", + "postCompletionNotes": "完成后的笔记", + "searchByName": "按名称搜索", + "selectActionItemCategory": "选择行动项目类别", + "selectAssignee": "选择受让人", + "status": "状态", + "successfulCreation": "行动项目创建成功", + "successfulUpdation": "行动项目更新成功", + "successfulDeletion": "行动项目删除成功", + "title": "行动项目", + "yes": "是" }, "eventListCard": { - "location": "地點", - "on": "上", - "end": "結尾", + "location": "活動地點", "deleteEvent": "刪除事件", "deleteEventMsg": "您要刪除此活動嗎?", "no": "不", @@ -255,6 +453,10 @@ "editEvent": "編輯事件", "eventTitle": "標題", "description": "描述", + "startDate": "开始日期", + "endDate": "结束日期", + "registerEvent": "登記", + "alreadyRegistered": "已經註冊", "startTime": "開始時間", "endTime": "時間結束", "allDay": "一整天", @@ -266,7 +468,19 @@ "eventDetails": "活動詳情", "eventDeleted": "活动删除成功。", "eventUpdated": "活動更新成功。", - "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。" + "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。", + "thisInstance": "此实例", + "thisAndFollowingInstances": "此及其后续实例", + "allInstances": "所有实例", + "customRecurrence": "自定义重复", + "repeatsEvery": "重复每", + "repeatsOn": "重复于", + "ends": "结束", + "never": "永不", + "on": "于", + "after": "之后", + "occurences": "次数", + "done": "完成" }, "orgPost": { "title": "塔拉瓦帖子", @@ -276,10 +490,9 @@ "postDetails": "帖子详情", "postTitle1": "填写帖子标题", "postTitle": "标题", + "addMedia": "上传照片或视频", "information": "信息", "information1": "填写帖子信息", - "image": "帖子图片", - "video": "帖子视频", "addPost": "添加帖子", "searchTitle": "按标题搜索", "searchText": "按文本搜索", @@ -292,7 +505,11 @@ "Oldest": "最旧的优先", "Latest": "最新的优先", "sortPost": "排序帖子", - "tag": "您的浏览器不支持视频标签" + "tag": "您的浏览器不支持视频标签", + "postCreatedSuccess": "恭喜!您已经发布了一些内容。", + "pinPost": "针柱", + "Next": "下一页", + "Previous": "上一页" }, "postNotFound": { "post": "郵政", @@ -321,6 +538,8 @@ "yes": "是", "editPost": "编辑帖子", "postTitle": "标题", + "postTitle1": "編輯貼文標題", + "information1": "編輯貼文訊息", "information": "信息", "image": "图片", "video": "视频", @@ -353,6 +572,14 @@ "noResultsFoundFor": "未找到结果 ", "noSpammerFound": "未发现垃圾邮件发送者" }, + "eventManagement": { + "title": "事件管理", + "dashboard": "仪表板", + "registrants": "注册参与者", + "eventActions": "事件操作", + "eventStats": "事件统计", + "to": "到" + }, "forgotPassword": { "title": "塔拉瓦忘記密碼", "forgotPassword": "忘記密碼", @@ -375,6 +602,7 @@ "pageNotFound": { "title": "404 未找到", "talawaAdmin": "塔拉瓦管理員", + "talawaUser": "塔拉瓦用戶", "404": "404", "notFoundMsg": "糟糕!找不到您請求的頁面!", "backToHome": "回到家" @@ -401,6 +629,8 @@ "orgSettings": { "title": "塔拉瓦設置", "pageName": "设置", + "general": "一般", + "actionItemCategories": "措施项类别", "updateYourDetails": "更新您的詳細信息", "updateYourPassword": "更新您的密碼", "updateOrganization": "更新組織", @@ -408,7 +638,8 @@ "settings": "設置", "noData": "沒有數據", "otherSettings": "其他设置", - "changeLanguage": "更改语言" + "changeLanguage": "更改语言", + "manageCustomFields": "管理自定义字段" }, "deleteOrg": { "deleteOrganization": "删除组织", @@ -416,7 +647,8 @@ "deleteMsg": "您是否要删除此组织?", "cancel": "取消", "confirmDelete": "确认删除", - "longDelOrgMsg": "点击删除组织按钮,组织将被永久删除,包括其事件、标签和所有相关数据。" + "longDelOrgMsg": "点击删除组织按钮,组织将被永久删除,包括其事件、标签和所有相关数据。", + "successfullyDeletedSampleOrganization": "已成功刪除樣本組織" }, "userUpdate": { "firstName": "名", @@ -452,8 +684,17 @@ "name": "姓名", "description": "描述", "location": "地點", + "address": "地址", + "city": "城市", + "countryCode": "国家代码", + "line1": "地址行 1", + "line2": "地址行 2", + "postalCode": "邮政编码", + "dependentLocality": "从属地区", + "sortingCode": "排序代码", + "state": "省 / 直辖市", "displayImage": "顯示圖像", - "isPublic": "公开", + "userRegistrationRequired": "需要用户注册", "isVisibleInSearch": "在搜索中可见", "saveChanges": "保存更改", "cancel": "取消", @@ -493,6 +734,7 @@ "memberDetail": { "title": "用户详细信息", "addAdmin": "添加管理员", + "alreadyIsAdmin": "会员已经是管理员", "organizations": "组织", "events": "事件", "role": "角色", @@ -501,9 +743,25 @@ "main": "主要的", "firstName": "名字", "lastName": "姓氏", - "memberOfOrganization": "组织成员", "language": "语言", - "adminApproved": "管理员已批准", + "gender": "性别", + "birthDate": "出生日期", + "educationGrade": "教育程度", + "employmentStatus": "就业状况", + "maritalStatus": "婚姻状况", + "displayImage": "显示图片", + "phone": "电话", + "address": "地址", + "countryCode": "国家代码", + "state": "州/省", + "city": "城市", + "personalInfoHeading": "个人信息", + "contactInfoHeading": "联系信息", + "actionsHeading": "操作", + "personalDetailsHeading": "个人详情", + "appLanguageCode": "选择语言", + "delete": "删除用户", + "saveChanges": "保存更改", "pluginCreationAllowed": "允许创建插件", "joined": "加入", "created": "创建", @@ -553,7 +811,6 @@ "events": "活動", "chat": "聊天", "donate": "捐", - "myTasks": "我的任務", "settings": "設置", "language": "語言", "logout": "登出", @@ -563,14 +820,25 @@ "allOrganizations": "所有組織", "joinedOrganizations": "加入組織", "createdOrganizations": "創建的組織", - "search": "搜索", + "search": "搜索用户", "nothingToShow": "這裡沒有什麼可展示的。", - "selectOrganization": "選擇組織" + "selectOrganization": "選擇組織", + "filter": "過濾", + "organizations": "组织", + "searchByName": "按名稱搜索" }, - "userSidebar": { + "userSidebarOrg": { "yourOrganizations": "您的組織", "noOrganizations": "您還沒有加入任何組織。", - "viewAll": "查看全部" + "viewAll": "查看全部", + "talawaUserPortal": "用户门户", + "menu": "菜单", + "my organizations": "我的组织", + "users": "用户", + "requests": "请求", + "communityProfile": "社区简介", + "logout": "登出", + "settings": "設置" }, "organizationSidebar": { "viewAll": "查看全部", @@ -586,34 +854,90 @@ "home": { "feed": "餵養", "pinnedPosts": "查看固定帖子", - "somethingOnYourMind": "你有什麼心事嗎?" + "somethingOnYourMind": "你有什麼心事嗎?", + "addPost": "添加帖子", + "startPost": "开始一篇帖子", + "media": "媒体", + "event": "活动", + "article": "文章" }, "settings": { - "profileSettings": "配置文件設置", + "settings": "设置", + "profileSettings": "配置文件设置", "firstName": "名", "lastName": "姓", - "emailAddress": "電子郵件地址", - "updateImage": "更新圖片", - "save": "節省" + "gender": "性别", + "emailAddress": "电子邮件地址", + "phoneNumber": "电话号码", + "displayImage": "个人资料图片", + "chooseFile": "选择文件", + "birthDate": "出生日期", + "grade": "教育程度", + "empStatus": "就业状况", + "maritalStatus": "婚姻状况", + "address": "地址", + "state": "城市/州", + "country": "国家", + "resetChanges": "重置更改", + "saveChanges": "保存更改", + "profileDetails": "个人资料详细信息", + "deleteUserMessage": "点击“删除用户”按钮后,您的用户将 永久删除,其事件、标签以及所有相关数据也将被删除。", + "copyLink": "复制个人资料链接", + "deleteUser": "删除用户", + "otherSettings": "其他设置", + "changeLanguage": "更改语言", + "sgender": "选择性别", + "gradePlaceholder": "输入成绩", + "sEmpStatus": "选择就业状态", + "male": "男性", + "female": "女性", + "other": "其他", + "employed": "已 employed", + "unemployed": "失业", + "sMaritalStatus": "选择婚姻状况", + "single": "单身", + "married": "已婚", + "divorced": "离婚", + "widowed": "鰥寡", + "engaged": "已订婚", + "seperated": "分居", + "grade1": "一年级", + "grade2": "二年级", + "grade3": "三年级", + "grade4": "四年级", + "grade5": "五年级", + "grade6": "六年级", + "grade7": "七年级", + "grade8": "八年级", + "grade9": "九年级", + "grade10": "十年级", + "grade11": "十一年级", + "grade12": "十二年级", + "graduate": "毕业生", + "kg": "幼儿园", + "preKg": "学前班", + "noGrade": "无等级", + "fullTime": "全职", + "partTime": "兼职", + "enterState": "输入城市或州", + "selectCountry": "选择国家/地区", + "joined": "加入" }, "donate": { + "donations": "捐款", + "searchDonations": "搜索捐款", + "donateForThe": "为", "donateTo": "捐贈給", "amount": "數量", "yourPreviousDonations": "您之前的捐款", "donate": "捐", - "nothingToShow": "這裡沒有什麼可顯示的。" + "nothingToShow": "這裡沒有什麼可顯示的。", + "success": "捐赠成功" }, "userEvents": { "nothingToShow": "這裡沒有什麼可顯示的。", "search": "搜索", "createEvent": "創建事件", - "eventTitle": "活動標題", - "eventDescription": "活動說明", - "eventLocation": "活動地點", - "startDate": "選擇開始日期", - "endDate": "選擇結束日期", - "publicEvent": "公共活動", - "registerable": "可註冊", "recurring": "再次發生的", "startTime": "開始時間", "endTime": "時間結束", @@ -622,7 +946,20 @@ "listView": "列表顯示", "calendarView": "日曆視圖", "allDay": "整天", - "eventCreated": "活動已成功創建並發布。" + "eventCreated": "活动创建并发布成功。", + "eventDetails": "活动详情", + "eventTitle": "标题", + "enterTitle": "输入标题", + "eventDescription": "描述", + "enterDescription": "输入描述", + "eventLocation": "地点", + "enterLocation": "输入位置", + "startDate": "开始日期", + "endDate": "结束日期", + "publicEvent": "公开", + "registerable": "可注册", + "monthlyCalendarView": "月历", + "yearlyCalendarView": "年度日历" }, "userEventCard": { "location": "地點", @@ -632,29 +969,26 @@ "alreadyRegistered": "已經註冊", "register": "登記" }, - "userTasks": { - "yourAssignedTasks": "您指派的任務", - "nothingToShow": "這裡沒有什麼可顯示的。" - }, - "userTaskCard": { - "description": "描述", - "deadline": "最後期限", - "created": "已創建", - "assignees": "受讓人", - "completed": "完全的", - "incomplete": "不完整", - "taskCompleted": "任務已完成", - "taskNotCompleted": "任務還沒完成", - "event": "事件", - "organization": "組織" - }, "advertisement": { "title": "广告", "pHeading": "管理广告", "activeAds": "活动广告", "archievedAds": "已完成的广告活动", "pMessage": "此广告活动没有相关广告。", - "delete": "删除" + "delete": "删除", + "validLink": "链接有效", + "invalidLink": "链接无效", + "close": "关闭", + "deleteAdvertisement": "删除广告", + "deleteAdvertisementMsg": "您是否要删除此广告?", + "no": "不", + "yes": "是", + "Rmedia": "提供要显示的媒体内容", + "view": "查看", + "edit": "编辑", + "editAdvertisement": "编辑广告", + "saveChanges": "保存更改", + "endOfResults": "結果結束" }, "userChat": { "chat": "聊天", @@ -664,5 +998,106 @@ "userChatRoom": { "selectContact": "選擇聯絡人開始對話", "sendMessage": "傳訊息" + }, + "orgProfileField": { + "loading": "正在加载...", + "noCustomField": "没有可用的自定义字段", + "customFieldName": "字段名称", + "enterCustomFieldName": "输入字段名称", + "customFieldType": "字段类型", + "saveChanges": "保存更改", + "删除自定义字段": "删除自定义字段", + "fieldSuccessMessage": "字段添加成功", + "fieldRemovalSuccess": "字段删除成功" + }, + "orgActionItemCategories": { + "createButton": "创建", + "editButton": "编辑", + "enableButton": "启用", + "disableButton": "禁用", + "updateActionItemCategory": "更新", + "actionItemCategoryName": "名称", + "actionItemCategoryDetails": "措施项类别详细信息", + "enterName": "输入名称", + "successfulCreation": "已成功创建措施项类别", + "successfulUpdation": "措施项类别已成功更新", + "sameNameConflict": "请更改名称以进行更新", + "categoryEnabled": "已启用措施项类别", + "categoryDisabled": "措施项类别已禁用" + }, + "organizationVenues": { + "title": "场地", + "addVenue": "添加场地", + "venueDetails": "场地详情", + "venueName": "场地名称", + "enterVenueName": "输入场地名称", + "description": "场地描述", + "enterVenueDesc": "输入场地描述", + "capacity": "容量", + "enterVenueCapacity": "输入场地容量", + "image": "场地图像", + "uploadVenueImage": "上传场地图像", + "createVenue": "创建场地", + "venueAdded": "场地添加成功", + "editVenue": "更新场地", + "venueUpdated": "场地详情更新成功", + "sort": "排序", + "highestCapacity": "最高容量", + "lowestCapacity": "最低容量", + "noVenues": "没有找到场地!", + "edit": "编辑", + "view": "查看", + "delete": "删除", + "venueTitleError": "场地标题不能为空!", + "venueCapacityError": "容量必须为正数!", + "searchBy": "搜索方式", + "name": "名称", + "desc": "描述" + }, + "addMember": { + "title": "添加成员", + "addMembers": "添加成员", + "existingUser": "现有用户", + "newUser": "新用户", + "searchFullName": "按全名搜索", + "firstName": "名字", + "enterFirstName": "输入名字", + "lastName": "姓氏", + "enterLastName": "输入姓氏", + "emailAddress": "电子邮件地址", + "enterEmail": "输入电子邮件", + "password": "密码", + "enterPassword": "输入密码", + "confirmPassword": "确认密码", + "enterConfirmPassword": "输入确认密码", + "organization": "组织", + "cancel": "取消", + "create": "创建", + "invalidDetailsMessage": "请提供所有必需的细节。", + "passwordNotMatch": "密码不匹配。", + "user": "用户", + "addMember": "添加成员" + }, + "eventActionItems": { + "title": "行动项目", + "createActionItem": "创建操作项", + "actionItemCategory": "操作项类别", + "selectActionItemCategory": "选择操作项类别", + "selectAssignee": "选择受让人", + "preCompletionNotes": "预完成注释", + "postCompletionNotes": "完成后注释", + "actionItemDetails": "操作项详细信息", + "dueDate": "截止日期", + "completionDate": "完成日期", + "editActionItem": "编辑操作项", + "deleteActionItem": "删除操作项", + "deleteActionItemMsg": "您要删除此操作项吗?", + "yes": "是的", + "不": "不", + "successfulDeletion": "操作项删除成功", + "successfulCreation": "操作项创建成功", + "successfulUpdation": "操作项更新成功", + "notes": "注释", + "save": "保存" } } diff --git a/schema.graphql b/schema.graphql index d200ee7349..0030ec7fc3 100644 --- a/schema.graphql +++ b/schema.graphql @@ -2,14 +2,94 @@ directive @auth on FIELD_DEFINITION directive @role(requires: UserType) on FIELD_DEFINITION +type ActionItem { + _id: ID! + actionItemCategory: ActionItemCategory + assignee: User + assigner: User + assignmentDate: Date! + completionDate: Date! + createdAt: Date! + creator: User + dueDate: Date! + event: Event + isCompleted: Boolean! + postCompletionNotes: String + preCompletionNotes: String + updatedAt: Date! +} + +type ActionItemCategory { + _id: ID! + createdAt: Date! + creator: User + isDisabled: Boolean! + name: String! + organization: Organization + updatedAt: Date! +} + +type Address { + city: String + countryCode: String + dependentLocality: String + line1: String + line2: String + postalCode: String + sortingCode: String + state: String +} + +input AddressInput { + city: String + countryCode: String + dependentLocality: String + line1: String + line2: String + postalCode: String + sortingCode: String + state: String +} + type Advertisement { - _id: ID + _id: ID! + createdAt: DateTime! + creator: User endDate: Date! - link: String! + mediaUrl: URL! name: String! - orgId: ID + orgId: ID! startDate: Date! - type: String! + type: AdvertisementType! + updatedAt: DateTime! +} + +enum AdvertisementType { + BANNER + MENU + POPUP +} + +type AdvertisementEdge { + cursor: String + node: Advertisement +} + +type AdvertisementsConnection { + edges: [AdvertisementEdge] + pageInfo: DefaultConnectionPageInfo + totalCount: Int +} + +type AgendaCategory { + _id: ID! + createdAt: Date! + createdBy: User! + description: String + name: String! + organization: Organization! + updatedAt: Date + updatedBy: User } type AggregatePost { @@ -20,18 +100,23 @@ type AggregateUser { count: Int! } -type AndroidFirebaseOptions { - apiKey: String - appId: String - messagingSenderId: String - projectId: String - storageBucket: String +scalar Any + +type AppUserProfile { + _id: ID! + adminFor: [Organization] + appLanguageCode: String! + createdEvents: [Event] + createdOrganizations: [Organization] + eventAdmin: [Event] + isSuperAdmin: Boolean! + pluginCreationAllowed: Boolean! + userId: User! } type AuthData { accessToken: String! - androidFirebaseOptions: AndroidFirebaseOptions! - iosFirebaseOptions: IOSFirebaseOptions! + appUserProfile: AppUserProfile! refreshToken: String! user: User! } @@ -40,9 +125,11 @@ type CheckIn { _id: ID! allotedRoom: String allotedSeat: String + createdAt: DateTime! event: Event! feedbackSubmitted: Boolean! time: DateTime! + updatedAt: DateTime! user: User! } @@ -60,13 +147,14 @@ type CheckInStatus { } type Comment { - _id: ID - createdAt: DateTime - creator: User! + _id: ID! + createdAt: DateTime! + creator: User likeCount: Int likedBy: [User] post: Post! text: String! + updatedAt: DateTime! } input CommentInput { @@ -82,6 +170,21 @@ type ConnectionPageInfo { startCursor: String } +scalar CountryCode + +input CreateActionItemInput { + assigneeId: ID! + dueDate: Date + eventId: ID + preCompletionNotes: String +} + +input CreateAgendaCategoryInput { + description: String + name: String! + organizationId: ID! +} + input CreateUserTagInput { name: String! organizationId: ID! @@ -104,9 +207,11 @@ type DeletePayload { type DirectChat { _id: ID! - creator: User! + createdAt: DateTime! + creator: User messages: [DirectChatMessage] organization: Organization! + updatedAt: DateTime! users: [User!]! } @@ -117,15 +222,18 @@ type DirectChatMessage { messageContent: String! receiver: User! sender: User! + updatedAt: DateTime! } type Donation { _id: ID! amount: Float! + createdAt: DateTime! nameOfOrg: String! nameOfUser: String! orgId: ID! payPalId: String! + updatedAt: DateTime! userId: ID! } @@ -144,22 +252,49 @@ input DonationWhereInput { name_of_user_starts_with: String } +enum EducationGrade { + GRADE_1 + GRADE_2 + GRADE_3 + GRADE_4 + GRADE_5 + GRADE_6 + GRADE_7 + GRADE_8 + GRADE_9 + GRADE_10 + GRADE_11 + GRADE_12 + GRADUATE + KG + NO_GRADE + PRE_KG +} + scalar EmailAddress +enum EmploymentStatus { + FULL_TIME + PART_TIME + UNEMPLOYED +} + interface Error { message: String! } type Event { _id: ID! - admins(adminId: ID): [User] + actionItems: [ActionItem] + admins(adminId: ID): [User!] allDay: Boolean! - attendees: [User!]! + attendees: [User] attendeesCheckInStatus: [CheckInStatus!]! averageFeedbackScore: Float - creator: User! + createdAt: DateTime! + creator: User description: String! - endDate: Date! + endDate: Date endTime: Time feedback: [Feedback!]! isPublic: Boolean! @@ -168,13 +303,13 @@ type Event { location: String longitude: Longitude organization: Organization - projects: [EventProject] recurrance: Recurrance recurring: Boolean! startDate: Date! startTime: Time status: Status! title: String! + updatedAt: DateTime! } input EventAttendeeInput { @@ -223,18 +358,26 @@ enum EventOrderByInput { title_DESC } -type EventProject { +type EventVolunteer { _id: ID! - description: String! - event: Event! - tasks: [Task] - title: String! + createdAt: DateTime! + creator: User + event: Event + isAssigned: Boolean + isInvited: Boolean + response: String + updatedAt: DateTime! + user: User! } -input EventProjectInput { - description: String! +input EventVolunteerInput { eventId: ID! - title: String! + userId: ID! +} + +enum EventVolunteerResponse { + NO + YES } input EventWhereInput { @@ -272,9 +415,11 @@ type ExtendSession { type Feedback { _id: ID! + createdAt: DateTime! event: Event! rating: Int! review: String + updatedAt: DateTime! } input FeedbackInput { @@ -294,20 +439,36 @@ input ForgotPasswordData { userOtp: String! } +enum Frequency { + DAILY + MONTHLY + WEEKLY + YEARLY +} + +enum Gender { + FEMALE + MALE + OTHER +} + type Group { - _id: ID - admins: [User] - createdAt: DateTime + _id: ID! + admins: [User!]! + createdAt: DateTime! description: String organization: Organization! - title: String + title: String! + updatedAt: DateTime! } type GroupChat { _id: ID! - creator: User! + createdAt: DateTime! + creator: User messages: [GroupChatMessage] organization: Organization! + updatedAt: DateTime! users: [User!]! } @@ -317,16 +478,7 @@ type GroupChatMessage { groupChatMessageBelongsTo: GroupChat! messageContent: String! sender: User! -} - -type IOSFirebaseOptions { - apiKey: String - appId: String - iosBundleId: String - iosClientId: String - messagingSenderId: String - projectId: String - storageBucket: String + updatedAt: DateTime! } type InvalidCursor implements FieldError { @@ -334,6 +486,8 @@ type InvalidCursor implements FieldError { path: [String!]! } +scalar JSON + type Language { _id: ID! createdAt: String! @@ -364,6 +518,15 @@ input LoginInput { scalar Longitude +enum MaritalStatus { + DIVORCED + ENGAGED + MARRIED + SEPERATED + SINGLE + WIDOWED +} + type MaximumLengthError implements FieldError { message: String! path: [String!]! @@ -383,10 +546,11 @@ type MembershipRequest { type Message { _id: ID! - createdAt: DateTime + createdAt: DateTime! creator: User imageUrl: URL - text: String + text: String! + updatedAt: DateTime! videoUrl: URL } @@ -397,6 +561,7 @@ type MessageChat { message: String! receiver: User! sender: User! + updatedAt: DateTime! } input MessageChatInput { @@ -415,23 +580,71 @@ type MinimumValueError implements FieldError { path: [String!]! } +enum AdvertisementType { + BANNER + MENU + POPUP +} + +input CreateAdvertisementInput { + endDate: Date! + name: String! + organizationId: ID! + startDate: Date! + type: AdvertisementType! + mediaFile: String! +} + +type CreateAdvertisementPayload { + advertisement: Advertisement +} + +input EditVenueInput { + capacity: Int + description: String + file: String + id: ID! + name: String +} + type Mutation { - acceptAdmin(id: ID!): Boolean! acceptMembershipRequest(membershipRequestId: ID!): MembershipRequest! addEventAttendee(data: EventAttendeeInput!): User! addFeedback(data: FeedbackInput!): Feedback! addLanguageTranslation(data: LanguageInput!): Language! + addOrganizationCustomField( + name: String! + organizationId: ID! + type: String! + ): OrganizationCustomField! addOrganizationImage(file: String!, organizationId: String!): Organization! + addUserCustomData( + dataName: String! + dataValue: Any! + organizationId: ID! + ): UserCustomData! addUserImage(file: String!): User! addUserToGroupChat(chatId: ID!, userId: ID!): GroupChat! + addUserToUserFamily(familyId: ID!, userId: ID!): UserFamily! adminRemoveEvent(eventId: ID!): Event! adminRemoveGroup(groupId: ID!): GroupChat! assignUserTag(input: ToggleUserTagAssignInput!): User - blockPluginCreationBySuperadmin(blockUser: Boolean!, userId: ID!): User! + blockPluginCreationBySuperadmin( + blockUser: Boolean! + userId: ID! + ): AppUserProfile! blockUser(organizationId: ID!, userId: ID!): User! cancelMembershipRequest(membershipRequestId: ID!): MembershipRequest! checkIn(data: CheckInInput!): CheckIn! - createAdmin(data: UserAndOrganizationInput!): User! + createActionItem( + actionItemCategoryId: ID! + data: CreateActionItemInput! + ): ActionItem! + createActionItemCategory( + name: String! + organizationId: ID! + ): ActionItemCategory! + createAdmin(data: UserAndOrganizationInput!): AppUserProfile! createAdvertisement( endDate: Date! link: String! @@ -440,6 +653,7 @@ type Mutation { startDate: Date! type: String! ): Advertisement! + createAgendaCategory(input: CreateAgendaCategoryInput!): AgendaCategory! createComment(data: CommentInput!, postId: ID!): Comment createDirectChat(data: createChatInput!): DirectChat! createDonation( @@ -450,8 +664,11 @@ type Mutation { payPalId: ID! userId: ID! ): Donation! - createEvent(data: EventInput): Event! - createEventProject(data: EventProjectInput!): EventProject! + createEvent( + data: EventInput! + recurrenceRuleData: RecurrenceRuleInput + ): Event! + createEventVolunteer(data: EventVolunteerInput!): EventVolunteer! createGroupChat(data: createGroupChatInput!): GroupChat! createMember(input: UserAndOrganizationInput!): Organization! createMessageChat(data: MessageChatInput!): MessageChat! @@ -463,10 +680,16 @@ type Mutation { uninstalledOrgs: [ID!] ): Plugin! createPost(data: PostInput!, file: String): Post - createTask(data: TaskInput!, eventProjectId: ID!): Task! + createSampleOrganization: Boolean! + createUserFamily(data: createUserFamilyInput!): UserFamily! createUserTag(input: CreateUserTagInput!): UserTag + createVenue(data: VenueInput!): Venue + deleteAdvertisement(id: ID!): DeletePayload! deleteAdvertisementById(id: ID!): DeletePayload! + deleteAgendaCategory(id: ID!): ID! deleteDonationById(id: ID!): DeletePayload! + deleteVenue(id: ID!): Venue + editVenue(data: EditVenueInput!): Venue forgotPassword(data: ForgotPasswordData!): Boolean! joinPublicOrganization(organizationId: ID!): User! leaveOrganization(organizationId: ID!): User! @@ -478,25 +701,32 @@ type Mutation { recaptcha(data: RecaptchaVerification!): Boolean! refreshToken(refreshToken: String!): ExtendSession! registerForEvent(id: ID!): Event! - rejectAdmin(id: ID!): Boolean! rejectMembershipRequest(membershipRequestId: ID!): MembershipRequest! - removeAdmin(data: UserAndOrganizationInput!): User! + removeActionItem(id: ID!): ActionItem! + removeAdmin(data: UserAndOrganizationInput!): AppUserProfile! removeAdvertisement(id: ID!): Advertisement removeComment(id: ID!): Comment removeDirectChat(chatId: ID!, organizationId: ID!): DirectChat! removeEvent(id: ID!): Event! removeEventAttendee(data: EventAttendeeInput!): User! - removeEventProject(id: ID!): EventProject! + removeEventVolunteer(id: ID!): EventVolunteer! removeGroupChat(chatId: ID!): GroupChat! removeMember(data: UserAndOrganizationInput!): Organization! - removeOrganization(id: ID!): User! + removeOrganization(id: ID!): UserData! + removeOrganizationCustomField( + customFieldId: ID! + organizationId: ID! + ): OrganizationCustomField! removeOrganizationImage(organizationId: String!): Organization! removePost(id: ID!): Post - removeTask(id: ID!): Task + removeSampleOrganization: Boolean! + removeUserCustomData(organizationId: ID!): UserCustomData! + removeUserFamily(familyId: ID!): UserFamily! removeUserFromGroupChat(chatId: ID!, userId: ID!): GroupChat! + removeUserFromUserFamily(familyId: ID!, userId: ID!): UserFamily! removeUserImage: User! removeUserTag(id: ID!): UserTag - revokeRefreshTokenForUser(userId: String!): Boolean! + revokeRefreshTokenForUser: Boolean! saveFcmToken(token: String): Boolean! sendMembershipRequest(organizationId: ID!): MembershipRequest! sendMessageToDirectChat( @@ -507,16 +737,30 @@ type Mutation { chatId: ID! messageContent: String! ): GroupChatMessage! - setTaskVolunteers(id: ID!, volunteers: [ID]!): Task signUp(data: UserInput!, file: String): AuthData! - togglePostPin(id: ID!): Post! + togglePostPin(id: ID!, title: String): Post! unassignUserTag(input: ToggleUserTagAssignInput!): User unblockUser(organizationId: ID!, userId: ID!): User! unlikeComment(id: ID!): Comment unlikePost(id: ID!): Post unregisterForEventByUser(id: ID!): Event! + updateActionItem(data: UpdateActionItemInput!, id: ID!): ActionItem + updateActionItemCategory( + data: UpdateActionItemCategoryInput! + id: ID! + ): ActionItemCategory + updateAdvertisement( + input: UpdateAdvertisementInput! + ): UpdateAdvertisementPayload + updateAgendaCategory( + id: ID! + input: UpdateAgendaCategoryInput! + ): AgendaCategory updateEvent(data: UpdateEventInput, id: ID!): Event! - updateEventProject(data: UpdateEventProjectInput!, id: ID!): EventProject! + updateEventVolunteer( + data: UpdateEventVolunteerInput + id: ID! + ): EventVolunteer! updateLanguage(languageCode: String!): User! updateOrganization( data: UpdateOrganizationInput @@ -525,11 +769,16 @@ type Mutation { ): Organization! updatePluginStatus(id: ID!, orgId: ID!): Plugin! updatePost(data: PostUpdateInput, id: ID!): Post! - updateTask(data: UpdateTaskInput!, id: ID!): Task - updateUserPassword(data: UpdateUserPasswordInput!): User! + updateUserPassword(data: UpdateUserPasswordInput!): UserData! updateUserProfile(data: UpdateUserInput, file: String): User! + updateUserRoleInOrganization( + organizationId: ID! + role: String! + userId: ID! + ): Organization! updateUserTag(input: UpdateUserTagInput!): UserTag updateUserType(data: UpdateUserTypeInput!): Boolean! + venues: [Venue] } input OTPInput { @@ -538,19 +787,23 @@ input OTPInput { type Organization { _id: ID! - admins(adminId: ID): [User] + actionItemCategories: [ActionItemCategory] + address: Address + admins(adminId: ID): [User!] + agendaCategories: [AgendaCategory] apiUrl: URL! blockedUsers: [User] - createdAt: DateTime - creator: User! + createdAt: DateTime! + creator: User + customFields: [OrganizationCustomField!]! description: String! image: String - isPublic: Boolean! - location: String members: [User] membershipRequests: [MembershipRequest] name: String! pinnedPosts: [Post] + updatedAt: DateTime! + userRegistrationRequired: Boolean! userTags( after: String before: String @@ -558,33 +811,50 @@ type Organization { last: PositiveInt ): UserTagsConnection visibleInSearch: Boolean! + venues: [Venue] +} + +type OrganizationCustomField { + _id: ID! + name: String! + organizationId: String! + type: String! +} + +type OrganizationCustomField { + _id: ID! + name: String! + organizationId: String! + type: String! } type OrganizationInfoNode { _id: ID! apiUrl: URL! - creator: User! + creator: User description: String! image: String - isPublic: Boolean! name: String! + userRegistrationRequired: Boolean! visibleInSearch: Boolean! } input OrganizationInput { + address: AddressInput! apiUrl: URL attendees: String description: String! image: String - isPublic: Boolean! - location: String name: String! - visibleInSearch: Boolean! + userRegistrationRequired: Boolean + visibleInSearch: Boolean } enum OrganizationOrderByInput { apiUrl_ASC apiUrl_DESC + createdAt_ASC + createdAt_DESC description_ASC description_DESC id_ASC @@ -612,13 +882,13 @@ input OrganizationWhereInput { id_not: ID id_not_in: [ID!] id_starts_with: ID - isPublic: Boolean name: String name_contains: String name_in: [String!] name_not: String name_not_in: [String!] name_starts_with: String + userRegistrationRequired: Boolean visibleInSearch: Boolean } @@ -658,11 +928,11 @@ type Plugin { pluginCreatedBy: String! pluginDesc: String! pluginName: String! - uninstalledOrgs: [ID!]! + uninstalledOrgs: [ID!] } type PluginField { - createdAt: DateTime + createdAt: DateTime! key: String! status: Status! value: String! @@ -687,8 +957,8 @@ type Post { _id: ID commentCount: Int comments: [Comment] - createdAt: DateTime - creator: User! + createdAt: DateTime! + creator: User imageUrl: URL likeCount: Int likedBy: [User] @@ -696,6 +966,7 @@ type Post { pinned: Boolean text: String! title: String + updatedAt: DateTime! videoUrl: URL } @@ -774,11 +1045,20 @@ input PostWhereInput { } type Query { + actionItem(id: ID!): ActionItem + actionItemCategoriesByOrganization(organizationId: ID!): [ActionItemCategory] + actionItemCategory(id: ID!): ActionItemCategory + actionItemsByEvent(eventId: ID!): [ActionItem] + actionItemsByOrganization(organizationId: ID!): [ActionItem] adminPlugin(orgId: ID!): [Plugin] + agendaCategory(id: ID!): AgendaCategory! checkAuth: User! + customDataByOrganization(organizationId: ID!): [UserCustomData!]! + customFieldsByOrganization(id: ID!): [OrganizationCustomField] directChatsByUserID(id: ID!): [DirectChat] directChatsMessagesByChatID(id: ID!): [DirectChatMessage] event(id: ID!): Event + eventVolunteersByEvent(id: ID!): [EventVolunteer] eventsByOrganization(id: ID, orderBy: EventOrderByInput): [Event] eventsByOrganizationConnection( first: Int @@ -786,7 +1066,7 @@ type Query { skip: Int where: EventWhereInput ): [Event!]! - getAdvertisements: [Advertisement] + advertisementsConnection(after: String, before: String, first: PositiveInt, last: PositiveInt): AdvertisementsConnection getDonationById(id: ID!): Donation! getDonationByOrgId(orgId: ID!): [Donation] getDonationByOrgIdConnection( @@ -798,9 +1078,11 @@ type Query { getPlugins: [Plugin] getlanguage(lang_code: String!): [Translation] hasSubmittedFeedback(eventId: ID!, userId: ID!): Boolean + isSampleOrganization(id: ID!): Boolean! joinedOrganizations(id: ID): [Organization] - me: User! + me: UserData! myLanguage: String + fundsByOrganization(organizationId: ID!, where: FundWhereInput): [Fund] organizations(id: ID, orderBy: OrganizationOrderByInput): [Organization] organizationsConnection( first: Int @@ -827,15 +1109,21 @@ type Query { ): PostConnection registeredEventsByUser(id: ID, orderBy: EventOrderByInput): [Event] registrantsByEvent(id: ID!): [User] - user(id: ID!): User! + user(id: ID!): UserData! userLanguage(userId: ID!): String - users(orderBy: UserOrderByInput, where: UserWhereInput): [User] + users( + first: Int + orderBy: UserOrderByInput + skip: Int + where: UserWhereInput + ): [UserData] usersConnection( first: Int orderBy: UserOrderByInput skip: Int where: UserWhereInput - ): [User]! + ): [UserData]! + venue(id:ID!):[Venue] } input RecaptchaVerification { @@ -850,6 +1138,12 @@ enum Recurrance { YEARLY } +input RecurrenceRuleInput { + count: Int + frequency: Frequency + weekDays: [WeekDays] +} + enum Status { ACTIVE BLOCKED @@ -863,37 +1157,6 @@ type Subscription { onPluginUpdate: Plugin } -type Task { - _id: ID! - completed: Boolean - createdAt: DateTime! - creator: User! - deadline: DateTime - description: String - event: Event! - title: String! - volunteers: [User] -} - -input TaskInput { - deadline: DateTime! - description: String! - title: String! -} - -enum TaskOrderByInput { - createdAt_ASC - createdAt_DESC - deadline_ASC - deadline_DESC - description_ASC - description_DESC - id_ASC - id_DESC - title_ASC - title_DESC -} - scalar Time input ToggleUserTagAssignInput { @@ -923,6 +1186,38 @@ type UnauthorizedError implements Error { message: String! } +input UpdateActionItemCategoryInput { + isDisabled: Boolean + name: String +} + +input UpdateActionItemInput { + assigneeId: ID + completionDate: Date + dueDate: Date + isCompleted: Boolean + postCompletionNotes: String + preCompletionNotes: String +} + +input UpdateAdvertisementInput { + _id: ID! + endDate: Date + link: String + name: String + startDate: Date + type: AdvertisementType +} + +type UpdateAdvertisementPayload { + advertisement: Advertisement +} + +input UpdateAgendaCategoryInput { + description: String + name: String +} + input UpdateEventInput { allDay: Boolean description: String @@ -940,30 +1235,83 @@ input UpdateEventInput { title: String } -input UpdateEventProjectInput { - description: String - title: String +input UpdateEventVolunteerInput { + eventId: ID + isAssigned: Boolean + isInvited: Boolean + response: EventVolunteerResponse } input UpdateOrganizationInput { + address: AddressInput description: String - isPublic: Boolean - location: String name: String + userRegistrationRequired: Boolean visibleInSearch: Boolean } -input UpdateTaskInput { - completed: Boolean - deadline: DateTime - description: String - title: String +input AddressInput { + city: String + countryCode: String + dependentLocality: String + line1: String + line2: String + postalCode: String + sortingCode: String + state: String +} + +enum EducationGrade { + GRADE_1 + GRADE_2 + GRADE_3 + GRADE_4 + GRADE_5 + GRADE_6 + GRADE_7 + GRADE_8 + GRADE_9 + GRADE_10 + GRADE_11 + GRADE_12 + GRADUATE + KG + NO_GRADE + PRE_KG +} + +enum EmploymentStatus { + FULL_TIME + PART_TIME + UNEMPLOYED +} + +enum Gender { + FEMALE + MALE + OTHER +} + +enum MaritalStatus { + DIVORCED + ENGAGED + MARRIED + SEPERATED + SINGLE + WIDOWED } input UpdateUserInput { + address: AddressInput + birthDate: Date + educationGrade: EducationGrade email: EmailAddress + employmentStatus: EmploymentStatus firstName: String + gender: Gender lastName: String + maritalStatus: MaritalStatus + phone: UserPhoneInput } input UpdateUserPasswordInput { @@ -986,23 +1334,23 @@ scalar Upload type User { _id: ID! - adminApproved: Boolean - adminFor: [Organization] - appLanguageCode: String! - assignedTasks: [Task] - createdAt: DateTime - createdEvents: [Event] - createdOrganizations: [Organization] + address: Address + appUserProfileId: AppUserProfile + birthDate: Date + createdAt: DateTime! + educationGrade: EducationGrade email: EmailAddress! - eventAdmin: [Event] + employmentStatus: EmploymentStatus firstName: String! + gender: Gender image: String joinedOrganizations: [Organization] lastName: String! + maritalStatus: MaritalStatus membershipRequests: [MembershipRequest] - organizationUserBelongsTo: Organization organizationsBlockedBy: [Organization] - pluginCreationAllowed: Boolean + phone: UserPhone + pluginCreationAllowed: Boolean! registeredEvents: [Event] tagsAssignedWith( after: String @@ -1011,8 +1359,25 @@ type User { last: PositiveInt organizationId: ID ): UserTagsConnection - tokenVersion: Int! - userType: String + updatedAt: DateTime! +} + +type Fund { + _id: ID! + campaigns: [FundraisingCampaign!] + createdAt: DateTime! + isArchived: Boolean! + isDefault: Boolean! + name: String! + creator: User + organizationId: ID! + refrenceNumber: String + taxDeductible: Boolean! + updatedAt: DateTime! +} + +input FundWhereInput { + name_contains: String } input UserAndOrganizationInput { @@ -1020,17 +1385,43 @@ input UserAndOrganizationInput { userId: ID! } +type UserPhone { + home: PhoneNumber + mobile: PhoneNumber + work: PhoneNumber +} + type UserConnection { aggregate: AggregateUser! edges: [User]! pageInfo: PageInfo! } +type UserCustomData { + _id: ID! + organizationId: ID! + userId: ID! + values: JSON! +} + +type UserData { + appUserProfile: AppUserProfile! + user: User! +} + type UserEdge { cursor: String! node: User! } +type UserFamily { + _id: ID! + admins: [User!]! + creator: User! + title: String + users: [User!]! +} + input UserInput { appLanguageCode: String email: EmailAddress! @@ -1041,8 +1432,6 @@ input UserInput { } enum UserOrderByInput { - appLanguageCode_ASC - appLanguageCode_DESC email_ASC email_DESC firstName_ASC @@ -1053,6 +1442,18 @@ enum UserOrderByInput { lastName_DESC } +type UserPhone { + home: PhoneNumber + mobile: PhoneNumber + work: PhoneNumber +} + +input UserPhoneInput { + home: PhoneNumber + mobile: PhoneNumber + work: PhoneNumber +} + type UserTag { _id: ID! childTags(input: UserTagsConnectionInput!): UserTagsConnectionResult! @@ -1085,18 +1486,12 @@ type UserTagsConnectionResult { enum UserType { ADMIN + NON_USER SUPERADMIN USER } input UserWhereInput { - admin_for: ID - appLanguageCode: String - appLanguageCode_contains: String - appLanguageCode_in: [String!] - appLanguageCode_not: String - appLanguageCode_not_in: [String!] - appLanguageCode_starts_with: String email: EmailAddress email_contains: EmailAddress email_in: [EmailAddress!] @@ -1140,6 +1535,16 @@ type UsersConnectionResult { errors: [ConnectionError!]! } +enum WeekDays { + FR + MO + SA + SU + TH + TU + WE +} + input createChatInput { organizationId: ID! userIds: [ID!]! @@ -1150,3 +1555,25 @@ input createGroupChatInput { title: String! userIds: [ID!]! } + +type Venue { + _id: ID! + capacity: Int! + description: String + imageUrl: URL + name: String! + organization: Organization! +} + +input VenueInput { + capacity: Int! + description: String + file: String + name: String! + organizationId: ID! +} + +input createUserFamilyInput { + title: String! + userIds: [ID!]! +} diff --git a/scripts/__mocks__/@dicebear/collection.ts b/scripts/__mocks__/@dicebear/collection.ts new file mode 100644 index 0000000000..9a7e1e9a57 --- /dev/null +++ b/scripts/__mocks__/@dicebear/collection.ts @@ -0,0 +1 @@ +export const initials = jest.fn(); diff --git a/scripts/__mocks__/@dicebear/core.ts b/scripts/__mocks__/@dicebear/core.ts new file mode 100644 index 0000000000..71a02f19ea --- /dev/null +++ b/scripts/__mocks__/@dicebear/core.ts @@ -0,0 +1,5 @@ +export const createAvatar = jest.fn(() => { + return { + toDataUriSync: jest.fn(() => 'mocked-data-uri'), + }; +}); diff --git a/scripts/config-overrides/custom_build.js b/scripts/config-overrides/custom_build.js new file mode 100644 index 0000000000..d5c0ce93a2 --- /dev/null +++ b/scripts/config-overrides/custom_build.js @@ -0,0 +1,17 @@ +require('dotenv').config(); +const { spawn } = require('child_process'); + +//use default react scritps config +const react_script_build = 'npx react-scripts build'; + +//use custom config overriden by react-app-rewired +const react_app_rewired_build = 'npx react-app-rewired build'; + +if (process.env.ALLOW_LOGS === "YES") { + spawn(react_app_rewired_build, { stdio: 'inherit', shell: true }); + +} +else { + spawn(react_script_build, { stdio: 'inherit', shell: true }); +} + diff --git a/scripts/config-overrides/custom_start.js b/scripts/config-overrides/custom_start.js new file mode 100644 index 0000000000..a784f1bb48 --- /dev/null +++ b/scripts/config-overrides/custom_start.js @@ -0,0 +1,19 @@ +require('dotenv').config(); +const { spawn } = require('child_process'); + +const port = process.env.PORT || 4321; +process.env.PORT = port; + +const react_script_start = 'npx react-scripts start'; +const react_app_rewired_start = 'npx react-app-rewired start --config-overrides=scripts/config-overrides'; + +if (process.env.ALLOW_LOGS === "YES") { + // Execute the npm command + spawn(react_app_rewired_start, { stdio: 'inherit', shell: true }); + +} +else { + // Execute the npm command + spawn(react_script_start, { stdio: 'inherit', shell: true }); + } + diff --git a/scripts/config-overrides/index.js b/scripts/config-overrides/index.js new file mode 100644 index 0000000000..a8d16aa7e9 --- /dev/null +++ b/scripts/config-overrides/index.js @@ -0,0 +1,29 @@ +const { override, addWebpackPlugin } = require('customize-cra'); +const webpack = require('webpack'); + + +module.exports = override( + // Add your new webpack plugin + addWebpackPlugin(new webpack.ProgressPlugin({ + activeModules: true, + entries: true, + handler: (percentage, message, ...args) => { + // Log a custom progress message with active module and its count + console.info(`: ${Math.floor(percentage * 100)}% ${message}`); + }, + modules: true, + modulesCount: 5000, + profile: false, + dependencies: true, + dependenciesCount: 10000, + percentBy: null, +})), + + // Modify infrastructureLogging level + (config) => { + config.infrastructureLogging = { + level: 'verbose', + }; + return config; + } +); \ No newline at end of file diff --git a/scripts/config-overrides/package.json b/scripts/config-overrides/package.json new file mode 100644 index 0000000000..c0a38b857f --- /dev/null +++ b/scripts/config-overrides/package.json @@ -0,0 +1,5 @@ +{ + "name": "config-overrides", + "version": "1.0.0", + "type": "commonjs" +} diff --git a/scripts/custom-test-env.js b/scripts/custom-test-env.js index 8e6c2022f3..6174d8cf11 100644 --- a/scripts/custom-test-env.js +++ b/scripts/custom-test-env.js @@ -6,7 +6,6 @@ import { TextEncoder, TextDecoder } from 'util'; * Providing a polyfill to the environment for the same */ export default class CustomTestEnvironment extends Environment { - // eslint-disable-next-line @typescript-eslint/explicit-function-return-type async setup() { await super.setup(); if (typeof this.global.TextEncoder === 'undefined') { diff --git a/scripts/githooks/check-localstorage-usage.js b/scripts/githooks/check-localstorage-usage.js new file mode 100755 index 0000000000..0a811df307 --- /dev/null +++ b/scripts/githooks/check-localstorage-usage.js @@ -0,0 +1,96 @@ +#!/usr/bin/env node + +import { readFileSync, existsSync } from 'fs'; +import path from 'path'; +import { execSync } from 'child_process'; + +const args = process.argv.slice(2); +const scanEntireRepo = args.includes('--scan-entire-repo'); + +const containsSkipComment = (file) => { + try { + const content = readFileSync(file, 'utf-8'); + return content.includes('// SKIP_LOCALSTORAGE_CHECK'); + } catch (error) { + console.error(`Error reading file ${file}:`, error.message); + return false; + } +}; + +const getModifiedFiles = () => { + try { + if (scanEntireRepo) { + const result = execSync('git ls-files | grep ".tsx\\?$"', { + encoding: 'utf-8', + }); + return result.trim().split('\n'); + } + + const result = execSync('git diff --cached --name-only', { + encoding: 'utf-8', + }); + return result.trim().split('\n'); + } catch (error) { + console.error('Error fetching modified files:', error.message); + process.exit(1); + } +}; + +const files = getModifiedFiles(); + +const filesWithLocalStorage = []; + +const checkLocalStorageUsage = (file) => { + if (!file) { + return; + } + + const fileName = path.basename(file); + + // Skip files with specific names or containing a skip comment + if ( + fileName === 'check-localstorage-usage.js' || + fileName === 'useLocalstorage.test.ts' || + fileName === 'useLocalstorage.ts' || + containsSkipComment(file) + ) { + console.log(`Skipping file: ${file}`); + return; + } + + try { + if (existsSync(file)) { + const content = readFileSync(file, 'utf-8'); + + if ( + content.includes('localStorage.getItem') || + content.includes('localStorage.setItem') || + content.includes('localStorage.removeItem') + ) { + filesWithLocalStorage.push(file); + } + } else { + console.log(`File ${file} does not exist.`); + } + } catch (error) { + console.error(`Error reading file ${file}:`, error.message); + } +}; + +files.forEach(checkLocalStorageUsage); + +if (filesWithLocalStorage.length > 0) { + console.error('\x1b[31m%s\x1b[0m', '\nError: Found usage of localStorage'); + console.error('\nFiles with localStorage usage:'); + filesWithLocalStorage.forEach((file) => console.error(file)); + + console.info( + '\x1b[34m%s\x1b[0m', + '\nInfo: Consider using custom hook functions.' + ); + console.info( + 'Please use the getItem, setItem, and removeItem functions provided by the custom hook useLocalStorage.\n' + ); + + process.exit(1); +} diff --git a/scripts/githooks/update-toc.js b/scripts/githooks/update-toc.js new file mode 100644 index 0000000000..268becfd13 --- /dev/null +++ b/scripts/githooks/update-toc.js @@ -0,0 +1,14 @@ +import fs from 'fs'; +import { execSync } from 'child_process'; + +const markdownFiles = fs + .readdirSync('./') + .filter((file) => file.endsWith('.md')); + +markdownFiles.forEach((file) => { + const command = `markdown-toc -i "${file}" --bullets "-"`; + execSync(command, { stdio: 'inherit' }); + +}); + +console.log('Table of contents updated successfully.'); diff --git a/scripts/test.js b/scripts/test.js index 7aefcebd4f..e5858251ff 100644 --- a/scripts/test.js +++ b/scripts/test.js @@ -15,7 +15,6 @@ process.on('unhandledRejection', (err) => { // Ensure environment variables are read. import 'react-scripts/config/env.js'; -// eslint-disable-next-line jest/no-jest-import import jest from 'jest'; import { execSync } from 'child_process'; diff --git a/setup.ts b/setup.ts new file mode 100644 index 0000000000..f930acc13a --- /dev/null +++ b/setup.ts @@ -0,0 +1,177 @@ +import dotenv from 'dotenv'; +import fs from 'fs'; +import inquirer from 'inquirer'; +import { checkConnection } from './src/setup/checkConnection/checkConnection'; +import { askForTalawaApiUrl } from './src/setup/askForTalawaApiUrl/askForTalawaApiUrl'; +import { checkEnvFile } from './src/setup/checkEnvFile/checkEnvFile'; +import { validateRecaptcha } from './src/setup/validateRecaptcha/validateRecaptcha'; +import { askForCustomPort } from './src/setup/askForCustomPort/askForCustomPort'; + +export async function main(): Promise { + console.log('Welcome to the Talawa Admin setup! 🚀'); + + if (!fs.existsSync('.env')) { + fs.openSync('.env', 'w'); + const config = dotenv.parse(fs.readFileSync('.env.example')); + for (const key in config) { + fs.appendFileSync('.env', `${key}=${config[key]}\n`); + } + } else { + checkEnvFile(); + } + + let shouldSetCustomPort: boolean; + + if (process.env.PORT) { + console.log( + `\nCustom port for development server already exists with the value:\n${process.env.PORT}`, + ); + shouldSetCustomPort = true; + } else { + const { shouldSetCustomPortResponse } = await inquirer.prompt({ + type: 'confirm', + name: 'shouldSetCustomPortResponse', + message: 'Would you like to set up a custom port?', + default: true, + }); + shouldSetCustomPort = shouldSetCustomPortResponse; + } + + if (shouldSetCustomPort) { + const customPort = await askForCustomPort(); + + const port = dotenv.parse(fs.readFileSync('.env')).PORT; + + fs.readFile('.env', 'utf8', (err, data) => { + const result = data.replace(`PORT=${port}`, `PORT=${customPort}`); + fs.writeFileSync('.env', result, 'utf8'); + }); + } + + let shouldSetTalawaApiUrl: boolean; + + if (process.env.REACT_APP_TALAWA_URL) { + console.log( + `\nEndpoint for accessing talawa-api graphql service already exists with the value:\n${process.env.REACT_APP_TALAWA_URL}`, + ); + shouldSetTalawaApiUrl = true; + } else { + const { shouldSetTalawaApiUrlResponse } = await inquirer.prompt({ + type: 'confirm', + name: 'shouldSetTalawaApiUrlResponse', + message: 'Would you like to set up talawa-api endpoint?', + default: true, + }); + shouldSetTalawaApiUrl = shouldSetTalawaApiUrlResponse; + } + + if (shouldSetTalawaApiUrl) { + let isConnected = false, + endpoint = ''; + + while (!isConnected) { + endpoint = await askForTalawaApiUrl(); + const url = new URL(endpoint); + isConnected = await checkConnection(url.origin); + } + + const talawaApiUrl = dotenv.parse( + fs.readFileSync('.env'), + ).REACT_APP_TALAWA_URL; + + fs.readFile('.env', 'utf8', (err, data) => { + const result = data.replace( + `REACT_APP_TALAWA_URL=${talawaApiUrl}`, + `REACT_APP_TALAWA_URL=${endpoint}`, + ); + fs.writeFileSync('.env', result, 'utf8'); + }); + } + + const { shouldUseRecaptcha } = await inquirer.prompt({ + type: 'confirm', + name: 'shouldUseRecaptcha', + message: 'Would you like to set up ReCAPTCHA?', + default: true, + }); + + if (shouldUseRecaptcha) { + const useRecaptcha = dotenv.parse( + fs.readFileSync('.env'), + ).REACT_APP_USE_RECAPTCHA; + + fs.readFile('.env', 'utf8', (err, data) => { + const result = data.replace( + `REACT_APP_USE_RECAPTCHA=${useRecaptcha}`, + `REACT_APP_USE_RECAPTCHA=yes`, + ); + fs.writeFileSync('.env', result, 'utf8'); + }); + let shouldSetRecaptchaSiteKey: boolean; + if (process.env.REACT_APP_RECAPTCHA_SITE_KEY) { + console.log( + `\nreCAPTCHA site key already exists with the value ${process.env.REACT_APP_RECAPTCHA_SITE_KEY}`, + ); + shouldSetRecaptchaSiteKey = true; + } else { + const { shouldSetRecaptchaSiteKeyResponse } = await inquirer.prompt({ + type: 'confirm', + name: 'shouldSetRecaptchaSiteKeyResponse', + message: 'Would you like to set up a reCAPTCHA site key?', + default: true, + }); + shouldSetRecaptchaSiteKey = shouldSetRecaptchaSiteKeyResponse; + } + + if (shouldSetRecaptchaSiteKey) { + const { recaptchaSiteKeyInput } = await inquirer.prompt([ + { + type: 'input', + name: 'recaptchaSiteKeyInput', + message: 'Enter your reCAPTCHA site key:', + validate: async (input: string): Promise => { + if (validateRecaptcha(input)) { + return true; + } + return 'Invalid reCAPTCHA site key. Please try again.'; + }, + }, + ]); + + const recaptchaSiteKey = dotenv.parse( + fs.readFileSync('.env'), + ).REACT_APP_RECAPTCHA_SITE_KEY; + + fs.readFile('.env', 'utf8', (err, data) => { + const result = data.replace( + `REACT_APP_RECAPTCHA_SITE_KEY=${recaptchaSiteKey}`, + `REACT_APP_RECAPTCHA_SITE_KEY=${recaptchaSiteKeyInput}`, + ); + fs.writeFileSync('.env', result, 'utf8'); + }); + } + } + + const { shouldLogErrors } = await inquirer.prompt({ + type: 'confirm', + name: 'shouldLogErrors', + message: + 'Would you like to log Compiletime and Runtime errors in the console?', + default: true, + }); + + if (shouldLogErrors) { + const logErrors = dotenv.parse(fs.readFileSync('.env')).ALLOW_LOGS; + + fs.readFile('.env', 'utf8', (err, data) => { + const result = data.replace(`ALLOW_LOGS=${logErrors}`, 'ALLOW_LOGS=YES'); + fs.writeFileSync('.env', result, 'utf8'); + }); + } + + console.log( + '\nCongratulations! Talawa Admin has been successfully setup! 🥂🎉', + ); +} + +main(); diff --git a/src/App.test.tsx b/src/App.test.tsx index f8db73a210..b20f75e1ce 100644 --- a/src/App.test.tsx +++ b/src/App.test.tsx @@ -10,6 +10,9 @@ import { store } from 'state/store'; import { CHECK_AUTH } from 'GraphQl/Queries/Queries'; import i18nForTest from './utils/i18nForTest'; import { StaticMockLink } from 'utils/StaticMockLink'; +import useLocalStorage from 'utils/useLocalstorage'; + +const { setItem } = useLocalStorage(); // Mock the modules for PieChart rendering as they require a trasformer being used (which is not done by Jest) // These modules are used by the Feedback components @@ -32,7 +35,19 @@ const MOCKS = [ lastName: 'Doe', image: 'john.jpg', email: 'johndoe@gmail.com', - userType: 'SUPERADMIN', + birthDate: '1990-01-01', + educationGrade: 'NO_GRADE', + employmentStatus: 'EMPLOYED', + gender: 'MALE', + maritalStatus: 'SINGLE', + address: { + line1: 'line1', + state: 'state', + countryCode: 'IND', + }, + phone: { + mobile: '+8912313112', + }, }, }, }, @@ -52,6 +67,7 @@ async function wait(ms = 100): Promise { describe('Testing the App Component', () => { test('Component should be rendered properly and user is loggedin', async () => { + setItem('AdminFor', [{ name: 'adi', _id: '1234', image: '' }]); render( @@ -61,7 +77,7 @@ describe('Testing the App Component', () => { - + , ); await wait(); @@ -71,8 +87,8 @@ describe('Testing the App Component', () => { expect(window.location).toBeAt('/orglist'); expect( screen.getByText( - 'An open source application by Palisadoes Foundation volunteers' - ) + 'An open source application by Palisadoes Foundation volunteers', + ), ).toBeTruthy(); }); @@ -86,7 +102,7 @@ describe('Testing the App Component', () => { - + , ); await wait(); diff --git a/src/App.tsx b/src/App.tsx index 3daf57b09c..24d52cf65c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,39 +1,51 @@ -import React, { useEffect } from 'react'; -import { Route, Switch } from 'react-router-dom'; -import { useQuery } from '@apollo/client'; -import * as installedPlugins from 'components/plugins/index'; -import { CHECK_AUTH } from 'GraphQl/Queries/Queries'; +import AddOnStore from 'components/AddOn/core/AddOnStore/AddOnStore'; +import OrganizationScreen from 'components/OrganizationScreen/OrganizationScreen'; import SecuredRoute from 'components/SecuredRoute/SecuredRoute'; -import SecuredRouteForUser from 'components/UserPortal/SecuredRouteForUser/SecuredRouteForUser'; +import SuperAdminScreen from 'components/SuperAdminScreen/SuperAdminScreen'; +import * as installedPlugins from 'components/plugins/index'; +import { Route, Routes } from 'react-router-dom'; +import BlockUser from 'screens/BlockUser/BlockUser'; +import EventManagement from 'screens/EventManagement/EventManagement'; +import ForgotPassword from 'screens/ForgotPassword/ForgotPassword'; import LoginPage from 'screens/LoginPage/LoginPage'; -import OrganizationEvents from 'screens/OrganizationEvents/OrganizationEvents'; -import OrganizationPeople from 'screens/OrganizationPeople/OrganizationPeople'; -import OrganizationDashboard from 'screens/OrganizationDashboard/OrganizationDashboard'; +import MemberDetail from 'screens/MemberDetail/MemberDetail'; import OrgContribution from 'screens/OrgContribution/OrgContribution'; import OrgList from 'screens/OrgList/OrgList'; import OrgPost from 'screens/OrgPost/OrgPost'; import OrgSettings from 'screens/OrgSettings/OrgSettings'; +import OrganizationActionItems from 'screens/OrganizationActionItems/OrganizationActionItems'; +import OrganizationDashboard from 'screens/OrganizationDashboard/OrganizationDashboard'; +import OrganizationEvents from 'screens/OrganizationEvents/OrganizationEvents'; +import OrganizaitionFundCampiagn from 'screens/OrganizationFundCampaign/OrganizationFundCampagins'; +import OrganizationFunds from 'screens/OrganizationFunds/OrganizationFunds'; +import OrganizationPeople from 'screens/OrganizationPeople/OrganizationPeople'; import PageNotFound from 'screens/PageNotFound/PageNotFound'; -import AddOnStore from 'components/AddOn/core/AddOnStore/AddOnStore'; -import ForgotPassword from 'screens/ForgotPassword/ForgotPassword'; -import Users from 'screens/Users/Users'; import Requests from 'screens/Requests/Requests'; -import BlockUser from 'screens/BlockUser/BlockUser'; -import EventDashboard from 'screens/EventDashboard/EventDashboard'; -import MemberDetail from 'screens/MemberDetail/MemberDetail'; -import Loader from 'components/Loader/Loader'; +import Users from 'screens/Users/Users'; +import CommunityProfile from 'screens/CommunityProfile/CommunityProfile'; +import OrganizationVenues from 'screens/OrganizationVenues/OrganizationVenues'; +import React, { useEffect } from 'react'; // User Portal Components -import UserLoginPage from 'screens/UserPortal/UserLoginPage/UserLoginPage'; +import Donate from 'screens/UserPortal/Donate/Donate'; +import Events from 'screens/UserPortal/Events/Events'; +import Posts from 'screens/UserPortal/Posts/Posts'; import Organizations from 'screens/UserPortal/Organizations/Organizations'; -import Home from 'screens/UserPortal/Home/Home'; import People from 'screens/UserPortal/People/People'; import Settings from 'screens/UserPortal/Settings/Settings'; -import Donate from 'screens/UserPortal/Donate/Donate'; -import Events from 'screens/UserPortal/Events/Events'; -import Tasks from 'screens/UserPortal/Tasks/Tasks'; +// import UserLoginPage from 'screens/UserPortal/UserLoginPage/UserLoginPage'; // import Chat from 'screens/UserPortal/Chat/Chat'; +import { useQuery } from '@apollo/client'; +import { CHECK_AUTH } from 'GraphQl/Queries/Queries'; import Advertisements from 'components/Advertisements/Advertisements'; +import SecuredRouteForUser from 'components/UserPortal/SecuredRouteForUser/SecuredRouteForUser'; +import FundCampaignPledge from 'screens/FundCampaignPledge/FundCampaignPledge'; + +import useLocalStorage from 'utils/useLocalstorage'; +import UserScreen from 'screens/UserPortal/UserScreen/UserScreen'; +import EventDashboardScreen from 'components/EventDashboardScreen/EventDashboardScreen'; + +const { setItem } = useLocalStorage(); function app(): JSX.Element { /*const { updatePluginLinks, updateInstalled } = bindActionCreators( @@ -65,74 +77,102 @@ function app(): JSX.Element { useEffect(() => { if (data) { - localStorage.setItem( - 'name', - `${data.checkAuth.firstName} ${data.checkAuth.lastName}` - ); - localStorage.setItem('id', data.checkAuth._id); - localStorage.setItem('email', data.checkAuth.email); - localStorage.setItem('IsLoggedIn', 'TRUE'); - localStorage.setItem('UserType', data.checkAuth.userType); - localStorage.setItem('FirstName', data.checkAuth.firstName); - localStorage.setItem('LastName', data.checkAuth.lastName); - localStorage.setItem('UserImage', data.checkAuth.image); - localStorage.setItem('Email', data.checkAuth.email); + setItem('name', `${data.checkAuth.firstName} ${data.checkAuth.lastName}`); + setItem('id', data.checkAuth._id); + setItem('email', data.checkAuth.email); + setItem('IsLoggedIn', 'TRUE'); + setItem('FirstName', data.checkAuth.firstName); + setItem('LastName', data.checkAuth.lastName); + setItem('UserImage', data.checkAuth.image); + setItem('Email', data.checkAuth.email); } }, [data, loading]); const extraRoutes = Object.entries(installedPlugins).map( - (plugin: any, index) => { + ( + plugin: [ + string, + ( + | typeof installedPlugins.DummyPlugin + | typeof installedPlugins.DummyPlugin2 + ), + ], + index: number, + ) => { const extraComponent = plugin[1]; return ( - ); - } + }, ); - if (loading) { - return ; - } return ( <> - - - - - - - - - - - - - - - - - {extraRoutes} - + + } /> + }> + }> + } /> + } /> + } /> + } /> + + }> + } /> + } /> + } /> + } /> + } /> + } + /> + } /> + } + /> + } + /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + {extraRoutes} + + + } /> {/* User Portal Routes */} - - - - - - - - + }> + } /> + } /> + }> + } /> + } /> + } /> + } /> + } /> + }> + } + /> + + + {/* */} - - - + } /> + ); } diff --git a/src/Constant/constant.spec.ts b/src/Constant/constant.spec.ts index c194f51a10..c2e57d29df 100644 --- a/src/Constant/constant.spec.ts +++ b/src/Constant/constant.spec.ts @@ -17,13 +17,13 @@ describe('constants', () => { it('RECAPTCHA_SITE_KEY should be equal to REACT_APP_RECAPTCHA_SITE_KEY environment variable', () => { expect(RECAPTCHA_SITE_KEY).toEqual( - process.env.REACT_APP_RECAPTCHA_SITE_KEY + process.env.REACT_APP_RECAPTCHA_SITE_KEY, ); }); it('REACT_APP_USE_RECAPTCHA should be equal to REACT_APP_USE_RECAPTCHA environment variable', () => { expect(REACT_APP_USE_RECAPTCHA).toEqual( - process.env.REACT_APP_USE_RECAPTCHA + process.env.REACT_APP_USE_RECAPTCHA, ); }); }); diff --git a/src/Constant/constant.ts b/src/Constant/constant.ts index 6582342ecd..d3b0efe1c1 100644 --- a/src/Constant/constant.ts +++ b/src/Constant/constant.ts @@ -2,5 +2,6 @@ export const AUTH_TOKEN = ''; export const BACKEND_URL = process.env.REACT_APP_TALAWA_URL; export const RECAPTCHA_SITE_KEY = process.env.REACT_APP_RECAPTCHA_SITE_KEY; export const REACT_APP_USE_RECAPTCHA = process.env.REACT_APP_USE_RECAPTCHA; +export const REACT_APP_CUSTOM_PORT = process.env.PORT; export const REACT_APP_BACKEND_WEBSOCKET_URL: string = process.env.REACT_APP_BACKEND_WEBSOCKET_URL || ''; diff --git a/src/GraphQl/Mutations/ActionItemCategoryMutations.ts b/src/GraphQl/Mutations/ActionItemCategoryMutations.ts new file mode 100644 index 0000000000..daae836362 --- /dev/null +++ b/src/GraphQl/Mutations/ActionItemCategoryMutations.ts @@ -0,0 +1,39 @@ +import gql from 'graphql-tag'; + +/** + * GraphQL mutation to create an action item category. + * + * @param name - Name of the ActionItemCategory. + * @param organizationId - Organization to which the ActionItemCategory belongs. + */ + +export const CREATE_ACTION_ITEM_CATEGORY_MUTATION = gql` + mutation CreateActionItemCategory($name: String!, $organizationId: ID!) { + createActionItemCategory(name: $name, organizationId: $organizationId) { + _id + } + } +`; + +/** + * GraphQL mutation to update an action item category. + * + * @param id - The id of the ActionItemCategory to be updated. + * @param name - Updated name of the ActionItemCategory. + * @param isDisabled - Updated disabled status of the ActionItemCategory. + */ + +export const UPDATE_ACTION_ITEM_CATEGORY_MUTATION = gql` + mutation UpdateActionItemCategory( + $actionItemCategoryId: ID! + $name: String + $isDisabled: Boolean + ) { + updateActionItemCategory( + id: $actionItemCategoryId + data: { name: $name, isDisabled: $isDisabled } + ) { + _id + } + } +`; diff --git a/src/GraphQl/Mutations/ActionItemMutations.ts b/src/GraphQl/Mutations/ActionItemMutations.ts new file mode 100644 index 0000000000..58dc7756d3 --- /dev/null +++ b/src/GraphQl/Mutations/ActionItemMutations.ts @@ -0,0 +1,85 @@ +import gql from 'graphql-tag'; + +/** + * GraphQL mutation to create an action item. + * + * @param actionItemCategoryId - ActionItemCategory to which the ActionItem is related. + * @param assigneeId - User to whom the ActionItem is assigned. + * @param preCompletionNotes - Notes prior to completion. + * @param dueDate - Due date. + * @param eventId - Event to which the ActionItem is related. + */ + +export const CREATE_ACTION_ITEM_MUTATION = gql` + mutation CreateActionItem( + $actionItemCategoryId: ID! + $assigneeId: ID! + $preCompletionNotes: String + $dueDate: Date + $eventId: ID + ) { + createActionItem( + actionItemCategoryId: $actionItemCategoryId + data: { + assigneeId: $assigneeId + preCompletionNotes: $preCompletionNotes + dueDate: $dueDate + eventId: $eventId + } + ) { + _id + } + } +`; + +/** + * GraphQL mutation to update an action item. + * + * @param id - Id of the ActionItem to be updated. + * @param assigneeId - User to whom the ActionItem is assigned. + * @param preCompletionNotes - Notes prior to completion. + * @param postCompletionNotes - Notes on completion. + * @param dueDate - Due date. + * @param completionDate - Completion date. + * @param isCompleted - Whether the ActionItem has been completed. + */ + +export const UPDATE_ACTION_ITEM_MUTATION = gql` + mutation UpdateActionItem( + $actionItemId: ID! + $assigneeId: ID! + $preCompletionNotes: String + $postCompletionNotes: String + $dueDate: Date + $completionDate: Date + $isCompleted: Boolean + ) { + updateActionItem( + id: $actionItemId + data: { + assigneeId: $assigneeId + preCompletionNotes: $preCompletionNotes + postCompletionNotes: $postCompletionNotes + dueDate: $dueDate + completionDate: $completionDate + isCompleted: $isCompleted + } + ) { + _id + } + } +`; + +/** + * GraphQL mutation to delete an action item. + * + * @param id - Id of the ActionItem to be updated. + */ + +export const DELETE_ACTION_ITEM_MUTATION = gql` + mutation RemoveActionItem($actionItemId: ID!) { + removeActionItem(id: $actionItemId) { + _id + } + } +`; diff --git a/src/GraphQl/Mutations/CampaignMutation.ts b/src/GraphQl/Mutations/CampaignMutation.ts new file mode 100644 index 0000000000..c012141dc8 --- /dev/null +++ b/src/GraphQl/Mutations/CampaignMutation.ts @@ -0,0 +1,87 @@ +import gql from 'graphql-tag'; + +/** + * GraphQL mutation to create a new fund Campaign. + * + * @param name - The name of the fund. + * @param fundId - The fund ID the campaign is associated with. + * @param fundingGoal - The funding goal of the campaign. + * @param startDate - The start date of the campaign. + * @param endDate - The end date of the campaign. + * @param currency - The currency of the campaign. + * @returns The ID of the created campaign. + */ + +export const CREATE_CAMPAIGN_MUTATION = gql` + mutation createFundraisingCampaign( + $fundId: ID! + $name: String! + $fundingGoal: Float! + $startDate: Date! + $endDate: Date! + $currency: Currency! + ) { + createFundraisingCampaign( + data: { + fundId: $fundId + name: $name + fundingGoal: $fundingGoal + startDate: $startDate + endDate: $endDate + currency: $currency + } + ) { + _id + } + } +`; + +/** + * GraphQL mutation to update a fund Campaign. + * + * @param id - The ID of the campaign being updated. + * @param name - The name of the campaign. + * @param fundingGoal - The funding goal of the campaign. + * @param startDate - The start date of the campaign. + * @param endDate - The end date of the campaign. + * @param currency - The currency of the campaign. + * @returns The ID of the updated campaign. + */ + +export const UPDATE_CAMPAIGN_MUTATION = gql` + mutation updateFundraisingCampaign( + $id: ID! + $name: String + $fundingGoal: Float + $startDate: Date + $endDate: Date + $currency: Currency + ) { + updateFundraisingCampaign( + id: $id + data: { + name: $name + fundingGoal: $fundingGoal + startDate: $startDate + endDate: $endDate + currency: $currency + } + ) { + _id + } + } +`; + +/** + * GraphQL mutation to delete a fund Campaign. + * + * @param id - The ID of the campaign being deleted. + * @returns The ID of the deleted campaign. + */ +export const DELETE_CAMPAIGN_MUTATION = gql` + mutation removeFundraisingCampaign($id: ID!) { + removeFundraisingCampaign(id: $id) { + _id + } + } +`; diff --git a/src/GraphQl/Mutations/CommentMutations.ts b/src/GraphQl/Mutations/CommentMutations.ts new file mode 100644 index 0000000000..7a2ca00c83 --- /dev/null +++ b/src/GraphQl/Mutations/CommentMutations.ts @@ -0,0 +1,58 @@ +import gql from 'graphql-tag'; + +/** + * GraphQL mutation to create a new comment on a post. + * + * @param comment - The text content of the comment. + * @param postId - The ID of the post to which the comment is being added. + * @returns The created comment object. + */ + +export const CREATE_COMMENT_POST = gql` + mutation createComment($comment: String!, $postId: ID!) { + createComment(data: { text: $comment }, postId: $postId) { + _id + creator { + _id + firstName + lastName + email + } + likeCount + likedBy { + _id + } + text + } + } +`; + +/** + * GraphQL mutation to like a comment. + * + * @param commentId - The ID of the comment to be liked. + * @returns The liked comment object. + */ + +export const LIKE_COMMENT = gql` + mutation likeComment($commentId: ID!) { + likeComment(id: $commentId) { + _id + } + } +`; + +/** + * GraphQL mutation to unlike a comment. + * + * @param commentId - The ID of the comment to be unliked. + * @returns The unliked comment object. + */ + +export const UNLIKE_COMMENT = gql` + mutation unlikeComment($commentId: ID!) { + unlikeComment(id: $commentId) { + _id + } + } +`; diff --git a/src/GraphQl/Mutations/EventAttendeeMutations.ts b/src/GraphQl/Mutations/EventAttendeeMutations.ts new file mode 100644 index 0000000000..94d7d97705 --- /dev/null +++ b/src/GraphQl/Mutations/EventAttendeeMutations.ts @@ -0,0 +1,49 @@ +import gql from 'graphql-tag'; + +/** + * GraphQL mutation to add an attendee to an event. + * + * @param userId - The ID of the user being added as an attendee. + * @param eventId - The ID of the event to which the user is being added as an attendee. + * @returns The updated event object with the added attendee. + */ + +export const ADD_EVENT_ATTENDEE = gql` + mutation addEventAttendee($userId: ID!, $eventId: ID!) { + addEventAttendee(data: { userId: $userId, eventId: $eventId }) { + _id + } + } +`; + +/** + * GraphQL mutation to remove an attendee from an event. + * + * @param userId - The ID of the user being removed as an attendee. + * @param eventId - The ID of the event from which the user is being removed as an attendee. + * @returns The updated event object without the removed attendee. + */ + +export const REMOVE_EVENT_ATTENDEE = gql` + mutation removeEventAttendee($userId: ID!, $eventId: ID!) { + removeEventAttendee(data: { userId: $userId, eventId: $eventId }) { + _id + } + } +`; + +/** + * GraphQL mutation to mark a user's check-in at an event. + * + * @param userId - The ID of the user checking in. + * @param eventId - The ID of the event at which the user is checking in. + * @returns The updated event object with the user's check-in information. + */ + +export const MARK_CHECKIN = gql` + mutation checkIn($userId: ID!, $eventId: ID!) { + checkIn(data: { userId: $userId, eventId: $eventId }) { + _id + } + } +`; diff --git a/src/GraphQl/Mutations/FundMutation.ts b/src/GraphQl/Mutations/FundMutation.ts new file mode 100644 index 0000000000..45bdc05e96 --- /dev/null +++ b/src/GraphQl/Mutations/FundMutation.ts @@ -0,0 +1,85 @@ +import gql from 'graphql-tag'; + +/** + * GraphQL mutation to create a new fund. + * + * @param name - The name of the fund. + * @param organizationId - The organization ID the fund is associated with. + * @param refrenceNumber - The reference number of the fund. + * @param taxDeductible - Whether the fund is tax deductible. + * @param isArchived - Whether the fund is archived. + * @param isDefault - Whether the fund is the default. + * @returns The ID of the created fund. + */ +export const CREATE_FUND_MUTATION = gql` + mutation CreateFund( + $name: String! + $organizationId: ID! + $refrenceNumber: String + $taxDeductible: Boolean! + $isArchived: Boolean! + $isDefault: Boolean! + ) { + createFund( + data: { + name: $name + organizationId: $organizationId + refrenceNumber: $refrenceNumber + taxDeductible: $taxDeductible + isArchived: $isArchived + isDefault: $isDefault + } + ) { + _id + } + } +`; + +/** + * GraphQL mutation to update a fund. + * + * @param id - The ID of the fund being updated. + * @param name - The name of the fund. + * @param refrenceNumber - The reference number of the fund. + * @param taxDeductible - Whether the fund is tax deductible. + * @param isArchived - Whether the fund is archived. + * @param isDefault - Whether the fund is the default. + * @returns The ID of the updated fund. + */ +export const UPDATE_FUND_MUTATION = gql` + mutation UpdateFund( + $id: ID! + $name: String + $refrenceNumber: String + $taxDeductible: Boolean + $isArchived: Boolean + $isDefault: Boolean + ) { + updateFund( + id: $id + data: { + name: $name + refrenceNumber: $refrenceNumber + taxDeductible: $taxDeductible + isArchived: $isArchived + isDefault: $isDefault + } + ) { + _id + } + } +`; + +/** + * GraphQL mutation to remove a fund. + * + * @param id - The ID of the fund being removed. + * @returns The ID of the removed fund. + */ +export const REMOVE_FUND_MUTATION = gql` + mutation RemoveFund($id: ID!) { + removeFund(id: $id) { + _id + } + } +`; diff --git a/src/GraphQl/Mutations/OrganizationMutations.ts b/src/GraphQl/Mutations/OrganizationMutations.ts new file mode 100644 index 0000000000..c40d259429 --- /dev/null +++ b/src/GraphQl/Mutations/OrganizationMutations.ts @@ -0,0 +1,176 @@ +import gql from 'graphql-tag'; + +// Changes the role of a user in an organization +/** + * GraphQL mutation to update the role of a user in an organization. + * + * @param organizationId - The ID of the organization in which the user's role is being updated. + * @param userId - The ID of the user whose role is being updated. + * @param role - The new role to be assigned to the user in the organization. + * @returns The updated user object with the new role in the organization. + */ +export const UPDATE_USER_ROLE_IN_ORG_MUTATION = gql` + mutation updateUserRoleInOrganization( + $organizationId: ID! + $userId: ID! + $role: String! + ) { + updateUserRoleInOrganization( + organizationId: $organizationId + userId: $userId + role: $role + ) { + _id + } + } +`; + +/** + * GraphQL mutation to create a sample organization. + * + * @returns The created sample organization object. + */ + +export const CREATE_SAMPLE_ORGANIZATION_MUTATION = gql` + mutation { + createSampleOrganization + } +`; + +/** + * GraphQL mutation to remove a sample organization. + * + * @returns The removed sample organization object. + */ + +export const REMOVE_SAMPLE_ORGANIZATION_MUTATION = gql` + mutation { + removeSampleOrganization + } +`; + +/** + * GraphQL mutation to create a direct chat between users in an organization. + * + * @param userIds - An array of user IDs participating in the direct chat. + * @param organizationId - The ID of the organization where the direct chat is created. + * @returns The created direct chat object. + */ + +export const CREATE_DIRECT_CHAT = gql` + mutation createDirectChat($userIds: [ID!]!, $organizationId: ID!) { + createDirectChat( + data: { userIds: $userIds, organizationId: $organizationId } + ) { + _id + } + } +`; +//Plugin WebSocket listner + +/** + * GraphQL subscription to listen for updates on plugins. + * + * @returns An object containing information about the updated plugin. + */ + +export const PLUGIN_SUBSCRIPTION = gql` + subscription onPluginUpdate { + onPluginUpdate { + pluginName + _id + pluginDesc + uninstalledOrgs + } + } +`; + +/** + * GraphQL mutation to toggle the pinned status of a post. + * + * @param id - The ID of the post to be toggled. + * @returns The updated post object with the new pinned status. + */ + +export const TOGGLE_PINNED_POST = gql` + mutation TogglePostPin($id: ID!) { + togglePostPin(id: $id) { + _id + } + } +`; + +/** + * GraphQL mutation to add a custom field to an organization. + * + * @param organizationId - The ID of the organization where the custom field is being added. + * @param type - The type of the custom field (e.g., String, Number). + * @param name - The name of the custom field. + * @returns The added organization custom field object. + */ + +export const ADD_CUSTOM_FIELD = gql` + mutation ($organizationId: ID!, $type: String!, $name: String!) { + addOrganizationCustomField( + organizationId: $organizationId + type: $type + name: $name + ) { + name + type + } + } +`; + +// Handles custom organization fields + +/** + * GraphQL mutation to remove a custom field from an organization. + * + * @param organizationId - The ID of the organization from which the custom field is being removed. + * @param customFieldId - The ID of the custom field to be removed. + * @returns The removed organization custom field object. + */ + +export const REMOVE_CUSTOM_FIELD = gql` + mutation ($organizationId: ID!, $customFieldId: ID!) { + removeOrganizationCustomField( + organizationId: $organizationId + customFieldId: $customFieldId + ) { + type + name + } + } +`; + +export const SEND_MEMBERSHIP_REQUEST = gql` + mutation ($organizationId: ID!) { + sendMembershipRequest(organizationId: $organizationId) { + _id + organization { + _id + name + } + user { + _id + } + } + } +`; + +export const JOIN_PUBLIC_ORGANIZATION = gql` + mutation ($organizationId: ID!) { + joinPublicOrganization(organizationId: $organizationId) { + _id + } + } +`; + +export const CANCEL_MEMBERSHIP_REQUEST = gql` + mutation ($membershipRequestId: ID!) { + cancelMembershipRequest(membershipRequestId: $membershipRequestId) { + _id + } + } +`; diff --git a/src/GraphQl/Mutations/PledgeMutation.ts b/src/GraphQl/Mutations/PledgeMutation.ts new file mode 100644 index 0000000000..aca0663635 --- /dev/null +++ b/src/GraphQl/Mutations/PledgeMutation.ts @@ -0,0 +1,82 @@ +import gql from 'graphql-tag'; + +/** + * GraphQL mutation to create a pledge. + * + * @param campaignId - The ID of the campaign the pledge is associated with. + * @param amount - The amount of the pledge. + * @param currency - The currency of the pledge. + * @param startDate - The start date of the pledge. + * @param endDate - The end date of the pledge. + * @param userIds - The IDs of the users associated with the pledge. + * @returns The ID of the created pledge. + */ +export const CREATE_PlEDGE = gql` + mutation CreateFundraisingCampaignPledge( + $campaignId: ID! + $amount: Float! + $currency: Currency! + $startDate: Date! + $endDate: Date! + $userIds: [ID!]! + ) { + createFundraisingCampaignPledge( + data: { + campaignId: $campaignId + amount: $amount + currency: $currency + startDate: $startDate + endDate: $endDate + userIds: $userIds + } + ) { + _id + } + } +`; + +/** + * GraphQL mutation to update a pledge. + * + * @param id - The ID of the pledge being updated. + * @param amount - The amount of the pledge. + * @param currency - The currency of the pledge. + * @param startDate - The start date of the pledge. + * @param endDate - The end date of the pledge. + * @returns The ID of the updated pledge. + */ +export const UPDATE_PLEDGE = gql` + mutation UpdateFundraisingCampaignPledge( + $id: ID! + $amount: Float + $currency: Currency + $startDate: Date + $endDate: Date + ) { + updateFundraisingCampaignPledge( + id: $id + data: { + amount: $amount + currency: $currency + startDate: $startDate + endDate: $endDate + } + ) { + _id + } + } +`; + +/** + * GraphQL mutation to delete a pledge. + * + * @param id - The ID of the pledge being deleted. + * @returns Whether the pledge was successfully deleted. + */ +export const DELETE_PLEDGE = gql` + mutation DeleteFundraisingCampaignPledge($id: ID!) { + removeFundraisingCampaignPledge(id: $id) { + _id + } + } +`; diff --git a/src/GraphQl/Mutations/VenueMutations.ts b/src/GraphQl/Mutations/VenueMutations.ts new file mode 100644 index 0000000000..44ccc1f63e --- /dev/null +++ b/src/GraphQl/Mutations/VenueMutations.ts @@ -0,0 +1,79 @@ +import gql from 'graphql-tag'; + +/** + * GraphQL mutation to create a venue. + * + * @param name - Name of the venue. + * @param capacity - Ineteger representing capacity of venue. + * @param description - Description of the venue. + * @param file - Image file for the venue. + * @param organizationId - Organization to which the ActionItemCategory belongs. + */ + +export const CREATE_VENUE_MUTATION = gql` + mutation createVenue( + $capacity: Int! + $description: String + $file: String + $name: String! + $organizationId: ID! + ) { + createVenue( + data: { + capacity: $capacity + description: $description + file: $file + name: $name + organizationId: $organizationId + } + ) { + _id + } + } +`; + +/** + * GraphQL mutation to update a venue. + * + * @param id - The id of the Venue to be updated. + * @param capacity - Ineteger representing capacity of venue. + * @param description - Description of the venue. + * @param file - Image file for the venue. + * @param name - Name of the venue. + */ + +export const UPDATE_VENUE_MUTATION = gql` + mutation editVenue( + $capacity: Int + $description: String + $file: String + $id: ID! + $name: String + ) { + editVenue( + data: { + capacity: $capacity + description: $description + file: $file + id: $id + name: $name + } + ) { + _id + } + } +`; + +/** + * GraphQL mutation to delete a venue. + * + * @param id - The id of the Venue to be deleted. + */ + +export const DELETE_VENUE_MUTATION = gql` + mutation DeleteVenue($id: ID!) { + deleteVenue(id: $id) { + _id + } + } +`; diff --git a/src/GraphQl/Mutations/mutations.ts b/src/GraphQl/Mutations/mutations.ts index 720d655b53..c5d0ea1c1a 100644 --- a/src/GraphQl/Mutations/mutations.ts +++ b/src/GraphQl/Mutations/mutations.ts @@ -1,9 +1,5 @@ import gql from 'graphql-tag'; -// List of the mutations used in the code - -// to unblock the user - export const UNBLOCK_USER_MUTATION = gql` mutation UnblockUser($userId: ID!, $orgId: ID!) { unblockUser(organizationId: $orgId, userId: $userId) { @@ -49,8 +45,8 @@ export const UPDATE_ORGANIZATION_MUTATION = gql` $id: ID! $name: String $description: String - $location: String - $isPublic: Boolean + $address: AddressInput + $userRegistrationRequired: Boolean $visibleInSearch: Boolean $file: String ) { @@ -59,9 +55,9 @@ export const UPDATE_ORGANIZATION_MUTATION = gql` data: { name: $name description: $description - isPublic: $isPublic + userRegistrationRequired: $userRegistrationRequired visibleInSearch: $visibleInSearch - location: $location + address: $address } file: $file ) { @@ -70,18 +66,52 @@ export const UPDATE_ORGANIZATION_MUTATION = gql` } `; +// fragment for defining the Address input type. +export const ADDRESS_DETAILS_FRAGMENT = gql` + fragment AddressDetails on AddressInput { + city: String + countryCode: String + dependentLocality: String + line1: String + line2: String + postalCode: String + sortingCode: String + state: String + } +`; + // to update the details of the user export const UPDATE_USER_MUTATION = gql` mutation UpdateUserProfile( $firstName: String $lastName: String + $gender: Gender $email: EmailAddress - $file: String + $phoneNumber: PhoneNumber + $birthDate: Date + $grade: EducationGrade + $empStatus: EmploymentStatus + $maritalStatus: MaritalStatus + $address: String + $state: String + $country: String + $image: String ) { updateUserProfile( - data: { firstName: $firstName, lastName: $lastName, email: $email } - file: $file + data: { + firstName: $firstName + lastName: $lastName + gender: $gender + email: $email + phone: { mobile: $phoneNumber } + birthDate: $birthDate + educationGrade: $grade + employmentStatus: $empStatus + maritalStatus: $maritalStatus + address: { line1: $address, state: $state, countryCode: $country } + } + file: $image ) { _id } @@ -103,7 +133,9 @@ export const UPDATE_USER_PASSWORD_MUTATION = gql` confirmNewPassword: $confirmNewPassword } ) { - _id + user { + _id + } } } `; @@ -116,6 +148,7 @@ export const SIGNUP_MUTATION = gql` $lastName: String! $email: EmailAddress! $password: String! + $orgId: ID! ) { signUp( data: { @@ -123,6 +156,7 @@ export const SIGNUP_MUTATION = gql` lastName: $lastName email: $email password: $password + selectedOrganization: $orgId } ) { user { @@ -141,8 +175,16 @@ export const LOGIN_MUTATION = gql` login(data: { email: $email, password: $password }) { user { _id - userType - adminApproved + firstName + lastName + image + email + } + appUserProfile { + adminFor { + _id + } + isSuperAdmin } accessToken refreshToken @@ -182,19 +224,19 @@ export const RECAPTCHA_MUTATION = gql` export const CREATE_ORGANIZATION_MUTATION = gql` mutation CreateOrganization( $description: String! - $location: String! + $address: AddressInput! $name: String! $visibleInSearch: Boolean! - $isPublic: Boolean! + $userRegistrationRequired: Boolean! $image: String ) { createOrganization( data: { description: $description - location: $location + address: $address name: $name visibleInSearch: $visibleInSearch - isPublic: $isPublic + userRegistrationRequired: $userRegistrationRequired } file: $image ) { @@ -208,7 +250,9 @@ export const CREATE_ORGANIZATION_MUTATION = gql` export const DELETE_ORGANIZATION_MUTATION = gql` mutation RemoveOrganization($id: ID!) { removeOrganization(id: $id) { - _id + user { + _id + } } } `; @@ -224,11 +268,18 @@ export const CREATE_EVENT_MUTATION = gql` $isRegisterable: Boolean! $organizationId: ID! $startDate: Date! - $endDate: Date + $endDate: Date! $allDay: Boolean! $startTime: Time $endTime: Time $location: String + $recurrenceStartDate: Date + $recurrenceEndDate: Date + $frequency: Frequency + $weekDays: [WeekDays] + $count: PositiveInt + $interval: PositiveInt + $weekDayOccurenceInMonth: Int ) { createEvent( data: { @@ -245,6 +296,15 @@ export const CREATE_EVENT_MUTATION = gql` endTime: $endTime location: $location } + recurrenceRuleData: { + recurrenceStartDate: $recurrenceStartDate + recurrenceEndDate: $recurrenceEndDate + frequency: $frequency + weekDays: $weekDays + interval: $interval + count: $count + weekDayOccurenceInMonth: $weekDayOccurenceInMonth + } ) { _id } @@ -254,15 +314,17 @@ export const CREATE_EVENT_MUTATION = gql` // to delete any event by any organization export const DELETE_EVENT_MUTATION = gql` - mutation RemoveEvent($id: ID!) { - removeEvent(id: $id) { + mutation RemoveEvent( + $id: ID! + $recurringEventDeleteType: RecurringEventMutationType + ) { + removeEvent(id: $id, recurringEventDeleteType: $recurringEventDeleteType) { _id } } `; // to remove an admin from an organization - export const REMOVE_ADMIN_MUTATION = gql` mutation RemoveAdmin($orgid: ID!, $userid: ID!) { removeAdmin(data: { organizationId: $orgid, userId: $userid }) { @@ -272,7 +334,6 @@ export const REMOVE_ADMIN_MUTATION = gql` `; // to Remove member from an organization - export const REMOVE_MEMBER_MUTATION = gql` mutation RemoveMember($orgid: ID!, $userid: ID!) { removeMember(data: { organizationId: $orgid, userId: $userid }) { @@ -282,7 +343,6 @@ export const REMOVE_MEMBER_MUTATION = gql` `; // to add the admin - export const ADD_ADMIN_MUTATION = gql` mutation CreateAdmin($orgid: ID!, $userid: ID!) { createAdmin(data: { organizationId: $orgid, userId: $userid }) { @@ -291,6 +351,16 @@ export const ADD_ADMIN_MUTATION = gql` } `; +export const ADD_MEMBER_MUTATION = gql` + mutation CreateMember($orgid: ID!, $userid: ID!) { + createMember(input: { organizationId: $orgid, userId: $userid }) { + organization { + _id + } + } + } +`; + export const CREATE_POST_MUTATION = gql` mutation CreatePost( $text: String! @@ -299,6 +369,7 @@ export const CREATE_POST_MUTATION = gql` $videoUrl: URL $organizationId: ID! $file: String + $pinned: Boolean ) { createPost( data: { @@ -307,6 +378,7 @@ export const CREATE_POST_MUTATION = gql` imageUrl: $imageUrl videoUrl: $videoUrl organizationId: $organizationId + pinned: $pinned } file: $file ) { @@ -347,27 +419,10 @@ export const FORGOT_PASSWORD_MUTATION = gql` } `; -export const UPDATE_USERTYPE_MUTATION = gql` - mutation UpdateUserType($id: ID!, $userType: String!) { - updateUserType(data: { id: $id, userType: $userType }) - } -`; - -export const ACCEPT_ADMIN_MUTATION = gql` - mutation AcceptAdmin($id: ID!) { - acceptAdmin(id: $id) - } -`; - -export const REJECT_ADMIN_MUTATION = gql` - mutation RejectAdmin($id: ID!) { - rejectAdmin(id: $id) - } -`; - /** - * @name UPDATE_INSTALL_STATUS_PLUGIN_MUTATION - * @description used to toggle `installStatus` (boolean value) of a Plugin + * {@label UPDATE_INSTALL_STATUS_PLUGIN_MUTATION} + * @remarks + * used to toggle `installStatus` (boolean value) of a Plugin */ export const UPDATE_INSTALL_STATUS_PLUGIN_MUTATION = gql` mutation ($id: ID!, $orgId: ID!) { @@ -382,8 +437,9 @@ export const UPDATE_INSTALL_STATUS_PLUGIN_MUTATION = gql` `; /** - * @name UPDATE_ORG_STATUS_PLUGIN_MUTATION - * @description used `updatePluginStatus`to add or remove the current Organization the in the plugin list `uninstalledOrgs` + * {@label UPDATE_ORG_STATUS_PLUGIN_MUTATION} + * @remarks + * used `updatePluginStatus`to add or remove the current Organization the in the plugin list `uninstalledOrgs` */ export const UPDATE_ORG_STATUS_PLUGIN_MUTATION = gql` mutation update_install_status_plugin_mutation($id: ID!, $orgId: ID!) { @@ -398,8 +454,9 @@ export const UPDATE_ORG_STATUS_PLUGIN_MUTATION = gql` `; /** - * @name ADD_PLUGIN_MUTATION - * @description used `createPlugin` to add new Plugin in database + * {@label ADD_PLUGIN_MUTATION} + * @remarks + * used `createPlugin` to add new Plugin in database */ export const ADD_PLUGIN_MUTATION = gql` mutation add_plugin_mutation( @@ -421,29 +478,60 @@ export const ADD_PLUGIN_MUTATION = gql` `; export const ADD_ADVERTISEMENT_MUTATION = gql` mutation ( - $orgId: ID! + $organizationId: ID! $name: String! - $link: String! - $type: String! + $type: AdvertisementType! $startDate: Date! $endDate: Date! + $file: String! ) { createAdvertisement( - orgId: $orgId - name: $name - link: $link - type: $type - startDate: $startDate - endDate: $endDate + input: { + organizationId: $organizationId + name: $name + type: $type + startDate: $startDate + endDate: $endDate + mediaFile: $file + } ) { - _id + advertisement { + _id + } + } + } +`; +export const UPDATE_ADVERTISEMENT_MUTATION = gql` + mutation UpdateAdvertisement( + $id: ID! + $name: String + $file: String + $type: AdvertisementType + $startDate: Date + $endDate: Date + ) { + updateAdvertisement( + input: { + _id: $id + name: $name + mediaFile: $file + type: $type + startDate: $startDate + endDate: $endDate + } + ) { + advertisement { + _id + } } } `; export const DELETE_ADVERTISEMENT_BY_ID = gql` mutation ($id: ID!) { - deleteAdvertisementById(id: $id) { - success + deleteAdvertisement(id: $id) { + advertisement { + _id + } } } `; @@ -472,15 +560,25 @@ export const UPDATE_POST_MUTATION = gql` export const UPDATE_EVENT_MUTATION = gql` mutation UpdateEvent( $id: ID! - $title: String! - $description: String! - $recurring: Boolean! - $isPublic: Boolean! - $isRegisterable: Boolean! - $allDay: Boolean! + $title: String + $description: String + $recurring: Boolean + $recurringEventUpdateType: RecurringEventMutationType + $isPublic: Boolean + $isRegisterable: Boolean + $allDay: Boolean + $startDate: Date + $endDate: Date $startTime: Time $endTime: Time $location: String + $recurrenceStartDate: Date + $recurrenceEndDate: Date + $frequency: Frequency + $weekDays: [WeekDays] + $count: PositiveInt + $interval: PositiveInt + $weekDayOccurenceInMonth: Int ) { updateEvent( id: $id @@ -491,10 +589,22 @@ export const UPDATE_EVENT_MUTATION = gql` isPublic: $isPublic isRegisterable: $isRegisterable allDay: $allDay + startDate: $startDate + endDate: $endDate startTime: $startTime endTime: $endTime location: $location } + recurrenceRuleData: { + recurrenceStartDate: $recurrenceStartDate + recurrenceEndDate: $recurrenceEndDate + frequency: $frequency + weekDays: $weekDays + interval: $interval + count: $count + weekDayOccurenceInMonth: $weekDayOccurenceInMonth + } + recurringEventUpdateType: $recurringEventUpdateType ) { _id } @@ -525,218 +635,86 @@ export const REGISTER_EVENT = gql` } `; -export const ADD_EVENT_PROJECT_MUTATION = gql` - mutation AddEventProject( - $title: String! - $description: String! - $eventId: ID! - ) { - createEventProject( - data: { title: $title, description: $description, eventId: $eventId } - ) { - _id - } - } -`; - -export const UPDATE_EVENT_PROJECT_MUTATION = gql` - mutation UpdateEventProject($title: String, $description: String, $id: ID!) { - updateEventProject( - id: $id - data: { title: $title, description: $description } - ) { - _id - } +export const UPDATE_COMMUNITY = gql` + mutation updateCommunity($data: UpdateCommunityInput!) { + updateCommunity(data: $data) } `; -export const DELETE_EVENT_PROJECT_MUTATION = gql` - mutation DeleteEventProject($id: ID!) { - removeEventProject(id: $id) { - _id - } +export const RESET_COMMUNITY = gql` + mutation resetCommunity { + resetCommunity } `; -export const ADD_EVENT_PROJECT_TASK_MUTATION = gql` - mutation AddEventTask( - $title: String! - $description: String! - $projectId: ID! - $deadline: DateTime! - ) { - createTask( - eventProjectId: $projectId - data: { title: $title, description: $description, deadline: $deadline } - ) { - _id - } - } -`; - -export const UPDATE_EVENT_PROJECT_TASK_MUTATION = gql` - mutation UpdateEventTask( - $title: String! - $description: String! - $taskId: ID! - $deadline: DateTime! - $completed: Boolean! - ) { - updateTask( - id: $taskId - data: { - title: $title - description: $description - deadline: $deadline - completed: $completed - } - ) { - _id - } - } -`; - -export const DELETE_EVENT_TASK_MUTATION = gql` - mutation DeleteTask($id: ID!) { - removeTask(id: $id) { - _id - } - } -`; - -export const SET_TASK_VOLUNTEERS_MUTATION = gql` - mutation SetTaskVolunteers($id: ID!, $volunteers: [ID]!) { - setTaskVolunteers(id: $id, volunteers: $volunteers) { - _id - } - } -`; - -export const ADD_EVENT_ATTENDEE = gql` - mutation addEventAttendee($userId: ID!, $eventId: ID!) { - addEventAttendee(data: { userId: $userId, eventId: $eventId }) { - _id - } - } -`; - -export const REMOVE_EVENT_ATTENDEE = gql` - mutation removeEventAttendee($userId: ID!, $eventId: ID!) { - removeEventAttendee(data: { userId: $userId, eventId: $eventId }) { - _id - } - } -`; - -export const MARK_CHECKIN = gql` - mutation checkIn( +export const DONATE_TO_ORGANIZATION = gql` + mutation donate( $userId: ID! - $eventId: ID! - $allotedRoom: String - $allotedSeat: String + $createDonationOrgId2: ID! + $payPalId: ID! + $nameOfUser: String! + $amount: Float! + $nameOfOrg: String! ) { - checkIn( - data: { - userId: $userId - eventId: $eventId - allotedRoom: $allotedRoom - allotedSeat: $allotedSeat - } - ) { - _id - } - } -`; - -export const CREATE_COMMENT_POST = gql` - mutation createComment($comment: String!, $postId: ID!) { - createComment(data: { text: $comment }, postId: $postId) { - _id - creator { - _id - firstName - lastName - email - } - likeCount - likedBy { - _id - } - text - } - } -`; - -export const LIKE_COMMENT = gql` - mutation likeComment($commentId: ID!) { - likeComment(id: $commentId) { - _id - } - } -`; - -export const UNLIKE_COMMENT = gql` - mutation unlikeComment($commentId: ID!) { - unlikeComment(id: $commentId) { - _id - } - } -`; - -// Changes the role of a user in an organization -export const UPDATE_USER_ROLE_IN_ORG_MUTATION = gql` - mutation updateUserRoleInOrganization( - $organizationId: ID! - $userId: ID! - $role: String! - ) { - updateUserRoleInOrganization( - organizationId: $organizationId + createDonation( userId: $userId - role: $role + orgId: $createDonationOrgId2 + payPalId: $payPalId + nameOfUser: $nameOfUser + amount: $amount + nameOfOrg: $nameOfOrg ) { _id + amount + nameOfUser + nameOfOrg } } `; -export const CREATE_SAMPLE_ORGANIZATION_MUTATION = gql` - mutation { - createSampleOrganization - } -`; +// Create and Update Action Item Categories +export { + CREATE_ACTION_ITEM_CATEGORY_MUTATION, + UPDATE_ACTION_ITEM_CATEGORY_MUTATION, +} from './ActionItemCategoryMutations'; -export const REMOVE_SAMPLE_ORGANIZATION_MUTATION = gql` - mutation { - removeSampleOrganization - } -`; +// Create, Update and Delete Action Items +export { + CREATE_ACTION_ITEM_MUTATION, + DELETE_ACTION_ITEM_MUTATION, + UPDATE_ACTION_ITEM_MUTATION, +} from './ActionItemMutations'; -export const CREATE_DIRECT_CHAT = gql` - mutation createDirectChat($userIds: [ID!]!, $organizationId: ID!) { - createDirectChat( - data: { userIds: $userIds, organizationId: $organizationId } - ) { - _id - } - } -`; +// Changes the role of a event in an organization and add and remove the event from the organization +export { + ADD_EVENT_ATTENDEE, + MARK_CHECKIN, + REMOVE_EVENT_ATTENDEE, +} from './EventAttendeeMutations'; -//Plugin WebSocket listner -export const PLUGIN_SUBSCRIPTION = gql` - subscription onPluginUpdate { - onPluginUpdate { - pluginName - _id - pluginDesc - uninstalledOrgs - } - } -`; -export const TOGGLE_PINNED_POST = gql` - mutation TogglePostPin($id: ID!) { - togglePostPin(id: $id) { - _id - } - } -`; +// Create the new comment on a post and Like and Unlike the comment +export { + CREATE_COMMENT_POST, + LIKE_COMMENT, + UNLIKE_COMMENT, +} from './CommentMutations'; + +// Changes the role of a user in an organization +export { + ADD_CUSTOM_FIELD, + CREATE_DIRECT_CHAT, + CREATE_SAMPLE_ORGANIZATION_MUTATION, + JOIN_PUBLIC_ORGANIZATION, + PLUGIN_SUBSCRIPTION, + REMOVE_CUSTOM_FIELD, + REMOVE_SAMPLE_ORGANIZATION_MUTATION, + SEND_MEMBERSHIP_REQUEST, + TOGGLE_PINNED_POST, + UPDATE_USER_ROLE_IN_ORG_MUTATION, +} from './OrganizationMutations'; + +export { + CREATE_VENUE_MUTATION, + DELETE_VENUE_MUTATION, + UPDATE_VENUE_MUTATION, +} from './VenueMutations'; diff --git a/src/GraphQl/Queries/ActionItemCategoryQueries.ts b/src/GraphQl/Queries/ActionItemCategoryQueries.ts new file mode 100644 index 0000000000..50c526f129 --- /dev/null +++ b/src/GraphQl/Queries/ActionItemCategoryQueries.ts @@ -0,0 +1,18 @@ +import gql from 'graphql-tag'; + +/** + * GraphQL query to retrieve action item categories by organization. + * + * @param organizationId - The ID of the organization for which action item categories are being retrieved. + * @returns The list of action item categories associated with the organization. + */ + +export const ACTION_ITEM_CATEGORY_LIST = gql` + query ActionItemCategoriesByOrganization($organizationId: ID!) { + actionItemCategoriesByOrganization(organizationId: $organizationId) { + _id + name + isDisabled + } + } +`; diff --git a/src/GraphQl/Queries/ActionItemQueries.ts b/src/GraphQl/Queries/ActionItemQueries.ts new file mode 100644 index 0000000000..0ce9f1acab --- /dev/null +++ b/src/GraphQl/Queries/ActionItemQueries.ts @@ -0,0 +1,103 @@ +import gql from 'graphql-tag'; + +/** + * GraphQL query to retrieve action item categories by organization. + * + * @param organizationId - The ID of the organization for which action item categories are being retrieved. + * @param orderBy - Sort action items Latest/Earliest first. + * @param actionItemCategory_id - Filter action items belonging to an action item category. + * @param event_id - Filter action items belonging to an event. + * @param is_active - Filter all the active action items. + * @param is_completed - Filter all the completed action items. + * @returns The list of action item categories associated with the organization. + */ + +export const ACTION_ITEM_LIST = gql` + query ActionItemsByOrganization( + $organizationId: ID! + $actionItemCategoryId: ID + $eventId: ID + $isActive: Boolean + $isCompleted: Boolean + $orderBy: ActionItemsOrderByInput + ) { + actionItemsByOrganization( + organizationId: $organizationId + orderBy: $orderBy + where: { + actionItemCategory_id: $actionItemCategoryId + event_id: $eventId + is_active: $isActive + is_completed: $isCompleted + } + ) { + _id + assignee { + _id + firstName + lastName + } + assigner { + _id + firstName + lastName + } + actionItemCategory { + _id + name + } + preCompletionNotes + postCompletionNotes + assignmentDate + dueDate + completionDate + isCompleted + event { + _id + title + } + creator { + _id + firstName + lastName + } + } + } +`; + +export const ACTION_ITEM_LIST_BY_EVENTS = gql` + query actionItemsByEvent($eventId: ID!) { + actionItemsByEvent(eventId: $eventId) { + _id + assignee { + _id + firstName + lastName + } + assigner { + _id + firstName + lastName + } + actionItemCategory { + _id + name + } + preCompletionNotes + postCompletionNotes + assignmentDate + dueDate + completionDate + isCompleted + event { + _id + title + } + creator { + _id + firstName + lastName + } + } + } +`; diff --git a/src/GraphQl/Queries/OrganizationQueries.ts b/src/GraphQl/Queries/OrganizationQueries.ts new file mode 100644 index 0000000000..2d199359bf --- /dev/null +++ b/src/GraphQl/Queries/OrganizationQueries.ts @@ -0,0 +1,320 @@ +// OrganizationQueries.js +import gql from 'graphql-tag'; + +// display posts + +/** + * GraphQL query to retrieve the list of organizations. + * + * @param first - Optional. Number of organizations to retrieve in the first batch. + * @param skip - Optional. Number of organizations to skip before starting to collect the result set. + * @param filter - Optional. Filter organizations by a specified string. + * @param id - Optional. The ID of a specific organization to retrieve. + * @returns The list of organizations based on the applied filters. + */ +export const ORGANIZATION_POST_LIST = gql` + query Organizations( + $id: ID! + $after: String + $before: String + $first: PositiveInt + $last: PositiveInt + ) { + organizations(id: $id) { + posts(after: $after, before: $before, first: $first, last: $last) { + edges { + node { + _id + title + text + imageUrl + videoUrl + creator { + _id + firstName + lastName + email + } + createdAt + likeCount + likedBy { + _id + firstName + lastName + } + commentCount + comments { + _id + text + creator { + _id + } + createdAt + likeCount + likedBy { + _id + } + } + pinned + } + cursor + } + pageInfo { + startCursor + endCursor + hasNextPage + hasPreviousPage + } + totalCount + } + } + } +`; + +export const ORGANIZATION_ADVERTISEMENT_LIST = gql` + query Organizations( + $id: ID! + $after: String + $before: String + $first: Int + $last: Int + ) { + organizations(id: $id) { + _id + advertisements( + after: $after + before: $before + first: $first + last: $last + ) { + edges { + node { + _id + name + startDate + endDate + mediaUrl + } + cursor + } + pageInfo { + startCursor + endCursor + hasNextPage + hasPreviousPage + } + totalCount + } + } + } +`; + +/** + * GraphQL query to retrieve organizations based on user connection. + * + * @param first - Optional. Number of organizations to retrieve in the first batch. + * @param skip - Optional. Number of organizations to skip before starting to collect the result set. + * @param filter - Optional. Filter organizations by a specified string. + * @param id - Optional. The ID of a specific organization to retrieve. + * @returns The list of organizations based on the applied filters. + */ + +export const USER_ORGANIZATION_CONNECTION = gql` + query organizationsConnection( + $first: Int + $skip: Int + $filter: String + $id: ID + ) { + organizationsConnection( + first: $first + skip: $skip + where: { name_contains: $filter, id: $id } + orderBy: name_ASC + ) { + _id + name + image + description + userRegistrationRequired + creator { + firstName + lastName + } + members { + _id + } + admins { + _id + } + createdAt + address { + city + countryCode + dependentLocality + line1 + line2 + postalCode + sortingCode + state + } + membershipRequests { + _id + user { + _id + } + } + } + } +`; + +/** + * GraphQL query to retrieve organizations joined by a user. + * + * @param id - The ID of the user for which joined organizations are being retrieved. + * @returns The list of organizations joined by the user. + */ + +export const USER_JOINED_ORGANIZATIONS = gql` + query UserJoinedOrganizations($id: ID!) { + users(where: { id: $id }) { + user { + joinedOrganizations { + _id + name + description + image + members { + _id + } + address { + city + countryCode + dependentLocality + line1 + line2 + postalCode + sortingCode + state + } + admins { + _id + } + } + } + } + } +`; + +/** + * GraphQL query to retrieve organizations created by a user. + * + * @param id - The ID of the user for which created organizations are being retrieved. + * @returns The list of organizations created by the user. + */ + +export const USER_CREATED_ORGANIZATIONS = gql` + query UserCreatedOrganizations($id: ID!) { + users(where: { id: $id }) { + appUserProfile { + createdOrganizations { + _id + name + description + image + members { + _id + } + address { + city + countryCode + dependentLocality + line1 + line2 + postalCode + sortingCode + state + } + admins { + _id + } + } + } + } + } +`; + +/** + * GraphQL query to retrieve the list of admins for a specific organization. + * + * @param id - The ID of the organization for which admins are being retrieved. + * @returns The list of admins associated with the organization. + */ + +export const ORGANIZATION_ADMINS_LIST = gql` + query Organizations($id: ID!) { + organizations(id: $id) { + _id + admins { + _id + image + firstName + lastName + email + } + } + } +`; + +/** + * GraphQL query to retrieve the list of members for a specific organization. + * + * @param id - The ID of the organization for which members are being retrieved. + * @returns The list of members associated with the organization. + */ +export const ORGANIZATION_FUNDS = gql` + query Organizations($id: ID!) { + organizations(id: $id) { + funds { + _id + name + refrenceNumber + taxDeductible + isArchived + isDefault + createdAt + } + } + } +`; + +/** + * GraphQL query to retrieve the list of venues for a specific organization. + * + * @param id - The ID of the organization for which venues are being retrieved. + * @returns The list of venues associated with the organization. + */ +export const VENUE_LIST = gql` + query GetVenueByOrgId( + $orgId: ID! + $first: Int + $orderBy: VenueOrderByInput + $where: VenueWhereInput + ) { + getVenueByOrgId( + orgId: $orgId + first: $first + orderBy: $orderBy + where: $where + ) { + _id + capacity + name + description + imageUrl + organization { + _id + } + } + } +`; diff --git a/src/GraphQl/Queries/PlugInQueries.ts b/src/GraphQl/Queries/PlugInQueries.ts new file mode 100644 index 0000000000..ff908ac57f --- /dev/null +++ b/src/GraphQl/Queries/PlugInQueries.ts @@ -0,0 +1,179 @@ +import gql from 'graphql-tag'; + +/** + * GraphQL query to retrieve a list of plugins. + * + * @returns The list of plugins with details such as ID, name, creator, description, and uninstalled organizations. + */ + +export const PLUGIN_GET = gql` + query getPluginList { + getPlugins { + _id + pluginName + pluginCreatedBy + pluginDesc + uninstalledOrgs + } + } +`; + +/** + * GraphQL query to retrieve a list of advertisements. + * + * @returns The list of advertisements with details such as ID, name, type, organization ID, link, start date, and end date. + */ + +export const ADVERTISEMENTS_GET = gql` + query getAdvertisements { + advertisementsConnection { + edges { + node { + _id + name + type + organization { + _id + } + mediaUrl + endDate + startDate + } + } + } + } +`; + +/** + * GraphQL query to retrieve a list of events based on organization connection. + * + * @param organization_id - The ID of the organization for which events are being retrieved. + * @param title_contains - Optional. Filter events by title containing a specified string. + * @param description_contains - Optional. Filter events by description containing a specified string. + * @param location_contains - Optional. Filter events by location containing a specified string. + * @param first - Optional. Number of events to retrieve in the first batch. + * @param skip - Optional. Number of events to skip before starting to collect the result set. + * @returns The list of events associated with the organization based on the applied filters. + */ + +export const ORGANIZATION_EVENTS_CONNECTION = gql` + query EventsByOrganizationConnection( + $organization_id: ID! + $title_contains: String + $description_contains: String + $location_contains: String + $first: Int + $skip: Int + ) { + eventsByOrganizationConnection( + where: { + organization_id: $organization_id + title_contains: $title_contains + description_contains: $description_contains + location_contains: $location_contains + } + first: $first + skip: $skip + ) { + _id + title + description + startDate + endDate + location + startTime + endTime + allDay + recurring + isPublic + isRegisterable + creator { + _id + firstName + lastName + } + attendees { + _id + } + } + } +`; + +/** + * GraphQL query to retrieve a list of direct chats based on user ID. + * + * @param id - The ID of the user for which direct chats are being retrieved. + * @returns The list of direct chats associated with the user, including details such as ID, creator, messages, organization, and participating users. + */ + +export const DIRECT_CHATS_LIST = gql` + query DirectChatsByUserID($id: ID!) { + directChatsByUserID(id: $id) { + _id + creator { + _id + firstName + lastName + email + } + messages { + _id + createdAt + messageContent + receiver { + _id + firstName + lastName + email + } + sender { + _id + firstName + lastName + email + } + } + organization { + _id + name + } + users { + _id + firstName + lastName + email + image + } + } + } +`; + +/** + * GraphQL query to check if an organization is a sample organization. + * + * @param isSampleOrganizationId - The ID of the organization being checked. + * @returns A boolean indicating whether the organization is a sample organization. + */ + +export const IS_SAMPLE_ORGANIZATION_QUERY = gql` + query ($isSampleOrganizationId: ID!) { + isSampleOrganization(id: $isSampleOrganizationId) + } +`; + +/** + * GraphQL query to retrieve custom fields for a specific organization. + * + * @param customFieldsByOrganizationId - The ID of the organization for which custom fields are being retrieved. + * @returns The list of custom fields associated with the organization, including details such as ID, type, and name. + */ + +export const ORGANIZATION_CUSTOM_FIELDS = gql` + query ($customFieldsByOrganizationId: ID!) { + customFieldsByOrganization(id: $customFieldsByOrganizationId) { + _id + type + name + } + } +`; diff --git a/src/GraphQl/Queries/Queries.ts b/src/GraphQl/Queries/Queries.ts index 7bf99d48ee..101d020285 100644 --- a/src/GraphQl/Queries/Queries.ts +++ b/src/GraphQl/Queries/Queries.ts @@ -1,9 +1,7 @@ import gql from 'graphql-tag'; //Query List - // Check Auth - export const CHECK_AUTH = gql` query { checkAuth { @@ -12,7 +10,19 @@ export const CHECK_AUTH = gql` lastName image email - userType + birthDate + educationGrade + employmentStatus + gender + maritalStatus + phone { + mobile + } + address { + line1 + state + countryCode + } } } `; @@ -35,18 +45,33 @@ export const ORGANIZATION_LIST = gql` _id } createdAt - location + address { + city + countryCode + dependentLocality + line1 + line2 + postalCode + sortingCode + state + } } } `; -// Query to take the Organization list with filter option +// Query to take the Organization list with filter and sort option export const ORGANIZATION_CONNECTION_LIST = gql` - query OrganizationsConnection($filter: String, $first: Int, $skip: Int) { + query OrganizationsConnection( + $filter: String + $first: Int + $skip: Int + $orderBy: OrganizationOrderByInput + ) { organizationsConnection( where: { name_contains: $filter } first: $first skip: $skip + orderBy: $orderBy ) { _id image @@ -62,7 +87,16 @@ export const ORGANIZATION_CONNECTION_LIST = gql` _id } createdAt - location + address { + city + countryCode + dependentLocality + line1 + line2 + postalCode + sortingCode + state + } } } `; @@ -83,46 +117,100 @@ export const USER_LIST = gql` skip: $skip first: $first ) { - firstName - lastName - image - _id - email - userType - adminApproved - adminFor { - _id - } - createdAt - organizationsBlockedBy { + user { _id - name - image - location - createdAt - creator { + joinedOrganizations { _id - firstName - lastName + name image - email createdAt + address { + city + countryCode + dependentLocality + line1 + line2 + postalCode + sortingCode + state + } + creator { + _id + firstName + lastName + image + email + } } - } - joinedOrganizations { - _id - name + firstName + lastName + email image - location createdAt - creator { + registeredEvents { _id - firstName - lastName + } + organizationsBlockedBy { + _id + name image - email + address { + city + countryCode + dependentLocality + line1 + line2 + postalCode + sortingCode + state + } + creator { + _id + firstName + lastName + image + email + } createdAt } + membershipRequests { + _id + } + } + appUserProfile { + _id + adminFor { + _id + } + isSuperAdmin + createdOrganizations { + _id + } + createdEvents { + _id + } + eventAdmin { + _id + } + } + } + } +`; +export const USER_LIST_FOR_TABLE = gql` + query Users($firstName_contains: String, $lastName_contains: String) { + users( + where: { + firstName_contains: $firstName_contains + lastName_contains: $lastName_contains + } + ) { + user { + _id + firstName + lastName + email + image + createdAt } } } @@ -134,8 +222,6 @@ export const USER_LIST_REQUEST = gql` $lastName_contains: String $first: Int $skip: Int - $userType: String - $adminApproved: Boolean ) { users( where: { @@ -144,17 +230,31 @@ export const USER_LIST_REQUEST = gql` } skip: $skip first: $first - userType: $userType - adminApproved: $adminApproved ) { - firstName - lastName - image - _id - email - userType - adminApproved - createdAt + user { + firstName + lastName + image + _id + email + createdAt + } + appUserProfile { + _id + adminFor { + _id + } + isSuperAdmin + createdOrganizations { + _id + } + createdEvents { + _id + } + eventAdmin { + _id + } + } } } `; @@ -182,23 +282,6 @@ export const EVENT_DETAILS = gql` attendees { _id } - projects { - _id - title - description - tasks { - _id - title - description - deadline - completed - volunteers { - _id - firstName - lastName - } - } - } } } `; @@ -229,8 +312,6 @@ export const EVENT_CHECKINS = gql` checkIn { _id time - allotedRoom - allotedSeat } } } @@ -264,8 +345,17 @@ export const ORGANIZATIONS_LIST = gql` } name description - location - isPublic + address { + city + countryCode + dependentLocality + line1 + line2 + postalCode + sortingCode + state + } + userRegistrationRequired visibleInSearch members { _id @@ -278,6 +368,7 @@ export const ORGANIZATIONS_LIST = gql` firstName lastName email + createdAt } membershipRequests { _id @@ -298,7 +389,6 @@ export const ORGANIZATIONS_LIST = gql` `; // Query to take the Members of a particular organization - export const MEMBERS_LIST = gql` query Organizations($id: ID!) { organizations(id: $id) { @@ -350,7 +440,6 @@ export const ORGANIZATIONS_MEMBER_CONNECTION_LIST = gql` $orgId: ID! $firstName_contains: String $lastName_contains: String - $admin_for: ID $event_title_contains: String $first: Int $skip: Int @@ -362,7 +451,6 @@ export const ORGANIZATIONS_MEMBER_CONNECTION_LIST = gql` where: { firstName_contains: $firstName_contains lastName_contains: $lastName_contains - admin_for: $admin_for event_title_contains: $event_title_contains } ) { @@ -380,17 +468,13 @@ export const ORGANIZATIONS_MEMBER_CONNECTION_LIST = gql` // To take the list of the oranization joined by a user export const USER_ORGANIZATION_LIST = gql` - query User($id: ID!) { - user(id: $id) { - firstName - lastName - image - email - userType - adminFor { - _id - name + query User($userId: ID!) { + user(id: $userId) { + user { + firstName + email image + lastName } } } @@ -400,41 +484,54 @@ export const USER_ORGANIZATION_LIST = gql` export const USER_DETAILS = gql` query User($id: ID!) { user(id: $id) { - image - firstName - lastName - email - appLanguageCode - userType - pluginCreationAllowed - adminApproved - createdAt - adminFor { - _id - } - createdOrganizations { - _id - } - joinedOrganizations { - _id - } - organizationUserBelongsTo { - _id - } - organizationsBlockedBy { - _id - } - createdEvents { - _id - } - registeredEvents { - _id - } - eventAdmin { + user { _id + joinedOrganizations { + _id + } + firstName + lastName + email + image + createdAt + birthDate + educationGrade + employmentStatus + gender + maritalStatus + phone { + mobile + } + address { + line1 + countryCode + city + state + } + registeredEvents { + _id + } + membershipRequests { + _id + } } - membershipRequests { + appUserProfile { _id + adminFor { + _id + } + isSuperAdmin + appLanguageCode + pluginCreationAllowed + createdOrganizations { + _id + } + createdEvents { + _id + } + eventAdmin { + _id + } } } } @@ -489,6 +586,16 @@ export const ORGANIZATION_EVENT_CONNECTION_LIST = gql` endTime allDay recurring + recurrenceRule { + recurrenceStartDate + recurrenceEndDate + frequency + weekDays + interval + count + weekDayOccurenceInMonth + } + isRecurringEventException isPublic isRegisterable } @@ -510,12 +617,12 @@ export const ORGANIZATION_DONATION_CONNECTION_LIST = gql` amount userId payPalId + updatedAt } } `; // to take the list of the admins of a particular - export const ADMIN_LIST = gql` query Organizations($id: ID!) { organizations(id: $id) { @@ -533,12 +640,20 @@ export const ADMIN_LIST = gql` `; // to take the membership request - export const MEMBERSHIP_REQUEST = gql` - query Organizations($id: ID!) { + query Organizations( + $id: ID! + $skip: Int + $first: Int + $firstName_contains: String + ) { organizations(id: $id) { _id - membershipRequests { + membershipRequests( + skip: $skip + first: $first + where: { user: { firstName_contains: $firstName_contains } } + ) { _id user { _id @@ -551,295 +666,141 @@ export const MEMBERSHIP_REQUEST = gql` } `; -// display posts - -export const ORGANIZATION_POST_LIST = gql` - query PostsByOrganization($id: ID!) { - postsByOrganization(id: $id) { - _id - title - text - imageUrl - videoUrl - creator { - _id - firstName - lastName - email - } - createdAt - } - } -`; - -export const ORGANIZATION_POST_CONNECTION_LIST = gql` - query PostsByOrganizationConnection( - $id: ID! - $title_contains: String - $text_contains: String +export const USERS_CONNECTION_LIST = gql` + query usersConnection( + $id_not_in: [ID!] + $firstName_contains: String + $lastName_contains: String ) { - postsByOrganizationConnection( - id: $id - where: { title_contains: $title_contains, text_contains: $text_contains } - orderBy: createdAt_DESC + users( + where: { + id_not_in: $id_not_in + firstName_contains: $firstName_contains + lastName_contains: $lastName_contains + } ) { - edges { + user { + firstName + lastName + image _id - title - text - imageUrl - videoUrl - creator { - _id - firstName - lastName - email - } + email createdAt - likeCount - commentCount - comments { + organizationsBlockedBy { _id + name + image + address { + city + countryCode + dependentLocality + line1 + line2 + postalCode + sortingCode + state + } + createdAt creator { _id firstName lastName + image email + createdAt } - likeCount - likedBy { - _id - } - text } - likedBy { + joinedOrganizations { _id - firstName - lastName + name + image + address { + city + countryCode + dependentLocality + line1 + line2 + postalCode + sortingCode + state + } + createdAt + creator { + _id + firstName + lastName + image + email + createdAt + } } } - } - } -`; - -export const USER_ORGANIZATION_CONNECTION = gql` - query organizationsConnection( - $first: Int - $skip: Int - $filter: String - $id: ID - ) { - organizationsConnection( - first: $first - skip: $skip - where: { name_contains: $filter, id: $id } - orderBy: name_ASC - ) { - _id - name - image - description - isPublic - creator { - firstName - lastName - } - } - } -`; - -export const USER_JOINED_ORGANIZATIONS = gql` - query UserJoinedOrganizations($id: ID!) { - users(where: { id: $id }) { - joinedOrganizations { - _id - name - description - image - } - } - } -`; - -export const USER_CREATED_ORGANIZATIONS = gql` - query UserJoinedOrganizations($id: ID!) { - users(where: { id: $id }) { - createdOrganizations { - _id - name - description - image - } - } - } -`; - -export const ORGANIZATION_ADMINS_LIST = gql` - query Organizations($id: ID!) { - organizations(id: $id) { - _id - admins { + appUserProfile { _id - image - firstName - lastName - email - } - } - } -`; - -/** - * @name PLUGIN_GET - * @description used to fetch list of plugins - */ -export const PLUGIN_GET = gql` - query getPluginList { - getPlugins { - _id - pluginName - pluginCreatedBy - pluginDesc - uninstalledOrgs - } - } -`; -export const ADVERTISEMENTS_GET = gql` - query getAdvertisement { - getAdvertisements { - _id - name - type - orgId - link - endDate - startDate - } - } -`; -export const ORGANIZATION_EVENTS_CONNECTION = gql` - query EventsByOrganizationConnection( - $organization_id: ID! - $title_contains: String - $description_contains: String - $location_contains: String - $first: Int - $skip: Int - ) { - eventsByOrganizationConnection( - where: { - organization_id: $organization_id - title_contains: $title_contains - description_contains: $description_contains - location_contains: $location_contains - } - first: $first - skip: $skip - ) { - _id - title - description - startDate - endDate - location - startTime - endTime - allDay - recurring - isPublic - isRegisterable - creator { - _id - firstName - lastName - } - attendees { - _id - } - } - } -`; - -export const USER_TASKS_LIST = gql` - query User($id: ID!) { - user(id: $id) { - _id - assignedTasks { - _id - title - description - deadline - volunteers { + adminFor { _id - firstName - lastName - email } - createdAt - completed - event { + isSuperAdmin + createdOrganizations { _id - title - organization { - _id - name - image - } } - creator { + createdEvents { + _id + } + eventAdmin { _id - firstName - lastName } } } } `; -export const DIRECT_CHATS_LIST = gql` - query DirectChatsByUserID($id: ID!) { - directChatsByUserID(id: $id) { +export const GET_COMMUNITY_DATA = gql` + query getCommunityData { + getCommunityData { _id - creator { - _id - firstName - lastName - email - } - messages { - _id - createdAt - messageContent - receiver { - _id - firstName - lastName - email - } - sender { - _id - firstName - lastName - email - } - } - organization { - _id - name - } - users { - _id - firstName - lastName - email - image + websiteLink + name + logoUrl + socialMediaUrls { + facebook + gitHub + instagram + twitter + linkedIn + youTube + reddit + slack } } } `; -export const IS_SAMPLE_ORGANIZATION_QUERY = gql` - query ($isSampleOrganizationId: ID!) { - isSampleOrganization(id: $isSampleOrganizationId) - } -`; +// get the list of Action Item Categories +export { ACTION_ITEM_CATEGORY_LIST } from './ActionItemCategoryQueries'; + +// get the list of Action Items +export { ACTION_ITEM_LIST } from './ActionItemQueries'; + +// to take the list of the blocked users +export { + ADVERTISEMENTS_GET, + DIRECT_CHATS_LIST, + IS_SAMPLE_ORGANIZATION_QUERY, + ORGANIZATION_CUSTOM_FIELDS, + ORGANIZATION_EVENTS_CONNECTION, + PLUGIN_GET, +} from './PlugInQueries'; + +// display posts +export { + ORGANIZATION_POST_LIST, + ORGANIZATION_ADVERTISEMENT_LIST, +} from './OrganizationQueries'; + +export { + ORGANIZATION_ADMINS_LIST, + USER_CREATED_ORGANIZATIONS, + USER_JOINED_ORGANIZATIONS, + USER_ORGANIZATION_CONNECTION, +} from './OrganizationQueries'; diff --git a/src/GraphQl/Queries/fundQueries.ts b/src/GraphQl/Queries/fundQueries.ts new file mode 100644 index 0000000000..85015f5f63 --- /dev/null +++ b/src/GraphQl/Queries/fundQueries.ts @@ -0,0 +1,67 @@ +/*eslint-disable*/ +import gql from 'graphql-tag'; + +/** + * GraphQL query to retrieve the list of members for a specific organization. + * + * @param id - The ID of the organization for which members are being retrieved. + * @param filter - The filter to search for a specific member. + * @returns The list of members associated with the organization. + */ +export const FUND_LIST = gql` + query FundsByOrganization($organizationId: ID!, $filter: String) { + fundsByOrganization( + organizationId: $organizationId + where: { name_contains: $filter } + ) { + _id + name + refrenceNumber + taxDeductible + isDefault + isArchived + createdAt + organizationId + creator { + _id + firstName + lastName + } + } + } +`; + +export const FUND_CAMPAIGN = gql` + query GetFundById($id: ID!) { + getFundById(id: $id) { + campaigns { + _id + endDate + fundingGoal + name + startDate + currency + } + } + } +`; + +export const FUND_CAMPAIGN_PLEDGE = gql` + query GetFundraisingCampaignById($id: ID!) { + getFundraisingCampaignById(id: $id) { + startDate + endDate + pledges { + _id + amount + currency + endDate + startDate + users { + _id + firstName + } + } + } + } +`; diff --git a/src/assets/css/app.css b/src/assets/css/app.css index ae21cf9cb0..a96b3afabe 100644 --- a/src/assets/css/app.css +++ b/src/assets/css/app.css @@ -1,8 +1,10 @@ +@charset "UTF-8"; +@import url('https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,100;0,300;0,400;0,700;0,900;1,100;1,300;1,400;1,700;1,900&display=swap'); /*! - * Bootstrap v5.3.0 (https://getbootstrap.com/) - * Copyright 2011-2023 The Bootstrap Authors - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - */ + * Bootstrap v5.3.0 (https://getbootstrap.com/) + * Copyright 2011-2023 The Bootstrap Authors + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ :root, [data-bs-theme='light'] { --bs-blue: #0d6efd; @@ -75,12 +77,14 @@ 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; --bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; + --bs-font-lato: 'Lato'; --bs-gradient: linear-gradient( 180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0) ); --bs-body-font-family: var(--bs-font-sans-serif); + --bs-leftDrawer-font-family: var(--bs-font-sans-serif); --bs-body-font-size: 1rem; --bs-body-font-weight: 400; --bs-body-line-height: 1.5; @@ -217,18 +221,18 @@ hr { opacity: 0.25; } -h1, -.h1, -h2, -.h2, -h3, -.h3, -h4, -.h4, +h6, +.h6, h5, .h5, -h6, -.h6 { +h4, +.h4, +h3, +.h3, +h2, +.h2, +h1, +.h1 { margin-top: 0; margin-bottom: 0.5rem; font-weight: 500; @@ -575,13 +579,13 @@ legend + * { } /* rtl:raw: -[type="tel"], -[type="url"], -[type="email"], -[type="number"] { - direction: ltr; -} -*/ + [type="tel"], + [type="url"], + [type="email"], + [type="number"] { + direction: ltr; + } + */ ::-webkit-search-decoration { -webkit-appearance: none; } @@ -724,7 +728,7 @@ progress { color: #6c757d; } .blockquote-footer::before { - content: '\2014\00A0'; + content: '— '; } .img-fluid { @@ -757,11 +761,11 @@ progress { .container, .container-fluid, -.container-sm, -.container-md, -.container-lg, +.container-xxl, .container-xl, -.container-xxl { +.container-lg, +.container-md, +.container-sm { --bs-gutter-x: 1.5rem; --bs-gutter-y: 0; width: 100%; @@ -772,50 +776,45 @@ progress { } @media (min-width: 576px) { - .container, - .container-sm { + .container-sm, + .container { max-width: 540px; } } - @media (min-width: 768px) { - .container, + .container-md, .container-sm, - .container-md { + .container { max-width: 720px; } } - @media (min-width: 992px) { - .container, - .container-sm, + .container-lg, .container-md, - .container-lg { + .container-sm, + .container { max-width: 960px; } } - @media (min-width: 1200px) { - .container, - .container-sm, - .container-md, + .container-xl, .container-lg, - .container-xl { + .container-md, + .container-sm, + .container { max-width: 1140px; } } - @media (min-width: 1400px) { - .container, - .container-sm, - .container-md, - .container-lg, + .container-xxl, .container-xl, - .container-xxl { + .container-lg, + .container-md, + .container-sm, + .container { max-width: 1320px; } } - :root { --bs-breakpoint-xs: 0; --bs-breakpoint-sm: 576px; @@ -864,7 +863,7 @@ progress { .row-cols-3 > * { flex: 0 0 auto; - width: 33.33333%; + width: 33.3333333333%; } .row-cols-4 > * { @@ -879,7 +878,7 @@ progress { .row-cols-6 > * { flex: 0 0 auto; - width: 16.66667%; + width: 16.6666666667%; } .col-auto { @@ -889,12 +888,12 @@ progress { .col-1 { flex: 0 0 auto; - width: 8.33333%; + width: 8.33333333%; } .col-2 { flex: 0 0 auto; - width: 16.66667%; + width: 16.66666667%; } .col-3 { @@ -904,12 +903,12 @@ progress { .col-4 { flex: 0 0 auto; - width: 33.33333%; + width: 33.33333333%; } .col-5 { flex: 0 0 auto; - width: 41.66667%; + width: 41.66666667%; } .col-6 { @@ -919,12 +918,12 @@ progress { .col-7 { flex: 0 0 auto; - width: 58.33333%; + width: 58.33333333%; } .col-8 { flex: 0 0 auto; - width: 66.66667%; + width: 66.66666667%; } .col-9 { @@ -934,12 +933,12 @@ progress { .col-10 { flex: 0 0 auto; - width: 83.33333%; + width: 83.33333333%; } .col-11 { flex: 0 0 auto; - width: 91.66667%; + width: 91.66666667%; } .col-12 { @@ -948,11 +947,11 @@ progress { } .offset-1 { - margin-left: 8.33333%; + margin-left: 8.33333333%; } .offset-2 { - margin-left: 16.66667%; + margin-left: 16.66666667%; } .offset-3 { @@ -960,11 +959,11 @@ progress { } .offset-4 { - margin-left: 33.33333%; + margin-left: 33.33333333%; } .offset-5 { - margin-left: 41.66667%; + margin-left: 41.66666667%; } .offset-6 { @@ -972,11 +971,11 @@ progress { } .offset-7 { - margin-left: 58.33333%; + margin-left: 58.33333333%; } .offset-8 { - margin-left: 66.66667%; + margin-left: 66.66666667%; } .offset-9 { @@ -984,11 +983,11 @@ progress { } .offset-10 { - margin-left: 83.33333%; + margin-left: 83.33333333%; } .offset-11 { - margin-left: 91.66667%; + margin-left: 91.66666667%; } .g-0, @@ -1069,7 +1068,7 @@ progress { } .row-cols-sm-3 > * { flex: 0 0 auto; - width: 33.33333%; + width: 33.3333333333%; } .row-cols-sm-4 > * { flex: 0 0 auto; @@ -1081,7 +1080,7 @@ progress { } .row-cols-sm-6 > * { flex: 0 0 auto; - width: 16.66667%; + width: 16.6666666667%; } .col-sm-auto { flex: 0 0 auto; @@ -1089,11 +1088,11 @@ progress { } .col-sm-1 { flex: 0 0 auto; - width: 8.33333%; + width: 8.33333333%; } .col-sm-2 { flex: 0 0 auto; - width: 16.66667%; + width: 16.66666667%; } .col-sm-3 { flex: 0 0 auto; @@ -1101,11 +1100,11 @@ progress { } .col-sm-4 { flex: 0 0 auto; - width: 33.33333%; + width: 33.33333333%; } .col-sm-5 { flex: 0 0 auto; - width: 41.66667%; + width: 41.66666667%; } .col-sm-6 { flex: 0 0 auto; @@ -1113,11 +1112,11 @@ progress { } .col-sm-7 { flex: 0 0 auto; - width: 58.33333%; + width: 58.33333333%; } .col-sm-8 { flex: 0 0 auto; - width: 66.66667%; + width: 66.66666667%; } .col-sm-9 { flex: 0 0 auto; @@ -1125,11 +1124,11 @@ progress { } .col-sm-10 { flex: 0 0 auto; - width: 83.33333%; + width: 83.33333333%; } .col-sm-11 { flex: 0 0 auto; - width: 91.66667%; + width: 91.66666667%; } .col-sm-12 { flex: 0 0 auto; @@ -1139,37 +1138,37 @@ progress { margin-left: 0; } .offset-sm-1 { - margin-left: 8.33333%; + margin-left: 8.33333333%; } .offset-sm-2 { - margin-left: 16.66667%; + margin-left: 16.66666667%; } .offset-sm-3 { margin-left: 25%; } .offset-sm-4 { - margin-left: 33.33333%; + margin-left: 33.33333333%; } .offset-sm-5 { - margin-left: 41.66667%; + margin-left: 41.66666667%; } .offset-sm-6 { margin-left: 50%; } .offset-sm-7 { - margin-left: 58.33333%; + margin-left: 58.33333333%; } .offset-sm-8 { - margin-left: 66.66667%; + margin-left: 66.66666667%; } .offset-sm-9 { margin-left: 75%; } .offset-sm-10 { - margin-left: 83.33333%; + margin-left: 83.33333333%; } .offset-sm-11 { - margin-left: 91.66667%; + margin-left: 91.66666667%; } .g-sm-0, .gx-sm-0 { @@ -1220,7 +1219,6 @@ progress { --bs-gutter-y: 3rem; } } - @media (min-width: 768px) { .col-md { flex: 1 0 0%; @@ -1239,7 +1237,7 @@ progress { } .row-cols-md-3 > * { flex: 0 0 auto; - width: 33.33333%; + width: 33.3333333333%; } .row-cols-md-4 > * { flex: 0 0 auto; @@ -1251,7 +1249,7 @@ progress { } .row-cols-md-6 > * { flex: 0 0 auto; - width: 16.66667%; + width: 16.6666666667%; } .col-md-auto { flex: 0 0 auto; @@ -1259,11 +1257,11 @@ progress { } .col-md-1 { flex: 0 0 auto; - width: 8.33333%; + width: 8.33333333%; } .col-md-2 { flex: 0 0 auto; - width: 16.66667%; + width: 16.66666667%; } .col-md-3 { flex: 0 0 auto; @@ -1271,11 +1269,11 @@ progress { } .col-md-4 { flex: 0 0 auto; - width: 33.33333%; + width: 33.33333333%; } .col-md-5 { flex: 0 0 auto; - width: 41.66667%; + width: 41.66666667%; } .col-md-6 { flex: 0 0 auto; @@ -1283,11 +1281,11 @@ progress { } .col-md-7 { flex: 0 0 auto; - width: 58.33333%; + width: 58.33333333%; } .col-md-8 { flex: 0 0 auto; - width: 66.66667%; + width: 66.66666667%; } .col-md-9 { flex: 0 0 auto; @@ -1295,11 +1293,11 @@ progress { } .col-md-10 { flex: 0 0 auto; - width: 83.33333%; + width: 83.33333333%; } .col-md-11 { flex: 0 0 auto; - width: 91.66667%; + width: 91.66666667%; } .col-md-12 { flex: 0 0 auto; @@ -1309,37 +1307,37 @@ progress { margin-left: 0; } .offset-md-1 { - margin-left: 8.33333%; + margin-left: 8.33333333%; } .offset-md-2 { - margin-left: 16.66667%; + margin-left: 16.66666667%; } .offset-md-3 { margin-left: 25%; } .offset-md-4 { - margin-left: 33.33333%; + margin-left: 33.33333333%; } .offset-md-5 { - margin-left: 41.66667%; + margin-left: 41.66666667%; } .offset-md-6 { margin-left: 50%; } .offset-md-7 { - margin-left: 58.33333%; + margin-left: 58.33333333%; } .offset-md-8 { - margin-left: 66.66667%; + margin-left: 66.66666667%; } .offset-md-9 { margin-left: 75%; } .offset-md-10 { - margin-left: 83.33333%; + margin-left: 83.33333333%; } .offset-md-11 { - margin-left: 91.66667%; + margin-left: 91.66666667%; } .g-md-0, .gx-md-0 { @@ -1390,7 +1388,6 @@ progress { --bs-gutter-y: 3rem; } } - @media (min-width: 992px) { .col-lg { flex: 1 0 0%; @@ -1409,7 +1406,7 @@ progress { } .row-cols-lg-3 > * { flex: 0 0 auto; - width: 33.33333%; + width: 33.3333333333%; } .row-cols-lg-4 > * { flex: 0 0 auto; @@ -1421,7 +1418,7 @@ progress { } .row-cols-lg-6 > * { flex: 0 0 auto; - width: 16.66667%; + width: 16.6666666667%; } .col-lg-auto { flex: 0 0 auto; @@ -1429,11 +1426,11 @@ progress { } .col-lg-1 { flex: 0 0 auto; - width: 8.33333%; + width: 8.33333333%; } .col-lg-2 { flex: 0 0 auto; - width: 16.66667%; + width: 16.66666667%; } .col-lg-3 { flex: 0 0 auto; @@ -1441,11 +1438,11 @@ progress { } .col-lg-4 { flex: 0 0 auto; - width: 33.33333%; + width: 33.33333333%; } .col-lg-5 { flex: 0 0 auto; - width: 41.66667%; + width: 41.66666667%; } .col-lg-6 { flex: 0 0 auto; @@ -1453,11 +1450,11 @@ progress { } .col-lg-7 { flex: 0 0 auto; - width: 58.33333%; + width: 58.33333333%; } .col-lg-8 { flex: 0 0 auto; - width: 66.66667%; + width: 66.66666667%; } .col-lg-9 { flex: 0 0 auto; @@ -1465,11 +1462,11 @@ progress { } .col-lg-10 { flex: 0 0 auto; - width: 83.33333%; + width: 83.33333333%; } .col-lg-11 { flex: 0 0 auto; - width: 91.66667%; + width: 91.66666667%; } .col-lg-12 { flex: 0 0 auto; @@ -1479,37 +1476,37 @@ progress { margin-left: 0; } .offset-lg-1 { - margin-left: 8.33333%; + margin-left: 8.33333333%; } .offset-lg-2 { - margin-left: 16.66667%; + margin-left: 16.66666667%; } .offset-lg-3 { margin-left: 25%; } .offset-lg-4 { - margin-left: 33.33333%; + margin-left: 33.33333333%; } .offset-lg-5 { - margin-left: 41.66667%; + margin-left: 41.66666667%; } .offset-lg-6 { margin-left: 50%; } .offset-lg-7 { - margin-left: 58.33333%; + margin-left: 58.33333333%; } .offset-lg-8 { - margin-left: 66.66667%; + margin-left: 66.66666667%; } .offset-lg-9 { margin-left: 75%; } .offset-lg-10 { - margin-left: 83.33333%; + margin-left: 83.33333333%; } .offset-lg-11 { - margin-left: 91.66667%; + margin-left: 91.66666667%; } .g-lg-0, .gx-lg-0 { @@ -1560,7 +1557,6 @@ progress { --bs-gutter-y: 3rem; } } - @media (min-width: 1200px) { .col-xl { flex: 1 0 0%; @@ -1579,7 +1575,7 @@ progress { } .row-cols-xl-3 > * { flex: 0 0 auto; - width: 33.33333%; + width: 33.3333333333%; } .row-cols-xl-4 > * { flex: 0 0 auto; @@ -1591,7 +1587,7 @@ progress { } .row-cols-xl-6 > * { flex: 0 0 auto; - width: 16.66667%; + width: 16.6666666667%; } .col-xl-auto { flex: 0 0 auto; @@ -1599,11 +1595,11 @@ progress { } .col-xl-1 { flex: 0 0 auto; - width: 8.33333%; + width: 8.33333333%; } .col-xl-2 { flex: 0 0 auto; - width: 16.66667%; + width: 16.66666667%; } .col-xl-3 { flex: 0 0 auto; @@ -1611,11 +1607,11 @@ progress { } .col-xl-4 { flex: 0 0 auto; - width: 33.33333%; + width: 33.33333333%; } .col-xl-5 { flex: 0 0 auto; - width: 41.66667%; + width: 41.66666667%; } .col-xl-6 { flex: 0 0 auto; @@ -1623,11 +1619,11 @@ progress { } .col-xl-7 { flex: 0 0 auto; - width: 58.33333%; + width: 58.33333333%; } .col-xl-8 { flex: 0 0 auto; - width: 66.66667%; + width: 66.66666667%; } .col-xl-9 { flex: 0 0 auto; @@ -1635,11 +1631,11 @@ progress { } .col-xl-10 { flex: 0 0 auto; - width: 83.33333%; + width: 83.33333333%; } .col-xl-11 { flex: 0 0 auto; - width: 91.66667%; + width: 91.66666667%; } .col-xl-12 { flex: 0 0 auto; @@ -1649,37 +1645,37 @@ progress { margin-left: 0; } .offset-xl-1 { - margin-left: 8.33333%; + margin-left: 8.33333333%; } .offset-xl-2 { - margin-left: 16.66667%; + margin-left: 16.66666667%; } .offset-xl-3 { margin-left: 25%; } .offset-xl-4 { - margin-left: 33.33333%; + margin-left: 33.33333333%; } .offset-xl-5 { - margin-left: 41.66667%; + margin-left: 41.66666667%; } .offset-xl-6 { margin-left: 50%; } .offset-xl-7 { - margin-left: 58.33333%; + margin-left: 58.33333333%; } .offset-xl-8 { - margin-left: 66.66667%; + margin-left: 66.66666667%; } .offset-xl-9 { margin-left: 75%; } .offset-xl-10 { - margin-left: 83.33333%; + margin-left: 83.33333333%; } .offset-xl-11 { - margin-left: 91.66667%; + margin-left: 91.66666667%; } .g-xl-0, .gx-xl-0 { @@ -1730,7 +1726,6 @@ progress { --bs-gutter-y: 3rem; } } - @media (min-width: 1400px) { .col-xxl { flex: 1 0 0%; @@ -1749,7 +1744,7 @@ progress { } .row-cols-xxl-3 > * { flex: 0 0 auto; - width: 33.33333%; + width: 33.3333333333%; } .row-cols-xxl-4 > * { flex: 0 0 auto; @@ -1761,7 +1756,7 @@ progress { } .row-cols-xxl-6 > * { flex: 0 0 auto; - width: 16.66667%; + width: 16.6666666667%; } .col-xxl-auto { flex: 0 0 auto; @@ -1769,11 +1764,11 @@ progress { } .col-xxl-1 { flex: 0 0 auto; - width: 8.33333%; + width: 8.33333333%; } .col-xxl-2 { flex: 0 0 auto; - width: 16.66667%; + width: 16.66666667%; } .col-xxl-3 { flex: 0 0 auto; @@ -1781,11 +1776,11 @@ progress { } .col-xxl-4 { flex: 0 0 auto; - width: 33.33333%; + width: 33.33333333%; } .col-xxl-5 { flex: 0 0 auto; - width: 41.66667%; + width: 41.66666667%; } .col-xxl-6 { flex: 0 0 auto; @@ -1793,11 +1788,11 @@ progress { } .col-xxl-7 { flex: 0 0 auto; - width: 58.33333%; + width: 58.33333333%; } .col-xxl-8 { flex: 0 0 auto; - width: 66.66667%; + width: 66.66666667%; } .col-xxl-9 { flex: 0 0 auto; @@ -1805,11 +1800,11 @@ progress { } .col-xxl-10 { flex: 0 0 auto; - width: 83.33333%; + width: 83.33333333%; } .col-xxl-11 { flex: 0 0 auto; - width: 91.66667%; + width: 91.66666667%; } .col-xxl-12 { flex: 0 0 auto; @@ -1819,37 +1814,37 @@ progress { margin-left: 0; } .offset-xxl-1 { - margin-left: 8.33333%; + margin-left: 8.33333333%; } .offset-xxl-2 { - margin-left: 16.66667%; + margin-left: 16.66666667%; } .offset-xxl-3 { margin-left: 25%; } .offset-xxl-4 { - margin-left: 33.33333%; + margin-left: 33.33333333%; } .offset-xxl-5 { - margin-left: 41.66667%; + margin-left: 41.66666667%; } .offset-xxl-6 { margin-left: 50%; } .offset-xxl-7 { - margin-left: 58.33333%; + margin-left: 58.33333333%; } .offset-xxl-8 { - margin-left: 66.66667%; + margin-left: 66.66666667%; } .offset-xxl-9 { margin-left: 75%; } .offset-xxl-10 { - margin-left: 83.33333%; + margin-left: 83.33333333%; } .offset-xxl-11 { - margin-left: 91.66667%; + margin-left: 91.66666667%; } .g-xxl-0, .gx-xxl-0 { @@ -1900,7 +1895,6 @@ progress { --bs-gutter-y: 3rem; } } - .table { --bs-table-color-type: initial; --bs-table-bg-type: initial; @@ -1961,7 +1955,6 @@ progress { .table-borderless > :not(caption) > * > * { border-bottom-width: 0; } - .table-borderless > :not(:first-child) { border-top-width: 0; } @@ -2109,35 +2102,30 @@ progress { -webkit-overflow-scrolling: touch; } } - @media (max-width: 767.98px) { .table-responsive-md { overflow-x: auto; -webkit-overflow-scrolling: touch; } } - @media (max-width: 991.98px) { .table-responsive-lg { overflow-x: auto; -webkit-overflow-scrolling: touch; } } - @media (max-width: 1199.98px) { .table-responsive-xl { overflow-x: auto; -webkit-overflow-scrolling: touch; } } - @media (max-width: 1399.98px) { .table-responsive-xxl { overflow-x: auto; -webkit-overflow-scrolling: touch; } } - .form-label { margin-bottom: 0.5rem; } @@ -2181,7 +2169,9 @@ progress { border: 0 solid var(--bs-border-color); appearance: none; border-radius: var(--bs-border-radius); - transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + transition: + border-color 0.15s ease-in-out, + box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .form-control { @@ -2230,8 +2220,11 @@ progress { border-width: 0; border-inline-end-width: 0; border-radius: 0; - transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, - border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + transition: + color 0.15s ease-in-out, + background-color 0.15s ease-in-out, + border-color 0.15s ease-in-out, + box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .form-control::file-selector-button { @@ -2289,11 +2282,9 @@ progress { textarea.form-control { min-height: calc(1.5em + 1.4rem + calc(0 * 2)); } - textarea.form-control-sm { min-height: calc(1.5em + 0.5rem + calc(0 * 2)); } - textarea.form-control-lg { min-height: calc(1.5em + 1rem + calc(0 * 2)); } @@ -2338,7 +2329,9 @@ textarea.form-control-lg { background-size: 16px 12px; border: 0 solid var(--bs-border-color); border-radius: var(--bs-border-radius); - transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + transition: + border-color 0.15s ease-in-out, + box-shadow 0.15s ease-in-out; appearance: none; } @media (prefers-reduced-motion: reduce) { @@ -2528,10 +2521,14 @@ textarea.form-control-lg { outline: 0; } .form-range:focus::-webkit-slider-thumb { - box-shadow: 0 0 0 1px #fff, 0 0 0 0.25rem rgba(49, 187, 107, 0.25); + box-shadow: + 0 0 0 1px #fff, + 0 0 0 0.25rem rgba(49, 187, 107, 0.25); } .form-range:focus::-moz-range-thumb { - box-shadow: 0 0 0 1px #fff, 0 0 0 0.25rem rgba(49, 187, 107, 0.25); + box-shadow: + 0 0 0 1px #fff, + 0 0 0 0.25rem rgba(49, 187, 107, 0.25); } .form-range::-moz-focus-outer { border: 0; @@ -2543,7 +2540,9 @@ textarea.form-control-lg { background-color: #31bb6b; border: 0; border-radius: 1rem; - transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, + transition: + background-color 0.15s ease-in-out, + border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; appearance: none; } @@ -2570,7 +2569,9 @@ textarea.form-control-lg { background-color: #31bb6b; border: 0; border-radius: 1rem; - transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, + transition: + background-color 0.15s ease-in-out, + border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; appearance: none; } @@ -2625,7 +2626,9 @@ textarea.form-control-lg { pointer-events: none; border: 0 solid transparent; transform-origin: 0 0; - transition: opacity 0.1s ease-in-out, transform 0.1s ease-in-out; + transition: + opacity 0.1s ease-in-out, + transform 0.1s ease-in-out; } @media (prefers-reduced-motion: reduce) { .form-floating > label { @@ -2769,7 +2772,6 @@ textarea.form-control-lg { border-top-right-radius: 0; border-bottom-right-radius: 0; } - .input-group.has-validation > :nth-last-child(n + 3):not(.dropdown-toggle):not(.dropdown-menu):not( .form-floating @@ -2784,7 +2786,6 @@ textarea.form-control-lg { border-top-right-radius: 0; border-bottom-right-radius: 0; } - .input-group > :not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not( .valid-feedback @@ -2793,7 +2794,6 @@ textarea.form-control-lg { border-top-left-radius: 0; border-bottom-left-radius: 0; } - .input-group > .form-floating:not(:first-child) > .form-control, .input-group > .form-floating:not(:first-child) > .form-select { border-top-left-radius: 0; @@ -2860,8 +2860,12 @@ textarea.form-control.is-valid { .form-select.is-valid:not([multiple])[size='1'] { --bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2331bb6b' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); padding-right: 5.5rem; - background-position: right 1rem center, center right 3rem; - background-size: 16px 12px, calc(0.75em + 0.7rem) calc(0.75em + 0.7rem); + background-position: + right 1rem center, + center right 3rem; + background-size: + 16px 12px, + calc(0.75em + 0.7rem) calc(0.75em + 0.7rem); } .was-validated .form-select:valid:focus, .form-select.is-valid:focus { @@ -2964,8 +2968,12 @@ textarea.form-control.is-invalid { .form-select.is-invalid:not([multiple])[size='1'] { --bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); padding-right: 5.5rem; - background-position: right 1rem center, center right 3rem; - background-size: 16px 12px, calc(0.75em + 0.7rem) calc(0.75em + 0.7rem); + background-position: + right 1rem center, + center right 3rem; + background-size: + 16px 12px, + calc(0.75em + 0.7rem) calc(0.75em + 0.7rem); } .was-validated .form-select:invalid:focus, .form-select.is-invalid:focus { @@ -3040,8 +3048,11 @@ textarea.form-control.is-invalid { border: var(--bs-btn-border-width) solid var(--bs-btn-border-color); border-radius: var(--bs-btn-border-radius); background-color: var(--bs-btn-bg); - transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, - border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + transition: + color 0.15s ease-in-out, + background-color 0.15s ease-in-out, + border-color 0.15s ease-in-out, + box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .btn { @@ -3551,7 +3562,6 @@ fieldset:disabled .btn { left: auto; } } - @media (min-width: 768px) { .dropdown-menu-md-start { --bs-position: start; @@ -3568,7 +3578,6 @@ fieldset:disabled .btn { left: auto; } } - @media (min-width: 992px) { .dropdown-menu-lg-start { --bs-position: start; @@ -3585,7 +3594,6 @@ fieldset:disabled .btn { left: auto; } } - @media (min-width: 1200px) { .dropdown-menu-xl-start { --bs-position: start; @@ -3602,7 +3610,6 @@ fieldset:disabled .btn { left: auto; } } - @media (min-width: 1400px) { .dropdown-menu-xxl-start { --bs-position: start; @@ -3619,14 +3626,12 @@ fieldset:disabled .btn { left: auto; } } - .dropup .dropdown-menu[data-bs-popper] { top: auto; bottom: 100%; margin-top: 0; margin-bottom: var(--bs-dropdown-spacer); } - .dropup .dropdown-toggle::after { display: inline-block; margin-left: 0.255em; @@ -3637,7 +3642,6 @@ fieldset:disabled .btn { border-bottom: 0.3em solid; border-left: 0.3em solid transparent; } - .dropup .dropdown-toggle:empty::after { margin-left: 0; } @@ -3649,7 +3653,6 @@ fieldset:disabled .btn { margin-top: 0; margin-left: var(--bs-dropdown-spacer); } - .dropend .dropdown-toggle::after { display: inline-block; margin-left: 0.255em; @@ -3660,11 +3663,9 @@ fieldset:disabled .btn { border-bottom: 0.3em solid transparent; border-left: 0.3em solid; } - .dropend .dropdown-toggle:empty::after { margin-left: 0; } - .dropend .dropdown-toggle::after { vertical-align: 0; } @@ -3676,18 +3677,15 @@ fieldset:disabled .btn { margin-top: 0; margin-right: var(--bs-dropdown-spacer); } - .dropstart .dropdown-toggle::after { display: inline-block; margin-left: 0.255em; vertical-align: 0.255em; content: ''; } - .dropstart .dropdown-toggle::after { display: none; } - .dropstart .dropdown-toggle::before { display: inline-block; margin-right: 0.255em; @@ -3697,11 +3695,9 @@ fieldset:disabled .btn { border-right: 0.3em solid; border-bottom: 0.3em solid transparent; } - .dropstart .dropdown-toggle:empty::after { margin-left: 0; } - .dropstart .dropdown-toggle::before { vertical-align: 0; } @@ -3906,7 +3902,9 @@ fieldset:disabled .btn { color: var(--bs-nav-link-color); background: none; border: 0; - transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, + transition: + color 0.15s ease-in-out, + background-color 0.15s ease-in-out, border-color 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { @@ -4032,7 +4030,6 @@ fieldset:disabled .btn { .tab-content > .tab-pane { display: none; } - .tab-content > .active { display: block; } @@ -4077,7 +4074,6 @@ fieldset:disabled .btn { align-items: center; justify-content: space-between; } - .navbar-brand { padding-top: var(--bs-navbar-brand-padding-y); padding-bottom: var(--bs-navbar-brand-padding-y); @@ -4216,7 +4212,6 @@ fieldset:disabled .btn { overflow-y: visible; } } - @media (min-width: 768px) { .navbar-expand-md { flex-wrap: nowrap; @@ -4264,7 +4259,6 @@ fieldset:disabled .btn { overflow-y: visible; } } - @media (min-width: 992px) { .navbar-expand-lg { flex-wrap: nowrap; @@ -4312,7 +4306,6 @@ fieldset:disabled .btn { overflow-y: visible; } } - @media (min-width: 1200px) { .navbar-expand-xl { flex-wrap: nowrap; @@ -4360,7 +4353,6 @@ fieldset:disabled .btn { overflow-y: visible; } } - @media (min-width: 1400px) { .navbar-expand-xxl { flex-wrap: nowrap; @@ -4408,7 +4400,6 @@ fieldset:disabled .btn { overflow-y: visible; } } - .navbar-expand { flex-wrap: nowrap; justify-content: flex-start; @@ -4623,7 +4614,6 @@ fieldset:disabled .btn { .card-group > .card { margin-bottom: var(--bs-card-group-margin); } - @media (min-width: 576px) { .card-group { display: flex; @@ -4789,7 +4779,6 @@ fieldset:disabled .btn { .accordion-flush .accordion-collapse { border-width: 0; } - .accordion-flush .accordion-item { border-right: 0; border-left: 0; @@ -4840,7 +4829,6 @@ fieldset:disabled .btn { content: var(--bs-breadcrumb-divider, '/') /* rtl: var(--bs-breadcrumb-divider, "/") */; } - .breadcrumb-item.active { color: var(--bs-breadcrumb-item-active-color); } @@ -4880,8 +4868,11 @@ fieldset:disabled .btn { background-color: var(--bs-pagination-bg); border: var(--bs-pagination-border-width) solid var(--bs-pagination-border-color); - transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, - border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + transition: + color 0.15s ease-in-out, + background-color 0.15s ease-in-out, + border-color 0.15s ease-in-out, + box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .page-link { @@ -4919,12 +4910,10 @@ fieldset:disabled .btn { .page-item:not(:first-child) .page-link { margin-left: calc(var(--bs-border-width) * -1); } - .page-item:first-child .page-link { border-top-left-radius: var(--bs-pagination-border-radius); border-bottom-left-radius: var(--bs-pagination-border-radius); } - .page-item:last-child .page-link { border-top-right-radius: var(--bs-pagination-border-radius); border-bottom-right-radius: var(--bs-pagination-border-radius); @@ -5071,7 +5060,6 @@ fieldset:disabled .btn { background-position-x: 1rem; } } - .progress, .progress-stacked { --bs-progress-height: 1rem; @@ -5274,7 +5262,6 @@ fieldset:disabled .btn { border-left-width: var(--bs-list-group-border-width); } } - @media (min-width: 768px) { .list-group-horizontal-md { flex-direction: row; @@ -5299,7 +5286,6 @@ fieldset:disabled .btn { border-left-width: var(--bs-list-group-border-width); } } - @media (min-width: 992px) { .list-group-horizontal-lg { flex-direction: row; @@ -5324,7 +5310,6 @@ fieldset:disabled .btn { border-left-width: var(--bs-list-group-border-width); } } - @media (min-width: 1200px) { .list-group-horizontal-xl { flex-direction: row; @@ -5349,7 +5334,6 @@ fieldset:disabled .btn { border-left-width: var(--bs-list-group-border-width); } } - @media (min-width: 1400px) { .list-group-horizontal-xxl { flex-direction: row; @@ -5374,7 +5358,6 @@ fieldset:disabled .btn { border-left-width: var(--bs-list-group-border-width); } } - .list-group-flush { border-radius: 0; } @@ -5560,7 +5543,7 @@ fieldset:disabled .btn { box-shadow: var(--bs-toast-box-shadow); border-radius: var(--bs-toast-border-radius); } -.showing { +.toast.showing { opacity: 0; } .toast:not(.show) { @@ -5774,20 +5757,17 @@ fieldset:disabled .btn { --bs-modal-width: 300px; } } - @media (min-width: 992px) { .modal-lg, .modal-xl { --bs-modal-width: 800px; } } - @media (min-width: 1200px) { .modal-xl { --bs-modal-width: 1140px; } } - .modal-fullscreen { width: 100vw; max-width: none; @@ -5827,7 +5807,6 @@ fieldset:disabled .btn { overflow-y: auto; } } - @media (max-width: 767.98px) { .modal-fullscreen-md-down { width: 100vw; @@ -5848,7 +5827,6 @@ fieldset:disabled .btn { overflow-y: auto; } } - @media (max-width: 991.98px) { .modal-fullscreen-lg-down { width: 100vw; @@ -5869,7 +5847,6 @@ fieldset:disabled .btn { overflow-y: auto; } } - @media (max-width: 1199.98px) { .modal-fullscreen-xl-down { width: 100vw; @@ -5890,7 +5867,6 @@ fieldset:disabled .btn { overflow-y: auto; } } - @media (max-width: 1399.98px) { .modal-fullscreen-xxl-down { width: 100vw; @@ -5911,7 +5887,6 @@ fieldset:disabled .btn { overflow-y: auto; } } - .tooltip { --bs-tooltip-zindex: 1080; --bs-tooltip-max-width: 200px; @@ -6163,7 +6138,6 @@ fieldset:disabled .btn { top: var(--bs-popover-border-width); border-bottom-color: var(--bs-popover-bg); } - .bs-popover-bottom .popover-header::before, .bs-popover-auto[data-popper-placement^='bottom'] .popover-header::before { position: absolute; @@ -6280,14 +6254,12 @@ fieldset:disabled .btn { transition-property: opacity; transform: none; } - .carousel-fade .carousel-item.active, .carousel-fade .carousel-item-next.carousel-item-start, .carousel-fade .carousel-item-prev.carousel-item-end { z-index: 1; opacity: 1; } - .carousel-fade .active.carousel-item-start, .carousel-fade .active.carousel-item-end { z-index: 0; @@ -6354,13 +6326,13 @@ fieldset:disabled .btn { } /* rtl:options: { - "autoRename": true, - "stringMap":[ { - "name" : "prev-next", - "search" : "prev", - "replace" : "next" - } ] -} */ + "autoRename": true, + "stringMap":[ { + "name" : "prev-next", + "search" : "prev", + "replace" : "next" + } ] + } */ .carousel-control-prev-icon { background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e"); } @@ -6424,11 +6396,9 @@ fieldset:disabled .btn { .carousel-dark .carousel-control-next-icon { filter: invert(1) grayscale(100); } - .carousel-dark .carousel-indicators [data-bs-target] { background-color: #000; } - .carousel-dark .carousel-caption { color: #000; } @@ -6439,12 +6409,10 @@ fieldset:disabled .btn { [data-bs-theme='dark'].carousel .carousel-control-next-icon { filter: invert(1) grayscale(100); } - [data-bs-theme='dark'] .carousel .carousel-indicators [data-bs-target], [data-bs-theme='dark'].carousel .carousel-indicators [data-bs-target] { background-color: #000; } - [data-bs-theme='dark'] .carousel .carousel-caption, [data-bs-theme='dark'].carousel .carousel-caption { color: #000; @@ -6466,7 +6434,6 @@ fieldset:disabled .btn { transform: rotate(360deg) /* rtl:ignore */; } } - .spinner-border { --bs-spinner-width: 2rem; --bs-spinner-height: 2rem; @@ -6493,7 +6460,6 @@ fieldset:disabled .btn { transform: none; } } - .spinner-grow { --bs-spinner-width: 2rem; --bs-spinner-height: 2rem; @@ -6515,13 +6481,12 @@ fieldset:disabled .btn { --bs-spinner-animation-speed: 1.5s; } } - -.offcanvas-sm, -.offcanvas-md, -.offcanvas-lg, -.offcanvas-xl, +.offcanvas, .offcanvas-xxl, -.offcanvas { +.offcanvas-xl, +.offcanvas-lg, +.offcanvas-md, +.offcanvas-sm { --bs-offcanvas-zindex: 1045; --bs-offcanvas-width: 400px; --bs-offcanvas-height: 30vh; @@ -6557,7 +6522,6 @@ fieldset:disabled .btn { transition: none; } } - @media (max-width: 575.98px) { .offcanvas-sm.offcanvas-start { top: 0; @@ -6604,7 +6568,6 @@ fieldset:disabled .btn { visibility: visible; } } - @media (min-width: 576px) { .offcanvas-sm { --bs-offcanvas-height: auto; @@ -6644,7 +6607,6 @@ fieldset:disabled .btn { transition: none; } } - @media (max-width: 767.98px) { .offcanvas-md.offcanvas-start { top: 0; @@ -6691,7 +6653,6 @@ fieldset:disabled .btn { visibility: visible; } } - @media (min-width: 768px) { .offcanvas-md { --bs-offcanvas-height: auto; @@ -6731,7 +6692,6 @@ fieldset:disabled .btn { transition: none; } } - @media (max-width: 991.98px) { .offcanvas-lg.offcanvas-start { top: 0; @@ -6778,7 +6738,6 @@ fieldset:disabled .btn { visibility: visible; } } - @media (min-width: 992px) { .offcanvas-lg { --bs-offcanvas-height: auto; @@ -6818,7 +6777,6 @@ fieldset:disabled .btn { transition: none; } } - @media (max-width: 1199.98px) { .offcanvas-xl.offcanvas-start { top: 0; @@ -6865,7 +6823,6 @@ fieldset:disabled .btn { visibility: visible; } } - @media (min-width: 1200px) { .offcanvas-xl { --bs-offcanvas-height: auto; @@ -6905,7 +6862,6 @@ fieldset:disabled .btn { transition: none; } } - @media (max-width: 1399.98px) { .offcanvas-xxl.offcanvas-start { top: 0; @@ -6952,7 +6908,6 @@ fieldset:disabled .btn { visibility: visible; } } - @media (min-width: 1400px) { .offcanvas-xxl { --bs-offcanvas-height: auto; @@ -7110,7 +7065,6 @@ fieldset:disabled .btn { opacity: 0.2; } } - .placeholder-wave { mask-image: linear-gradient( 130deg, @@ -7127,7 +7081,6 @@ fieldset:disabled .btn { mask-position: -200% 0%; } } - .clearfix::after { display: block; clear: both; @@ -7398,15 +7351,15 @@ fieldset:disabled .btn { } .ratio-4x3 { - --bs-aspect-ratio: calc(3 / 4 * 100%); + --bs-aspect-ratio: 75%; } .ratio-16x9 { - --bs-aspect-ratio: calc(9 / 16 * 100%); + --bs-aspect-ratio: 56.25%; } .ratio-21x9 { - --bs-aspect-ratio: calc(9 / 21 * 100%); + --bs-aspect-ratio: 42.8571428571%; } .fixed-top { @@ -7449,7 +7402,6 @@ fieldset:disabled .btn { z-index: 1020; } } - @media (min-width: 768px) { .sticky-md-top { position: sticky; @@ -7462,7 +7414,6 @@ fieldset:disabled .btn { z-index: 1020; } } - @media (min-width: 992px) { .sticky-lg-top { position: sticky; @@ -7475,7 +7426,6 @@ fieldset:disabled .btn { z-index: 1020; } } - @media (min-width: 1200px) { .sticky-xl-top { position: sticky; @@ -7488,7 +7438,6 @@ fieldset:disabled .btn { z-index: 1020; } } - @media (min-width: 1400px) { .sticky-xxl-top { position: sticky; @@ -7501,7 +7450,6 @@ fieldset:disabled .btn { z-index: 1020; } } - .hstack { display: flex; flex-direction: row; @@ -10161,7 +10109,6 @@ fieldset:disabled .btn { text-align: center !important; } } - @media (min-width: 768px) { .float-md-start { float: left !important; @@ -10712,7 +10659,6 @@ fieldset:disabled .btn { text-align: center !important; } } - @media (min-width: 992px) { .float-lg-start { float: left !important; @@ -11263,7 +11209,6 @@ fieldset:disabled .btn { text-align: center !important; } } - @media (min-width: 1200px) { .float-xl-start { float: left !important; @@ -11814,7 +11759,6 @@ fieldset:disabled .btn { text-align: center !important; } } - @media (min-width: 1400px) { .float-xxl-start { float: left !important; @@ -12365,7 +12309,6 @@ fieldset:disabled .btn { text-align: center !important; } } - @media (min-width: 1200px) { .fs-1 { font-size: 2.5rem !important; @@ -12380,7 +12323,6 @@ fieldset:disabled .btn { font-size: 1.5rem !important; } } - @media print { .d-print-inline { display: inline !important; @@ -12416,27 +12358,26 @@ fieldset:disabled .btn { display: none !important; } } - /* - TALAWA SCSS - ----------- - This file is used to import all partial scss files in the project. - It is used to compile the final CSS file to the CSS folder as main.css . - -========= Table of Contents ========= -1. Components -2. Content -3. Forms -4. Utilities -5. General -6. Colors - -*/ + TALAWA SCSS + ----------- + This file is used to import all partial scss files in the project. + It is used to compile the final CSS file to the CSS folder as main.css . + + ========= Table of Contents ========= + 1. Components + 2. Content + 3. Forms + 4. Utilities + 5. General + 6. Colors + + */ /* - - 1. COMPONENTS - -*/ + + 1. COMPONENTS + + */ .btn-primary, .btn-secondary, .btn-success, @@ -12475,13 +12416,11 @@ fieldset:disabled .btn { background-position-x: 1rem; } } - @keyframes spinner-border { to { transform: rotate(360deg) /* rtl:ignore */; } } - @keyframes spinner-grow { 0% { transform: scale(0); @@ -12491,33 +12430,32 @@ fieldset:disabled .btn { transform: none; } } - /* - - 2. CONTENT - -*/ + + 2. CONTENT + + */ /* - DISPLAY SASS VARIABLES -*/ + DISPLAY SASS VARIABLES + */ /* - DISPLAY SASS VARIABLES -*/ + DISPLAY SASS VARIABLES + */ /* - - 3. FORMS - -*/ + + 3. FORMS + + */ /* - - 4. UTILITIES - -*/ + + 4. UTILITIES + + */ /* - - 5. General - -*/ + + 5. General + + */ :root { --bs-body-font-family: Arial, Helvetica, sans-serif; } @@ -12572,7 +12510,6 @@ input[type='file']::file-selector-button { background-position: 100% 0; } } - @keyframes shimmer { 0% { background-position: -1200px 0; @@ -12581,9 +12518,10 @@ input[type='file']::file-selector-button { background-position: 1200px 0; } } - /* 6. COLORS */ + +/*# sourceMappingURL=app.css.map */ diff --git a/src/assets/css/app.css.map b/src/assets/css/app.css.map new file mode 100644 index 0000000000..00a8ba5443 --- /dev/null +++ b/src/assets/css/app.css.map @@ -0,0 +1 @@ +{"version":3,"sourceRoot":"","sources":["../../../node_modules/bootstrap/scss/mixins/_banner.scss","../../../node_modules/bootstrap/scss/_root.scss","../../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../../node_modules/bootstrap/scss/mixins/_color-mode.scss","../../../node_modules/bootstrap/scss/_reboot.scss","../../../node_modules/bootstrap/scss/_variables.scss","../scss/_variables.scss","../../../node_modules/bootstrap/scss/mixins/_border-radius.scss","../../../node_modules/bootstrap/scss/_type.scss","../../../node_modules/bootstrap/scss/mixins/_lists.scss","../../../node_modules/bootstrap/scss/_images.scss","../../../node_modules/bootstrap/scss/mixins/_image.scss","../../../node_modules/bootstrap/scss/_containers.scss","../../../node_modules/bootstrap/scss/mixins/_container.scss","../../../node_modules/bootstrap/scss/mixins/_breakpoints.scss","../../../node_modules/bootstrap/scss/_grid.scss","../../../node_modules/bootstrap/scss/mixins/_grid.scss","../../../node_modules/bootstrap/scss/_tables.scss","../../../node_modules/bootstrap/scss/mixins/_table-variants.scss","../../../node_modules/bootstrap/scss/forms/_labels.scss","../../../node_modules/bootstrap/scss/forms/_form-text.scss","../../../node_modules/bootstrap/scss/forms/_form-control.scss","../../../node_modules/bootstrap/scss/mixins/_transition.scss","../../../node_modules/bootstrap/scss/mixins/_gradients.scss","../../../node_modules/bootstrap/scss/forms/_form-select.scss","../../../node_modules/bootstrap/scss/forms/_form-check.scss","../../../node_modules/bootstrap/scss/forms/_form-range.scss","../../../node_modules/bootstrap/scss/forms/_floating-labels.scss","../../../node_modules/bootstrap/scss/forms/_input-group.scss","../../../node_modules/bootstrap/scss/mixins/_forms.scss","../../../node_modules/bootstrap/scss/_buttons.scss","../../../node_modules/bootstrap/scss/mixins/_buttons.scss","../../../node_modules/bootstrap/scss/_transitions.scss","../../../node_modules/bootstrap/scss/_dropdown.scss","../../../node_modules/bootstrap/scss/mixins/_caret.scss","../../../node_modules/bootstrap/scss/_button-group.scss","../../../node_modules/bootstrap/scss/_nav.scss","../../../node_modules/bootstrap/scss/_navbar.scss","../../../node_modules/bootstrap/scss/_card.scss","../../../node_modules/bootstrap/scss/_accordion.scss","../../../node_modules/bootstrap/scss/_breadcrumb.scss","../../../node_modules/bootstrap/scss/_pagination.scss","../../../node_modules/bootstrap/scss/mixins/_pagination.scss","../../../node_modules/bootstrap/scss/_badge.scss","../../../node_modules/bootstrap/scss/_alert.scss","../../../node_modules/bootstrap/scss/_progress.scss","../../../node_modules/bootstrap/scss/_list-group.scss","../../../node_modules/bootstrap/scss/_close.scss","../../../node_modules/bootstrap/scss/_toasts.scss","../../../node_modules/bootstrap/scss/_modal.scss","../../../node_modules/bootstrap/scss/mixins/_backdrop.scss","../../../node_modules/bootstrap/scss/_tooltip.scss","../../../node_modules/bootstrap/scss/mixins/_reset-text.scss","../../../node_modules/bootstrap/scss/_popover.scss","../../../node_modules/bootstrap/scss/_carousel.scss","../../../node_modules/bootstrap/scss/mixins/_clearfix.scss","../../../node_modules/bootstrap/scss/_spinners.scss","../../../node_modules/bootstrap/scss/_offcanvas.scss","../../../node_modules/bootstrap/scss/_placeholders.scss","../../../node_modules/bootstrap/scss/helpers/_color-bg.scss","../../../node_modules/bootstrap/scss/helpers/_colored-links.scss","../../../node_modules/bootstrap/scss/helpers/_focus-ring.scss","../../../node_modules/bootstrap/scss/helpers/_icon-link.scss","../../../node_modules/bootstrap/scss/helpers/_ratio.scss","../../../node_modules/bootstrap/scss/helpers/_position.scss","../../../node_modules/bootstrap/scss/helpers/_stacks.scss","../../../node_modules/bootstrap/scss/helpers/_visually-hidden.scss","../../../node_modules/bootstrap/scss/mixins/_visually-hidden.scss","../../../node_modules/bootstrap/scss/helpers/_stretched-link.scss","../../../node_modules/bootstrap/scss/helpers/_text-truncation.scss","../../../node_modules/bootstrap/scss/mixins/_text-truncate.scss","../../../node_modules/bootstrap/scss/helpers/_vr.scss","../../../node_modules/bootstrap/scss/mixins/_utilities.scss","../../../node_modules/bootstrap/scss/utilities/_api.scss","../scss/_talawa.scss","../scss/components/_buttons.scss","../scss/components/_progress.scss","../scss/components/_spinners.scss","../scss/content/_typography.scss","../scss/_general.scss"],"names":[],"mappings":"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N;EACE;;;AAOJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAOE;;;AAGF;EACE;;;AASF;EACE;EACA;;;AAQF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWA;EACE;;;AAKF;EACE;;;AAOF;EACE;EACA;;;AAKF;EACE;;;AAKF;EACE;;;AAOF;EACE;EACA;;;AAQF;EACE;;;AAQF;EACE;;;AIpkBF;ENmQM,WALI;EM5PR,aHwoB4B;;;AGnoB5B;ENgQM;EM5PJ,aHynBkB;EGxnBlB,aHwmB0B;;AHzgB1B;EMpGF;INuQM;;;;AMvQN;ENgQM;EM5PJ,aHynBkB;EGxnBlB,aHwmB0B;;AHzgB1B;EMpGF;INuQM;;;;AMvQN;ENgQM;EM5PJ,aHynBkB;EGxnBlB,aHwmB0B;;AHzgB1B;EMpGF;INuQM;;;;AMvQN;ENgQM;EM5PJ,aHynBkB;EGxnBlB,aHwmB0B;;AHzgB1B;EMpGF;INuQM;;;;AMvQN;ENgQM;EM5PJ,aHynBkB;EGxnBlB,aHwmB0B;;AHzgB1B;EMpGF;INuQM;;;;AMvQN;ENgQM;EM5PJ,aHynBkB;EGxnBlB,aHwmB0B;;AHzgB1B;EMpGF;INuQM;;;;AM/OR;ECvDE;EACA;;;AD2DF;EC5DE;EACA;;;AD8DF;EACE;;AAEA;EACE,cHkoB0B;;;AGxnB9B;EN8MM,WALI;EMvMR;;;AAIF;EACE,eHiUO;EH1HH,WALI;;AM/LR;EACE;;;AAIJ;EACE;EACA,eHuTO;EH1HH,WALI;EMtLR,OHtFS;;AGwFT;EACE;;;AEhGJ;ECIE;EAGA;;;ADDF;EACE,SLyjDkC;EKxjDlC,kBLyjDkC;EKxjDlC;EHGE;EIRF;EAGA;;;ADcF;EAEE;;;AAGF;EACE;EACA;;;AAGF;ERyPM,WALI;EQlPR,OL4iDkC;;;AO9kDlC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ECHA;EACA;EACA;EACA;EACA;EACA;EACA;;;ACsDE;EF5CE;IACE,WPkee;;;ASvbnB;EF5CE;IACE,WPkee;;;ASvbnB;EF5CE;IACE,WPkee;;;ASvbnB;EF5CE;IACE,WPkee;;;ASvbnB;EF5CE;IACE,WPkee;;;AUl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B9B;EACA;EACA;EACA;EACA,yBf9EiB;Ee+EjB;ECzFE,YD0FF;;ACtFE;ED0EJ;ICzEM;;;ADwFN;EACE,kBhBs7B8B;;;AgB76BlC;EACE;EACA;EACA;EACA;EACA,ahBwf4B;EgBvf5B,OhBqxBsC;EgBpxBtC;EACA;EACA;;AAEA;EACE;;AAGF;EAEE;EACA;;;AAWJ;EACE,YhBswBsC;EgBrwBtC;EnByII,WALI;EKvQN;;AcuIF;EACE;EACA;EACA,mBhB+nB0B;;;AgB3nB9B;EACE,YhB0vBsC;EgBzvBtC;EnB4HI,WALI;EKvQN;;AcoJF;EACE;EACA;EACA,mBhBsnB0B;;;AgB9mB5B;EACE,YhBuuBoC;;AgBpuBtC;EACE,YhBouBoC;;AgBjuBtC;EACE,YhBiuBoC;;;AgB5tBxC;EACE,OhB+tBsC;EgB9tBtC,QhBwtBsC;EgBvtBtC,SfvKoB;;AeyKpB;EACE;;AAGF;EACE;EdvLA;;Ac2LF;EACE;Ed5LA;;AcgMF;EAAoB,QhBwsBkB;;AgBvsBtC;EAAoB,QhBwsBkB;;;AmBv5BxC;EACE;EAEA;EACA;EACA;EtBqRI,WALI;EsB7QR,anB+lB4B;EmB9lB5B,anBsmB4B;EmBrmB5B,OnBm3BsC;EmBl3BtC,kBlBCe;EkBAf;EACA;EACA,qBnB09BkC;EmBz9BlC,iBnB09BkC;EmBz9BlC;EjBFE;EeHE,YEQJ;EACA;;AFLI;EEfN;IFgBQ;;;AEMN;EACE,cnBg3BoC;EmB/2BpC;EAKE,YnB29B4B;;AmBv9BhC;EAEE,elBXkB;EkBYlB;;AAGF;EAEE,kBnBi1BoC;;AmB50BtC;EACE;EACA;;;AAIJ;EACE,anBiuB4B;EmBhuB5B,gBnBguB4B;EmB/tB5B,cnBguB4B;EH7fxB,WALI;EKvQN;;;AiB8CJ;EACE,anB6tB4B;EmB5tB5B,gBnB4tB4B;EmB3tB5B,cnB4tB4B;EHjgBxB,WALI;EKvQN;;;AiBwDA;EACE;;;ACxEN;EACE;EACA,YpB+5BwC;EoB95BxC,cpB+5BwC;EoB95BxC,epB+5BwC;;AoB75BxC;EACE;EACA;;;AAIJ;EACE,epBq5BwC;EoBp5BxC;EACA;;AAEA;EACE;EACA;EACA;;;AAIJ;EACE;EAEA,OpBq4BwC;EoBp4BxC,QpBo4BwC;EoBn4BxC;EACA;EACA;EACA;EACA;EACA;EACA;EACA,QpBu4BwC;EoBt4BxC;EACA;;AAGA;ElB1BE;;AkB8BF;EAEE,epB83BsC;;AoB33BxC;EACE,QpBq3BsC;;AoBl3BxC;EACE,cpBi1BoC;EoBh1BpC;EACA,YpB+foB;;AoB5ftB;EACE,kBnB/DM;EmBgEN,cnBhEM;;AmBkEN;EAII;;AAIJ;EAII;;AAKN;EACE,kBnBpFM;EmBqFN,cnBrFM;EmB0FJ;;AAIJ;EACE;EACA;EACA,SpB61BuC;;AoBt1BvC;EACE;EACA,SpBo1BqC;;;AoBt0B3C;EACE,cpB+0BgC;;AoB70BhC;EACE;EAEA,OpBy0B8B;EoBx0B9B;EACA;EACA;ElBhHA;EeHE,YGqHF;;AHjHE;EGyGJ;IHxGM;;;AGkHJ;EACE;;AAGF;EACE,qBpBw0B4B;EoBn0B1B;;AAKN;EACE,epBmzB8B;EoBlzB9B;;AAEA;EACE;EACA;;;AAKN;EACE;EACA,cpBiyBgC;;;AoB9xBlC;EACE;EACA;EACA;;AAIE;EACE;EACA;EACA,SpBkpBwB;;;AoB3oB1B;EACE;;;AClLN;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAIA;EAA0B,YrBwgCa;;AqBvgCvC;EAA0B,YrBugCa;;AqBpgCzC;EACE;;AAGF;EACE,OrBy/BuC;EqBx/BvC,QrBw/BuC;EqBv/BvC;EHzBF,kBjBFQ;EoB6BN,QrBw/BuC;EEpgCvC;EeHE,YIkBF;EACA;;AJfE;EIMJ;IJLM;;;AIgBJ;EHjCF,kBlBwhCyC;;AqBl/BzC;EACE,OrBk+B8B;EqBj+B9B,QrBk+B8B;EqBj+B9B;EACA,QrBi+B8B;EqBh+B9B,kBrBi+B8B;EqBh+B9B;EnB7BA;;AmBkCF;EACE,OrB89BuC;EqB79BvC,QrB69BuC;EkBhhCzC,kBjBFQ;EoBuDN,QrB89BuC;EEpgCvC;EeHE,YI4CF;EACA;;AJzCE;EIiCJ;IJhCM;;;AI0CJ;EH3DF,kBlBwhCyC;;AqBx9BzC;EACE,OrBw8B8B;EqBv8B9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ALI;E4BhRR;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;E5BsQI,WALI;E4B/PR;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EvBjBE;EgBfF,kBOkCqB;ERtBjB,YQwBJ;;ARpBI;EQhBN;IRiBQ;;;AQqBN;EACE;EAEA;EACA;;AAGF;EAEE;EACA;EACA;;AAGF;EACE;EPrDF,kBOsDuB;EACrB;EACA;EAKE;;AAIJ;EACE;EACA;EAKE;;AAIJ;EAKE;EACA;EAGA;;AAGA;EAKI;;AAKN;EAGE;EACA;EACA;EAEA;EACA;;;AAYF;ECtGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;ADyFA;ECtGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;ADyFA;ECtGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;ADyFA;ECtGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;ADyFA;ECtGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;ADyFA;ECtGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;ADyFA;ECtGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;ADyFA;ECtGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;ADmHA;ECvGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AD0FA;ECvGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AD0FA;ECvGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AD0FA;ECvGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AD0FA;ECvGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AD0FA;ECvGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AD0FA;ECvGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AD0FA;ECvGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;ADsGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA,iBxBxJgB;;AwBkKhB;EACE;;AAGF;EACE;;;AAWJ;ECxIE;EACA;E7B8NI,oBALI;E6BvNR;;;ADyIF;EC5IE;EACA;E7B8NI,oBALI;E6BvNR;;;ACnEF;EVgBM,YUfJ;;AVmBI;EUpBN;IVqBQ;;;AUlBN;EACE;;;AAMF;EACE;;;AAIJ;EACE;EACA;EVDI,YUEJ;;AVEI;EULN;IVMQ;;;AUDN;EACE;EACA;EVNE,YUOF;;AVHE;EUAJ;IVCM;;;;AWpBR;AAAA;AAAA;AAAA;AAAA;AAAA;EAME;;;AAGF;EACE;;ACwBE;EACE;EACA,a7B6hBwB;E6B5hBxB,gB7B2hBwB;E6B1hBxB;EArCJ;EACA;EACA;EACA;;AA0DE;EACE;;;AD9CN;EAEE;EACA;EACA;EACA;EACA;E/BuQI,yBALI;E+BhQR;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EACA;EACA;E/B0OI,WALI;E+BnOR;EACA;EACA;EACA;EACA;EACA;E1BzCE;;A0B6CF;EACE;EACA;EACA;;;AAwBA;EACE;;AAEA;EACE;EACA;;;AAIJ;EACE;;AAEA;EACE;EACA;;;AnB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EAEE;EACA;EAEA;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EACA;;AAGE;EAEE;;AAIJ;EACE;;;AASJ;EACE,ahCwgCkC;EgCvgClC,gBhCugCkC;EgCtgClC;;AAEA;AAAA;AAAA;EAGE;;;AAaJ;EACE;EACA;EAGA;;;AAIF;EACE;EnCyII,WALI;EmClIR;EACA;EACA;EACA;E9BxIE;EeHE,Ye6IJ;;AfzII;EeiIN;IfhIQ;;;Ae0IN;EACE;;AAGF;EACE;EACA;EACA;;;AAMJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AvB1HE;EuBsIA;IAEI;IACA;;EAEA;IACE;;EAEA;IACE;;EAGF;IACE;IACA;;EAIJ;IACE;;EAGF;IACE;IACA;;EAGF;IACE;;EAGF;IAEE;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;If9NJ,YegOI;;EAGA;IACE;;EAGF;IACE;IACA;IACA;IACA;;;AvB5LR;EuBsIA;IAEI;IACA;;EAEA;IACE;;EAEA;IACE;;EAGF;IACE;IACA;;EAIJ;IACE;;EAGF;IACE;IACA;;EAGF;IACE;;EAGF;IAEE;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;If9NJ,YegOI;;EAGA;IACE;;EAGF;IACE;IACA;IACA;IACA;;;AvB5LR;EuBsIA;IAEI;IACA;;EAEA;IACE;;EAEA;IACE;;EAGF;IACE;IACA;;EAIJ;IACE;;EAGF;IACE;IACA;;EAGF;IACE;;EAGF;IAEE;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;If9NJ,YegOI;;EAGA;IACE;;EAGF;IACE;IACA;IACA;IACA;;;AvB5LR;EuBsIA;IAEI;IACA;;EAEA;IACE;;EAEA;IACE;;EAGF;IACE;IACA;;EAIJ;IACE;;EAGF;IACE;IACA;;EAGF;IACE;;EAGF;IAEE;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;If9NJ,YegOI;;EAGA;IACE;;EAGF;IACE;IACA;IACA;IACA;;;AvB5LR;EuBsIA;IAEI;IACA;;EAEA;IACE;;EAEA;IACE;;EAGF;IACE;IACA;;EAIJ;IACE;;EAGF;IACE;IACA;;EAGF;IACE;;EAGF;IAEE;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;If9NJ,YegOI;;EAGA;IACE;;EAGF;IACE;IACA;IACA;IACA;;;AAtDR;EAEI;EACA;;AAEA;EACE;;AAEA;EACE;;AAGF;EACE;EACA;;AAIJ;EACE;;AAGF;EACE;EACA;;AAGF;EACE;;AAGF;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;Ef9NJ,YegOI;;AAGA;EACE;;AAGF;EACE;EACA;EACA;EACA;;;AAiBZ;AAAA;EAGE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAME;EACE;;;ACzRN;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;E/BjBE;;A+BqBF;EACE;EACA;;AAGF;EACE;EACA;;AAEA;EACE;E/BtBF;EACA;;A+ByBA;EACE;E/BbF;EACA;;A+BmBF;AAAA;EAEE;;;AAIJ;EAGE;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AAQA;EACE;;;AAQJ;EACE;EACA;EACA;EACA;EACA;;AAEA;E/B7FE;;;A+BkGJ;EACE;EACA;EACA;EACA;;AAEA;E/BxGE;;;A+BkHJ;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;;;AAIJ;EACE;EACA;;;AAIF;EACE;EACA;EACA;EACA;EACA;EACA;E/B1IE;;;A+B8IJ;AAAA;AAAA;EAGE;;;AAGF;AAAA;E/B3II;EACA;;;A+B+IJ;AAAA;E/BlII;EACA;;;A+B8IF;EACE;;AxB3HA;EwBuHJ;IAQI;IACA;;EAGA;IAEE;IACA;;EAEA;IACE;IACA;;EAKA;I/B3KJ;IACA;;E+B6KM;AAAA;IAGE;;EAEF;AAAA;IAGE;;EAIJ;I/B5KJ;IACA;;E+B8KM;AAAA;IAGE;;EAEF;AAAA;IAGE;;;;ACpOZ;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAIF;EACE;EACA;EACA;EACA;EACA;ErC2PI,WALI;EqCpPR;EACA;EACA;EACA;EhCtBE;EgCwBF;EjB3BI,YiB4BJ;;AjBxBI;EiBWN;IjBVQ;;;AiByBN;EACE;EACA;EACA;;AAEA;EACE;EACA;;AAKJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EjBlDE,YiBmDF;;AjB/CE;EiBsCJ;IjBrCM;;;AiBiDN;EACE;;AAGF;EACE;EACA;EACA;EACA;;;AAIJ;EACE;;;AAGF;EACE;EACA;EACA;;AAEA;EhC/DE;EACA;;AgCiEA;EhClEA;EACA;;AgCsEF;EACE;;AAIF;EhC9DE;EACA;;AgCiEE;EhClEF;EACA;;AgCsEA;EhCvEA;EACA;;;AgC4EJ;EACE;;;AASA;EACE;;AAGF;EACE;EACA;EhCpHA;;AgCuHA;EAAgB;;AAChB;EAAe;;AAGb;EhC3HF;;;AgCqIA;EACE;EACA;;;AC1JN;EAEE;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EtC+QI,WALI;EsCxQR;EACA;EjCAE;;;AiCMF;EACE;;AAEA;EACE;EACA;EACA;EACA;;AAIJ;EACE;;;ACrCJ;EAEE;EACA;EvC4RI,2BALI;EuCrRR;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAGA;EhCpBA;EACA;;;AgCuBF;EACE;EACA;EACA;EvCgQI,WALI;EuCzPR;EAEA;EACA;EnBpBI,YmBqBJ;;AnBjBI;EmBQN;InBPQ;;;AmBkBN;EACE;EACA;EAEA;EACA;;AAGF;EACE;EACA;EACA;EACA,SpCouCgC;EoCnuChC;;AAGF;EAEE;EACA;ElBtDF,kBkBuDuB;EACrB;;AAGF;EAEE;EACA;EACA;EACA;;;AAKF;EACE,apCusCgC;;AoClsC9B;ElC9BF;EACA;;AkCmCE;ElClDF;EACA;;;AkCkEJ;EClGE;EACA;ExC0RI,2BALI;EwCnRR;;;ADmGF;ECtGE;EACA;ExC0RI,2BALI;EwCnRR;;;ACFF;EAEE;EACA;EzCuRI,sBALI;EyChRR;EACA;EACA;EAGA;EACA;EzC+QI,WALI;EyCxQR;EACA;EACA;EACA;EACA;EACA;EpCJE;;AoCSF;EACE;;;AAKJ;EACE;EACA;;;AChCF;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EACA;EACA;ErCHE;;;AqCQJ;EAEE;;;AAIF;EACE,avC6kB4B;EuC5kB5B;;;AAQF;EACE,evCg+C8B;;AuC79C9B;EACE;EACA;EACA;EACA;EACA;;;AAQF;EACE;EACA;EACA;EACA;;;AAJF;EACE;EACA;EACA;EACA;;;AAJF;EACE;EACA;EACA;EACA;;;AAJF;EACE;EACA;EACA;EACA;;;AAJF;EACE;EACA;EACA;EACA;;;AAJF;EACE;EACA;EACA;EACA;;;AAJF;EACE;EACA;EACA;EACA;;;AAJF;EACE;EACA;EACA;EACA;;;AC5DF;EACE;IAAK,uBxCmhD2B;;;AwC9gDpC;AAAA;EAGE;E3CkRI,yBALI;E2C3QR;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;E3CsQI,WALI;E2C/PR;EtCRE;;;AsCaJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EvBxBI,YuByBJ;;AvBrBI;EuBYN;IvBXQ;;;;AuBuBR;EtBAE;EsBEA;;;AAGF;EACE;;;AAGF;EACE;;;AAIA;EACE;;AAGE;EAJJ;IAKM;;;;AC3DR;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;EAGA;EACA;EvCXE;;;AuCeJ;EACE;EACA;;AAEA;EAEE;EACA;;;AASJ;EACE;EACA;EACA;;AAGA;EAEE;EACA;EACA;EACA;;AAGF;EACE;EACA;;;AAQJ;EACE;EACA;EACA;EACA;EAEA;EACA;;AAEA;EvCvDE;EACA;;AuC0DF;EvC7CE;EACA;;AuCgDF;EAEE;EACA;EACA;;AAIF;EACE;EACA;EACA;EACA;;AAIF;EACE;;AAEA;EACE;EACA;;;AAaF;EACE;;AAGE;EvCvDJ;EAZA;;AuCwEI;EvCxEJ;EAYA;;AuCiEI;EACE;;AAGF;EACE;EACA;;AAEA;EACE;EACA;;;AhCtFR;EgC8DA;IACE;;EAGE;IvCvDJ;IAZA;;EuCwEI;IvCxEJ;IAYA;;EuCiEI;IACE;;EAGF;IACE;IACA;;EAEA;IACE;IACA;;;AhCtFR;EgC8DA;IACE;;EAGE;IvCvDJ;IAZA;;EuCwEI;IvCxEJ;IAYA;;EuCiEI;IACE;;EAGF;IACE;IACA;;EAEA;IACE;IACA;;;AhCtFR;EgC8DA;IACE;;EAGE;IvCvDJ;IAZA;;EuCwEI;IvCxEJ;IAYA;;EuCiEI;IACE;;EAGF;IACE;IACA;;EAEA;IACE;IACA;;;AhCtFR;EgC8DA;IACE;;EAGE;IvCvDJ;IAZA;;EuCwEI;IvCxEJ;IAYA;;EuCiEI;IACE;;EAGF;IACE;IACA;;EAEA;IACE;IACA;;;AhCtFR;EgC8DA;IACE;;EAGE;IvCvDJ;IAZA;;EuCwEI;IvCxEJ;IAYA;;EuCiEI;IACE;;EAGF;IACE;IACA;;EAEA;IACE;IACA;;;AAcZ;EvChJI;;AuCmJF;EACE;;AAEA;EACE;;;AAaJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAVF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAVF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAVF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAVF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAVF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAVF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAVF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AC5LJ;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAGA;EACA,O1C+oD2B;E0C9oD3B,Q1C8oD2B;E0C7oD3B;EACA;EACA;EACA;ExCJE;EwCMF;;AAGA;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;;AAGF;EAEE;EACA;EACA;;;AAQJ;EAHE;;;AASE;EATF;;;ACjDF;EAEE;EACA;EACA;EACA;EACA;E9CyRI,sBALI;E8ClRR;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;E9C2QI,WALI;E8CpQR;EACA;EACA;EACA;EACA;EACA;EzCRE;;AyCWF;EACE;;AAGF;EACE;;;AAIJ;EACE;EAEA;EACA;EACA;EACA;EACA;;AAEA;EACE;;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EzChCE;EACA;;AyCkCF;EACE;EACA;;;AAIJ;EACE;EACA;;;AC9DF;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAGA;;;AAOF;EACE;EACA;EACA;EAEA;;AAGA;E3B5CI,Y2B6CF;EACA,W5Cy7CgC;;AiBn+C9B;E2BwCJ;I3BvCM;;;A2B2CN;EACE,W5Cu7CgC;;A4Cn7ClC;EACE,W5Co7CgC;;;A4Ch7CpC;EACE;;AAEA;EACE;EACA;;AAGF;EACE;;;AAIJ;EACE;EACA;EACA;;;AAIF;EACE;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;E1CrFE;E0CyFF;;;AAIF;EAEE;EACA;EACA;EClHA;EACA;EACA;EACA,SDkH0B;ECjH1B;EACA;EACA,kBD+G4D;;AC5G5D;EAAS;;AACT;EAAS,SD2GiF;;;AAK5F;EACE;EACA;EACA;EACA;EACA;EACA;E1CtGE;EACA;;A0CwGF;EACE;EACA;;;AAKJ;EACE;EACA;;;AAKF;EACE;EAGA;EACA;;;AAIF;EACE;EACA;EACA;EACA;EACA;E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;IACA;IACA;IACA;IACA;;EAGF;IACE;IACA;IACA;IACA;IACA;;EAGF;IACE;IACA;IACA;IACA;IACA;IACA;IACA;;EAGF;IACE;IACA;IACA;IACA;IACA;IACA;;EAGF;IAEE;;EAGF;IAGE;;;A3C5BJ;E2C/BF;IAiEM;IACA;IACA;;EAEA;IACE;;EAGF;IACE;IACA;IACA;IACA;IAEA;;;;A3CnCN;E2C5CF;IAEI;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;InC5BA,YmC8BA;;;AnC1BA;EmCYJ;InCXM;;;ARuDJ;E2C5BE;IACE;IACA;IACA;IACA;IACA;;EAGF;IACE;IACA;IACA;IACA;IACA;;EAGF;IACE;IACA;IACA;IACA;IACA;IACA;IACA;;EAGF;IACE;IACA;IACA;IACA;IACA;IACA;;EAGF;IAEE;;EAGF;IAGE;;;A3C5BJ;E2C/BF;IAiEM;IACA;IACA;;EAEA;IACE;;EAGF;IACE;IACA;IACA;IACA;IAEA;;;;A3CnCN;E2C5CF;IAEI;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;InC5BA,YmC8BA;;;AnC1BA;EmCYJ;InCXM;;;ARuDJ;E2C5BE;IACE;IACA;IACA;IACA;IACA;;EAGF;IACE;IACA;IACA;IACA;IACA;;EAGF;IACE;IACA;IACA;IACA;IACA;IACA;IACA;;EAGF;IACE;IACA;IACA;IACA;IACA;IACA;;EAGF;IAEE;;EAGF;IAGE;;;A3C5BJ;E2C/BF;IAiEM;IACA;IACA;;EAEA;IACE;;EAGF;IACE;IACA;IACA;IACA;IAEA;;;;A3CnCN;E2C5CF;IAEI;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;InC5BA,YmC8BA;;;AnC1BA;EmCYJ;InCXM;;;ARuDJ;E2C5BE;IACE;IACA;IACA;IACA;IACA;;EAGF;IACE;IACA;IACA;IACA;IACA;;EAGF;IACE;IACA;IACA;IACA;IACA;IACA;IACA;;EAGF;IACE;IACA;IACA;IACA;IACA;IACA;;EAGF;IAEE;;EAGF;IAGE;;;A3C5BJ;E2C/BF;IAiEM;IACA;IACA;;EAEA;IACE;;EAGF;IACE;IACA;IACA;IACA;IAEA;;;;A3CnCN;E2C5CF;IAEI;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;InC5BA,YmC8BA;;;AnC1BA;EmCYJ;InCXM;;;ARuDJ;E2C5BE;IACE;IACA;IACA;IACA;IACA;;EAGF;IACE;IACA;IACA;IACA;IACA;;EAGF;IACE;IACA;IACA;IACA;IACA;IACA;IACA;;EAGF;IACE;IACA;IACA;IACA;IACA;IACA;;EAGF;IAEE;;EAGF;IAGE;;;A3C5BJ;E2C/BF;IAiEM;IACA;IACA;;EAEA;IACE;;EAGF;IACE;IACA;IACA;IACA;IAEA;;;;AA/ER;EAEI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EnC5BA,YmC8BA;;AnC1BA;EmCYJ;InCXM;;;AmC2BF;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAGF;EAEE;;AAGF;EAGE;;;AA2BR;EPpHE;EACA;EACA;EACA,S7ComCkC;E6CnmClC;EACA;EACA,kB7CUS;;A6CPT;EAAS;;AACT;EAAS,S7C09CyB;;;AoD52CpC;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;;;AAIJ;EACE;EACA;;;AAGF;EACE;EACA;EACA;;;AChJF;EACE;EACA;EACA;EACA;EACA;EACA,SrDyyCkC;;AqDvyClC;EACE;EACA;;;AAKJ;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAKA;EACE;;;AAIJ;EACE;IACE,SrD4wCgC;;;AqDxwCpC;EACE;EACA;EACA;;;AAGF;EACE;IACE;;;AH9CF;EACE;EACA;EACA;;;AIFF;EACE;EACA;;;AAFF;EACE;EACA;;;AAFF;EACE;EACA;;;AAFF;EACE;EACA;;;AAFF;EACE;EACA;;;AAFF;EACE;EACA;;;AAFF;EACE;EACA;;;AAFF;EACE;EACA;;;ACHF;EACE;EACA;;AAGE;EAGE;EACA;;;AATN;EACE;EACA;;AAGE;EAGE;EACA;;;AATN;EACE;EACA;;AAGE;EAGE;EACA;;;AATN;EACE;EACA;;AAGE;EAGE;EACA;;;AATN;EACE;EACA;;AAGE;EAGE;EACA;;;AATN;EACE;EACA;;AAGE;EAGE;EACA;;;AATN;EACE;EACA;;AAGE;EAGE;EACA;;;AATN;EACE;EACA;;AAGE;EAGE;EACA;;;AAOR;EACE;EACA;;AAGE;EAEE;EACA;;;AC1BN;EACE;EAEA;;;ACHF;EACE;EACA,KzD6c4B;EyD5c5B;EACA;EACA,uBzD2c4B;EyD1c5B;;AAEA;EACE;EACA,OzDuc0B;EyDtc1B,QzDsc0B;EyDrc1B;ExCIE,YwCHF;;AxCOE;EwCZJ;IxCaM;;;;AwCDJ;EACE;;;ACnBN;EACE;EACA;;AAEA;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAKF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;ACrBJ;EACE;EACA;EACA;EACA;EACA,S3DimCkC;;;A2D9lCpC;EACE;EACA;EACA;EACA;EACA,S3DylCkC;;;A2DjlChC;EACE;EACA;EACA,S3D6kC8B;;;A2D1kChC;EACE;EACA;EACA,S3DukC8B;;;ASxiChC;EkDxCA;IACE;IACA;IACA,S3D6kC8B;;E2D1kChC;IACE;IACA;IACA,S3DukC8B;;;ASxiChC;EkDxCA;IACE;IACA;IACA,S3D6kC8B;;E2D1kChC;IACE;IACA;IACA,S3DukC8B;;;ASxiChC;EkDxCA;IACE;IACA;IACA,S3D6kC8B;;E2D1kChC;IACE;IACA;IACA,S3DukC8B;;;ASxiChC;EkDxCA;IACE;IACA;IACA,S3D6kC8B;;E2D1kChC;IACE;IACA;IACA,S3DukC8B;;;ASxiChC;EkDxCA;IACE;IACA;IACA,S3D6kC8B;;E2D1kChC;IACE;IACA;IACA,S3DukC8B;;;A4DtmCpC;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;ACRF;AAAA;ECIE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGA;AAAA;EACE;;;ACdF;EACE;EACA;EACA;EACA;EACA;EACA,S/DgcsC;E+D/btC;;;ACRJ;ECAE;EACA;EACA;;;ACNF;EACE;EACA;EACA;EACA;EACA;EACA,SlE2rB4B;;;AmE/nBtB;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAjBJ;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AASF;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAIQ;EAGJ;;;AAPJ;EAIQ;EAGJ;;;AAPJ;EAIQ;EAGJ;;;AAPJ;EAIQ;EAGJ;;;AAPJ;EAIQ;EAGJ;;;AAPJ;EAIQ;EAGJ;;;AAPJ;EAIQ;EAGJ;;;AAPJ;EAIQ;EAGJ;;;AAPJ;EAIQ;EAGJ;;;AAPJ;EAIQ;EAGJ;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAjBJ;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AASF;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;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;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;EAAA;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;AAPJ;EAOI;;;A1DVR;E0DGI;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;;A1DVR;E0DGI;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;;A1DVR;E0DGI;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;;A1DVR;E0DGI;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;;A1DVR;E0DGI;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;IAAA;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;;ACtDZ;ED+CQ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;;ACnCZ;ED4BQ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;EAPJ;IAOI;;;AEzEZ;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAgBA;;AAAA;;AAAA;ACmCA;AAAA;AAAA;AAAA;AAAA;EAKE,OtEhDS;;AsEiDT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAEE;;;AASF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAEE;;;AC3DF;EACE;IACE,uBAbY;;;ACUlB;EACE;IACE;;;AAGJ;EACE;IACE;;EAEF;IACE;IACA;;;AHuDJ;;AAAA;;AAAA;AI5EA;AAAA;AAAA;AAkBA;AAAA;AAAA;AJsEA;;AAAA;;AAAA;AA2BA;;AAAA;;AAAA;AAQA;;AAAA;;AAAA;AK3HA;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;IACE;;EAGF;IACE;;;AAIJ;EACE;IACE;;EAGF;IACE;;;ALsEJ;;AAAA;;AAAA","file":"app.css"} \ No newline at end of file diff --git a/src/assets/css/scrollStyles.css b/src/assets/css/scrollStyles.css new file mode 100644 index 0000000000..71248ac1b6 --- /dev/null +++ b/src/assets/css/scrollStyles.css @@ -0,0 +1,18 @@ +.customScroll { + overflow-y: scroll; +} +.customScroll::-webkit-scrollbar { + width: 5px; +} +.customScroll::-webkit-scrollbar-track { + background: #f1f1f1; + border-radius: 6px; +} +.customScroll::-webkit-scrollbar-thumb { + background: var(--bs-gray-500); + border-radius: 6px; +} +.customScroll::-webkit-scrollbar-thumb:hover { + background: var(--bs-gray-600); + border-radius: 6px; +} diff --git a/src/assets/scss/components/_accordion.scss b/src/assets/scss/components/_accordion.scss index 96be1dbcfa..64eb323b55 100644 --- a/src/assets/scss/components/_accordion.scss +++ b/src/assets/scss/components/_accordion.scss @@ -17,7 +17,9 @@ $accordion-button-padding-y: $accordion-padding-y; $accordion-button-padding-x: $accordion-padding-x; $accordion-button-color: var(--#{$prefix}body-color); $accordion-button-bg: var(--#{$prefix}accordion-bg); -$accordion-transition: $btn-transition, border-radius 0.15s ease; +$accordion-transition: + $btn-transition, + border-radius 0.15s ease; $accordion-button-active-bg: var(--#{$prefix}primary-bg-subtle); $accordion-button-active-color: var(--#{$prefix}primary-text-emphasis); diff --git a/src/assets/scss/components/_buttons.scss b/src/assets/scss/components/_buttons.scss index 1301eaf5a8..c0400fbeae 100644 --- a/src/assets/scss/components/_buttons.scss +++ b/src/assets/scss/components/_buttons.scss @@ -17,7 +17,9 @@ $btn-font-size-lg: $input-btn-font-size-lg; $btn-border-width: $input-btn-border-width; $btn-font-weight: $font-weight-normal; -$btn-box-shadow: inset 0 1px 0 rgba($white, 0.15), 0 1px 1px rgba($black, 0.075); +$btn-box-shadow: + inset 0 1px 0 rgba($white, 0.15), + 0 1px 1px rgba($black, 0.075); $btn-focus-width: $input-btn-focus-width; $btn-focus-box-shadow: $input-btn-focus-box-shadow; $btn-disabled-opacity: 0.65; @@ -32,8 +34,11 @@ $btn-border-radius: var(--#{$prefix}border-radius); $btn-border-radius-sm: var(--#{$prefix}border-radius-sm); $btn-border-radius-lg: var(--#{$prefix}border-radius-lg); -$btn-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, - border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +$btn-transition: + color 0.15s ease-in-out, + background-color 0.15s ease-in-out, + border-color 0.15s ease-in-out, + box-shadow 0.15s ease-in-out; $btn-hover-bg-shade-amount: 15%; $btn-hover-bg-tint-amount: 15%; diff --git a/src/assets/scss/components/_nav.scss b/src/assets/scss/components/_nav.scss index 1474454488..84aeab343c 100644 --- a/src/assets/scss/components/_nav.scss +++ b/src/assets/scss/components/_nav.scss @@ -4,8 +4,10 @@ $nav-link-font-size: null; $nav-link-font-weight: null; $nav-link-color: var(--#{$prefix}link-color); $nav-link-hover-color: var(--#{$prefix}link-hover-color); -$nav-link-transition: color 0.15s ease-in-out, - background-color 0.15s ease-in-out, border-color 0.15s ease-in-out; +$nav-link-transition: + color 0.15s ease-in-out, + background-color 0.15s ease-in-out, + border-color 0.15s ease-in-out; $nav-link-disabled-color: var(--#{$prefix}secondary-color); $nav-link-focus-box-shadow: $focus-ring-box-shadow; diff --git a/src/assets/scss/components/_pagination.scss b/src/assets/scss/components/_pagination.scss index 4bb3888854..830c140492 100644 --- a/src/assets/scss/components/_pagination.scss +++ b/src/assets/scss/components/_pagination.scss @@ -35,9 +35,10 @@ $pagination-disabled-color: var(--#{$prefix}secondary-color); $pagination-disabled-bg: var(--#{$prefix}secondary-bg); $pagination-disabled-border-color: var(--#{$prefix}border-color); -$pagination-transition: color 0.15s ease-in-out, - background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, - box-shadow 0.15s ease-in-out; +$pagination-transition: + color 0.15s ease-in-out, + background-color 0.15s ease-in-out, + border-color 0.15s ease-in-out; $pagination-border-radius-sm: var(--#{$prefix}border-radius-sm); $pagination-border-radius-lg: var(--#{$prefix}border-radius-lg); diff --git a/src/assets/scss/forms/_floating-label.scss b/src/assets/scss/forms/_floating-label.scss index 56198eaf48..8ab47c4a25 100644 --- a/src/assets/scss/forms/_floating-label.scss +++ b/src/assets/scss/forms/_floating-label.scss @@ -9,4 +9,6 @@ $form-floating-label-opacity: 0.65; $form-floating-label-transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem); $form-floating-label-disabled-color: $gray-600; -$form-floating-transition: opacity 0.1s ease-in-out, transform 0.1s ease-in-out; +$form-floating-transition: + opacity 0.1s ease-in-out, + transform 0.1s ease-in-out; diff --git a/src/assets/scss/forms/_form-control.scss b/src/assets/scss/forms/_form-control.scss index f4d570d278..230b3ec76b 100644 --- a/src/assets/scss/forms/_form-control.scss +++ b/src/assets/scss/forms/_form-control.scss @@ -82,7 +82,9 @@ $input-height-lg: add( add($input-padding-y-lg * 2, $input-height-border, false) ); -$input-transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +$input-transition: + border-color 0.15s ease-in-out, + box-shadow 0.15s ease-in-out; $form-color-width: 3rem; diff --git a/src/assets/scss/forms/_range.scss b/src/assets/scss/forms/_range.scss index 73be68f4f2..c0cdc61171 100644 --- a/src/assets/scss/forms/_range.scss +++ b/src/assets/scss/forms/_range.scss @@ -11,9 +11,13 @@ $form-range-thumb-bg: $component-active-bg; $form-range-thumb-border: 0; $form-range-thumb-border-radius: 1rem; $form-range-thumb-box-shadow: 0 0.1rem 0.25rem rgba($black, 0.1); -$form-range-thumb-focus-box-shadow: 0 0 0 1px $body-bg, $input-focus-box-shadow; +$form-range-thumb-focus-box-shadow: + 0 0 0 1px $body-bg, + $input-focus-box-shadow; $form-range-thumb-focus-box-shadow-width: $input-focus-width; // For focus box shadow issue in Edge $form-range-thumb-active-bg: tint-color($component-active-bg, 70%); $form-range-thumb-disabled-bg: var(--#{$prefix}secondary-color); -$form-range-thumb-transition: background-color 0.15s ease-in-out, - border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +$form-range-thumb-transition: + background-color 0.15s ease-in-out, + border-color 0.15s ease-in-out, + box-shadow 0.15s ease-in-out; diff --git a/src/assets/svgs/actionItem.svg b/src/assets/svgs/actionItem.svg new file mode 100644 index 0000000000..d660b378cd --- /dev/null +++ b/src/assets/svgs/actionItem.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/assets/svgs/addEventProject.svg b/src/assets/svgs/addEventProject.svg deleted file mode 100644 index 3c561d5ee8..0000000000 --- a/src/assets/svgs/addEventProject.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/svgs/angleLeft.svg b/src/assets/svgs/angleLeft.svg new file mode 100644 index 0000000000..a0362e5e38 --- /dev/null +++ b/src/assets/svgs/angleLeft.svg @@ -0,0 +1,5 @@ + + +angle-left + + \ No newline at end of file diff --git a/src/assets/svgs/article.svg b/src/assets/svgs/article.svg new file mode 100644 index 0000000000..e828aa40fc --- /dev/null +++ b/src/assets/svgs/article.svg @@ -0,0 +1,14 @@ + + + \ No newline at end of file diff --git a/src/assets/svgs/cardItemDate.svg b/src/assets/svgs/cardItemDate.svg new file mode 100644 index 0000000000..e3e738a3dc --- /dev/null +++ b/src/assets/svgs/cardItemDate.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/svgs/cardItemEvent.svg b/src/assets/svgs/cardItemEvent.svg new file mode 100644 index 0000000000..e37a084018 --- /dev/null +++ b/src/assets/svgs/cardItemEvent.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/svgs/cardItemLocation.svg b/src/assets/svgs/cardItemLocation.svg new file mode 100644 index 0000000000..1518f97a75 --- /dev/null +++ b/src/assets/svgs/cardItemLocation.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/svgs/eventDashboard.svg b/src/assets/svgs/eventDashboard.svg new file mode 100644 index 0000000000..769c57d315 --- /dev/null +++ b/src/assets/svgs/eventDashboard.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/assets/svgs/eventStats.svg b/src/assets/svgs/eventStats.svg index 9503758f39..ffa43fdc4a 100644 --- a/src/assets/svgs/eventStats.svg +++ b/src/assets/svgs/eventStats.svg @@ -1 +1,12 @@ - \ No newline at end of file + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgs/funds.svg b/src/assets/svgs/funds.svg new file mode 100644 index 0000000000..372a258577 --- /dev/null +++ b/src/assets/svgs/funds.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/media.svg b/src/assets/svgs/media.svg new file mode 100644 index 0000000000..956c1e9a19 --- /dev/null +++ b/src/assets/svgs/media.svg @@ -0,0 +1,14 @@ + + + \ No newline at end of file diff --git a/src/assets/svgs/people.svg b/src/assets/svgs/people.svg index 17c62eb14e..cd8134aa67 100644 --- a/src/assets/svgs/people.svg +++ b/src/assets/svgs/people.svg @@ -1,4 +1,4 @@ - - + + diff --git a/src/assets/svgs/requests.svg b/src/assets/svgs/requests.svg index 8873bce1d7..ccf700e5fe 100644 --- a/src/assets/svgs/requests.svg +++ b/src/assets/svgs/requests.svg @@ -1,10 +1,3 @@ - - - - - - - - - - + + + \ No newline at end of file diff --git a/src/assets/svgs/settings.svg b/src/assets/svgs/settings.svg index 064f6c9001..fc111cfc08 100644 --- a/src/assets/svgs/settings.svg +++ b/src/assets/svgs/settings.svg @@ -1,4 +1,4 @@ - - + + diff --git a/src/assets/svgs/social-icons/Facebook-Logo.svg b/src/assets/svgs/social-icons/Facebook-Logo.svg new file mode 100644 index 0000000000..a70f112dc7 --- /dev/null +++ b/src/assets/svgs/social-icons/Facebook-Logo.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/svgs/social-icons/Github-Logo.svg b/src/assets/svgs/social-icons/Github-Logo.svg new file mode 100644 index 0000000000..7679af859c --- /dev/null +++ b/src/assets/svgs/social-icons/Github-Logo.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/svgs/social-icons/Instagram-Logo.svg b/src/assets/svgs/social-icons/Instagram-Logo.svg new file mode 100644 index 0000000000..cbf278ae75 --- /dev/null +++ b/src/assets/svgs/social-icons/Instagram-Logo.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/svgs/social-icons/Linkedin-Logo.svg b/src/assets/svgs/social-icons/Linkedin-Logo.svg new file mode 100644 index 0000000000..998dd1b826 --- /dev/null +++ b/src/assets/svgs/social-icons/Linkedin-Logo.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/svgs/social-icons/Reddit-Logo.svg b/src/assets/svgs/social-icons/Reddit-Logo.svg new file mode 100644 index 0000000000..8111415030 --- /dev/null +++ b/src/assets/svgs/social-icons/Reddit-Logo.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/assets/svgs/social-icons/Slack-Logo.svg b/src/assets/svgs/social-icons/Slack-Logo.svg new file mode 100644 index 0000000000..29a9087d21 --- /dev/null +++ b/src/assets/svgs/social-icons/Slack-Logo.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/assets/svgs/social-icons/Twitter-Logo.svg b/src/assets/svgs/social-icons/Twitter-Logo.svg new file mode 100644 index 0000000000..efa659339d --- /dev/null +++ b/src/assets/svgs/social-icons/Twitter-Logo.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/svgs/social-icons/Youtube-Logo.svg b/src/assets/svgs/social-icons/Youtube-Logo.svg new file mode 100644 index 0000000000..112b9c2d3b --- /dev/null +++ b/src/assets/svgs/social-icons/Youtube-Logo.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/svgs/social-icons/index.tsx b/src/assets/svgs/social-icons/index.tsx new file mode 100644 index 0000000000..af6ef77966 --- /dev/null +++ b/src/assets/svgs/social-icons/index.tsx @@ -0,0 +1,19 @@ +import FacebookLogo from './Facebook-Logo.svg'; +import GithubLogo from './Github-Logo.svg'; +import InstagramLogo from './Instagram-Logo.svg'; +import LinkedInLogo from './Linkedin-Logo.svg'; +import SlackLogo from './Slack-Logo.svg'; +import TwitterLogo from './Twitter-Logo.svg'; +import YoutubeLogo from './Youtube-Logo.svg'; +import RedditLogo from './Reddit-Logo.svg'; + +export { + FacebookLogo, + GithubLogo, + InstagramLogo, + LinkedInLogo, + SlackLogo, + TwitterLogo, + YoutubeLogo, + RedditLogo, +}; diff --git a/src/assets/svgs/userEvent.svg b/src/assets/svgs/userEvent.svg new file mode 100644 index 0000000000..1623ca2e07 --- /dev/null +++ b/src/assets/svgs/userEvent.svg @@ -0,0 +1,14 @@ + + + \ No newline at end of file diff --git a/src/assets/svgs/venues.svg b/src/assets/svgs/venues.svg new file mode 100644 index 0000000000..c8cd52f4e7 --- /dev/null +++ b/src/assets/svgs/venues.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/ActionItems/ActionItemsContainer.module.css b/src/components/ActionItems/ActionItemsContainer.module.css new file mode 100644 index 0000000000..b55328c563 --- /dev/null +++ b/src/components/ActionItems/ActionItemsContainer.module.css @@ -0,0 +1,25 @@ +.actionItemStatusBadge { + width: 5.5rem; + margin-left: 1.1rem; +} + +.createModal { + margin-top: 20vh; + margin-left: 13vw; + max-width: 80vw; +} + +.titlemodal { + color: var(--bs-gray-600); + font-weight: 600; + font-size: 20px; + margin-bottom: 20px; + padding-bottom: 5px; + border-bottom: 3px solid var(--bs-primary); + width: 65%; +} + +.actionItemsOptionsButton { + width: 24px; + height: 24px; +} diff --git a/src/components/ActionItems/ActionItemsContainer.test.tsx b/src/components/ActionItems/ActionItemsContainer.test.tsx new file mode 100644 index 0000000000..dda9e07035 --- /dev/null +++ b/src/components/ActionItems/ActionItemsContainer.test.tsx @@ -0,0 +1,670 @@ +import React from 'react'; +import { + render, + screen, + fireEvent, + waitFor, + act, + waitForElementToBeRemoved, +} from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import 'jest-localstorage-mock'; +import { MockedProvider } from '@apollo/client/testing'; +import 'jest-location-mock'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import i18nForTest from 'utils/i18nForTest'; +import { toast } from 'react-toastify'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; + +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; + +import ActionItemsContainer from './ActionItemsContainer'; +import { props, props2 } from './ActionItemsContainerProps'; +import { MOCKS, MOCKS_ERROR_MUTATIONS } from './ActionItemsContainerMocks'; + +const link = new StaticMockLink(MOCKS, true); +const link2 = new StaticMockLink(MOCKS_ERROR_MUTATIONS, true); + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +jest.mock('@mui/x-date-pickers/DateTimePicker', () => { + return { + DateTimePicker: jest.requireActual( + '@mui/x-date-pickers/DesktopDateTimePicker', + ).DesktopDateTimePicker, + }; +}); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +const translations = JSON.parse( + JSON.stringify( + i18nForTest.getDataByLanguage('en')?.translation.organizationActionItems, + ), +); + +describe('Testing Action Item Categories Component', () => { + const formData = { + assignee: 'Scott Norris', + preCompletionNotes: 'pre completion notes edited', + dueDate: '02/14/2024', + completionDate: '02/21/2024', + }; + + test('component loads correctly with action items', async () => { + render( + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.queryByText(translations.noActionItems), + ).not.toBeInTheDocument(); + }); + }); + + test('component loads correctly with no action items', async () => { + render( + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.queryByText(translations.noActionItems), + ).toBeInTheDocument(); + }); + }); + + test('opens and closes the update modal correctly', async () => { + render( + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.getAllByTestId('editActionItemModalBtn')[0], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('editActionItemModalBtn')[0]); + + await waitFor(() => { + return expect( + screen.findByTestId('updateActionItemModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('updateActionItemModalCloseBtn')); + + await waitForElementToBeRemoved(() => + screen.queryByTestId('updateActionItemModalCloseBtn'), + ); + }); + + test('opens and closes the action item status change modal correctly', async () => { + render( + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.getAllByTestId('actionItemStatusChangeCheckbox')[0], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('actionItemStatusChangeCheckbox')[0]); + + await waitFor(() => { + return expect( + screen.findByTestId('actionItemStatusChangeModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('actionItemStatusChangeModalCloseBtn')); + + await waitForElementToBeRemoved(() => + screen.queryByTestId('actionItemStatusChangeModalCloseBtn'), + ); + }); + + test('opens and closes the preview modal correctly', async () => { + render( + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.getAllByTestId('previewActionItemModalBtn')[0], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('previewActionItemModalBtn')[0]); + + await waitFor(() => { + return expect( + screen.findByTestId('previewActionItemModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('previewActionItemModalCloseBtn')); + + await waitForElementToBeRemoved(() => + screen.queryByTestId('previewActionItemModalCloseBtn'), + ); + }); + + test('opens and closes the update and delete modals through the preview modal', async () => { + render( + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.getAllByTestId('previewActionItemModalBtn')[0], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('previewActionItemModalBtn')[0]); + + await waitFor(() => { + return expect( + screen.findByTestId('previewActionItemModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + + await waitFor(() => { + expect( + screen.getByTestId('deleteActionItemPreviewModalBtn'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('deleteActionItemPreviewModalBtn')); + + await waitFor(() => { + return expect( + screen.findByTestId('actionItemDeleteModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('actionItemDeleteModalCloseBtn')); + + await waitForElementToBeRemoved(() => + screen.queryByTestId('actionItemDeleteModalCloseBtn'), + ); + + await waitFor(() => { + expect( + screen.getByTestId('editActionItemPreviewModalBtn'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('editActionItemPreviewModalBtn')); + + await waitFor(() => { + return expect( + screen.findByTestId('updateActionItemModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('updateActionItemModalCloseBtn')); + + await waitForElementToBeRemoved(() => + screen.queryByTestId('updateActionItemModalCloseBtn'), + ); + }); + + test('updates an action item and toasts success', async () => { + render( + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.getAllByTestId('editActionItemModalBtn')[0], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('editActionItemModalBtn')[0]); + + await waitFor(() => { + expect(screen.getByTestId('formUpdateAssignee')).toBeInTheDocument(); + }); + + userEvent.selectOptions( + screen.getByTestId('formUpdateAssignee'), + formData.assignee, + ); + + const preCompletionNotes = screen.getByPlaceholderText( + translations.preCompletionNotes, + ); + fireEvent.change(preCompletionNotes, { target: { value: '' } }); + userEvent.type(preCompletionNotes, formData.preCompletionNotes); + + // const postCompletionNotes = screen.getByPlaceholderText( + // translations.postCompletionNotes, + // ); + // fireEvent.change(postCompletionNotes, { target: { value: '' } }); + // userEvent.type(postCompletionNotes, formData.postCompletionNotes); + + const dueDatePicker = screen.getByLabelText(translations.dueDate); + fireEvent.change(dueDatePicker, { + target: { value: formData.dueDate }, + }); + + const completionDatePicker = screen.getByLabelText( + translations.completionDate, + ); + fireEvent.change(completionDatePicker, { + target: { value: formData.completionDate }, + }); + + // await waitFor(() => { + // expect(screen.getByTestId('alldayCheck')).toBeInTheDocument(); + // }); + // userEvent.click(screen.getByTestId('alldayCheck')); + + await waitFor(() => { + expect(screen.getByTestId('editActionItemBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('editActionItemBtn')); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.successfulUpdation); + }); + }); + + test('toasts error on unsuccessful updation', async () => { + render( + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.getAllByTestId('editActionItemModalBtn')[0], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('editActionItemModalBtn')[0]); + + await waitFor(() => { + expect(screen.getByTestId('formUpdateAssignee')).toBeInTheDocument(); + }); + + userEvent.selectOptions( + screen.getByTestId('formUpdateAssignee'), + formData.assignee, + ); + + const preCompletionNotes = screen.getByPlaceholderText( + translations.preCompletionNotes, + ); + fireEvent.change(preCompletionNotes, { target: { value: '' } }); + userEvent.type(preCompletionNotes, formData.preCompletionNotes); + + // const postCompletionNotes = screen.getByPlaceholderText( + // translations.postCompletionNotes, + // ); + // fireEvent.change(postCompletionNotes, { target: { value: '' } }); + // userEvent.type(postCompletionNotes, formData.postCompletionNotes); + + const dueDatePicker = screen.getByLabelText(translations.dueDate); + fireEvent.change(dueDatePicker, { + target: { value: formData.dueDate }, + }); + + const completionDatePicker = screen.getByLabelText( + translations.completionDate, + ); + fireEvent.change(completionDatePicker, { + target: { value: formData.completionDate }, + }); + + // await waitFor(() => { + // expect(screen.getByTestId('alldayCheck')).toBeInTheDocument(); + // }); + // userEvent.click(screen.getByTestId('alldayCheck')); + + await waitFor(() => { + expect(screen.getByTestId('editActionItemBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('editActionItemBtn')); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); + + test('updates an action item status through the action item status change modal', async () => { + render( + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.getAllByTestId('actionItemStatusChangeCheckbox')[0], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('actionItemStatusChangeCheckbox')[0]); + + await waitFor(() => { + expect( + screen.getByTestId('actionItemsStatusChangeNotes'), + ).toBeInTheDocument(); + }); + + const postCompletionNotes = screen.getByTestId( + 'actionItemsStatusChangeNotes', + ); + fireEvent.change(postCompletionNotes, { target: { value: '' } }); + userEvent.type( + postCompletionNotes, + 'this action item has been completed successfully', + ); + + await waitFor(() => { + expect( + screen.getByTestId('actionItemStatusChangeSubmitBtn'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('actionItemStatusChangeSubmitBtn')); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.successfulUpdation); + }); + + await waitFor(() => { + expect( + screen.getAllByTestId('actionItemStatusChangeCheckbox')[1], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('actionItemStatusChangeCheckbox')[1]); + + await waitFor(() => { + expect( + screen.getByTestId('actionItemsStatusChangeNotes'), + ).toBeInTheDocument(); + }); + + const preCompletionNotes = screen.getByTestId( + 'actionItemsStatusChangeNotes', + ); + fireEvent.change(preCompletionNotes, { target: { value: '' } }); + userEvent.type( + preCompletionNotes, + 'this action item has been made active again', + ); + + await waitFor(() => { + expect( + screen.getByTestId('actionItemStatusChangeSubmitBtn'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('actionItemStatusChangeSubmitBtn')); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.successfulUpdation); + }); + }); + + test('deletes the action item and toasts success', async () => { + render( + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.getAllByTestId('previewActionItemModalBtn')[0], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('previewActionItemModalBtn')[0]); + + await waitFor(() => { + return expect( + screen.findByTestId('previewActionItemModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + + await waitFor(() => { + expect( + screen.getByTestId('deleteActionItemPreviewModalBtn'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('deleteActionItemPreviewModalBtn')); + + await waitFor(() => { + return expect( + screen.findByTestId('actionItemDeleteModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('deleteActionItemBtn')); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.successfulDeletion); + }); + }); + + test('toasts error on unsuccessful deletion', async () => { + render( + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.getAllByTestId('previewActionItemModalBtn')[0], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('previewActionItemModalBtn')[0]); + + await waitFor(() => { + return expect( + screen.findByTestId('previewActionItemModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + + await waitFor(() => { + expect( + screen.getByTestId('deleteActionItemPreviewModalBtn'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('deleteActionItemPreviewModalBtn')); + + await waitFor(() => { + return expect( + screen.findByTestId('actionItemDeleteModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('deleteActionItemBtn')); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); + + test('shows the overlay text on action item notes', async () => { + const { getAllByTestId } = render( + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.getAllByTestId('actionItemPreCompletionNotesOverlay')[0], + ).toBeInTheDocument(); + }); + + await waitFor(() => { + fireEvent.mouseEnter( + getAllByTestId('actionItemPreCompletionNotesOverlay')[0], + ); + }); + + await waitFor(() => { + expect(screen.getByTestId('popover-actionItem1')).toBeInTheDocument(); + }); + + await waitFor(() => { + fireEvent.mouseLeave( + getAllByTestId('actionItemPreCompletionNotesOverlay')[0], + ); + }); + + await waitFor(() => { + fireEvent.mouseEnter( + getAllByTestId('actionItemPostCompletionNotesOverlay')[0], + ); + }); + + await waitFor(() => { + expect(screen.getByTestId('popover-actionItem2')).toBeInTheDocument(); + }); + + await waitFor(() => { + fireEvent.mouseLeave( + getAllByTestId('actionItemPostCompletionNotesOverlay')[0], + ); + }); + }); +}); diff --git a/src/components/ActionItems/ActionItemsContainer.tsx b/src/components/ActionItems/ActionItemsContainer.tsx new file mode 100644 index 0000000000..733591d9b2 --- /dev/null +++ b/src/components/ActionItems/ActionItemsContainer.tsx @@ -0,0 +1,461 @@ +import React, { useState } from 'react'; +import dayjs from 'dayjs'; +import type { ChangeEvent } from 'react'; +import { + Button, + Col, + Form, + Modal, + OverlayTrigger, + Popover, + Row, +} from 'react-bootstrap'; +import { useTranslation } from 'react-i18next'; +import { toast } from 'react-toastify'; + +import { + DELETE_ACTION_ITEM_MUTATION, + UPDATE_ACTION_ITEM_MUTATION, +} from 'GraphQl/Mutations/mutations'; +import { useMutation } from '@apollo/client'; + +import type { + InterfaceActionItemInfo, + InterfaceMemberInfo, +} from 'utils/interfaces'; +import styles from './ActionItemsContainer.module.css'; +import ActionItemUpdateModal from '../../screens/OrganizationActionItems/ActionItemUpdateModal'; +import ActionItemPreviewModal from '../../screens/OrganizationActionItems/ActionItemPreviewModal'; +import ActionItemDeleteModal from '../../screens/OrganizationActionItems/ActionItemDeleteModal'; + +function actionItemsContainer({ + actionItemsConnection, + actionItemsData, + membersData, + actionItemsRefetch, +}: { + actionItemsConnection: 'Organization' | 'Event'; + actionItemsData: InterfaceActionItemInfo[] | undefined; + membersData: InterfaceMemberInfo[] | undefined; + actionItemsRefetch: () => void; +}): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'organizationActionItems', + }); + + const [actionItemPreviewModalIsOpen, setActionItemPreviewModalIsOpen] = + useState(false); + const [actionItemUpdateModalIsOpen, setActionItemUpdateModalIsOpen] = + useState(false); + const [actionItemDeleteModalIsOpen, setActionItemDeleteModalIsOpen] = + useState(false); + const [actionItemStatusModal, setActionItemStatusModal] = useState(false); + const [isActionItemCompleted, setIsActionItemCompleted] = useState(false); + + const [assignmentDate, setAssignmentDate] = useState(new Date()); + const [dueDate, setDueDate] = useState(new Date()); + const [completionDate, setCompletionDate] = useState(new Date()); + const [actionItemId, setActionItemId] = useState(''); + const [actionItemNotes, setActionItemNotes] = useState(''); + + const [formState, setFormState] = useState({ + assignee: '', + assigner: '', + assigneeId: '', + preCompletionNotes: '', + postCompletionNotes: '', + isCompleted: false, + }); + + const showPreviewModal = (actionItem: InterfaceActionItemInfo): void => { + setActionItemState(actionItem); + setActionItemPreviewModalIsOpen(true); + }; + + const showUpdateModal = (): void => { + setActionItemUpdateModalIsOpen(!actionItemUpdateModalIsOpen); + }; + + const hidePreviewModal = (): void => { + setActionItemPreviewModalIsOpen(false); + }; + + const hideUpdateModal = (): void => { + setActionItemId(''); + setActionItemUpdateModalIsOpen(!actionItemUpdateModalIsOpen); + }; + + const toggleDeleteModal = (): void => { + setActionItemDeleteModalIsOpen(!actionItemDeleteModalIsOpen); + }; + + const [updateActionItem] = useMutation(UPDATE_ACTION_ITEM_MUTATION); + + const updateActionItemHandler = async ( + e: ChangeEvent, + ): Promise => { + e.preventDefault(); + try { + await updateActionItem({ + variables: { + actionItemId, + assigneeId: formState.assigneeId, + preCompletionNotes: formState.preCompletionNotes, + postCompletionNotes: formState.postCompletionNotes, + dueDate: dayjs(dueDate).format('YYYY-MM-DD'), + completionDate: dayjs(completionDate).format('YYYY-MM-DD'), + isCompleted: formState.isCompleted, + }, + }); + + actionItemsRefetch(); + hideUpdateModal(); + toast.success(t('successfulUpdation')); + } catch (error: unknown) { + if (error instanceof Error) { + toast.error(error.message); + console.log(error.message); + } + } + }; + + const [removeActionItem] = useMutation(DELETE_ACTION_ITEM_MUTATION); + const deleteActionItemHandler = async (): Promise => { + try { + await removeActionItem({ + variables: { + actionItemId, + }, + }); + + actionItemsRefetch(); + toggleDeleteModal(); + toast.success(t('successfulDeletion')); + } catch (error: unknown) { + if (error instanceof Error) { + toast.error(error.message); + console.log(error.message); + } + } + }; + + const handleEditClick = (actionItem: InterfaceActionItemInfo): void => { + setActionItemState(actionItem); + showUpdateModal(); + }; + + const handleActionItemStatusChange = ( + actionItem: InterfaceActionItemInfo, + ): void => { + actionItem = { ...actionItem, isCompleted: !actionItem.isCompleted }; + setIsActionItemCompleted(!actionItem.isCompleted); + setActionItemState(actionItem); + setActionItemStatusModal(true); + }; + + const hideActionItemStatusModal = (): void => { + setActionItemStatusModal(false); + }; + + const setActionItemState = (actionItem: InterfaceActionItemInfo): void => { + setFormState({ + ...formState, + assignee: `${actionItem.assignee.firstName} ${actionItem.assignee.lastName}`, + assigner: `${actionItem.assigner.firstName} ${actionItem.assigner.lastName}`, + assigneeId: actionItem.assignee._id, + preCompletionNotes: actionItem.preCompletionNotes, + postCompletionNotes: actionItem.postCompletionNotes, + isCompleted: actionItem.isCompleted, + }); + setActionItemId(actionItem._id); + setDueDate(actionItem.dueDate); + setAssignmentDate(actionItem.assignmentDate); + setCompletionDate(actionItem.completionDate); + }; + + const popover = ( + + {actionItemNotes} + + ); + + return ( + <> +
    +
    + + +
    {t('assignee')}
    + + + {t('actionItemCategory')} + + +
    {t('preCompletionNotes')}
    + + +
    {t('postCompletionNotes')}
    + + +
    {t('options')}
    + +
    +
    + +
    + {actionItemsData?.map((actionItem, index) => ( +
    + + + {`${actionItem.assignee.firstName} ${actionItem.assignee.lastName}`} + + + {actionItem.actionItemCategory.name} + + +
    + + { + setActionItemId(actionItem._id); + setActionItemNotes(actionItem.preCompletionNotes); + }} + > + {actionItem.preCompletionNotes.length > 25 + ? `${actionItem.preCompletionNotes.substring(0, 25)}...` + : actionItem.preCompletionNotes} + + +
    + + +
    + {actionItem.isCompleted ? ( + + { + setActionItemId(actionItem._id); + setActionItemNotes(actionItem.postCompletionNotes); + }} + className="ms-3 " + > + {actionItem.postCompletionNotes?.length > 25 + ? `${actionItem.postCompletionNotes.substring(0, 25)}...` + : actionItem.postCompletionNotes} + + + ) : ( + + {t('actionItemActive')} + + )} +
    + + +
    + handleActionItemStatusChange(actionItem)} + /> + + +
    + +
    + + {index !== actionItemsData.length - 1 &&
    } +
    + ))} + + {actionItemsData?.length === 0 && ( +
    + {t('noActionItems')} +
    + )} +
    +
    + + {/* action item status change modal */} + + +

    {t('actionItemStatus')}

    + +
    + +
    + + {isActionItemCompleted + ? t('preCompletionNotes') + : t('postCompletionNotes')} + + { + if (isActionItemCompleted) { + setFormState({ + ...formState, + preCompletionNotes: e.target.value, + }); + } else { + setFormState({ + ...formState, + postCompletionNotes: e.target.value, + }); + } + }} + /> + + +
    +
    + + {/* preview modal */} + + + {/* Update Modal */} + + + {/* Delete Modal */} + + + ); +} + +export default actionItemsContainer; diff --git a/src/components/ActionItems/ActionItemsContainerMocks.ts b/src/components/ActionItems/ActionItemsContainerMocks.ts new file mode 100644 index 0000000000..a2dc20c5eb --- /dev/null +++ b/src/components/ActionItems/ActionItemsContainerMocks.ts @@ -0,0 +1,112 @@ +import { + UPDATE_ACTION_ITEM_MUTATION, + DELETE_ACTION_ITEM_MUTATION, +} from 'GraphQl/Mutations/mutations'; + +export const MOCKS = [ + { + request: { + query: UPDATE_ACTION_ITEM_MUTATION, + variables: { + actionItemId: 'actionItem1', + assigneeId: 'user2', + preCompletionNotes: 'pre completion notes edited', + postCompletionNotes: 'Post Completion Notes', + dueDate: '2024-02-14', + completionDate: '2024-02-21', + isCompleted: false, + }, + }, + result: { + data: { + updateActionItem: { + _id: 'actionItem1', + }, + }, + }, + }, + { + request: { + query: UPDATE_ACTION_ITEM_MUTATION, + variables: { + actionItemId: 'actionItem1', + assigneeId: 'user1', + preCompletionNotes: 'Pre Completion Notes', + postCompletionNotes: 'this action item has been completed successfully', + dueDate: '2024-02-21', + completionDate: '2024-02-21', + isCompleted: true, + }, + }, + result: { + data: { + updateActionItem: { + _id: 'actionItem1', + }, + }, + }, + }, + { + request: { + query: UPDATE_ACTION_ITEM_MUTATION, + variables: { + actionItemId: 'actionItem2', + assigneeId: 'user1', + preCompletionNotes: 'this action item has been made active again', + postCompletionNotes: 'Post Completion Notes', + dueDate: '2024-02-21', + completionDate: '2024-02-21', + isCompleted: false, + }, + }, + result: { + data: { + updateActionItem: { + _id: 'actionItem1', + }, + }, + }, + }, + { + request: { + query: DELETE_ACTION_ITEM_MUTATION, + variables: { + actionItemId: 'actionItem1', + }, + }, + result: { + data: { + removeActionItem: { + _id: 'actionItem1', + }, + }, + }, + }, +]; + +export const MOCKS_ERROR_MUTATIONS = [ + { + request: { + query: UPDATE_ACTION_ITEM_MUTATION, + variables: { + actionItemId: 'actionItem1', + assigneeId: 'user2', + preCompletionNotes: 'pre completion notes edited', + postCompletionNotes: '', + dueDate: '2024-02-14', + completionDate: '2024-02-21', + isCompleted: false, + }, + }, + error: new Error('Mock Graphql Error'), + }, + { + request: { + query: DELETE_ACTION_ITEM_MUTATION, + variables: { + actionItemId: 'actionItem1', + }, + }, + error: new Error('Mock Graphql Error'), + }, +]; diff --git a/src/components/ActionItems/ActionItemsContainerProps.ts b/src/components/ActionItems/ActionItemsContainerProps.ts new file mode 100644 index 0000000000..19ba6f6369 --- /dev/null +++ b/src/components/ActionItems/ActionItemsContainerProps.ts @@ -0,0 +1,131 @@ +type ActionItemsConnectionType = 'Organization' | 'Event'; + +export const props = { + actionItemsConnection: 'Organization' as ActionItemsConnectionType, + actionItemsData: [ + { + _id: 'actionItem1', + assignee: { + _id: 'user1', + firstName: 'Harve', + lastName: 'Lance', + }, + actionItemCategory: { + _id: 'actionItemCategory1', + name: 'ActionItemCategory 1', + }, + preCompletionNotes: 'Pre Completion Notes', + postCompletionNotes: 'Post Completion Notes', + assignmentDate: new Date('2024-02-14'), + dueDate: new Date('2024-02-21'), + completionDate: new Date('2024-02-21'), + isCompleted: false, + assigner: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + event: { + _id: 'event1', + title: 'event 1', + }, + creator: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + { + _id: 'actionItem2', + assignee: { + _id: 'user1', + firstName: 'Harve', + lastName: 'Lance', + }, + actionItemCategory: { + _id: 'actionItemCategory1', + name: 'ActionItemCategory 1', + }, + preCompletionNotes: 'Pre Completion Notes', + postCompletionNotes: 'Post Completion Notes', + assignmentDate: new Date('2024-02-14'), + dueDate: new Date('2024-02-21'), + completionDate: new Date('2024-02-21'), + isCompleted: true, + assigner: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + event: { + _id: 'event1', + title: 'event 1', + }, + creator: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + { + _id: 'actionItem3', + assignee: { + _id: 'user1', + firstName: 'Harve', + lastName: 'Lance', + }, + actionItemCategory: { + _id: 'actionItemCategory1', + name: 'ActionItemCategory 1', + }, + preCompletionNotes: 'Pre Completion Notes more than 25 characters', + postCompletionNotes: 'Post Completion Notes more than 25 characters', + assignmentDate: new Date('2024-02-14'), + dueDate: new Date('2024-02-21'), + completionDate: new Date('2024-02-21'), + isCompleted: true, + assigner: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + event: { + _id: 'event1', + title: 'event 1', + }, + creator: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + ], + membersData: [ + { + _id: 'user1', + firstName: 'Harve', + lastName: 'Lance', + email: 'harve@example.com', + image: '', + organizationsBlockedBy: [], + createdAt: '2024-02-14', + }, + { + _id: 'user2', + firstName: 'Scott', + lastName: 'Norris', + email: 'scott@example.com', + image: '', + organizationsBlockedBy: [], + createdAt: '2024-02-14', + }, + ], + actionItemsRefetch: jest.fn(), +}; + +export const props2 = { + actionItemsConnection: 'Organization' as ActionItemsConnectionType, + actionItemsData: [], + membersData: [], + actionItemsRefetch: jest.fn(), +}; diff --git a/src/components/ActionItems/ActionItemsModal.test.tsx b/src/components/ActionItems/ActionItemsModal.test.tsx new file mode 100644 index 0000000000..01a15ee6aa --- /dev/null +++ b/src/components/ActionItems/ActionItemsModal.test.tsx @@ -0,0 +1,294 @@ +import React from 'react'; +import { + act, + fireEvent, + render, + screen, + waitFor, +} from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { MockedProvider } from '@apollo/react-testing'; +import { ActionItemsModal } from './ActionItemsModal'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { toast } from 'react-toastify'; + +import { + MOCKS_ERROR_ACTION_ITEM_CATEGORY_LIST_QUERY, + MOCKS_ERROR_ACTION_ITEM_LIST_QUERY, + MOCKS_ERROR_MEMBERS_LIST_QUERY, + MOCKS_ERROR_MUTATIONS, +} from '../../screens/OrganizationActionItems/OrganizationActionItemsErrorMocks'; +import { MOCKS } from '../../screens/OrganizationActionItems/OrganizationActionItemMocks'; +import { StaticMockLink } from 'utils/StaticMockLink'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +jest.mock('@mui/x-date-pickers/DateTimePicker', () => { + return { + DateTimePicker: jest.requireActual( + '@mui/x-date-pickers/DesktopDateTimePicker', + ).DesktopDateTimePicker, + }; +}); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +const link = new StaticMockLink(MOCKS, true); +const link2 = new StaticMockLink( + MOCKS_ERROR_ACTION_ITEM_CATEGORY_LIST_QUERY, + true, +); +const link3 = new StaticMockLink(MOCKS_ERROR_MEMBERS_LIST_QUERY, true); +const link4 = new StaticMockLink(MOCKS_ERROR_ACTION_ITEM_LIST_QUERY, true); +const link5 = new StaticMockLink(MOCKS_ERROR_MUTATIONS, true); + +const translations = JSON.parse( + JSON.stringify( + i18nForTest.getDataByLanguage('en')?.translation.organizationActionItems, + ), +); + +describe('Testing Check In Attendees Modal', () => { + const formData = { + actionItemCategory: 'ActionItemCategory 1', + assignee: 'Harve Lance', + preCompletionNotes: 'pre completion notes', + dueDate: '02/14/2024', + }; + + const props = { + show: true, + eventId: 'event1', + orgId: '123', + handleClose: jest.fn(), + }; + + test('The modal should be rendered properly', async () => { + render( + + + + + + + + + + + , + ); + + await waitFor(() => + expect(screen.queryByTestId('modal-title')).toBeInTheDocument(), + ); + + await waitFor(() => { + return expect( + screen.findByTestId('createEventActionItemBtn'), + ).resolves.toBeInTheDocument(); + }); + }); + + test('render error component on unsuccessful action item category list query', async () => { + const { queryByText } = render( + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect(queryByText('createEventActionItemBtn')).not.toBeInTheDocument(); + }); + }); + + test('render error component on unsuccessful member list query', async () => { + const { queryByText } = render( + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect(queryByText('createEventActionItemBtn')).not.toBeInTheDocument(); + }); + }); + + test('render error component on unsuccessful action items list query', async () => { + const { queryByText } = render( + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect(queryByText('createEventActionItemBtn')).not.toBeInTheDocument(); + }); + }); + + test('creates new action item associated with the event', async () => { + render( + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.getByTestId('createEventActionItemBtn'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('createEventActionItemBtn')); + + await waitFor(() => { + return expect( + screen.findByTestId('createActionItemModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + + await waitFor(() => { + expect( + screen.getByTestId('formSelectActionItemCategory'), + ).toBeInTheDocument(); + }); + + userEvent.selectOptions( + screen.getByTestId('formSelectActionItemCategory'), + formData.actionItemCategory, + ); + + userEvent.selectOptions( + screen.getByTestId('formSelectAssignee'), + formData.assignee, + ); + + userEvent.type( + screen.getByPlaceholderText(translations.preCompletionNotes), + formData.preCompletionNotes, + ); + + const dueDatePicker = screen.getByLabelText(translations.dueDate); + fireEvent.change(dueDatePicker, { + target: { value: formData.dueDate }, + }); + + userEvent.click(screen.getByTestId('createActionItemFormSubmitBtn')); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.successfulCreation); + }); + }); + + test('toasts error on unsuccessful creation', async () => { + render( + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.getByTestId('createEventActionItemBtn'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('createEventActionItemBtn')); + + await waitFor(() => { + return expect( + screen.findByTestId('createActionItemModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + + await waitFor(() => { + expect( + screen.getByTestId('formSelectActionItemCategory'), + ).toBeInTheDocument(); + }); + + userEvent.selectOptions( + screen.getByTestId('formSelectActionItemCategory'), + formData.actionItemCategory, + ); + + userEvent.selectOptions( + screen.getByTestId('formSelectAssignee'), + formData.assignee, + ); + + userEvent.type( + screen.getByPlaceholderText(translations.preCompletionNotes), + formData.preCompletionNotes, + ); + + const dueDatePicker = screen.getByLabelText(translations.dueDate); + fireEvent.change(dueDatePicker, { + target: { value: formData.dueDate }, + }); + + userEvent.click(screen.getByTestId('createActionItemFormSubmitBtn')); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/components/ActionItems/ActionItemsModal.tsx b/src/components/ActionItems/ActionItemsModal.tsx new file mode 100644 index 0000000000..8b8cafba4a --- /dev/null +++ b/src/components/ActionItems/ActionItemsModal.tsx @@ -0,0 +1,42 @@ +import React from 'react'; +import { Modal } from 'react-bootstrap'; +import styles from 'components/ActionItems/ActionItemsWrapper.module.css'; +import { ActionItemsModalBody } from './ActionItemsModalBody'; +import { useTranslation } from 'react-i18next'; + +export interface InterfaceModalProp { + show: boolean; + eventId: string; + orgId: string; + handleClose: () => void; +} + +export const ActionItemsModal = (props: InterfaceModalProp): JSX.Element => { + const { t } = useTranslation('translation', { + keyPrefix: 'organizationActionItems', + }); + + return ( + <> + + + + {t('eventActionItems')} + + + + + + + + ); +}; diff --git a/src/components/ActionItems/ActionItemsModalBody.tsx b/src/components/ActionItems/ActionItemsModalBody.tsx new file mode 100644 index 0000000000..59de3b1681 --- /dev/null +++ b/src/components/ActionItems/ActionItemsModalBody.tsx @@ -0,0 +1,217 @@ +import React, { useState } from 'react'; +import type { ChangeEvent } from 'react'; +import { Button } from 'react-bootstrap'; +import { useMutation, useQuery } from '@apollo/client'; +import { + ACTION_ITEM_CATEGORY_LIST, + ACTION_ITEM_LIST, + MEMBERS_LIST, +} from 'GraphQl/Queries/Queries'; +import styles from 'components/ActionItems/ActionItemsWrapper.module.css'; +import type { + InterfaceActionItemCategoryList, + InterfaceActionItemList, + InterfaceMembersList, +} from 'utils/interfaces'; + +import ActionItemsContainer from 'components/ActionItems/ActionItemsContainer'; +import Loader from 'components/Loader/Loader'; +import { WarningAmberRounded } from '@mui/icons-material'; +import { CREATE_ACTION_ITEM_MUTATION } from 'GraphQl/Mutations/ActionItemMutations'; +import dayjs from 'dayjs'; +import { toast } from 'react-toastify'; +import ActionItemCreateModal from 'screens/OrganizationActionItems/ActionItemCreateModal'; +import { useTranslation } from 'react-i18next'; + +export const ActionItemsModalBody = ({ + organizationId, + eventId, +}: { + organizationId: string; + eventId: string; +}): JSX.Element => { + const { t } = useTranslation('translation', { + keyPrefix: 'organizationActionItems', + }); + + const [dueDate, setDueDate] = useState(new Date()); + const [actionItemCreateModalIsOpen, setActionItemCreateModalIsOpen] = + useState(false); + + const [formState, setFormState] = useState({ + actionItemCategoryId: '', + assigneeId: '', + preCompletionNotes: '', + }); + + const { + data: actionItemCategoriesData, + loading: actionItemCategoriesLoading, + error: actionItemCategoriesError, + }: { + data: InterfaceActionItemCategoryList | undefined; + loading: boolean; + error?: Error | undefined; + } = useQuery(ACTION_ITEM_CATEGORY_LIST, { + variables: { + organizationId, + }, + notifyOnNetworkStatusChange: true, + }); + + const { + data: membersData, + loading: membersLoading, + error: membersError, + }: { + data: InterfaceMembersList | undefined; + loading: boolean; + error?: Error | undefined; + } = useQuery(MEMBERS_LIST, { + variables: { id: organizationId }, + }); + + const { + data: actionItemsData, + loading: actionItemsLoading, + error: actionItemsError, + refetch: actionItemsRefetch, + }: { + data: InterfaceActionItemList | undefined; + loading: boolean; + error?: Error | undefined; + refetch: any; + } = useQuery(ACTION_ITEM_LIST, { + variables: { + organizationId, + eventId, + orderBy: 'createdAt_DESC', + }, + notifyOnNetworkStatusChange: true, + }); + + const [createActionItem] = useMutation(CREATE_ACTION_ITEM_MUTATION); + + const createActionItemHandler = async ( + e: ChangeEvent, + ): Promise => { + e.preventDefault(); + try { + await createActionItem({ + variables: { + assigneeId: formState.assigneeId, + actionItemCategoryId: formState.actionItemCategoryId, + eventId, + preCompletionNotes: formState.preCompletionNotes, + dueDate: dayjs(dueDate).format('YYYY-MM-DD'), + }, + }); + + setFormState({ + assigneeId: '', + actionItemCategoryId: '', + preCompletionNotes: '', + }); + + setDueDate(new Date()); + + actionItemsRefetch(); + hideCreateModal(); + toast.success(t('successfulCreation')); + } catch (error: unknown) { + if (error instanceof Error) { + toast.error(error.message); + console.log(error.message); + } + } + }; + + const showCreateModal = (): void => { + setActionItemCreateModalIsOpen(!actionItemCreateModalIsOpen); + }; + + const hideCreateModal = (): void => { + setActionItemCreateModalIsOpen(!actionItemCreateModalIsOpen); + }; + + if (actionItemCategoriesLoading || membersLoading || actionItemsLoading) { + return ; + } + + if (actionItemCategoriesError || membersError || actionItemsError) { + return ( +
    + +
    + Error occured while loading{' '} + {actionItemCategoriesError + ? 'Action Item Categories' + : membersError + ? 'Members List' + : 'Action Items List'}{' '} + Data +
    + {actionItemCategoriesError + ? actionItemCategoriesError.message + : membersError + ? membersError.message + : actionItemsError?.message} +
    +
    + ); + } + + const actionItemCategories = + actionItemCategoriesData?.actionItemCategoriesByOrganization.filter( + (category) => !category.isDisabled, + ); + + const completedActionItemsCount = + actionItemsData?.actionItemsByOrganization.reduce( + (acc, item) => (item.isCompleted === true ? acc + 1 : acc), + 0, + ); + + return ( + <> +
    + + Status: + {actionItemsData?.actionItemsByOrganization.length} action items + assigned, {completedActionItemsCount} completed + + + +
    + + + + {/* Create Modal */} + + + ); +}; diff --git a/src/components/ActionItems/ActionItemsWrapper.module.css b/src/components/ActionItems/ActionItemsWrapper.module.css new file mode 100644 index 0000000000..125db8a125 --- /dev/null +++ b/src/components/ActionItems/ActionItemsWrapper.module.css @@ -0,0 +1,53 @@ +.actionItemsModal { + margin: auto; + max-width: 85%; +} + +button .iconWrapper { + width: 32px; + padding-right: 4px; + margin-right: 4px; +} + +button .iconWrapperSm { + width: 32px; + display: flex; + justify-content: center; + align-items: center; +} + +.errorIcon { + transform: scale(1.5); + color: var(--bs-danger); + margin-bottom: 1rem; +} + +.greenregbtn { + margin: 1rem 0 0; + margin-top: 0; + margin-right: 4px; + border: 1px solid var(--bs-gray-300); + box-shadow: 0 2px 2px var(--bs-gray-300); + padding: 10px 10px; + border-radius: 5px; + background-color: var(--bs-primary); + width: 100%; + font-size: 16px; + color: var(--bs-white); + outline: none; + font-weight: 600; + cursor: pointer; + transition: + transform 0.2s, + box-shadow 0.2s; + max-width: 100px; +} + +.message { + margin-top: 15%; + margin-bottom: 15%; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; +} diff --git a/src/components/ActionItems/ActionItemsWrapper.test.tsx b/src/components/ActionItems/ActionItemsWrapper.test.tsx new file mode 100644 index 0000000000..7b27e7ccd3 --- /dev/null +++ b/src/components/ActionItems/ActionItemsWrapper.test.tsx @@ -0,0 +1,73 @@ +import React from 'react'; +import { act, render, screen, waitFor } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { ActionItemsWrapper } from './ActionItemsWrapper'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; +import { ToastContainer } from 'react-toastify'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import userEvent from '@testing-library/user-event'; +import { MOCKS } from '../../screens/OrganizationActionItems/OrganizationActionItemMocks'; + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +const link = new StaticMockLink(MOCKS, true); + +describe('Testing Action Items Wrapper', () => { + const props = { + eventId: 'event1', + orgId: '123', + }; + + test('The button to open and close the modal should work properly', async () => { + render( + + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.getByLabelText('eventDashboardActionItems'), + ).toBeInTheDocument(); + }); + + userEvent.click(screen.getByLabelText('eventDashboardActionItems')); + + await waitFor(() => + expect(screen.queryByTestId('modal-title')).toBeInTheDocument(), + ); + + await waitFor(() => { + expect(screen.getByLabelText('Close')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByLabelText('Close')); + + await waitFor(() => + expect(screen.queryByTestId('modal-title')).not.toBeInTheDocument(), + ); + }); +}); diff --git a/src/components/ActionItems/ActionItemsWrapper.tsx b/src/components/ActionItems/ActionItemsWrapper.tsx new file mode 100644 index 0000000000..b44e0782b2 --- /dev/null +++ b/src/components/ActionItems/ActionItemsWrapper.tsx @@ -0,0 +1,45 @@ +import React, { useState } from 'react'; +import { ActionItemsModal } from './ActionItemsModal'; +import { Button } from 'react-bootstrap'; +import IconComponent from 'components/IconComponent/IconComponent'; +import styles from './ActionItemsWrapper.module.css'; +import { useTranslation } from 'react-i18next'; + +type PropType = { + orgId: string; + eventId: string; +}; + +export const ActionItemsWrapper = (props: PropType): JSX.Element => { + const { t } = useTranslation('translation', { + keyPrefix: 'organizationActionItems', + }); + + const [showModal, setShowModal] = useState(false); + + return ( + <> + + {showModal && ( + setShowModal(false)} + orgId={props.orgId} + eventId={props.eventId} + /> + )} + + ); +}; diff --git a/src/components/AddOn/AddOn.test.tsx b/src/components/AddOn/AddOn.test.tsx index 7ca192c63a..8313fefcb1 100644 --- a/src/components/AddOn/AddOn.test.tsx +++ b/src/components/AddOn/AddOn.test.tsx @@ -25,7 +25,7 @@ describe('Testing Addon component', () => { - + , ); expect(getByTestId('pluginContainer')).toBeInTheDocument(); diff --git a/src/components/AddOn/core/AddOnEntry/AddOnEntry.test.tsx b/src/components/AddOn/core/AddOnEntry/AddOnEntry.test.tsx index 50e56adf1e..c09840a8f0 100644 --- a/src/components/AddOn/core/AddOnEntry/AddOnEntry.test.tsx +++ b/src/components/AddOn/core/AddOnEntry/AddOnEntry.test.tsx @@ -16,11 +16,21 @@ import { store } from 'state/store'; import { BACKEND_URL } from 'Constant/constant'; import i18nForTest from 'utils/i18nForTest'; import { I18nextProvider } from 'react-i18next'; +import userEvent from '@testing-library/user-event'; +import { MockedProvider, wait } from '@apollo/react-testing'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { ADD_ON_ENTRY_MOCK } from './AddOnEntryMocks'; +import { ToastContainer } from 'react-toastify'; +import useLocalStorage from 'utils/useLocalstorage'; + +const { getItem } = useLocalStorage(); + +const link = new StaticMockLink(ADD_ON_ENTRY_MOCK, true); const httpLink = new HttpLink({ uri: BACKEND_URL, headers: { - authorization: 'Bearer ' + localStorage.getItem('token') || '', + authorization: 'Bearer ' + getItem('token') || '', }, }); console.error = jest.fn(); @@ -28,6 +38,11 @@ const client: ApolloClient = new ApolloClient({ cache: new InMemoryCache(), link: ApolloLink.from([httpLink]), }); +let mockID: string | undefined = '1'; +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: mockID }), +})); describe('Testing AddOnEntry', () => { const props = { @@ -56,7 +71,7 @@ describe('Testing AddOnEntry', () => { - + , ); expect(getByTestId('AddOnEntry')).toBeInTheDocument(); }); @@ -88,11 +103,107 @@ describe('Testing AddOnEntry', () => { - + , ); expect(getByText('Test Addon')).toBeInTheDocument(); expect(getByText('Test addon description')).toBeInTheDocument(); expect(getByText('Test User')).toBeInTheDocument(); }); + it('Uninstall Button works correctly', async () => { + const props = { + id: '1', + title: 'Test Addon', + description: 'Test addon description', + createdBy: 'Test User', + component: 'string', + installed: true, + configurable: true, + modified: true, + isInstalled: true, + uninstalledOrgs: [], + enabled: true, + getInstalledPlugins: (): { sample: string } => { + return { sample: 'sample' }; + }, + }; + mockID = 'undefined'; + const { findByText, getByTestId } = render( + + + + + + {} + + + + , + ); + await wait(100); + const btn = getByTestId('AddOnEntry_btn_install'); + await userEvent.click(btn); + await wait(100); + expect(btn.innerHTML).toMatch(/Install/i); + expect( + await findByText('This feature is now removed from your organization'), + ).toBeInTheDocument(); + await userEvent.click(btn); + await wait(100); + + expect(btn.innerHTML).toMatch(/Uninstall/i); + expect( + await findByText('This feature is now enabled in your organization'), + ).toBeInTheDocument(); + }); + + it('Check if uninstalled orgs includes current org', async () => { + const props = { + id: '1', + title: 'Test Addon', + description: 'Test addon description', + createdBy: 'Test User', + component: 'string', + installed: true, + configurable: true, + modified: true, + isInstalled: true, + uninstalledOrgs: ['undefined'], + enabled: true, + getInstalledPlugins: (): { sample: string } => { + return { sample: 'sample' }; + }, + }; + + const { getByTestId } = render( + + + + + {} + + + + , + ); + await wait(100); + const btn = getByTestId('AddOnEntry_btn_install'); + expect(btn.innerHTML).toMatch(/install/i); + }); + test('should be redirected to /orglist if orgId is undefined', async () => { + mockID = undefined; + render( + + + + + {} + + + + , + ); + await wait(100); + expect(window.location.pathname).toEqual('/orglist'); + }); }); diff --git a/src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx b/src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx index 7503d0667d..6f2cdaf1dc 100644 --- a/src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx +++ b/src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx @@ -6,6 +6,7 @@ import { UPDATE_INSTALL_STATUS_PLUGIN_MUTATION } from 'GraphQl/Mutations/mutatio import { useMutation } from '@apollo/client'; import { useTranslation } from 'react-i18next'; import { toast } from 'react-toastify'; +import { Navigate, useParams } from 'react-router-dom'; interface InterfaceAddOnEntryProps { id: string; @@ -29,14 +30,17 @@ function addOnEntry({ }: InterfaceAddOnEntryProps): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'addOnEntry' }); //getting orgId from URL - const currentOrg = window.location.href.split('/id=')[1] + ''; + const { orgId: currentOrg } = useParams(); + if (!currentOrg) { + return ; + } const [buttonLoading, setButtonLoading] = useState(false); const [isInstalledLocal, setIsInstalledLocal] = useState( - uninstalledOrgs.includes(currentOrg) + uninstalledOrgs.includes(currentOrg), ); // const [addOrgAsUninstalled] = useMutation(UPDATE_ORG_STATUS_PLUGIN_MUTATION); const [addOrgAsUninstalled] = useMutation( - UPDATE_INSTALL_STATUS_PLUGIN_MUTATION + UPDATE_INSTALL_STATUS_PLUGIN_MUTATION, ); const togglePluginInstall = async (): Promise => { @@ -65,7 +69,6 @@ function addOnEntry({ id="custom-switch" label={t('enable')} className={styles.entrytoggle} - // eslint-disable-next-line @typescript-eslint/no-empty-function onChange={(): void => {}} disabled={switchInProgress} checked={enabled} diff --git a/src/components/AddOn/core/AddOnEntry/AddOnEntryMocks.ts b/src/components/AddOn/core/AddOnEntry/AddOnEntryMocks.ts new file mode 100644 index 0000000000..3967a0963a --- /dev/null +++ b/src/components/AddOn/core/AddOnEntry/AddOnEntryMocks.ts @@ -0,0 +1,25 @@ +import { UPDATE_INSTALL_STATUS_PLUGIN_MUTATION } from 'GraphQl/Mutations/mutations'; + +// Mock data representing the response structure of the mutation +const updatePluginStatus = { + _id: '123', + pluginName: 'Sample Plugin', + pluginCreatedBy: 'John Doe', + pluginDesc: 'This is a sample plugin description.', + uninstalledOrgs: [], +}; + +// Creating the mock entry +export const ADD_ON_ENTRY_MOCK = [ + { + request: { + query: UPDATE_INSTALL_STATUS_PLUGIN_MUTATION, + variables: { id: '1', orgId: 'undefined' }, + }, + result: { + data: { + updatePluginStatus: updatePluginStatus, + }, + }, + }, +]; diff --git a/src/components/AddOn/core/AddOnRegister/AddOnRegister.test.tsx b/src/components/AddOn/core/AddOnRegister/AddOnRegister.test.tsx index 7caa1f9e3e..dcd749ba41 100644 --- a/src/components/AddOn/core/AddOnRegister/AddOnRegister.test.tsx +++ b/src/components/AddOn/core/AddOnRegister/AddOnRegister.test.tsx @@ -1,6 +1,8 @@ import React from 'react'; -import { act, render, screen } from '@testing-library/react'; +import { act, render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; +import { MockedProvider } from '@apollo/react-testing'; +import { ADD_PLUGIN_MUTATION } from 'GraphQl/Mutations/mutations'; import AddOnRegister from './AddOnRegister'; import { ApolloClient, @@ -16,15 +18,49 @@ import { BrowserRouter } from 'react-router-dom'; import { BACKEND_URL } from 'Constant/constant'; import i18nForTest from 'utils/i18nForTest'; import { I18nextProvider } from 'react-i18next'; +import { toast } from 'react-toastify'; +import useLocalStorage from 'utils/useLocalstorage'; + +const { getItem } = useLocalStorage(); const httpLink = new HttpLink({ uri: BACKEND_URL, headers: { - authorization: 'Bearer ' + localStorage.getItem('token') || '', + authorization: 'Bearer ' + getItem('token') || '', }, }); -async function wait(ms = 500): Promise { +const client: ApolloClient = new ApolloClient({ + cache: new InMemoryCache(), + link: ApolloLink.from([httpLink]), +}); + +const mocks = [ + { + request: { + query: ADD_PLUGIN_MUTATION, + variables: { + pluginName: 'Test Plugin', + pluginCreatedBy: 'Test Creator', + pluginDesc: 'Test Description', + pluginInstallStatus: false, + installedOrgs: ['id'], + }, + }, + result: { + data: { + createPlugin: { + _id: '1', + pluginName: 'Test Plugin', + pluginCreatedBy: 'Test Creator', + pluginDesc: 'Test Description', + }, + }, + }, + }, +]; + +async function wait(ms = 100): Promise { await act(() => { return new Promise((resolve) => { setTimeout(resolve, ms); @@ -32,10 +68,26 @@ async function wait(ms = 500): Promise { }); } -const client: ApolloClient = new ApolloClient({ - cache: new InMemoryCache(), - link: ApolloLink.from([httpLink]), -}); +const pluginData = { + pluginName: 'Test Plugin', + pluginCreatedBy: 'Test Creator', + pluginDesc: 'Test Description', +}; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + }, +})); + +const mockNavigate = jest.fn(); +let mockId: string | undefined = 'id'; +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: mockId }), + useNavigate: () => mockNavigate, +})); + describe('Testing AddOnRegister', () => { const props = { id: '6234d8bf6ud937ddk70ecc5c9', @@ -52,7 +104,7 @@ describe('Testing AddOnRegister', () => { - + , ); await wait(100); @@ -61,12 +113,89 @@ describe('Testing AddOnRegister', () => { userEvent.type(screen.getByPlaceholderText(/Ex: Donations/i), 'myplugin'); userEvent.type( screen.getByPlaceholderText(/This Plugin enables UI for/i), - 'test description' + 'test description', ); userEvent.type( screen.getByPlaceholderText(/Ex: john Doe/i), - 'test creator' + 'test creator', + ); + }); + }); + + test('Expect toast.success to be called on successful plugin addition', async () => { + await act(async () => { + render( + + + + + + + + + , + ); + await waitFor(() => new Promise((resolve) => setTimeout(resolve, 0))); + + userEvent.click(screen.getByRole('button', { name: /Add New/i })); + await wait(100); + expect(screen.getByTestId('addonregisterBtn')).toBeInTheDocument(); + userEvent.type(screen.getByTestId('pluginName'), pluginData.pluginName); + userEvent.type( + screen.getByTestId('pluginCreatedBy'), + pluginData.pluginCreatedBy, ); + userEvent.type(screen.getByTestId('pluginDesc'), pluginData.pluginDesc); + userEvent.click(screen.getByTestId('addonregisterBtn')); + + await wait(100); + expect(toast.success).toBeCalledWith('Plugin Added Successfully'); }); }); + + test('Expect the window to reload after successful plugin addition', async () => { + await act(async () => { + render( + + + + + + + + + , + ); + await waitFor(() => new Promise((resolve) => setTimeout(resolve, 0))); + + userEvent.click(screen.getByRole('button', { name: /Add New/i })); + await wait(100); + expect(screen.getByTestId('addonregisterBtn')).toBeInTheDocument(); + userEvent.type(screen.getByTestId('pluginName'), pluginData.pluginName); + userEvent.type( + screen.getByTestId('pluginCreatedBy'), + pluginData.pluginCreatedBy, + ); + userEvent.type(screen.getByTestId('pluginDesc'), pluginData.pluginDesc); + userEvent.click(screen.getByTestId('addonregisterBtn')); + + await wait(3000); // Waiting for 3 seconds to reload the page as timeout is set to 2 seconds in the component + expect(mockNavigate).toHaveBeenCalledWith(0); + }); + }); + test('should be redirected to /orglist if orgId is undefined', async () => { + mockId = undefined; + render( + + + + + {} + + + + , + ); + expect(window.location.pathname).toEqual('/orglist'); + }); }); diff --git a/src/components/AddOn/core/AddOnRegister/AddOnRegister.tsx b/src/components/AddOn/core/AddOnRegister/AddOnRegister.tsx index 4f720b4fad..f808d223e8 100644 --- a/src/components/AddOn/core/AddOnRegister/AddOnRegister.tsx +++ b/src/components/AddOn/core/AddOnRegister/AddOnRegister.tsx @@ -6,11 +6,8 @@ import { useMutation } from '@apollo/client'; import { ADD_PLUGIN_MUTATION } from 'GraphQl/Mutations/mutations'; import { useTranslation } from 'react-i18next'; import { toast } from 'react-toastify'; +import { Navigate, useNavigate, useParams } from 'react-router-dom'; -interface InterfaceAddOnRegisterProps { - id?: string; // OrgId - createdBy?: string; // User -} interface InterfaceFormStateTypes { pluginName: string; pluginCreatedBy: string; @@ -19,14 +16,15 @@ interface InterfaceFormStateTypes { installedOrgs: [string] | []; } -const currentUrl = window.location.href.split('=')[1]; -// eslint-disable-next-line @typescript-eslint/no-unused-vars -function addOnRegister({ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - createdBy, -}: InterfaceAddOnRegisterProps): JSX.Element { +function addOnRegister(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'addOnRegister' }); + const { orgId: currentUrl } = useParams(); + const navigate = useNavigate(); + if (!currentUrl) { + return ; + } + const [show, setShow] = useState(false); const handleClose = (): void => setShow(false); @@ -44,18 +42,18 @@ function addOnRegister({ const handleRegister = async (): Promise => { const { data } = await create({ variables: { - $pluginName: formState.pluginName, - $pluginCreatedBy: formState.pluginCreatedBy, - $pluginDesc: formState.pluginDesc, - $pluginInstallStatus: formState.pluginInstallStatus, - $installedOrgs: formState.installedOrgs, + pluginName: formState.pluginName, + pluginCreatedBy: formState.pluginCreatedBy, + pluginDesc: formState.pluginDesc, + pluginInstallStatus: formState.pluginInstallStatus, + installedOrgs: formState.installedOrgs, }, }); if (data) { toast.success('Plugin Added Successfully'); setTimeout(() => { - window.location.reload(); + navigate(0); }, 2000); } }; @@ -81,6 +79,7 @@ function addOnRegister({ { @@ -138,7 +139,7 @@ function addOnRegister({ diff --git a/src/components/AddOn/core/AddOnStore/AddOnStore.test.tsx b/src/components/AddOn/core/AddOnStore/AddOnStore.test.tsx index 2fc5e61e92..600e34dd5d 100644 --- a/src/components/AddOn/core/AddOnStore/AddOnStore.test.tsx +++ b/src/components/AddOn/core/AddOnStore/AddOnStore.test.tsx @@ -1,11 +1,6 @@ import React from 'react'; -import { render } from '@testing-library/react'; -// import * as reactRedux from 'react-redux'; -// import { BrowserRouter } from 'react-router-dom'; -// import userEvent from '@testing-library/user-event'; - -// import AddOnStore from './AddOnStore'; -// import { store } from 'state/store'; +import 'jest-location-mock'; +import { act, fireEvent, render, screen } from '@testing-library/react'; import { ApolloClient, ApolloProvider, @@ -13,7 +8,6 @@ import { ApolloLink, HttpLink, } from '@apollo/client'; - import type { NormalizedCacheObject } from '@apollo/client'; import { BrowserRouter } from 'react-router-dom'; import AddOnStore from './AddOnStore'; @@ -22,39 +16,379 @@ import { store } from 'state/store'; import { BACKEND_URL } from 'Constant/constant'; import i18nForTest from 'utils/i18nForTest'; import { I18nextProvider } from 'react-i18next'; +import { ORGANIZATIONS_LIST, PLUGIN_GET } from 'GraphQl/Queries/Queries'; +import userEvent from '@testing-library/user-event'; +import useLocalStorage from 'utils/useLocalstorage'; +import { MockedProvider } from '@apollo/react-testing'; + +const { getItem } = useLocalStorage(); + +jest.mock('components/AddOn/support/services/Plugin.helper', () => ({ + __esModule: true, + default: jest.fn().mockImplementation(() => ({ + fetchStore: jest.fn().mockResolvedValue([ + { + _id: '1', + pluginName: 'Plugin 1', + pluginDesc: 'Description 1', + pluginCreatedBy: 'User 1', + pluginInstallStatus: true, + }, + { + _id: '2', + pluginName: 'Plugin 2', + pluginDesc: 'Description 2', + pluginCreatedBy: 'User 2', + pluginInstallStatus: false, + }, + // Add more mock data as needed + ]), + fetchInstalled: jest.fn().mockResolvedValue([ + { + _id: '1', + pluginName: 'Installed Plugin 1', + pluginDesc: 'Installed Description 1', + pluginCreatedBy: 'User 3', + pluginInstallStatus: true, + }, + { + _id: '3', + pluginName: 'Installed Plugin 3', + pluginDesc: 'Installed Description 3', + pluginCreatedBy: 'User 4', + pluginInstallStatus: true, + }, + // Add more mock data as needed + ]), + generateLinks: jest.fn().mockImplementation((plugins) => { + return plugins + .filter((plugin: { enabled: any }) => plugin.enabled) + .map((installedPlugin: { pluginName: any; component: string }) => { + return { + name: installedPlugin.pluginName, + url: `/plugin/${installedPlugin.component.toLowerCase()}`, + }; + }); + }), + })), +})); const httpLink = new HttpLink({ uri: BACKEND_URL, headers: { - authorization: 'Bearer ' + localStorage.getItem('token') || '', + authorization: 'Bearer ' + getItem('token') || '', }, }); +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + const client: ApolloClient = new ApolloClient({ cache: new InMemoryCache(), link: ApolloLink.from([httpLink]), }); + +jest.mock('components/AddOn/support/services/Plugin.helper', () => ({ + __esModule: true, + default: jest.fn().mockImplementation(() => ({ + fetchInstalled: jest.fn().mockResolvedValue([]), + fetchStore: jest.fn().mockResolvedValue([]), + })), +})); + +const today = new Date(); +const tomorrow = today; +tomorrow.setDate(today.getDate() + 1); + +const PLUGIN_GET_MOCK = { + request: { + query: PLUGIN_GET, + }, + result: { + data: { + getPlugins: [ + { + _id: '6581be50e88e74003aab436c', + pluginName: 'Plugin 1', + pluginCreatedBy: 'Talawa Team', + pluginDesc: + 'User can share messages with other users in a chat user interface.', + uninstalledOrgs: [ + '62ccfccd3eb7fd2a30f41601', + '62ccfccd3eb7fd2a30f41601', + ], + __typename: 'Plugin', + }, + { + _id: '6581be50e88e74003aab436d', + pluginName: 'Plugin 2', + pluginCreatedBy: 'Talawa Team', + pluginDesc: + 'User can share messages with other users in a chat user interface.', + uninstalledOrgs: ['6537904485008f171cf29924'], + __typename: 'Plugin', + }, + { + _id: '6581be50e88e74003aab436e', + pluginName: 'Plugin 3', + pluginCreatedBy: 'Talawa Team', + pluginDesc: + 'User can share messages with other users in a chat user interface.', + uninstalledOrgs: [ + '62ccfccd3eb7fd2a30f41601', + '62ccfccd3eb7fd2a30f41601', + ], + __typename: 'Plugin', + }, + ], + }, + loading: false, + }, +}; + +const PLUGIN_LOADING_MOCK = { + request: { + query: PLUGIN_GET, + }, + result: { + data: { + getPlugins: [], + }, + loading: true, + }, +}; +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'undefined' }), +})); +const ORGANIZATIONS_LIST_MOCK = { + request: { + query: ORGANIZATIONS_LIST, + variables: { + id: 'undefined', + }, + }, + result: { + data: { + organizations: [ + { + _id: 'undefined', + image: '', + creator: { + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + name: 'name', + description: 'description', + userRegistrationRequired: true, + + visibleInSearch: true, + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + members: { + _id: 'id', + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + admins: { + _id: 'id', + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + membershipRequests: { + _id: 'id', + user: { + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + }, + blockedUsers: { + _id: 'id', + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + }, + ], + }, + }, +}; + describe('Testing AddOnStore Component', () => { - test('Temporary test for AddOnStore', () => { - expect(true).toBe(true); - const { getByTestId } = render( + test('for the working of the tabs', async () => { + const mocks = [ORGANIZATIONS_LIST_MOCK, PLUGIN_GET_MOCK]; + + render( + + + + + + + + + + + , + ); + + await wait(); + userEvent.click(screen.getByText('Installed')); + + await wait(); + userEvent.click(screen.getByText('Available')); + }); + + test('check the working search bar when on Available tab', async () => { + const mocks = [ORGANIZATIONS_LIST_MOCK, PLUGIN_GET_MOCK]; + + render( + + + + + + + + + + + , + ); + + await wait(); + userEvent.click(screen.getByText('Available')); + + await wait(); + let searchText = ''; + fireEvent.change(screen.getByPlaceholderText('Ex: Donations'), { + target: { value: searchText }, + }); + expect(screen.getAllByText('Plugin 1').length).toBeGreaterThanOrEqual(1); + expect(screen.getAllByText('Plugin 2').length).toBeGreaterThanOrEqual(1); + expect(screen.getAllByText('Plugin 3').length).toBeGreaterThanOrEqual(1); + + searchText = 'Plugin 1'; + fireEvent.change(screen.getByPlaceholderText('Ex: Donations'), { + target: { value: searchText }, + }); + const plugin1Elements = screen.queryAllByText('Plugin 1'); + expect(plugin1Elements.length).toBeGreaterThan(1); + + searchText = 'Test Plugin'; + fireEvent.change(screen.getByPlaceholderText('Ex: Donations'), { + target: { value: searchText }, + }); + + const message = screen.getAllByText('Plugin does not exists'); + expect(message.length).toBeGreaterThanOrEqual(1); + }); + + test('check filters enabled and disabled under Installed tab', async () => { + const mocks = [ORGANIZATIONS_LIST_MOCK, PLUGIN_GET_MOCK]; + render( + + + + + + + + + + + , + ); + + await wait(); + userEvent.click(screen.getByText('Installed')); + + expect(screen.getByText('Filters')).toBeInTheDocument(); + expect(screen.getByLabelText('Enabled')).toBeInTheDocument(); + expect(screen.getByLabelText('Disabled')).toBeInTheDocument(); + + fireEvent.click(screen.getByLabelText('Enabled')); + expect(screen.getByLabelText('Enabled')).toBeChecked(); + fireEvent.click(screen.getByLabelText('Disabled')); + expect(screen.getByLabelText('Disabled')).toBeChecked(); + }); + + test('check the working search bar when on Installed tab', async () => { + const mocks = [ORGANIZATIONS_LIST_MOCK, PLUGIN_GET_MOCK]; + + const { container } = render( - {} + + + - + , ); - expect(getByTestId('AddOnEntryStore')).toBeInTheDocument(); + await wait(); + userEvent.click(screen.getByText('Installed')); + + await wait(); + let searchText = ''; + fireEvent.change(screen.getByPlaceholderText('Ex: Donations'), { + target: { value: searchText }, + }); + expect(container).toHaveTextContent('Plugin 1'); + expect(container).toHaveTextContent('Plugin 3'); + + searchText = 'Plugin 1'; + fireEvent.change(screen.getByPlaceholderText('Ex: Donations'), { + target: { value: searchText }, + }); + const plugin1Elements = screen.queryAllByText('Plugin 1'); + expect(plugin1Elements.length).toBeGreaterThan(1); + + searchText = 'Test Plugin'; + fireEvent.change(screen.getByPlaceholderText('Ex: Donations'), { + target: { value: searchText }, + }); + const message = screen.getAllByText('Plugin does not exists'); + expect(message.length).toBeGreaterThanOrEqual(1); }); - // const useSelectorMock = jest.spyOn(reactRedux, 'useSelector'); - // const useDispatchMock = jest.spyOn(reactRedux, 'useDispatch'); - // beforeEach(() => { - // useSelectorMock.mockClear(); - // useDispatchMock.mockClear(); - // }); + test('AddOnStore loading test', async () => { + expect(true).toBe(true); + const mocks = [ORGANIZATIONS_LIST_MOCK, PLUGIN_LOADING_MOCK]; + render( + + + + + + + + + + + , + ); + + expect(screen.getByTestId('AddOnEntryStore')).toBeInTheDocument(); + }); }); diff --git a/src/components/AddOn/core/AddOnStore/AddOnStore.tsx b/src/components/AddOn/core/AddOnStore/AddOnStore.tsx index d81ce6fa4c..9eb65f9241 100644 --- a/src/components/AddOn/core/AddOnStore/AddOnStore.tsx +++ b/src/components/AddOn/core/AddOnStore/AddOnStore.tsx @@ -1,27 +1,15 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ -import React, { useEffect, useState } from 'react'; -import PropTypes from 'react'; +import React, { useState } from 'react'; +// import PropTypes from 'react'; import styles from './AddOnStore.module.css'; import AddOnEntry from '../AddOnEntry/AddOnEntry'; import Action from '../../support/components/Action/Action'; -import SidePanel from 'components/AddOn/support/components/SidePanel/SidePanel'; -import MainContent from 'components/AddOn/support/components/MainContent/MainContent'; import { useQuery } from '@apollo/client'; -import { - ADMIN_LIST, - MEMBERS_LIST, - PLUGIN_GET, - USER_LIST, -} from 'GraphQl/Queries/Queries'; // PLUGIN_LIST -import { useSelector } from 'react-redux'; -import type { RootState } from '../../../../state/reducers'; +import { PLUGIN_GET } from 'GraphQl/Queries/Queries'; // PLUGIN_LIST import { Col, Form, Row, Tab, Tabs } from 'react-bootstrap'; -import AddOnRegister from '../AddOnRegister/AddOnRegister'; import PluginHelper from 'components/AddOn/support/services/Plugin.helper'; import { store } from './../../../../state/store'; import { useTranslation } from 'react-i18next'; -import Loader from 'components/Loader/Loader'; -import OrganizationScreen from 'components/OrganizationScreen/OrganizationScreen'; +import { useParams } from 'react-router-dom'; function addOnStore(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'addOnStore' }); @@ -30,22 +18,18 @@ function addOnStore(): JSX.Element { const [isStore, setIsStore] = useState(true); const [showEnabled, setShowEnabled] = useState(true); const [searchText, setSearchText] = useState(''); - const [dataList, setDataList] = useState([]); + const [, setDataList] = useState([]); - const [render, setRender] = useState(true); - const appRoutes = useSelector((state: RootState) => state.appRoutes); - const { targets, configUrl } = appRoutes; - - const plugins = useSelector((state: RootState) => state.plugins); - const { installed, addonStore } = plugins; // type plugData = { pluginName: String, plug }; - const { data, loading, error } = useQuery(PLUGIN_GET); + const { data, loading } = useQuery(PLUGIN_GET); + + const { orgId } = useParams(); + /* istanbul ignore next */ - // eslint-disable-next-line @typescript-eslint/explicit-function-return-type - const getStorePlugins = async () => { + const getStorePlugins = async (): Promise => { let plugins = await new PluginHelper().fetchStore(); const installIds = (await new PluginHelper().fetchInstalled()).map( - (plugin: any) => plugin.id + (plugin: any) => plugin.id, ); plugins = plugins.map((plugin: any) => { plugin.installed = installIds.includes(plugin.id); @@ -71,25 +55,9 @@ function addOnStore(): JSX.Element { // return plugins; }; - /* istanbul ignore next */ - const updateLinks = async (links: any[]): Promise => { - store.dispatch({ type: 'UPDATE_P_TARGETS', payload: links }); - }; - // /* istanbul ignore next */ - const pluginModified = (): void => { - return getInstalledPlugins(); - // .then((installedPlugins) => { - // getStorePlugins(); - // return installedPlugins; - // }); - }; - - // useEffect(() => { - // pluginModified(); - // }, []); - const updateSelectedTab = (tab: any): void => { setIsStore(tab === 'available'); + /* istanbul ignore next */ isStore ? getStorePlugins() : getInstalledPlugins(); }; @@ -107,69 +75,90 @@ function addOnStore(): JSX.Element { } return ( <> - - - - - setSearchText(e.target.value)} - /> + + + + setSearchText(e.target.value)} + /> + + {!isStore && ( + +
    +
    + + +
    +
    - {!isStore && ( - -
    -
    - - -
    -
    -
    - )} - - -
    -

    {t('pHeading')}

    - {searchText ? ( -

    - Search results for {searchText} -

    - ) : null} + )} + + +
    +

    {t('pHeading')}

    + {searchText ? ( +

    + Search results for {searchText} +

    + ) : null} - - - {console.log( - data.getPlugins.filter( + + + {data.getPlugins.filter( + (val: { + _id: string; + pluginName: string | undefined; + pluginDesc: string | undefined; + pluginCreatedBy: string; + pluginInstallStatus: boolean | undefined; + getInstalledPlugins: () => any; + }) => { + if (searchText == '') { + return val; + } else if ( + val.pluginName + ?.toLowerCase() + .includes(searchText.toLowerCase()) + ) { + return val; + } + }, + ).length === 0 ? ( +

    {t('pMessage')}

    + ) : ( + data.getPlugins + .filter( (val: { _id: string; pluginName: string | undefined; @@ -187,10 +176,43 @@ function addOnStore(): JSX.Element { ) { return val; } - } + }, ) - )} - {data.getPlugins.filter( + .map( + ( + plug: { + _id: string; + pluginName: string | undefined; + pluginDesc: string | undefined; + pluginCreatedBy: string; + uninstalledOrgs: string[]; + getInstalledPlugins: () => any; + }, + i: React.Key | null | undefined, + ): JSX.Element => ( + + ), + ) + )} +
    + + {data.getPlugins + .filter( + (plugin: any) => !plugin.uninstalledOrgs.includes(orgId), + ) + .filter( (val: { _id: string; pluginName: string | undefined; @@ -208,65 +230,14 @@ function addOnStore(): JSX.Element { ) { return val; } - } + }, ).length === 0 ? ( -

    {t('pMessage')}

    - ) : ( - data.getPlugins - .filter( - (val: { - _id: string; - pluginName: string | undefined; - pluginDesc: string | undefined; - pluginCreatedBy: string; - pluginInstallStatus: boolean | undefined; - getInstalledPlugins: () => any; - }) => { - if (searchText == '') { - return val; - } else if ( - val.pluginName - ?.toLowerCase() - .includes(searchText.toLowerCase()) - ) { - return val; - } - } - ) - .map( - ( - plug: { - _id: string; - pluginName: string | undefined; - pluginDesc: string | undefined; - pluginCreatedBy: string; - uninstalledOrgs: string[]; - getInstalledPlugins: () => any; - }, - i: React.Key | null | undefined - ): JSX.Element => ( - { - console.log('Plugin is modified'); - }} - getInstalledPlugins={getInstalledPlugins} - uninstalledOrgs={plug.uninstalledOrgs} - /> - ) - ) - )} -
    - - {data.getPlugins - .filter((plugin: any) => plugin.pluginInstallStatus == true) +

    {t('pMessage')}

    + ) : ( + data.getPlugins + .filter( + (plugin: any) => !plugin.uninstalledOrgs.includes(orgId), + ) .filter( (val: { _id: string; @@ -285,70 +256,42 @@ function addOnStore(): JSX.Element { ) { return val; } - } - ).length === 0 ? ( -

    {t('pMessage')}

    // eslint-disable-line - ) : ( - data.getPlugins - .filter( - (plugin: any) => plugin.pluginInstallStatus == true - ) - .filter( - (val: { + }, + ) + .map( + ( + plug: { _id: string; pluginName: string | undefined; pluginDesc: string | undefined; pluginCreatedBy: string; + uninstalledOrgs: string[]; pluginInstallStatus: boolean | undefined; getInstalledPlugins: () => any; - }) => { - if (searchText == '') { - return val; - } else if ( - val.pluginName - ?.toLowerCase() - .includes(searchText.toLowerCase()) - ) { - return val; - } - } - ) - .map( - ( - plug: { - _id: string; - pluginName: string | undefined; - pluginDesc: string | undefined; - pluginCreatedBy: string; - uninstalledOrgs: string[]; - getInstalledPlugins: () => any; - }, - i: React.Key | null | undefined - ): JSX.Element => ( - { - console.log('Plugin is modified'); - }} - getInstalledPlugins={getInstalledPlugins} - uninstalledOrgs={plug.uninstalledOrgs} - /> - ) - ) - )} -
    -
    -
    - - - + }, + i: React.Key | null | undefined, + ): JSX.Element => ( + + ), + ) + )} + + +
    + +
    ); } diff --git a/src/components/AddOn/support/components/Action/Action.test.tsx b/src/components/AddOn/support/components/Action/Action.test.tsx index 9c9d37781d..ce6cd633b9 100644 --- a/src/components/AddOn/support/components/Action/Action.test.tsx +++ b/src/components/AddOn/support/components/Action/Action.test.tsx @@ -15,7 +15,7 @@ describe('Testing Action Component', () => { const { getByText } = render( - + , ); expect(getByText(props.label)).toBeInTheDocument(); diff --git a/src/components/AddOn/support/components/MainContent/MainContent.test.tsx b/src/components/AddOn/support/components/MainContent/MainContent.test.tsx index fe2914a277..81adbc916e 100644 --- a/src/components/AddOn/support/components/MainContent/MainContent.test.tsx +++ b/src/components/AddOn/support/components/MainContent/MainContent.test.tsx @@ -17,7 +17,7 @@ describe('Testing MainContent component', () => { - + , ); expect(getByTestId('mainContentCheck')).toBeInTheDocument(); diff --git a/src/components/AddOn/support/components/SidePanel/SidePanel.test.tsx b/src/components/AddOn/support/components/SidePanel/SidePanel.test.tsx index 5590fa1786..d929278d0e 100644 --- a/src/components/AddOn/support/components/SidePanel/SidePanel.test.tsx +++ b/src/components/AddOn/support/components/SidePanel/SidePanel.test.tsx @@ -20,7 +20,7 @@ describe('Testing Contribution Stats', () => { render( - + , ); expect(screen.getByTestId('SidePanel')).toBeInTheDocument(); }); diff --git a/src/components/AddOn/support/services/Plugin.helper.ts b/src/components/AddOn/support/services/Plugin.helper.ts index 358d4b3d7f..4730f0c568 100644 --- a/src/components/AddOn/support/services/Plugin.helper.ts +++ b/src/components/AddOn/support/services/Plugin.helper.ts @@ -1,6 +1,6 @@ class PluginHelper { fetchStore = async (): Promise => { - const result = await fetch(`http://localhost:3005/store`); + const result = await fetch(`http://localhost:${process.env.PORT}/store`); return await result.json(); }; diff --git a/src/components/Advertisements/Advertisements.test.tsx b/src/components/Advertisements/Advertisements.test.tsx index bec43589b6..0eb638f6b1 100644 --- a/src/components/Advertisements/Advertisements.test.tsx +++ b/src/components/Advertisements/Advertisements.test.tsx @@ -1,5 +1,12 @@ import React from 'react'; -import { render } from '@testing-library/react'; +import 'jest-location-mock'; +import { + act, + fireEvent, + render, + screen, + waitFor, +} from '@testing-library/react'; import { MockedProvider } from '@apollo/client/testing'; import { ApolloClient, @@ -9,7 +16,7 @@ import { HttpLink, } from '@apollo/client'; -import type { NormalizedCacheObject } from '@apollo/client'; +import type { DocumentNode, NormalizedCacheObject } from '@apollo/client'; import { BrowserRouter } from 'react-router-dom'; import Advertisement from './Advertisements'; import { Provider } from 'react-redux'; @@ -17,66 +24,696 @@ import { store } from 'state/store'; import { BACKEND_URL } from 'Constant/constant'; import i18nForTest from 'utils/i18nForTest'; import { I18nextProvider } from 'react-i18next'; -import { ADVERTISEMENTS_GET } from 'GraphQl/Queries/Queries'; +import { + ORGANIZATIONS_LIST, + ORGANIZATION_ADVERTISEMENT_LIST, + PLUGIN_GET, +} from 'GraphQl/Queries/Queries'; +import userEvent from '@testing-library/user-event'; +import { ADD_ADVERTISEMENT_MUTATION } from 'GraphQl/Mutations/mutations'; +import { ToastContainer } from 'react-toastify'; +import useLocalStorage from 'utils/useLocalstorage'; + +const { getItem } = useLocalStorage(); const httpLink = new HttpLink({ uri: BACKEND_URL, headers: { - authorization: 'Bearer ' + localStorage.getItem('token') || '', + authorization: 'Bearer ' + getItem('token') || '', }, }); +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + const client: ApolloClient = new ApolloClient({ cache: new InMemoryCache(), link: ApolloLink.from([httpLink]), }); -describe('Testing Advertisement Component', () => { - test('Temporary test for Advertisement', () => { - expect(true).toBe(true); - const { getByTestId } = render( + +jest.mock('components/AddOn/support/services/Plugin.helper', () => ({ + __esModule: true, + default: jest.fn().mockImplementation(() => ({ + fetchInstalled: jest.fn().mockResolvedValue([]), + fetchStore: jest.fn().mockResolvedValue([]), + })), +})); +let mockID: string | undefined = '1'; +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: mockID }), +})); + +const today = new Date(); +const tomorrow = today; +tomorrow.setDate(today.getDate() + 1); + +const ADVERTISEMENTS_LIST_MOCK: { + request: + | { + query: DocumentNode; + variables: { id: string; first: number; after: null }; + } + | { + query: DocumentNode; + variables: { + id: string; + first: number; + after: null; + before: null; + last: null; + }; + }; + result: + | { + data: { + organizations: { + _id: string; + advertisements: { + edges: { + node: { + _id: string; + name: string; + startDate: string; + endDate: string; + mediaUrl: string; + }; + cursor: string; + }[]; + pageInfo: { + startCursor: string; + endCursor: string; + hasNextPage: boolean; + hasPreviousPage: boolean; + }; + totalCount: number; + }; + }[]; + }; + } + | { + data: { + organizations: { + _id: string; + advertisements: { + edges: { + node: { + _id: string; + name: string; + startDate: string; + endDate: string; + mediaUrl: string; + }; + cursor: string; + }[]; + pageInfo: { + startCursor: string; + endCursor: string; + hasNextPage: boolean; + hasPreviousPage: boolean; + }; + totalCount: number; + }; + }[]; + }; + }; +}[] = []; + +for (let i = 0; i < 4; i++) { + ADVERTISEMENTS_LIST_MOCK.push({ + request: { + query: ORGANIZATION_ADVERTISEMENT_LIST, + variables: { + id: '1', + first: 6, + after: null, + }, + }, + result: { + data: { + organizations: [ + { + _id: '1', + advertisements: { + edges: [ + { + node: { + _id: '1', + name: 'Advertisement1', + startDate: '2022-01-01', + endDate: '2023-01-01', + mediaUrl: 'http://example1.com', + }, + cursor: 'cursor1', + }, + { + node: { + _id: '2', + name: 'Advertisement2', + startDate: '2024-02-01', + endDate: '2025-02-01', + mediaUrl: 'http://example2.com', + }, + cursor: 'cursor2', + }, + ], + pageInfo: { + startCursor: 'cursor1', + endCursor: 'cursor2', + hasNextPage: true, + hasPreviousPage: false, + }, + totalCount: 2, + }, + }, + ], + }, + }, + }); + ADVERTISEMENTS_LIST_MOCK.push({ + request: { + query: ORGANIZATION_ADVERTISEMENT_LIST, + variables: { + id: '1', + first: 6, + after: null, + before: null, + last: null, + }, + }, + result: { + data: { + organizations: [ + { + _id: '1', + advertisements: { + edges: [ + { + node: { + _id: '1', + name: 'Advertisement1', + startDate: '2022-01-01', + endDate: '2023-01-01', + mediaUrl: 'http://example1.com', + }, + cursor: 'cursor1', + }, + { + node: { + _id: '2', + name: 'Advertisement2', + startDate: '2024-02-01', + endDate: '2025-02-01', + mediaUrl: 'http://example2.com', + }, + cursor: 'cursor2', + }, + ], + pageInfo: { + startCursor: 'cursor1', + endCursor: 'cursor2', + hasNextPage: true, + hasPreviousPage: false, + }, + totalCount: 2, + }, + }, + ], + }, + }, + }); +} + +const PLUGIN_GET_MOCK = { + request: { + query: PLUGIN_GET, + }, + result: { + data: { + getPlugins: [ + { + _id: '6581be50e88e74003aab436c', + pluginName: 'Chats', + pluginCreatedBy: 'Talawa Team', + pluginDesc: + 'User can share messages with other users in a chat user interface.', + uninstalledOrgs: [ + '62ccfccd3eb7fd2a30f41601', + '62ccfccd3eb7fd2a30f41601', + ], + pluginInstallStatus: true, + __typename: 'Plugin', + }, + ], + }, + loading: false, + }, +}; + +const ADD_ADVERTISEMENT_MUTATION_MOCK = { + request: { + query: ADD_ADVERTISEMENT_MUTATION, + variables: { + organizationId: '1', + name: 'Cookie Shop', + file: 'data:image/png;base64,bWVkaWEgY29udGVudA==', + type: 'POPUP', + startDate: '2023-01-01', + endDate: '2023-02-02', + }, + }, + result: { + data: { + createAdvertisement: { + _id: '65844efc814dd4003db811c4', + advertisement: null, + __typename: 'Advertisement', + }, + }, + }, +}; + +const ORGANIZATIONS_LIST_MOCK = { + request: { + query: ORGANIZATIONS_LIST, + variables: { + id: '1', + }, + }, + result: { + data: { + organizations: [ + { + _id: '1', + image: '', + creator: { + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + name: 'name', + description: 'description', + userRegistrationRequired: true, + + visibleInSearch: true, + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + members: { + _id: 'id', + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + admins: { + _id: 'id', + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + membershipRequests: { + _id: 'id', + user: { + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + }, + blockedUsers: { + _id: 'id', + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + }, + ], + }, + }, +}; + +describe('Testing Advertisement Component', () => { + test('for creating new Advertisements', async () => { + const mocks = [ + ORGANIZATIONS_LIST_MOCK, + PLUGIN_GET_MOCK, + ADD_ADVERTISEMENT_MUTATION_MOCK, + ...ADVERTISEMENTS_LIST_MOCK, + ]; + + render( + + + + + + + + + + , + ); + + await wait(); + + userEvent.click(screen.getByText('Create new advertisement')); + userEvent.type( + screen.getByLabelText('Enter name of Advertisement'), + 'Cookie Shop', + ); + const mediaFile = new File(['media content'], 'test.png', { + type: 'image/png', + }); + + const mediaInput = screen.getByTestId('advertisementMedia'); + fireEvent.change(mediaInput, { + target: { + files: [mediaFile], + }, + }); + const mediaPreview = await screen.findByTestId('mediaPreview'); + expect(mediaPreview).toBeInTheDocument(); + userEvent.selectOptions( + screen.getByLabelText('Select type of Advertisement'), + 'POPUP', + ); + userEvent.type(screen.getByLabelText('Select Start Date'), '2023-01-01'); + userEvent.type(screen.getByLabelText('Select End Date'), '2023-02-02'); + + userEvent.click(screen.getByTestId('addonregister')); + expect( + await screen.findByText('Advertisement created successfully'), + ).toBeInTheDocument(); + }); + + test('for the working of the tabs', async () => { + const mocks = [ + ORGANIZATIONS_LIST_MOCK, + PLUGIN_GET_MOCK, + ADD_ADVERTISEMENT_MUTATION_MOCK, + ...ADVERTISEMENTS_LIST_MOCK, + ]; + + render( + + + + + + + + + + + , + ); + + await wait(); + userEvent.click(screen.getByText('Active Campaigns')); + + await wait(); + userEvent.click(screen.getByText('Completed Campaigns')); + }); + + test('if the component renders correctly and ads are correctly categorized date wise', async () => { + mockID = '1'; + const mocks = [...ADVERTISEMENTS_LIST_MOCK]; + + render( + + + + + + + + + + + , + ); + + await wait(); + + const date = await screen.findAllByTestId('Ad_end_date'); + const dateString = date[1].innerHTML; + const dateMatch = dateString.match( + /\b(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)\s+(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s+(\d{1,2})\s+(\d{4})\b/, + ); + let dateObject = new Date(); + + if (dateMatch) { + const monthName = dateMatch[1]; + const day = parseInt(dateMatch[2], 10); + const year = parseInt(dateMatch[3], 10); + + const monthIndex = + 'JanFebMarAprMayJunJulAugSepOctNovDec'.indexOf(monthName) / 3; + + dateObject = new Date(year, monthIndex, day); + } + + expect(dateObject.getTime()).toBeLessThan(new Date().getTime()); + }); + + test('delete ad', async () => { + mockID = '1'; + const mocks = [...ADVERTISEMENTS_LIST_MOCK]; + + render( - {} + + + - + , ); - expect(getByTestId('AdEntryStore')).toBeInTheDocument(); + + await wait(); + + const moreiconbtn = await screen.findAllByTestId('moreiconbtn'); + fireEvent.click(moreiconbtn[1]); + expect(await screen.findByTestId('deletebtn')); + fireEvent.click(await screen.findByTestId('deletebtn')); }); - test('renders advertisement data', async () => { + test('infinite scroll', async () => { + mockID = '1'; const mocks = [ + ...ADVERTISEMENTS_LIST_MOCK, + { + request: { + query: ORGANIZATION_ADVERTISEMENT_LIST, + variables: { + id: '1', + first: 2, + after: null, + last: null, + before: null, + }, + }, + result: { + data: { + organizations: [ + { + _id: '1', + advertisements: { + edges: [ + { + node: { + _id: '1', + name: 'Advertisement1', + startDate: '2022-01-01', + endDate: '2023-01-01', + mediaUrl: 'http://example1.com', + }, + cursor: 'cursor1', + }, + { + node: { + _id: '2', + name: 'Advertisement2', + startDate: '2024-02-01', + endDate: '2025-02-01', + mediaUrl: 'http://example2.com', + }, + cursor: 'cursor2', + }, + { + node: { + _id: '3', + name: 'Advertisement1', + startDate: '2022-01-01', + endDate: '2023-01-01', + mediaUrl: 'http://example1.com', + }, + cursor: 'cursor3', + }, + { + node: { + _id: '4', + name: 'Advertisement2', + startDate: '2024-02-01', + endDate: '2025-02-01', + mediaUrl: 'http://example2.com', + }, + cursor: 'cursor4', + }, + { + node: { + _id: '5', + name: 'Advertisement1', + startDate: '2022-01-01', + endDate: '2023-01-01', + mediaUrl: 'http://example1.com', + }, + cursor: 'cursor5', + }, + { + node: { + _id: '6', + name: 'Advertisement2', + startDate: '2024-02-01', + endDate: '2025-02-01', + mediaUrl: 'http://example2.com', + }, + cursor: 'cursor6', + }, + ], + pageInfo: { + startCursor: 'cursor1', + endCursor: 'cursor6', + hasNextPage: true, + hasPreviousPage: false, + }, + totalCount: 8, + }, + }, + ], + }, + }, + }, + { + request: { + query: ORGANIZATION_ADVERTISEMENT_LIST, + variables: { + id: '1', + first: 6, + after: 'cursor6', + last: null, + before: null, + }, + }, + result: { + data: { + organizations: [ + { + _id: '1', + advertisements: { + edges: [ + { + node: { + _id: '7', + name: 'Advertisement7', + startDate: '2022-01-01', + endDate: '2023-01-01', + mediaUrl: 'http://example1.com', + }, + cursor: '5rdiyruyu3hkjkjiwfhwaify', + }, + { + node: { + _id: '8', + name: 'Advertisement8', + startDate: '2024-02-01', + endDate: '2025-02-01', + mediaUrl: 'http://example2.com', + }, + cursor: '5rdiyrhgkjkjjyg3iwfhwaify', + }, + ], + pageInfo: { + startCursor: '5rdiyruyu3hkjkjiwfhwaify', + endCursor: '5rdiyrhgkjkjjyg3iwfhwaify', + hasNextPage: false, + hasPreviousPage: true, + }, + totalCount: 8, + }, + }, + ], + }, + }, + }, { request: { - query: ADVERTISEMENTS_GET, + query: ORGANIZATION_ADVERTISEMENT_LIST, variables: { - name: 'Test', + id: '1', + first: 6, + after: 'cursor2', }, }, result: { data: { - getAdvertisements: [ + organizations: [ { _id: '1', - name: 'Advertisement', - type: 'POPUP', - orgId: 'org1', - link: 'http://example.com', - endDate: new Date(), - startDate: new Date(), + advertisements: { + edges: [ + { + node: { + _id: '7', + name: 'Advertisement7', + startDate: '2022-01-01', + endDate: '2023-01-01', + mediaUrl: 'http://example1.com', + }, + cursor: '5rdiyruyu3hkjkjiwfhwaify', + }, + { + node: { + _id: '8', + name: 'Advertisement8', + startDate: '2024-02-01', + endDate: '2025-02-01', + mediaUrl: 'http://example2.com', + }, + cursor: '5rdiyrhgkjkjjyg3iwfhwaify', + }, + ], + pageInfo: { + startCursor: '5rdiyruyu3hkjkjiwfhwaify', + endCursor: '5rdiyrhgkjkjjyg3iwfhwaify', + hasNextPage: false, + hasPreviousPage: true, + }, + totalCount: 8, + }, }, - // Add more mock data if needed ], }, - loading: false, }, }, ]; - const { getByTestId } = render( + render( @@ -87,9 +724,12 @@ describe('Testing Advertisement Component', () => { - + , ); - - expect(getByTestId('AdEntryStore')).toBeInTheDocument(); + let moreiconbtn = await screen.findAllByTestId('moreiconbtn'); + console.log('before scroll', moreiconbtn); + fireEvent.scroll(window, { target: { scrollY: 500 } }); + moreiconbtn = await screen.findAllByTestId('moreiconbtn'); + console.log('after scroll', moreiconbtn); }); }); diff --git a/src/components/Advertisements/Advertisements.tsx b/src/components/Advertisements/Advertisements.tsx index 7af6fd98c9..95b95fb936 100644 --- a/src/components/Advertisements/Advertisements.tsx +++ b/src/components/Advertisements/Advertisements.tsx @@ -1,193 +1,238 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ import React, { useEffect, useState } from 'react'; -import PropTypes from 'react'; import styles from './Advertisements.module.css'; import { useQuery } from '@apollo/client'; -import { ADVERTISEMENTS_GET, PLUGIN_GET } from 'GraphQl/Queries/Queries'; // PLUGIN_LIST -import { useSelector } from 'react-redux'; -import type { RootState } from '../../state/reducers'; -import { Col, Form, Row, Tab, Tabs } from 'react-bootstrap'; -import PluginHelper from 'components/AddOn/support/services/Plugin.helper'; -import { store } from 'state/store'; +import { ORGANIZATION_ADVERTISEMENT_LIST } from 'GraphQl/Queries/Queries'; +import { Col, Row, Tab, Tabs } from 'react-bootstrap'; import { useTranslation } from 'react-i18next'; -import Loader from 'components/Loader/Loader'; -import OrganizationScreen from 'components/OrganizationScreen/OrganizationScreen'; import AdvertisementEntry from './core/AdvertisementEntry/AdvertisementEntry'; import AdvertisementRegister from './core/AdvertisementRegister/AdvertisementRegister'; -import AddOnRegister from 'components/AddOn/core/AddOnRegister/AddOnRegister'; +import { useParams } from 'react-router-dom'; +import type { InterfaceQueryOrganizationAdvertisementListItem } from 'utils/interfaces'; +import InfiniteScroll from 'react-infinite-scroll-component'; + export default function advertisements(): JSX.Element { - const { - data: data2, - loading: loading2, - error: error2, - } = useQuery(ADVERTISEMENTS_GET); - const currentOrgId = window.location.href.split('/id=')[1] + ''; + const { orgId: currentOrgId } = useParams(); const { t } = useTranslation('translation', { keyPrefix: 'advertisement' }); document.title = t('title'); + const [after, setAfter] = useState(null); - const [isStore, setIsStore] = useState(true); - const [showEnabled, setShowEnabled] = useState(true); - const [searchText, setSearchText] = useState(''); - const [dataList, setDataList] = useState([]); - - const [render, setRender] = useState(true); - const appRoutes = useSelector((state: RootState) => state.appRoutes); - const { targets, configUrl } = appRoutes; - - const plugins = useSelector((state: RootState) => state.plugins); - const { installed, addonStore } = plugins; - const { data, loading, error } = useQuery(PLUGIN_GET); - /* istanbul ignore next */ - // eslint-disable-next-line @typescript-eslint/explicit-function-return-type - const getStorePlugins = async () => { - let plugins = await new PluginHelper().fetchStore(); - const installIds = (await new PluginHelper().fetchInstalled()).map( - (plugin: any) => plugin.id - ); - plugins = plugins.map((plugin: any) => { - plugin.installed = installIds.includes(plugin.id); - return plugin; - }); - store.dispatch({ type: 'UPDATE_STORE', payload: plugins }); + type Ad = { + _id: string; + name: string; + type: 'BANNER' | 'MENU' | 'POPUP'; + mediaUrl: string; + endDate: string; // Assuming it's a string in the format 'yyyy-MM-dd' + startDate: string; // Assuming it's a string in the format 'yyyy-MM-dd' }; - /* istanbul ignore next */ - const getInstalledPlugins: () => any = () => { - setDataList(data); - }; - // const getAdvertisements: () => any = ()=> { - // return - // } - - /* istanbul ignore next */ - const updateLinks = async (links: any[]): Promise => { - store.dispatch({ type: 'UPDATE_P_TARGETS', payload: links }); - }; - // /* istanbul ignore next */ - const pluginModified = (): void => { - return getInstalledPlugins(); - // .then((installedPlugins) => { - // getStorePlugins(); - // return installedPlugins; - // }); - }; + const { + data: orgAdvertisementListData, + refetch, + }: { + data?: { + organizations: InterfaceQueryOrganizationAdvertisementListItem[]; + }; + refetch: any; + } = useQuery(ORGANIZATION_ADVERTISEMENT_LIST, { + variables: { + id: currentOrgId, + after: after, + first: 6, + }, + }); + const [advertisements, setAdvertisements] = useState( + orgAdvertisementListData?.organizations[0].advertisements?.edges.map( + (edge: { node: Ad }) => edge.node, + ) || [], + ); - const updateSelectedTab = (tab: any): void => { - setIsStore(tab === 'activeAds'); - isStore ? getStorePlugins() : getInstalledPlugins(); - }; + useEffect(() => { + if (orgAdvertisementListData && orgAdvertisementListData.organizations) { + const ads: Ad[] = + orgAdvertisementListData.organizations[0].advertisements?.edges.map( + (edge) => edge.node, + ); + after + ? setAdvertisements([...advertisements, ...ads]) + : setAdvertisements(ads); + } + }, [orgAdvertisementListData, after]); - const filterChange = (ev: any): void => { - setShowEnabled(ev.target.value === 'enabled'); - }; + async function loadMoreAdvertisements(): Promise { + await refetch(); - /* istanbul ignore next */ - if (loading) { - return ( - <> -
    - - ); + if (orgAdvertisementListData && orgAdvertisementListData.organizations) { + setAfter( + orgAdvertisementListData?.organizations[0]?.advertisements.pageInfo + .endCursor, + ); + } } return ( <> - - - -
    -

    {t('pHeading')}

    - - - - - {data2?.getAdvertisements - .filter((ad: any) => ad.orgId == currentOrgId) - .filter((ad: any) => new Date(ad.endDate) > new Date()) - .length == 0 ? ( -

    {t('pMessage')}

    // eslint-disable-line + + +
    + + + + + {[...Array(6)].map((_, index) => ( +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + ))} + + } + hasMore={ + orgAdvertisementListData?.organizations[0].advertisements + .pageInfo.hasNextPage ?? false + } + className={styles.listBox} + data-testid="organizations-list" + endMessage={ + advertisements.filter( + (ad: Ad) => new Date(ad.endDate) > new Date(), + ).length !== 0 && ( +
    +
    {t('endOfResults')}
    +
    + ) + } + > + {advertisements.filter( + (ad: Ad) => new Date(ad.endDate) > new Date(), + ).length === 0 ? ( +

    {t('pMessage')}

    ) : ( - data2?.getAdvertisements - .filter((ad: any) => ad.orgId == currentOrgId) - .filter((ad: any) => new Date(ad.endDate) > new Date()) + advertisements + .filter((ad: Ad) => new Date(ad.endDate) > new Date()) .map( ( ad: { _id: string; name: string | undefined; type: string | undefined; - orgId: string; - link: string; - endDate: Date; - startDate: Date; + mediaUrl: string; + endDate: string; + startDate: string; }, - i: React.Key | null | undefined + i: React.Key | null | undefined, ): JSX.Element => ( - ) + ), ) )} - - - {data2?.getAdvertisements - .filter((ad: any) => ad.orgId == currentOrgId) - .filter((ad: any) => new Date(ad.endDate) < new Date()) - .length == 0 ? ( -

    {t('pMessage')}

    // eslint-disable-line + +
    + + + {[...Array(6)].map((_, index) => ( +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + ))} + + } + hasMore={ + orgAdvertisementListData?.organizations[0].advertisements + .pageInfo.hasNextPage ?? false + } + className={styles.listBox} + data-testid="organizations-list" + endMessage={ + advertisements.filter( + (ad: Ad) => new Date(ad.endDate) < new Date(), + ).length !== 0 && ( +
    +
    {t('endOfResults')}
    +
    + ) + } + > + {advertisements.filter( + (ad: Ad) => new Date(ad.endDate) < new Date(), + ).length === 0 ? ( +

    {t('pMessage')}

    ) : ( - data2?.getAdvertisements - .filter((ad: any) => ad.orgId == currentOrgId) - .filter((ad: any) => new Date(ad.endDate) < new Date()) + advertisements + .filter((ad: Ad) => new Date(ad.endDate) < new Date()) .map( ( ad: { _id: string; name: string | undefined; type: string | undefined; - orgId: string; - link: string; - endDate: Date; - startDate: Date; + mediaUrl: string; + endDate: string; + startDate: string; }, - i: React.Key | null | undefined + i: React.Key | null | undefined, ): JSX.Element => ( - ) + ), ) )} - - -
    - - - +
    +
    + +
    + + ); } diff --git a/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.module.css b/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.module.css index 1f1ea89996..879d96a0a0 100644 --- a/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.module.css +++ b/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.module.css @@ -4,13 +4,12 @@ } .entryaction { - margin-left: auto; display: flex !important; - align-items: center; } .entryaction i { margin-right: 8px; + margin-top: 4px; } .entryaction .spinner-grow { @@ -18,3 +17,59 @@ width: 1rem; margin-right: 8px; } + +.admedia { + object-fit: cover; + height: 20rem; +} + +.buttons { + display: flex; + justify-content: flex-end; +} + +.dropdownButton { + background-color: transparent; + color: #000; + border: none; + cursor: pointer; + display: flex; + width: 100%; + justify-content: flex-end; + padding: 8px 10px; +} + +.dropdownContainer { + position: relative; + display: inline-block; +} + +.dropdownmenu { + display: none; + position: absolute; + z-index: 1; + background-color: white; + width: 120px; + box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2); + padding: 5px 0; + margin: 0; + list-style-type: none; + right: 0; + top: 100%; +} + +.dropdownmenu li { + cursor: pointer; + padding: 8px 16px; + text-decoration: none; + display: block; + color: #333; +} + +.dropdownmenu li:hover { + background-color: #f1f1f1; +} + +.dropdownContainer:hover .dropdownmenu { + display: block; +} diff --git a/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.test.tsx b/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.test.tsx index 896c61e5e1..0850d1f89f 100644 --- a/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.test.tsx +++ b/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.test.tsx @@ -1,6 +1,5 @@ import React from 'react'; -import { render } from '@testing-library/react'; - +import { render, fireEvent, waitFor, screen } from '@testing-library/react'; import { ApolloClient, ApolloProvider, @@ -8,53 +7,574 @@ import { ApolloLink, HttpLink, } from '@apollo/client'; - import type { NormalizedCacheObject } from '@apollo/client'; import { BrowserRouter } from 'react-router-dom'; import AdvertisementEntry from './AdvertisementEntry'; +import AdvertisementRegister from '../AdvertisementRegister/AdvertisementRegister'; import { Provider } from 'react-redux'; import { store } from 'state/store'; import { BACKEND_URL } from 'Constant/constant'; import i18nForTest from 'utils/i18nForTest'; import { I18nextProvider } from 'react-i18next'; +import dayjs from 'dayjs'; +import useLocalStorage from 'utils/useLocalstorage'; +import { MockedProvider } from '@apollo/client/testing'; +import { ORGANIZATION_ADVERTISEMENT_LIST } from 'GraphQl/Queries/OrganizationQueries'; +import { DELETE_ADVERTISEMENT_BY_ID } from 'GraphQl/Mutations/mutations'; + +const { getItem } = useLocalStorage(); const httpLink = new HttpLink({ uri: BACKEND_URL, headers: { - authorization: 'Bearer ' + localStorage.getItem('token') || '', + authorization: 'Bearer ' + getItem('token') || '', }, }); +const translations = JSON.parse( + JSON.stringify( + i18nForTest.getDataByLanguage('en')?.translation?.advertisement ?? null, + ), +); + const client: ApolloClient = new ApolloClient({ cache: new InMemoryCache(), link: ApolloLink.from([httpLink]), }); + +const mockUseMutation = jest.fn(); +jest.mock('@apollo/client', () => { + const originalModule = jest.requireActual('@apollo/client'); + return { + ...originalModule, + useMutation: () => mockUseMutation(), + }; +}); +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: '1' }), +})); + describe('Testing Advertisement Entry Component', () => { - test('Temporary test for Advertisement Entry', () => { + test('Testing rendering and deleting of advertisement', async () => { + const deleteAdByIdMock = jest.fn(); + mockUseMutation.mockReturnValue([deleteAdByIdMock]); const { getByTestId, getAllByText } = render( + + + + + , + ); + + //Testing rendering + expect(getByTestId('AdEntry')).toBeInTheDocument(); + expect(getAllByText('POPUP')[0]).toBeInTheDocument(); + expect(getAllByText('Advert1')[0]).toBeInTheDocument(); + expect(screen.getByTestId('media')).toBeInTheDocument(); + + //Testing successful deletion + fireEvent.click(getByTestId('moreiconbtn')); + fireEvent.click(getByTestId('deletebtn')); + + await waitFor(() => { + expect(screen.getByTestId('delete_title')).toBeInTheDocument(); + expect(screen.getByTestId('delete_body')).toBeInTheDocument(); + }); + + fireEvent.click(getByTestId('delete_yes')); + + await waitFor(() => { + expect(deleteAdByIdMock).toHaveBeenCalledWith({ + variables: { + id: '1', + }, + }); + const deletedMessage = screen.queryByText('Advertisement Deleted'); + expect(deletedMessage).toBeNull(); + }); + + //Testing unsuccessful deletion + deleteAdByIdMock.mockRejectedValueOnce(new Error('Deletion Failed')); + + fireEvent.click(getByTestId('moreiconbtn')); + + fireEvent.click(getByTestId('delete_yes')); + + await waitFor(() => { + expect(deleteAdByIdMock).toHaveBeenCalledWith({ + variables: { + id: '1', + }, + }); + const deletionFailedText = screen.queryByText((content, element) => { + return ( + element?.textContent === 'Deletion Failed' && + element.tagName.toLowerCase() === 'div' + ); + }); + expect(deletionFailedText).toBeNull(); + }); + }); + + it('should open and close the dropdown when options button is clicked', () => { + const { getByTestId, queryByText, getAllByText } = render( + + + + + + + + + , + ); + + // Test initial rendering + expect(getByTestId('AdEntry')).toBeInTheDocument(); + expect(getAllByText('POPUP')[0]).toBeInTheDocument(); + expect(getAllByText('Advert1')[0]).toBeInTheDocument(); + + // Test dropdown functionality + const optionsButton = getByTestId('moreiconbtn'); + + // Initially, the dropdown should not be visible + expect(queryByText('Edit')).toBeNull(); + + // Click to open the dropdown + fireEvent.click(optionsButton); + + // After clicking the button, the dropdown should be visible + expect(queryByText('Edit')).toBeInTheDocument(); + + // Click again to close the dropdown + fireEvent.click(optionsButton); + + // After the second click, the dropdown should be hidden again + expect(queryByText('Edit')).toBeNull(); + }); + + test('Updates the advertisement and shows success toast on successful update', async () => { + const updateAdByIdMock = jest.fn().mockResolvedValue({ + data: { + updateAdvertisement: { + advertisement: { + _id: '1', + name: 'Updated Advertisement', + mediaUrl: '', + startDate: dayjs(new Date()).add(1, 'day').format('YYYY-MM-DD'), + endDate: dayjs(new Date()).add(2, 'days').format('YYYY-MM-DD'), + type: 'BANNER', + }, + }, + }, + }); + + mockUseMutation.mockReturnValue([updateAdByIdMock]); + + render( + + + + + + + + + , + ); + + const optionsButton = screen.getByTestId('moreiconbtn'); + fireEvent.click(optionsButton); + fireEvent.click(screen.getByTestId('editBtn')); + + fireEvent.change(screen.getByLabelText('Enter name of Advertisement'), { + target: { value: 'Updated Advertisement' }, + }); + + expect(screen.getByLabelText('Enter name of Advertisement')).toHaveValue( + 'Updated Advertisement', + ); + + fireEvent.change(screen.getByLabelText(translations.Rtype), { + target: { value: 'BANNER' }, + }); + expect(screen.getByLabelText(translations.Rtype)).toHaveValue('BANNER'); + + fireEvent.change(screen.getByLabelText(translations.RstartDate), { + target: { value: dayjs().add(1, 'day').format('YYYY-MM-DD') }, + }); + + fireEvent.change(screen.getByLabelText(translations.RendDate), { + target: { value: dayjs().add(2, 'days').format('YYYY-MM-DD') }, + }); + + fireEvent.click(screen.getByTestId('addonupdate')); + + expect(updateAdByIdMock).toHaveBeenCalledWith({ + variables: { + id: '1', + name: 'Updated Advertisement', + type: 'BANNER', + startDate: dayjs().add(1, 'day').format('YYYY-MM-DD'), + endDate: dayjs().add(2, 'days').format('YYYY-MM-DD'), + }, + }); + }); + + test('Simulating if the mutation doesnt have data variable while updating', async () => { + const updateAdByIdMock = jest.fn().mockResolvedValue({ + updateAdvertisement: { + _id: '1', + name: 'Updated Advertisement', + type: 'BANNER', + }, + }); + + mockUseMutation.mockReturnValue([updateAdByIdMock]); + + render( + + + + + + + + + , + ); + + const optionsButton = screen.getByTestId('moreiconbtn'); + fireEvent.click(optionsButton); + fireEvent.click(screen.getByTestId('editBtn')); + + fireEvent.change(screen.getByLabelText('Enter name of Advertisement'), { + target: { value: 'Updated Advertisement' }, + }); + + expect(screen.getByLabelText('Enter name of Advertisement')).toHaveValue( + 'Updated Advertisement', + ); + + fireEvent.change(screen.getByLabelText(translations.Rtype), { + target: { value: 'BANNER' }, + }); + expect(screen.getByLabelText(translations.Rtype)).toHaveValue('BANNER'); + + fireEvent.click(screen.getByTestId('addonupdate')); + + expect(updateAdByIdMock).toHaveBeenCalledWith({ + variables: { + id: '1', + name: 'Updated Advertisement', + type: 'BANNER', + }, + }); + }); + + test('Simulating if the mutation does not have data variable while registering', async () => { + Object.defineProperty(window, 'location', { + configurable: true, + value: { + reload: jest.fn(), + href: 'https://example.com/page/id=1', + }, + }); + const createAdByIdMock = jest.fn().mockResolvedValue({ + data1: { + createAdvertisement: { + _id: '1', + }, + }, + }); + + mockUseMutation.mockReturnValue([createAdByIdMock]); + + render( + + + + + { + + } + + + + , + ); + + fireEvent.click(screen.getByTestId('createAdvertisement')); + + fireEvent.change(screen.getByLabelText('Enter name of Advertisement'), { + target: { value: 'Updated Advertisement' }, + }); + + expect(screen.getByLabelText('Enter name of Advertisement')).toHaveValue( + 'Updated Advertisement', + ); + + fireEvent.change(screen.getByLabelText(translations.Rtype), { + target: { value: 'BANNER' }, + }); + expect(screen.getByLabelText(translations.Rtype)).toHaveValue('BANNER'); + + fireEvent.change(screen.getByLabelText(translations.RstartDate), { + target: { value: '2023-01-01' }, + }); + expect(screen.getByLabelText(translations.RstartDate)).toHaveValue( + '2023-01-01', + ); + + fireEvent.change(screen.getByLabelText(translations.RendDate), { + target: { value: '2023-02-01' }, + }); + expect(screen.getByLabelText(translations.RendDate)).toHaveValue( + '2023-02-01', + ); + + fireEvent.click(screen.getByTestId('addonregister')); + + expect(createAdByIdMock).toHaveBeenCalledWith({ + variables: { + organizationId: '1', + name: 'Updated Advertisement', + file: '', + type: 'BANNER', + startDate: dayjs(new Date('2023-01-01')).format('YYYY-MM-DD'), + endDate: dayjs(new Date('2023-02-01')).format('YYYY-MM-DD'), + }, + }); + }); + test('delet advertisement', async () => { + const deleteAdByIdMock = jest.fn(); + const mocks = [ + { + request: { + query: ORGANIZATION_ADVERTISEMENT_LIST, + variables: { + id: '1', + first: 2, + after: null, + last: null, + before: null, + }, + }, + result: { + data: { + organizations: [ { + _id: '1', + advertisements: { + edges: [ + { + node: { + _id: '1', + name: 'Advertisement1', + startDate: '2022-01-01', + endDate: '2023-01-01', + mediaUrl: 'http://example1.com', + }, + cursor: 'cursor1', + }, + { + node: { + _id: '2', + name: 'Advertisement2', + startDate: '2024-02-01', + endDate: '2025-02-01', + mediaUrl: 'http://example2.com', + }, + cursor: 'cursor2', + }, + { + node: { + _id: '3', + name: 'Advertisement1', + startDate: '2022-01-01', + endDate: '2023-01-01', + mediaUrl: 'http://example1.com', + }, + cursor: 'cursor3', + }, + { + node: { + _id: '4', + name: 'Advertisement2', + startDate: '2024-02-01', + endDate: '2025-02-01', + mediaUrl: 'http://example2.com', + }, + cursor: 'cursor4', + }, + { + node: { + _id: '5', + name: 'Advertisement1', + startDate: '2022-01-01', + endDate: '2023-01-01', + mediaUrl: 'http://example1.com', + }, + cursor: 'cursor5', + }, + { + node: { + _id: '6', + name: 'Advertisement2', + startDate: '2024-02-01', + endDate: '2025-02-01', + mediaUrl: 'http://example2.com', + }, + cursor: 'cursor6', + }, + ], + pageInfo: { + startCursor: 'cursor1', + endCursor: 'cursor6', + hasNextPage: true, + hasPreviousPage: false, + }, + totalCount: 8, + }, + }, + ], + }, + }, + }, + { + request: { + query: DELETE_ADVERTISEMENT_BY_ID, + variables: { + id: '1', + }, + }, + result: { + data: { + advertisements: { + _id: null, + }, + }, + }, + }, + ]; + mockUseMutation.mockReturnValue([deleteAdByIdMock]); + const { getByTestId, getAllByText } = render( + + + + + - } + - + , ); + + //Testing rendering expect(getByTestId('AdEntry')).toBeInTheDocument(); expect(getAllByText('POPUP')[0]).toBeInTheDocument(); expect(getAllByText('Advert1')[0]).toBeInTheDocument(); + expect(screen.getByTestId('media')).toBeInTheDocument(); + + //Testing successful deletion + fireEvent.click(getByTestId('moreiconbtn')); + fireEvent.click(getByTestId('deletebtn')); + + await waitFor(() => { + expect(screen.getByTestId('delete_title')).toBeInTheDocument(); + expect(screen.getByTestId('delete_body')).toBeInTheDocument(); + }); + + fireEvent.click(getByTestId('delete_yes')); + + await waitFor(() => { + expect(deleteAdByIdMock).toHaveBeenCalledWith({ + variables: { + id: '1', + }, + }); + const deletedMessage = screen.queryByText('Advertisement Deleted'); + expect(deletedMessage).toBeNull(); + }); + + //Testing unsuccessful deletion + deleteAdByIdMock.mockRejectedValueOnce(new Error('Deletion Failed')); + + fireEvent.click(getByTestId('moreiconbtn')); + + fireEvent.click(getByTestId('delete_yes')); + + await waitFor(() => { + expect(deleteAdByIdMock).toHaveBeenCalledWith({ + variables: { + id: '1', + }, + }); + const deletionFailedText = screen.queryByText((content, element) => { + return ( + element?.textContent === 'Deletion Failed' && + element.tagName.toLowerCase() === 'div' + ); + }); + expect(deletionFailedText).toBeNull(); + }); }); }); diff --git a/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.tsx b/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.tsx index a98275e646..c6faa21de8 100644 --- a/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.tsx +++ b/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.tsx @@ -1,42 +1,76 @@ import React, { useState } from 'react'; import PropTypes from 'prop-types'; import styles from './AdvertisementEntry.module.css'; -import { Button, Card, Col, Row, Spinner } from 'react-bootstrap'; +import { Button, Card, Col, Row, Spinner, Modal } from 'react-bootstrap'; import { DELETE_ADVERTISEMENT_BY_ID } from 'GraphQl/Mutations/mutations'; import { useMutation } from '@apollo/client'; import { useTranslation } from 'react-i18next'; +import { ORGANIZATION_ADVERTISEMENT_LIST } from 'GraphQl/Queries/Queries'; +import AdvertisementRegister from '../AdvertisementRegister/AdvertisementRegister'; +import MoreVertIcon from '@mui/icons-material/MoreVert'; +import { toast } from 'react-toastify'; + +type Ad = { + _id: string; + name: string; + type: 'BANNER' | 'MENU' | 'POPUP'; + mediaUrl: string; + endDate: string; // Assuming it's a string in the format 'yyyy-MM-dd' + startDate: string; // Assuming it's a string in the format 'yyyy-MM-dd' +}; interface InterfaceAddOnEntryProps { id: string; name: string; - link: string; + mediaUrl: string; type: string; - orgId: string; + organizationId: string; startDate: Date; endDate: Date; + setAfter: any; } function advertisementEntry({ id, name, type, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - orgId, - link, + mediaUrl, endDate, - // eslint-disable-next-line @typescript-eslint/no-unused-vars + organizationId, startDate, + setAfter, }: InterfaceAddOnEntryProps): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'advertisement' }); const [buttonLoading, setButtonLoading] = useState(false); - const [deleteAdById] = useMutation(DELETE_ADVERTISEMENT_BY_ID); + const [dropdown, setDropdown] = useState(false); + const [showDeleteModal, setShowDeleteModal] = useState(false); + + const [deleteAdById] = useMutation(DELETE_ADVERTISEMENT_BY_ID, { + refetchQueries: [ + { + query: ORGANIZATION_ADVERTISEMENT_LIST, + variables: { first: 6, after: null, id: organizationId }, + }, + ], + }); + const toggleShowDeleteModal = (): void => setShowDeleteModal((prev) => !prev); const onDelete = async (): Promise => { setButtonLoading(true); - await deleteAdById({ - variables: { - id: id.toString(), - }, - }); - setButtonLoading(false); + try { + await deleteAdById({ + variables: { + id: id.toString(), + }, + }); + toast.error('Advertisement Deleted'); + setButtonLoading(false); + setAfter(null); + } catch (error: any) { + toast.error(error.message); + setButtonLoading(false); + } + }; + const handleOptionsClick = (): void => { + setDropdown(!dropdown); }; return ( <> @@ -44,35 +78,106 @@ function advertisementEntry({ {Array.from({ length: 1 }).map((_, idx) => ( - +
    + + {dropdown && ( +
      +
    • + +
    • +
    • + {t('delete')} +
    • +
    + )} +
    + {mediaUrl?.includes('videos') ? ( + + ) : ( + + )} {name} - Ends on {endDate?.toDateString()} + + Ends on {endDate?.toDateString()} + {type} - {link} - +
    + +
    + + +
    + {t('deleteAdvertisement')} +
    + +
    + + {t('deleteAdvertisementMsg')} + + + + + +
    @@ -86,8 +191,8 @@ function advertisementEntry({ advertisementEntry.propTypes = { name: PropTypes.string, type: PropTypes.string, - orgId: PropTypes.string, - link: PropTypes.string, + organizationId: PropTypes.string, + mediaUrl: PropTypes.string, endDate: PropTypes.instanceOf(Date), startDate: PropTypes.instanceOf(Date), }; @@ -95,8 +200,8 @@ advertisementEntry.propTypes = { advertisementEntry.defaultProps = { name: '', type: '', - orgId: '', - link: '', + organizationId: '', + mediaUrl: '', endDate: new Date(), startDate: new Date(), }; diff --git a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.module.css b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.module.css index c122d386fa..75b90fd1d7 100644 --- a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.module.css +++ b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.module.css @@ -4,6 +4,52 @@ align-items: center; } -.modalbtn i { +.modalbtn i, +.button i { margin-right: 8px; } + +.preview { + display: flex; + position: relative; + width: 100%; + margin-top: 10px; + justify-content: center; +} +.preview img { + width: 400px; + height: auto; +} +.preview video { + width: 400px; + height: auto; +} + +.closeButton { + position: absolute; + top: 0px; + right: 0px; + background: transparent; + transform: scale(1.2); + cursor: pointer; + border: none; + color: #707070; + font-weight: 600; + font-size: 16px; + cursor: pointer; +} + +.button { + min-width: 102px; +} + +.editHeader { + background-color: #31bb6b; + color: white; +} + +.link_check { + display: flex; + justify-content: center; + align-items: flex-start; +} diff --git a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.test.tsx b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.test.tsx index 3bf5cb9792..00a8f94ac8 100644 --- a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.test.tsx +++ b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.test.tsx @@ -1,5 +1,11 @@ import React from 'react'; -import { render, fireEvent, waitFor } from '@testing-library/react'; +import { + render, + fireEvent, + waitFor, + screen, + act, +} from '@testing-library/react'; import { ApolloClient, @@ -15,14 +21,108 @@ import AdvertisementRegister from './AdvertisementRegister'; import { Provider } from 'react-redux'; import { store } from 'state/store'; import { BACKEND_URL } from 'Constant/constant'; -import i18nForTest from 'utils/i18nForTest'; +// import i18nForTest from 'utils/i18nForTest'; import { I18nextProvider } from 'react-i18next'; +import { MockedProvider } from '@apollo/client/testing'; import i18n from 'utils/i18nForTest'; +import { toast } from 'react-toastify'; +import { ADD_ADVERTISEMENT_MUTATION } from 'GraphQl/Mutations/mutations'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import userEvent from '@testing-library/user-event'; +import useLocalStorage from 'utils/useLocalstorage'; +import { ORGANIZATION_ADVERTISEMENT_LIST } from 'GraphQl/Queries/Queries'; + +const { getItem } = useLocalStorage(); + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }, +})); + +const MOCKS = [ + { + request: { + query: ADD_ADVERTISEMENT_MUTATION, + variables: { + organizationId: '1', + name: 'Ad1', + type: 'BANNER', + startDate: '2023-01-01', + endDate: '2023-02-01', + file: 'data:image/png;base64,bWVkaWEgY29udGVudA==', + }, + }, + result: { + data: { + createAdvertisement: { + _id: '1', + advertisement: null, + __typename: 'Advertisement', + }, + }, + }, + }, + { + request: { + query: ORGANIZATION_ADVERTISEMENT_LIST, + variables: { + id: '1', + first: 6, + after: null, + }, + }, + result: { + data: { + organizations: [ + { + _id: '1', + advertisements: { + edges: [ + { + node: { + _id: '1', + name: 'Advertisement1', + startDate: '2022-01-01', + endDate: '2023-01-01', + mediaUrl: 'http://example1.com', + }, + cursor: '5rdiyr3iwfhwaify', + }, + { + node: { + _id: '2', + name: 'Advertisement2', + startDate: '2024-02-01', + endDate: '2025-02-01', + mediaUrl: 'http://example2.com', + }, + cursor: '5rdiyr3iwfhwaify', + }, + ], + pageInfo: { + startCursor: 'erdftgyhujkerty', + endCursor: 'edrftgyhujikl', + hasNextPage: false, + hasPreviousPage: false, + }, + totalCount: 2, + }, + }, + ], + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); const httpLink = new HttpLink({ uri: BACKEND_URL, headers: { - authorization: 'Bearer ' + localStorage.getItem('token') || '', + authorization: 'Bearer ' + getItem('token') || '', }, }); @@ -32,56 +132,326 @@ const client: ApolloClient = new ApolloClient({ }); const translations = JSON.parse( - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-non-null-asserted-optional-chain - JSON.stringify(i18n.getDataByLanguage('en')?.translation.advertisement!) + JSON.stringify( + i18n.getDataByLanguage('en')?.translation?.advertisement ?? null, + ), ); +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: '1' }), +})); describe('Testing Advertisement Register Component', () => { - test('AdvertismentRegister component loads correctly', async () => { + test('AdvertismentRegister component loads correctly in register mode', async () => { const { getByText } = render( - - { - - } + + - + , ); await waitFor(() => { expect(getByText(translations.addNew)).toBeInTheDocument(); }); }); - test('opens and closes modals on button click', async () => { + + test('create advertisement', async () => { + const setTimeoutSpy = jest.spyOn(global, 'setTimeout'); + const { getByText, queryByText, getByLabelText } = render( + + + + + + + + + , + ); + + expect(getByText(translations.addNew)).toBeInTheDocument(); + + fireEvent.click(getByText(translations.addNew)); + expect(queryByText(translations.RClose)).toBeInTheDocument(); + + fireEvent.change(getByLabelText(translations.Rname), { + target: { value: 'Ad1' }, + }); + expect(getByLabelText(translations.Rname)).toHaveValue('Ad1'); + + const mediaFile = new File(['media content'], 'test.png', { + type: 'image/png', + }); + + const mediaInput = getByLabelText(translations.Rmedia); + fireEvent.change(mediaInput, { + target: { + files: [mediaFile], + }, + }); + + const mediaPreview = await screen.findByTestId('mediaPreview'); + expect(mediaPreview).toBeInTheDocument(); + + fireEvent.change(getByLabelText(translations.Rtype), { + target: { value: 'BANNER' }, + }); + expect(getByLabelText(translations.Rtype)).toHaveValue('BANNER'); + + fireEvent.change(getByLabelText(translations.RstartDate), { + target: { value: '2023-01-01' }, + }); + expect(getByLabelText(translations.RstartDate)).toHaveValue('2023-01-01'); + + fireEvent.change(getByLabelText(translations.RendDate), { + target: { value: '2023-02-01' }, + }); + expect(getByLabelText(translations.RendDate)).toHaveValue('2023-02-01'); + + await waitFor(() => { + fireEvent.click(getByText(translations.register)); + }); + expect(toast.success).toBeCalledWith('Advertisement created successfully'); + expect(setTimeoutSpy).toHaveBeenCalled(); + }); + + test('update advertisement', async () => { + const setTimeoutSpy = jest.spyOn(global, 'setTimeout'); + const { getByText, queryByText, getByLabelText } = render( + + + + + + + + + , + ); + + fireEvent.click(getByText(translations.edit)); + + fireEvent.change(getByLabelText(translations.Rname), { + target: { value: 'Ad1' }, + }); + expect(getByLabelText(translations.Rname)).toHaveValue('Ad1'); + + const mediaFile = new File(['media content'], 'test.png', { + type: 'image/png', + }); + + const mediaInput = getByLabelText(translations.Rmedia); + fireEvent.change(mediaInput, { + target: { + files: [mediaFile], + }, + }); + + const mediaPreview = await screen.findByTestId('mediaPreview'); + expect(mediaPreview).toBeInTheDocument(); + + fireEvent.change(getByLabelText(translations.Rtype), { + target: { value: 'BANNER' }, + }); + expect(getByLabelText(translations.Rtype)).toHaveValue('BANNER'); + + fireEvent.change(getByLabelText(translations.RstartDate), { + target: { value: '2023-01-01' }, + }); + expect(getByLabelText(translations.RstartDate)).toHaveValue('2023-01-01'); + + fireEvent.change(getByLabelText(translations.RendDate), { + target: { value: '2023-02-01' }, + }); + expect(getByLabelText(translations.RendDate)).toHaveValue('2023-02-01'); + + await waitFor(() => { + fireEvent.click(getByText(translations.saveChanges)); + }); + expect(toast.success).toBeCalledWith('Advertisement created successfully'); + expect(setTimeoutSpy).toHaveBeenCalled(); + }); + + test('Logs error to the console and shows error toast when advertisement creation fails', async () => { + const setTimeoutSpy = jest.spyOn(global, 'setTimeout'); + const { getByText, queryByText } = render( + + + + + + + + + , + ); + + expect(getByText(translations.addNew)).toBeInTheDocument(); + + fireEvent.click(getByText(translations.addNew)); + expect(queryByText(translations.RClose)).toBeInTheDocument(); + + await waitFor(() => { + fireEvent.click(getByText(translations.register)); + }); + expect(toast.error).toBeCalledWith( + 'An error occured, could not create new advertisement', + ); + expect(setTimeoutSpy).toHaveBeenCalled(); + }); + + test('Throws error when the end date is less than the start date', async () => { + const setTimeoutSpy = jest.spyOn(global, 'setTimeout'); + const { getByText, queryByText, getByLabelText } = render( + + + + + + + + + , + ); + + expect(getByText(translations.addNew)).toBeInTheDocument(); + + fireEvent.click(getByText(translations.addNew)); + expect(queryByText(translations.RClose)).toBeInTheDocument(); + + fireEvent.change(getByLabelText(translations.Rname), { + target: { value: 'Ad1' }, + }); + expect(getByLabelText(translations.Rname)).toHaveValue('Ad1'); + + const mediaFile = new File(['media content'], 'test.png', { + type: 'image/png', + }); + + const mediaInput = getByLabelText(translations.Rmedia); + fireEvent.change(mediaInput, { + target: { + files: [mediaFile], + }, + }); + + const mediaPreview = await screen.findByTestId('mediaPreview'); + expect(mediaPreview).toBeInTheDocument(); + + fireEvent.change(getByLabelText(translations.Rtype), { + target: { value: 'BANNER' }, + }); + expect(getByLabelText(translations.Rtype)).toHaveValue('BANNER'); + + fireEvent.change(getByLabelText(translations.RstartDate), { + target: { value: '2023-01-01' }, + }); + expect(getByLabelText(translations.RstartDate)).toHaveValue('2023-01-01'); + + fireEvent.change(getByLabelText(translations.RendDate), { + target: { value: '2022-02-01' }, + }); + expect(getByLabelText(translations.RendDate)).toHaveValue('2022-02-01'); + + await waitFor(() => { + fireEvent.click(getByText(translations.register)); + }); + expect(toast.error).toBeCalledWith( + 'End date must be greater than or equal to start date', + ); + expect(setTimeoutSpy).toHaveBeenCalled(); + }); + + test('AdvertismentRegister component loads correctly in edit mode', async () => { + render( + + + + + + + + + , + ); + await waitFor(() => { + expect(screen.getByTestId('editBtn')).toBeInTheDocument(); + }); + }); + + test('Opens and closes modals on button click', async () => { const { getByText, queryByText } = render( - - { - - } + + - + , ); await waitFor(() => { fireEvent.click(getByText(translations.addNew)); @@ -91,47 +461,107 @@ describe('Testing Advertisement Register Component', () => { expect(queryByText(translations.close)).not.toBeInTheDocument(); }); }); - test('submits the form and shows success toast on successful advertisement creation', async () => { - const { getByText, getByLabelText } = render( - + + test('Throws error when the end date is less than the start date while editing the advertisement', async () => { + const { getByText, getByLabelText, queryByText } = render( + - + { } - + , + ); + + fireEvent.click(getByText(translations.edit)); + expect(queryByText(translations.editAdvertisement)).toBeInTheDocument(); + fireEvent.change(getByLabelText(translations.Rname), { + target: { value: 'Test Advertisement' }, + }); + expect(getByLabelText(translations.Rname)).toHaveValue( + 'Test Advertisement', ); + + const mediaFile = new File(['video content'], 'test.mp4', { + type: 'video/mp4', + }); + const mediaInput = screen.getByTestId('advertisementMedia'); + userEvent.upload(mediaInput, mediaFile); + + const mediaPreview = await screen.findByTestId('mediaPreview'); + expect(mediaPreview).toBeInTheDocument(); + + fireEvent.change(getByLabelText(translations.Rtype), { + target: { value: 'BANNER' }, + }); + expect(getByLabelText(translations.Rtype)).toHaveValue('BANNER'); + + fireEvent.change(getByLabelText(translations.RstartDate), { + target: { value: '2023-02-02' }, + }); + expect(getByLabelText(translations.RstartDate)).toHaveValue('2023-02-02'); + + fireEvent.change(getByLabelText(translations.RendDate), { + target: { value: '2023-01-01' }, + }); + expect(getByLabelText(translations.RendDate)).toHaveValue('2023-01-01'); + + fireEvent.click(getByText(translations.saveChanges)); await waitFor(() => { - fireEvent.click(getByText(translations.addNew)); + expect(toast.error).toBeCalledWith( + 'End date must be greater than or equal to start date', + ); + }); + }); - fireEvent.change(getByLabelText(translations.Rname), { - target: { value: 'Test Advertisement' }, - }); - fireEvent.change(getByLabelText(translations.Rlink), { - target: { value: 'http://example.com' }, - }); - fireEvent.change(getByLabelText(translations.Rtype), { - target: { value: 'BANNER' }, - }); - fireEvent.change(getByLabelText(translations.RstartDate), { - target: { value: '2023-01-01' }, - }); - fireEvent.change(getByLabelText(translations.RendDate), { - target: { value: '2023-02-01' }, - }); + test('Media preview renders correctly', async () => { + render( + + + + + + + + + , + ); - fireEvent.click(getByText(translations.register)); + fireEvent.click(screen.getByText(translations.addNew)); + await screen.findByText(translations.RClose); + + const mediaFile = new File(['video content'], 'test.mp4', { + type: 'video/mp4', }); + const mediaInput = screen.getByTestId('advertisementMedia'); + userEvent.upload(mediaInput, mediaFile); + + const mediaPreview = await screen.findByTestId('mediaPreview'); + expect(mediaPreview).toBeInTheDocument(); + + const closeButton = await screen.findByTestId('closePreview'); + fireEvent.click(closeButton); + expect(mediaPreview).not.toBeInTheDocument(); }); }); diff --git a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.tsx b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.tsx index e205d50598..8261c304f2 100644 --- a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.tsx +++ b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.tsx @@ -1,86 +1,233 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import PropTypes from 'prop-types'; import styles from './AdvertisementRegister.module.css'; import { Button, Form, Modal } from 'react-bootstrap'; +import { + ADD_ADVERTISEMENT_MUTATION, + UPDATE_ADVERTISEMENT_MUTATION, +} from 'GraphQl/Mutations/mutations'; import { useMutation } from '@apollo/client'; -import { ADD_ADVERTISEMENT_MUTATION } from 'GraphQl/Mutations/mutations'; import { useTranslation } from 'react-i18next'; import { toast } from 'react-toastify'; import dayjs from 'dayjs'; - +import convertToBase64 from 'utils/convertToBase64'; +import { ORGANIZATION_ADVERTISEMENT_LIST } from 'GraphQl/Queries/Queries'; +import { useParams } from 'react-router-dom'; interface InterfaceAddOnRegisterProps { - id?: string; // OrgId + id?: string; // organizationId createdBy?: string; // User + formStatus?: string; + idEdit?: string; + nameEdit?: string; + typeEdit?: string; + orgIdEdit?: string; + advertisementMediaEdit?: string; + endDateEdit?: Date; + startDateEdit?: Date; + setAfter: any; } interface InterfaceFormStateTypes { name: string; - link: string; + advertisementMedia: string; type: string; startDate: Date; endDate: Date; - orgId: string; + organizationId: string | undefined; } -// eslint-disable-next-line @typescript-eslint/no-unused-vars + function advertisementRegister({ - /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ - createdBy, + formStatus, + idEdit, + nameEdit, + typeEdit, + advertisementMediaEdit, + endDateEdit, + startDateEdit, + setAfter, }: InterfaceAddOnRegisterProps): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'advertisement' }); - const [show, setShow] = useState(false); + const { orgId: currentOrg } = useParams(); + const [show, setShow] = useState(false); const handleClose = (): void => setShow(false); const handleShow = (): void => setShow(true); - const [create] = useMutation(ADD_ADVERTISEMENT_MUTATION); + const [create] = useMutation(ADD_ADVERTISEMENT_MUTATION, { + refetchQueries: [ + { + query: ORGANIZATION_ADVERTISEMENT_LIST, + variables: { first: 6, after: null, id: currentOrg }, + }, + ], + }); + const [updateAdvertisement] = useMutation(UPDATE_ADVERTISEMENT_MUTATION, { + refetchQueries: [ + { + query: ORGANIZATION_ADVERTISEMENT_LIST, + variables: { first: 6, after: null, id: currentOrg }, + }, + ], + }); + //getting organizationId from URL - //getting orgId from URL - const currentOrg = window.location.href.split('/id=')[1] + ''; const [formState, setFormState] = useState({ name: '', - link: '', + advertisementMedia: '', type: 'BANNER', startDate: new Date(), endDate: new Date(), - orgId: currentOrg, + organizationId: currentOrg, }); + + //if set to edit set the formState by edit variables + useEffect(() => { + if (formStatus === 'edit') { + setFormState((prevState) => ({ + ...prevState, + name: nameEdit || '', + advertisementMedia: advertisementMediaEdit || '', + type: typeEdit || 'BANNER', + startDate: startDateEdit || new Date(), + endDate: endDateEdit || new Date(), + orgId: currentOrg, + })); + } + }, [ + formStatus, + nameEdit, + advertisementMediaEdit, + typeEdit, + startDateEdit, + endDateEdit, + currentOrg, + ]); + const handleRegister = async (): Promise => { try { console.log('At handle register', formState); + if (formState.endDate < formState.startDate) { + toast.error('End date must be greater than or equal to start date'); + return; + } const { data } = await create({ variables: { - orgId: currentOrg, + organizationId: currentOrg, name: formState.name as string, - link: formState.link as string, type: formState.type as string, startDate: dayjs(formState.startDate).format('YYYY-MM-DD'), endDate: dayjs(formState.endDate).format('YYYY-MM-DD'), + file: formState.advertisementMedia as string, }, }); if (data) { toast.success('Advertisement created successfully'); - setTimeout(() => { - window.location.reload(); - }, 2000); + setFormState({ + name: '', + advertisementMedia: '', + type: 'BANNER', + startDate: new Date(), + endDate: new Date(), + organizationId: currentOrg, + }); + } + setAfter(null); + } catch (error: unknown) { + if (error instanceof Error) { + toast.error('An error occured, could not create new advertisement'); + console.log('error occured', error.message); + } + } + }; + const handleUpdate = async (): Promise => { + try { + const updatedFields: Partial = {}; + + // Only include the fields which are updated + if (formState.name !== nameEdit) { + updatedFields.name = formState.name; + } + if (formState.advertisementMedia !== advertisementMediaEdit) { + updatedFields.advertisementMedia = formState.advertisementMedia; + } + if (formState.type !== typeEdit) { + updatedFields.type = formState.type; + } + if (formState.endDate < formState.startDate) { + toast.error('End date must be greater than or equal to start date'); + return; + } + const startDateFormattedString = dayjs(formState.startDate).format( + 'YYYY-MM-DD', + ); + const endDateFormattedString = dayjs(formState.endDate).format( + 'YYYY-MM-DD', + ); + + const startDateDate = dayjs( + startDateFormattedString, + 'YYYY-MM-DD', + ).toDate(); + const endDateDate = dayjs(endDateFormattedString, 'YYYY-MM-DD').toDate(); + + if (!dayjs(startDateDate).isSame(startDateEdit, 'day')) { + updatedFields.startDate = startDateDate; + } + if (!dayjs(endDateDate).isSame(endDateEdit, 'day')) { + updatedFields.endDate = endDateDate; + } + + console.log('At handle update', updatedFields); + const { data } = await updateAdvertisement({ + variables: { + id: idEdit, + ...(updatedFields.name && { name: updatedFields.name }), + ...(updatedFields.advertisementMedia && { + file: updatedFields.advertisementMedia, + }), + ...(updatedFields.type && { type: updatedFields.type }), + ...(updatedFields.startDate && { + startDate: startDateFormattedString, + }), + ...(updatedFields.endDate && { endDate: endDateFormattedString }), + }, + }); + + if (data) { + toast.success('Advertisement updated successfully'); + handleClose(); + setAfter(null); } - } catch (error) { - console.log('error occured', error); + } catch (error: any) { + toast.error(error.message); } }; return ( + //If register show register button else show edit button <> - + {formStatus === 'register' ? ( + + ) : ( +
    + {t('edit')} +
    + )} - - {t('RClose')} + + {formStatus === 'register' ? ( + {t('RClose')} + ) : ( + {t('editAdvertisement')} + )}
    @@ -100,21 +247,70 @@ function advertisementRegister({ }} /> - - {t('Rlink')} + + + {t('Rmedia')} + { - setFormState({ - ...formState, - link: e.target.value, - }); + accept="image/*, video/*" + data-testid="advertisementMedia" + name="advertisementMedia" + type="file" + id="advertisementMedia" + multiple={false} + onChange={async ( + e: React.ChangeEvent, + ): Promise => { + const target = e.target as HTMLInputElement; + const file = target.files && target.files[0]; + if (file) { + const mediaBase64 = await convertToBase64(file); + setFormState({ + ...formState, + advertisementMedia: mediaBase64, + }); + } }} /> + {formState.advertisementMedia && ( +
    + {formState.advertisementMedia.includes('video') ? ( + + ) : ( + + )} + +
    + )}
    {t('Rtype')} @@ -126,7 +322,6 @@ function advertisementRegister({ ...formState, type: e.target.value, }); - console.log(e.target, e.target.value, typeof e.target.value); }} > @@ -139,7 +334,7 @@ function advertisementRegister({ { setFormState({ ...formState, @@ -154,7 +349,7 @@ function advertisementRegister({ { setFormState({ ...formState, @@ -173,13 +368,23 @@ function advertisementRegister({ > {t('close')} - + {formStatus === 'register' ? ( + + ) : ( + + )} @@ -188,20 +393,22 @@ function advertisementRegister({ advertisementRegister.defaultProps = { name: '', - link: '', + advertisementMedia: '', type: 'BANNER', startDate: new Date(), endDate: new Date(), - orgId: '', + organizationId: '', + formStatus: 'register', }; advertisementRegister.propTypes = { name: PropTypes.string, - link: PropTypes.string, + advertisementMedia: PropTypes.string, type: PropTypes.string, startDate: PropTypes.instanceOf(Date), endDate: PropTypes.instanceOf(Date), - orgId: PropTypes.string, + organizationId: PropTypes.string, + formStatus: PropTypes.string, }; export default advertisementRegister; diff --git a/src/components/Avatar/Avatar.module.css b/src/components/Avatar/Avatar.module.css new file mode 100644 index 0000000000..14aa36e9ad --- /dev/null +++ b/src/components/Avatar/Avatar.module.css @@ -0,0 +1,11 @@ +.imageContainer { + width: 56px; + height: 56px; + border-radius: 100%; +} +.imageContainer img { + width: 100%; + height: 100%; + object-fit: cover; + border-radius: 100%; +} diff --git a/src/components/Avatar/Avatar.test.tsx b/src/components/Avatar/Avatar.test.tsx new file mode 100644 index 0000000000..d178c48a4a --- /dev/null +++ b/src/components/Avatar/Avatar.test.tsx @@ -0,0 +1,50 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import Avatar from './Avatar'; +import { BrowserRouter } from 'react-router-dom'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; + +describe('Avatar component', () => { + test('renders with name and alt attribute', () => { + const testName = 'John Doe'; + const testAlt = 'Test Alt Text'; + const testSize = 64; + + const { getByAltText } = render( + + + + + , + ); + const avatarElement = getByAltText(testAlt); + + expect(avatarElement).toBeInTheDocument(); + expect(avatarElement.getAttribute('src')).toBeDefined(); + }); + + test('renders with custom style and data-testid', () => { + const testName = 'Jane Doe'; + const testStyle = 'custom-avatar-style'; + const testDataTestId = 'custom-avatar-test-id'; + + const { getByAltText } = render( + + + + + , + ); + const avatarElement = getByAltText('Dummy Avatar'); + + expect(avatarElement).toBeInTheDocument(); + expect(avatarElement.getAttribute('src')).toBeDefined(); + expect(avatarElement.getAttribute('class')).toContain(testStyle); + expect(avatarElement.getAttribute('data-testid')).toBe(testDataTestId); + }); +}); diff --git a/src/components/Avatar/Avatar.tsx b/src/components/Avatar/Avatar.tsx new file mode 100644 index 0000000000..6d4cab405b --- /dev/null +++ b/src/components/Avatar/Avatar.tsx @@ -0,0 +1,45 @@ +import React, { useMemo } from 'react'; +import { createAvatar } from '@dicebear/core'; +import { initials } from '@dicebear/collection'; +import styles from 'components/Avatar/Avatar.module.css'; + +interface InterfaceAvatarProps { + name: string; + alt?: string; + size?: number; + avatarStyle?: string; + dataTestId?: string; + radius?: number; +} + +const Avatar = ({ + name, + alt = 'Dummy Avatar', + size, + avatarStyle, + dataTestId, + radius, +}: InterfaceAvatarProps): JSX.Element => { + const avatar = useMemo(() => { + return createAvatar(initials, { + size: size || 128, + seed: name, + radius: radius || 0, + }).toDataUriSync(); + }, [name, size]); + + const svg = avatar.toString(); + + return ( +
    + {alt} +
    + ); +}; + +export default Avatar; diff --git a/src/components/ChangeLanguageDropdown/ChangeLanguageDropDown.tsx b/src/components/ChangeLanguageDropdown/ChangeLanguageDropDown.tsx index 8f4fd945ed..e3ee7a987f 100644 --- a/src/components/ChangeLanguageDropdown/ChangeLanguageDropDown.tsx +++ b/src/components/ChangeLanguageDropdown/ChangeLanguageDropDown.tsx @@ -15,7 +15,7 @@ export const changeLanguage = async (languageCode: string): Promise => { }; const ChangeLanguageDropDown = ( - props: InterfaceChangeLanguageDropDownProps + props: InterfaceChangeLanguageDropDownProps, ): JSX.Element => { const currentLanguageCode = cookies.get('i18next') || 'en'; diff --git a/src/components/ChangeLanguageDropdown/ChangeLanguageDropdown.test.tsx b/src/components/ChangeLanguageDropdown/ChangeLanguageDropdown.test.tsx index 79209107fa..1708882cea 100644 --- a/src/components/ChangeLanguageDropdown/ChangeLanguageDropdown.test.tsx +++ b/src/components/ChangeLanguageDropdown/ChangeLanguageDropdown.test.tsx @@ -23,7 +23,7 @@ describe('Testing Change Language Dropdown', () => { - + , ); expect(getByTestId('language-dropdown-container')).toBeInTheDocument(); @@ -39,7 +39,7 @@ describe('Testing Change Language Dropdown', () => { languages.map((language) => { expect( - getByTestId(`change-language-btn-${language.code}`) + getByTestId(`change-language-btn-${language.code}`), ).toBeInTheDocument(); }); }); @@ -55,10 +55,10 @@ describe('Testing Change Language Dropdown', () => { - + , ); getByTestId('language-dropdown-container').className.includes( - props.parentContainerStyle + props.parentContainerStyle, ); getByTestId('language-dropdown-btn').className.includes(props.btnStyle); getByTestId('dropdown-btn-0').className.includes(props.btnTextStyle); @@ -73,7 +73,7 @@ describe('Testing Change Language Dropdown', () => { render( - + , ); await wait(); @@ -89,14 +89,14 @@ describe('Testing Change Language Dropdown', () => { const { getByTestId } = render( - + , ); userEvent.click(getByTestId('language-dropdown-btn')); await wait(); languages.map((language) => { const changeLanguageBtn = getByTestId( - `change-language-btn-${language.code}` + `change-language-btn-${language.code}`, ); expect(changeLanguageBtn).toBeInTheDocument(); userEvent.click(changeLanguageBtn); diff --git a/src/components/CheckIn/CheckInModal.test.tsx b/src/components/CheckIn/CheckInModal.test.tsx index 80fe9dd918..1660c7c4bb 100644 --- a/src/components/CheckIn/CheckInModal.test.tsx +++ b/src/components/CheckIn/CheckInModal.test.tsx @@ -35,11 +35,11 @@ describe('Testing Check In Attendees Modal', () => { - + , ); await waitFor(() => - expect(queryByText('Event Check In Management')).toBeInTheDocument() + expect(queryByText('Event Check In Management')).toBeInTheDocument(), ); await waitFor(() => expect(queryByText('John Doe')).toBeInTheDocument()); @@ -52,7 +52,7 @@ describe('Testing Check In Attendees Modal', () => { await waitFor(() => expect(queryByText('John Doe')).toBeInTheDocument()); await waitFor(() => - expect(queryByText('John2 Doe2')).not.toBeInTheDocument() + expect(queryByText('John2 Doe2')).not.toBeInTheDocument(), ); }); }); diff --git a/src/components/CheckIn/CheckInModal.tsx b/src/components/CheckIn/CheckInModal.tsx index 3f15824ecd..6b4e5425c0 100644 --- a/src/components/CheckIn/CheckInModal.tsx +++ b/src/components/CheckIn/CheckInModal.tsx @@ -45,8 +45,8 @@ export const CheckInModal = (props: InterfaceModalProp): JSX.Element => { checkIn: checkIn.checkIn, eventId: props.eventId, }, - }) - ) + }), + ), ); }, [checkInData, props.eventId, checkInLoading]); @@ -80,7 +80,7 @@ export const CheckInModal = (props: InterfaceModalProp): JSX.Element => { size="lg" > - + Event Check In Management diff --git a/src/components/CheckIn/CheckInWrapper.test.tsx b/src/components/CheckIn/CheckInWrapper.test.tsx index 9cb7fef4ba..81f53d0043 100644 --- a/src/components/CheckIn/CheckInWrapper.test.tsx +++ b/src/components/CheckIn/CheckInWrapper.test.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { fireEvent, render, waitFor } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import { MockedProvider } from '@apollo/react-testing'; import { CheckInWrapper } from './CheckInWrapper'; import { BrowserRouter } from 'react-router-dom'; @@ -21,7 +21,7 @@ describe('Testing CheckIn Wrapper', () => { }; test('The button to open and close the modal should work properly', async () => { - const { queryByText } = render( + render( @@ -33,26 +33,23 @@ describe('Testing CheckIn Wrapper', () => { - + , ); // Open the modal - fireEvent.click(queryByText('Check In Registrants') as Element); + fireEvent.click(screen.getByLabelText('checkInRegistrants') as Element); await waitFor(() => - expect(queryByText('Event Check In Management')).toBeInTheDocument() + expect(screen.queryByTestId('modal-title')).toBeInTheDocument(), ); - /* - TODO - The following test of closing the modal should be uncommented when the memory leak issue of MUI Data Grid is fixed. - - It will consequently ensure 100% coverage of the file. - */ - // Close the modal - // fireEvent.click(queryByRole('button', { name: /close/i }) as HTMLElement); - // await waitFor(() => - // expect(queryByText('Event Check In Management')).not.toBeInTheDocument() - // ); + // Close the modal + const closebtn = screen.getByLabelText('Close'); + + fireEvent.click(closebtn as Element); + + await waitFor(() => + expect(screen.queryByTestId('modal-title')).not.toBeInTheDocument(), + ); }); }); diff --git a/src/components/CheckIn/TableRow.test.tsx b/src/components/CheckIn/TableRow.test.tsx index b8ab48f397..8d41f1036b 100644 --- a/src/components/CheckIn/TableRow.test.tsx +++ b/src/components/CheckIn/TableRow.test.tsx @@ -37,7 +37,7 @@ describe('Testing Table Row for CheckIn Table', () => { - + , ); await waitFor(() => expect(queryByText('Check In')).toBeInTheDocument()); @@ -45,7 +45,7 @@ describe('Testing Table Row for CheckIn Table', () => { fireEvent.click(queryByText('Check In') as Element); await waitFor(() => - expect(queryByText('Checked in successfully!')).toBeInTheDocument() + expect(queryByText('Checked in successfully!')).toBeInTheDocument(), ); }); @@ -58,8 +58,6 @@ describe('Testing Table Row for CheckIn Table', () => { checkIn: { _id: '123', time: '12:00:00', - allotedRoom: '', - allotedSeat: '', }, eventId: `event123`, }, @@ -78,7 +76,7 @@ describe('Testing Table Row for CheckIn Table', () => { - + , ); // Stubbing functions required by the @pdfme to show pdfs @@ -87,13 +85,13 @@ describe('Testing Table Row for CheckIn Table', () => { await waitFor(() => expect(queryByText('Checked In')).toBeInTheDocument()); await waitFor(() => - expect(queryByText('Download Tag')).toBeInTheDocument() + expect(queryByText('Download Tag')).toBeInTheDocument(), ); fireEvent.click(queryByText('Download Tag') as Element); await waitFor(() => - expect(queryByText('Generating pdf...')).toBeInTheDocument() + expect(queryByText('Generating pdf...')).toBeInTheDocument(), ); await waitFor(() => { expect(queryByText('PDF generated successfully!')).toBeInTheDocument(); @@ -124,7 +122,7 @@ describe('Testing Table Row for CheckIn Table', () => { - + , ); await waitFor(() => expect(queryByText('Check In')).toBeInTheDocument()); @@ -133,8 +131,8 @@ describe('Testing Table Row for CheckIn Table', () => { await waitFor(() => expect( - queryByText('There was an error in checking in!') - ).toBeInTheDocument() + queryByText('There was an error in checking in!'), + ).toBeInTheDocument(), ); await waitFor(() => expect(queryByText('Oops')).toBeInTheDocument()); }); diff --git a/src/components/CheckIn/TableRow.tsx b/src/components/CheckIn/TableRow.tsx index 90e22deff0..bceaf3a49d 100644 --- a/src/components/CheckIn/TableRow.tsx +++ b/src/components/CheckIn/TableRow.tsx @@ -17,14 +17,11 @@ export const TableRow = ({ const [checkInMutation] = useMutation(MARK_CHECKIN); const markCheckIn = (): void => { - // Since the backend supports the storage of the alloted seat and the alloted room to the user, we pass the same as blank // as we do not want to clutter the UI currently with the same (only provide the most basic of operations) checkInMutation({ variables: { userId: data.userId, eventId: data.eventId, - allotedSeat: '', - allotedRoom: '', }, }) .then(() => { diff --git a/src/components/CheckIn/mocks.ts b/src/components/CheckIn/mocks.ts index b038e5ae7a..a4e78aa2fc 100644 --- a/src/components/CheckIn/mocks.ts +++ b/src/components/CheckIn/mocks.ts @@ -25,8 +25,6 @@ const checkInQueryData: InterfaceAttendeeQueryResponse = { checkIn: { _id: 'checkin1', time: '08:00:00', - allotedRoom: 'Room 1', - allotedSeat: 'Seat 1', }, }, ], @@ -52,8 +50,6 @@ export const checkInMutationSuccess = [ variables: { userId: 'user123', eventId: 'event123', - allotedSeat: '', - allotedRoom: '', }, }, result: { @@ -73,8 +69,6 @@ export const checkInMutationUnsuccess = [ variables: { userId: 'user123', eventId: 'event123', - allotedSeat: '', - allotedRoom: '', }, }, error: new Error('Oops'), diff --git a/src/components/CheckIn/types.ts b/src/components/CheckIn/types.ts index 19dc4db4af..2fcb2d63cf 100644 --- a/src/components/CheckIn/types.ts +++ b/src/components/CheckIn/types.ts @@ -10,8 +10,6 @@ export interface InterfaceAttendeeCheckIn { checkIn: null | { _id: string; time: string; - allotedRoom: string; - allotedSeat: string; }; } @@ -35,8 +33,6 @@ export interface InterfaceTableCheckIn { checkIn: null | { _id: string; time: string; - allotedRoom: string; - allotedSeat: string; }; eventId: string; } diff --git a/src/components/CollapsibleDropdown/CollapsibleDropdown.test.tsx b/src/components/CollapsibleDropdown/CollapsibleDropdown.test.tsx index 4f1916669a..f7c94b223b 100644 --- a/src/components/CollapsibleDropdown/CollapsibleDropdown.test.tsx +++ b/src/components/CollapsibleDropdown/CollapsibleDropdown.test.tsx @@ -1,12 +1,24 @@ import React from 'react'; -import { render, screen } from '@testing-library/react'; +import { render, screen, fireEvent } from '@testing-library/react'; import { BrowserRouter } from 'react-router-dom'; import CollapsibleDropdown from './CollapsibleDropdown'; import type { InterfaceCollapsibleDropdown } from './CollapsibleDropdown'; +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useLocation: () => ({ + pathname: '/orgstore', + state: {}, + key: '', + search: '', + hash: '', + }), +})); + const props: InterfaceCollapsibleDropdown = { - screenName: 'SubCategory 1', + showDropdown: true, + setShowDropdown: jest.fn(), target: { name: 'DropDown Category', url: undefined, @@ -27,7 +39,11 @@ const props: InterfaceCollapsibleDropdown = { describe('Testing CollapsibleDropdown component', () => { test('Component should be rendered properly', () => { - render(); + render( + + + , + ); expect(screen.getByText('DropDown Category')).toBeInTheDocument(); expect(screen.getByText('SubCategory 1')).toBeInTheDocument(); expect(screen.getByText('SubCategory 2')).toBeInTheDocument(); @@ -37,13 +53,14 @@ describe('Testing CollapsibleDropdown component', () => { render( - + , ); const parentDropdownBtn = screen.getByTestId('collapsible-dropdown'); const activeDropdownBtn = screen.getByText('SubCategory 1'); const nonActiveDropdownBtn = screen.getByText('SubCategory 2'); // Check if dropdown is rendered with correct classes + activeDropdownBtn.click(); expect(parentDropdownBtn).toBeInTheDocument(); expect(parentDropdownBtn).toHaveClass('text-white'); expect(parentDropdownBtn).toHaveClass('btn-success'); @@ -58,17 +75,13 @@ describe('Testing CollapsibleDropdown component', () => { expect(nonActiveDropdownBtn).toHaveClass('text-secondary'); expect(nonActiveDropdownBtn).toHaveClass('btn-light'); - // Check if dropdown is expanded by default since the screenName prop passes - // the same value as the name prop of the subTarget - expect(parentDropdownBtn).toHaveAttribute('aria-expanded', 'true'); - // Check if dropdown is collapsed after clicking on it - parentDropdownBtn.click(); - expect(parentDropdownBtn).toHaveAttribute('aria-expanded', 'false'); + fireEvent.click(parentDropdownBtn); + expect(props.setShowDropdown).toHaveBeenCalledWith(false); // Check if dropdown is expanded after clicking on it again - parentDropdownBtn.click(); - expect(parentDropdownBtn).toHaveAttribute('aria-expanded', 'true'); + fireEvent.click(parentDropdownBtn); + expect(props.setShowDropdown).toHaveBeenCalledWith(true); // Click on non active dropdown button and check if it navigates to the correct url nonActiveDropdownBtn.click(); diff --git a/src/components/CollapsibleDropdown/CollapsibleDropdown.tsx b/src/components/CollapsibleDropdown/CollapsibleDropdown.tsx index 81b82e220d..03f08b044f 100644 --- a/src/components/CollapsibleDropdown/CollapsibleDropdown.tsx +++ b/src/components/CollapsibleDropdown/CollapsibleDropdown.tsx @@ -3,36 +3,35 @@ import { Button, Collapse } from 'react-bootstrap'; import type { TargetsType } from 'state/reducers/routesReducer'; import styles from './CollapsibleDropdown.module.css'; import IconComponent from 'components/IconComponent/IconComponent'; -import { useHistory } from 'react-router-dom'; +import { NavLink, useLocation, useNavigate } from 'react-router-dom'; export interface InterfaceCollapsibleDropdown { - screenName: string; + showDropdown: boolean; target: TargetsType; + setShowDropdown: React.Dispatch>; } const collapsibleDropdown = ({ - screenName, target, + showDropdown, + setShowDropdown, }: InterfaceCollapsibleDropdown): JSX.Element => { - const [showDropdown, setShowDropdown] = React.useState(false); - const [active, setActive] = React.useState(false); const { name, subTargets } = target; - const history = useHistory(); - + const navigate = useNavigate(); + const location = useLocation(); useEffect(() => { - target.subTargets?.map(({ name }) => { - if (name === screenName) { - setActive(true); - setShowDropdown(true); - } - }); - }, [target.subTargets]); + if (location.pathname.includes('orgstore')) { + setShowDropdown(true); + } else { + setShowDropdown(false); + } + }, [location.pathname]); return ( <>
    - + onClick={(): void => { + navigate(url); + }} + data-testid={`collapsible-dropdown-btn-${index}`} + > +
    + +
    + {name} +
    + +
    + + )} + ); })}
    diff --git a/src/components/ContriStats/ContriStats.test.tsx b/src/components/ContriStats/ContriStats.test.tsx index 9c21944318..3164c880c8 100644 --- a/src/components/ContriStats/ContriStats.test.tsx +++ b/src/components/ContriStats/ContriStats.test.tsx @@ -27,7 +27,7 @@ describe('Testing Contribution Stats', () => { - + , ); expect(screen.getByText('Recent Contribution: $')).toBeInTheDocument(); expect(screen.getByText('Highest Contribution: $')).toBeInTheDocument(); diff --git a/src/components/CurrentHourIndicator/CurrentHourIndicator.module.css b/src/components/CurrentHourIndicator/CurrentHourIndicator.module.css new file mode 100644 index 0000000000..d2c250035a --- /dev/null +++ b/src/components/CurrentHourIndicator/CurrentHourIndicator.module.css @@ -0,0 +1,19 @@ +.round { + background-color: red; + border-radius: 100%; + width: 15px; + height: 15px; +} +.line { + width: 100%; + height: 1px; + background-color: red; + margin: auto; +} +.container { + position: relative; + display: flex; + flex-direction: row; + top: -8px; + left: -9px; +} diff --git a/src/components/CurrentHourIndicator/CurrentHourIndicator.test.tsx b/src/components/CurrentHourIndicator/CurrentHourIndicator.test.tsx new file mode 100644 index 0000000000..084817dc0d --- /dev/null +++ b/src/components/CurrentHourIndicator/CurrentHourIndicator.test.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import CurrentHourIndicator from './CurrentHourIndicator'; + +describe('Testing Current Hour Indicator', () => { + test('Component Should be rendered properly', async () => { + const { getByTestId } = render(); + expect(getByTestId('container')).toBeInTheDocument(); + }); +}); diff --git a/src/components/CurrentHourIndicator/CurrentHourIndicator.tsx b/src/components/CurrentHourIndicator/CurrentHourIndicator.tsx new file mode 100644 index 0000000000..9e4a85454a --- /dev/null +++ b/src/components/CurrentHourIndicator/CurrentHourIndicator.tsx @@ -0,0 +1,13 @@ +import React from 'react'; +import styles from './CurrentHourIndicator.module.css'; + +const CurrentHourIndicator = (): JSX.Element => { + return ( +
    +
    +
    +
    + ); +}; + +export default CurrentHourIndicator; diff --git a/src/components/DeleteOrg/DeleteOrg.test.tsx b/src/components/DeleteOrg/DeleteOrg.test.tsx index 936cf44e03..d9ac99f3ad 100644 --- a/src/components/DeleteOrg/DeleteOrg.test.tsx +++ b/src/components/DeleteOrg/DeleteOrg.test.tsx @@ -6,34 +6,108 @@ import { I18nextProvider } from 'react-i18next'; import { Provider } from 'react-redux'; import { BrowserRouter } from 'react-router-dom'; -import { DELETE_ORGANIZATION_MUTATION } from 'GraphQl/Mutations/mutations'; +import { + DELETE_ORGANIZATION_MUTATION, + REMOVE_SAMPLE_ORGANIZATION_MUTATION, +} from 'GraphQl/Mutations/mutations'; import { act } from 'react-dom/test-utils'; import { store } from 'state/store'; import { StaticMockLink } from 'utils/StaticMockLink'; import i18nForTest from 'utils/i18nForTest'; import DeleteOrg from './DeleteOrg'; +import { ToastContainer, toast } from 'react-toastify'; +import { IS_SAMPLE_ORGANIZATION_QUERY } from 'GraphQl/Queries/Queries'; +import useLocalStorage from 'utils/useLocalstorage'; + +const { setItem } = useLocalStorage(); + +async function wait(ms = 1000): Promise { + await act(async () => { + await new Promise((resolve) => setTimeout(resolve, ms)); + }); +} const MOCKS = [ + { + request: { + query: IS_SAMPLE_ORGANIZATION_QUERY, + variables: { + isSampleOrganizationId: '123', + }, + }, + result: { + data: { + isSampleOrganization: true, + }, + }, + }, + { + request: { + query: REMOVE_SAMPLE_ORGANIZATION_MUTATION, + }, + result: { + data: { + removeSampleOrganization: true, + }, + }, + }, { request: { query: DELETE_ORGANIZATION_MUTATION, variables: { - id: 123, + id: '456', + }, + }, + result: { + data: { + removeOrganization: { + _id: '456', + }, + }, + }, + }, +]; + +const MOCKS_WITH_ERROR = [ + { + request: { + query: IS_SAMPLE_ORGANIZATION_QUERY, + variables: { + isSampleOrganizationId: '123', }, }, result: { data: { - removeOrganization: [ - { - _id: 123, - }, - ], + isSampleOrganization: true, + }, + }, + }, + { + request: { + query: DELETE_ORGANIZATION_MUTATION, + variables: { + id: '456', }, }, + error: new Error('Failed to delete organization'), + }, + { + request: { + query: REMOVE_SAMPLE_ORGANIZATION_MUTATION, + }, + error: new Error('Failed to delete sample organization'), }, ]; +const mockNavgatePush = jest.fn(); +let mockURL = '123'; +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: mockURL }), + useNavigate: () => mockNavgatePush, +})); const link = new StaticMockLink(MOCKS, true); +const link2 = new StaticMockLink(MOCKS_WITH_ERROR, true); afterEach(() => { localStorage.clear(); @@ -41,31 +115,75 @@ afterEach(() => { describe('Delete Organization Component', () => { test('should be able to Toggle Delete Organization Modal', async () => { - window.location.assign('/orgsetting/id=123'); - localStorage.setItem('UserType', 'SUPERADMIN'); + mockURL = '456'; + setItem('SuperAdmin', true); render( + - + , ); + await wait(); + screen.getByTestId(/openDeleteModalBtn/i).click(); + expect(screen.getByTestId(/orgDeleteModal/i)).toBeInTheDocument(); + screen.getByTestId(/closeDelOrgModalBtn/i).click(); + await act(async () => { + expect(screen.queryByTestId(/orgDeleteModal/i)).not.toHaveFocus(); + }); + }); + + test('should be able to Toggle Delete Organization Modal When Organization is Sample Organization', async () => { + mockURL = '123'; + setItem('SuperAdmin', true); + render( + + + + + + + + + + , + ); + await wait(); screen.getByTestId(/openDeleteModalBtn/i).click(); expect(screen.getByTestId(/orgDeleteModal/i)).toBeInTheDocument(); screen.getByTestId(/closeDelOrgModalBtn/i).click(); await act(async () => { expect(screen.queryByTestId(/orgDeleteModal/i)).not.toHaveFocus(); }); - expect(window.location).toBeAt('/orgsetting/id=123'); }); test('Delete organization functionality should work properly', async () => { - window.location.assign('/orgsetting/id=123'); - localStorage.setItem('UserType', 'SUPERADMIN'); + mockURL = '456'; + setItem('SuperAdmin', true); + render( + + + + + + + + + , + ); + await wait(); + screen.getByTestId(/openDeleteModalBtn/i).click(); + screen.getByTestId(/deleteOrganizationBtn/i).click(); + }); + + test('Delete organization functionality should work properly for sample org', async () => { + mockURL = '123'; + setItem('SuperAdmin', true); render( @@ -75,10 +193,56 @@ describe('Delete Organization Component', () => { - + , + ); + await wait(); + screen.getByTestId(/openDeleteModalBtn/i).click(); + screen.getByTestId(/deleteOrganizationBtn/i).click(); + await wait(2000); + expect(mockNavgatePush).toHaveBeenCalledWith('/orglist'); + }); + + test('Error handling for IS_SAMPLE_ORGANIZATION_QUERY mock', async () => { + mockURL = '123'; + setItem('SuperAdmin', true); + jest.spyOn(toast, 'error'); + render( + + + + + + + + + , + ); + await wait(); + screen.getByTestId(/openDeleteModalBtn/i).click(); + screen.getByTestId(/deleteOrganizationBtn/i).click(); + await wait(); + expect(toast.error).toHaveBeenCalledWith( + 'Failed to delete sample organization', + ); + }); + + test('Error handling for DELETE_ORGANIZATION_MUTATION mock', async () => { + mockURL = '456'; + setItem('SuperAdmin', true); + render( + + + + + + + + + , ); + await wait(); screen.getByTestId(/openDeleteModalBtn/i).click(); screen.getByTestId(/deleteOrganizationBtn/i).click(); - expect(window.location).not.toBeNull(); + await wait(); }); }); diff --git a/src/components/DeleteOrg/DeleteOrg.tsx b/src/components/DeleteOrg/DeleteOrg.tsx index b7ceafbd5c..947aa023f6 100644 --- a/src/components/DeleteOrg/DeleteOrg.tsx +++ b/src/components/DeleteOrg/DeleteOrg.tsx @@ -4,23 +4,29 @@ import { useTranslation } from 'react-i18next'; import { useMutation, useQuery } from '@apollo/client'; import { errorHandler } from 'utils/errorHandler'; import { toast } from 'react-toastify'; -import { DELETE_ORGANIZATION_MUTATION } from 'GraphQl/Mutations/mutations'; -import { REMOVE_SAMPLE_ORGANIZATION_MUTATION } from 'GraphQl/Mutations/mutations'; +import { + DELETE_ORGANIZATION_MUTATION, + REMOVE_SAMPLE_ORGANIZATION_MUTATION, +} from 'GraphQl/Mutations/mutations'; import { IS_SAMPLE_ORGANIZATION_QUERY } from 'GraphQl/Queries/Queries'; import styles from './DeleteOrg.module.css'; +import { useNavigate, useParams } from 'react-router-dom'; +import useLocalStorage from 'utils/useLocalstorage'; function deleteOrg(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'deleteOrg', }); + const { orgId: currentUrl } = useParams(); + const navigate = useNavigate(); const [showDeleteModal, setShowDeleteModal] = useState(false); - const currentUrl = window.location.href.split('=')[1]; - const canDelete = localStorage.getItem('UserType') === 'SUPERADMIN'; + const { getItem } = useLocalStorage(); + const canDelete = getItem('SuperAdmin'); const toggleDeleteModal = (): void => setShowDeleteModal(!showDeleteModal); const [del] = useMutation(DELETE_ORGANIZATION_MUTATION); const [removeSampleOrganization] = useMutation( - REMOVE_SAMPLE_ORGANIZATION_MUTATION + REMOVE_SAMPLE_ORGANIZATION_MUTATION, ); const { data } = useQuery(IS_SAMPLE_ORGANIZATION_QUERY, { @@ -33,12 +39,14 @@ function deleteOrg(): JSX.Element { if (data && data.isSampleOrganization) { removeSampleOrganization() .then(() => { - toast.success('Successfully deleted sample Organization'); + toast.success(t('successfullyDeletedSampleOrganization')); + setTimeout(() => { + navigate('/orglist'); + }, 1000); }) .catch((error) => { toast.error(error.message); }); - window.location.replace('/orglist'); } else { try { await del({ @@ -46,8 +54,8 @@ function deleteOrg(): JSX.Element { id: currentUrl, }, }); - window.location.replace('/orglist'); - } catch (error: any) { + navigate('/orglist'); + } catch (error) { errorHandler(t, error); } } @@ -56,7 +64,7 @@ function deleteOrg(): JSX.Element { return ( <> {canDelete && ( - +
    {t('deleteOrganization')}
    @@ -82,7 +90,7 @@ function deleteOrg(): JSX.Element { onHide={toggleDeleteModal} data-testid="orgDeleteModal" > - +
    {t('deleteOrganization')}
    {t('deleteMsg')} diff --git a/src/components/DynamicDropDown/DynamicDropDown.module.css b/src/components/DynamicDropDown/DynamicDropDown.module.css new file mode 100644 index 0000000000..0edf85b621 --- /dev/null +++ b/src/components/DynamicDropDown/DynamicDropDown.module.css @@ -0,0 +1,12 @@ +.dropwdownToggle { + background-color: #f1f3f6; + color: black; + border: none; + padding: 0.5rem; + text-align: left; + display: flex; + align-items: center; + justify-content: space-between; + min-width: 8rem; + outline: 1px solid var(--bs-gray-400); +} diff --git a/src/components/DynamicDropDown/DynamicDropDown.test.tsx b/src/components/DynamicDropDown/DynamicDropDown.test.tsx new file mode 100644 index 0000000000..c77ac5aebf --- /dev/null +++ b/src/components/DynamicDropDown/DynamicDropDown.test.tsx @@ -0,0 +1,64 @@ +import React from 'react'; +import { render, screen, act, waitFor } from '@testing-library/react'; +import DynamicDropDown from './DynamicDropDown'; +import { BrowserRouter } from 'react-router-dom'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; +import userEvent from '@testing-library/user-event'; + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('DynamicDropDown component', () => { + test('renders with name and alt attribute', async () => { + const [formData, setFormData] = [ + { + fieldName: 'TEST', + }, + jest.fn(), + ]; + + render( + + + + + , + ); + const containterElement = screen.getByTestId( + 'fieldname-dropdown-container', + ); + await act(async () => { + userEvent.click(containterElement); + }); + + const optionButton = screen.getByTestId('fieldname-dropdown-btn'); + + await act(async () => { + userEvent.click(optionButton); + }); + + const optionElement = screen.getByTestId('change-fieldname-btn-TEST'); + await act(async () => { + userEvent.click(optionElement); + }); + await wait(); + expect(containterElement).toBeInTheDocument(); + await waitFor(() => { + expect(optionButton).toHaveTextContent('label1'); + }); + }); +}); diff --git a/src/components/DynamicDropDown/DynamicDropDown.tsx b/src/components/DynamicDropDown/DynamicDropDown.tsx new file mode 100644 index 0000000000..170b6be29b --- /dev/null +++ b/src/components/DynamicDropDown/DynamicDropDown.tsx @@ -0,0 +1,55 @@ +import React from 'react'; +import { Dropdown } from 'react-bootstrap'; +import styles from './DynamicDropDown.module.css'; + +interface InterfaceChangeDropDownProps { + parentContainerStyle?: string; + btnStyle?: string; + btnTextStyle?: string; + setFormState: React.Dispatch>; + formState: any; + fieldOptions: { value: string; label: string }[]; // Field options for dropdown + fieldName: string; // Field name for labeling +} + +const DynamicDropDown = (props: InterfaceChangeDropDownProps): JSX.Element => { + const handleFieldChange = (value: string): void => { + props.setFormState({ ...props.formState, [props.fieldName]: value }); + }; + + const getLabel = (value: string): string => { + const selectedOption = props.fieldOptions.find( + (option) => option.value === value, + ); + return selectedOption ? selectedOption.label : `None`; + }; + + return ( + + + {getLabel(props.formState[props.fieldName])} + + + {props.fieldOptions.map((option, index: number) => ( + handleFieldChange(option.value)} + data-testid={`change-${props.fieldName.toLowerCase()}-btn-${option.value}`} + > + {option.label} + + ))} + + + ); +}; + +export default DynamicDropDown; diff --git a/src/components/EditCustomFieldDropDown/EditCustomFieldDropDown.test.tsx b/src/components/EditCustomFieldDropDown/EditCustomFieldDropDown.test.tsx new file mode 100644 index 0000000000..d4b92007e2 --- /dev/null +++ b/src/components/EditCustomFieldDropDown/EditCustomFieldDropDown.test.tsx @@ -0,0 +1,60 @@ +import type { Dispatch, SetStateAction } from 'react'; +import React from 'react'; +import { act, render } from '@testing-library/react'; +import { BrowserRouter } from 'react-router-dom'; +import EditOrgCustomFieldDropDown from './EditCustomFieldDropDown'; +import type { InterfaceCustomFieldData } from 'components/OrgProfileFieldSettings/OrgProfileFieldSettings'; +import userEvent from '@testing-library/user-event'; +import availableFieldTypes from 'utils/fieldTypes'; + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Testing Custom Field Dropdown', () => { + test('Component Should be rendered properly', async () => { + const customFieldData = { + type: 'Number', + name: 'Age', + }; + + const setCustomFieldData: Dispatch< + SetStateAction + > = (val) => { + { + val; + } + }; + const props = { + customFieldData: customFieldData as InterfaceCustomFieldData, + setCustomFieldData: setCustomFieldData, + parentContainerStyle: 'parentContainerStyle', + btnStyle: 'btnStyle', + btnTextStyle: 'btnTextStyle', + }; + + const { getByTestId, getByText } = render( + + + , + ); + + expect(getByText('Number')).toBeInTheDocument(); + + act(() => { + userEvent.click(getByTestId('toggleBtn')); + }); + + await wait(); + + availableFieldTypes.forEach(async (_, index) => { + act(() => { + userEvent.click(getByTestId(`dropdown-btn-${index}`)); + }); + }); + }); +}); diff --git a/src/components/EditCustomFieldDropDown/EditCustomFieldDropDown.tsx b/src/components/EditCustomFieldDropDown/EditCustomFieldDropDown.tsx new file mode 100644 index 0000000000..5ef7780627 --- /dev/null +++ b/src/components/EditCustomFieldDropDown/EditCustomFieldDropDown.tsx @@ -0,0 +1,53 @@ +import React from 'react'; +import type { SetStateAction, Dispatch } from 'react'; +import { Dropdown } from 'react-bootstrap'; +import availableFieldTypes from 'utils/fieldTypes'; +import type { InterfaceCustomFieldData } from 'components/OrgProfileFieldSettings/OrgProfileFieldSettings'; + +interface InterfaceEditCustomFieldDropDownProps { + customFieldData: InterfaceCustomFieldData; + setCustomFieldData: Dispatch>; + parentContainerStyle?: string; + btnStyle?: string; + btnTextStyle?: string; +} +[]; + +const EditOrgCustomFieldDropDown = ( + props: InterfaceEditCustomFieldDropDownProps, +): JSX.Element => { + return ( + + + {props.customFieldData.type || 'None'} + + + {availableFieldTypes.map((customFieldType, index: number) => ( + { + props.setCustomFieldData({ + ...props.customFieldData, + type: customFieldType, + }); + }} + disabled={props.customFieldData.type == customFieldType} + > + {customFieldType} + + ))} + + + ); +}; + +export default EditOrgCustomFieldDropDown; diff --git a/src/components/EventCalendar/EventCalendar.module.css b/src/components/EventCalendar/EventCalendar.module.css index 37ecb175d4..67ecd2dec6 100644 --- a/src/components/EventCalendar/EventCalendar.module.css +++ b/src/components/EventCalendar/EventCalendar.module.css @@ -1,56 +1,133 @@ .calendar { - /* display: flex; - flex-direction: column; */ font-family: sans-serif; font-size: 1.2rem; + margin-bottom: 20px; + background: rgb(255, 255, 255); + border-radius: 10px; + padding: 5px; } .calendar__header { display: flex; margin-bottom: 2rem; + align-items: center; + margin: 0px 10px 0px 10px; +} +.input { + flex: 1; + position: relative; } .calendar__header_month { margin: 0.5rem; color: #707070; - font-weight: bold; + font-weight: 800; + font-size: 55px; + display: flex; + gap: 23px; + flex-direction: row; +} +.calendar__header_month div { + font-weight: 400; + color: black; + font-family: Outfit; +} +.space { + flex: 1; + display: flex; + align-items: center; + justify-content: space-around; } .button { - background-color: rgba(40, 167, 69, 1); - color: #fff; - padding: 1px; + border-radius: 100px; + color: #707070; + background-color: rgba(194, 247, 182, 0); font-weight: bold; + border: 0px; + font-size: 20px; } + .calendar__weekdays { display: grid; grid-template-columns: repeat(7, 1fr); - margin-bottom: 1rem; background-color: black; + font-family: Outfit; + height: 60px; +} +.calendar__scroll { + height: 80vh; + padding: 10px; } .weekday { display: flex; justify-content: center; align-items: center; - border: 1px solid white; - color: #fff; - background-color: rgba(40, 167, 69, 1); + background-color: white; + font-weight: 600; } .calendar__days { display: grid; - grid-template-columns: repeat(7, 1fr); + grid-template-columns: repeat(7, minmax(0, 1fr)); grid-template-rows: repeat(6, 1fr); } +.calendar_hour_text_container { + display: flex; + flex-direction: row; + align-items: flex-end; + border-right: 1px solid #8d8d8d55; + width: 40px; +} +.calendar_hour_text { + top: -10px; + left: -5px; + position: relative; + color: #707070; + font-size: 12px; +} +.calendar_timezone_text { + top: -10px; + left: -11px; + position: relative; + color: #707070; + font-size: 9px; +} +.calendar_hour_block { + display: flex; + flex-direction: row; + border-bottom: 1px solid #8d8d8d55; + position: relative; + height: 50px; + border-bottom-right-radius: 5px; +} +.event_list_parent { + position: relative; + width: 100%; +} +.event_list_parent_current { + background-color: #def6e1; + position: relative; + width: 100%; +} +.dummyWidth { + width: 1px; +} .day { background-color: #ffffff; - border: 1px solid rgb(0, 0, 0); - padding-bottom: 4rem; padding-left: 0.3rem; padding-right: 0.3rem; + border-radius: 10px; + margin: 5px; background-color: white; - border: 1px solid #707070; - color: #212121; + border: 1px solid #8d8d8d55; + color: #4b4b4b; + font-weight: 600; + height: 9rem; + position: relative; +} +.day_weekends { + background-color: rgba(49, 187, 107, 0.2); } .day__outside { - background-color: #eeeded; - color: #898989; + background-color: white; + color: #89898996; } .day__selected { background-color: #007bff; @@ -60,23 +137,206 @@ background-color: #def6e1; font-weight: 700; text-decoration: underline; - color: #006000; + color: #31bb6b; +} +.day__events { + background-color: white; } .btn__today { - background: #06960f; transition: ease-in all 200ms; - border-radius: 11px; - box-shadow: 0px 1px 3px #666666; font-family: Arial; color: #ffffff; - font-size: 20px; + font-size: 18px; padding: 10px 20px 10px 20px; text-decoration: none; margin-left: 20px; border: none; } +.btnsContainer { + display: flex; + margin: 2.5rem 0 2.5rem 0; +} -.btn__today:hover { - background: #006000; - text-decoration: none; +.btnsContainer .btnsBlock { + display: flex; +} + +.btnsContainer .btnsBlock button { + margin-left: 1rem; + display: flex; + justify-content: center; + align-items: center; +} + +.dropdown { + border-color: #31bb6b; + background-color: white; + color: #31bb6b; + box-shadow: 0px 2px 1px rgba(49, 187, 107, 0.5); /* Added blur effect */ +} + +.btnsContainer .input { + flex: 1; + position: relative; +} + +.btnsContainer input { + outline: 1px solid var(--bs-gray-400); +} + +.btnsContainer .input button { + width: 52px; +} +.searchBtn { + margin-bottom: 10px; +} + +.inputField { + margin-top: 10px; + margin-bottom: 10px; + background-color: white; + box-shadow: 0 1px 1px #31bb6b; +} +.inputField > button { + padding-top: 10px; + padding-bottom: 10px; +} +.btn__more { + border: 0px; + font-size: 14px; + background-color: initial; + color: #262727; + font-weight: 600; + transition: all 200ms; + position: relative; + display: block; + margin: 2px; +} +.btn__more:hover { + color: #454645; +} + +.expand_event_list { + display: block; +} +.list_container { + padding: 5px; + width: fit-content; + display: flex; + flex-direction: row; +} +.event_list_hour { + display: flex; + flex-direction: row; +} +.expand_list_container { + width: 200px; + max-height: 250px; + z-index: 10; + position: absolute; + left: auto; + right: auto; + overflow: auto; + padding: 10px 4px 0px 4px; + background-color: rgb(241, 241, 241); + border: 1px solid rgb(201, 201, 201); + border-radius: 5px; + margin: 5px; +} +.flex_grow { + flex-grow: 1; +} + +@media only screen and (max-width: 700px) { + .event_list { + display: none; + } + .expand_list_container { + width: 150px; + padding: 4px 4px 0px 4px; + } + .day { + height: 5rem; + } +} + +@media only screen and (max-width: 500px) { + .btn__more { + font-size: 12px; + } +} + +.calendar__infocards { + display: flex; + flex-direction: row; + justify-content: space-between; + gap: 10px; + margin-top: 35px; +} +.card__holidays { + background-color: rgba(246, 242, 229, 1); + display: flex; + flex-direction: column; + width: 50%; + font-family: Outfit; + border-radius: 20px; + padding: 30px; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; +} +.month__holidays { + display: flex; + flex-direction: column; +} +.holiday__data { + display: flex; + flex-direction: row; + gap: 10px; +} +.holiday__date { + font-size: 20px; + color: rgba(234, 183, 86, 1); + font-weight: 700; +} +.holiday__name { + font-size: 20px; + margin-left: 35px; +} +.card__events { + background-color: rgba(244, 244, 244, 1); + display: flex; + flex-direction: column; + width: 50%; + font-family: Outfit; + border-radius: 20px; + padding: 30px; +} +.innercard__events { + display: flex; + flex-direction: row; + align-items: center; + gap: 1rem; +} +.innercard__events p { + margin-bottom: 0; +} +.orgEvent__color { + height: 15px; + width: 40px; + background-color: rgba(82, 172, 255, 0.5); + border-radius: 10px; +} +.holidays__color { + height: 15px; + width: 40px; + background: rgba(0, 0, 0, 0.15); + border-radius: 10px; +} + +.userEvents__color { + height: 15px; + width: 40px; + background: rgba(146, 200, 141, 0.5); + border-radius: 10px; } diff --git a/src/components/EventCalendar/EventCalendar.test.tsx b/src/components/EventCalendar/EventCalendar.test.tsx index 89d76329ac..657f43a781 100644 --- a/src/components/EventCalendar/EventCalendar.test.tsx +++ b/src/components/EventCalendar/EventCalendar.test.tsx @@ -1,8 +1,9 @@ -/* eslint-disable react/react-in-jsx-scope */ import Calendar from './EventCalendar'; -import { render, screen, fireEvent } from '@testing-library/react'; +import { render, screen, fireEvent, act } from '@testing-library/react'; import { MockedProvider } from '@apollo/react-testing'; import { I18nextProvider } from 'react-i18next'; +import React from 'react'; +import { ViewType } from 'screens/OrganizationEvents/OrganizationEvents'; import { DELETE_EVENT_MUTATION, @@ -10,7 +11,9 @@ import { } from 'GraphQl/Mutations/mutations'; import i18nForTest from 'utils/i18nForTest'; import { StaticMockLink } from 'utils/StaticMockLink'; -import styles from './EventCalendar.module.css'; +import { weekdays } from './constants'; +import { months } from './constants'; +import { BrowserRouter as Router } from 'react-router-dom'; const eventData = [ { @@ -24,8 +27,11 @@ const eventData = [ endTime: '12:00', allDay: false, recurring: false, + recurrenceRule: null, + isRecurringEventException: false, isPublic: true, isRegisterable: true, + viewType: ViewType.DAY, }, { _id: '2', @@ -38,6 +44,8 @@ const eventData = [ endTime: '16:00', allDay: false, recurring: false, + recurrenceRule: null, + isRecurringEventException: false, isPublic: true, isRegisterable: true, }, @@ -85,10 +93,18 @@ const MOCKS = [ const link = new StaticMockLink(MOCKS, true); +async function wait(ms = 200): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + describe('Calendar', () => { it('renders weekdays', () => { - render(); - const weekdays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; + render(); + weekdays.forEach((weekday) => { expect(screen.getByText(weekday)).toBeInTheDocument(); }); @@ -101,7 +117,7 @@ describe('Calendar', () => { const currentYear = getByTestId('current-date'); expect(currentMonth).toHaveTextContent( - today.toLocaleString('default', { month: 'long' }) + today.toLocaleString('default', { month: 'long' }), ); expect(currentYear).toHaveTextContent(today.getFullYear().toString()); }); @@ -111,19 +127,18 @@ describe('Calendar', () => { }); it('should render the current month and year', () => { - const { getByText } = render(); + const { getByTestId } = render(); + + // Find the element by its data-testid attribute + const currentDateElement = getByTestId('current-date'); + + // Assert that the text content of the element matches the current month and year const currentMonth = new Date().toLocaleString('default', { month: 'long', }); const currentYear = new Date().getFullYear(); - expect(getByText(`${currentMonth} ${currentYear}`)).toBeInTheDocument(); - }); - - it('should highlight the selected date when clicked', () => { - const { getByText } = render(); - const selectedDate = getByText('15'); - fireEvent.click(selectedDate); - expect(selectedDate).toHaveClass(styles.day); + const expectedText = ` ${currentYear} ${currentMonth}`; + expect(currentDateElement.textContent).toContain(expectedText); }); it('Should show prev and next month on clicking < & > buttons', () => { @@ -133,12 +148,12 @@ describe('Calendar', () => { - + , ); - const prevButton = screen.getByText('<'); + const prevButton = screen.getByTestId('prevmonthordate'); fireEvent.click(prevButton); //testing next month button - const nextButton = screen.getByText('>'); + const nextButton = screen.getByTestId('nextmonthordate'); fireEvent.click(nextButton); //Testing year change for (let index = 0; index < 13; index++) { @@ -148,6 +163,51 @@ describe('Calendar', () => { fireEvent.click(prevButton); } }); + it('Should show prev and next year on clicking < & > buttons when in year view', async () => { + //testing previous month button + render( + + + + + , + ); + await wait(); + const prevButtons = screen.getAllByTestId('prevYear'); + prevButtons.forEach((button) => { + fireEvent.click(button); + }); + await wait(); + //testing next year button + const nextButton = screen.getAllByTestId('prevYear'); + nextButton.forEach((button) => { + fireEvent.click(button); + }); + }); + it('Should show prev and next date on clicking < & > buttons in the day view', async () => { + render( + + + + + + + , + ); + //testing previous date button + const prevButton = screen.getByTestId('prevmonthordate'); + fireEvent.click(prevButton); + //testing next date button + const nextButton = screen.getByTestId('nextmonthordate'); + fireEvent.click(nextButton); + //Testing year change and month change + for (let index = 0; index < 366; index++) { + fireEvent.click(prevButton); + } + for (let index = 0; index < 732; index++) { + fireEvent.click(nextButton); + } + }); it('Should render eventlistcard of current day event', () => { const currentDayEventMock = [ { @@ -161,34 +221,45 @@ describe('Calendar', () => { endTime: '12:00', allDay: false, recurring: false, + recurrenceRule: null, + isRecurringEventException: false, isPublic: true, isRegisterable: true, }, ]; render( - - - - - + + + + + + + , + , ); }); it('Test for superadmin case', () => { render( - - - - - + + + + + + + , + , ); }); it('Today Cell is having correct styles', () => { render( - - - - - + + + + + + + , + , ); // const todayDate = new Date().getDate(); // const todayElement = screen.getByText(todayDate.toString()); @@ -196,20 +267,148 @@ describe('Calendar', () => { }); it('Today button should show today cell', () => { render( - - - - - + + + + + + + , + , ); //Changing the month - const prevButton = screen.getByText('<'); + const prevButton = screen.getByTestId('prevmonthordate'); fireEvent.click(prevButton); // Clicking today button - const todayButton = screen.getByText('Today'); + const todayButton = screen.getByTestId('today'); fireEvent.click(todayButton); // const todayCell = screen.getByText(new Date().getDate().toString()); // expect(todayCell).toHaveClass(styles.day__today); }); + it('Should handle window resize in day view', async () => { + const multipleEventData = [ + { + _id: '1', + title: 'Event 1', + description: 'This is event 1', + startDate: new Date().toISOString().split('T')[0], + endDate: new Date().toISOString().split('T')[0], + location: 'Los Angeles', + startTime: null, + endTime: null, + allDay: true, + recurring: false, + recurrenceRule: null, + isRecurringEventException: false, + isPublic: true, + isRegisterable: true, + }, + { + _id: '2', + title: 'Event 2', + description: 'This is event 2', + startDate: new Date().toISOString().split('T')[0], + endDate: new Date().toISOString().split('T')[0], + location: 'Los Angeles', + startTime: null, + endTime: null, + allDay: true, + recurring: false, + recurrenceRule: null, + isRecurringEventException: false, + isPublic: true, + isRegisterable: true, + }, + { + _id: '3', + title: 'Event 3', + description: 'This is event 3', + startDate: new Date().toISOString().split('T')[0], + endDate: new Date().toISOString().split('T')[0], + location: 'Los Angeles', + startTime: '14:00', + endTime: '16:00', + allDay: false, + recurring: false, + recurrenceRule: null, + isRecurringEventException: false, + isPublic: true, + isRegisterable: true, + }, + { + _id: '4', + title: 'Event 4', + description: 'This is event 4', + startDate: new Date().toISOString().split('T')[0], + endDate: new Date().toISOString().split('T')[0], + location: 'Los Angeles', + startTime: '14:00', + endTime: '16:00', + allDay: false, + recurring: false, + recurrenceRule: null, + isRecurringEventException: false, + isPublic: true, + isRegisterable: true, + }, + { + _id: '5', + title: 'Event 5', + description: 'This is event 5', + startDate: new Date().toISOString().split('T')[0], + endDate: new Date().toISOString().split('T')[0], + location: 'Los Angeles', + startTime: '17:00', + endTime: '19:00', + allDay: false, + recurring: false, + recurrenceRule: null, + isRecurringEventException: false, + isPublic: true, + isRegisterable: true, + }, + ]; + render( + + + + + + + , + , + ); + await act(async () => { + window.innerWidth = 500; + window.dispatchEvent(new Event('resize')); + }); + }); + test('Handles window resize', () => { + render( + + + + + + + , + , + ); + + act(() => { + window.dispatchEvent(new Event('resize')); + }); + }); + it('renders year view', async () => { + render(); + + await wait(); + months.forEach((month) => { + const elements = screen.getAllByText(month); + elements.forEach((element) => { + expect(element).toBeInTheDocument(); + }); + }); + }); }); diff --git a/src/components/EventCalendar/EventCalendar.tsx b/src/components/EventCalendar/EventCalendar.tsx index 4cb027647d..c06f3c5fea 100644 --- a/src/components/EventCalendar/EventCalendar.tsx +++ b/src/components/EventCalendar/EventCalendar.tsx @@ -3,34 +3,48 @@ import dayjs from 'dayjs'; import Button from 'react-bootstrap/Button'; import React, { useState, useEffect } from 'react'; import styles from './EventCalendar.module.css'; +import { ChevronLeft, ChevronRight } from '@mui/icons-material'; +import CurrentHourIndicator from 'components/CurrentHourIndicator/CurrentHourIndicator'; +import { ViewType } from 'screens/OrganizationEvents/OrganizationEvents'; +import HolidayCard from '../HolidayCards/HolidayCard'; +import { holidays, hours, months, weekdays } from './constants'; +import type { InterfaceRecurrenceRule } from 'utils/recurrenceUtils'; +import YearlyEventCalender from './YearlyEventCalender'; -interface InterfaceEvent { +interface InterfaceEventListCardProps { + userRole?: string; + key?: string; _id: string; + location: string; title: string; description: string; startDate: string; endDate: string; - location: string; - startTime: string; - endTime: string; + startTime: string | null; + endTime: string | null; allDay: boolean; recurring: boolean; - registrants?: InterfaceIEventAttendees[]; + recurrenceRule: InterfaceRecurrenceRule | null; + isRecurringEventException: boolean; isPublic: boolean; isRegisterable: boolean; + attendees?: { + _id: string; + }[]; + creator?: { + firstName: string; + lastName: string; + _id: string; + }; } interface InterfaceCalendarProps { - eventData: InterfaceEvent[]; + eventData: InterfaceEventListCardProps[]; + refetchEvents?: () => void; orgData?: InterfaceIOrgList; userRole?: string; userId?: string; -} - -enum Status { - ACTIVE = 'ACTIVE', - BLOCKED = 'BLOCKED', - DELETED = 'DELETED', + viewType?: ViewType; } enum Role { @@ -38,51 +52,44 @@ enum Role { SUPERADMIN = 'SUPERADMIN', ADMIN = 'ADMIN', } -interface InterfaceIEventAttendees { - userId: string; - user?: string; - status?: Status; - createdAt?: Date; -} interface InterfaceIOrgList { admins: { _id: string }[]; } const Calendar: React.FC = ({ eventData, + refetchEvents, orgData, userRole, userId, + viewType, }) => { const [selectedDate] = useState(null); - const weekdays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; - const months = [ - 'January', - 'February', - 'March', - 'April', - 'May', - 'June', - 'July', - 'August', - 'September', - 'October', - 'November', - 'December', - ]; - const today = new Date(); + const [currentDate, setCurrentDate] = useState(today.getDate()); const [currentMonth, setCurrentMonth] = useState(today.getMonth()); const [currentYear, setCurrentYear] = useState(today.getFullYear()); - const [events, setEvents] = useState(null); + const [events, setEvents] = useState( + null, + ); + const [expanded, setExpanded] = useState(-1); + const [windowWidth, setWindowWidth] = useState(window.screen.width); + + useEffect(() => { + function handleResize(): void { + setWindowWidth(window.screen.width); + } + window.addEventListener('resize', handleResize); + return () => window.removeEventListener('resize', handleResize); + }, []); const filterData = ( - eventData: InterfaceEvent[], + eventData: InterfaceEventListCardProps[], orgData?: InterfaceIOrgList, userRole?: string, - userId?: string - ): InterfaceEvent[] => { - const data: InterfaceEvent[] = []; + userId?: string, + ): InterfaceEventListCardProps[] => { + const data: InterfaceEventListCardProps[] = []; if (userRole === Role.SUPERADMIN) return eventData; // Hard to test all the cases /* istanbul ignore next */ @@ -91,7 +98,7 @@ const Calendar: React.FC = ({ if (event.isPublic) data.push(event); if (!event.isPublic) { const filteredOrg: boolean | undefined = orgData?.admins?.some( - (data) => data._id === userId + (data) => data._id === userId, ); if (filteredOrg) { @@ -102,8 +109,8 @@ const Calendar: React.FC = ({ } else { eventData?.forEach((event) => { if (event.isPublic) data.push(event); - const userAttending = event.registrants?.some( - (data) => data.userId === userId + const userAttending = event.attendees?.some( + (data) => data._id === userId, ); if (userAttending) { data.push(event); @@ -119,6 +126,7 @@ const Calendar: React.FC = ({ }, [eventData, orgData, userRole, userId]); const handlePrevMonth = (): void => { + /*istanbul ignore next*/ if (currentMonth === 0) { setCurrentMonth(11); setCurrentYear(currentYear - 1); @@ -128,6 +136,7 @@ const Calendar: React.FC = ({ }; const handleNextMonth = (): void => { + /*istanbul ignore next*/ if (currentMonth === 11) { setCurrentMonth(0); setCurrentYear(currentYear + 1); @@ -135,22 +144,290 @@ const Calendar: React.FC = ({ setCurrentMonth(currentMonth + 1); } }; + + const handlePrevDate = (): void => { + /*istanbul ignore next*/ + if (currentDate > 1) { + setCurrentDate(currentDate - 1); + } else { + if (currentMonth > 0) { + const lastDayOfPrevMonth = new Date( + currentYear, + currentMonth, + 0, + ).getDate(); + setCurrentDate(lastDayOfPrevMonth); + setCurrentMonth(currentMonth - 1); + } else { + setCurrentDate(31); + setCurrentMonth(11); + setCurrentYear(currentYear - 1); + } + } + }; + /*istanbul ignore next*/ + const handleNextDate = (): void => { + /*istanbul ignore next*/ + const lastDayOfCurrentMonth = new Date( + currentYear, + currentMonth - 1, + 0, + ).getDate(); + /*istanbul ignore next*/ + if (currentDate < lastDayOfCurrentMonth) { + setCurrentDate(currentDate + 1); + } else { + if (currentMonth < 12) { + setCurrentDate(1); + setCurrentMonth(currentMonth + 1); + } else { + setCurrentDate(1); + setCurrentMonth(1); + setCurrentYear(currentYear + 1); + } + } + }; + const handleTodayButton = (): void => { + /*istanbul ignore next*/ setCurrentYear(today.getFullYear()); setCurrentMonth(today.getMonth()); + setCurrentDate(today.getDate()); }; + + const timezoneString = `UTC${ + new Date().getTimezoneOffset() > 0 ? '-' : '+' + }${String(Math.floor(Math.abs(new Date().getTimezoneOffset()) / 60)).padStart( + 2, + '0', + )}:${String(Math.abs(new Date().getTimezoneOffset()) % 60).padStart(2, '0')}`; + + /*istanbul ignore next*/ + const renderHours = (): JSX.Element => { + const toggleExpand = (index: number): void => { + if (expanded === index) { + setExpanded(-1); + } else { + setExpanded(index); + } + }; + + /*istanbul ignore next*/ + const allDayEventsList: JSX.Element[] = + events + ?.filter((datas) => { + /*istanbul ignore next*/ + const currDate = new Date(currentYear, currentMonth, currentDate); + if ( + datas.startTime == undefined && + datas.startDate == dayjs(currDate).format('YYYY-MM-DD') + ) { + return datas; + } + }) + .map((datas: InterfaceEventListCardProps) => { + const attendees: { _id: string }[] = []; + datas.attendees?.forEach((attendee: { _id: string }) => { + const r = { + _id: attendee._id, + }; + + attendees.push(r); + }); + + return ( + + ); + }) || []; + + return ( + <> +
    +
    +

    {timezoneString}

    +
    +
    +
    0 + ? styles.event_list_parent_current + : styles.event_list_parent + } + > +
    +
    + {expanded === -100 + ? allDayEventsList + : allDayEventsList?.slice(0, 1)} +
    + {(allDayEventsList?.length > 2 || + (windowWidth <= 700 && allDayEventsList?.length > 0)) && ( + + )} +
    +
    +
    + {hours.map((hour, index) => { + const timeEventsList: JSX.Element[] = + events + ?.filter((datas) => { + const currDate = new Date( + currentYear, + currentMonth, + currentDate, + ); + + if ( + datas.startTime?.slice(0, 2) == (index % 24).toString() && + datas.startDate == dayjs(currDate).format('YYYY-MM-DD') + ) { + return datas; + } + }) + .map((datas: InterfaceEventListCardProps) => { + const attendees: { _id: string }[] = []; + datas.attendees?.forEach((attendee: { _id: string }) => { + const r = { + _id: attendee._id, + }; + + attendees.push(r); + }); + + return ( + + ); + }) || []; + /*istanbul ignore next*/ + return ( +
    +
    +

    {`${hour}`}

    +
    +
    +
    0 + ? styles.event_list_parent_current + : styles.event_list_parent + } + > + {index % 24 == new Date().getHours() && + new Date().getDate() == currentDate && ( + + )} +
    +
    + {/*istanbul ignore next*/} + {expanded === index + ? timeEventsList + : timeEventsList?.slice(0, 1)} +
    + {(timeEventsList?.length > 1 || + (windowWidth <= 700 && timeEventsList?.length > 0)) && ( + + )} +
    +
    +
    + ); + })} + + ); + }; + const renderDays = (): JSX.Element[] => { const monthStart = new Date(currentYear, currentMonth, 1); const monthEnd = new Date(currentYear, currentMonth + 1, 0); const startDate = new Date( monthStart.getFullYear(), monthStart.getMonth(), - monthStart.getDate() - monthStart.getDay() + monthStart.getDate() - monthStart.getDay(), ); const endDate = new Date( monthEnd.getFullYear(), monthEnd.getMonth(), - monthEnd.getDate() + (6 - monthEnd.getDay()) + monthEnd.getDate() + (6 - monthEnd.getDay()), ); const days = []; let currentDate = startDate; @@ -159,11 +436,13 @@ const Calendar: React.FC = ({ currentDate = new Date( currentDate.getFullYear(), currentDate.getMonth(), - currentDate.getDate() + 1 + currentDate.getDate() + 1, ); } + return days.map((date, index) => { const className = [ + date.getDay() === 0 || date.getDay() === 6 ? styles.day_weekends : '', date.toLocaleDateString() === today.toLocaleDateString() //Styling for today day cell ? styles.day__today : '', @@ -171,35 +450,113 @@ const Calendar: React.FC = ({ selectedDate?.getTime() === date.getTime() ? styles.day__selected : '', styles.day, ].join(' '); + const toggleExpand = (index: number): void => { + /*istanbul ignore next*/ + if (expanded === index) { + setExpanded(-1); + } else { + setExpanded(index); + } + }; + /*istanbul ignore next*/ + const allEventsList: JSX.Element[] = + events + ?.filter((datas) => { + if (datas.startDate == dayjs(date).format('YYYY-MM-DD')) + return datas; + }) + .map((datas: InterfaceEventListCardProps) => { + const attendees: { _id: string }[] = []; + datas.attendees?.forEach((attendee: { _id: string }) => { + const r = { + _id: attendee._id, + }; + + attendees.push(r); + }); + + return ( + + ); + }) || []; + + const holidayList: JSX.Element[] = holidays + .filter((holiday) => { + if (holiday.date == dayjs(date).format('MM-DD')) return holiday; + }) + .map((holiday) => { + return ; + }); return ( -
    +
    0 && styles.day__events) + } + data-testid="day" + > {date.getDate()} -
    - {events - ?.filter((datas) => { - if (datas.startDate == dayjs(date).format('YYYY-MM-DD')) - return datas; - }) - .map((datas: InterfaceEvent) => { - return ( - - ); - })} -
    + {date.getMonth() !== currentMonth ? null : ( +
    +
    +
    {holidayList}
    + { + /*istanbul ignore next*/ + expanded === index + ? allEventsList + : holidayList?.length > 0 + ? /*istanbul ignore next*/ + allEventsList?.slice(0, 1) + : allEventsList?.slice(0, 2) + } +
    + {(allEventsList?.length > 2 || + (windowWidth <= 700 && allEventsList?.length > 0)) && ( + /*istanbul ignore next*/ + + )} +
    + )}
    ); }); @@ -207,34 +564,77 @@ const Calendar: React.FC = ({ return (
    -
    - -
    - {months[currentMonth]} {currentYear} -
    - -
    - -
    -
    -
    - {weekdays.map((weekday, index) => ( -
    - {weekday} +
    + {viewType == ViewType.DAY ? `${currentDate}` : ``} {currentYear}{' '} +
    {months[currentMonth]}
    - ))} + +
    + +
    +
    + )} +
    + {viewType == ViewType.MONTH ? ( +
    +
    + {weekdays.map((weekday, index) => ( +
    + {weekday} +
    + ))} +
    +
    {renderDays()}
    +
    + ) : ( + // +
    + {viewType == ViewType.YEAR ? ( + + ) : ( +
    {renderHours()}
    + )} +
    + )} +
    +
    + {viewType == ViewType.YEAR ? ( + + ) : ( +
    {renderHours()}
    + )}
    -
    {renderDays()}
    ); }; diff --git a/src/components/EventCalendar/EventHeader.test.tsx b/src/components/EventCalendar/EventHeader.test.tsx new file mode 100644 index 0000000000..215182af9c --- /dev/null +++ b/src/components/EventCalendar/EventHeader.test.tsx @@ -0,0 +1,100 @@ +import React from 'react'; +import { render, fireEvent } from '@testing-library/react'; +import EventHeader from './EventHeader'; +import { ViewType } from '../../screens/OrganizationEvents/OrganizationEvents'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; +import { act } from 'react-dom/test-utils'; // Import act for async testing + +describe('EventHeader Component', () => { + const viewType = ViewType.MONTH; + const handleChangeView = jest.fn(); + const showInviteModal = jest.fn(); + + it('renders correctly', () => { + const { getByTestId } = render( + + + , + ); + + expect(getByTestId('searchEvent')).toBeInTheDocument(); + expect(getByTestId('createEventModalBtn')).toBeInTheDocument(); + }); + + it('calls handleChangeView with selected view type', async () => { + // Add async keyword + const { getByTestId } = render( + + + , + ); + + fireEvent.click(getByTestId('selectViewType')); + + await act(async () => { + fireEvent.click(getByTestId('selectDay')); + }); + + // Expect handleChangeView to be called with the new view type + expect(handleChangeView).toHaveBeenCalledTimes(1); + }); + it('calls handleChangeView with selected event type', async () => { + const { getByTestId } = render( + + + , + ); + + fireEvent.click(getByTestId('eventType')); + + await act(async () => { + fireEvent.click(getByTestId('events')); + }); + + expect(handleChangeView).toHaveBeenCalledTimes(1); + }); + + it('calls showInviteModal when create event button is clicked', () => { + const { getByTestId } = render( + + + , + ); + + fireEvent.click(getByTestId('createEventModalBtn')); + expect(showInviteModal).toHaveBeenCalled(); + }); + it('updates the input value when changed', () => { + const { getByTestId } = render( + + + , + ); + + const input = getByTestId('searchEvent') as HTMLInputElement; + fireEvent.change(input, { target: { value: 'test event' } }); + + expect(input.value).toBe('test event'); + }); +}); diff --git a/src/components/EventCalendar/EventHeader.tsx b/src/components/EventCalendar/EventHeader.tsx new file mode 100644 index 0000000000..a4bc59596c --- /dev/null +++ b/src/components/EventCalendar/EventHeader.tsx @@ -0,0 +1,110 @@ +import React, { useState } from 'react'; +import { Button, Dropdown, Form } from 'react-bootstrap'; +import { Search } from '@mui/icons-material'; +import styles from './EventCalendar.module.css'; +import { ViewType } from '../../screens/OrganizationEvents/OrganizationEvents'; +import { useTranslation } from 'react-i18next'; + +interface InterfaceEventHeaderProps { + viewType: ViewType; + handleChangeView: (item: string | null) => void; + showInviteModal: () => void; +} + +function eventHeader({ + viewType, + handleChangeView, + showInviteModal, +}: InterfaceEventHeaderProps): JSX.Element { + const [eventName, setEventName] = useState(''); + const { t } = useTranslation('translation', { + keyPrefix: 'organizationEvents', + }); + + return ( +
    +
    +
    + setEventName(e.target.value)} + /> + +
    +
    +
    +
    + + + {viewType} + + + + {ViewType.MONTH} + + + {ViewType.DAY} + + + {ViewType.YEAR} + + + +
    +
    + + + {t('eventType')} + + + + Events + + + Workshops + + + +
    + +
    +
    +
    + ); +} + +export default eventHeader; diff --git a/src/components/EventCalendar/YearlyEventCalender.module.css b/src/components/EventCalendar/YearlyEventCalender.module.css new file mode 100644 index 0000000000..723cb20e22 --- /dev/null +++ b/src/components/EventCalendar/YearlyEventCalender.module.css @@ -0,0 +1,354 @@ +.calendar { + font-family: sans-serif; + font-size: 1.2rem; + margin-bottom: 20px; +} +.calendar__header { + display: flex; + margin-bottom: 2rem; + align-items: center; + margin: 0px 10px 0px 10px; +} +.input { + flex: 1; + position: relative; +} +.calendar__header_month { + margin: 0.5rem; + color: #707070; + font-weight: bold; +} +.space { + flex: 1; + display: flex; + align-items: center; + justify-content: space-around; +} +.button { + color: #707070; + background-color: rgba(0, 0, 0, 0); + font-weight: bold; + border: 0px; +} +.calendar__weekdays { + display: grid; + grid-template-columns: repeat(7, 1fr); + background-color: #707070; + height: 60px; +} +.calendar__scroll { + height: 80vh; + padding: 10px; +} +.weekday { + display: flex; + justify-content: center; + align-items: center; + color: #fff; + background-color: #31bb6b; + font-weight: 600; +} +.calendar__days { + display: grid; + grid-template-columns: repeat(7, minmax(0, 1fr)); + grid-template-rows: repeat(6, 1fr); +} +.calendar_hour_text_container { + display: flex; + flex-direction: row; + align-items: flex-end; + border-right: 1px solid #8d8d8d55; + width: 40px; +} +.calendar_hour_text { + top: -10px; + left: -5px; + position: relative; + color: #707070; + font-size: 12px; +} +.calendar_timezone_text { + top: -10px; + left: -11px; + position: relative; + color: #707070; + font-size: 9px; +} +.calendar_hour_block { + display: flex; + flex-direction: row; + border-bottom: 1px solid #8d8d8d55; + position: relative; + height: 50px; + border-bottom-right-radius: 5px; +} +.event_list_parent { + position: relative; + width: 100%; +} +.event_list_parent_current { + background-color: #def6e1; + position: relative; + width: 100%; +} +.dummyWidth { + width: 1px; +} +.day { + background-color: #ffffff; + padding-left: 0.3rem; + padding-right: 0.3rem; + background-color: white; + border: 1px solid #8d8d8d55; + color: black; + font-weight: 600; + height: 8rem; + position: relative; +} +.day__outside { + /* background-color: #ededee !important; */ + color: #89898996 !important; +} +.day__selected { + background-color: #007bff; + color: #707070; +} +.day__today { + background-color: #def6e1; + font-weight: 700; + text-decoration: underline; + color: #31bb6b; +} +.day__events { + background-color: #def6e1; +} +/* yearly calender styling */ +.yearlyCalender { + background-color: #ffffff; + box-sizing: border-box; +} + +.circularButton { + width: 25px; + height: 25px; + border-radius: 50%; + background-color: rgba(255, 255, 255, 0); + border: none; + cursor: pointer; + margin-left: 0.75rem; +} +.circularButton:hover { + background-color: rgba(82, 172, 255, 0.5); +} +.closebtn { + padding: 10px; +} + +.yearlyCalendarHeader { + display: flex; + flex-direction: row; +} + +.yearlyCalendarHeader > div { + font-weight: 600; + font-size: 2rem; + padding: 0 10px; + color: #4b4b4b; +} +.noEventAvailable { + background-color: rgba(255, 255, 255, 0); +} + +.card { + /* box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2); */ + padding: 16px; + text-align: center; + /* background-color: #f1f1f1; */ + height: 21rem; +} +.cardHeader { + text-align: left; +} + +.row { + margin: 1px -5px; +} + +/* Clear floats after the columns */ +.row:after { + content: ''; + display: table; + clear: both; +} + +.weekday__yearly { + display: flex; + justify-content: center; + align-items: center; + /* color: #fff; */ + background-color: #ffffff; + font-weight: 600; +} +.day__yearly { + background-color: #ffffff; + padding-left: 0.3rem; + padding-right: 0.3rem; + background-color: white; + /* border: 1px solid #8d8d8d55; */ + color: #4b4b4b; + font-weight: 600; + height: 2rem; + position: relative; +} +* { + box-sizing: border-box; +} + +/* Float four columns side by side */ +.column { + float: left; + width: 25%; + padding: 10px; +} + +/* Remove extra left and right margins, due to padding */ +.row { + margin: 0 -5px; +} + +/* Clear floats after the columns */ +.row:after { + content: ''; + display: table; + clear: both; +} +/* yearly calender styling ends */ +.btn__today { + transition: ease-in all 200ms; + font-family: Arial; + color: #ffffff; + font-size: 18px; + padding: 10px 20px 10px 20px; + text-decoration: none; + margin-left: 20px; + border: none; +} +.btnsContainer { + display: flex; + margin: 2.5rem 0 2.5rem 0; +} + +.btnsContainer .btnsBlock { + display: flex; +} + +.btnsContainer .btnsBlock button { + margin-left: 1rem; + display: flex; + justify-content: center; + align-items: center; +} + +.dropdown { + border-color: #31bb6b; + background-color: white; + color: #31bb6b; + box-shadow: 0px 2px 1px rgba(49, 187, 107, 0.5); /* Added blur effect */ +} + +.btnsContainer .input { + flex: 1; + position: relative; +} + +.btnsContainer input { + outline: 1px solid var(--bs-gray-400); +} + +.btnsContainer .input button { + width: 52px; +} +.searchBtn { + margin-bottom: 10px; +} + +.inputField { + margin-top: 10px; + margin-bottom: 10px; + background-color: white; + box-shadow: 0 1px 1px #31bb6b; +} +.inputField > button { + padding-top: 10px; + padding-bottom: 10px; +} +.btn__more { + border: 0px; + font-size: 14px; + background-color: initial; + font-weight: 600; + transition: all 200ms; + position: relative; + display: block; + margin: -9px; + margin-top: -28px; +} +.btn__more:hover { + color: #3ce080; +} + +.expand_event_list { + display: block; +} +.list_container { + padding: 5px; + width: fit-content; + display: flex; + flex-direction: row; +} +.event_list_hour { + display: flex; + flex-direction: row; +} +.expand_list_container { + width: 200px; + max-height: 250px; + z-index: 10; + position: absolute; + left: auto; + right: auto; + overflow: auto; + padding: 10px 4px 0px 4px; + background-color: rgb(241, 241, 241); + border: 1px solid rgb(201, 201, 201); + border-radius: 5px; + margin: 5px; +} +.flex_grow { + flex-grow: 1; +} + +@media only screen and (max-width: 700px) { + .event_list { + display: none; + } + .expand_list_container { + width: 150px; + padding: 4px 4px 0px 4px; + } + .day { + height: 5rem; + } +} + +@media only screen and (max-width: 500px) { + .btn__more { + font-size: 12px; + } + + .column { + float: left; + width: 100%; + padding: 10px; + } +} diff --git a/src/components/EventCalendar/YearlyEventCalender.tsx b/src/components/EventCalendar/YearlyEventCalender.tsx new file mode 100644 index 0000000000..2bf8a6eb9d --- /dev/null +++ b/src/components/EventCalendar/YearlyEventCalender.tsx @@ -0,0 +1,360 @@ +import EventListCard from 'components/EventListCard/EventListCard'; +import dayjs from 'dayjs'; +import Button from 'react-bootstrap/Button'; +import React, { useState, useEffect } from 'react'; +import styles from './YearlyEventCalender.module.css'; +import { ViewType } from 'screens/OrganizationEvents/OrganizationEvents'; +import { ChevronLeft, ChevronRight } from '@mui/icons-material'; +import type { InterfaceRecurrenceRule } from 'utils/recurrenceUtils'; + +interface InterfaceEventListCardProps { + userRole?: string; + key?: string; + _id: string; + location: string; + title: string; + description: string; + startDate: string; + endDate: string; + startTime: string | null; + endTime: string | null; + allDay: boolean; + recurring: boolean; + recurrenceRule: InterfaceRecurrenceRule | null; + isRecurringEventException: boolean; + isPublic: boolean; + isRegisterable: boolean; + attendees?: { + _id: string; + }[]; + creator?: { + firstName: string; + lastName: string; + _id: string; + }; +} + +interface InterfaceCalendarProps { + eventData: InterfaceEventListCardProps[]; + refetchEvents?: () => void; + orgData?: InterfaceIOrgList; + userRole?: string; + userId?: string; + viewType?: ViewType; +} + +enum Status { + ACTIVE = 'ACTIVE', + BLOCKED = 'BLOCKED', + DELETED = 'DELETED', +} + +enum Role { + USER = 'USER', + SUPERADMIN = 'SUPERADMIN', + ADMIN = 'ADMIN', +} + +interface InterfaceIEventAttendees { + userId: string; + user?: string; + status?: Status; + createdAt?: Date; +} + +interface InterfaceIOrgList { + admins: { _id: string }[]; +} +const Calendar: React.FC = ({ + eventData, + refetchEvents, + orgData, + userRole, + userId, +}) => { + const [selectedDate] = useState(null); + const weekdaysShorthand = ['M', 'T', 'W', 'T', 'F', 'S', 'S']; + const months = [ + 'January', + 'February', + 'March', + 'April', + 'May', + 'June', + 'July', + 'August', + 'September', + 'October', + 'November', + 'December', + ]; + const today = new Date(); + const [currentYear, setCurrentYear] = useState(today.getFullYear()); + const [events, setEvents] = useState( + null, + ); + const [expandedY, setExpandedY] = useState(null); + + const filterData = ( + eventData: InterfaceEventListCardProps[], + orgData?: InterfaceIOrgList, + userRole?: string, + userId?: string, + ): InterfaceEventListCardProps[] => { + const data: InterfaceEventListCardProps[] = []; + if (userRole === Role.SUPERADMIN) return eventData; + // Hard to test all the cases + /* istanbul ignore next */ + if (userRole === Role.ADMIN) { + eventData?.forEach((event) => { + if (event.isPublic) data.push(event); + if (!event.isPublic) { + const filteredOrg: boolean | undefined = orgData?.admins?.some( + (data) => data._id === userId, + ); + + if (filteredOrg) { + data.push(event); + } + } + }); + } else { + eventData?.forEach((event) => { + if (event.isPublic) data.push(event); + const userAttending = event.attendees?.some( + (data) => data._id === userId, + ); + if (userAttending) { + data.push(event); + } + }); + } + return data; + }; + + useEffect(() => { + const data = filterData(eventData, orgData, userRole, userId); + setEvents(data); + }, [eventData, orgData, userRole, userId]); + + const handlePrevYear = (): void => { + /*istanbul ignore next*/ + setCurrentYear(currentYear - 1); + }; + + const handleNextYear = (): void => { + /*istanbul ignore next*/ + setCurrentYear(currentYear + 1); + }; + + const renderMonthDays = (): JSX.Element[] => { + const renderedMonths: JSX.Element[] = []; + + for (let monthInx = 0; monthInx < 12; monthInx++) { + const monthStart = new Date(currentYear, monthInx, 1); + const monthEnd = new Date(currentYear, monthInx + 1, 0); + + const startDate = new Date(monthStart); + const dayOfWeek = startDate.getDay(); + const diff = startDate.getDate() - dayOfWeek + (dayOfWeek === 0 ? -6 : 1); + startDate.setDate(diff); + + const endDate = new Date(monthEnd); + const endDayOfWeek = endDate.getDay(); + const diffEnd = + endDate.getDate() + (7 - endDayOfWeek) - (endDayOfWeek === 0 ? 7 : 0); + endDate.setDate(diffEnd); + + const days = []; + let currentDate = startDate; + while (currentDate <= endDate) { + days.push(currentDate); + currentDate = new Date( + currentDate.getFullYear(), + currentDate.getMonth(), + currentDate.getDate() + 1, + ); + } + + const renderedDays = days.map((date, dayIndex) => { + const className = [ + date.toLocaleDateString() === today.toLocaleDateString() + ? styles.day__today + : '', + date.getMonth() !== monthInx ? styles.day__outside : '', + selectedDate?.getTime() === date.getTime() + ? styles.day__selected + : '', + styles.day__yearly, + ].join(' '); + + const eventsForCurrentDate = events?.filter((event) => { + return dayjs(event.startDate).isSame(date, 'day'); + }); + + /*istanbul ignore next*/ + const renderedEvents = + eventsForCurrentDate?.map((datas: InterfaceEventListCardProps) => { + const attendees: { _id: string }[] = []; + datas.attendees?.forEach((attendee: { _id: string }) => { + const r = { + _id: attendee._id, + }; + + attendees.push(r); + }); + + return ( + + ); + }) || []; + + /*istanbul ignore next*/ + const toggleExpand = (index: string): void => { + if (expandedY === index) { + setExpandedY(null); + } else { + setExpandedY(index); + } + }; + + /*istanbul ignore next*/ + return ( +
    + {date.getDate()} +
    +
    + {expandedY === `${monthInx}-${dayIndex}` && renderedEvents} +
    + {renderedEvents && renderedEvents?.length > 0 && ( + + )} + {renderedEvents && renderedEvents?.length == 0 && ( + + )} +
    +
    + ); + }); + + renderedMonths.push( +
    +
    +
    {months[monthInx]}
    +
    + {weekdaysShorthand.map((weekday, index) => ( +
    + {weekday} +
    + ))} +
    +
    {renderedDays}
    +
    +
    , + ); + } + + return renderedMonths; + }; + + const renderYearlyCalendar = (): JSX.Element => { + return ( +
    +
    + +
    {currentYear}
    + +
    + +
    +
    {renderMonthDays()}
    +
    +
    + ); + }; + + return ( +
    +
    +
    {renderYearlyCalendar()}
    +
    +
    + ); +}; + +export default Calendar; diff --git a/src/components/EventCalendar/constants.js b/src/components/EventCalendar/constants.js new file mode 100644 index 0000000000..f2b770426c --- /dev/null +++ b/src/components/EventCalendar/constants.js @@ -0,0 +1,56 @@ +export const holidays = [ + { name: 'May Day / Labour Day', date: '05-01', month: 'May' }, // May 1st + { name: "Mother's Day", date: '05-08', month: 'May' }, // Second Sunday in May + { name: "Father's Day", date: '06-19', month: 'June' }, // Third Sunday in June + { name: 'Independence Day (US)', date: '07-04', month: 'July' }, // July 4th + { name: 'Oktoberfest', date: '09-21', month: 'September' }, // September 21st (starts in September, ends in October) + { name: 'Halloween', date: '10-31', month: 'October' }, // October 31st + { name: 'Diwali', date: '11-04', month: 'November' }, + { + name: 'Remembrance Day / Veterans Day', + date: '11-11', + month: 'November', + }, + { name: 'Christmas Day', date: '12-25', month: 'December' }, // December 25th +]; +export const weekdays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; +export const months = [ + 'January', + 'February', + 'March', + 'April', + 'May', + 'June', + 'July', + 'August', + 'September', + 'October', + 'November', + 'December', +]; +export const hours = [ + '12 AM', + '01 AM', + '02 AM', + '03 AM', + '04 AM', + '05 AM', + '06 AM', + '07 AM', + '08 AM', + '09 AM', + '10 AM', + '11 AM', + '12 PM', + '01 PM', + '02 PM', + '03 PM', + '04 PM', + '05 PM', + '06 PM', + '07 PM', + '08 PM', + '09 PM', + '10 PM', + '11 PM', +]; diff --git a/src/components/EventDashboardScreen/EventDashboardScreen.module.css b/src/components/EventDashboardScreen/EventDashboardScreen.module.css new file mode 100644 index 0000000000..33c642dd95 --- /dev/null +++ b/src/components/EventDashboardScreen/EventDashboardScreen.module.css @@ -0,0 +1,198 @@ +.gap { + gap: 20px; +} + +.mainContainer { + width: 50%; + flex-grow: 3; + padding: 20px; + max-height: 100%; + overflow: auto; +} + +.containerHeight { + height: calc(100vh - 66px); +} + +.colorLight { + background-color: #f1f3f6; +} + +.pageContainer { + display: flex; + flex-direction: column; + min-height: 100vh; + padding: 1rem 1.5rem 0 calc(300px + 2rem + 1.5rem); +} + +.expand { + padding-left: 4rem; + animation: moveLeft 0.5s ease-in-out; +} +.avatarStyle { + border-radius: 100%; +} +.profileContainer { + border: none; + padding: 2.1rem 0.5rem; + height: 52px; + border-radius: 8px 0px 0px 8px; + display: flex; + align-items: center; + background-color: white !important; + box-shadow: + 0 4px 4px 0 rgba(177, 177, 177, 0.2), + 0 6px 20px 0 rgba(151, 151, 151, 0.19); +} +.profileContainer:focus { + outline: none; + background-color: var(--bs-gray-100); +} +.imageContainer { + width: 56px; +} +.profileContainer .profileText { + flex: 1; + text-align: start; + overflow: hidden; + margin-right: 4px; +} +.angleDown { + margin-left: 4px; +} +.profileContainer .profileText .primaryText { + font-size: 1rem; + font-weight: 600; + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 2; /* number of lines to show */ + -webkit-box-orient: vertical; + word-wrap: break-word; + white-space: normal; +} +.profileContainer .profileText .secondaryText { + font-size: 0.8rem; + font-weight: 400; + color: var(--bs-secondary); + display: block; + text-transform: capitalize; +} + +.contract { + padding-left: calc(300px + 2rem + 1.5rem); + animation: moveRight 0.5s ease-in-out; +} + +.collapseSidebarButton { + position: fixed; + height: 40px; + bottom: 0; + z-index: 9999; + width: calc(300px + 2rem); + background-color: rgba(245, 245, 245, 0.7); + color: black; + border: none; + border-radius: 0px; +} + +.collapseSidebarButton:hover, +.opendrawer:hover { + opacity: 1; + color: black !important; +} +.opendrawer { + position: fixed; + display: flex; + align-items: center; + justify-content: center; + top: 0; + left: 0; + width: 40px; + height: 100vh; + z-index: 9999; + background-color: rgba(245, 245, 245); + border: none; + border-radius: 0px; + margin-right: 20px; + color: black; +} +.profileDropdown { + background-color: transparent !important; +} +.profileDropdown .dropdown-toggle .btn .btn-normal { + display: none !important; + background-color: transparent !important; +} +.dropdownToggle { + background-image: url(/public/images/svg/angleDown.svg); + background-repeat: no-repeat; + background-position: center; + background-color: azure; +} + +.dropdownToggle::after { + border-top: none !important; + border-bottom: none !important; +} + +.opendrawer:hover { + transition: background-color 0.5s ease; + background-color: var(--bs-primary); +} +.collapseSidebarButton:hover { + transition: background-color 0.5s ease; + background-color: var(--bs-primary); +} + +@media (max-width: 1120px) { + .contract { + padding-left: calc(250px + 2rem + 1.5rem); + } + .collapseSidebarButton { + width: calc(250px + 2rem); + } +} + +@media (max-height: 900px) { + .pageContainer { + padding: 1rem 1.5rem 0 calc(300px + 2rem); + } + .collapseSidebarButton { + height: 30px; + width: calc(300px + 1rem); + } +} +@media (max-height: 650px) { + .pageContainer { + padding: 1rem 1.5rem 0 calc(270px); + } + .collapseSidebarButton { + width: 250px; + height: 20px; + } + .opendrawer { + width: 30px; + } +} + +/* For tablets */ +@media (max-width: 820px) { + .pageContainer { + padding-left: 2.5rem; + } + + .opendrawer { + width: 25px; + } + + .contract, + .expand { + animation: none; + } + + .collapseSidebarButton { + width: 100%; + left: 0; + right: 0; + } +} diff --git a/src/components/EventDashboardScreen/EventDashboardScreen.test.tsx b/src/components/EventDashboardScreen/EventDashboardScreen.test.tsx new file mode 100644 index 0000000000..6b48b034a9 --- /dev/null +++ b/src/components/EventDashboardScreen/EventDashboardScreen.test.tsx @@ -0,0 +1,166 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { fireEvent, render, screen } from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import 'jest-location-mock'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import EventDashboardScreen from './EventDashboardScreen'; +import { ORGANIZATIONS_LIST } from 'GraphQl/Queries/Queries'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import useLocalStorage from 'utils/useLocalstorage'; +const { setItem } = useLocalStorage(); + +Object.defineProperty(window, 'matchMedia', { + writable: true, + value: jest.fn().mockImplementation((query) => ({ + matches: false, + media: query, + onchange: null, + addListener: jest.fn(), // Deprecated + removeListener: jest.fn(), // Deprecated + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn(), + })), +}); + +let mockID: string | undefined = '123'; +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: mockID }), +})); + +const MOCKS = [ + { + request: { + query: ORGANIZATIONS_LIST, + variables: { id: '123' }, + }, + result: { + data: { + organizations: [ + { + _id: '123', + image: null, + creator: { + firstName: 'John', + lastName: 'Doe', + email: 'JohnDoe@example.com', + }, + name: 'Test Organization', + description: 'Testing this organization', + address: { + city: 'Mountain View', + countryCode: 'US', + dependentLocality: 'Some Dependent Locality', + line1: '123 Main Street', + line2: 'Apt 456', + postalCode: '94040', + sortingCode: 'XYZ-789', + state: 'CA', + }, + userRegistrationRequired: true, + visibleInSearch: true, + members: [], + admins: [], + membershipRequests: [], + blockedUsers: [], + }, + ], + }, + }, + }, +]; +const link = new StaticMockLink(MOCKS, true); + +const resizeWindow = (width: number): void => { + window.innerWidth = width; + fireEvent(window, new Event('resize')); +}; + +const clickToggleMenuBtn = (toggleButton: HTMLElement): void => { + fireEvent.click(toggleButton); +}; + +describe('Testing LeftDrawer in OrganizationScreen', () => { + test('should be redirected to / if IsLoggedIn is false', async () => { + setItem('IsLoggedIn', false); + render( + + + + + + + + + , + ); + expect(window.location.pathname).toEqual('/'); + }); + test('should be redirected to / if ss is false', async () => { + setItem('IsLoggedIn', true); + render( + + + + + + + + + , + ); + }); + test('Testing LeftDrawer in page functionality', async () => { + setItem('IsLoggedIn', true); + setItem('AdminFor', [ + { _id: '6637904485008f171cf29924', __typename: 'Organization' }, + ]); + render( + + + + + + + + + , + ); + const toggleButton = screen.getByTestId('toggleMenuBtn') as HTMLElement; + const icon = toggleButton.querySelector('i'); + + // Resize window to a smaller width + resizeWindow(800); + clickToggleMenuBtn(toggleButton); + expect(icon).toHaveClass('fa fa-angle-double-right'); + // Resize window back to a larger width + + resizeWindow(1000); + clickToggleMenuBtn(toggleButton); + expect(icon).toHaveClass('fa fa-angle-double-left'); + + clickToggleMenuBtn(toggleButton); + expect(icon).toHaveClass('fa fa-angle-double-right'); + }); + + test('should be redirected to / if orgId is undefined', async () => { + mockID = undefined; + render( + + + + + + + + + , + ); + expect(window.location.pathname).toEqual('/'); + }); +}); diff --git a/src/components/EventDashboardScreen/EventDashboardScreen.tsx b/src/components/EventDashboardScreen/EventDashboardScreen.tsx new file mode 100644 index 0000000000..86e1d460f3 --- /dev/null +++ b/src/components/EventDashboardScreen/EventDashboardScreen.tsx @@ -0,0 +1,144 @@ +import LeftDrawerOrg from 'components/LeftDrawerOrg/LeftDrawerOrg'; +import React, { useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useDispatch, useSelector } from 'react-redux'; +import { Navigate, Outlet, useLocation, useParams } from 'react-router-dom'; +import { updateTargets } from 'state/action-creators'; +import type { RootState } from 'state/reducers'; +import type { TargetsType } from 'state/reducers/routesReducer'; +import styles from './EventDashboardScreen.module.css'; +import ProfileDropdown from 'components/ProfileDropdown/ProfileDropdown'; +import useLocalStorage from 'utils/useLocalstorage'; +const { getItem } = useLocalStorage(); + +const EventDashboardScreen = (): JSX.Element => { + const isLoggedIn = getItem('IsLoggedIn'); + const adminFor = getItem('AdminFor'); + const location = useLocation(); + const titleKey: string | undefined = map[location.pathname.split('/')[1]]; + const { t } = useTranslation('translation', { keyPrefix: titleKey }); + const [hideDrawer, setHideDrawer] = useState(null); + const { orgId } = useParams(); + if (!orgId) { + return ; + } + + if (isLoggedIn === false) return ; + if (adminFor === null) { + return ( + <> +
    +
    +
    +
    +

    {t('title')}

    +
    + +
    +
    +
    + + ); + } + + const appRoutes: { + targets: TargetsType[]; + } = useSelector((state: RootState) => state.appRoutes); + const { targets } = appRoutes; + + const dispatch = useDispatch(); + useEffect(() => { + dispatch(updateTargets(orgId)); + }, [orgId]); // Added orgId to the dependency array + + const handleResize = (): void => { + if (window.innerWidth <= 820 && !hideDrawer) { + setHideDrawer(true); + } + }; + + const toggleDrawer = (): void => { + setHideDrawer(!hideDrawer); + }; + + useEffect(() => { + handleResize(); + window.addEventListener('resize', handleResize); + return () => { + window.removeEventListener('resize', handleResize); + }; + }, [hideDrawer]); + + return ( + <> + +
    + +
    +
    +
    +
    +

    {t('title')}

    +
    + +
    + +
    + + ); +}; + +export default EventDashboardScreen; + +interface InterfaceMapType { + [key: string]: string; +} + +const map: InterfaceMapType = { + orgdash: 'dashboard', + orgpeople: 'organizationPeople', + requests: 'requests', + orgads: 'advertisement', + member: 'memberDetail', + orgevents: 'organizationEvents', + orgactionitems: 'organizationActionItems', + orgcontribution: 'orgContribution', + orgpost: 'orgPost', + orgfunds: 'funds', + orgfundcampaign: 'fundCampaign', + fundCampaignPledge: 'pledges', + orgsetting: 'orgSettings', + orgstore: 'addOnStore', + blockuser: 'blockUnblockUser', + orgvenues: 'organizationVenues', + event: 'eventManagement', +}; diff --git a/src/components/EventListCard/EventListCard.module.css b/src/components/EventListCard/EventListCard.module.css index 1648c9d16a..1e47972a42 100644 --- a/src/components/EventListCard/EventListCard.module.css +++ b/src/components/EventListCard/EventListCard.module.css @@ -1,6 +1,7 @@ .cards h2 { font-size: 15px; - color: #fff; + color: #4e4c4c; + font-weight: 500; } .cards > h3 { font-size: 17px; @@ -21,36 +22,35 @@ position: relative; overflow: hidden; transition: all 0.3s; + margin-bottom: 5px; } .dispflex { display: flex; - height: 50px; - transition: transform 0.3s ease; cursor: pointer; + justify-content: space-between; + margin: 10px 5px 5px 0px; } -.cards:hover { - transform: scale(2.5); - z-index: 5; -} -.cards:hover h2 { - font-size: 0.4vmax; - margin-bottom: 0; +.eventtitle { + margin-bottom: 0px; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; } .iconContainer { display: flex; justify-content: flex-end; } .icon { - margin: 1px; + margin: 2px; } .cards { width: 100%; - background: rgba(40, 167, 69, 1); + background: #5cacf7 !important; padding: 2px 3px; border-radius: 5px; border: 1px solid #e8e8e8; - box-shadow: 0 3px 5px #c9c9c9; + box-shadow: 0 3px 2px #e8e8e8; color: #737373; box-sizing: border-box; } @@ -78,7 +78,8 @@ .datediv { display: flex; flex-direction: row; - margin-bottom: 15px; + margin-top: 5px; + margin-bottom: 5px; } .datebox { width: 90%; @@ -91,36 +92,48 @@ padding-right: 5px; padding-left: 5px; } -.checkboxdiv > label { +.datediv > div > p { + margin-bottom: 0.5rem; +} + +.startDate { + margin-right: 0.25rem; +} +.endDate { + margin-left: 1.5rem; +} + +.checkboxdiv > div label { margin-right: 50px; } .checkboxdiv > label > input { margin-left: 10px; } -.dispflex { - display: flex; - margin-bottom: 5px; - margin-right: 5px; -} + .dispflex > input { width: 20%; border: none; box-shadow: none; margin-top: 5px; } -.checkboxdiv { + +.checkboxContainer { display: flex; + justify-content: space-between; } -.checkboxdiv > div { - width: 50%; + +.checkboxdiv { + display: flex; + flex-direction: column; } .preview { display: flex; flex-direction: row; - font-weight: 900; + font-weight: 700; font-size: 16px; - color: rgb(80, 80, 80); + color: #000000; + margin: 0; } .view { margin-left: 2%; @@ -158,13 +171,13 @@ flex-direction: column; } .titlemodal { - color: #707070; + color: #000000; font-weight: 600; - font-size: 20px; + font-size: 24px; margin-bottom: 20px; padding-bottom: 5px; - border-bottom: 3px solid #31bb6b; - width: 65%; + border-bottom: 4px solid #31bb6b; + width: 50%; } .cancel > i { margin-top: 5px; @@ -185,9 +198,26 @@ width: 90%; top: 45%; } + .checkboxContainer { + flex-direction: column; + } + + .datediv { + flex-direction: column; + } + + .datediv > div { + width: 100%; + margin-left: 0; + margin-bottom: 10px; + } + + .datediv > div p { + margin-bottom: 5px; + } } .customButton { - background-color: #31bb6b; - border: #31bb6b; + width: 90%; + margin: 0 auto; } diff --git a/src/components/EventListCard/EventListCard.test.tsx b/src/components/EventListCard/EventListCard.test.tsx index 820e563957..cf321fa4b1 100644 --- a/src/components/EventListCard/EventListCard.test.tsx +++ b/src/components/EventListCard/EventListCard.test.tsx @@ -1,61 +1,40 @@ import React from 'react'; -import { act, render, screen, fireEvent } from '@testing-library/react'; +import type { RenderResult } from '@testing-library/react'; +import { + act, + render, + screen, + fireEvent, + waitFor, +} from '@testing-library/react'; import { MockedProvider } from '@apollo/react-testing'; import userEvent from '@testing-library/user-event'; import { I18nextProvider } from 'react-i18next'; - +import type { InterfaceEventListCardProps } from './EventListCard'; import EventListCard from './EventListCard'; -import { - DELETE_EVENT_MUTATION, - UPDATE_EVENT_MUTATION, -} from 'GraphQl/Mutations/mutations'; import i18nForTest from 'utils/i18nForTest'; import { StaticMockLink } from 'utils/StaticMockLink'; -import { BrowserRouter } from 'react-router-dom'; +import { BrowserRouter, MemoryRouter, Route, Routes } from 'react-router-dom'; import { Provider } from 'react-redux'; import { store } from 'state/store'; +import { toast } from 'react-toastify'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import useLocalStorage from 'utils/useLocalstorage'; +import { props } from './EventListCardProps'; +import { ERROR_MOCKS, MOCKS } from './EventListCardMocks'; -const MOCKS = [ - { - request: { - query: DELETE_EVENT_MUTATION, - variable: { id: '123' }, - }, - result: { - data: { - removeEvent: { - _id: '1', - }, - }, - }, - }, - { - request: { - query: UPDATE_EVENT_MUTATION, - variable: { - id: '123', - title: 'Updated title', - description: 'This is a new update', - isPublic: true, - recurring: false, - isRegisterable: true, - allDay: false, - location: 'New Delhi', - startTime: '02:00', - endTime: '07:00', - }, - }, - result: { - data: { - updateEvent: { - _id: '1', - }, - }, - }, - }, -]; +const { setItem } = useLocalStorage(); const link = new StaticMockLink(MOCKS, true); +const link2 = new StaticMockLink(ERROR_MOCKS, true); + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); async function wait(ms = 100): Promise { await act(() => { @@ -65,280 +44,874 @@ async function wait(ms = 100): Promise { }); } +const translations = JSON.parse( + JSON.stringify( + i18nForTest.getDataByLanguage('en')?.translation.eventListCard, + ), +); + +const renderEventListCard = ( + props: InterfaceEventListCardProps, +): RenderResult => { + return render( + + + + + + + } + /> + } + /> + } /> + + + + + + , + ); +}; + describe('Testing Event List Card', () => { - const props = { - key: '123', - id: '1', - eventLocation: 'India', - eventName: 'Shelter for Dogs', - eventDescription: 'This is shelter for dogs event', - regDate: '19/03/2022', - regEndDate: '26/03/2022', - startTime: '02:00', - endTime: '06:00', - allDay: true, - recurring: false, + const updateData = { + title: 'Updated title', + description: 'This is a new update', isPublic: true, - isRegisterable: false, + recurring: false, + isRegisterable: true, + allDay: false, + location: 'New Delhi', + startDate: '03/18/2022', + endDate: '03/20/2022', + startTime: '09:00 AM', + endTime: '05:00 PM', }; - global.alert = jest.fn(); - test('Testing for modal', async () => { - render( - - - - - - - - - - ); + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId' }), + })); + }); - await wait(); + afterAll(() => { + localStorage.clear(); + jest.clearAllMocks(); + }); + + test('Testing for event modal', async () => { + renderEventListCard(props[1]); userEvent.click(screen.getByTestId('card')); - userEvent.click(screen.getByTestId('createEventModalCloseBtn')); + await waitFor(() => { + expect(screen.getByTestId('eventModalCloseBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('eventModalCloseBtn')); - await wait(); + await waitFor(() => { + expect( + screen.queryByTestId('eventModalCloseBtn'), + ).not.toBeInTheDocument(); + }); }); - test('Should render text elements when props value is not passed', async () => { - global.confirm = (): boolean => false; - + test('Should navigate to "/" if orgId is not defined', async () => { render( - + + + - + , ); await wait(); - expect(screen.queryByText(props.eventName)).not.toBeInTheDocument(); + await waitFor(() => { + expect(window.location.pathname).toEqual('/'); + }); }); - test('Testing for update modal', async () => { - render( - - - - - - - - - + test('Should render default text if event details are null', async () => { + renderEventListCard(props[0]); + + await waitFor(() => { + expect(screen.getByText('Dogs Care')).toBeInTheDocument(); + }); + }); + + test('should render props and text elements test for the screen', async () => { + renderEventListCard(props[1]); + + expect(screen.getByText(props[1].eventName)).toBeInTheDocument(); + + userEvent.click(screen.getByTestId('card')); + + await waitFor(() => { + expect(screen.getByTestId('updateDescription')).toBeInTheDocument(); + }); + + expect(screen.getByTestId('updateDescription')).toHaveValue( + props[1].eventDescription, + ); + expect(screen.getByTestId('updateLocation')).toHaveValue( + props[1].eventLocation, ); - await wait(); + userEvent.click(screen.getByTestId('eventModalCloseBtn')); + + await waitFor(() => { + expect( + screen.queryByTestId('eventModalCloseBtn'), + ).not.toBeInTheDocument(); + }); + }); + + test('Should render truncated event name when length is more than 100', async () => { + const longEventName = 'a'.repeat(101); + renderEventListCard({ ...props[1], eventName: longEventName }); userEvent.click(screen.getByTestId('card')); - userEvent.click(screen.getByTestId('editEventModalBtn')); - userEvent.click(screen.getByTestId('EventUpdateModalCloseBtn')); - userEvent.click(screen.getByTestId('createEventModalCloseBtn')); + await waitFor(() => { + expect(screen.getByTestId('updateTitle')).toBeInTheDocument(); + }); - await wait(); + expect(screen.getByTestId('updateTitle')).toHaveValue( + `${longEventName.substring(0, 100)}...`, + ); + + userEvent.click(screen.getByTestId('eventModalCloseBtn')); + + await waitFor(() => { + expect( + screen.queryByTestId('eventModalCloseBtn'), + ).not.toBeInTheDocument(); + }); }); - test('Testing event update functionality', async () => { - render( - - - - - + test('Should render full event name when length is less than or equal to 100', async () => { + const shortEventName = 'a'.repeat(100); + renderEventListCard({ ...props[1], eventName: shortEventName }); + + userEvent.click(screen.getByTestId('card')); + + await waitFor(() => { + expect(screen.getByTestId('updateTitle')).toBeInTheDocument(); + }); + + expect(screen.getByTestId('updateTitle')).toHaveValue(shortEventName); + + userEvent.click(screen.getByTestId('eventModalCloseBtn')); + + await waitFor(() => { + expect( + screen.queryByTestId('eventModalCloseBtn'), + ).not.toBeInTheDocument(); + }); + }); + + test('Should render truncated event description when length is more than 256', async () => { + const longEventDescription = 'a'.repeat(257); + + renderEventListCard({ + ...props[1], + eventDescription: longEventDescription, + }); + + userEvent.click(screen.getByTestId('card')); + + await waitFor(() => { + expect(screen.getByTestId('updateDescription')).toBeInTheDocument(); + }); + expect(screen.getByTestId('updateDescription')).toHaveValue( + `${longEventDescription.substring(0, 256)}...`, ); - await wait(); + userEvent.click(screen.getByTestId('eventModalCloseBtn')); + + await waitFor(() => { + expect( + screen.queryByTestId('eventModalCloseBtn'), + ).not.toBeInTheDocument(); + }); + }); + + test('Should render full event description when length is less than or equal to 256', async () => { + const shortEventDescription = 'a'.repeat(256); + + renderEventListCard({ + ...props[1], + eventDescription: shortEventDescription, + }); + userEvent.click(screen.getByTestId('card')); - userEvent.click(screen.getByTestId('editEventModalBtn')); - userEvent.type(screen.getByTestId('updateTitle'), props.eventName); - userEvent.type( - screen.getByTestId('updateDescription'), - props.eventDescription + + await waitFor(() => { + expect(screen.getByTestId('updateDescription')).toBeInTheDocument(); + }); + expect(screen.getByTestId('updateDescription')).toHaveValue( + shortEventDescription, ); - userEvent.type(screen.getByTestId('updateLocation'), props.eventLocation); + + userEvent.click(screen.getByTestId('eventModalCloseBtn')); + + await waitFor(() => { + expect( + screen.queryByTestId('eventModalCloseBtn'), + ).not.toBeInTheDocument(); + }); + }); + + test('Should navigate to event dashboard when clicked', async () => { + renderEventListCard(props[1]); + + userEvent.click(screen.getByTestId('card')); + + await waitFor(() => { + expect(screen.getByTestId('showEventDashboardBtn')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('showEventDashboardBtn')); + + await waitFor(() => { + expect(screen.queryByTestId('card')).not.toBeInTheDocument(); + }); + }); + + test('Should update a non-recurring event', async () => { + renderEventListCard(props[1]); + + userEvent.click(screen.getByTestId('card')); + + const eventTitle = screen.getByTestId('updateTitle'); + fireEvent.change(eventTitle, { target: { value: '' } }); + userEvent.type(eventTitle, updateData.title); + + const eventDescription = screen.getByTestId('updateDescription'); + fireEvent.change(eventDescription, { target: { value: '' } }); + userEvent.type(eventDescription, updateData.description); + + const eventLocation = screen.getByTestId('updateLocation'); + fireEvent.change(eventLocation, { target: { value: '' } }); + userEvent.type(eventLocation, updateData.location); + + const startDatePicker = screen.getByLabelText(translations.startDate); + fireEvent.change(startDatePicker, { + target: { value: updateData.startDate }, + }); + + const endDatePicker = screen.getByLabelText(translations.endDate); + fireEvent.change(endDatePicker, { + target: { value: updateData.endDate }, + }); + userEvent.click(screen.getByTestId('updateAllDay')); - userEvent.click(screen.getByTestId('updateRecurring')); userEvent.click(screen.getByTestId('updateIsPublic')); userEvent.click(screen.getByTestId('updateRegistrable')); + userEvent.click(screen.getByTestId('updateEventBtn')); - userEvent.click(screen.getByTestId('updatePostBtn')); + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.eventUpdated); + }); + + await waitFor(() => { + expect( + screen.queryByTestId('eventModalCloseBtn'), + ).not.toBeInTheDocument(); + }); }); - test('should render props and text elements test for the screen', async () => { - const { container } = render( - - - - - - - - ); - expect(container.textContent).not.toBe('Loading data...'); + test('Should update a non all day non-recurring event', async () => { + renderEventListCard(props[1]); - await wait(); + userEvent.click(screen.getByTestId('card')); + + const eventTitle = screen.getByTestId('updateTitle'); + fireEvent.change(eventTitle, { target: { value: '' } }); + userEvent.type(eventTitle, updateData.title); + + const eventDescription = screen.getByTestId('updateDescription'); + fireEvent.change(eventDescription, { target: { value: '' } }); + userEvent.type(eventDescription, updateData.description); + + const eventLocation = screen.getByTestId('updateLocation'); + fireEvent.change(eventLocation, { target: { value: '' } }); + userEvent.type(eventLocation, updateData.location); + + const startDatePicker = screen.getByLabelText(translations.startDate); + fireEvent.change(startDatePicker, { + target: { value: updateData.startDate }, + }); + + const endDatePicker = screen.getByLabelText(translations.endDate); + fireEvent.change(endDatePicker, { + target: { value: updateData.endDate }, + }); + + const startTimePicker = screen.getByLabelText(translations.startTime); + fireEvent.change(startTimePicker, { + target: { value: updateData.startTime }, + }); + + const endTimePicker = screen.getByLabelText(translations.endTime); + fireEvent.change(endTimePicker, { + target: { value: updateData.endTime }, + }); + + userEvent.click(screen.getByTestId('updateIsPublic')); + userEvent.click(screen.getByTestId('updateRegistrable')); + + userEvent.click(screen.getByTestId('updateEventBtn')); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.eventUpdated); + }); + + await waitFor(() => { + expect( + screen.queryByTestId('eventModalCloseBtn'), + ).not.toBeInTheDocument(); + }); }); - test('Testing if the event is not for all day', async () => { - render( - - - - - - ); + test('should update a single event to be recurring', async () => { + renderEventListCard(props[1]); - await wait(); userEvent.click(screen.getByTestId('card')); - userEvent.click(screen.getByTestId('editEventModalBtn')); - userEvent.type(screen.getByTestId('updateTitle'), props.eventName); - userEvent.type( - screen.getByTestId('updateDescription'), - props.eventDescription - ); - userEvent.type(screen.getByTestId('updateLocation'), props.eventLocation); + + const eventTitle = screen.getByTestId('updateTitle'); + fireEvent.change(eventTitle, { target: { value: '' } }); + userEvent.type(eventTitle, updateData.title); + + const eventDescription = screen.getByTestId('updateDescription'); + fireEvent.change(eventDescription, { target: { value: '' } }); + userEvent.type(eventDescription, updateData.description); + + const eventLocation = screen.getByTestId('updateLocation'); + fireEvent.change(eventLocation, { target: { value: '' } }); + userEvent.type(eventLocation, updateData.location); + + const startDatePicker = screen.getByLabelText(translations.startDate); + fireEvent.change(startDatePicker, { + target: { value: updateData.startDate }, + }); + + const endDatePicker = screen.getByLabelText(translations.endDate); + fireEvent.change(endDatePicker, { + target: { value: updateData.endDate }, + }); + userEvent.click(screen.getByTestId('updateAllDay')); + userEvent.click(screen.getByTestId('updateRecurring')); + userEvent.click(screen.getByTestId('updateIsPublic')); + userEvent.click(screen.getByTestId('updateRegistrable')); + userEvent.click(screen.getByTestId('updateEventBtn')); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.eventUpdated); + }); + + await waitFor(() => { + expect( + screen.queryByTestId('eventModalCloseBtn'), + ).not.toBeInTheDocument(); + }); + }); + + test('should show different update options for a recurring event based on different conditions', async () => { + renderEventListCard(props[5]); + + userEvent.click(screen.getByTestId('card')); + + await waitFor(() => { + expect(screen.queryByTestId('updateEventBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('updateEventBtn')); + + // shows options to update thisInstance and thisAndFollowingInstances, and allInstances + await waitFor(() => { + expect(screen.getByTestId('update-thisInstance')).toBeInTheDocument(); + expect( + screen.getByTestId('update-thisAndFollowingInstances'), + ).toBeInTheDocument(); + expect(screen.getByTestId('update-allInstances')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('eventUpdateOptionsModalCloseBtn')); + + await waitFor(() => { + expect(screen.getByLabelText(translations.startDate)).toBeInTheDocument(); + }); + + // change the event dates + let startDatePicker = screen.getByLabelText(translations.startDate); + fireEvent.change(startDatePicker, { + target: { value: updateData.startDate }, + }); + + let endDatePicker = screen.getByLabelText(translations.endDate); + fireEvent.change(endDatePicker, { + target: { value: updateData.endDate }, + }); + + userEvent.click(screen.getByTestId('updateEventBtn')); + + // shows options to update thisInstance and thisAndFollowingInstances only + await waitFor(() => { + expect(screen.getByTestId('update-thisInstance')).toBeInTheDocument(); + expect( + screen.getByTestId('update-thisAndFollowingInstances'), + ).toBeInTheDocument(); + expect( + screen.queryByTestId('update-allInstances'), + ).not.toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('eventUpdateOptionsModalCloseBtn')); + + await waitFor(() => { + expect(screen.getByLabelText(translations.startDate)).toBeInTheDocument(); + }); + + // reset the event dates to their original values + startDatePicker = screen.getByLabelText(translations.startDate); + fireEvent.change(startDatePicker, { + target: { value: '03/17/2022' }, + }); + + endDatePicker = screen.getByLabelText(translations.endDate); + fireEvent.change(endDatePicker, { + target: { value: '03/17/2022' }, + }); + + // now change the recurrence rule of the event + await waitFor(() => { + expect(screen.getByTestId('recurrenceOptions')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('recurrenceOptions')); + + await waitFor(() => { + expect(screen.getByTestId('customRecurrence')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('customRecurrence')); + + await waitFor(() => { + expect( + screen.getByTestId('customRecurrenceFrequencyDropdown'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('customRecurrenceFrequencyDropdown')); + + await waitFor(() => { + expect(screen.getByTestId('customDailyRecurrence')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('customDailyRecurrence')); + + await waitFor(() => { + expect( + screen.getByTestId('customRecurrenceSubmitBtn'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('customRecurrenceSubmitBtn')); + + await waitFor(() => { + expect(screen.getByTestId('updateEventBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('updateEventBtn')); + + // shows options to update thisAndFollowingInstances and allInstances only + await waitFor(() => { + expect( + screen.queryByTestId('update-thisInstance'), + ).not.toBeInTheDocument(); + expect( + screen.getByTestId('update-thisAndFollowingInstances'), + ).toBeInTheDocument(); + expect(screen.queryByTestId('update-allInstances')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('eventUpdateOptionsModalCloseBtn')); + + await waitFor(() => { + expect(screen.getByTestId('eventModalCloseBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('eventModalCloseBtn')); + + await waitFor(() => { + expect( + screen.queryByTestId('eventModalCloseBtn'), + ).not.toBeInTheDocument(); + }); + }); + + test('should show recurrenceRule as changed if the recurrence weekdays have changed', async () => { + renderEventListCard(props[4]); + + userEvent.click(screen.getByTestId('card')); + + await waitFor(() => { + expect(screen.getByTestId('recurrenceOptions')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('recurrenceOptions')); + + await waitFor(() => { + expect(screen.getByTestId('customRecurrence')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('customRecurrence')); + + // since the current recurrence weekDay for the current recurring event is "SATURDAY", + // let's first deselect it, and then we'll select a different day + // the recurrence rule should be marked as changed and we should see the option to update + // thisAndFollowingInstances and allInstances only + await waitFor(() => { + expect(screen.getAllByTestId('recurrenceWeekDay')[6]).toBeInTheDocument(); + }); + + // deselect saturday, which is the 7th day in recurrenceWeekDay options + userEvent.click(screen.getAllByTestId('recurrenceWeekDay')[6]); + + // select a different day, say wednesday, the 4th day in recurrenceWeekDay options + userEvent.click(screen.getAllByTestId('recurrenceWeekDay')[3]); + + userEvent.click(screen.getByTestId('customRecurrenceSubmitBtn')); + + await waitFor(() => { + expect(screen.getByTestId('updateEventBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('updateEventBtn')); + + // shows options to update thisInstance and thisAndFollowingInstances, and allInstances + await waitFor(() => { + expect( + screen.queryByTestId('update-thisInstance'), + ).not.toBeInTheDocument(); + expect( + screen.getByTestId('update-thisAndFollowingInstances'), + ).toBeInTheDocument(); + expect(screen.getByTestId('update-allInstances')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('eventUpdateOptionsModalCloseBtn')); + + await waitFor(() => { + expect(screen.getByTestId('eventModalCloseBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('eventModalCloseBtn')); + + await waitFor(() => { + expect( + screen.queryByTestId('eventModalCloseBtn'), + ).not.toBeInTheDocument(); + }); + }); + + test('should update all instances of a recurring event', async () => { + renderEventListCard(props[6]); + + userEvent.click(screen.getByTestId('card')); + + await waitFor(() => { + expect(screen.getByTestId('updateTitle')).toBeInTheDocument(); + }); + + const eventTitle = screen.getByTestId('updateTitle'); + fireEvent.change(eventTitle, { target: { value: '' } }); + userEvent.type(eventTitle, updateData.title); + + const eventDescription = screen.getByTestId('updateDescription'); + fireEvent.change(eventDescription, { target: { value: '' } }); + userEvent.type(eventDescription, updateData.description); + + const eventLocation = screen.getByTestId('updateLocation'); + fireEvent.change(eventLocation, { target: { value: '' } }); + userEvent.type(eventLocation, updateData.location); + + userEvent.click(screen.getByTestId('updateEventBtn')); + + // shows options to update thisInstance and thisAndFollowingInstances, and allInstances + await waitFor(() => { + expect(screen.getByTestId('update-thisInstance')).toBeInTheDocument(); + expect( + screen.getByTestId('update-thisAndFollowingInstances'), + ).toBeInTheDocument(); + expect(screen.getByTestId('update-allInstances')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('update-allInstances')); + userEvent.click(screen.getByTestId('recurringEventUpdateOptionSubmitBtn')); + + await waitFor(() => { + expect(screen.getByTestId('updateEventBtn')).toBeInTheDocument(); + }); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.eventUpdated); + }); + + await waitFor(() => { + expect( + screen.queryByTestId('eventModalCloseBtn'), + ).not.toBeInTheDocument(); + }); + }); + + test('should update thisAndFollowingInstances of a recurring event', async () => { + renderEventListCard(props[5]); + + userEvent.click(screen.getByTestId('card')); + + await waitFor(() => { + expect(screen.getByLabelText(translations.startDate)).toBeInTheDocument(); + }); + + // change the event dates + const startDatePicker = screen.getByLabelText(translations.startDate); + fireEvent.change(startDatePicker, { + target: { value: updateData.startDate }, + }); + + const endDatePicker = screen.getByLabelText(translations.endDate); + fireEvent.change(endDatePicker, { + target: { value: updateData.endDate }, + }); + + // now change the recurrence rule of the event + await waitFor(() => { + expect(screen.getByTestId('recurrenceOptions')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('recurrenceOptions')); + + await waitFor(() => { + expect(screen.getByTestId('customRecurrence')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('customRecurrence')); + + await waitFor(() => { + expect( + screen.getByTestId('customRecurrenceFrequencyDropdown'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('customRecurrenceFrequencyDropdown')); + + await waitFor(() => { + expect(screen.getByTestId('customDailyRecurrence')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('customDailyRecurrence')); + + await waitFor(() => { + expect( + screen.getByTestId('customRecurrenceSubmitBtn'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('customRecurrenceSubmitBtn')); + + await waitFor(() => { + expect(screen.getByTestId('updateEventBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('updateEventBtn')); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.eventUpdated); + }); + + await waitFor(() => { + expect( + screen.queryByTestId('eventModalCloseBtn'), + ).not.toBeInTheDocument(); + }); + }); + + test('should render the delete modal', async () => { + renderEventListCard(props[1]); + + userEvent.click(screen.getByTestId('card')); + + await waitFor(() => { + expect(screen.getByTestId('deleteEventModalBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('deleteEventModalBtn')); + + await waitFor(() => { + expect( + screen.getByTestId('eventDeleteModalCloseBtn'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('eventDeleteModalCloseBtn')); + + await waitFor(() => { + expect( + screen.queryByTestId('eventDeleteModalCloseBtn'), + ).not.toBeInTheDocument(); + }); + + await waitFor(() => { + expect(screen.getByTestId('eventModalCloseBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('eventModalCloseBtn')); + + await waitFor(() => { + expect( + screen.queryByTestId('eventModalCloseBtn'), + ).not.toBeInTheDocument(); + }); + }); + + test('should call the delete event mutation when the "Yes" button is clicked', async () => { + renderEventListCard(props[1]); + + userEvent.click(screen.getByTestId('card')); + + await waitFor(() => { + expect(screen.getByTestId('deleteEventModalBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('deleteEventModalBtn')); + + await waitFor(() => { + expect(screen.getByTestId('deleteEventBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('deleteEventBtn')); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.eventDeleted); + }); + + await waitFor(() => { + expect( + screen.queryByTestId('eventModalCloseBtn'), + ).not.toBeInTheDocument(); + }); + }); + + test('select different delete options on recurring events & then delete the recurring event', async () => { + renderEventListCard(props[4]); + await wait(); - userEvent.type(screen.getByTestId('updateStartTime'), props.startTime); - userEvent.type(screen.getByTestId('updateEndTime'), props.endTime); + await waitFor(() => { + expect(screen.getByTestId('card')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('card')); + + await waitFor(() => { + expect(screen.getByTestId('deleteEventModalBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('deleteEventModalBtn')); + + await waitFor(() => { + expect( + screen.getByTestId('delete-thisAndFollowingInstances'), + ).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('delete-thisAndFollowingInstances')); + + userEvent.click(screen.getByTestId('delete-allInstances')); + userEvent.click(screen.getByTestId('delete-thisInstance')); - userEvent.click(screen.getByTestId('updatePostBtn')); + userEvent.click(screen.getByTestId('deleteEventBtn')); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.eventDeleted); + }); + + await waitFor(() => { + expect( + screen.queryByTestId('eventModalCloseBtn'), + ).not.toBeInTheDocument(); + }); }); - test('Testing event preview modal', async () => { + + test('should show an error toast when the delete event mutation fails', async () => { render( - - - - - + + + + + + + } + /> + } + /> + + + + + + , ); - await wait(); - expect(screen.getByText(props.eventName)).toBeInTheDocument(); + + userEvent.click(screen.getByTestId('card')); + userEvent.click(screen.getByTestId('deleteEventModalBtn')); + userEvent.click(screen.getByTestId('deleteEventBtn')); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); }); - describe('EventListCard', () => { - it('should render the delete modal', () => { - render( - - - - ); - userEvent.click(screen.getByTestId('card')); - userEvent.click(screen.getByTestId('deleteEventModalBtn')); - userEvent.click(screen.getByTestId('EventDeleteModalCloseBtn')); - userEvent.click(screen.getByTestId('createEventModalCloseBtn')); + test('handle register should work properly', async () => { + setItem('userId', '456'); + + renderEventListCard(props[2]); + + userEvent.click(screen.getByTestId('card')); + + await waitFor(() => { + expect(screen.getByTestId('registerEventBtn')).toBeInTheDocument(); }); + userEvent.click(screen.getByTestId('registerEventBtn')); - it('should call the delete event mutation when the "Yes" button is clicked', async () => { - render( - - - - ); - userEvent.click(screen.getByTestId('card')); - userEvent.click(screen.getByTestId('deleteEventModalBtn')); - const deleteBtn = screen.getByTestId('deleteEventBtn'); - fireEvent.click(deleteBtn); - }); - - it('should show an error toast when the delete event mutation fails', async () => { - const errorMocks = [ - { - request: { - query: DELETE_EVENT_MUTATION, - variables: { - id: props.id, - }, - }, - error: new Error('Something went wrong'), - }, - ]; - const link2 = new StaticMockLink(errorMocks, true); - render( - - - + await waitFor(() => { + expect(toast.success).toBeCalledWith( + `Successfully registered for ${props[2].eventName}`, ); - userEvent.click(screen.getByTestId('card')); - userEvent.click(screen.getByTestId('deleteEventModalBtn')); - const deleteBtn = screen.getByTestId('deleteEventBtn'); - fireEvent.click(deleteBtn); + }); + + await waitFor(() => { + expect( + screen.queryByTestId('eventModalCloseBtn'), + ).not.toBeInTheDocument(); }); }); - test('Should render truncated event details', async () => { - const longEventName = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. A very long event name that exceeds 150 characters and needs to be truncated'; - const longDescription = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. A very long description that exceeds 150 characters and needs to be truncated'; - const longEventNameLength = longEventName.length; - const longDescriptionLength = longDescription.length; - const truncatedEventName = longEventName.substring(0, 150) + '...'; - const truncatedDescriptionName = longDescription.substring(0, 150) + '...'; - render( - - - - - - ); + test('should show already registered text when the user is registered for an event', async () => { + renderEventListCard(props[3]); - await wait(); + userEvent.click(screen.getByTestId('card')); - expect(longEventNameLength).toBeGreaterThan(100); - expect(longDescriptionLength).toBeGreaterThan(256); - expect(truncatedEventName).toContain('...'); - expect(truncatedDescriptionName).toContain('...'); - await wait(); + expect( + screen.getByText(translations.alreadyRegistered), + ).toBeInTheDocument(); }); }); diff --git a/src/components/EventListCard/EventListCard.tsx b/src/components/EventListCard/EventListCard.tsx index 0ec3a62d6f..cdcfabcde2 100644 --- a/src/components/EventListCard/EventListCard.tsx +++ b/src/components/EventListCard/EventListCard.tsx @@ -1,463 +1,81 @@ -import type { ChangeEvent } from 'react'; -import React, { useEffect, useState } from 'react'; -import { useMutation } from '@apollo/client'; -import { toast } from 'react-toastify'; +import React, { useState } from 'react'; import { useTranslation } from 'react-i18next'; -import Modal from 'react-bootstrap/Modal'; -import Button from 'react-bootstrap/Button'; import styles from './EventListCard.module.css'; -import { - DELETE_EVENT_MUTATION, - UPDATE_EVENT_MUTATION, -} from 'GraphQl/Mutations/mutations'; -import { Form } from 'react-bootstrap'; -import { errorHandler } from 'utils/errorHandler'; -import { useHistory } from 'react-router-dom'; +import { Navigate, useParams } from 'react-router-dom'; +import EventListCardModals from './EventListCardModals'; +import type { InterfaceRecurrenceRule } from 'utils/recurrenceUtils'; -interface InterfaceEventListCardProps { +export interface InterfaceEventListCardProps { + refetchEvents?: () => void; + userRole?: string; key: string; id: string; eventLocation: string; eventName: string; eventDescription: string; - regDate: string; - regEndDate: string; - startTime: string; - endTime: string; + startDate: string; + endDate: string; + startTime: string | null; + endTime: string | null; allDay: boolean; recurring: boolean; + recurrenceRule: InterfaceRecurrenceRule | null; + isRecurringEventException: boolean; isPublic: boolean; isRegisterable: boolean; + registrants?: { + _id: string; + }[]; + creator?: { + firstName: string; + lastName: string; + _id: string; + }; } + function eventListCard(props: InterfaceEventListCardProps): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'eventListCard', }); - const [eventmodalisOpen, setEventModalIsOpen] = useState(false); - const [alldaychecked, setAllDayChecked] = useState(true); - const [recurringchecked, setRecurringChecked] = useState(false); - const [publicchecked, setPublicChecked] = useState(true); - const [registrablechecked, setRegistrableChecked] = React.useState(false); - const [eventDeleteModalIsOpen, setEventDeleteModalIsOpen] = useState(false); - const [eventUpdateModalIsOpen, setEventUpdateModalIsOpen] = useState(false); - const history = useHistory(); - const [formState, setFormState] = useState({ - title: '', - eventdescrip: '', - location: '', - startTime: '08:00:00', - endTime: '18:00:00', - }); - const showViewModal = (): void => { - setEventModalIsOpen(true); - }; - const hideViewModal = (): void => { - setEventModalIsOpen(false); - }; - - const toggleDeleteModal = (): void => { - setEventDeleteModalIsOpen(!eventDeleteModalIsOpen); - }; - - const toggleUpdateModel = (): void => { - setEventUpdateModalIsOpen(!eventUpdateModalIsOpen); - }; - - useEffect(() => { - setFormState({ - title: props.eventName, - eventdescrip: props.eventDescription, - location: props.eventLocation, - startTime: props.startTime?.split('.')[0] || '08:00:00', - endTime: props.endTime?.split('.')[0] || '18:00:00', - }); - setAllDayChecked(props.allDay); - setRecurringChecked(props.recurring); - setPublicChecked(props.isPublic); - setRegistrableChecked(props.isRegisterable); - }, []); + const [eventModalIsOpen, setEventModalIsOpen] = useState(false); - const [create] = useMutation(DELETE_EVENT_MUTATION); - const [updateEvent] = useMutation(UPDATE_EVENT_MUTATION); + const { orgId } = useParams(); + if (!orgId) { + return ; + } - const deleteEvent = async (): Promise => { - try { - const { data } = await create({ - variables: { - id: props.id, - }, - }); - - /* istanbul ignore next */ - if (data) { - toast.success(t('eventDeleted')); - setTimeout(() => { - window.location.reload(); - }, 2000); - } - } catch (error: any) { - /* istanbul ignore next */ - errorHandler(t, error); - } - }; - - const updateEventHandler = async ( - e: ChangeEvent - ): Promise => { - e.preventDefault(); - - try { - const { data } = await updateEvent({ - variables: { - id: props.id, - title: formState.title, - description: formState.eventdescrip, - isPublic: publicchecked, - recurring: recurringchecked, - isRegisterable: registrablechecked, - allDay: alldaychecked, - location: formState.location, - startTime: !alldaychecked ? formState.startTime + 'Z' : null, - endTime: !alldaychecked ? formState.endTime + 'Z' : null, - }, - }); - - /* istanbul ignore next */ - if (data) { - toast.success(t('eventUpdated')); - setTimeout(() => { - window.location.reload(); - }, 2000); - } - } catch (error: any) { - /* istanbul ignore next */ - errorHandler(t, error); - } + const showViewModal = (): void => { + setEventModalIsOpen(true); }; - const openEventDashboard = (): void => { - history.push(`/event/${props.id}`); + const hideViewModal = (): void => { + setEventModalIsOpen(false); }; return ( <> -
    -
    -
    -

    - {props.eventName ? ( - <> - {props.eventName.length > 150 ? ( - <>{props.eventName.substring(0, 150)}... - ) : ( - <>{props.eventName} - )} - - ) : ( - <>Dogs Care - )} -

    -
    +
    +
    +

    + {props.eventName ? <>{props.eventName} : <>Dogs Care} +

    - {/* preview modal */} - - -

    {t('eventDetails')}

    - -
    - - -
    -

    - {t('eventTitle')}:{' '} - - {props.eventName ? ( - <> - {props.eventName.length > 100 ? ( - <>{props.eventName.substring(0, 100)}... - ) : ( - <>{props.eventName} - )} - - ) : ( - <>Dogs Care - )} - -

    -

    - {t('location')}: - - {props.eventLocation ? ( - <>{props.eventLocation} - ) : ( - <>India - )} - -

    -

    - {t('description')}:{' '} - - {props.eventDescription && props.eventDescription.length > 256 - ? props.eventDescription.substring(0, 256) + '...' - : props.eventDescription} - -

    -

    - {t('on')}: {props.regDate} -

    -

    - {t('end')}:{' '} - {props.regEndDate} -

    - -
    -
    - - -
    - -
    -
    - {/* delete modal */} - - - - {t('deleteEvent')} - - - {t('deleteEventMsg')} - - - - - - - {/* Edit Modal */} - - - - {' '} - {t('editEvent')} - - -
    - - - { - setFormState({ - ...formState, - title: e.target.value, - }); - }} - /> - - { - setFormState({ - ...formState, - eventdescrip: e.target.value, - }); - }} - /> - - { - setFormState({ - ...formState, - location: e.target.value, - }); - }} - /> - {!alldaychecked && ( -
    -
    - - - setFormState({ - ...formState, - startTime: e.target.value, - }) - } - /> -
    -
    - - - setFormState({ - ...formState, - endTime: e.target.value, - }) - } - /> -
    -
    - )} -
    -
    - - setAllDayChecked(!alldaychecked)} - /> -
    -
    - - setRecurringChecked(!recurringchecked)} - /> -
    -
    -
    -
    - - setPublicChecked(!publicchecked)} - /> -
    -
    - - - setRegistrableChecked(!registrablechecked) - } - /> -
    -
    -
    - - - - -
    -
    + ); } diff --git a/src/components/EventListCard/EventListCardMocks.ts b/src/components/EventListCard/EventListCardMocks.ts new file mode 100644 index 0000000000..e5f7ea3227 --- /dev/null +++ b/src/components/EventListCard/EventListCardMocks.ts @@ -0,0 +1,201 @@ +import { + DELETE_EVENT_MUTATION, + REGISTER_EVENT, + UPDATE_EVENT_MUTATION, +} from 'GraphQl/Mutations/mutations'; + +export const MOCKS = [ + { + request: { + query: DELETE_EVENT_MUTATION, + variables: { id: '1' }, + }, + result: { + data: { + removeEvent: { + _id: '1', + }, + }, + }, + }, + { + request: { + query: DELETE_EVENT_MUTATION, + variables: { id: '1', recurringEventDeleteType: 'thisInstance' }, + }, + result: { + data: { + removeEvent: { + _id: '1', + }, + }, + }, + }, + { + request: { + query: UPDATE_EVENT_MUTATION, + variables: { + id: '1', + title: 'Updated title', + description: 'This is a new update', + isPublic: false, + recurring: false, + isRegisterable: true, + allDay: true, + startDate: '2022-03-18', + endDate: '2022-03-20', + location: 'New Delhi', + }, + }, + result: { + data: { + updateEvent: { + _id: '1', + }, + }, + }, + }, + { + request: { + query: UPDATE_EVENT_MUTATION, + variables: { + id: '1', + title: 'Updated title', + description: 'This is a new update', + isPublic: false, + recurring: false, + isRegisterable: true, + allDay: false, + startDate: '2022-03-18', + endDate: '2022-03-20', + location: 'New Delhi', + startTime: '09:00:00Z', + endTime: '17:00:00Z', + }, + }, + result: { + data: { + updateEvent: { + _id: '1', + }, + }, + }, + }, + { + request: { + query: UPDATE_EVENT_MUTATION, + variables: { + id: '1', + title: 'Updated title', + description: 'This is a new update', + isPublic: false, + recurring: true, + recurringEventUpdateType: 'thisInstance', + isRegisterable: true, + allDay: true, + startDate: '2022-03-18', + endDate: '2022-03-20', + location: 'New Delhi', + recurrenceStartDate: '2022-03-18', + recurrenceEndDate: null, + frequency: 'WEEKLY', + weekDays: ['FRIDAY'], + interval: 1, + }, + }, + result: { + data: { + updateEvent: { + _id: '1', + }, + }, + }, + }, + { + request: { + query: UPDATE_EVENT_MUTATION, + variables: { + id: '1', + title: 'Updated title', + description: 'This is a new update', + isPublic: true, + recurring: true, + recurringEventUpdateType: 'allInstances', + isRegisterable: false, + allDay: true, + startDate: '2022-03-17', + endDate: '2022-03-17', + location: 'New Delhi', + recurrenceStartDate: '2022-03-17', + recurrenceEndDate: '2023-03-17', + frequency: 'MONTHLY', + weekDays: ['THURSDAY'], + interval: 1, + weekDayOccurenceInMonth: 3, + }, + }, + result: { + data: { + updateEvent: { + _id: '1', + }, + }, + }, + }, + { + request: { + query: UPDATE_EVENT_MUTATION, + variables: { + id: '1', + title: 'Shelter for Cats', + description: 'This is shelter for cat event', + isPublic: true, + recurring: true, + recurringEventUpdateType: 'thisAndFollowingInstances', + isRegisterable: false, + allDay: true, + startDate: '2022-03-18', + endDate: '2022-03-20', + location: 'India', + recurrenceStartDate: '2022-03-18', + recurrenceEndDate: null, + frequency: 'DAILY', + interval: 1, + }, + }, + result: { + data: { + updateEvent: { + _id: '1', + }, + }, + }, + }, + { + request: { + query: REGISTER_EVENT, + variables: { eventId: '1' }, + }, + result: { + data: { + registerForEvent: [ + { + _id: '123', + }, + ], + }, + }, + }, +]; + +export const ERROR_MOCKS = [ + { + request: { + query: DELETE_EVENT_MUTATION, + variables: { + id: '1', + }, + }, + error: new Error('Something went wrong'), + }, +]; diff --git a/src/components/EventListCard/EventListCardModals.tsx b/src/components/EventListCard/EventListCardModals.tsx new file mode 100644 index 0000000000..7fdc85647a --- /dev/null +++ b/src/components/EventListCard/EventListCardModals.tsx @@ -0,0 +1,810 @@ +import React, { useEffect, useState } from 'react'; +import { Button, Form, Modal, Popover } from 'react-bootstrap'; +import styles from './EventListCard.module.css'; +import { DatePicker, TimePicker } from '@mui/x-date-pickers'; +import dayjs from 'dayjs'; +import type { Dayjs } from 'dayjs'; +import type { InterfaceEventListCardProps } from './EventListCard'; +import { + type InterfaceRecurrenceRuleState, + type RecurringEventMutationType, + Days, + Frequency, + allInstances, + getRecurrenceRuleText, + getWeekDayOccurenceInMonth, + recurringEventMutationOptions, + thisAndFollowingInstances, + thisInstance, + haveInstanceDatesChanged, + hasRecurrenceRuleChanged, +} from 'utils/recurrenceUtils'; +import useLocalStorage from 'utils/useLocalstorage'; +import RecurrenceOptions from 'components/RecurrenceOptions/RecurrenceOptions'; +import { useNavigate, useParams } from 'react-router-dom'; +import { + DELETE_EVENT_MUTATION, + REGISTER_EVENT, + UPDATE_EVENT_MUTATION, +} from 'GraphQl/Mutations/mutations'; +import { useMutation } from '@apollo/client'; +import { toast } from 'react-toastify'; +import { errorHandler } from 'utils/errorHandler'; + +enum Role { + USER = 'USER', + SUPERADMIN = 'SUPERADMIN', + ADMIN = 'ADMIN', +} + +const timeToDayJs = (time: string): Dayjs => { + const dateTimeString = dayjs().format('YYYY-MM-DD') + ' ' + time; + return dayjs(dateTimeString, { format: 'YYYY-MM-DD HH:mm:ss' }); +}; + +interface InterfaceEventListCardModalProps { + eventListCardProps: InterfaceEventListCardProps; + eventModalIsOpen: boolean; + hideViewModal: () => void; + t: (key: string) => string; +} + +function EventListCardModals({ + eventListCardProps, + eventModalIsOpen, + hideViewModal, + t, +}: InterfaceEventListCardModalProps): JSX.Element { + const { refetchEvents } = eventListCardProps; + + const { getItem } = useLocalStorage(); + const userId = getItem('userId'); + + const { orgId } = useParams(); + const navigate = useNavigate(); + + const [alldaychecked, setAllDayChecked] = useState(eventListCardProps.allDay); + const [recurringchecked, setRecurringChecked] = useState( + eventListCardProps.recurring, + ); + const [publicchecked, setPublicChecked] = useState( + eventListCardProps.isPublic, + ); + const [registrablechecked, setRegistrableChecked] = useState( + eventListCardProps.isRegisterable, + ); + const [eventDeleteModalIsOpen, setEventDeleteModalIsOpen] = useState(false); + const [recurringEventUpdateModalIsOpen, setRecurringEventUpdateModalIsOpen] = + useState(false); + const [eventStartDate, setEventStartDate] = useState( + new Date(eventListCardProps.startDate), + ); + const [eventEndDate, setEventEndDate] = useState( + new Date(eventListCardProps.endDate), + ); + + const [recurrenceRuleState, setRecurrenceRuleState] = + useState({ + recurrenceStartDate: eventStartDate, + recurrenceEndDate: null, + frequency: Frequency.WEEKLY, + weekDays: [Days[eventStartDate.getDay()]], + interval: 1, + count: undefined, + weekDayOccurenceInMonth: undefined, + }); + + const { + recurrenceStartDate, + recurrenceEndDate, + frequency, + weekDays, + interval, + count, + weekDayOccurenceInMonth, + } = recurrenceRuleState; + + const recurrenceRuleText = getRecurrenceRuleText(recurrenceRuleState); + + const [formState, setFormState] = useState({ + title: eventListCardProps.eventName, + eventdescrip: eventListCardProps.eventDescription, + location: eventListCardProps.eventLocation, + startTime: eventListCardProps.startTime?.split('.')[0] || '08:00:00', + endTime: eventListCardProps.endTime?.split('.')[0] || '08:00:00', + }); + + const [recurringEventDeleteType, setRecurringEventDeleteType] = + useState(thisInstance); + + const [recurringEventUpdateType, setRecurringEventUpdateType] = + useState(thisInstance); + + const [recurringEventUpdateOptions, setRecurringEventUpdateOptions] = + useState([ + thisInstance, + thisAndFollowingInstances, + allInstances, + ]); + + const [ + shouldShowRecurringEventUpdateOptions, + setShouldShowRecurringEventUpdateOptions, + ] = useState(true); + + useEffect(() => { + if (eventModalIsOpen) { + if (eventListCardProps.recurrenceRule) { + // get the recurrence rule + const { recurrenceRule } = eventListCardProps; + + // set the recurrence rule state + setRecurrenceRuleState({ + recurrenceStartDate: new Date(recurrenceRule.recurrenceStartDate), + recurrenceEndDate: recurrenceRule.recurrenceEndDate + ? new Date(recurrenceRule.recurrenceEndDate) + : null, + frequency: recurrenceRule.frequency, + weekDays: recurrenceRule.weekDays, + interval: recurrenceRule.interval, + count: recurrenceRule.count ?? undefined, + weekDayOccurenceInMonth: + recurrenceRule.weekDayOccurenceInMonth ?? undefined, + }); + } + } + }, [eventModalIsOpen]); + + // a state to specify whether the recurrence rule has changed + const [recurrenceRuleChanged, setRecurrenceRuleChanged] = useState(false); + + // a state to specify whether the instance's startDate or endDate has changed + const [instanceDatesChanged, setInstanceDatesChanged] = useState(false); + + // the `recurrenceRuleChanged` & `instanceDatesChanged` are required, + // because we will provide recurring event update options based on them, i.e.: + // - if the `instanceDatesChanged` is true, we'll not provide the option to update "allInstances" + // - if the `recurrenceRuleChanged` is true, we'll not provide the option to update "thisInstance" + // - if both are true, we'll only provide the option to update "thisAndFollowingInstances" + // updating recurring events is not very straightforward, + // find more info on the approach in this doc https://docs.talawa.io/docs/functionalities/recurring-events + + useEffect(() => { + setInstanceDatesChanged( + haveInstanceDatesChanged( + eventListCardProps.startDate, + eventListCardProps.endDate, + dayjs(eventStartDate).format('YYYY-MM-DD'), // convert to date string + dayjs(eventEndDate).format('YYYY-MM-DD'), // convert to date string + ), + ); + setRecurrenceRuleChanged( + hasRecurrenceRuleChanged( + eventListCardProps.recurrenceRule, + recurrenceRuleState, + ), + ); + }, [eventStartDate, eventEndDate, recurrenceRuleState]); + + useEffect(() => { + if (instanceDatesChanged) { + setRecurringEventUpdateType(thisInstance); + setRecurringEventUpdateOptions([thisInstance, thisAndFollowingInstances]); + setShouldShowRecurringEventUpdateOptions(true); + } + + if (recurrenceRuleChanged) { + setRecurringEventUpdateType(thisAndFollowingInstances); + setRecurringEventUpdateOptions([thisAndFollowingInstances, allInstances]); + setShouldShowRecurringEventUpdateOptions(true); + } + + if (recurrenceRuleChanged && instanceDatesChanged) { + setRecurringEventUpdateType(thisAndFollowingInstances); + setShouldShowRecurringEventUpdateOptions(false); + } + + if (!recurrenceRuleChanged && !instanceDatesChanged) { + setRecurringEventUpdateType(thisInstance); + setRecurringEventUpdateOptions([ + thisInstance, + thisAndFollowingInstances, + allInstances, + ]); + setShouldShowRecurringEventUpdateOptions(true); + } + }, [recurrenceRuleChanged, instanceDatesChanged]); + + const [updateEvent] = useMutation(UPDATE_EVENT_MUTATION); + + const updateEventHandler = async (): Promise => { + try { + const { data } = await updateEvent({ + variables: { + id: eventListCardProps.id, + title: formState.title, + description: formState.eventdescrip, + isPublic: publicchecked, + recurring: recurringchecked, + recurringEventUpdateType: recurringchecked + ? recurringEventUpdateType + : undefined, + isRegisterable: registrablechecked, + allDay: alldaychecked, + startDate: dayjs(eventStartDate).format('YYYY-MM-DD'), + endDate: dayjs(eventEndDate).format('YYYY-MM-DD'), + location: formState.location, + startTime: !alldaychecked ? formState.startTime + 'Z' : undefined, + endTime: !alldaychecked ? formState.endTime + 'Z' : undefined, + recurrenceStartDate: recurringchecked + ? recurringEventUpdateType === thisAndFollowingInstances && + (instanceDatesChanged || recurrenceRuleChanged) + ? dayjs(eventStartDate).format('YYYY-MM-DD') + : dayjs(recurrenceStartDate).format('YYYY-MM-DD') + : undefined, + recurrenceEndDate: recurringchecked + ? recurrenceEndDate + ? dayjs(recurrenceEndDate).format('YYYY-MM-DD') + : null + : undefined, + frequency: recurringchecked ? frequency : undefined, + weekDays: + recurringchecked && + (frequency === Frequency.WEEKLY || + (frequency === Frequency.MONTHLY && weekDayOccurenceInMonth)) + ? weekDays + : undefined, + interval: recurringchecked ? interval : undefined, + count: recurringchecked ? count : undefined, + weekDayOccurenceInMonth: recurringchecked + ? weekDayOccurenceInMonth + : undefined, + }, + }); + + if (data) { + toast.success(t('eventUpdated')); + setRecurringEventUpdateModalIsOpen(false); + hideViewModal(); + if (refetchEvents) { + refetchEvents(); + } + } + } catch (error: unknown) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + + const handleEventUpdate = async (): Promise => { + if (!eventListCardProps.recurring) { + await updateEventHandler(); + } else { + if (shouldShowRecurringEventUpdateOptions) { + setRecurringEventUpdateModalIsOpen(true); + } else { + await updateEventHandler(); + } + } + }; + + const [deleteEvent] = useMutation(DELETE_EVENT_MUTATION); + + const deleteEventHandler = async (): Promise => { + try { + const { data } = await deleteEvent({ + variables: { + id: eventListCardProps.id, + recurringEventDeleteType: eventListCardProps.recurring + ? recurringEventDeleteType + : undefined, + }, + }); + + if (data) { + toast.success(t('eventDeleted')); + setEventDeleteModalIsOpen(false); + hideViewModal(); + if (refetchEvents) { + refetchEvents(); + } + } + } catch (error: unknown) { + errorHandler(t, error); + } + }; + + const toggleDeleteModal = (): void => { + setEventDeleteModalIsOpen(!eventDeleteModalIsOpen); + }; + + const isInitiallyRegistered = eventListCardProps?.registrants?.some( + (registrant) => registrant._id === userId, + ); + const [registerEventMutation] = useMutation(REGISTER_EVENT); + const [isRegistered, setIsRegistered] = React.useState(isInitiallyRegistered); + + const registerEventHandler = async (): Promise => { + if (!isRegistered) { + try { + const { data } = await registerEventMutation({ + variables: { + eventId: eventListCardProps.id, + }, + }); + + if (data) { + toast.success( + `Successfully registered for ${eventListCardProps.eventName}`, + ); + setIsRegistered(true); + hideViewModal(); + } + } catch (error: unknown) { + /* istanbul ignore next */ + errorHandler(t, error); + } + } + }; + + const toggleRecurringEventUpdateModal = (): void => { + setRecurringEventUpdateModalIsOpen(!recurringEventUpdateModalIsOpen); + }; + + const openEventDashboard = (): void => { + navigate(`/event/${orgId}/${eventListCardProps.id}`); + }; + + const popover = ( + + {recurrenceRuleText} + + ); + + return ( + <> + {/* preview modal */} + + +

    {t('eventDetails')}

    + +
    + +
    +

    {t('eventTitle')}

    + 100 + ? formState.title.substring(0, 100) + '...' + : formState.title + } + onChange={(e): void => { + setFormState({ + ...formState, + title: e.target.value, + }); + }} + disabled={ + !(eventListCardProps.creator?._id === userId) && + eventListCardProps.userRole === Role.USER + } + /> +

    {t('description')}

    + 256 + ? formState.eventdescrip.substring(0, 256) + '...' + : formState.eventdescrip + } + onChange={(e): void => { + setFormState({ + ...formState, + eventdescrip: e.target.value, + }); + }} + disabled={ + !(eventListCardProps.creator?._id === userId) && + eventListCardProps.userRole === Role.USER + } + /> +

    {t('location')}

    + { + setFormState({ + ...formState, + location: e.target.value, + }); + }} + disabled={ + !(eventListCardProps.creator?._id === userId) && + eventListCardProps.userRole === Role.USER + } + /> +
    +
    + { + if (date) { + setEventStartDate(date?.toDate()); + setEventEndDate( + eventEndDate < date?.toDate() + ? date?.toDate() + : eventEndDate, + ); + if (!eventListCardProps.recurring) { + setRecurrenceRuleState({ + ...recurrenceRuleState, + recurrenceStartDate: date?.toDate(), + weekDays: [Days[date?.toDate().getDay()]], + weekDayOccurenceInMonth: weekDayOccurenceInMonth + ? /* istanbul ignore next */ getWeekDayOccurenceInMonth( + date?.toDate(), + ) + : undefined, + }); + } + } + }} + /> +
    +
    + { + if (date) { + setEventEndDate(date?.toDate()); + } + }} + minDate={dayjs(eventStartDate)} + /> +
    +
    + {!alldaychecked && ( +
    +
    + { + if (time) { + setFormState({ + ...formState, + startTime: time?.format('HH:mm:ss'), + endTime: + timeToDayJs(formState.endTime) < time + ? time?.format('HH:mm:ss') + : /* istanbul ignore next */ + formState.endTime, + }); + } + }} + disabled={alldaychecked} + /> +
    +
    + { + if (time) { + setFormState({ + ...formState, + endTime: time?.format('HH:mm:ss'), + }); + } + }} + minTime={timeToDayJs(formState.startTime)} + disabled={alldaychecked} + /> +
    +
    + )} +
    +
    +
    + + { + setAllDayChecked(!alldaychecked); + }} + disabled={ + !(eventListCardProps.creator?._id === userId) && + eventListCardProps.userRole === Role.USER + } + /> +
    +
    + + { + setRecurringChecked(!recurringchecked); + }} + disabled={ + !(eventListCardProps.creator?._id === userId) && + eventListCardProps.userRole === Role.USER + } + /> +
    +
    +
    +
    + + { + setPublicChecked(!publicchecked); + }} + disabled={ + !(eventListCardProps.creator?._id === userId) && + eventListCardProps.userRole === Role.USER + } + /> +
    +
    + + { + setRegistrableChecked(!registrablechecked); + }} + disabled={ + !(eventListCardProps.creator?._id === userId) && + eventListCardProps.userRole === Role.USER + } + /> +
    +
    +
    + + {/* Recurrence Options */} + {recurringchecked && ( + + )} + +
    + + {(eventListCardProps.userRole !== Role.USER || + eventListCardProps.creator?._id === userId) && ( + + )} + {(eventListCardProps.userRole !== Role.USER || + eventListCardProps.creator?._id === userId) && ( + + )} + {(eventListCardProps.userRole !== Role.USER || + eventListCardProps.creator?._id === userId) && ( + + )} + {eventListCardProps.userRole === Role.USER && + !(eventListCardProps.creator?._id === userId) && + (isRegistered ? ( + + ) : ( + + ))} + +
    + + {/* recurring event update options modal */} + + + + {t('editEvent')} + + + +
    + {recurringEventUpdateOptions.map((option, index) => ( +
    + + setRecurringEventUpdateType( + e.target.value as RecurringEventMutationType, + ) + } + defaultChecked={option === recurringEventUpdateType} + data-testid={`update-${option}`} + /> +
    + ))} +
    +
    + + + + +
    + + {/* delete modal */} + + + + {t('deleteEvent')} + + + + {!eventListCardProps.recurring && t('deleteEventMsg')} + {eventListCardProps.recurring && ( + <> +
    + {recurringEventMutationOptions.map((option, index) => ( +
    + + setRecurringEventDeleteType( + e.target.value as RecurringEventMutationType, + ) + } + defaultChecked={option === recurringEventDeleteType} + data-testid={`delete-${option}`} + /> +
    + ))} +
    + + )} +
    + + + + +
    + + ); +} + +export default EventListCardModals; diff --git a/src/components/EventListCard/EventListCardProps.ts b/src/components/EventListCard/EventListCardProps.ts new file mode 100644 index 0000000000..9aef474254 --- /dev/null +++ b/src/components/EventListCard/EventListCardProps.ts @@ -0,0 +1,194 @@ +import { Frequency, WeekDays } from 'utils/recurrenceUtils'; +import type { InterfaceEventListCardProps } from './EventListCard'; + +export const props: InterfaceEventListCardProps[] = [ + { + key: '', + id: '', + eventLocation: '', + eventName: '', + eventDescription: '', + startDate: '', + endDate: '', + startTime: '', + endTime: '', + allDay: false, + recurring: false, + recurrenceRule: null, + isRecurringEventException: false, + isPublic: false, + isRegisterable: false, + refetchEvents: (): void => { + /* refetch function */ + }, + }, + { + key: '123', + id: '1', + eventLocation: 'India', + eventName: 'Shelter for Dogs', + eventDescription: 'This is shelter for dogs event', + startDate: '2022-03-19', + endDate: '2022-03-26', + startTime: '02:00', + endTime: '06:00', + allDay: false, + recurring: false, + recurrenceRule: null, + isRecurringEventException: false, + isPublic: true, + isRegisterable: false, + refetchEvents: (): void => { + /* refetch function */ + }, + }, + { + userRole: 'USER', + key: '123', + id: '1', + eventLocation: 'India', + eventName: 'Shelter for Dogs', + eventDescription: 'This is shelter for dogs event', + startDate: '2022-03-19', + endDate: '2022-03-26', + startTime: '02:00', + endTime: '06:00', + allDay: true, + recurring: false, + recurrenceRule: null, + isRecurringEventException: false, + isPublic: true, + isRegisterable: false, + creator: { + firstName: 'Joe', + lastName: 'David', + _id: '123', + }, + registrants: [ + { + _id: '234', + }, + ], + refetchEvents: (): void => { + /* refetch function */ + }, + }, + { + userRole: 'USER', + key: '123', + id: '1', + eventLocation: 'India', + eventName: 'Shelter for Dogs', + eventDescription: 'This is shelter for dogs event', + startDate: '2022-03-19', + endDate: '2022-03-26', + startTime: '02:00', + endTime: '06:00', + allDay: true, + recurring: false, + recurrenceRule: null, + isRecurringEventException: false, + isPublic: true, + isRegisterable: false, + creator: { + firstName: 'Joe', + lastName: 'David', + _id: '123', + }, + registrants: [ + { + _id: '456', + }, + ], + refetchEvents: (): void => { + /* refetch function */ + }, + }, + { + userRole: 'ADMIN', + key: '123', + id: '1', + eventLocation: 'India', + eventName: 'Shelter for Cats', + eventDescription: 'This is shelter for cat event', + startDate: '2022-03-19', + endDate: '2022-03-19', + startTime: '2:00', + endTime: '6:00', + allDay: false, + recurring: true, + recurrenceRule: { + recurrenceStartDate: '2022-03-19', + recurrenceEndDate: '2022-03-26', + frequency: Frequency.WEEKLY, + weekDays: [WeekDays.SATURDAY], + interval: 1, + count: null, + weekDayOccurenceInMonth: null, + }, + isRecurringEventException: false, + isPublic: true, + isRegisterable: false, + refetchEvents: (): void => { + /* refetch function */ + }, + }, + { + userRole: 'ADMIN', + key: '123', + id: '1', + eventLocation: 'India', + eventName: 'Shelter for Cats', + eventDescription: 'This is shelter for cat event', + startDate: '2022-03-17', + endDate: '2022-03-17', + startTime: null, + endTime: null, + allDay: true, + recurring: true, + recurrenceRule: { + recurrenceStartDate: '2022-03-17', + recurrenceEndDate: null, + frequency: Frequency.MONTHLY, + weekDays: [WeekDays.THURSDAY], + interval: 1, + count: null, + weekDayOccurenceInMonth: 3, + }, + isRecurringEventException: false, + isPublic: true, + isRegisterable: false, + refetchEvents: (): void => { + /* refetch function */ + }, + }, + { + userRole: 'ADMIN', + key: '123', + id: '1', + eventLocation: 'India', + eventName: 'Shelter for Cats', + eventDescription: 'This is shelter for cat event', + startDate: '2022-03-17', + endDate: '2022-03-17', + startTime: null, + endTime: null, + allDay: true, + recurring: true, + recurrenceRule: { + recurrenceStartDate: '2022-03-17', + recurrenceEndDate: '2023-03-17', + frequency: Frequency.MONTHLY, + weekDays: [WeekDays.THURSDAY], + interval: 1, + count: null, + weekDayOccurenceInMonth: 3, + }, + isRecurringEventException: false, + isPublic: true, + isRegisterable: false, + refetchEvents: (): void => { + /* refetch function */ + }, + }, +]; diff --git a/src/components/EventManagement/Dashboard/EventDashboard.mocks.ts b/src/components/EventManagement/Dashboard/EventDashboard.mocks.ts new file mode 100644 index 0000000000..5aeb20b205 --- /dev/null +++ b/src/components/EventManagement/Dashboard/EventDashboard.mocks.ts @@ -0,0 +1,65 @@ +import { EVENT_DETAILS } from 'GraphQl/Queries/Queries'; + +// Mock 1 +export const MOCKS_WITH_TIME = [ + { + request: { + query: EVENT_DETAILS, + variables: { + id: 'event123', + }, + }, + result: { + data: { + event: { + _id: 'event123', + title: 'Event Title', + description: 'Event Description', + startDate: '1/1/23', + endDate: '16/2/23', + startTime: '08:00:00', + endTime: '09:00:00', + allDay: false, + location: 'India', + organization: { + _id: 'org1', + members: [{ _id: 'user1', firstName: 'John', lastName: 'Doe' }], + }, + attendees: [{ _id: 'user1' }], + }, + }, + }, + }, +]; + +// Mock 2 +export const MOCKS_WITHOUT_TIME = [ + { + request: { + query: EVENT_DETAILS, + variables: { + id: 'event123', + }, + }, + result: { + data: { + event: { + _id: 'event123', + title: 'Event Title', + description: 'Event Description', + startDate: '1/1/23', + endDate: '2/2/23', + startTime: null, + endTime: null, + allDay: false, + location: 'India', + organization: { + _id: 'org1', + members: [{ _id: 'user1', firstName: 'John', lastName: 'Doe' }], + }, + attendees: [{ _id: 'user1' }], + }, + }, + }, + }, +]; diff --git a/src/components/EventManagement/Dashboard/EventDashboard.module.css b/src/components/EventManagement/Dashboard/EventDashboard.module.css new file mode 100644 index 0000000000..b7a29e0011 --- /dev/null +++ b/src/components/EventManagement/Dashboard/EventDashboard.module.css @@ -0,0 +1,76 @@ +.eventContainer { + display: flex; + align-items: center; +} + +.eventDetailsBox { + position: relative; + margin-left: 50px; + height: 90%; + width: 45%; + box-sizing: border-box; + background: #ffffff; + border: 1px solid #dddddd; + border-radius: 8px; + margin-bottom: 0; +} + +.eventDetailsBox::before { + content: ''; + position: absolute; + top: 0; + height: 100%; + width: 6px; + background-color: #31bb6b; + border-radius: 8px; +} + +.time { + display: flex; + justify-content: space-between; + padding: 15px; + padding-bottom: 0px; +} + +.startTime, +.endTime { + display: flex; + font-size: 20px; +} + +.to { + padding-right: 10px; +} + +.startDate, +.endDate { + color: #808080; + font-size: 14px; +} + +.titlename { + font-weight: 600; + font-size: 20px; + padding: 15px; + padding-bottom: 0px; + width: 100%; +} + +.description { + color: #737373; + font-weight: 300; + font-size: 14px; + word-wrap: break-word; + padding: 15px; + padding-bottom: 0px; +} + +.toporgloc { + font-size: 16px; + padding: 15px; + padding-bottom: 0px; +} + +.toporgloc span { + color: #737373; +} diff --git a/src/components/EventManagement/Dashboard/EventDashboard.test.tsx b/src/components/EventManagement/Dashboard/EventDashboard.test.tsx new file mode 100644 index 0000000000..24a4ba207a --- /dev/null +++ b/src/components/EventManagement/Dashboard/EventDashboard.test.tsx @@ -0,0 +1,83 @@ +import React from 'react'; +import type { RenderResult } from '@testing-library/react'; +import { render, act } from '@testing-library/react'; +import EventDashboard from './EventDashboard'; +import { BrowserRouter } from 'react-router-dom'; +import { ToastContainer } from 'react-toastify'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import type { ApolloLink, DefaultOptions } from '@apollo/client'; + +import { MOCKS_WITHOUT_TIME, MOCKS_WITH_TIME } from './EventDashboard.mocks'; +import { StaticMockLink } from 'utils/StaticMockLink'; + +const mockWithTime = new StaticMockLink(MOCKS_WITH_TIME, true); +const mockWithoutTime = new StaticMockLink(MOCKS_WITHOUT_TIME, true); + +// We want to disable all forms of caching so that we do not need to define a custom merge function in testing for the network requests +const defaultOptions: DefaultOptions = { + watchQuery: { + fetchPolicy: 'no-cache', + errorPolicy: 'ignore', + }, + query: { + fetchPolicy: 'no-cache', + errorPolicy: 'all', + }, +}; + +async function wait(ms = 500): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +const mockID = 'event123'; +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ eventId: mockID }), +})); + +const renderEventDashboard = (mockLink: ApolloLink): RenderResult => { + return render( + + + + + + + + + + , + ); +}; + +describe('Testing Event Dashboard Screen', () => { + test('The page should display event details correctly and also show the time if provided', async () => { + const { queryByText, queryAllByText } = renderEventDashboard(mockWithTime); + + await wait(); + + expect(queryAllByText('Event Title').length).toBe(1); + expect(queryAllByText('Event Description').length).toBe(1); + expect(queryByText('India')).toBeInTheDocument(); + + await wait(); + }); + + test('The page should display event details correctly and should not show the time if it is null', async () => { + const { queryAllByText } = renderEventDashboard(mockWithoutTime); + await wait(); + expect(queryAllByText('Event Title').length).toBe(1); + }); +}); diff --git a/src/components/EventManagement/Dashboard/EventDashboard.tsx b/src/components/EventManagement/Dashboard/EventDashboard.tsx new file mode 100644 index 0000000000..84b0493198 --- /dev/null +++ b/src/components/EventManagement/Dashboard/EventDashboard.tsx @@ -0,0 +1,108 @@ +import React from 'react'; +import { Col, Row } from 'react-bootstrap'; +import styles from './EventDashboard.module.css'; +import { useTranslation } from 'react-i18next'; +import { EVENT_DETAILS } from 'GraphQl/Queries/Queries'; +import { useQuery } from '@apollo/client'; +import Loader from 'components/Loader/Loader'; + +const EventDashboard = (props: { eventId: string }): JSX.Element => { + const { eventId } = props; + const { t } = useTranslation('translation', { + keyPrefix: 'eventManagement', + }); + + const { data: eventData, loading: eventInfoLoading } = useQuery( + EVENT_DETAILS, + { + variables: { id: eventId }, + }, + ); + + if (eventInfoLoading) { + return ; + } + + function formatTime(timeString: string): string { + const [hours, minutes] = timeString.split(':').slice(0, 2); + return `${hours}:${minutes}`; + } + + function formatDate(dateString: string): string { + const date = new Date(dateString); + const day = date.getDate(); + const monthIndex = date.getMonth(); + const year = date.getFullYear(); + + const suffixes = ['th', 'st', 'nd', 'rd']; + const suffix = suffixes[day % 10] || suffixes[0]; + + const monthNames = [ + 'Jan', + 'Feb', + 'Mar', + 'Apr', + 'May', + 'Jun', + 'Jul', + 'Aug', + 'Sep', + 'Oct', + 'Nov', + 'Dec', + ]; + + const formattedDate = `${day}${suffix} ${monthNames[monthIndex]} ${year}`; + return formattedDate; + } + return ( +
    + + +
    +
    +
    +

    + + {eventData.event.startTime !== null + ? `${formatTime(eventData.event.startTime)}` + : ``} + {' '} + + {formatDate(eventData.event.startDate)}{' '} + +

    +

    {t('to')}

    +

    + + {' '} + {eventData.event.endTime !== null + ? `${formatTime(eventData.event.endTime)}` + : ``} + {' '} + + {formatDate(eventData.event.endDate)}{' '} + +

    +
    +

    {eventData.event.title}

    +

    + {eventData.event.description} +

    +

    + Location: {eventData.event.location} +

    +

    + Registrants:{' '} + {eventData.event.attendees.length} +

    +
    +
    +
    + +
    +
    + ); +}; + +export default EventDashboard; diff --git a/src/components/EventManagement/EventActionItems/EventActionItems.module.css b/src/components/EventManagement/EventActionItems/EventActionItems.module.css new file mode 100644 index 0000000000..a73fd82113 --- /dev/null +++ b/src/components/EventManagement/EventActionItems/EventActionItems.module.css @@ -0,0 +1,172 @@ +@media screen and (max-width: 575.5px) { + .mainpageright { + width: 98%; + } +} +.modalContent { + width: 670px; + max-width: 680px; +} +.dropdown { + background-color: white; + border: 1px solid #31bb6b; + position: relative; + display: inline-block; + margin-top: 10px; + margin-bottom: 10px; + color: #31bb6b; +} +.input { + flex: 1; + position: relative; +} + +.btnsContainer { + display: flex; + margin: 2.5rem 0 2.5rem 0; +} + +.btnsContainer .btnsBlock { + display: flex; +} + +.btnsContainer .btnsBlock button { + margin-left: 1rem; + display: flex; + justify-content: center; + align-items: center; +} + +.btnsContainer .input { + flex: 1; + position: relative; +} + +input { + outline: 1px solid var(--bs-gray-400); +} + +.btnsContainer .input button { + width: 52px; +} + +.inputField { + margin-top: 10px; + margin-bottom: 10px; + background-color: white; + box-shadow: 0 1px 1px #31bb6b; +} +.inputFieldModal { + margin-bottom: 10px; + background-color: white; + box-shadow: 0 1px 1px #31bb6b; +} +.inputField > button { + padding-top: 10px; + padding-bottom: 10px; +} +.TableImage { + object-fit: cover; + width: 50px !important; + height: 50px !important; + border-radius: 100% !important; +} +.tableHead { + background-color: #31bb6b !important; + color: white; + border-radius: 20px !important; + padding: 20px; + margin-top: 20px; +} + +.tableHead :nth-first-child() { + border-top-left-radius: 20px; +} + +.mainpageright > hr { + margin-top: 10px; + width: 100%; + margin-left: -15px; + margin-right: -15px; + margin-bottom: 20px; +} +.rowBackground { + background-color: var(--bs-white); +} +.tableHeader { + background-color: var(--bs-primary); + color: var(--bs-white); + font-size: 16px; +} +.addButton { + width: 7em; + position: absolute; + right: 1rem; + top: 1rem; +} + +.createModal { + margin-top: 20vh; + margin-left: 13vw; + max-width: 80vw; +} + +.icon { + transform: scale(1.5); + color: var(--bs-danger); + margin-bottom: 1rem; +} + +.message { + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; +} + +.titlemodal { + color: var(--bs-gray-600); + font-weight: 600; + font-size: 20px; + margin-top: 1rem; + width: 65%; +} + +.editDelBtns { + display: flex; + justify-content: space-around; +} + +.greenregbtn { + margin-bottom: 20px; + margin-left: 85%; +} + +.datatable { + margin-top: 5rem; +} + +.datediv { + display: flex; +} + +@-webkit-keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} +@keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} diff --git a/src/components/EventManagement/EventActionItems/EventActionItems.test.tsx b/src/components/EventManagement/EventActionItems/EventActionItems.test.tsx new file mode 100644 index 0000000000..ef69796da4 --- /dev/null +++ b/src/components/EventManagement/EventActionItems/EventActionItems.test.tsx @@ -0,0 +1,628 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { act, fireEvent, render, screen } from '@testing-library/react'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; +import EventActionItems from './EventActionItems'; +import { store } from 'state/store'; +import 'jest-location-mock'; +import { toast } from 'react-toastify'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { + CREATE_ACTION_ITEM_MUTATION, + UPDATE_ACTION_ITEM_MUTATION, + DELETE_ACTION_ITEM_MUTATION, +} from 'GraphQl/Mutations/ActionItemMutations'; +import { + ACTION_ITEM_CATEGORY_LIST, + MEMBERS_LIST, +} from 'GraphQl/Queries/Queries'; +import { ACTION_ITEM_LIST_BY_EVENTS } from 'GraphQl/Queries/ActionItemQueries'; + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +const MOCKS = [ + { + request: { + query: CREATE_ACTION_ITEM_MUTATION, + variables: { + assigneeId: '658930fd2caa9d8d6908745c', + actionItemCategoryId: '65f069a53b63ad266db32b3f', + eventId: '123', + preCompletionNotes: 'task to be done with high priority', + dueDate: '2024-04-05', + }, + }, + result: { + data: { + createActionItem: { + _id: 'newly_created_action_item_id', + }, + }, + }, + }, + { + request: { + query: UPDATE_ACTION_ITEM_MUTATION, + variables: { + actionItemId: '_6613ef741677gygwuyu', + assigneeId: '658930fd2caa9d8d6908745c', + preCompletionNotes: 'task to be done with high priority', + postCompletionNotes: 'Done', + dueDate: '2024-04-05', + completionDate: '2024-04-05', + isCompleted: false, + }, + }, + result: { + data: { + updateActionItem: { + _id: '_6613ef741677gygwuyu', + __typename: 'ActionItem', + }, + }, + }, + }, + { + request: { + query: DELETE_ACTION_ITEM_MUTATION, + variables: { + actionItemId: '_6613ef741677gygwuyu', + }, + }, + result: { + data: { + removeActionItem: { + _id: '_6613ef741677gygwuyu', + __typename: 'ActionItem', + }, + }, + }, + }, + { + request: { + query: ACTION_ITEM_CATEGORY_LIST, + variables: { + organizationId: '111', + }, + }, + result: { + data: { + actionItemCategoriesByOrganization: [ + { + _id: '65f069a53b63ad266db32b3f', + name: 'Default', + isDisabled: false, + __typename: 'ActionItemCategory', + }, + ], + }, + }, + }, + { + request: { + query: MEMBERS_LIST, + variables: { + id: '111', + }, + }, + result: { + data: { + organizations: [ + { + _id: '111', + members: [ + { + createdAt: '2023-04-13T04:53:17.742Z', + email: 'testuser4@example.com', + firstName: 'Teresa', + image: null, + lastName: 'Bradley', + organizationsBlockedBy: [], + __typename: 'User', + _id: '658930fd2caa9d8d6908745c', + }, + { + createdAt: '2024-04-13T04:53:17.742Z', + email: 'testuser2@example.com', + firstName: 'Anna', + image: null, + lastName: 'Bradley', + organizationsBlockedBy: [], + __typename: 'User', + _id: '658930fd2caa9d8d690sfhgush', + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: ACTION_ITEM_LIST_BY_EVENTS, + variables: { + eventId: '123', + }, + }, + result: { + data: { + actionItemsByEvent: [ + { + _id: '_6613ef741677gygwuyu', + actionItemCategory: { + __typename: 'ActionItemCategory', + _id: '65f069a53b63ad266db32b3j', + name: 'Default', + }, + assignee: { + __typename: 'User', + _id: '6589387e2caa9d8d69087485', + firstName: 'Burton', + lastName: 'Sanders', + }, + assigner: { + __typename: 'User', + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + assignmentDate: '2024-04-08', + completionDate: '2024-04-08', + creator: { + __typename: 'User', + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + dueDate: '2024-04-08', + event: { + __typename: 'Event', + _id: '123', + title: 'Adult Painting Lessons', + }, + isCompleted: false, + postCompletionNotes: 'Post Completion Note', + preCompletionNotes: 'Pre Completion Note', + }, + ], + }, + refetch: jest.fn(), + }, + }, +]; + +const CREATE_ACTION_ITEM_ERROR_MOCK = [ + { + request: { + query: CREATE_ACTION_ITEM_MUTATION, + variables: { + assigneeId: '658930fd2caa9d8d6908745c', + actionItemCategoryId: '65f069a53b63ad266db32b3f', + eventId: '123', + preCompletionNotes: 'task to be done with high priority', + dueDate: '2024-04-05', + }, + }, + result: { + data: { + createActionItem: { + _id: undefined, + }, + }, + }, + }, +]; + +const UPDATE_ACTION_ITEM_ERROR_MOCK = [ + { + request: { + query: ACTION_ITEM_LIST_BY_EVENTS, + variables: { + eventId: '123', + }, + }, + result: { + data: { + actionItemsByEvent: [ + { + _id: '_6613ef741677gygwuyu', + actionItemCategory: { + __typename: 'ActionItemCategory', + _id: '65f069a53b63ad266db32b3j', + name: 'Default', + }, + assignee: { + __typename: 'User', + _id: '6589387e2caa9d8d69087485', + firstName: 'Burton', + lastName: 'Sanders', + }, + assigner: { + __typename: 'User', + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + assignmentDate: '2024-04-08', + completionDate: '2024-04-08', + creator: { + __typename: 'User', + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + dueDate: '2024-04-08', + event: { + __typename: 'Event', + _id: '123', + title: 'Adult Painting Lessons', + }, + isCompleted: false, + postCompletionNotes: 'Post Completion Note', + preCompletionNotes: 'Pre Completion Note', + }, + ], + }, + refetch: jest.fn(), + }, + }, + { + request: { + query: UPDATE_ACTION_ITEM_MUTATION, + variables: { + actionItemId: '_6613ef741677gygwuyu', + assigneeId: '658930fd2caa9d8d6908745c', + preCompletionNotes: 'task to be done with high priority', + postCompletionNotes: 'Done', + dueDate: '2024-04-05', + completionDate: '2024-04-05', + isCompleted: false, + }, + }, + result: { + data: { + updateActionItem: { + _id: undefined, + __typename: 'ActionItem', + }, + }, + }, + }, +]; + +const NO_ACTION_ITEMs_ERROR_MOCK = [ + { + request: { + query: ACTION_ITEM_LIST_BY_EVENTS, + variables: { + eventId: '123', + }, + }, + result: { + data: { + actionItemsByEvent: [], + }, + refetch: jest.fn(), + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); +const link2 = new StaticMockLink(CREATE_ACTION_ITEM_ERROR_MOCK, true); +const link3 = new StaticMockLink(UPDATE_ACTION_ITEM_ERROR_MOCK, true); +const link4 = new StaticMockLink(NO_ACTION_ITEMs_ERROR_MOCK, true); + +const translations = JSON.parse( + JSON.stringify( + i18nForTest.getDataByLanguage('en')?.translation.eventActionItems, + ), +); + +describe('Event Action Items Page', () => { + test('Testing add new action item modal', async () => { + window.location.assign('/event/111/123'); + render( + + + + + + {} + + + + + , + ); + await wait(); + userEvent.click(screen.getByTestId('createEventActionItemBtn')); + + await wait(); + expect(screen.getByText('Action Item Details')).toBeInTheDocument(); + + const categoryDropdown = screen.getByTestId('formSelectActionItemCategory'); + userEvent.selectOptions(categoryDropdown, 'Default'); + + expect(categoryDropdown).toHaveValue('65f069a53b63ad266db32b3f'); + + const assigneeDropdown = screen.getByTestId('formSelectAssignee'); + userEvent.selectOptions(assigneeDropdown, 'Teresa Bradley'); + + expect(assigneeDropdown).toHaveValue('658930fd2caa9d8d6908745c'); + + fireEvent.change(screen.getByPlaceholderText('Notes'), { + target: { value: 'task to be done with high priority' }, + }); + expect(screen.getByPlaceholderText('Notes')).toHaveValue( + 'task to be done with high priority', + ); + + fireEvent.change(screen.getByLabelText('Due Date'), { + target: { value: '04/05/2024' }, + }); + expect(screen.getByLabelText('Due Date')).toHaveValue('04/05/2024'); + + userEvent.click(screen.getByTestId('createActionItemFormSubmitBtn')); + + await wait(); + + expect(toast.success).toBeCalledWith(translations.successfulCreation); + }); + + test('Display all the action items', async () => { + window.location.assign('/event/111/123'); + render( + + + + + + {} + + + + + , + ); + await wait(); + + expect(screen.getByText('#')).toBeInTheDocument(); + expect(screen.getByText('Assignee')).toBeInTheDocument(); + expect(screen.getByText('Action Item Category')).toBeInTheDocument(); + expect(screen.getByText('Notes')).toBeInTheDocument(); + expect(screen.getByText('Completion Notes')).toBeInTheDocument(); + + await wait(); + expect(screen.getByText('Burton Sanders')).toBeInTheDocument(); + expect(screen.getByText('Pre Completion Note')).toBeInTheDocument(); + const updateButtons = screen.getAllByText(/Manage Actions/i); + expect(updateButtons[0]).toBeInTheDocument(); + }); + + test('Testing update action item modal', async () => { + window.location.assign('/event/111/123'); + render( + + + + + + {} + + + + + , + ); + await wait(); + const updateButtons = screen.getAllByText(/Manage Actions/i); + userEvent.click(updateButtons[0]); + + expect(screen.getByText('Action Item Details')).toBeInTheDocument(); + + const assigneeDropdown = screen.getByTestId('formUpdateAssignee'); + userEvent.selectOptions(assigneeDropdown, 'Teresa Bradley'); + + expect(assigneeDropdown).toHaveValue('658930fd2caa9d8d6908745c'); + fireEvent.change(screen.getByPlaceholderText('Notes'), { + target: { value: 'task to be done with high priority' }, + }); + expect(screen.getByPlaceholderText('Notes')).toHaveValue( + 'task to be done with high priority', + ); + + fireEvent.change(screen.getByPlaceholderText('Post Completion Notes'), { + target: { value: 'Done' }, + }); + expect(screen.getByPlaceholderText('Post Completion Notes')).toHaveValue( + 'Done', + ); + + fireEvent.change(screen.getByLabelText('Due Date'), { + target: { value: '04/05/2024' }, + }); + expect(screen.getByLabelText('Due Date')).toHaveValue('04/05/2024'); + + fireEvent.change(screen.getByLabelText('Completion Date'), { + target: { value: '04/05/2024' }, + }); + expect(screen.getByLabelText('Completion Date')).toHaveValue('04/05/2024'); + + userEvent.click(screen.getByTestId('updateActionItemFormSubmitBtn')); + + await wait(); + + expect(toast.success).toBeCalledWith(translations.successfulUpdation); + }); + test('Testing delete action item modal and delete the record', async () => { + window.location.assign('/event/111/123'); + render( + + + + + + {} + + + + + , + ); + await wait(); + const updateButtons = screen.getAllByText(/Manage Actions/i); + userEvent.click(updateButtons[0]); + + expect(screen.getByText('Action Item Details')).toBeInTheDocument(); + + expect(screen.getByTestId('deleteActionItemBtn')).toBeInTheDocument(); + userEvent.click(screen.getByTestId('deleteActionItemBtn')); + await wait(); + expect( + screen.getByText('Do you want to remove this action item?'), + ).toBeInTheDocument(); + userEvent.click(screen.getByText('Yes')); + await wait(); + + expect(toast.success).toBeCalledWith(translations.successfulDeletion); + }); + + test('Testing delete action item modal and does not delete the record', async () => { + window.location.assign('/event/111/123'); + render( + + + + + + {} + + + + + , + ); + await wait(); + const updateButtons = screen.getAllByText(/Manage Actions/i); + userEvent.click(updateButtons[0]); + + expect(screen.getByText('Action Item Details')).toBeInTheDocument(); + + expect(screen.getByTestId('deleteActionItemBtn')).toBeInTheDocument(); + userEvent.click(screen.getByTestId('deleteActionItemBtn')); + await wait(); + expect( + screen.getByText('Do you want to remove this action item?'), + ).toBeInTheDocument(); + userEvent.click(screen.getByText('No')); + await wait(); + expect(screen.getByText('Teresa Bradley')).toBeInTheDocument(); + }); + + test('Raises an error when incorrect information is filled while creation', async () => { + window.location.assign('/event/111/123'); + render( + + + + + + {} + + + + + , + ); + await wait(); + userEvent.click(screen.getByTestId('createEventActionItemBtn')); + + await wait(); + expect(screen.getByText('Action Item Details')).toBeInTheDocument(); + + fireEvent.change(screen.getByPlaceholderText('Notes'), { + target: { value: 'task to be done with high priority' }, + }); + expect(screen.getByPlaceholderText('Notes')).toHaveValue( + 'task to be done with high priority', + ); + + fireEvent.change(screen.getByLabelText('Due Date'), { + target: { value: '04/05/2024' }, + }); + expect(screen.getByLabelText('Due Date')).toHaveValue('04/05/2024'); + + userEvent.click(screen.getByTestId('createActionItemFormSubmitBtn')); + await wait(); + + expect(toast.error).toBeCalled(); + }); + + test('Raises an error when incorrect information is filled while updation', async () => { + window.location.assign('/event/111/123'); + render( + + + + + + {} + + + + + , + ); + await wait(); + const updateButtons = screen.getAllByText(/Manage Actions/i); + userEvent.click(updateButtons[0]); + + expect(screen.getByText('Action Item Details')).toBeInTheDocument(); + + userEvent.click(screen.getByTestId('updateActionItemFormSubmitBtn')); + + await wait(); + + expect(toast.success).toBeCalledWith(translations.successfulUpdation); + + expect(toast.error).toBeCalled(); + }); + + test('Displays message when no data is available', async () => { + window.location.assign('/event/111/123'); + render( + + + + + + {} + + + + + , + ); + await wait(); + expect(screen.getByText('Nothing Found !!')).toBeInTheDocument(); + }); +}); diff --git a/src/components/EventManagement/EventActionItems/EventActionItems.tsx b/src/components/EventManagement/EventActionItems/EventActionItems.tsx new file mode 100644 index 0000000000..d23cfd3bee --- /dev/null +++ b/src/components/EventManagement/EventActionItems/EventActionItems.tsx @@ -0,0 +1,598 @@ +import { useMutation, useQuery } from '@apollo/client'; +import type { Dayjs } from 'dayjs'; +import dayjs from 'dayjs'; +import type { ChangeEvent } from 'react'; +import React, { useEffect, useState } from 'react'; +import { Button, Form } from 'react-bootstrap'; +import { useTranslation } from 'react-i18next'; +import { Link } from 'react-router-dom'; +import { toast } from 'react-toastify'; +import styles from './EventActionItems.module.css'; +import { DataGrid } from '@mui/x-data-grid'; +import type { GridColDef, GridCellParams } from '@mui/x-data-grid'; +import { Stack } from '@mui/material'; +import Modal from 'react-bootstrap/Modal'; +import { + CREATE_ACTION_ITEM_MUTATION, + DELETE_ACTION_ITEM_MUTATION, + UPDATE_ACTION_ITEM_MUTATION, +} from 'GraphQl/Mutations/ActionItemMutations'; +import type { + InterfaceActionItemCategoryList, + InterfaceMembersList, +} from 'utils/interfaces'; +import { DatePicker } from '@mui/x-date-pickers'; +import { + ACTION_ITEM_CATEGORY_LIST, + MEMBERS_LIST, +} from 'GraphQl/Queries/Queries'; +import { ACTION_ITEM_LIST_BY_EVENTS } from 'GraphQl/Queries/ActionItemQueries'; + +function eventActionItems(props: { eventId: string }): JSX.Element { + const { eventId } = props; + const { t } = useTranslation('translation', { + keyPrefix: 'eventActionItems', + }); + + const [actionItemCreateModalIsOpen, setActionItemCreateModalIsOpen] = + useState(false); + const [actionItemUpdateModalIsOpen, setActionItemUpdateModalIsOpen] = + useState(false); + const [actionItemDeleteModalIsOpen, setActionItemDeleteModalIsOpen] = + useState(false); + const [dueDate, setDueDate] = useState(new Date()); + const [completionDate, setCompletionDate] = useState(new Date()); + const [actionItemId, setActionItemId] = useState(''); + document.title = t('title'); + const url: string = window.location.href; + const startIdx: number = url.indexOf('/event/') + '/event/'.length; + const orgId: string = url.slice(startIdx, url.indexOf('/', startIdx)); + const [formState, setFormState] = useState({ + actionItemCategoryId: '', + assignee: '', + assigner: '', + assigneeId: '', + preCompletionNotes: '', + postCompletionNotes: '', + isCompleted: false, + }); + const showCreateModal = (): void => { + const newState = !actionItemCreateModalIsOpen; + setActionItemCreateModalIsOpen(newState); + }; + const hideCreateModal = (): void => { + setActionItemCreateModalIsOpen(!actionItemCreateModalIsOpen); + }; + const showUpdateModal = (): void => { + setActionItemUpdateModalIsOpen(!actionItemUpdateModalIsOpen); + }; + const hideUpdateModal = (): void => { + setActionItemId(''); + setActionItemUpdateModalIsOpen(!actionItemUpdateModalIsOpen); + }; + const toggleDeleteModal = (): void => { + setActionItemDeleteModalIsOpen(!actionItemDeleteModalIsOpen); + }; + const { + data: actionItemCategoriesData, + }: { + data: InterfaceActionItemCategoryList | undefined; + loading: boolean; + error?: Error | undefined; + } = useQuery(ACTION_ITEM_CATEGORY_LIST, { + variables: { + organizationId: orgId, + }, + }); + const actionItemCategories = + actionItemCategoriesData?.actionItemCategoriesByOrganization.filter( + (category) => !category.isDisabled, + ); + const { data: actionItemsData, refetch: actionItemsRefetch } = useQuery( + ACTION_ITEM_LIST_BY_EVENTS, + { + variables: { + eventId, + }, + }, + ); + const { + data: membersData, + }: { + data: InterfaceMembersList | undefined; + loading: boolean; + error?: Error | undefined; + } = useQuery(MEMBERS_LIST, { + variables: { id: orgId }, + }); + const [createActionItem] = useMutation(CREATE_ACTION_ITEM_MUTATION); + const createActionItemHandler = async ( + e: ChangeEvent, + ): Promise => { + e.preventDefault(); + try { + await createActionItem({ + variables: { + assigneeId: formState.assigneeId, + actionItemCategoryId: formState.actionItemCategoryId, + eventId, + preCompletionNotes: formState.preCompletionNotes, + dueDate: dayjs(dueDate).format('YYYY-MM-DD'), + }, + }); + setFormState({ + actionItemCategoryId: '', + assignee: '', + assigner: '', + assigneeId: '', + preCompletionNotes: '', + postCompletionNotes: '', + isCompleted: false, + }); + setDueDate(new Date()); + actionItemsRefetch(); + hideCreateModal(); + toast.success(t('successfulCreation')); + } catch (error: unknown) { + if (error instanceof Error) { + toast.error(error.message); + } + } + }; + useEffect(() => { + actionItemsRefetch({ + eventId, + }); + }, []); + const [updateActionItem] = useMutation(UPDATE_ACTION_ITEM_MUTATION); + const updateActionItemHandler = async ( + e: ChangeEvent, + ): Promise => { + e.preventDefault(); + try { + await updateActionItem({ + variables: { + actionItemId, + assigneeId: formState.assigneeId, + preCompletionNotes: formState.preCompletionNotes, + postCompletionNotes: formState.postCompletionNotes, + dueDate: dayjs(dueDate).format('YYYY-MM-DD'), + completionDate: dayjs(completionDate).format('YYYY-MM-DD'), + isCompleted: formState.isCompleted, + }, + }); + actionItemsRefetch(); + hideUpdateModal(); + toast.success(t('successfulUpdation')); + } catch (error: unknown) { + if (error instanceof Error) { + toast.error(error.message); + } + } + }; + const [removeActionItem] = useMutation(DELETE_ACTION_ITEM_MUTATION); + const deleteActionItemHandler = async (): Promise => { + await removeActionItem({ + variables: { + actionItemId, + }, + }); + actionItemsRefetch(); + toggleDeleteModal(); + hideUpdateModal(); + toast.success(t('successfulDeletion')); + }; + const columns: GridColDef[] = [ + { + field: 'serialNo', + headerName: '#', + flex: 1, + minWidth: 50, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return params.row?.index; + }, + }, + { + field: 'assignee', + headerName: 'Assignee', + flex: 2, + minWidth: 150, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return ( + + {params.row?.assignee.firstName + + ' ' + + params.row?.assignee.lastName} + + ); + }, + }, + { + field: 'actionItemCategory', + headerName: 'Action Item Category', + flex: 2, + minWidth: 100, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return params.row.actionItemCategory.name; + }, + }, + { + field: 'notes', + headerName: 'Notes', + minWidth: 150, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + flex: 2, + sortable: false, + renderCell: (params: GridCellParams) => { + return params.row.preCompletionNotes; + }, + }, + { + field: 'completionNotes', + headerName: 'Completion Notes', + minWidth: 150, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + flex: 2, + sortable: false, + renderCell: (params: GridCellParams) => { + return params.row.postCompletionNotes; + }, + }, + { + field: 'options', + headerName: 'Options', + flex: 2, + minWidth: 100, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return ( + + ); + }, + }, + ]; + return ( + <> + + {/* create action item modal */} + + +

    {t('actionItemDetails')}

    + +
    + +
    + + {t('actionItemCategory')} + + setFormState({ + ...formState, + actionItemCategoryId: e.target.value, + }) + } + > + + {actionItemCategories?.map((category, index) => ( + + ))} + + + + Assignee + + setFormState({ ...formState, assigneeId: e.target.value }) + } + > + + {membersData?.organizations[0].members?.map((member, index) => ( + + ))} + + + + { + setFormState({ + ...formState, + preCompletionNotes: e.target.value, + }); + }} + /> +
    + { + if (date) { + setDueDate(date?.toDate()); + } + }} + /> +
    + + +
    +
    + {/* update action items modal */} + + +

    {t('actionItemDetails')}

    + +
    + +
    + + Assignee + + setFormState({ ...formState, assigneeId: e.target.value }) + } + > + + {membersData?.organizations[0].members.map((member, index) => { + const currMemberName = `${member.firstName} ${member.lastName}`; + if (currMemberName !== formState.assignee) { + return ( + + ); + } + })} + + + + { + setFormState({ + ...formState, + preCompletionNotes: e.target.value, + }); + }} + /> + + { + setFormState({ + ...formState, + postCompletionNotes: e.target.value, + }); + }} + className="mb-2" + /> +

    +
    + { + if (date) { + setDueDate(date?.toDate()); + } + }} + /> +   + { + if (date) { + setCompletionDate(date?.toDate()); + } + }} + /> +
    +

    +
    + + + +
    + +
    +
    + {/* delete modal */} + + + + {t('deleteActionItem')} + + + {t('deleteActionItemMsg')} + + + + + + {actionItemsData && ( +
    + row._id} + components={{ + NoRowsOverlay: () => ( + + Nothing Found !! + + ), + }} + sx={{ + '&.MuiDataGrid-root .MuiDataGrid-cell:focus-within': { + outline: 'none !important', + }, + '&.MuiDataGrid-root .MuiDataGrid-columnHeader:focus-within': { + outline: 'none', + }, + '& .MuiDataGrid-row:hover': { + backgroundColor: 'transparent', + }, + '& .MuiDataGrid-row.Mui-hovered': { + backgroundColor: 'transparent', + }, + }} + getRowClassName={() => `${styles.rowBackground}`} + autoHeight + rowHeight={70} + rows={actionItemsData?.actionItemsByEvent?.map( + (item: object, index: number) => ({ + ...item, + index: index + 1, + }), + )} + columns={columns} + isRowSelectable={() => false} + /> +
    + )} + + ); +} +export default eventActionItems; diff --git a/src/components/EventProjectModals/AddEventProjectModal.test.tsx b/src/components/EventProjectModals/AddEventProjectModal.test.tsx deleted file mode 100644 index 1dd57e0d1e..0000000000 --- a/src/components/EventProjectModals/AddEventProjectModal.test.tsx +++ /dev/null @@ -1,132 +0,0 @@ -import React from 'react'; -import { fireEvent, render, waitFor } from '@testing-library/react'; -import { MockedProvider } from '@apollo/react-testing'; -import { AddEventProjectModal } from './AddEventProjectModal'; -import { ADD_EVENT_PROJECT_MUTATION } from 'GraphQl/Mutations/mutations'; -import { BrowserRouter } from 'react-router-dom'; -import { Provider } from 'react-redux'; -import { store } from 'state/store'; -import { I18nextProvider } from 'react-i18next'; -import i18nForTest from 'utils/i18nForTest'; -import { ToastContainer } from 'react-toastify'; - -const successfulMutationMock = [ - { - request: { - query: ADD_EVENT_PROJECT_MUTATION, - variables: { - title: 'Title', - description: 'Description', - eventId: '123', - }, - }, - result: { - data: { - createEventProject: { - _id: '456', - }, - }, - }, - }, -]; - -const unsuccessfulMutationMock = [ - { - request: { - query: ADD_EVENT_PROJECT_MUTATION, - variables: { - title: 'Title', - description: 'Description', - eventId: '123', - }, - }, - error: new Error('Oops'), - }, -]; - -describe('Testing Add Event Project Modal', () => { - const props = { - show: true, - eventId: '123', - handleClose: jest.fn(), - refetchData: jest.fn(), - }; - - test('The modal should be rendered and add button should not work with blank values', async () => { - const { queryByText, queryByLabelText } = render( - - - - - - - - - - - ); - - await waitFor(() => - expect(queryByText('Add an Event Project')).toBeInTheDocument() - ); - - fireEvent.click(queryByText('Create Project') as Element); - - // Check for blank entry warning modals - await waitFor(() => - expect(queryByText('Title cannot be empty!')).toBeInTheDocument() - ); - await waitFor(() => - expect(queryByText('Description cannot be empty!')).toBeInTheDocument() - ); - - // Type in the title and the description of the event project - fireEvent.change(queryByLabelText('Title') as Element, { - target: { value: 'Title' }, - }); - fireEvent.change(queryByLabelText('Description') as Element, { - target: { value: 'Description' }, - }); - - fireEvent.click(queryByText('Create Project') as Element); - - await waitFor(() => - expect(queryByText('Adding the project...')).toBeInTheDocument() - ); - - await waitFor(() => - expect(queryByText('Added the project successfully!')).toBeInTheDocument() - ); - }); - - test('The modal should be rendered and error message should be shown if mutation fails', async () => { - const { queryByText, queryByLabelText } = render( - - - - - - - - - - - ); - - // Type in the title and the description of the event project - fireEvent.change(queryByLabelText('Title') as Element, { - target: { value: 'Title' }, - }); - fireEvent.change(queryByLabelText('Description') as Element, { - target: { value: 'Description' }, - }); - - fireEvent.click(queryByText('Create Project') as Element); - - await waitFor(() => - expect( - queryByText('There was an error in adding the project!') - ).toBeInTheDocument() - ); - }); -}); diff --git a/src/components/EventProjectModals/AddEventProjectModal.tsx b/src/components/EventProjectModals/AddEventProjectModal.tsx deleted file mode 100644 index 10273b5e4f..0000000000 --- a/src/components/EventProjectModals/AddEventProjectModal.tsx +++ /dev/null @@ -1,99 +0,0 @@ -import React, { useState } from 'react'; -import { Modal, Button, Form } from 'react-bootstrap'; -import { toast } from 'react-toastify'; -import { useMutation } from '@apollo/client'; -import { ADD_EVENT_PROJECT_MUTATION } from 'GraphQl/Mutations/mutations'; - -type ModalPropType = { - show: boolean; - eventId: string; - handleClose: () => void; - refetchData: () => void; -}; - -export const AddEventProjectModal = ({ - show, - handleClose, - refetchData, - eventId, -}: ModalPropType): JSX.Element => { - const [title, setTitle] = useState(''); - const [description, setDescription] = useState(''); - - const [addMutation] = useMutation(ADD_EVENT_PROJECT_MUTATION); - - const notify = (e: React.FormEvent): Promise => { - e.preventDefault(); - return toast.promise(handleSubmit, { - pending: 'Adding the project...', - success: 'Added the project successfully!', - error: 'There was an error in adding the project!', - }); - }; - - const handleSubmit = async (): Promise => { - let toSubmit = true; - if (title.trim().length == 0) { - toast.error('Title cannot be empty!'); - toSubmit = false; - } - if (description.trim().length == 0) { - toast.error('Description cannot be empty!'); - toSubmit = false; - } - if (!toSubmit) return Promise.reject(); - await addMutation({ - variables: { - title, - description, - eventId, - }, - }); - refetchData(); - setTitle(''); - setDescription(''); - handleClose(); - }; - - return ( - <> - - - Add an Event Project - -
    - - - Title - setTitle(e.target.value)} - /> - - - - Description - setDescription(e.target.value)} - /> - - - - - -
    -
    - - ); -}; diff --git a/src/components/EventProjectModals/DeleteEventProjectModal.test.tsx b/src/components/EventProjectModals/DeleteEventProjectModal.test.tsx deleted file mode 100644 index 6a29735f2e..0000000000 --- a/src/components/EventProjectModals/DeleteEventProjectModal.test.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import React from 'react'; -import { fireEvent, render, waitFor } from '@testing-library/react'; -import { MockedProvider } from '@apollo/react-testing'; -import { DeleteEventProjectModal } from './DeleteEventProjectModal'; -import { DELETE_EVENT_PROJECT_MUTATION } from 'GraphQl/Mutations/mutations'; -import { BrowserRouter } from 'react-router-dom'; -import { Provider } from 'react-redux'; -import { store } from 'state/store'; -import { I18nextProvider } from 'react-i18next'; -import i18nForTest from 'utils/i18nForTest'; -import { ToastContainer } from 'react-toastify'; - -const successfulMutationMock = [ - { - request: { - query: DELETE_EVENT_PROJECT_MUTATION, - variables: { id: '123' }, - }, - result: { - data: { - removeEventProject: { - _id: '123', - }, - }, - }, - }, -]; - -const unsuccessfulMutationMock = [ - { - request: { - query: DELETE_EVENT_PROJECT_MUTATION, - variables: { id: '123' }, - }, - error: new Error('Oops'), - }, -]; - -describe('Testing Delete Event Project Modal', () => { - const props = { - show: true, - project: { - _id: '123', - title: 'Test Event Project', - description: 'Test Event Project Description', - }, - handleClose: jest.fn(), - refetchData: jest.fn(), - }; - - test('The modal should be rendered and delete button should work', async () => { - const { queryByText } = render( - - - - - - - - - - - ); - - await waitFor(() => - expect(queryByText('Delete Event Project')).toBeInTheDocument() - ); - - fireEvent.click(queryByText('Delete') as Element); - await waitFor(() => - expect(queryByText('Deleting the project...')).toBeInTheDocument() - ); - await waitFor(() => - expect( - queryByText('Deleted the project successfully!') - ).toBeInTheDocument() - ); - }); - - test('The modal should be rendered and error message should be shown if mutation fails', async () => { - const { queryByText } = render( - - - - - - - - - - - ); - - await waitFor(() => - expect(queryByText('Delete Event Project')).toBeInTheDocument() - ); - - fireEvent.click(queryByText('Delete') as Element); - await waitFor(() => - expect(queryByText('Deleting the project...')).toBeInTheDocument() - ); - await waitFor(() => - expect( - queryByText('There was an error in deleting the project details!') - ).toBeInTheDocument() - ); - }); -}); diff --git a/src/components/EventProjectModals/DeleteEventProjectModal.tsx b/src/components/EventProjectModals/DeleteEventProjectModal.tsx deleted file mode 100644 index 042e2fcd15..0000000000 --- a/src/components/EventProjectModals/DeleteEventProjectModal.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import React from 'react'; -import { Modal, Button } from 'react-bootstrap'; -import { toast } from 'react-toastify'; -import { useMutation } from '@apollo/client'; -import { DELETE_EVENT_PROJECT_MUTATION } from 'GraphQl/Mutations/mutations'; - -type ModalPropType = { - show: boolean; - project: { - _id: string; - title: string; - description: string; - }; - handleClose: () => void; - refetchData: () => void; -}; - -export const DeleteEventProjectModal = (props: ModalPropType): JSX.Element => { - const [deleteMutation] = useMutation(DELETE_EVENT_PROJECT_MUTATION); - - const notify = (): Promise => { - return toast.promise(deleteProject, { - pending: 'Deleting the project...', - success: 'Deleted the project successfully!', - error: 'There was an error in deleting the project details!', - }); - }; - const deleteProject = async (): Promise => { - await deleteMutation({ - variables: { - id: props.project._id, - }, - }); - - props.refetchData(); - props.handleClose(); - }; - - return ( - <> - - - Delete Event Project - - -
    - Are you sure you want to delete this? -
    -
    - - - - -
    - - ); -}; diff --git a/src/components/EventProjectModals/UpdateEventProjectModal.test.tsx b/src/components/EventProjectModals/UpdateEventProjectModal.test.tsx deleted file mode 100644 index b184b24f75..0000000000 --- a/src/components/EventProjectModals/UpdateEventProjectModal.test.tsx +++ /dev/null @@ -1,155 +0,0 @@ -import React from 'react'; -import { fireEvent, render, waitFor } from '@testing-library/react'; -import { MockedProvider } from '@apollo/react-testing'; -import { UpdateEventProjectModal } from './UpdateEventProjectModal'; -import { UPDATE_EVENT_PROJECT_MUTATION } from 'GraphQl/Mutations/mutations'; -import { BrowserRouter } from 'react-router-dom'; -import { Provider } from 'react-redux'; -import { store } from 'state/store'; -import { I18nextProvider } from 'react-i18next'; -import i18nForTest from 'utils/i18nForTest'; -import { ToastContainer } from 'react-toastify'; - -const successfulMutationMock = [ - { - request: { - query: UPDATE_EVENT_PROJECT_MUTATION, - variables: { - title: 'NewTitle', - description: 'NewDescription', - id: '123', - }, - }, - result: { - data: { - updateEventProject: { - _id: '123', - }, - }, - }, - }, -]; - -const unsuccessfulMutationMock = [ - { - request: { - query: UPDATE_EVENT_PROJECT_MUTATION, - variables: { - title: 'NewTitle', - description: 'NewDescription', - id: '123', - }, - }, - error: new Error('Oops'), - }, -]; - -describe('Testing Update Event Project Modal', () => { - const props = { - show: true, - project: { - title: 'OldTitle', - description: 'OldDescription', - _id: '123', - }, - handleClose: jest.fn(), - refetchData: jest.fn(), - }; - - test('The modal should be rendered, the default text should be added from the props and update button should not work with blank values', async () => { - const { queryByText, queryByLabelText } = render( - - - - - - - - - - - ); - - await waitFor(() => - expect(queryByText('Update Event Project')).toBeInTheDocument() - ); - - // Check for already populated values - await waitFor(() => - expect(queryByLabelText('Title')).toHaveValue('OldTitle') - ); - await waitFor(() => - expect(queryByLabelText('Description')).toHaveValue('OldDescription') - ); - - // Update the values to blank ones - // Type in the title and the description of the event project - fireEvent.change(queryByLabelText('Title') as Element, { - target: { value: '' }, - }); - fireEvent.change(queryByLabelText('Description') as Element, { - target: { value: '' }, - }); - - fireEvent.click(queryByText('Update Details') as Element); - - // Check for blank entry warning modals - await waitFor(() => - expect(queryByText('Title cannot be empty!')).toBeInTheDocument() - ); - await waitFor(() => - expect(queryByText('Description cannot be empty!')).toBeInTheDocument() - ); - - // Set the title and the description of the event project to new values - fireEvent.change(queryByLabelText('Title') as Element, { - target: { value: 'NewTitle' }, - }); - fireEvent.change(queryByLabelText('Description') as Element, { - target: { value: 'NewDescription' }, - }); - - fireEvent.click(queryByText('Update Details') as Element); - - await waitFor(() => - expect(queryByText('Updating the project...')).toBeInTheDocument() - ); - - await waitFor(() => - expect( - queryByText('Updated the project successfully!') - ).toBeInTheDocument() - ); - }); - - test('The modal should be rendered and error message should be shown if mutation fails', async () => { - const { queryByText, queryByLabelText } = render( - - - - - - - - - - - ); - - // Type in the title and the description of the event project - fireEvent.change(queryByLabelText('Title') as Element, { - target: { value: 'NewTitle' }, - }); - fireEvent.change(queryByLabelText('Description') as Element, { - target: { value: 'NewDescription' }, - }); - - fireEvent.click(queryByText('Update Details') as Element); - - await waitFor(() => - expect( - queryByText('There was an error in updating the project details!') - ).toBeInTheDocument() - ); - }); -}); diff --git a/src/components/EventProjectModals/UpdateEventProjectModal.tsx b/src/components/EventProjectModals/UpdateEventProjectModal.tsx deleted file mode 100644 index 08ac230c69..0000000000 --- a/src/components/EventProjectModals/UpdateEventProjectModal.tsx +++ /dev/null @@ -1,103 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import { Modal, Button, Form } from 'react-bootstrap'; -import { toast } from 'react-toastify'; -import { useMutation } from '@apollo/client'; -import { UPDATE_EVENT_PROJECT_MUTATION } from 'GraphQl/Mutations/mutations'; - -type ModalPropType = { - show: boolean; - project: { - _id: string; - title: string; - description: string; - }; - handleClose: () => void; - refetchData: () => void; -}; - -export const UpdateEventProjectModal = (props: ModalPropType): JSX.Element => { - const [title, setTitle] = useState(''); - const [description, setDescription] = useState(''); - - useEffect(() => { - setTitle(props.project.title); - setDescription(props.project.description); - }, [props.project]); - - const [updateMutation] = useMutation(UPDATE_EVENT_PROJECT_MUTATION); - const notify = (e: React.FormEvent): Promise => { - e.preventDefault(); - return toast.promise(handleSubmit, { - pending: 'Updating the project...', - success: 'Updated the project successfully!', - error: 'There was an error in updating the project details!', - }); - }; - const handleSubmit = async (): Promise => { - let toSubmit = true; - - if (title.trim().length == 0) { - toast.error('Title cannot be empty!'); - toSubmit = false; - } - if (description.trim().length == 0) { - toast.error('Description cannot be empty!'); - toSubmit = false; - } - if (!toSubmit) return Promise.reject(); - await updateMutation({ - variables: { - id: props.project._id, - title, - description, - }, - }); - props.refetchData(); - props.handleClose(); - }; - - return ( - <> - - - Update Event Project - -
    - - - Title - setTitle(e.target.value)} - /> - - - - Description - setDescription(e.target.value)} - /> - - - - - -
    -
    - - ); -}; diff --git a/src/components/EventRegistrantsModal/EventRegistrantsModal.test.tsx b/src/components/EventRegistrantsModal/EventRegistrantsModal.test.tsx index 3e06f784f4..597502ac8e 100644 --- a/src/components/EventRegistrantsModal/EventRegistrantsModal.test.tsx +++ b/src/components/EventRegistrantsModal/EventRegistrantsModal.test.tsx @@ -153,21 +153,21 @@ describe('Testing Event Registrants Modal', () => { - + , ); await waitFor(() => - expect(queryByText('Event Registrants')).toBeInTheDocument() + expect(queryByText('Event Registrants')).toBeInTheDocument(), ); await waitFor(() => - expect(queryByText('Registered Registrants')).toBeInTheDocument() + expect(queryByText('Registered Registrants')).toBeInTheDocument(), ); await waitFor(() => expect( - queryByText('There are no registered attendees for this event.') - ).toBeInTheDocument() + queryByText('There are no registered attendees for this event.'), + ).toBeInTheDocument(), ); // Get warning modal on blank button click @@ -175,8 +175,8 @@ describe('Testing Event Registrants Modal', () => { await waitFor(() => expect( - queryByText('Please choose an user to add first!') - ).toBeInTheDocument() + queryByText('Please choose an user to add first!'), + ).toBeInTheDocument(), ); // Choose a user to add as an attendee @@ -190,13 +190,13 @@ describe('Testing Event Registrants Modal', () => { fireEvent.click(queryByText('Add Registrant') as Element); await waitFor(() => - expect(queryByText('Adding the attendee...')).toBeInTheDocument() + expect(queryByText('Adding the attendee...')).toBeInTheDocument(), ); await waitFor(() => expect( - queryByText('Added the attendee successfully!') - ).toBeInTheDocument() + queryByText('Added the attendee successfully!'), + ).toBeInTheDocument(), ); }); @@ -220,13 +220,13 @@ describe('Testing Event Registrants Modal', () => { - + , ); await waitFor(() => expect( - queryByText('There are no registered attendees for this event.') - ).toBeInTheDocument() + queryByText('There are no registered attendees for this event.'), + ).toBeInTheDocument(), ); // Choose a user to add as an attendee @@ -240,13 +240,13 @@ describe('Testing Event Registrants Modal', () => { fireEvent.click(queryByText('Add Registrant') as Element); await waitFor(() => - expect(queryByText('Adding the attendee...')).toBeInTheDocument() + expect(queryByText('Adding the attendee...')).toBeInTheDocument(), ); await waitFor(() => expect( - queryByText('There was an error in adding the attendee!') - ).toBeInTheDocument() + queryByText('There was an error in adding the attendee!'), + ).toBeInTheDocument(), ); }); @@ -270,11 +270,11 @@ describe('Testing Event Registrants Modal', () => { - + , ); await waitFor(() => - expect(queryByText('Registered Registrants')).toBeInTheDocument() + expect(queryByText('Registered Registrants')).toBeInTheDocument(), ); await waitFor(() => expect(queryByText('John Doe')).toBeInTheDocument()); @@ -282,13 +282,13 @@ describe('Testing Event Registrants Modal', () => { fireEvent.click(queryByTestId('CancelIcon') as Element); await waitFor(() => - expect(queryByText('Removing the attendee...')).toBeInTheDocument() + expect(queryByText('Removing the attendee...')).toBeInTheDocument(), ); await waitFor(() => expect( - queryByText('Removed the attendee successfully!') - ).toBeInTheDocument() + queryByText('Removed the attendee successfully!'), + ).toBeInTheDocument(), ); }); @@ -312,11 +312,11 @@ describe('Testing Event Registrants Modal', () => { - + , ); await waitFor(() => - expect(queryByText('Registered Registrants')).toBeInTheDocument() + expect(queryByText('Registered Registrants')).toBeInTheDocument(), ); await waitFor(() => expect(queryByText('John Doe')).toBeInTheDocument()); @@ -324,13 +324,13 @@ describe('Testing Event Registrants Modal', () => { fireEvent.click(queryByTestId('CancelIcon') as Element); await waitFor(() => - expect(queryByText('Removing the attendee...')).toBeInTheDocument() + expect(queryByText('Removing the attendee...')).toBeInTheDocument(), ); await waitFor(() => expect( - queryByText('There was an error in removing the attendee!') - ).toBeInTheDocument() + queryByText('There was an error in removing the attendee!'), + ).toBeInTheDocument(), ); }); }); diff --git a/src/components/EventRegistrantsModal/EventRegistrantsModal.tsx b/src/components/EventRegistrantsModal/EventRegistrantsModal.tsx index a75c9d942d..0b3ef64d28 100644 --- a/src/components/EventRegistrantsModal/EventRegistrantsModal.tsx +++ b/src/components/EventRegistrantsModal/EventRegistrantsModal.tsx @@ -1,8 +1,7 @@ import React, { useState } from 'react'; import { Modal, Button } from 'react-bootstrap'; import { toast } from 'react-toastify'; -import { useMutation } from '@apollo/client'; -import { useQuery } from '@apollo/client'; +import { useMutation, useQuery } from '@apollo/client'; import { EVENT_ATTENDEES, MEMBERS_LIST } from 'GraphQl/Queries/Queries'; import { ADD_EVENT_ATTENDEE, @@ -111,7 +110,7 @@ export const EventRegistrantsModal = (props: ModalPropType): JSX.Element => { {attendeesData.event.attendees.length == 0 ? `There are no registered attendees for this event.` : null} - + {attendeesData.event.attendees.map((attendee: InterfaceUser) => ( { - + , ); // Open the modal fireEvent.click(queryByText('Show Registrants') as Element); await waitFor(() => - expect(queryByText('Event Registrants')).toBeInTheDocument() + expect(queryByText('Event Registrants')).toBeInTheDocument(), ); // Close the modal fireEvent.click(queryByRole('button', { name: /close/i }) as HTMLElement); await waitFor(() => - expect(queryByText('Event Registrants')).not.toBeInTheDocument() + expect(queryByText('Event Registrants')).not.toBeInTheDocument(), ); }); }); diff --git a/src/components/EventStats/EventStats.module.css b/src/components/EventStats/EventStats.module.css new file mode 100644 index 0000000000..44ba75a0a8 --- /dev/null +++ b/src/components/EventStats/EventStats.module.css @@ -0,0 +1,35 @@ +.stackEvents { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + margin: 10px 20px; + padding: 10px 20px; + overflow: hidden; + gap: 2px; + column-gap: 2px; +} + +@media screen and (min-width: 801px) { + .stackEvents { + flex-direction: row; + justify-content: space-between; + align-items: flex-start; + padding: 0 2rem; + margin: 0 40px; + gap: 5px; + column-gap: 4px; + } +} + +@media screen and (min-width: 768px) and (max-width: 800px) { + .stackEvents { + flex-direction: row; + justify-content: space-between; + align-items: flex-start; + padding: 0 2rem; + margin: 0 20px; + gap: 5px; + column-gap: 4px; + } +} diff --git a/src/components/EventStats/EventStats.test.tsx b/src/components/EventStats/EventStats.test.tsx index c02e0dd619..e2496fa5af 100644 --- a/src/components/EventStats/EventStats.test.tsx +++ b/src/components/EventStats/EventStats.test.tsx @@ -52,11 +52,11 @@ describe('Testing Event Stats', () => { - + , ); await waitFor(() => - expect(queryByText('Event Statistics')).toBeInTheDocument() + expect(queryByText('Event Statistics')).toBeInTheDocument(), ); }); }); diff --git a/src/components/EventStats/EventStats.tsx b/src/components/EventStats/EventStats.tsx index 6158c39075..c9f1a70e8d 100644 --- a/src/components/EventStats/EventStats.tsx +++ b/src/components/EventStats/EventStats.tsx @@ -3,8 +3,8 @@ import { Modal } from 'react-bootstrap'; import { FeedbackStats } from './Statistics/Feedback'; import { ReviewStats } from './Statistics/Review'; import { AverageRating } from './Statistics/AverageRating'; -import Stack from '@mui/material/Stack'; import styles from './Loader.module.css'; +import eventStatsStyles from './EventStats.module.css'; import { useQuery } from '@apollo/client'; import { EVENT_FEEDBACKS } from 'GraphQl/Queries/Queries'; @@ -44,14 +44,12 @@ export const EventStats = ({ Event Statistics - - - -
    - - -
    -
    + + +
    + + +
    diff --git a/src/components/EventStats/EventStatsWrapper.test.tsx b/src/components/EventStats/EventStatsWrapper.test.tsx index 726ffa2b43..0e64ac13cc 100644 --- a/src/components/EventStats/EventStatsWrapper.test.tsx +++ b/src/components/EventStats/EventStatsWrapper.test.tsx @@ -57,20 +57,20 @@ describe('Testing Event Stats Wrapper', () => { - + , ); // Open the modal fireEvent.click(queryByText('View Event Statistics') as Element); await waitFor(() => - expect(queryByText('Event Statistics')).toBeInTheDocument() + expect(queryByText('Event Statistics')).toBeInTheDocument(), ); // Close the modal fireEvent.click(queryByRole('button', { name: /close/i }) as HTMLElement); await waitFor(() => - expect(queryByText('Event Statistics')).not.toBeInTheDocument() + expect(queryByText('Event Statistics')).not.toBeInTheDocument(), ); }); }); diff --git a/src/components/EventStats/Statistics/AverageRating.test.tsx b/src/components/EventStats/Statistics/AverageRating.test.tsx index 53f0acacba..01cf6461e3 100644 --- a/src/components/EventStats/Statistics/AverageRating.test.tsx +++ b/src/components/EventStats/Statistics/AverageRating.test.tsx @@ -44,15 +44,15 @@ describe('Testing Average Rating Card', () => { - + , ); await waitFor(() => - expect(queryByText('Average Review Score')).toBeInTheDocument() + expect(queryByText('Average Review Score')).toBeInTheDocument(), ); await waitFor(() => - expect(queryByText('Rated 5.00 / 5')).toBeInTheDocument() + expect(queryByText('Rated 5.00 / 5')).toBeInTheDocument(), ); }); }); diff --git a/src/components/EventStats/Statistics/AverageRating.tsx b/src/components/EventStats/Statistics/AverageRating.tsx index a3769934d8..6dcfa03b3f 100644 --- a/src/components/EventStats/Statistics/AverageRating.tsx +++ b/src/components/EventStats/Statistics/AverageRating.tsx @@ -4,7 +4,6 @@ import Rating from '@mui/material/Rating'; import FavoriteIcon from '@mui/icons-material/Favorite'; import FavoriteBorderIcon from '@mui/icons-material/FavoriteBorder'; import Typography from '@mui/material/Typography'; -import { styled } from '@mui/material/styles'; type ModalPropType = { data: { @@ -22,16 +21,6 @@ type FeedbackType = { review: string | null; }; -// eslint-disable-next-line @typescript-eslint/naming-convention -const StyledRating = styled(Rating)({ - '& .MuiRating-iconFilled': { - color: '#ff6d75', - }, - '& .MuiRating-iconHover': { - color: '#ff3d47', - }, -}); - export const AverageRating = ({ data }: ModalPropType): JSX.Element => { return ( <> @@ -43,7 +32,7 @@ export const AverageRating = ({ data }: ModalPropType): JSX.Element => { Rated {data.event.averageFeedbackScore.toFixed(2)} / 5 - { icon={} size="medium" emptyIcon={} + sx={{ + '& .MuiRating-iconFilled': { + color: '#ff6d75', + }, + '& .MuiRating-iconHover': { + color: '#ff3d47', + }, + }} /> diff --git a/src/components/EventStats/Statistics/Feedback.test.tsx b/src/components/EventStats/Statistics/Feedback.test.tsx index 0a8b5a571d..9abdee4c57 100644 --- a/src/components/EventStats/Statistics/Feedback.test.tsx +++ b/src/components/EventStats/Statistics/Feedback.test.tsx @@ -61,18 +61,22 @@ describe('Testing Feedback Statistics Card', () => { - + , ); await waitFor(() => - expect(queryByText('Feedback Analysis')).toBeInTheDocument() + expect(queryByText('Feedback Analysis')).toBeInTheDocument(), ); await waitFor(() => expect( - queryByText('3 people have filled feedback for this event.') - ).toBeInTheDocument() + queryByText('3 people have filled feedback for this event.'), + ).toBeInTheDocument(), ); + + await waitFor(() => { + expect(queryByText('Test')).toBeInTheDocument(); + }); }); test('The component should be rendered and message should be shown if no feedback is present', async () => { @@ -84,17 +88,17 @@ describe('Testing Feedback Statistics Card', () => { - + , ); await waitFor(() => - expect(queryByText('Feedback Analysis')).toBeInTheDocument() + expect(queryByText('Feedback Analysis')).toBeInTheDocument(), ); await waitFor(() => expect( - queryByText('Please ask attendees to submit feedback for insights!') - ).toBeInTheDocument() + queryByText('Please ask attendees to submit feedback for insights!'), + ).toBeInTheDocument(), ); }); }); diff --git a/src/components/EventStats/Statistics/Feedback.tsx b/src/components/EventStats/Statistics/Feedback.tsx index ff4fe7a647..a4a9e41430 100644 --- a/src/components/EventStats/Statistics/Feedback.tsx +++ b/src/components/EventStats/Statistics/Feedback.tsx @@ -67,7 +67,8 @@ export const FeedbackStats = ({ data }: ModalPropType): JSX.Element => { series={[ { data: chartData, - arcLabel: (item) => `${item.id} (${item.value})`, + arcLabel: /* istanbul ignore next */ (item) => + `${item.id} (${item.value})`, innerRadius: 30, outerRadius: 120, paddingAngle: 2, diff --git a/src/components/EventStats/Statistics/Review.test.tsx b/src/components/EventStats/Statistics/Review.test.tsx index ee9f79c54c..9093444ab2 100644 --- a/src/components/EventStats/Statistics/Review.test.tsx +++ b/src/components/EventStats/Statistics/Review.test.tsx @@ -60,13 +60,13 @@ describe('Testing Review Statistics Card', () => { - + , ); await waitFor(() => expect(queryByText('Reviews')).toBeInTheDocument()); await waitFor(() => - expect(queryByText('Filled by 2 people.')).toBeInTheDocument() + expect(queryByText('Filled by 2 people.')).toBeInTheDocument(), ); await waitFor(() => expect(queryByText('review2')).toBeInTheDocument()); @@ -81,15 +81,15 @@ describe('Testing Review Statistics Card', () => { - + , ); await waitFor(() => expect(queryByText('Reviews')).toBeInTheDocument()); await waitFor(() => expect( - queryByText('Waiting for people to talk about the event...') - ).toBeInTheDocument() + queryByText('Waiting for people to talk about the event...'), + ).toBeInTheDocument(), ); }); }); diff --git a/src/components/EventStats/Statistics/Review.tsx b/src/components/EventStats/Statistics/Review.tsx index b5aecd61de..0afc687023 100644 --- a/src/components/EventStats/Statistics/Review.tsx +++ b/src/components/EventStats/Statistics/Review.tsx @@ -20,7 +20,7 @@ type FeedbackType = { export const ReviewStats = ({ data }: ModalPropType): JSX.Element => { const reviews = data.event.feedback.filter( - (feedback: FeedbackType) => feedback.review != null + (feedback: FeedbackType) => feedback.review != null, ); return ( diff --git a/src/components/HolidayCards/HolidayCard.module.css b/src/components/HolidayCards/HolidayCard.module.css new file mode 100644 index 0000000000..c7686ab870 --- /dev/null +++ b/src/components/HolidayCards/HolidayCard.module.css @@ -0,0 +1,12 @@ +.card { + background-color: #b4dcb7; + font-size: 14px; + font-weight: 400; + display: flex; + padding: 8px 4px; + border-radius: 5px; + margin-bottom: 4px; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; +} diff --git a/src/components/HolidayCards/HolidayCard.tsx b/src/components/HolidayCards/HolidayCard.tsx new file mode 100644 index 0000000000..0235659ee2 --- /dev/null +++ b/src/components/HolidayCards/HolidayCard.tsx @@ -0,0 +1,12 @@ +import React from 'react'; +import styles from './HolidayCard.module.css'; + +interface InterfaceHolidayList { + holidayName: string; +} +const HolidayCard = (props: InterfaceHolidayList): JSX.Element => { + /*istanbul ignore next*/ + return
    {props?.holidayName}
    ; +}; + +export default HolidayCard; diff --git a/src/components/IconComponent/IconComponent.test.tsx b/src/components/IconComponent/IconComponent.test.tsx index ff83ebe57c..e8faa75404 100644 --- a/src/components/IconComponent/IconComponent.test.tsx +++ b/src/components/IconComponent/IconComponent.test.tsx @@ -1,7 +1,6 @@ -import React from 'react'; import { render, screen } from '@testing-library/react'; import IconComponent from './IconComponent'; - +import React from 'react'; const screenTestIdMap: Record> = { Dashboard: { name: 'Dashboard', @@ -15,10 +14,18 @@ const screenTestIdMap: Record> = { name: 'Events', testId: 'Icon-Component-EventsIcon', }, + ActionItems: { + name: 'Action Items', + testId: 'Icon-Component-ActionItemIcon', + }, Posts: { name: 'Posts', testId: 'Icon-Component-PostsIcon', }, + Funds: { + name: 'Funds', + testId: 'Icon-Component-Funds', + }, BlockUnblock: { name: 'Block/Unblock', testId: 'Block/Icon-Component-UnblockIcon', @@ -32,12 +39,8 @@ const screenTestIdMap: Record> = { testId: 'Icon-Component-SettingsIcon', }, AllOrganizations: { - name: 'All Organizations', - testId: 'Icon-Component-AllOrganizationsIcon', - }, - EventProject: { - name: 'Add Event Project', - testId: 'Icon-Component-Add-Event-Project', + name: 'My Organizations', + testId: 'Icon-Component-MyOrganizationsIcon', }, ListEventRegistrant: { name: 'List Event Registrants', @@ -51,6 +54,14 @@ const screenTestIdMap: Record> = { name: 'Event Stats', testId: 'Icon-Component-Event-Stats', }, + Advertisement: { + name: 'Advertisement', + testId: 'Icon-Component-Advertisement', + }, + Venues: { + name: 'Venues', + testId: 'Icon-Component-Venues', + }, default: { name: 'default', testId: 'Icon-Component-DefaultIcon', @@ -62,7 +73,7 @@ describe('Testing Collapsible Dropdown component', () => { for (const component in screenTestIdMap) { render(); expect( - screen.getByTestId(screenTestIdMap[component].testId) + screen.getByTestId(screenTestIdMap[component].testId), ).toBeInTheDocument(); } }); diff --git a/src/components/IconComponent/IconComponent.tsx b/src/components/IconComponent/IconComponent.tsx index 4c490c9c94..d65982edef 100644 --- a/src/components/IconComponent/IconComponent.tsx +++ b/src/components/IconComponent/IconComponent.tsx @@ -1,17 +1,23 @@ -import React from 'react'; import { QuestionMarkOutlined } from '@mui/icons-material'; +import { ReactComponent as ActionItemIcon } from 'assets/svgs/actionItem.svg'; import { ReactComponent as BlockUserIcon } from 'assets/svgs/blockUser.svg'; +import { ReactComponent as CheckInRegistrantsIcon } from 'assets/svgs/checkInRegistrants.svg'; import { ReactComponent as DashboardIcon } from 'assets/svgs/dashboard.svg'; +import { ReactComponent as EventStatsIcon } from 'assets/svgs/eventStats.svg'; import { ReactComponent as EventsIcon } from 'assets/svgs/events.svg'; +import { ReactComponent as FundsIcon } from 'assets/svgs/funds.svg'; +import { ReactComponent as ListEventRegistrantsIcon } from 'assets/svgs/listEventRegistrants.svg'; import { ReactComponent as OrganizationsIcon } from 'assets/svgs/organizations.svg'; import { ReactComponent as PeopleIcon } from 'assets/svgs/people.svg'; import { ReactComponent as PluginsIcon } from 'assets/svgs/plugins.svg'; import { ReactComponent as PostsIcon } from 'assets/svgs/posts.svg'; import { ReactComponent as SettingsIcon } from 'assets/svgs/settings.svg'; -import { ReactComponent as AddEventProjectIcon } from 'assets/svgs/addEventProject.svg'; -import { ReactComponent as ListEventRegistrantsIcon } from 'assets/svgs/listEventRegistrants.svg'; -import { ReactComponent as CheckInRegistrantsIcon } from 'assets/svgs/checkInRegistrants.svg'; -import { ReactComponent as EventStatsIcon } from 'assets/svgs/eventStats.svg'; +import { ReactComponent as VenueIcon } from 'assets/svgs/venues.svg'; +import { ReactComponent as RequestsIcon } from 'assets/svgs/requests.svg'; +import { ReactComponent as HomeIcon } from 'assets/svgs/home.svg'; +import { ReactComponent as DonateIcon } from 'assets/svgs/donate.svg'; + +import React from 'react'; export interface InterfaceIconComponent { name: string; @@ -22,14 +28,32 @@ export interface InterfaceIconComponent { const iconComponent = (props: InterfaceIconComponent): JSX.Element => { switch (props.name) { + case 'My Organizations': + return ( + + ); case 'Dashboard': return ( ); case 'People': return ; + case 'Requests': + return ( + + ); case 'Events': return ; + case 'Action Items': + return ( + + ); case 'Posts': return ; case 'Block/Unblock': @@ -53,20 +77,6 @@ const iconComponent = (props: InterfaceIconComponent): JSX.Element => { data-testid="Icon-Component-SettingsIcon" /> ); - case 'All Organizations': - return ( - - ); - case 'Add Event Project': - return ( - - ); case 'List Event Registrants': return ( { /> ); case 'Advertisement': - return ; + return ( + + ); + case 'Funds': + return ( + + ); + case 'Venues': + return ( + + ); + case 'Home': + return ( + + ); + case 'Donate': + return ( + + ); default: return ( { + window.innerWidth = width; + fireEvent(window, new Event('resize')); }; -const propsReq: InterfaceLeftDrawerProps = { + +const propsOrg: InterfaceLeftDrawerProps = { ...props, - hideDrawer: false, - screenName: 'Requests', }; const propsUsers: InterfaceLeftDrawerProps = { ...props, hideDrawer: null, - screenName: 'Users', }; const MOCKS = [ @@ -52,11 +53,11 @@ jest.mock('react-toastify', () => ({ })); beforeEach(() => { - localStorage.setItem('FirstName', 'John'); - localStorage.setItem('LastName', 'Doe'); - localStorage.setItem( + setItem('FirstName', 'John'); + setItem('LastName', 'Doe'); + setItem( 'UserImage', - 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe' + 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', ); }); @@ -67,8 +68,11 @@ afterEach(() => { describe('Testing Left Drawer component for SUPERADMIN', () => { test('Component should be rendered properly', () => { - localStorage.setItem('UserImage', ''); - localStorage.setItem('UserType', 'SUPERADMIN'); + setItem('UserImage', ''); + setItem('UserImage', ''); + setItem('SuperAdmin', true); + setItem('FirstName', 'John'); + setItem('LastName', 'Doe'); render( @@ -76,107 +80,34 @@ describe('Testing Left Drawer component for SUPERADMIN', () => { - + , ); - expect(screen.getByText('Organizations')).toBeInTheDocument(); - expect(screen.getByText('Requests')).toBeInTheDocument(); + expect(screen.getByText('My Organizations')).toBeInTheDocument(); expect(screen.getByText('Users')).toBeInTheDocument(); + expect(screen.getByText('Community Profile')).toBeInTheDocument(); expect(screen.getByText('Talawa Admin Portal')).toBeInTheDocument(); - expect(screen.getByText(/John Doe/i)).toBeInTheDocument(); - expect(screen.getByText(/Superadmin/i)).toBeInTheDocument(); - expect(screen.getByAltText(/dummy picture/i)).toBeInTheDocument(); - const orgsBtn = screen.getByTestId(/orgsBtn/i); - const requestsBtn = screen.getByTestId(/requestsBtn/i); const rolesBtn = screen.getByTestId(/rolesBtn/i); + const communityProfileBtn = screen.getByTestId(/communityProfileBtn/i); + orgsBtn.click(); expect( - orgsBtn.className.includes('text-white btn btn-success') - ).toBeTruthy(); - expect( - requestsBtn.className.includes('text-secondary btn btn-light') + orgsBtn.className.includes('text-white btn btn-success'), ).toBeTruthy(); + expect(rolesBtn.className.includes('text-secondary btn')).toBeTruthy(); expect( - rolesBtn.className.includes('text-secondary btn btn-light') + communityProfileBtn.className.includes('text-secondary btn'), ).toBeTruthy(); - // Coming soon - userEvent.click(screen.getByTestId(/profileBtn/i)); - // Send to roles screen userEvent.click(rolesBtn); expect(global.window.location.pathname).toContain('/users'); - }); - - test('Testing in requests screen', () => { - localStorage.setItem('UserType', 'SUPERADMIN'); - render( - - - - - - - - ); - - const orgsBtn = screen.getByTestId(/orgsBtn/i); - - // Send to organizations screen - userEvent.click(orgsBtn); - expect(global.window.location.pathname).toContain('/orglist'); - }); - - test('Testing in roles screen', () => { - localStorage.setItem('UserType', 'SUPERADMIN'); - render( - - - - - - - - ); - - const orgsBtn = screen.getByTestId(/orgsBtn/i); - const requestsBtn = screen.getByTestId(/requestsBtn/i); - const rolesBtn = screen.getByTestId(/rolesBtn/i); - - expect( - orgsBtn.className.includes('text-secondary btn btn-light') - ).toBeTruthy(); - expect( - requestsBtn.className.includes('text-secondary btn btn-light') - ).toBeTruthy(); - expect( - rolesBtn.className.includes('text-white btn btn-success') - ).toBeTruthy(); - - // Send to requests screen - userEvent.click(requestsBtn); - expect(global.window.location.pathname).toContain('/requests'); - }); - - test('Testing Drawer open close functionality', () => { - localStorage.setItem('UserType', 'SUPERADMIN'); - render( - - - - - - - - ); - const closeModalBtn = screen.getByTestId(/closeModalBtn/i); - userEvent.click(closeModalBtn); + userEvent.click(communityProfileBtn); }); test('Testing Drawer when hideDrawer is null', () => { - localStorage.setItem('UserType', 'SUPERADMIN'); render( @@ -184,25 +115,27 @@ describe('Testing Left Drawer component for SUPERADMIN', () => { - + , ); }); - - test('Testing Drawer when hideDrawer is true', () => { - localStorage.setItem('UserType', 'SUPERADMIN'); + test('Testing Drawer when hideDrawer is false', () => { + const tempProps: InterfaceLeftDrawerProps = { + ...props, + hideDrawer: false, + }; render( - + - + , ); }); - test('Testing logout functionality', async () => { - localStorage.setItem('UserType', 'SUPERADMIN'); + test('Testing Drawer when the screen size is less than or equal to 820px', () => { + resizeWindow(800); render( @@ -210,17 +143,22 @@ describe('Testing Left Drawer component for SUPERADMIN', () => { - + , ); - userEvent.click(screen.getByTestId('logoutBtn')); - expect(localStorage.clear).toHaveBeenCalled(); - expect(global.window.location.pathname).toBe('/'); + expect(screen.getByText('My Organizations')).toBeInTheDocument(); + expect(screen.getByText('Talawa Admin Portal')).toBeInTheDocument(); + + const orgsBtn = screen.getByTestId(/orgsBtn/i); + + orgsBtn.click(); + expect( + orgsBtn.className.includes('text-white btn btn-success'), + ).toBeTruthy(); }); }); describe('Testing Left Drawer component for ADMIN', () => { test('Components should be rendered properly', () => { - localStorage.setItem('UserType', 'ADMIN'); render( @@ -228,30 +166,23 @@ describe('Testing Left Drawer component for ADMIN', () => { - + , ); - expect(screen.getByText('Organizations')).toBeInTheDocument(); + expect(screen.getByText('My Organizations')).toBeInTheDocument(); expect(screen.getByText('Talawa Admin Portal')).toBeInTheDocument(); - expect(screen.getByText(/John Doe/i)).toBeInTheDocument(); - expect(screen.getAllByText(/admin/i)).toHaveLength(2); - expect(screen.getByAltText(/profile picture/i)).toBeInTheDocument(); + expect(screen.getAllByText(/admin/i)).toHaveLength(1); const orgsBtn = screen.getByTestId(/orgsBtn/i); - + orgsBtn.click(); expect( - orgsBtn.className.includes('text-white btn btn-success') + orgsBtn.className.includes('text-white btn btn-success'), ).toBeTruthy(); // These screens arent meant for admins so they should not be present expect(screen.queryByTestId(/rolesBtn/i)).toBeNull(); - expect(screen.queryByTestId(/requestsBtn/i)).toBeNull(); - // Coming soon - userEvent.click(screen.getByTestId(/profileBtn/i)); - - // Send to roles screen userEvent.click(orgsBtn); expect(global.window.location.pathname).toContain('/orglist'); }); diff --git a/src/components/LeftDrawer/LeftDrawer.tsx b/src/components/LeftDrawer/LeftDrawer.tsx index d8708e2327..94d4974d0f 100644 --- a/src/components/LeftDrawer/LeftDrawer.tsx +++ b/src/components/LeftDrawer/LeftDrawer.tsx @@ -1,43 +1,32 @@ import React from 'react'; import Button from 'react-bootstrap/Button'; import { useTranslation } from 'react-i18next'; -import { useHistory } from 'react-router-dom'; -import { ReactComponent as AngleRightIcon } from 'assets/svgs/angleRight.svg'; -import { ReactComponent as LogoutIcon } from 'assets/svgs/logout.svg'; +import { NavLink } from 'react-router-dom'; import { ReactComponent as OrganizationsIcon } from 'assets/svgs/organizations.svg'; -import { ReactComponent as RequestsIcon } from 'assets/svgs/requests.svg'; import { ReactComponent as RolesIcon } from 'assets/svgs/roles.svg'; +import { ReactComponent as SettingsIcon } from 'assets/svgs/settings.svg'; import { ReactComponent as TalawaLogo } from 'assets/svgs/talawa.svg'; import styles from './LeftDrawer.module.css'; -import { useMutation } from '@apollo/client'; -import { REVOKE_REFRESH_TOKEN } from 'GraphQl/Mutations/mutations'; +import useLocalStorage from 'utils/useLocalstorage'; export interface InterfaceLeftDrawerProps { hideDrawer: boolean | null; setHideDrawer: React.Dispatch>; - screenName: string; } const leftDrawer = ({ - screenName, hideDrawer, setHideDrawer, }: InterfaceLeftDrawerProps): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'leftDrawer' }); - const userType = localStorage.getItem('UserType'); - const firstName = localStorage.getItem('FirstName'); - const lastName = localStorage.getItem('LastName'); - const userImage = localStorage.getItem('UserImage'); - const userId = localStorage.getItem('id'); - const history = useHistory(); + const { getItem } = useLocalStorage(); + const superAdmin = getItem('SuperAdmin'); - const [revokeRefreshToken] = useMutation(REVOKE_REFRESH_TOKEN); - - const logout = (): void => { - revokeRefreshToken(); - localStorage.clear(); - history.push('/'); + const handleLinkClick = (): void => { + if (window.innerWidth <= 820) { + setHideDrawer(true); + } }; return ( @@ -47,134 +36,86 @@ const leftDrawer = ({ hideDrawer === null ? styles.hideElemByDefault : hideDrawer - ? styles.inactiveDrawer - : styles.activeDrawer + ? styles.inactiveDrawer + : styles.activeDrawer }`} data-testid="leftDrawerContainer" > -

    {t('talawaAdminPortal')}

    -
    {t('menu')}
    +
    {t('menu')}
    -
    - {t('organizations')} - - {userType === 'SUPERADMIN' && ( - - )} - {userType === 'SUPERADMIN' && ( - + data-testid="orgsBtn" + > +
    + +
    + {t('my organizations')} + + )} + + {superAdmin && ( + <> + + {({ isActive }) => ( + + )} + + + {({ isActive }) => ( + + )} + + )}
    -
    - - - -
    ); diff --git a/src/components/LeftDrawerEvent/LeftDrawerEvent.test.tsx b/src/components/LeftDrawerEvent/LeftDrawerEvent.test.tsx deleted file mode 100644 index 3ce94b2a1d..0000000000 --- a/src/components/LeftDrawerEvent/LeftDrawerEvent.test.tsx +++ /dev/null @@ -1,243 +0,0 @@ -import React from 'react'; -import { render, screen, waitFor, fireEvent } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import 'jest-localstorage-mock'; -import { I18nextProvider } from 'react-i18next'; -import { BrowserRouter } from 'react-router-dom'; -import i18nForTest from 'utils/i18nForTest'; -import LeftDrawerEvent, { - type InterfaceLeftDrawerProps, -} from './LeftDrawerEvent'; -import { MockedProvider } from '@apollo/react-testing'; -import { EVENT_FEEDBACKS } from 'GraphQl/Queries/Queries'; -import { REVOKE_REFRESH_TOKEN } from 'GraphQl/Mutations/mutations'; - -const props: InterfaceLeftDrawerProps = { - event: { - _id: 'testEvent', - title: 'Test Event', - description: 'Test Description', - organization: { - _id: 'TestOrganization', - }, - }, - hideDrawer: false, - setHideDrawer: jest.fn(), - setShowAddEventProjectModal: jest.fn(), -}; -const props2: InterfaceLeftDrawerProps = { - event: { - _id: 'testEvent', - title: 'This is a very long event title that exceeds 20 characters', - description: - 'This is a very long event description that exceeds 30 characters. It contains more details about the event.', - organization: { - _id: 'Test Organization', - }, - }, - hideDrawer: false, - setHideDrawer: jest.fn(), - setShowAddEventProjectModal: jest.fn(), -}; - -const mocks = [ - { - request: { - query: REVOKE_REFRESH_TOKEN, - }, - result: {}, - }, - { - request: { - query: EVENT_FEEDBACKS, - variables: { - id: 'testEvent', - }, - }, - result: { - data: { - event: { - _id: 'testEvent', - feedback: [], - averageFeedbackScore: 5, - }, - }, - }, - }, -]; - -jest.mock('react-toastify', () => ({ - toast: { - success: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - }, -})); - -// Mock the modules for PieChart rendering as they require a trasformer being used (which is not done by Jest) -// They are required by the feedback statistics component -jest.mock('@mui/x-charts/PieChart', () => ({ - pieArcLabelClasses: jest.fn(), - PieChart: jest.fn().mockImplementation(() => <>Test), - pieArcClasses: jest.fn(), -})); - -beforeEach(() => { - localStorage.setItem('FirstName', 'John'); - localStorage.setItem('LastName', 'Doe'); - localStorage.setItem( - 'UserImage', - 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe' - ); -}); - -afterEach(() => { - jest.clearAllMocks(); - localStorage.clear(); -}); - -describe('Testing Left Drawer component for the Event Dashboard', () => { - test('Component should be rendered properly', async () => { - localStorage.setItem('UserImage', ''); - localStorage.setItem('UserType', 'SUPERADMIN'); - - const { queryByText } = render( - - - - - - - - ); - - await waitFor(() => - expect(queryByText('Talawa Admin Portal')).toBeInTheDocument() - ); - await waitFor(() => expect(queryByText('Test Event')).toBeInTheDocument()); - await waitFor(() => - expect(queryByText('Test Description')).toBeInTheDocument() - ); - await waitFor(() => - expect(queryByText('Event Options')).toBeInTheDocument() - ); - }); - - test('Add Event Project button and profile page button should work properly', async () => { - localStorage.setItem('UserType', 'SUPERADMIN'); - - const { queryByText, queryByTestId } = render( - - - - - - - - ); - - await waitFor(() => - expect(queryByText('Talawa Admin Portal')).toBeInTheDocument() - ); - - fireEvent.click(queryByText('Add an Event Project') as HTMLElement); - expect(props.setShowAddEventProjectModal).toHaveBeenCalled(); - - fireEvent.click(queryByTestId(/profileBtn/i) as HTMLElement); - }); - - test('Testing Drawer when hideDrawer is null', () => { - localStorage.setItem('UserType', 'SUPERADMIN'); - render( - - - - - - - - ); - }); - - test('Testing Drawer when hideDrawer is true', () => { - localStorage.setItem('UserType', 'SUPERADMIN'); - render( - - - - - - - - ); - }); - - test('Testing Drawer open close functionality', () => { - localStorage.setItem('UserType', 'SUPERADMIN'); - render( - - - - - - - - ); - const closeModalBtn = screen.getByTestId(/closeModalBtn/i); - userEvent.click(closeModalBtn); - }); - - test('Testing logout functionality', async () => { - localStorage.setItem('UserType', 'SUPERADMIN'); - render( - - - - - - - - ); - - userEvent.click(screen.getByTestId('logoutBtn')); - expect(localStorage.clear).toHaveBeenCalled(); - expect(global.window.location.pathname).toBe('/'); - }); - test('Testing substring functionality in event title and description', async () => { - localStorage.setItem('UserType', 'SUPERADMIN'); - render( - - - - - - - - ); - const eventTitle = props2.event.title; - expect(eventTitle.length).toBeGreaterThan(20); - const eventDescription = props2.event.description; - expect(eventDescription.length).toBeGreaterThan(30); - const truncatedEventTitle = eventTitle.substring(0, 20) + '...'; - const truncatedEventDescription = eventDescription.substring(0, 30) + '...'; - expect(truncatedEventTitle).toContain('...'); - expect(truncatedEventDescription).toContain('...'); - }); - test('Testing all events button', async () => { - localStorage.setItem('UserType', 'SUPERADMIN'); - render( - - - - - - - - ); - - userEvent.click(screen.getByTestId('allEventsBtn')); - expect(global.window.location.pathname).toBe( - `/orgevents/id=${props.event.organization._id}` - ); - }); -}); diff --git a/src/components/LeftDrawerEvent/LeftDrawerEvent.tsx b/src/components/LeftDrawerEvent/LeftDrawerEvent.tsx deleted file mode 100644 index 795f6016cb..0000000000 --- a/src/components/LeftDrawerEvent/LeftDrawerEvent.tsx +++ /dev/null @@ -1,199 +0,0 @@ -import React from 'react'; -import Button from 'react-bootstrap/Button'; -import { useHistory } from 'react-router-dom'; -import { ReactComponent as AngleRightIcon } from 'assets/svgs/angleRight.svg'; -import { ReactComponent as LogoutIcon } from 'assets/svgs/logout.svg'; -import { ReactComponent as TalawaLogo } from 'assets/svgs/talawa.svg'; -import styles from './LeftDrawerEvent.module.css'; -import IconComponent from 'components/IconComponent/IconComponent'; -import { EventRegistrantsWrapper } from 'components/EventRegistrantsModal/EventRegistrantsWrapper'; -import { CheckInWrapper } from 'components/CheckIn/CheckInWrapper'; -import { EventStatsWrapper } from 'components/EventStats/EventStatsWrapper'; -import { REVOKE_REFRESH_TOKEN } from 'GraphQl/Mutations/mutations'; -import { useMutation } from '@apollo/client'; - -export interface InterfaceLeftDrawerProps { - event: { - _id: string; - title: string; - description: string; - organization: { - _id: string; - }; - }; - hideDrawer: boolean | null; - setHideDrawer: React.Dispatch>; - setShowAddEventProjectModal: React.Dispatch>; -} - -const leftDrawerEvent = ({ - event, - hideDrawer, - setHideDrawer, - setShowAddEventProjectModal, -}: InterfaceLeftDrawerProps): JSX.Element => { - const [revokeRefreshToken] = useMutation(REVOKE_REFRESH_TOKEN); - const userType = localStorage.getItem('UserType'); - const firstName = localStorage.getItem('FirstName'); - const lastName = localStorage.getItem('LastName'); - const userImage = localStorage.getItem('UserImage'); - const userId = localStorage.getItem('id'); - - const history = useHistory(); - const logout = (): void => { - revokeRefreshToken(); - localStorage.clear(); - history.push('/'); - }; - - return ( - <> -
    - {/* Close Drawer Button for small devices */} - - - {/* Branding Section */} -
    - - Talawa Admin Portal -
    - - {/* Event Detail Section */} -
    - -
    - - {/* Options List */} -
    -
    Event Options
    - - - - - -
    - - {/* Profile Section & Logout Btn */} -
    - - -
    -
    - - ); -}; - -export default leftDrawerEvent; diff --git a/src/components/LeftDrawerEvent/LeftDrawerEventWrapper.module.css b/src/components/LeftDrawerEvent/LeftDrawerEventWrapper.module.css deleted file mode 100644 index 681ac8823d..0000000000 --- a/src/components/LeftDrawerEvent/LeftDrawerEventWrapper.module.css +++ /dev/null @@ -1,60 +0,0 @@ -.pageContainer { - display: flex; - flex-direction: column; - min-height: 100vh; - padding: 1rem 1.5rem 0 calc(300px + 2rem + 1.5rem); -} - -.expand { - padding-left: 1.5rem; - animation: moveLeft 0.5s ease-in-out; -} - -.contract { - padding-left: calc(300px + 2rem + 1.5rem); - animation: moveRight 0.5s ease-in-out; -} - -@media (max-width: 1120px) { - .contract { - padding-left: calc(250px + 2rem + 1.5rem); - } -} - -/* For tablets */ -@media (max-width: 820px) { - .pageContainer { - padding-left: 1.5rem; - } - - .contract, - .expand { - animation: none; - } -} - -@media (max-width: 820px) { - .pageContainer { - padding: 1rem; - } -} - -@keyframes moveLeft { - from { - padding-left: calc(300px + 2rem + 1.5rem); - } - - to { - padding-left: 1.5rem; - } -} - -@keyframes moveRight { - from { - padding-left: 1.5rem; - } - - to { - padding-left: calc(300px + 2rem + 1.5rem); - } -} diff --git a/src/components/LeftDrawerEvent/LeftDrawerEventWrapper.test.tsx b/src/components/LeftDrawerEvent/LeftDrawerEventWrapper.test.tsx deleted file mode 100644 index 72093aaf06..0000000000 --- a/src/components/LeftDrawerEvent/LeftDrawerEventWrapper.test.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import React from 'react'; -import 'jest-localstorage-mock'; -import { render, waitFor, fireEvent } from '@testing-library/react'; -import { I18nextProvider } from 'react-i18next'; -import { BrowserRouter } from 'react-router-dom'; -import i18nForTest from 'utils/i18nForTest'; -import { - type InterfacePropType, - LeftDrawerEventWrapper, -} from './LeftDrawerEventWrapper'; -import { MockedProvider } from '@apollo/react-testing'; -import { EVENT_FEEDBACKS } from 'GraphQl/Queries/Queries'; - -const props: InterfacePropType = { - event: { - _id: 'testEvent', - title: 'Test Event', - description: 'Test Description', - organization: { - _id: 'Test Organization', - }, - }, - setShowAddEventProjectModal: jest.fn(), - children: null, -}; - -const mocks = [ - { - request: { - query: EVENT_FEEDBACKS, - variables: { - id: 'testEvent', - }, - }, - result: { - data: { - event: { - _id: 'testEvent', - feedback: [], - averageFeedbackScore: 5, - }, - }, - }, - }, -]; - -jest.mock('react-toastify', () => ({ - toast: { - success: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - }, -})); - -// Mock the modules for PieChart rendering as they require a trasformer being used (which is not done by Jest) -// They are required by the feedback statistics component -jest.mock('@mui/x-charts/PieChart', () => ({ - pieArcLabelClasses: jest.fn(), - PieChart: jest.fn().mockImplementation(() => <>Test), - pieArcClasses: jest.fn(), -})); - -beforeEach(() => { - localStorage.setItem('FirstName', 'John'); - localStorage.setItem('LastName', 'Doe'); - localStorage.setItem( - 'UserImage', - 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe' - ); -}); - -afterEach(() => { - jest.clearAllMocks(); - localStorage.clear(); -}); - -describe('Testing Left Drawer Wrapper component for the Event Dashboard', () => { - test('Component should be rendered properly and the close menu button should function', async () => { - const { queryByText, queryByTestId } = render( - - - - - - - - ); - - await waitFor(() => - expect(queryByText('Event Management')).toBeInTheDocument() - ); - fireEvent.click(queryByTestId('closeLeftDrawerBtn') as HTMLElement); - }); -}); diff --git a/src/components/LeftDrawerEvent/LeftDrawerEventWrapper.tsx b/src/components/LeftDrawerEvent/LeftDrawerEventWrapper.tsx deleted file mode 100644 index 1b1157385c..0000000000 --- a/src/components/LeftDrawerEvent/LeftDrawerEventWrapper.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import MenuIcon from '@mui/icons-material/Menu'; -import LeftDrawerEvent from './LeftDrawerEvent'; -import React, { useState } from 'react'; -import Button from 'react-bootstrap/Button'; -import styles from './LeftDrawerEventWrapper.module.css'; - -export interface InterfacePropType { - event: { - _id: string; - title: string; - description: string; - organization: { - _id: string; - }; - }; - setShowAddEventProjectModal: React.Dispatch>; - children: React.ReactNode; -} - -export const LeftDrawerEventWrapper = ( - props: InterfacePropType -): JSX.Element => { - const [hideDrawer, setHideDrawer] = useState(null); - - return ( - <> - - -
    -
    -
    -

    Event Management

    -
    - -
    - {props.children} -
    - - ); -}; diff --git a/src/components/LeftDrawerOrg/LeftDrawerOrg.module.css b/src/components/LeftDrawerOrg/LeftDrawerOrg.module.css index 399a7cb4ef..b300eb7e89 100644 --- a/src/components/LeftDrawerOrg/LeftDrawerOrg.module.css +++ b/src/components/LeftDrawerOrg/LeftDrawerOrg.module.css @@ -1,5 +1,6 @@ .leftDrawer { width: calc(300px + 2rem); + min-height: 100%; position: fixed; top: 0; bottom: 0; @@ -9,23 +10,7 @@ padding: 0.8rem 1rem 0 1rem; background-color: var(--bs-white); transition: 0.5s; - overflow-y: scroll; -} - -.leftDrawer::-webkit-scrollbar { - width: 6px; -} - -.leftDrawer::-webkit-scrollbar-track { - background: #f1f1f1; -} - -.leftDrawer::-webkit-scrollbar-thumb { - background: var(--bs-gray-500); -} - -.leftDrawer::-webkit-scrollbar-thumb:hover { - background: var(--bs-gray-600); + font-family: var(--bs-leftDrawer-font-family); } .activeDrawer { @@ -45,10 +30,6 @@ animation: goToLeftBigScreen 0.5s ease-in-out; } -.leftDrawer .closeModalBtn { - display: none; -} - .leftDrawer .brandingContainer { display: flex; justify-content: flex-start; @@ -57,26 +38,30 @@ .leftDrawer .organizationContainer button { position: relative; - margin: 1.25rem 0; + margin: 0.7rem 0; padding: 2.5rem 0.1rem; - border-radius: 0.5rem; - border: 1px solid var(--bs-gray-300); - background-color: var(--bs-gray-100); + border-radius: 16px; } .leftDrawer .talawaLogo { - width: 42px; - height: 42px; - margin-right: 0.5rem; + width: 50px; + height: 50px; + margin-right: 0.3rem; } .leftDrawer .talawaText { - font-size: 1.1rem; + font-size: 18px; + font-weight: 500; } .leftDrawer .titleHeader { - margin-bottom: 1rem; font-weight: 600; + margin: 0.6rem 0rem; +} + +.leftDrawer .optionList { + height: 100%; + overflow-y: auto; } .leftDrawer .optionList button { @@ -85,8 +70,12 @@ width: 100%; text-align: start; margin-bottom: 0.8rem; - border: 1px solid var(--bs-gray-200); - border-radius: 8px; + border-radius: 16px; + font-size: 16px; + padding: 0.6rem; + padding-left: 0.8rem; + outline: none; + border: none; } .leftDrawer button .iconWrapper { @@ -95,6 +84,7 @@ .leftDrawer .optionList .collapseBtn { height: 48px; + border: none; } .leftDrawer button .iconWrapperSm { @@ -104,24 +94,28 @@ align-items: center; } +.leftDrawer .organizationContainer .profileContainer { + background-color: #31bb6b33; + padding-right: 10px; +} + .leftDrawer .profileContainer { border: none; width: 100%; - margin-top: 5rem; height: 52px; - border-radius: 8px; - background-color: var(--bs-white); + border-radius: 16px; display: flex; align-items: center; + background-color: var(--bs-white); } .leftDrawer .profileContainer:focus { outline: none; - background-color: var(--bs-gray-100); } .leftDrawer .imageContainer { width: 68px; + margin-right: 8px; } .leftDrawer .profileContainer img { @@ -133,11 +127,18 @@ .leftDrawer .profileContainer .profileText { flex: 1; text-align: start; + overflow: hidden; } .leftDrawer .profileContainer .profileText .primaryText { font-size: 1.1rem; font-weight: 600; + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 2; /* number of lines to show */ + -webkit-box-orient: vertical; + word-wrap: break-word; + white-space: normal; } .leftDrawer .profileContainer .profileText .secondaryText { @@ -156,6 +157,72 @@ } /* For tablets */ +@media (max-height: 900px) { + .leftDrawer { + width: calc(300px + 1rem); + } + .leftDrawer .talawaLogo { + width: 38px; + height: 38px; + margin-right: 0.4rem; + } + .leftDrawer .talawaText { + font-size: 1rem; + } + .leftDrawer .organizationContainer button { + margin: 0.6rem 0; + padding: 2.2rem 0.1rem; + } + .leftDrawer .optionList button { + margin-bottom: 0.05rem; + font-size: 16px; + padding-left: 0.8rem; + } + .leftDrawer .profileContainer .profileText .primaryText { + font-size: 1rem; + } + .leftDrawer .profileContainer .profileText .secondaryText { + font-size: 0.8rem; + } +} +@media (max-height: 650px) { + .leftDrawer { + padding: 0.5rem 0.8rem 0 0.8rem; + width: calc(250px); + } + .leftDrawer .talawaText { + font-size: 0.8rem; + } + .leftDrawer .organizationContainer button { + margin: 0.2rem 0; + padding: 1.6rem 0rem; + } + .leftDrawer .titleHeader { + font-size: 16px; + } + .leftDrawer .optionList button { + margin-bottom: 0.05rem; + font-size: 14px; + padding: 0.4rem; + padding-left: 0.8rem; + } + .leftDrawer .profileContainer .profileText .primaryText { + font-size: 0.8rem; + } + .leftDrawer .profileContainer .profileText .secondaryText { + font-size: 0.6rem; + } + .leftDrawer .imageContainer { + width: 40px; + margin-left: 5px; + margin-right: 12px; + } + .leftDrawer .imageContainer img { + width: 40px; + height: 100%; + } +} + @media (max-width: 820px) { .hideElemByDefault { display: none; @@ -167,27 +234,21 @@ right: 0; } - .leftDrawer .closeModalBtn { - display: block; - position: absolute; - top: 1rem; - right: 1rem; - z-index: 10; - } - - /* For smaller devices .activeDrawer in real behaves like inactive */ - .activeDrawer { + .inactiveDrawer { opacity: 0; left: 0; z-index: -1; - animation: closeDrawer 0.4s ease-in-out; + animation: closeDrawer 0.2s ease-in-out; } - /* For smaller devices .inactiveDrawer in real behaves like active */ - .inactiveDrawer { + .activeDrawer { display: flex; z-index: 100; - animation: openDrawer 0.6s ease-in-out; + animation: openDrawer 0.4s ease-in-out; + } + + .logout { + margin-bottom: 2.5rem; } } diff --git a/src/components/LeftDrawerOrg/LeftDrawerOrg.test.tsx b/src/components/LeftDrawerOrg/LeftDrawerOrg.test.tsx index 101f4133e2..9bd2ffd1d9 100644 --- a/src/components/LeftDrawerOrg/LeftDrawerOrg.test.tsx +++ b/src/components/LeftDrawerOrg/LeftDrawerOrg.test.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { render, screen } from '@testing-library/react'; +import { fireEvent, render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import 'jest-localstorage-mock'; import { I18nextProvider } from 'react-i18next'; @@ -15,9 +15,11 @@ import { ORGANIZATIONS_LIST } from 'GraphQl/Queries/Queries'; import { act } from 'react-dom/test-utils'; import { StaticMockLink } from 'utils/StaticMockLink'; import { REVOKE_REFRESH_TOKEN } from 'GraphQl/Mutations/mutations'; +import useLocalStorage from 'utils/useLocalstorage'; + +const { setItem } = useLocalStorage(); const props: InterfaceLeftDrawerProps = { - screenName: 'Dashboard', orgId: '123', targets: [ { @@ -68,7 +70,11 @@ const MOCKS = [ request: { query: REVOKE_REFRESH_TOKEN, }, - result: {}, + result: { + data: { + revokeRefreshTokenForUser: true, + }, + }, }, { request: { @@ -88,8 +94,17 @@ const MOCKS = [ }, name: 'Test Organization', description: 'Testing this organization', - location: 'Gotham, DC', - isPublic: true, + address: { + city: 'Delhi', + countryCode: 'IN', + dependentLocality: 'Some Dependent Locality', + line1: '123 Random Street', + line2: 'Apartment 456', + postalCode: '110001', + sortingCode: 'ABC-123', + state: 'Delhi', + }, + userRegistrationRequired: true, visibleInSearch: true, members: [ { @@ -111,6 +126,7 @@ const MOCKS = [ firstName: 'John', lastName: 'Doe', email: 'JohnDoe@example.com', + createdAt: '12-03-2024', }, ], membershipRequests: [], @@ -142,8 +158,17 @@ const MOCKS_WITH_IMAGE = [ }, name: 'Test Organization', description: 'Testing this organization', - location: 'Gotham, DC', - isPublic: true, + address: { + city: 'Delhi', + countryCode: 'IN', + dependentLocality: 'Some Dependent Locality', + line1: '123 Random Street', + line2: 'Apartment 456', + postalCode: '110001', + sortingCode: 'ABC-123', + state: 'Delhi', + }, + userRegistrationRequired: true, visibleInSearch: true, members: [ { @@ -165,6 +190,7 @@ const MOCKS_WITH_IMAGE = [ firstName: 'John', lastName: 'Doe', email: 'JohnDoe@example.com', + createdAt: '12-03-2024', }, ], membershipRequests: [], @@ -175,6 +201,7 @@ const MOCKS_WITH_IMAGE = [ }, }, ]; + const MOCKS_EMPTY = [ { request: { @@ -215,12 +242,18 @@ async function wait(ms = 100): Promise { }); }); } + +const resizeWindow = (width: number): void => { + window.innerWidth = width; + fireEvent(window, new Event('resize')); +}; + beforeEach(() => { - localStorage.setItem('FirstName', 'John'); - localStorage.setItem('LastName', 'Doe'); - localStorage.setItem( + setItem('FirstName', 'John'); + setItem('LastName', 'Doe'); + setItem( 'UserImage', - 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe' + 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', ); }); @@ -233,10 +266,12 @@ const link = new StaticMockLink(MOCKS, true); const linkImage = new StaticMockLink(MOCKS_WITH_IMAGE, true); const linkEmpty = new StaticMockLink(MOCKS_EMPTY, true); -describe('Testing Left Drawer component for SUPERADMIN', () => { +describe('Testing LeftDrawerOrg component for SUPERADMIN', () => { test('Component should be rendered properly', async () => { - localStorage.setItem('UserImage', ''); - localStorage.setItem('UserType', 'SUPERADMIN'); + setItem('UserImage', ''); + setItem('SuperAdmin', true); + setItem('FirstName', 'John'); + setItem('LastName', 'Doe'); render( @@ -246,19 +281,19 @@ describe('Testing Left Drawer component for SUPERADMIN', () => { - + , ); await wait(); defaultScreens.map((screenName) => { expect(screen.getByText(screenName)).toBeInTheDocument(); }); - expect(screen.getByText(/John Doe/i)).toBeInTheDocument(); - expect(screen.getByText(/Superadmin/i)).toBeInTheDocument(); - expect(screen.getByAltText(/dummy picture/i)).toBeInTheDocument(); }); test('Testing Profile Page & Organization Detail Modal', async () => { - localStorage.setItem('UserType', 'SUPERADMIN'); + setItem('UserImage', ''); + setItem('SuperAdmin', true); + setItem('FirstName', 'John'); + setItem('LastName', 'Doe'); render( @@ -268,15 +303,17 @@ describe('Testing Left Drawer component for SUPERADMIN', () => { - + , ); await wait(); expect(screen.getByTestId(/orgBtn/i)).toBeInTheDocument(); - userEvent.click(screen.getByTestId(/profileBtn/i)); }); test('Testing Menu Buttons', async () => { - localStorage.setItem('UserType', 'SUPERADMIN'); + setItem('UserImage', ''); + setItem('SuperAdmin', true); + setItem('FirstName', 'John'); + setItem('LastName', 'Doe'); render( @@ -286,52 +323,44 @@ describe('Testing Left Drawer component for SUPERADMIN', () => { - + , ); await wait(); userEvent.click(screen.getByText('Dashboard')); expect(global.window.location.pathname).toContain('/orgdash/id=123'); }); - test('Testing when image is present for Organization', async () => { - localStorage.setItem('UserType', 'SUPERADMIN'); + test('Testing when screen size is less than 820px', async () => { + setItem('SuperAdmin', true); render( - + - + - + , ); await wait(); - }); + resizeWindow(800); + expect(screen.getByText(/Dashboard/i)).toBeInTheDocument(); + expect(screen.getByText(/People/i)).toBeInTheDocument(); - test('Testing when Organization does not exists', async () => { - localStorage.setItem('UserType', 'SUPERADMIN'); - render( - - - - - - - - - - ); + const peopelBtn = screen.getByTestId(/People/i); + userEvent.click(peopelBtn); await wait(); - expect( - screen.getByText(/Error Occured while loading the Organization/i) - ).toBeInTheDocument(); + expect(window.location.pathname).toContain('/orgpeople/id=123'); }); - test('Testing Drawer when hideDrawer is null', () => { - localStorage.setItem('UserType', 'SUPERADMIN'); + test('Testing when image is present for Organization', async () => { + setItem('UserImage', ''); + setItem('SuperAdmin', true); + setItem('FirstName', 'John'); + setItem('LastName', 'Doe'); render( - + @@ -339,57 +368,66 @@ describe('Testing Left Drawer component for SUPERADMIN', () => { - + , ); + await wait(); }); - test('Testing Drawer when hideDrawer is true', () => { - localStorage.setItem('UserType', 'SUPERADMIN'); + test('Testing when Organization does not exists', async () => { + setItem('UserImage', ''); + setItem('SuperAdmin', true); + setItem('FirstName', 'John'); + setItem('LastName', 'Doe'); render( - + - + - + , ); + await wait(); + expect( + screen.getByText(/Error Occured while loading the Organization/i), + ).toBeInTheDocument(); }); - test('Testing Drawer open close functionality', () => { - localStorage.setItem('UserType', 'SUPERADMIN'); + test('Testing Drawer when hideDrawer is null', () => { + setItem('UserImage', ''); + setItem('SuperAdmin', true); + setItem('FirstName', 'John'); + setItem('LastName', 'Doe'); render( - + - + , ); - const closeModalBtn = screen.getByTestId(/closeModalBtn/i); - userEvent.click(closeModalBtn); }); - test('Testing logout functionality', async () => { - localStorage.setItem('UserType', 'SUPERADMIN'); + test('Testing Drawer when hideDrawer is true', () => { + setItem('UserImage', ''); + setItem('SuperAdmin', true); + setItem('FirstName', 'John'); + setItem('LastName', 'Doe'); render( - + - + , ); - userEvent.click(screen.getByTestId('logoutBtn')); - expect(localStorage.clear).toHaveBeenCalled(); - expect(global.window.location.pathname).toBe('/'); }); }); diff --git a/src/components/LeftDrawerOrg/LeftDrawerOrg.tsx b/src/components/LeftDrawerOrg/LeftDrawerOrg.tsx index aa263f7e12..115b2cf7bc 100644 --- a/src/components/LeftDrawerOrg/LeftDrawerOrg.tsx +++ b/src/components/LeftDrawerOrg/LeftDrawerOrg.tsx @@ -1,4 +1,4 @@ -import { useMutation, useQuery } from '@apollo/client'; +import { useQuery } from '@apollo/client'; import { WarningAmberOutlined } from '@mui/icons-material'; import { ORGANIZATIONS_LIST } from 'GraphQl/Queries/Queries'; import CollapsibleDropdown from 'components/CollapsibleDropdown/CollapsibleDropdown'; @@ -6,31 +6,30 @@ import IconComponent from 'components/IconComponent/IconComponent'; import React, { useEffect, useState } from 'react'; import Button from 'react-bootstrap/Button'; import { useTranslation } from 'react-i18next'; -import { useHistory } from 'react-router-dom'; +import { NavLink } from 'react-router-dom'; import type { TargetsType } from 'state/reducers/routesReducer'; import type { InterfaceQueryOrganizationsListObject } from 'utils/interfaces'; import { ReactComponent as AngleRightIcon } from 'assets/svgs/angleRight.svg'; -import { ReactComponent as LogoutIcon } from 'assets/svgs/logout.svg'; import { ReactComponent as TalawaLogo } from 'assets/svgs/talawa.svg'; import styles from './LeftDrawerOrg.module.css'; -import { REVOKE_REFRESH_TOKEN } from 'GraphQl/Mutations/mutations'; +import Avatar from 'components/Avatar/Avatar'; export interface InterfaceLeftDrawerProps { orgId: string; - screenName: string; targets: TargetsType[]; hideDrawer: boolean | null; setHideDrawer: React.Dispatch>; } const leftDrawerOrg = ({ - screenName, targets, orgId, hideDrawer, setHideDrawer, }: InterfaceLeftDrawerProps): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'leftDrawerOrg' }); + const [showDropdown, setShowDropdown] = React.useState(false); + const [organization, setOrganization] = useState(); const { @@ -44,31 +43,22 @@ const leftDrawerOrg = ({ } = useQuery(ORGANIZATIONS_LIST, { variables: { id: orgId }, }); - - const [revokeRefreshToken] = useMutation(REVOKE_REFRESH_TOKEN); - - const userType = localStorage.getItem('UserType'); - const firstName = localStorage.getItem('FirstName'); - const lastName = localStorage.getItem('LastName'); - const userImage = localStorage.getItem('UserImage'); - const userId = localStorage.getItem('id'); - const history = useHistory(); - // Set organization data useEffect(() => { let isMounted = true; if (data && isMounted) { setOrganization(data?.organizations[0]); + console.log(targets, 'targets'); } return () => { isMounted = false; }; }, [data]); - const logout = (): void => { - revokeRefreshToken(); - localStorage.clear(); - history.push('/'); + const handleLinkClick = (): void => { + if (window.innerWidth <= 820) { + setHideDrawer(true); + } }; return ( @@ -78,23 +68,11 @@ const leftDrawerOrg = ({ hideDrawer === null ? styles.hideElemByDefault : hideDrawer - ? styles.inactiveDrawer - : styles.activeDrawer + ? styles.inactiveDrawer + : styles.activeDrawer }`} data-testid="leftDrawerContainer" > - {/* Close Drawer Btn for small devices */} - - {/* Branding Section */}
    @@ -128,100 +106,63 @@ const leftDrawerOrg = ({ {organization.image ? ( {`profile ) : ( - {`Dummy )}
    {organization.name} - {organization.location} + {organization.address.city}
    + )}
    {/* Options List */}
    -
    {t('menu')}
    +
    + {t('menu')} +
    {targets.map(({ name, url }, index) => { return url ? ( - + + {({ isActive }) => ( + + )} + ) : ( ); })}
    - - {/* Profile Section & Logout Btn */} -
    - - -
    ); diff --git a/src/components/Loader/Loader.tsx b/src/components/Loader/Loader.tsx index f761ebd79b..fe5ddef793 100644 --- a/src/components/Loader/Loader.tsx +++ b/src/components/Loader/Loader.tsx @@ -20,8 +20,8 @@ const Loader = (props: InterfaceLoaderProps): JSX.Element => { props?.size == 'sm' ? styles.spinnerSm : props?.size == 'lg' - ? styles.spinnerLg - : styles.spinnerXl + ? styles.spinnerLg + : styles.spinnerXl } `} animation="border" diff --git a/src/components/LoginPortalToggle/LoginPortalToggle.module.css b/src/components/LoginPortalToggle/LoginPortalToggle.module.css new file mode 100644 index 0000000000..5983e20905 --- /dev/null +++ b/src/components/LoginPortalToggle/LoginPortalToggle.module.css @@ -0,0 +1,34 @@ +.navLinkClass { + display: inline-block; + padding: 0.375rem 0.75rem; + font-size: 1rem; + line-height: 1.4; + text-align: center; + vertical-align: middle; + cursor: pointer; + color: var(--bs-gray-900); + border-radius: 0.3rem; + width: 100%; + box-sizing: border-box; + border: 1px solid var(--bs-gray-700); + font-weight: 500; + transition: all 0.25s ease; +} + +.navLinkClass:hover { + color: var(--bs-white); + background-color: var(--bs-gray); + border-color: var(--bs-gray); +} + +.activeLink { + color: var(--bs-white); + border: 1px solid var(--bs-primary); + background-color: var(--bs-primary); +} + +.activeLink:hover { + color: var(--bs-white); + background-color: var(--bs-primary); + border: 1px solid var(--bs-primary); +} diff --git a/src/components/LoginPortalToggle/LoginPortalToggle.test.tsx b/src/components/LoginPortalToggle/LoginPortalToggle.test.tsx new file mode 100644 index 0000000000..ac971e52ea --- /dev/null +++ b/src/components/LoginPortalToggle/LoginPortalToggle.test.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import { act, render } from '@testing-library/react'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { I18nextProvider } from 'react-i18next'; +import LoginPortalToggle from './LoginPortalToggle'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Testing LoginPortalToggle component', () => { + test('Component Should be rendered properly', async () => { + const mockOnToggle = jest.fn(); + render( + + + + + + + , + ); + + await wait(); + }); +}); diff --git a/src/components/LoginPortalToggle/LoginPortalToggle.tsx b/src/components/LoginPortalToggle/LoginPortalToggle.tsx new file mode 100644 index 0000000000..359cfd577a --- /dev/null +++ b/src/components/LoginPortalToggle/LoginPortalToggle.tsx @@ -0,0 +1,47 @@ +import React, { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import styles from './LoginPortalToggle.module.css'; +import Col from 'react-bootstrap/Col'; +import Row from 'react-bootstrap/Row'; +import { NavLink } from 'react-router-dom'; + +interface InterfaceLoginPortalToggleProps { + onToggle: (role: 'admin' | 'user') => void; +} + +function loginPortalToggle({ + onToggle, +}: InterfaceLoginPortalToggleProps): JSX.Element { + const { t } = useTranslation('translation', { keyPrefix: 'loginPage' }); + const [activeRole, setActiveRole] = useState<'admin' | 'user'>('admin'); + + const handleNavLinkClick = (role: 'admin' | 'user'): void => { + onToggle(role); + setActiveRole(role); + }; + + return ( + + + handleNavLinkClick('admin')} + > + {t('admin')} + + + + handleNavLinkClick('user')} + > + {t('user')} + + + + ); +} + +export default loginPortalToggle; diff --git a/src/components/MemberRequestCard/MemberRequestCard.test.tsx b/src/components/MemberRequestCard/MemberRequestCard.test.tsx index 94efce5f09..121213e4e7 100644 --- a/src/components/MemberRequestCard/MemberRequestCard.test.tsx +++ b/src/components/MemberRequestCard/MemberRequestCard.test.tsx @@ -74,7 +74,7 @@ describe('Testing Member Request Card', () => { - + , ); await wait(); @@ -105,7 +105,7 @@ describe('Testing Member Request Card', () => { email="johndoe@gmail.com" /> - + , ); await wait(); diff --git a/src/components/MemberRequestCard/MemberRequestCard.tsx b/src/components/MemberRequestCard/MemberRequestCard.tsx index b238b66a9d..1ce1f1924c 100644 --- a/src/components/MemberRequestCard/MemberRequestCard.tsx +++ b/src/components/MemberRequestCard/MemberRequestCard.tsx @@ -24,7 +24,7 @@ interface InterfaceMemberRequestCardProps { } function memberRequestCard( - props: InterfaceMemberRequestCardProps + props: InterfaceMemberRequestCardProps, ): JSX.Element { const [acceptMutation] = useMutation(ACCEPT_ORGANIZATION_REQUEST_MUTATION); const [rejectMutation] = useMutation(REJECT_ORGANIZATION_REQUEST_MUTATION); diff --git a/src/components/NotFound/NotFound.module.css b/src/components/NotFound/NotFound.module.css index 5f0ca7a730..a209bc9f48 100644 --- a/src/components/NotFound/NotFound.module.css +++ b/src/components/NotFound/NotFound.module.css @@ -1,15 +1,13 @@ .section { - position: relative; - margin: 20px auto; - width: 100%; - background-color: #fff; - padding: 4px; - border-radius: 0.5rem; + flex: 1; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; } .error { font-size: 1.2rem; - color: #575656; font-weight: 500; } diff --git a/src/components/NotFound/NotFound.test.tsx b/src/components/NotFound/NotFound.test.tsx index 82c3bd348e..54c0bcfe4a 100644 --- a/src/components/NotFound/NotFound.test.tsx +++ b/src/components/NotFound/NotFound.test.tsx @@ -10,7 +10,7 @@ describe('Tesing the NotFound Component', () => { render( - + , ); expect(screen.getByText(/Not Found!/i)).toBeInTheDocument(); }); @@ -19,7 +19,7 @@ describe('Tesing the NotFound Component', () => { render( - + , ); expect(screen.getByText(/Not Found!/i)).toBeInTheDocument(); }); diff --git a/src/components/OrgActionItemCategories/OrgActionItemCategories.module.css b/src/components/OrgActionItemCategories/OrgActionItemCategories.module.css new file mode 100644 index 0000000000..ac9f4a5900 --- /dev/null +++ b/src/components/OrgActionItemCategories/OrgActionItemCategories.module.css @@ -0,0 +1,33 @@ +.addButton { + width: 7em; + position: absolute; + right: 1rem; + top: 1rem; +} + +.createModal { + margin-top: 20vh; + margin-left: 13vw; + max-width: 80vw; +} + +.icon { + transform: scale(1.5); + color: var(--bs-danger); + margin-bottom: 1rem; +} + +.message { + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; +} + +.titlemodal { + color: var(--bs-gray-600); + font-weight: 600; + font-size: 20px; + margin-top: 1rem; + width: 65%; +} diff --git a/src/components/OrgActionItemCategories/OrgActionItemCategories.test.tsx b/src/components/OrgActionItemCategories/OrgActionItemCategories.test.tsx new file mode 100644 index 0000000000..4440b1395e --- /dev/null +++ b/src/components/OrgActionItemCategories/OrgActionItemCategories.test.tsx @@ -0,0 +1,368 @@ +import React from 'react'; +import { + render, + screen, + fireEvent, + waitFor, + act, +} from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import 'jest-localstorage-mock'; +import { MockedProvider } from '@apollo/client/testing'; +import 'jest-location-mock'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import i18nForTest from 'utils/i18nForTest'; +import { toast } from 'react-toastify'; + +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; + +import OrgActionItemCategories from './OrgActionItemCategories'; +import { + MOCKS, + MOCKS_ERROR_QUERY, + MOCKS_ERROR_MUTATIONS, +} from './OrgActionItemCategoryMocks'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: '123' }), +})); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +const link = new StaticMockLink(MOCKS, true); +const link2 = new StaticMockLink(MOCKS_ERROR_QUERY, true); +const link3 = new StaticMockLink(MOCKS_ERROR_MUTATIONS, true); + +const translations = JSON.parse( + JSON.stringify( + i18nForTest.getDataByLanguage('en')?.translation.orgActionItemCategories, + ), +); + +describe('Testing Action Item Categories Component', () => { + test('Component loads correctly', async () => { + window.location.assign('/orgsetting/id=123'); + const { getByText } = render( + + + + + {} + + + + , + ); + + await wait(); + + await waitFor(() => { + expect(getByText(translations.createButton)).toBeInTheDocument(); + }); + }); + + test('render error component on unsuccessful query', async () => { + window.location.assign('/orgsetting/id=123'); + const { queryByText } = render( + + + + + {} + + + + , + ); + + await wait(); + + await waitFor(() => { + expect(queryByText(translations.createButton)).not.toBeInTheDocument(); + }); + }); + + test('opens and closes create and update modals on button clicks', async () => { + window.location.assign('/orgsetting/id=123'); + render( + + + + + {} + + + + , + ); + + await wait(); + + await waitFor(() => { + userEvent.click(screen.getByTestId('actionItemCategoryModalOpenBtn')); + userEvent.click(screen.getByTestId('actionItemCategoryModalCloseBtn')); + }); + + await waitFor(() => { + userEvent.click( + screen.getAllByTestId('actionItemCategoryUpdateModalOpenBtn')[0], + ); + userEvent.click(screen.getByTestId('actionItemCategoryModalCloseBtn')); + }); + }); + + test('create a new action item category', async () => { + window.location.assign('/orgsetting/id=123'); + render( + + + + + {} + + + + , + ); + + await wait(); + + await waitFor(() => { + userEvent.click(screen.getByTestId('actionItemCategoryModalOpenBtn')); + userEvent.type( + screen.getByPlaceholderText(translations.enterName), + 'ActionItemCategory 4', + ); + + userEvent.click(screen.getByTestId('formSubmitButton')); + }); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.successfulCreation); + }); + }); + + test('toast error on unsuccessful creation', async () => { + window.location.assign('/orgsetting/id=123'); + render( + + + + + {} + + + + , + ); + + await wait(); + + await waitFor(() => { + userEvent.click(screen.getByTestId('actionItemCategoryModalOpenBtn')); + userEvent.type( + screen.getByPlaceholderText(translations.enterName), + 'ActionItemCategory 4', + ); + + userEvent.click(screen.getByTestId('formSubmitButton')); + }); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); + + test('update an action item category', async () => { + window.location.assign('/orgsetting/id=123'); + render( + + + + + {} + + + + , + ); + + await wait(); + + await waitFor(() => { + userEvent.click( + screen.getAllByTestId('actionItemCategoryUpdateModalOpenBtn')[0], + ); + + const name = screen.getByPlaceholderText(translations.enterName); + fireEvent.change(name, { target: { value: '' } }); + + userEvent.type( + screen.getByPlaceholderText(translations.enterName), + 'ActionItemCategory 1 updated', + ); + + userEvent.click(screen.getByTestId('formSubmitButton')); + }); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.successfulUpdation); + }); + }); + + test('toast error on unsuccessful updation', async () => { + window.location.assign('/orgsetting/id=123'); + render( + + + + + {} + + + + , + ); + + await wait(); + + await waitFor(() => { + userEvent.click( + screen.getAllByTestId('actionItemCategoryUpdateModalOpenBtn')[0], + ); + + const name = screen.getByPlaceholderText(translations.enterName); + fireEvent.change(name, { target: { value: '' } }); + + userEvent.type( + screen.getByPlaceholderText(translations.enterName), + 'ActionItemCategory 1 updated', + ); + + userEvent.click(screen.getByTestId('formSubmitButton')); + }); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); + + test('toast error on providing the same name on updation', async () => { + window.location.assign('/orgsetting/id=123'); + render( + + + + + {} + + + + , + ); + + await wait(); + + await waitFor(() => { + userEvent.click( + screen.getAllByTestId('actionItemCategoryUpdateModalOpenBtn')[0], + ); + + const name = screen.getByPlaceholderText(translations.enterName); + fireEvent.change(name, { target: { value: '' } }); + + userEvent.type( + screen.getByPlaceholderText(translations.enterName), + 'ActionItemCategory 1', + ); + + userEvent.click(screen.getByTestId('formSubmitButton')); + }); + + await waitFor(() => { + expect(toast.error).toBeCalledWith(translations.sameNameConflict); + }); + }); + + test('toggle the disablity status of an action item category', async () => { + window.location.assign('/orgsetting/id=123'); + render( + + + + + {} + + + + , + ); + + await wait(); + + await waitFor(() => { + userEvent.click(screen.getAllByTestId('disabilityStatusButton')[0]); + }); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.categoryDisabled); + }); + + await waitFor(() => { + userEvent.click(screen.getAllByTestId('disabilityStatusButton')[1]); + }); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.categoryEnabled); + }); + }); + + test('toast error on unsuccessful toggling of the disablity status', async () => { + window.location.assign('/orgsetting/id=123'); + render( + + + + + {} + + + + , + ); + + await wait(); + + await waitFor(() => { + userEvent.click(screen.getAllByTestId('disabilityStatusButton')[0]); + }); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + + await waitFor(() => { + userEvent.click(screen.getAllByTestId('disabilityStatusButton')[1]); + }); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/components/OrgActionItemCategories/OrgActionItemCategories.tsx b/src/components/OrgActionItemCategories/OrgActionItemCategories.tsx new file mode 100644 index 0000000000..5f4c356af6 --- /dev/null +++ b/src/components/OrgActionItemCategories/OrgActionItemCategories.tsx @@ -0,0 +1,291 @@ +import type { ChangeEvent } from 'react'; +import React, { useState } from 'react'; +import { Button, Form, Modal } from 'react-bootstrap'; +import styles from './OrgActionItemCategories.module.css'; +import { useTranslation } from 'react-i18next'; +import { toast } from 'react-toastify'; +import { WarningAmberRounded } from '@mui/icons-material'; + +import { useMutation, useQuery } from '@apollo/client'; +import { + CREATE_ACTION_ITEM_CATEGORY_MUTATION, + UPDATE_ACTION_ITEM_CATEGORY_MUTATION, +} from 'GraphQl/Mutations/mutations'; +import { ACTION_ITEM_CATEGORY_LIST } from 'GraphQl/Queries/Queries'; +import type { InterfaceActionItemCategoryList } from 'utils/interfaces'; +import Loader from 'components/Loader/Loader'; +import { useParams } from 'react-router-dom'; + +type ModalType = 'Create' | 'Update'; + +const OrgActionItemCategories = (): any => { + const { t } = useTranslation('translation', { + keyPrefix: 'orgActionItemCategories', + }); + + const [modalIsOpen, setModalIsOpen] = useState(false); + const [modalType, setModalType] = useState('Create'); + const [categoryId, setCategoryId] = useState(''); + + const [name, setName] = useState(''); + const [currName, setCurrName] = useState(''); + + const { orgId: currentUrl } = useParams(); + + const { + data, + loading, + error, + refetch, + }: { + data: InterfaceActionItemCategoryList | undefined; + loading: boolean; + error?: Error | undefined; + refetch: any; + } = useQuery(ACTION_ITEM_CATEGORY_LIST, { + variables: { + organizationId: currentUrl, + }, + notifyOnNetworkStatusChange: true, + }); + + const [createActionItemCategory] = useMutation( + CREATE_ACTION_ITEM_CATEGORY_MUTATION, + ); + + const [updateActionItemCategory] = useMutation( + UPDATE_ACTION_ITEM_CATEGORY_MUTATION, + ); + + const handleCreate = async ( + e: ChangeEvent, + ): Promise => { + e.preventDefault(); + try { + await createActionItemCategory({ + variables: { + name, + organizationId: currentUrl, + }, + }); + + setName(''); + refetch(); + + setModalIsOpen(false); + + toast.success(t('successfulCreation')); + } catch (error: unknown) { + if (error instanceof Error) { + toast.error(error.message); + console.log(error.message); + } + } + }; + + const handleEdit = async (e: ChangeEvent): Promise => { + e.preventDefault(); + if (name === currName) { + toast.error(t('sameNameConflict')); + } else { + try { + await updateActionItemCategory({ + variables: { + actionItemCategoryId: categoryId, + name, + }, + }); + + setName(''); + setCategoryId(''); + refetch(); + + setModalIsOpen(false); + + toast.success(t('successfulUpdation')); + } catch (error: unknown) { + if (error instanceof Error) { + toast.error(error.message); + console.log(error.message); + } + } + } + }; + + const handleStatusChange = async ( + id: string, + disabledStatus: boolean, + ): Promise => { + try { + await updateActionItemCategory({ + variables: { + actionItemCategoryId: id, + isDisabled: !disabledStatus, + }, + }); + + refetch(); + + toast.success( + disabledStatus ? t('categoryEnabled') : t('categoryDisabled'), + ); + } catch (error: unknown) { + if (error instanceof Error) { + toast.error(error.message); + console.log(error.message); + } + } + }; + + const showCreateModal = (): void => { + setModalType('Create'); + setModalIsOpen(true); + }; + + const showUpdateModal = (name: string, id: string): void => { + setCurrName(name); + setName(name); + setCategoryId(id); + setModalType('Update'); + setModalIsOpen(true); + }; + + const hideModal = (): void => { + setName(''); + setCategoryId(''); + setModalIsOpen(false); + }; + + if (loading) { + return ; + } + + if (error) { + return ( +
    + +
    + Error occured while loading Action Item Categories Data +
    + {`${error.message}`} +
    +
    + ); + } + + const actionItemCategories = data?.actionItemCategoriesByOrganization; + + return ( + <> + + +
    + {actionItemCategories?.map((category, index) => { + return ( +
    +
    +
    + {category.name} +
    +
    + + +
    +
    + + {index !== actionItemCategories.length - 1 &&
    } +
    + ); + })} +
    + + + +

    + {t('actionItemCategoryDetails')} +

    + +
    + +
    + + {t('actionItemCategoryName')} + + { + setName(e.target.value); + }} + /> + + +
    +
    + + ); +}; + +export default OrgActionItemCategories; diff --git a/src/components/OrgActionItemCategories/OrgActionItemCategoryMocks.ts b/src/components/OrgActionItemCategories/OrgActionItemCategoryMocks.ts new file mode 100644 index 0000000000..b03e53c5f5 --- /dev/null +++ b/src/components/OrgActionItemCategories/OrgActionItemCategoryMocks.ts @@ -0,0 +1,174 @@ +import { + CREATE_ACTION_ITEM_CATEGORY_MUTATION, + UPDATE_ACTION_ITEM_CATEGORY_MUTATION, +} from 'GraphQl/Mutations/mutations'; + +import { ACTION_ITEM_CATEGORY_LIST } from 'GraphQl/Queries/Queries'; + +export const MOCKS = [ + { + request: { + query: ACTION_ITEM_CATEGORY_LIST, + variables: { organizationId: '123' }, + }, + result: { + data: { + actionItemCategoriesByOrganization: [ + { + _id: '1', + name: 'ActionItemCategory 1', + isDisabled: false, + }, + { + _id: '2', + name: 'ActionItemCategory 2', + isDisabled: true, + }, + { + _id: '3', + name: 'ActionItemCategory 3', + isDisabled: false, + }, + ], + }, + }, + }, + { + request: { + query: CREATE_ACTION_ITEM_CATEGORY_MUTATION, + variables: { name: 'ActionItemCategory 4', organizationId: '123' }, + }, + result: { + data: { + createActionItemCategory: { + _id: '4', + }, + }, + }, + }, + { + request: { + query: UPDATE_ACTION_ITEM_CATEGORY_MUTATION, + variables: { + name: 'ActionItemCategory 1 updated', + actionItemCategoryId: '1', + }, + }, + result: { + data: { + updateActionItemCategory: { + _id: '1', + }, + }, + }, + }, + { + request: { + query: UPDATE_ACTION_ITEM_CATEGORY_MUTATION, + variables: { + isDisabled: true, + actionItemCategoryId: '1', + }, + }, + result: { + data: { + updateActionItemCategory: { + _id: '1', + }, + }, + }, + }, + { + request: { + query: UPDATE_ACTION_ITEM_CATEGORY_MUTATION, + variables: { + isDisabled: false, + actionItemCategoryId: '2', + }, + }, + result: { + data: { + updateActionItemCategory: { + _id: '2', + }, + }, + }, + }, +]; + +export const MOCKS_ERROR_QUERY = [ + { + request: { + query: ACTION_ITEM_CATEGORY_LIST, + variables: { organizationId: '123' }, + }, + error: new Error('Mock Graphql Error'), + }, +]; + +export const MOCKS_ERROR_MUTATIONS = [ + { + request: { + query: ACTION_ITEM_CATEGORY_LIST, + variables: { organizationId: '123' }, + }, + result: { + data: { + actionItemCategoriesByOrganization: [ + { + _id: '1', + name: 'ActionItemCategory 1', + isDisabled: false, + }, + { + _id: '2', + name: 'ActionItemCategory 2', + isDisabled: true, + }, + { + _id: '3', + name: 'ActionItemCategory 3', + isDisabled: false, + }, + ], + }, + }, + }, + { + request: { + query: CREATE_ACTION_ITEM_CATEGORY_MUTATION, + variables: { name: 'ActionItemCategory 4', organizationId: '123' }, + }, + error: new Error('Mock Graphql Error'), + }, + { + request: { + query: UPDATE_ACTION_ITEM_CATEGORY_MUTATION, + variables: { + name: 'ActionItemCategory 1 updated', + actionItemCategoryId: '1', + }, + }, + error: new Error('Mock Graphql Error'), + }, + { + request: { + query: UPDATE_ACTION_ITEM_CATEGORY_MUTATION, + variables: { + isDisabled: true, + actionItemCategoryId: '1', + }, + }, + error: new Error('Mock Graphql Error'), + }, + { + request: { + query: UPDATE_ACTION_ITEM_CATEGORY_MUTATION, + variables: { + isDisabled: false, + actionItemCategoryId: '2', + }, + }, + error: new Error('Mock Graphql Error'), + }, +]; diff --git a/src/components/OrgAdminListCard/OrgAdminListCard.module.css b/src/components/OrgAdminListCard/OrgAdminListCard.module.css deleted file mode 100644 index 187757a531..0000000000 --- a/src/components/OrgAdminListCard/OrgAdminListCard.module.css +++ /dev/null @@ -1,74 +0,0 @@ -.memberlist { - margin-top: -1px; -} -.memberimg { - width: 200px; - height: 100px; - border-radius: 7px; - margin-left: 20px; -} -.singledetails { - display: flex; - flex-direction: row; - justify-content: space-between; -} -.singledetails p { - margin-bottom: -5px; -} -.singledetails_data_left { - margin-top: 10px; - margin-left: 10px; - color: #707070; -} -.singledetails_data_right { - justify-content: right; - margin-top: 10px; - text-align: right; - color: #707070; -} -.membername { - font-size: 16px; - font-weight: bold; -} -.memberfont { - margin-top: 3px; -} -.memberfont > span { - width: 80%; -} -.memberfontcreated { - margin-top: 18px; -} -.memberfontcreatedbtn { - margin-top: 33px; - border-radius: 7px; - border-color: #31bb6b; - background-color: #31bb6b; - color: white; - padding-right: 10px; - padding-left: 10px; - justify-content: flex-end; - float: right; - text-align: right; - box-shadow: none; -} -#grid_wrapper { - align-items: left; -} -.peoplelistdiv { - margin-right: 50px; -} -@media only screen and (max-width: 600px) { - .singledetails { - margin-left: 20px; - } - .memberimg { - margin: auto; - } - .singledetails_data_right { - margin-right: -52px; - } - .singledetails_data_left { - margin-left: 0px; - } -} diff --git a/src/components/OrgAdminListCard/OrgAdminListCard.test.tsx b/src/components/OrgAdminListCard/OrgAdminListCard.test.tsx index db499cd0b1..cb2492d306 100644 --- a/src/components/OrgAdminListCard/OrgAdminListCard.test.tsx +++ b/src/components/OrgAdminListCard/OrgAdminListCard.test.tsx @@ -1,28 +1,26 @@ import React from 'react'; -import { act, render, screen } from '@testing-library/react'; +import { act, render, screen, waitFor } from '@testing-library/react'; +import type { RenderResult } from '@testing-library/react'; import { MockedProvider } from '@apollo/react-testing'; import userEvent from '@testing-library/user-event'; import { I18nextProvider } from 'react-i18next'; - import { REMOVE_ADMIN_MUTATION } from 'GraphQl/Mutations/mutations'; import OrgAdminListCard from './OrgAdminListCard'; import i18nForTest from 'utils/i18nForTest'; -import { BrowserRouter } from 'react-router-dom'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; import { StaticMockLink } from 'utils/StaticMockLink'; const MOCKS = [ { request: { query: REMOVE_ADMIN_MUTATION, - variable: { userid: '564', orgid: '987' }, + variables: { userid: '456', orgid: '987' }, }, result: { data: { - organizations: [ - { - _id: '1', - }, - ], + removeAdmin: { + _id: '456', + }, }, }, }, @@ -36,64 +34,70 @@ async function wait(ms = 100): Promise { }); } +const renderOrgAdminListCard = (props: { + toggleRemoveModal: () => boolean; + id: string | undefined; +}): RenderResult => { + return render( + + + + + } + /> + orgListScreen
    } + /> + + + + , + ); +}; + describe('Testing Organization Admin List Card', () => { global.alert = jest.fn(); + beforeEach(() => { + Object.defineProperty(window, 'location', { + writable: true, + value: { reload: jest.fn() }, + }); + }); + + afterEach(() => { + jest.restoreAllMocks(); + }); + test('should render props and text elements test for the page component', async () => { const props = { - key: '123', + toggleRemoveModal: () => true, id: '456', - memberName: 'John Doe', - joinDate: '05/05/2022', - memberImage: 'image', - memberEmail: 'johndoe@gmail.com', }; - render( - - - - - - - - ); + renderOrgAdminListCard(props); await wait(); - userEvent.click(screen.getByTestId(/removeAdminModalBtn/i)); userEvent.click(screen.getByTestId(/removeAdminBtn/i)); - expect(screen.getByText(props.memberName)).toBeInTheDocument(); - expect(screen.getByText(props.joinDate)).toBeInTheDocument(); + await wait(2000); }); - test('Should render text elements when props value is not passed', async () => { + test('Should not render text elements when props value is not passed', async () => { const props = { - key: '123', - id: '456', - memberName: '', - joinDate: '05/05/2022', - memberImage: '', - memberEmail: '', + toggleRemoveModal: () => true, + id: undefined, }; - render( - - - - - - - - ); - - await wait(); - - userEvent.click(screen.getByTestId(/removeAdminModalBtn/i)); - userEvent.click(screen.getByTestId(/removeAdminBtn/i)); + renderOrgAdminListCard(props); - expect(screen.getByText(/Dogs Care/i)).toBeInTheDocument(); - expect(screen.getByText(props.joinDate)).toBeInTheDocument(); + await waitFor(() => { + const orgListScreen = screen.getByTestId('orgListScreen'); + expect(orgListScreen).toBeInTheDocument(); + }); }); }); diff --git a/src/components/OrgAdminListCard/OrgAdminListCard.tsx b/src/components/OrgAdminListCard/OrgAdminListCard.tsx index df0bf70071..6d60af9338 100644 --- a/src/components/OrgAdminListCard/OrgAdminListCard.tsx +++ b/src/components/OrgAdminListCard/OrgAdminListCard.tsx @@ -1,39 +1,29 @@ import React from 'react'; -import Row from 'react-bootstrap/Row'; -import Col from 'react-bootstrap/Col'; import Button from 'react-bootstrap/Button'; import Modal from 'react-bootstrap/Modal'; import { useMutation } from '@apollo/client'; import { toast } from 'react-toastify'; - -import styles from './OrgAdminListCard.module.css'; import { REMOVE_ADMIN_MUTATION } from 'GraphQl/Mutations/mutations'; import { useTranslation } from 'react-i18next'; -import { Link } from 'react-router-dom'; -import defaultImg from 'assets/images/blank.png'; +import { Navigate, useParams } from 'react-router-dom'; import { errorHandler } from 'utils/errorHandler'; interface InterfaceOrgPeopleListCardProps { - key: string; - id: string; - memberName: string; - joinDate: string; - memberImage: string; - memberEmail: string; + id: string | undefined; + toggleRemoveModal: () => void; } -const currentUrl = window.location.href.split('=')[1]; function orgAdminListCard(props: InterfaceOrgPeopleListCardProps): JSX.Element { + if (!props.id) { + return ; + } + const { orgId: currentUrl } = useParams(); const [remove] = useMutation(REMOVE_ADMIN_MUTATION); - const [showRemoveAdminModal, setShowRemoveAdminModal] = React.useState(false); const { t } = useTranslation('translation', { keyPrefix: 'orgAdminListCard', }); - const toggleRemoveAdminModal = (): void => - setShowRemoveAdminModal(!showRemoveAdminModal); - const removeAdmin = async (): Promise => { try { const { data } = await remove({ @@ -42,67 +32,29 @@ function orgAdminListCard(props: InterfaceOrgPeopleListCardProps): JSX.Element { orgid: currentUrl, }, }); - - /* istanbul ignore next */ if (data) { toast.success(t('adminRemoved')); setTimeout(() => { window.location.reload(); }, 2000); } - } catch (error: any) { + } catch (error: unknown) { /* istanbul ignore next */ errorHandler(t, error); } }; return ( -
    -
    - - {props.memberImage ? ( - - ) : ( - - )} - -
    - - {props.memberName ? <>{props.memberName} : <>Dogs Care} - -

    {props.memberEmail}

    -
    -
    -

    - {t('joined')}: {props.joinDate} -

    - -
    - -
    -
    -
    - + <> +
    {t('removeAdmin')}
    -
    {t('removeAdminMsg')} -
    + ); } export default orgAdminListCard; diff --git a/src/components/OrgContriCards/OrgContriCards.test.tsx b/src/components/OrgContriCards/OrgContriCards.test.tsx index 95de529d98..4f202cd355 100644 --- a/src/components/OrgContriCards/OrgContriCards.test.tsx +++ b/src/components/OrgContriCards/OrgContriCards.test.tsx @@ -38,7 +38,7 @@ describe('Testing the Organization Contributions Cards', () => { userEmail={props.userEmail} /> - + , ); expect(screen.getByText('Date:')).toBeInTheDocument(); expect(screen.getByText('John Doe')).toBeInTheDocument(); diff --git a/src/components/OrgDelete/OrgDelete.test.tsx b/src/components/OrgDelete/OrgDelete.test.tsx index cc89241f56..b9b9ca2572 100644 --- a/src/components/OrgDelete/OrgDelete.test.tsx +++ b/src/components/OrgDelete/OrgDelete.test.tsx @@ -20,7 +20,7 @@ describe('Testing Organization People List Card', () => { - + , ); expect(screen.getByText('Delete Org')).toBeInTheDocument(); }); diff --git a/src/components/OrgListCard/OrgListCard.module.css b/src/components/OrgListCard/OrgListCard.module.css index 1f1e5e2974..430ea318d6 100644 --- a/src/components/OrgListCard/OrgListCard.module.css +++ b/src/components/OrgListCard/OrgListCard.module.css @@ -21,13 +21,13 @@ border-radius: 4px; } -.orgCard .innerContainer .orgImgContainer img { +.orgCard .innerContainer .orgImgContainer { width: 125px; height: 120px; object-fit: contain; } -.orgCard .innerContainer .orgImgContainer .emptyImg { +.orgCard .innerContainer .orgImgContainer { width: 125px; height: 120px; background-color: var(--bs-gray-200); @@ -36,6 +36,8 @@ .orgCard .innerContainer .content { flex: 1; margin-left: 1rem; + width: 70%; + margin-top: 0.7rem; } .orgCard button { @@ -45,7 +47,57 @@ z-index: 1; } -@media (max-width: 450px) { +.flaskIcon { + margin-top: 4px; +} + +.manageBtn { + display: flex; + justify-content: space-around; + width: 8rem; +} + +.orgName { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + font-size: 1rem; +} + +.orgdesc { + font-size: 0.9rem; + color: var(--bs-gray-600); + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 1; + line-clamp: 1; + -webkit-box-orient: vertical; + max-width: 20rem; +} + +.orgadmin { + font-size: 0.9rem; +} + +.orgmember { + font-size: 0.9rem; +} + +.address { + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 1; + line-clamp: 1; + -webkit-box-orient: vertical; + align-items: center; +} + +.address h6 { + font-size: 0.9rem; + color: var(--bs-gray-600); +} + +@media (max-width: 580px) { .orgCard { height: unset; margin: 0.5rem 0; @@ -76,17 +128,14 @@ margin-left: auto; display: block; } -} -.flaskIcon { - position: absolute; - top: 0; - right: 0; - margin: 10px 20px 0px 0px; -} + .flaskIcon { + margin-bottom: 6px; + } -.manageBtn { - display: flex; - justify-content: space-around; - width: 150px; + .manageBtn { + display: flex; + justify-content: space-around; + width: 100%; + } } diff --git a/src/components/OrgListCard/OrgListCard.test.tsx b/src/components/OrgListCard/OrgListCard.test.tsx index ffcf92981f..25d7f01ed1 100644 --- a/src/components/OrgListCard/OrgListCard.test.tsx +++ b/src/components/OrgListCard/OrgListCard.test.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { render, screen } from '@testing-library/react'; +import { act, render, screen } from '@testing-library/react'; import 'jest-location-mock'; import { I18nextProvider } from 'react-i18next'; @@ -11,11 +11,17 @@ import { BrowserRouter } from 'react-router-dom'; import { IS_SAMPLE_ORGANIZATION_QUERY } from 'GraphQl/Queries/Queries'; import { StaticMockLink } from 'utils/StaticMockLink'; import { MockedProvider } from '@apollo/react-testing'; +import useLocalStorage from 'utils/useLocalstorage'; + +const { setItem, removeItem } = useLocalStorage(); const MOCKS = [ { request: { query: IS_SAMPLE_ORGANIZATION_QUERY, + variables: { + isSampleOrganizationId: 'xyz', + }, }, result: { data: { @@ -27,12 +33,29 @@ const MOCKS = [ const link = new StaticMockLink(MOCKS, true); +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + const props: InterfaceOrgListCardProps = { data: { _id: 'xyz', name: 'Dogs Care', image: 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', - location: 'India', + address: { + city: 'Sample City', + countryCode: 'US', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Sample Street', + line2: 'Apartment 456', + postalCode: '12345', + sortingCode: 'ABC-123', + state: 'Sample State', + }, admins: [ { _id: '123', @@ -52,8 +75,9 @@ const props: InterfaceOrgListCardProps = { }; describe('Testing the Super Dash List', () => { - test('should render props and text elements test for the page component', () => { - localStorage.setItem('id', '123'); // Means the user is an admin + test('should render props and text elements test for the page component', async () => { + removeItem('id'); + setItem('id', '123'); // Means the user is an admin render( @@ -62,14 +86,19 @@ describe('Testing the Super Dash List', () => { - + , ); + await wait(); expect(screen.getByAltText(/Dogs Care image/i)).toBeInTheDocument(); - expect(screen.getByText('Admins:')).toBeInTheDocument(); - expect(screen.getByText('Members:')).toBeInTheDocument(); + expect(screen.getByText(/Admins:/i)).toBeInTheDocument(); + expect(screen.getByText(/Members:/i)).toBeInTheDocument(); expect(screen.getByText('Dogs Care')).toBeInTheDocument(); - expect(screen.getByText('India')).toBeInTheDocument(); + expect(screen.getByText(/Sample City/i)).toBeInTheDocument(); + expect(screen.getByText(/123 Sample Street/i)).toBeInTheDocument(); + expect(screen.getByTestId(/manageBtn/i)).toBeInTheDocument(); + expect(screen.getByTestId(/flaskIcon/i)).toBeInTheDocument(); userEvent.click(screen.getByTestId(/manageBtn/i)); + removeItem('id'); }); test('Testing if the props data is not provided', () => { @@ -82,7 +111,7 @@ describe('Testing the Super Dash List', () => { - + , ); expect(window.location).toBeAt('/orgdash'); @@ -95,10 +124,12 @@ describe('Testing the Super Dash List', () => { }; render( - - - - + + + + + + , ); expect(screen.getByTestId(/emptyContainerForImage/i)).toBeInTheDocument(); }); @@ -111,9 +142,8 @@ describe('Testing the Super Dash List', () => { - + , ); userEvent.click(screen.getByTestId('manageBtn')); - expect(window.location).toBeAt('/orgdash/id=xyz'); }); }); diff --git a/src/components/OrgListCard/OrgListCard.tsx b/src/components/OrgListCard/OrgListCard.tsx index 191a689bc0..ef1e5efeba 100644 --- a/src/components/OrgListCard/OrgListCard.tsx +++ b/src/components/OrgListCard/OrgListCard.tsx @@ -3,18 +3,25 @@ import { ReactComponent as FlaskIcon } from 'assets/svgs/flask.svg'; import Button from 'react-bootstrap/Button'; import { useTranslation } from 'react-i18next'; import styles from './OrgListCard.module.css'; -import { useHistory } from 'react-router-dom'; -import type { InterfaceOrgConnectionInfoType } from 'utils/interfaces'; -import LocationOnIcon from '@mui/icons-material/LocationOn'; -import { IS_SAMPLE_ORGANIZATION_QUERY } from 'GraphQl/Queries/Queries'; +import { useNavigate } from 'react-router-dom'; +import type { + InterfaceOrgConnectionInfoType, + InterfaceQueryOrganizationsListObject, +} from 'utils/interfaces'; +import { + IS_SAMPLE_ORGANIZATION_QUERY, + ORGANIZATIONS_LIST, +} from 'GraphQl/Queries/Queries'; import { useQuery } from '@apollo/client'; +import { Tooltip } from '@mui/material'; +import Avatar from 'components/Avatar/Avatar'; export interface InterfaceOrgListCardProps { data: InterfaceOrgConnectionInfoType; } function orgListCard(props: InterfaceOrgListCardProps): JSX.Element { - const { _id, admins, image, location, members, name } = props.data; + const { _id, admins, image, address, members, name } = props.data; const { data } = useQuery(IS_SAMPLE_ORGANIZATION_QUERY, { variables: { @@ -22,14 +29,22 @@ function orgListCard(props: InterfaceOrgListCardProps): JSX.Element { }, }); - const history = useHistory(); + const navigate = useNavigate(); + const { + data: userData, + }: { + data?: { + organizations: InterfaceQueryOrganizationsListObject[]; + }; + } = useQuery(ORGANIZATIONS_LIST, { + variables: { id: _id }, + }); function handleClick(): void { - const url = '/orgdash/id=' + _id; + const url = '/orgdash/' + _id; // Dont change the below two lines - window.location.replace(url); - history.push(url); + navigate(url); } const { t } = useTranslation('translation', { @@ -42,30 +57,35 @@ function orgListCard(props: InterfaceOrgListCardProps): JSX.Element {
    {image ? ( - {`${name} + {`${name} ) : ( -
    )}
    -
    - - {location} -
    -
    - {t('admins')}: {admins.length} + +

    {name}

    +
    +
    + {userData?.organizations[0].description}
    -
    + {address && address.city && ( +
    +
    + {address.line1}, + {address.city}, + {address.countryCode} +
    +
    + )} +
    + {t('admins')}: {admins.length}      {' '} {t('members')}: {members.length}
    -
    {name}
    -
    - - -
    -
    - +
    {t('removeMember')}
    -
    {t('removeMemberMsg')} - + +
    +
    +
    +
    + ); +}; + +export default OrgProfileFieldSettings; diff --git a/src/components/OrgUpdate/OrgUpdate.test.tsx b/src/components/OrgUpdate/OrgUpdate.test.tsx index 79b076c452..9c56a61d78 100644 --- a/src/components/OrgUpdate/OrgUpdate.test.tsx +++ b/src/components/OrgUpdate/OrgUpdate.test.tsx @@ -30,9 +30,18 @@ describe('Testing Organization Update', () => { const formData = { name: 'Palisadoes Organization', description: 'This is a updated description', - location: 'This is updated location', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, displayImage: new File(['hello'], 'hello.png', { type: 'image/png' }), - isPublic: false, + userRegistrationRequired: false, isVisible: true, }; @@ -45,30 +54,44 @@ describe('Testing Organization Update', () => { - + , ); }); await wait(); // Check labels are present or not expect(screen.getByText('Name')).toBeInTheDocument(); expect(screen.getByText('Description')).toBeInTheDocument(); - expect(screen.getByText('Location')).toBeInTheDocument(); + expect(screen.getByText('Address')).toBeInTheDocument(); expect(screen.getByText('Display Image:')).toBeInTheDocument(); - expect(screen.getByText('Public:')).toBeInTheDocument(); + expect(screen.getByText(/Registration/)).toBeInTheDocument(); expect(screen.getByText('Visible in Search:')).toBeInTheDocument(); // Get the input fields, and btns const name = screen.getByPlaceholderText(/Enter Organization Name/i); const des = screen.getByPlaceholderText(/Description/i); - const location = screen.getByPlaceholderText(/Location/i); - const isPublic = screen.getByPlaceholderText(/Public/i); + const city = screen.getByPlaceholderText(/City/i); + const countryCode = screen.getByTestId('countrycode'); + const line1 = screen.getByPlaceholderText(/Line 1/i); + const line2 = screen.getByPlaceholderText(/Line 2/i); + const dependentLocality = + screen.getByPlaceholderText(/Dependent Locality/i); + const sortingCode = screen.getByPlaceholderText(/Sorting code/i); + const postalCode = screen.getByPlaceholderText(/Postal Code/i); + const userRegistrationRequired = + screen.getByPlaceholderText(/Registration/i); const isVisible = screen.getByPlaceholderText(/Visible/i); // Checking if form fields got updated according to the mock data expect(name).toHaveValue('Palisadoes'); expect(des).toHaveValue('Equitable Access to STEM Education Jobs'); - expect(location).toHaveValue('Jamaica'); - expect(isPublic).toBeChecked(); + expect(city).toHaveValue('Kingston'); + expect(countryCode).toHaveValue('JM'); + expect(dependentLocality).toHaveValue('Sample Dependent Locality'); + expect(line1).toHaveValue('123 Jamaica Street'); + expect(line2).toHaveValue('Apartment 456'); + expect(postalCode).toHaveValue('JM12345'); + expect(sortingCode).toHaveValue('ABC-123'); + expect(userRegistrationRequired).toBeChecked(); expect(isVisible).not.toBeChecked(); }); @@ -79,7 +102,7 @@ describe('Testing Organization Update', () => { - + , ); }); @@ -88,23 +111,43 @@ describe('Testing Organization Update', () => { // Get the input fields, and btns const name = screen.getByPlaceholderText(/Enter Organization Name/i); const des = screen.getByPlaceholderText(/Description/i); - const location = screen.getByPlaceholderText(/Location/i); + + const city = screen.getByPlaceholderText(/City/i); + const countryCode = screen.getByTestId('countrycode'); + const line1 = screen.getByPlaceholderText(/Line 1/i); + const line2 = screen.getByPlaceholderText(/Line 2/i); + const dependentLocality = + screen.getByPlaceholderText(/Dependent Locality/i); + const sortingCode = screen.getByPlaceholderText(/Sorting code/i); + const postalCode = screen.getByPlaceholderText(/Postal Code/i); const displayImage = screen.getByPlaceholderText(/Display Image/i); - const isPublic = screen.getByPlaceholderText(/Public/i); + const userRegistrationRequired = + screen.getByPlaceholderText(/Registration/i); const isVisible = screen.getByPlaceholderText(/Visible/i); const saveChangesBtn = screen.getByText(/Save Changes/i); // Emptying the text fields to add updated data fireEvent.change(name, { target: { value: '' } }); fireEvent.change(des, { target: { value: '' } }); - fireEvent.change(location, { target: { value: '' } }); + fireEvent.change(city, { target: { value: '' } }); + fireEvent.change(line1, { target: { value: '' } }); + fireEvent.change(line2, { target: { value: '' } }); + fireEvent.change(postalCode, { target: { value: '' } }); + fireEvent.change(sortingCode, { target: { value: '' } }); + fireEvent.change(dependentLocality, { target: { value: '' } }); // Mocking filling form behaviour userEvent.type(name, formData.name); userEvent.type(des, formData.description); - userEvent.type(location, formData.location); + userEvent.type(city, formData.address.city); + userEvent.selectOptions(countryCode, formData.address.countryCode); + userEvent.type(line1, formData.address.line1); + userEvent.type(line2, formData.address.line2); + userEvent.type(postalCode, formData.address.postalCode); + userEvent.type(dependentLocality, formData.address.dependentLocality); + userEvent.type(sortingCode, formData.address.sortingCode); userEvent.upload(displayImage, formData.displayImage); - userEvent.click(isPublic); + userEvent.click(userRegistrationRequired); userEvent.click(isVisible); await wait(); @@ -113,9 +156,15 @@ describe('Testing Organization Update', () => { // Checking if the form got update accordingly expect(name).toHaveValue(formData.name); expect(des).toHaveValue(formData.description); - expect(location).toHaveValue(formData.location); + expect(city).toHaveValue(formData.address.city); + expect(countryCode).toHaveValue(formData.address.countryCode); + expect(dependentLocality).toHaveValue(formData.address.dependentLocality); + expect(line1).toHaveValue(formData.address.line1); + expect(line2).toHaveValue(formData.address.line2); + expect(postalCode).toHaveValue(formData.address.postalCode); + expect(sortingCode).toHaveValue(formData.address.sortingCode); expect(displayImage).toBeTruthy(); - expect(isPublic).not.toBeChecked(); + expect(userRegistrationRequired).not.toBeChecked(); expect(isVisible).toBeChecked(); }); @@ -126,7 +175,7 @@ describe('Testing Organization Update', () => { - + , ); }); await wait(); @@ -140,7 +189,7 @@ describe('Testing Organization Update', () => { - + , ); }); @@ -149,23 +198,42 @@ describe('Testing Organization Update', () => { // Get the input fields, and btns const name = screen.getByPlaceholderText(/Enter Organization Name/i); const des = screen.getByPlaceholderText(/Description/i); - const location = screen.getByPlaceholderText(/Location/i); + const city = screen.getByPlaceholderText(/City/i); + const countryCode = screen.getByTestId('countrycode'); + const line1 = screen.getByPlaceholderText(/Line 1/i); + const line2 = screen.getByPlaceholderText(/Line 2/i); + const dependentLocality = + screen.getByPlaceholderText(/Dependent Locality/i); + const sortingCode = screen.getByPlaceholderText(/Sorting code/i); + const postalCode = screen.getByPlaceholderText(/Postal Code/i); const displayImage = screen.getByPlaceholderText(/Display Image/i); - const isPublic = screen.getByPlaceholderText(/Public/i); + const userRegistrationRequired = + screen.getByPlaceholderText(/Registration/i); const isVisible = screen.getByPlaceholderText(/Visible/i); const saveChangesBtn = screen.getByText(/Save Changes/i); // Emptying the text fields to add updated data fireEvent.change(name, { target: { value: '' } }); fireEvent.change(des, { target: { value: '' } }); - fireEvent.change(location, { target: { value: '' } }); + fireEvent.change(city, { target: { value: '' } }); + fireEvent.change(line1, { target: { value: '' } }); + fireEvent.change(line2, { target: { value: '' } }); + fireEvent.change(postalCode, { target: { value: '' } }); + fireEvent.change(sortingCode, { target: { value: '' } }); + fireEvent.change(dependentLocality, { target: { value: '' } }); // Mocking filling form behaviour userEvent.type(name, formData.name); userEvent.type(des, formData.description); - userEvent.type(location, formData.location); + userEvent.type(city, formData.address.city); + userEvent.selectOptions(countryCode, formData.address.countryCode); + userEvent.type(line1, formData.address.line1); + userEvent.type(line2, formData.address.line2); + userEvent.type(postalCode, formData.address.postalCode); + userEvent.type(dependentLocality, formData.address.dependentLocality); + userEvent.type(sortingCode, formData.address.sortingCode); userEvent.upload(displayImage, formData.displayImage); - userEvent.click(isPublic); + userEvent.click(userRegistrationRequired); userEvent.click(isVisible); await wait(); diff --git a/src/components/OrgUpdate/OrgUpdate.tsx b/src/components/OrgUpdate/OrgUpdate.tsx index 16222717d6..b19ba4af92 100644 --- a/src/components/OrgUpdate/OrgUpdate.tsx +++ b/src/components/OrgUpdate/OrgUpdate.tsx @@ -12,8 +12,12 @@ import Loader from 'components/Loader/Loader'; import { Col, Form, Row } from 'react-bootstrap'; import convertToBase64 from 'utils/convertToBase64'; import { errorHandler } from 'utils/errorHandler'; -import type { InterfaceQueryOrganizationsListObject } from 'utils/interfaces'; import styles from './OrgUpdate.module.css'; +import type { + InterfaceQueryOrganizationsListObject, + InterfaceAddress, +} from 'utils/interfaces'; +import { countryOptions } from 'utils/formEnumFields'; interface InterfaceOrgUpdateProps { orgId: string; @@ -25,16 +29,36 @@ function orgUpdate(props: InterfaceOrgUpdateProps): JSX.Element { const [formState, setFormState] = useState<{ orgName: string; orgDescrip: string; - location: string; + address: InterfaceAddress; orgImage: string | null; }>({ orgName: '', orgDescrip: '', - location: '', + address: { + city: '', + countryCode: '', + dependentLocality: '', + line1: '', + line2: '', + postalCode: '', + sortingCode: '', + state: '', + }, orgImage: null, }); - const [publicchecked, setPublicChecked] = React.useState(false); + const handleInputChange = (fieldName: string, value: string): void => { + setFormState((prevState) => ({ + ...prevState, + address: { + ...prevState.address, + [fieldName]: value, + }, + })); + }; + + const [userRegistrationRequiredChecked, setuserRegistrationRequiredChecked] = + React.useState(false); const [visiblechecked, setVisibleChecked] = React.useState(false); const [login] = useMutation(UPDATE_ORGANIZATION_MUTATION); @@ -67,9 +91,11 @@ function orgUpdate(props: InterfaceOrgUpdateProps): JSX.Element { ...formState, orgName: data.organizations[0].name, orgDescrip: data.organizations[0].description, - location: data.organizations[0].location, + address: data.organizations[0].address, }); - setPublicChecked(data.organizations[0].isPublic); + setuserRegistrationRequiredChecked( + data.organizations[0].userRegistrationRequired, + ); setVisibleChecked(data.organizations[0].visibleInSearch); } return () => { @@ -84,8 +110,17 @@ function orgUpdate(props: InterfaceOrgUpdateProps): JSX.Element { id: orgId, name: formState.orgName, description: formState.orgDescrip, - location: formState.location, - isPublic: publicchecked, + address: { + city: formState.address.city, + countryCode: formState.address.countryCode, + dependentLocality: formState.address.dependentLocality, + line1: formState.address.line1, + line2: formState.address.line2, + postalCode: formState.address.postalCode, + sortingCode: formState.address.sortingCode, + state: formState.address.state, + }, + userRegistrationRequired: userRegistrationRequiredChecked, visibleInSearch: visiblechecked, file: formState.orgImage, }, @@ -149,27 +184,115 @@ function orgUpdate(props: InterfaceOrgUpdateProps): JSX.Element { }); }} /> - {t('location')} - { - setFormState({ - ...formState, - location: e.target.value, - }); - }} - /> + {t('address')} + + + { + const countryCode = e.target.value; + handleInputChange('countryCode', countryCode); + }} + > + + {countryOptions.map((country) => ( + + ))} + + + + handleInputChange('city', e.target.value)} + /> + + + + + handleInputChange('state', e.target.value)} + /> + + + + handleInputChange('dependentLocality', e.target.value) + } + /> + + + + + handleInputChange('line1', e.target.value)} + /> + + + handleInputChange('line2', e.target.value)} + /> + + + + + + handleInputChange('postalCode', e.target.value) + } + /> + + + + handleInputChange('sortingCode', e.target.value) + } + /> + + - {t('isPublic')}: + + {t('userRegistrationRequired')}: + setPublicChecked(!publicchecked)} + placeholder={t('userRegistrationRequired')} + checked={userRegistrationRequiredChecked} + onChange={(): void => + setuserRegistrationRequiredChecked( + !userRegistrationRequiredChecked, + ) + } /> diff --git a/src/components/OrgUpdate/OrgUpdateMocks.ts b/src/components/OrgUpdate/OrgUpdateMocks.ts index cd78d37fd0..4c7f704719 100644 --- a/src/components/OrgUpdate/OrgUpdateMocks.ts +++ b/src/components/OrgUpdate/OrgUpdateMocks.ts @@ -15,8 +15,17 @@ export const MOCKS = [ image: null, name: 'Palisadoes', description: 'Equitable Access to STEM Education Jobs', - location: 'Jamaica', - isPublic: true, + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + userRegistrationRequired: true, visibleInSearch: false, creator: { firstName: 'John', @@ -35,6 +44,7 @@ export const MOCKS = [ firstName: 'John', lastName: 'Doe', email: 'johndoe@gmail.com', + createdAt: '12-03-2024', }, ], membershipRequests: { @@ -58,9 +68,18 @@ export const MOCKS = [ id: '123', name: 'Updated Organization', description: 'This is an updated test organization', - location: 'Updated location', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, image: new File(['hello'], 'hello.png', { type: 'image/png' }), - isPublic: true, + userRegistrationRequired: true, visibleInSearch: false, }, }, @@ -70,8 +89,17 @@ export const MOCKS = [ _id: '123', name: 'Updated Organization', description: 'This is an updated test organization', - location: 'Updated location', - isPublic: true, + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + userRegistrationRequired: true, visibleInSearch: false, }, }, @@ -103,8 +131,17 @@ export const MOCKS_ERROR_UPDATE_ORGLIST = [ image: null, name: 'Palisadoes', description: 'Equitable Access to STEM Education Jobs', - location: 'Jamaica', - isPublic: true, + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + userRegistrationRequired: true, visibleInSearch: false, creator: { firstName: 'John', @@ -123,6 +160,7 @@ export const MOCKS_ERROR_UPDATE_ORGLIST = [ firstName: 'John', lastName: 'Doe', email: 'johndoe@gmail.com', + createdAt: '12-03-2024', }, ], membershipRequests: { @@ -146,9 +184,18 @@ export const MOCKS_ERROR_UPDATE_ORGLIST = [ id: '123', name: 'Updated Organization', description: 'This is an updated test organization', - location: 'Updated location', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, image: new File(['hello'], 'hello.png', { type: 'image/png' }), - isPublic: true, + userRegistrationRequired: true, visibleInSearch: false, }, }, diff --git a/src/components/OrganizationCardStart/OrganizationCardStart.tsx b/src/components/OrganizationCardStart/OrganizationCardStart.tsx index 37c7b65686..4fdbc0edb2 100644 --- a/src/components/OrganizationCardStart/OrganizationCardStart.tsx +++ b/src/components/OrganizationCardStart/OrganizationCardStart.tsx @@ -9,7 +9,7 @@ interface InterfaceOrganizationCardStartProps { } function organizationCardStart( - props: InterfaceOrganizationCardStartProps + props: InterfaceOrganizationCardStartProps, ): JSX.Element { const uri = '/orghome/i=' + props.id; diff --git a/src/components/OrganizationDashCards/CardItem.module.css b/src/components/OrganizationDashCards/CardItem.module.css index 0330411b0c..bfb85cb1bb 100644 --- a/src/components/OrganizationDashCards/CardItem.module.css +++ b/src/components/OrganizationDashCards/CardItem.module.css @@ -2,7 +2,9 @@ position: relative; display: flex; align-items: center; - padding: 0.75rem 0; + border: 1px solid var(--bs-gray-200); + border-radius: 8px; + margin-top: 20px; } .cardItem .iconWrapper { @@ -39,6 +41,22 @@ .cardItem .title { font-size: 1rem; flex: 1; + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 1; + line-clamp: 1; + -webkit-box-orient: vertical; + margin-left: 3px; +} + +.cardItem .location { + font-size: 0.9rem; + color: var(--bs-primary); + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 1; + line-clamp: 1; + -webkit-box-orient: vertical; } .cardItem .time { @@ -53,8 +71,11 @@ .rightCard { display: flex; - gap: 5px; + gap: 7px; min-width: 170px; justify-content: center; flex-direction: column; + margin-left: 10px; + overflow-x: hidden; + width: 210px; } diff --git a/src/components/OrganizationDashCards/CardItem.test.tsx b/src/components/OrganizationDashCards/CardItem.test.tsx index 2102e86f94..31f3474607 100644 --- a/src/components/OrganizationDashCards/CardItem.test.tsx +++ b/src/components/OrganizationDashCards/CardItem.test.tsx @@ -5,19 +5,26 @@ import type { InterfaceCardItem } from './CardItem'; import dayjs from 'dayjs'; describe('Testing the Organization Card', () => { - test('should render props and text elements For event card', () => { + test('Should render props and text elements For event card', () => { const props: InterfaceCardItem = { type: 'Event', title: 'Event Title', - time: '2023-09-03', + startdate: '2023-09-13', + enddate: '2023-09-14', + location: 'Event Location', }; render(); expect(screen.getByText(/Event Title/i)).toBeInTheDocument(); expect( - screen.getByText(dayjs(props.time).format('MMM D, YYYY')) + screen.getByText( + `${dayjs(props.startdate).format('MMM D, YYYY')} - ${dayjs( + props.enddate, + ).format('MMM D, YYYY')}`, + ), ).toBeInTheDocument(); + expect(screen.getByText(/Event Location/i)).toBeInTheDocument(); }); test('Should render props and text elements for Post card', () => { @@ -25,14 +32,22 @@ describe('Testing the Organization Card', () => { type: 'Post', title: 'Post Title', time: '2023-09-03', + creator: { + email: 'johndoe@example.com', + firstName: 'John', + lastName: 'Doe', + __typename: 'User', + _id: '1', + }, }; render(); expect(screen.getByText(/Post Title/i)).toBeInTheDocument(); expect( - screen.getByText(dayjs(props.time).format('MMM D, YYYY')) + screen.getByText(dayjs(props.time).format('MMM D, YYYY')), ).toBeInTheDocument(); + expect(screen.getByText(/John Doe/i)).toBeInTheDocument(); }); test('Should render props and text elements for Membership Request card', () => { diff --git a/src/components/OrganizationDashCards/CardItem.tsx b/src/components/OrganizationDashCards/CardItem.tsx index bcaaea68c5..b020f1885f 100644 --- a/src/components/OrganizationDashCards/CardItem.tsx +++ b/src/components/OrganizationDashCards/CardItem.tsx @@ -1,8 +1,8 @@ import React from 'react'; -import { ReactComponent as EventsIcon } from 'assets/svgs/events.svg'; +import { ReactComponent as EventsIcon } from 'assets/svgs/cardItemEvent.svg'; import { ReactComponent as PostsIcon } from 'assets/svgs/post.svg'; -import { ReactComponent as MarkerIcon } from 'assets/svgs/location.svg'; -import { ReactComponent as DateIcon } from 'assets/svgs/date.svg'; +import { ReactComponent as MarkerIcon } from 'assets/svgs/cardItemLocation.svg'; +import { ReactComponent as DateIcon } from 'assets/svgs/cardItemDate.svg'; import { ReactComponent as UserIcon } from 'assets/svgs/user.svg'; import dayjs from 'dayjs'; import styles from './CardItem.module.css'; @@ -12,15 +12,20 @@ export interface InterfaceCardItem { type: 'Event' | 'Post' | 'MembershipRequest'; title: string; time?: string; + startdate?: string; + enddate?: string; creator?: any; location?: string; } const cardItem = (props: InterfaceCardItem): JSX.Element => { - const { creator, type, title, time, location } = props; + const { creator, type, title, startdate, time, enddate, location } = props; return ( <> -
    +
    {type == 'Event' ? ( @@ -37,7 +42,6 @@ const cardItem = (props: InterfaceCardItem): JSX.Element => { ) )}
    - {`${title}`}
    {creator && ( @@ -55,23 +59,45 @@ const cardItem = (props: InterfaceCardItem): JSX.Element => { )} + {title && ( + + {title} + + )} + {location && ( - + {' '} {location} )} - {time && ( - + {type == 'Event' && startdate && ( + {type === 'Event' && ( + )}{' '} + {dayjs(startdate).format('MMM D, YYYY')} -{' '} + {dayjs(enddate).format('MMM D, YYYY')} + + )} + {type == 'Post' && time && ( + + {type === 'Post' && ( + diff --git a/src/components/OrganizationScreen/OrganizationScreen.module.css b/src/components/OrganizationScreen/OrganizationScreen.module.css index 681ac8823d..7570b14ced 100644 --- a/src/components/OrganizationScreen/OrganizationScreen.module.css +++ b/src/components/OrganizationScreen/OrganizationScreen.module.css @@ -6,55 +6,170 @@ } .expand { - padding-left: 1.5rem; + padding-left: 4rem; animation: moveLeft 0.5s ease-in-out; } +.avatarStyle { + border-radius: 100%; +} +.profileContainer { + border: none; + padding: 2.1rem 0.5rem; + height: 52px; + border-radius: 8px 0px 0px 8px; + display: flex; + align-items: center; + background-color: white !important; + box-shadow: + 0 4px 4px 0 rgba(177, 177, 177, 0.2), + 0 6px 20px 0 rgba(151, 151, 151, 0.19); +} +.profileContainer:focus { + outline: none; + background-color: var(--bs-gray-100); +} +.imageContainer { + width: 56px; +} +.profileContainer .profileText { + flex: 1; + text-align: start; + overflow: hidden; + margin-right: 4px; +} +.angleDown { + margin-left: 4px; +} +.profileContainer .profileText .primaryText { + font-size: 1rem; + font-weight: 600; + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 2; /* number of lines to show */ + -webkit-box-orient: vertical; + word-wrap: break-word; + white-space: normal; +} +.profileContainer .profileText .secondaryText { + font-size: 0.8rem; + font-weight: 400; + color: var(--bs-secondary); + display: block; + text-transform: capitalize; +} .contract { padding-left: calc(300px + 2rem + 1.5rem); animation: moveRight 0.5s ease-in-out; } +.collapseSidebarButton { + position: fixed; + height: 40px; + bottom: 0; + z-index: 9999; + width: calc(300px + 2rem); + background-color: rgba(245, 245, 245, 0.7); + color: black; + border: none; + border-radius: 0px; +} + +.collapseSidebarButton:hover, +.opendrawer:hover { + opacity: 1; + color: black !important; +} +.opendrawer { + position: fixed; + display: flex; + align-items: center; + justify-content: center; + top: 0; + left: 0; + width: 40px; + height: 100vh; + z-index: 9999; + background-color: rgba(245, 245, 245); + border: none; + border-radius: 0px; + margin-right: 20px; + color: black; +} +.profileDropdown { + background-color: transparent !important; +} +.profileDropdown .dropdown-toggle .btn .btn-normal { + display: none !important; + background-color: transparent !important; +} +.dropdownToggle { + background-image: url(/public/images/svg/angleDown.svg); + background-repeat: no-repeat; + background-position: center; + background-color: azure; +} + +.dropdownToggle::after { + border-top: none !important; + border-bottom: none !important; +} + +.opendrawer:hover { + transition: background-color 0.5s ease; + background-color: var(--bs-primary); +} +.collapseSidebarButton:hover { + transition: background-color 0.5s ease; + background-color: var(--bs-primary); +} + @media (max-width: 1120px) { .contract { - padding-left: calc(250px + 2rem + 1.5rem); + padding-left: calc(276px + 2rem + 1.5rem); + } + .collapseSidebarButton { + width: calc(250px + 2rem); } } -/* For tablets */ -@media (max-width: 820px) { +@media (max-height: 900px) { + .collapseSidebarButton { + height: 30px; + width: calc(300px + 1rem); + } +} +@media (max-height: 650px) { .pageContainer { - padding-left: 1.5rem; + padding: 1rem 1.5rem 0 calc(270px); } - - .contract, - .expand { - animation: none; + .collapseSidebarButton { + width: 250px; + height: 20px; + } + .opendrawer { + width: 30px; } } +/* For tablets */ @media (max-width: 820px) { .pageContainer { - padding: 1rem; - } -} - -@keyframes moveLeft { - from { - padding-left: calc(300px + 2rem + 1.5rem); + padding-left: 2.5rem; } - to { - padding-left: 1.5rem; + .opendrawer { + width: 25px; } -} -@keyframes moveRight { - from { - padding-left: 1.5rem; + .contract, + .expand { + animation: none; } - to { - padding-left: calc(300px + 2rem + 1.5rem); + .collapseSidebarButton { + width: 100%; + left: 0; + right: 0; } } diff --git a/src/components/OrganizationScreen/OrganizationScreen.test.tsx b/src/components/OrganizationScreen/OrganizationScreen.test.tsx index 8df2640990..d31511ea1e 100644 --- a/src/components/OrganizationScreen/OrganizationScreen.test.tsx +++ b/src/components/OrganizationScreen/OrganizationScreen.test.tsx @@ -1,39 +1,117 @@ import React from 'react'; import { MockedProvider } from '@apollo/react-testing'; -import { render, screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; +import { fireEvent, render, screen } from '@testing-library/react'; import { I18nextProvider } from 'react-i18next'; +import 'jest-location-mock'; import { Provider } from 'react-redux'; import { BrowserRouter } from 'react-router-dom'; import { store } from 'state/store'; import i18nForTest from 'utils/i18nForTest'; -import type { InterfaceOrganizationScreenProps } from './OrganizationScreen'; import OrganizationScreen from './OrganizationScreen'; +import { ORGANIZATIONS_LIST } from 'GraphQl/Queries/Queries'; +import { StaticMockLink } from 'utils/StaticMockLink'; -const props: InterfaceOrganizationScreenProps = { - title: 'Dashboard', - screenName: 'Dashboard', - children:
    Testing ...
    , +let mockID: string | undefined = '123'; +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: mockID }), +})); + +const MOCKS = [ + { + request: { + query: ORGANIZATIONS_LIST, + variables: { id: '123' }, + }, + result: { + data: { + organizations: [ + { + _id: '123', + image: null, + creator: { + firstName: 'John', + lastName: 'Doe', + email: 'JohnDoe@example.com', + }, + name: 'Test Organization', + description: 'Testing this organization', + address: { + city: 'Mountain View', + countryCode: 'US', + dependentLocality: 'Some Dependent Locality', + line1: '123 Main Street', + line2: 'Apt 456', + postalCode: '94040', + sortingCode: 'XYZ-789', + state: 'CA', + }, + userRegistrationRequired: true, + visibleInSearch: true, + members: [], + admins: [], + membershipRequests: [], + blockedUsers: [], + }, + ], + }, + }, + }, +]; +const link = new StaticMockLink(MOCKS, true); + +const resizeWindow = (width: number): void => { + window.innerWidth = width; + fireEvent(window, new Event('resize')); +}; + +const clickToggleMenuBtn = (toggleButton: HTMLElement): void => { + fireEvent.click(toggleButton); }; describe('Testing LeftDrawer in OrganizationScreen', () => { test('Testing LeftDrawer in page functionality', async () => { - localStorage.setItem('UserType', 'SUPERADMIN'); + render( + + + + + + + + + , + ); + const toggleButton = screen.getByTestId('closeMenu') as HTMLElement; + const icon = toggleButton.querySelector('i'); + + // Resize window to a smaller width + resizeWindow(800); + clickToggleMenuBtn(toggleButton); + expect(icon).toHaveClass('fa fa-angle-double-left'); + // Resize window back to a larger width + + resizeWindow(1000); + clickToggleMenuBtn(toggleButton); + expect(icon).toHaveClass('fa fa-angle-double-right'); + + clickToggleMenuBtn(toggleButton); + expect(icon).toHaveClass('fa fa-angle-double-left'); + }); + test('should be redirected to / if orgId is undefined', async () => { + mockID = undefined; render( - + - + - + , ); - // sets hideDrawer to true - userEvent.click(screen.getByTestId('menuBtn')); - // sets hideDrawer to false - userEvent.click(screen.getByTestId('menuBtn')); + expect(window.location.pathname).toEqual('/'); }); }); diff --git a/src/components/OrganizationScreen/OrganizationScreen.tsx b/src/components/OrganizationScreen/OrganizationScreen.tsx index de82dc7eec..59b6f289c9 100644 --- a/src/components/OrganizationScreen/OrganizationScreen.tsx +++ b/src/components/OrganizationScreen/OrganizationScreen.tsx @@ -1,66 +1,125 @@ -import MenuIcon from '@mui/icons-material/Menu'; import LeftDrawerOrg from 'components/LeftDrawerOrg/LeftDrawerOrg'; -import React, { useState } from 'react'; -import Button from 'react-bootstrap/Button'; -import styles from './OrganizationScreen.module.css'; -import { useSelector } from 'react-redux'; -import type { TargetsType } from 'state/reducers/routesReducer'; +import React, { useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useDispatch, useSelector } from 'react-redux'; +import { Navigate, Outlet, useLocation, useParams } from 'react-router-dom'; +import { updateTargets } from 'state/action-creators'; import type { RootState } from 'state/reducers'; +import type { TargetsType } from 'state/reducers/routesReducer'; +import styles from './OrganizationScreen.module.css'; +import ProfileDropdown from 'components/ProfileDropdown/ProfileDropdown'; +import { Button } from 'react-bootstrap'; -export interface InterfaceOrganizationScreenProps { - title: string; // Multilingual Page title - screenName: string; // Internal Screen name for developers - children: React.ReactNode; -} -const organizationScreen = ({ - title, - screenName, - children, -}: InterfaceOrganizationScreenProps): JSX.Element => { +const OrganizationScreen = (): JSX.Element => { + const location = useLocation(); + const titleKey: string | undefined = map[location.pathname.split('/')[1]]; + const { t } = useTranslation('translation', { keyPrefix: titleKey }); const [hideDrawer, setHideDrawer] = useState(null); + const { orgId } = useParams(); + + if (!orgId) { + return ; + } const appRoutes: { targets: TargetsType[]; - configUrl: string; } = useSelector((state: RootState) => state.appRoutes); - const { targets, configUrl } = appRoutes; + const { targets } = appRoutes; + + const dispatch = useDispatch(); + useEffect(() => { + dispatch(updateTargets(orgId)); + }, [orgId]); // Added orgId to the dependency array + + const handleResize = (): void => { + if (window.innerWidth <= 820) { + setHideDrawer(!hideDrawer); + } + }; + + useEffect(() => { + handleResize(); + window.addEventListener('resize', handleResize); + return () => { + window.removeEventListener('resize', handleResize); + }; + }, []); + return ( <> - + {hideDrawer ? ( + + ) : ( + + )} +
    + +
    -

    {title}

    +

    {t('title')}

    - +
    - {children} +
    ); }; -export default organizationScreen; +export default OrganizationScreen; + +interface InterfaceMapType { + [key: string]: string; +} + +const map: InterfaceMapType = { + orgdash: 'dashboard', + orgpeople: 'organizationPeople', + requests: 'requests', + orgads: 'advertisement', + member: 'memberDetail', + orgevents: 'organizationEvents', + orgactionitems: 'organizationActionItems', + orgcontribution: 'orgContribution', + orgpost: 'orgPost', + orgfunds: 'funds', + orgfundcampaign: 'fundCampaign', + fundCampaignPledge: 'pledges', + orgsetting: 'orgSettings', + orgstore: 'addOnStore', + blockuser: 'blockUnblockUser', + orgvenues: 'organizationVenues', + event: 'eventManagement', +}; diff --git a/src/components/Pagination/Pagination.test.tsx b/src/components/Pagination/Pagination.test.tsx index 88bb3752c5..b8161c4c84 100644 --- a/src/components/Pagination/Pagination.test.tsx +++ b/src/components/Pagination/Pagination.test.tsx @@ -2,11 +2,10 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; import { Provider } from 'react-redux'; import { BrowserRouter } from 'react-router-dom'; -import { createTheme } from '@mui/material/styles'; +import { createTheme, ThemeProvider } from '@mui/material/styles'; import Pagination from './Pagination'; import { store } from 'state/store'; import userEvent from '@testing-library/user-event'; -import { ThemeProvider } from '@mui/material/styles'; describe('Testing Pagination component', () => { const props = { @@ -24,7 +23,7 @@ describe('Testing Pagination component', () => { - + , ); userEvent.click(screen.getByTestId(/nextPage/i)); @@ -54,7 +53,7 @@ test('Component should be rendered properly', () => { - + , ); userEvent.click(screen.getByTestId(/nextPage/i)); diff --git a/src/components/Pagination/Pagination.tsx b/src/components/Pagination/Pagination.tsx index 1a4b1d5921..ce7192e2a4 100644 --- a/src/components/Pagination/Pagination.tsx +++ b/src/components/Pagination/Pagination.tsx @@ -13,7 +13,7 @@ interface InterfaceTablePaginationActionsProps { rowsPerPage: number; onPageChange: ( event: React.MouseEvent, - newPage: number + newPage: number, ) => void; } @@ -23,27 +23,27 @@ function pagination(props: InterfaceTablePaginationActionsProps): JSX.Element { /* istanbul ignore next */ const handleFirstPageButtonClick = ( - event: React.MouseEvent + event: React.MouseEvent, ): void => { onPageChange(event, 0); }; const handleBackButtonClick = ( - event: React.MouseEvent + event: React.MouseEvent, ): void => { onPageChange(event, page - 1); }; /* istanbul ignore next */ const handleNextButtonClick = ( - event: React.MouseEvent + event: React.MouseEvent, ): void => { onPageChange(event, page + 1); }; /* istanbul ignore next */ const handleLastPageButtonClick = ( - event: React.MouseEvent + event: React.MouseEvent, ): void => { onPageChange(event, Math.max(0, Math.ceil(count / rowsPerPage) - 1)); }; diff --git a/src/components/PaginationList/PaginationList.tsx b/src/components/PaginationList/PaginationList.tsx index 562f5204bb..3c0928f7fb 100644 --- a/src/components/PaginationList/PaginationList.tsx +++ b/src/components/PaginationList/PaginationList.tsx @@ -11,10 +11,10 @@ interface InterfacePropsInterface { page: number; onPageChange: ( event: React.MouseEvent | null, - newPage: number + newPage: number, ) => void; onRowsPerPageChange: ( - event: React.ChangeEvent + event: React.ChangeEvent, ) => void; } diff --git a/src/components/ProfileDropdown/ProfileDropdown.module.css b/src/components/ProfileDropdown/ProfileDropdown.module.css new file mode 100644 index 0000000000..46af582126 --- /dev/null +++ b/src/components/ProfileDropdown/ProfileDropdown.module.css @@ -0,0 +1,75 @@ +.profileContainer { + border: none; + padding: 2.1rem 0.5rem; + height: 52px; + border-radius: 8px 0px 0px 8px; + display: flex; + align-items: center; + background-color: white !important; + box-shadow: + 0 4px 4px 0 rgba(177, 177, 177, 0.2), + 0 6px 44px 0 rgba(246, 246, 246, 0.19); +} +.profileContainer:focus { + outline: none; + background-color: var(--bs-gray-100); +} +.imageContainer { + width: 56px; + height: 56px; + border-radius: 100%; + margin-right: 10px; +} +.imageContainer img { + width: 100%; + height: 100%; + object-fit: cover; + border-radius: 100%; +} +.profileContainer .profileText { + flex: 1; + text-align: start; + overflow: hidden; + margin-right: 4px; +} +.angleDown { + margin-left: 4px; +} +.profileContainer .profileText .primaryText { + font-size: 1rem; + font-weight: 600; + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 2; /* number of lines to show */ + -webkit-box-orient: vertical; + word-wrap: break-word; + white-space: normal; +} +.profileContainer .profileText .secondaryText { + font-size: 0.8rem; + font-weight: 400; + color: var(--bs-secondary); + display: block; + text-transform: capitalize; +} +.profileDropdown { + background-color: transparent !important; +} +.profileDropdown .dropdown-toggle .btn .btn-normal { + display: none !important; + background-color: transparent !important; +} +.dropdownToggle { + background-image: url(/public/images/svg/angleDown.svg); + background-repeat: no-repeat; + background-position: center; + background-color: azure; +} + +.dropdownToggle::after { + border-top: none !important; + border-bottom: none !important; +} +.avatarStyle { + border-radius: 100%; +} diff --git a/src/components/ProfileDropdown/ProfileDropdown.test.tsx b/src/components/ProfileDropdown/ProfileDropdown.test.tsx new file mode 100644 index 0000000000..73d32f5022 --- /dev/null +++ b/src/components/ProfileDropdown/ProfileDropdown.test.tsx @@ -0,0 +1,127 @@ +import React from 'react'; +import { act, render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { BrowserRouter } from 'react-router-dom'; +import ProfileDropdown from './ProfileDropdown'; +import 'jest-localstorage-mock'; +import { MockedProvider } from '@apollo/react-testing'; +import { REVOKE_REFRESH_TOKEN } from 'GraphQl/Mutations/mutations'; +import useLocalStorage from 'utils/useLocalstorage'; + +const { setItem } = useLocalStorage(); +const MOCKS = [ + { + request: { + query: REVOKE_REFRESH_TOKEN, + }, + result: { + data: { + revokeRefreshTokenForUser: true, + }, + }, + }, +]; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }, + clear: jest.fn(), +})); + +beforeEach(() => { + setItem('FirstName', 'John'); + setItem('LastName', 'Doe'); + setItem( + 'UserImage', + 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', + ); + setItem('SuperAdmin', false); + setItem('AdminFor', []); + setItem('id', '123'); +}); + +afterEach(() => { + jest.clearAllMocks(); + localStorage.clear(); +}); +afterEach(() => { + jest.clearAllMocks(); + localStorage.clear(); +}); + +describe('ProfileDropdown Component', () => { + test('renders with user information', () => { + render( + + + + + , + ); + + expect(screen.getByTestId('display-name')).toBeInTheDocument(); + expect(screen.getByText('John Doe')).toBeInTheDocument(); + expect(screen.getByText('User')).toBeInTheDocument(); + expect(screen.getByTestId('display-type')).toBeInTheDocument(); + expect(screen.getByAltText('profile picture')).toBeInTheDocument(); + }); + + test('renders Super admin', () => { + setItem('SuperAdmin', true); + render( + + + + + , + ); + expect(screen.getByText('SuperAdmin')).toBeInTheDocument(); + }); + test('renders Admin', () => { + setItem('AdminFor', ['123']); + render( + + + + + , + ); + expect(screen.getByText('Admin')).toBeInTheDocument(); + }); + + test('logout functionality clears local storage and redirects to home', async () => { + render( + + + + + , + ); + await act(async () => { + userEvent.click(screen.getByTestId('togDrop')); + }); + + userEvent.click(screen.getByTestId('logoutBtn')); + expect(global.window.location.pathname).toBe('/'); + }); + describe('Member screen routing testing', () => { + test('member screen', async () => { + render( + + + + + , + ); + await act(async () => { + userEvent.click(screen.getByTestId('togDrop')); + }); + + userEvent.click(screen.getByTestId('profileBtn')); + expect(global.window.location.pathname).toBe('/user/settings'); + }); + }); +}); diff --git a/src/components/ProfileDropdown/ProfileDropdown.tsx b/src/components/ProfileDropdown/ProfileDropdown.tsx new file mode 100644 index 0000000000..f5c3af8664 --- /dev/null +++ b/src/components/ProfileDropdown/ProfileDropdown.tsx @@ -0,0 +1,107 @@ +import Avatar from 'components/Avatar/Avatar'; +import React from 'react'; +import { ButtonGroup, Dropdown } from 'react-bootstrap'; +import { useNavigate } from 'react-router-dom'; +import useLocalStorage from 'utils/useLocalstorage'; +import styles from './ProfileDropdown.module.css'; +import { REVOKE_REFRESH_TOKEN } from 'GraphQl/Mutations/mutations'; +import { useMutation } from '@apollo/client'; + +const profileDropdown = (): JSX.Element => { + const [revokeRefreshToken] = useMutation(REVOKE_REFRESH_TOKEN); + const { getItem } = useLocalStorage(); + const superAdmin = getItem('SuperAdmin'); + const adminFor = getItem('AdminFor'); + const userRole = superAdmin + ? 'SuperAdmin' + : adminFor?.length > 0 + ? 'Admin' + : 'User'; + const firstName = getItem('FirstName'); + const lastName = getItem('LastName'); + const userImage = getItem('UserImage'); + const userID = getItem('id'); + const navigate = useNavigate(); + + const logout = async (): Promise => { + try { + await revokeRefreshToken(); + } catch (error) { + /*istanbul ignore next*/ + console.error('Error revoking refresh token:', error); + } + localStorage.clear(); + navigate('/'); + }; + const MAX_NAME_LENGTH = 20; + const fullName = `${firstName} ${lastName}`; + const displayedName = + fullName.length > MAX_NAME_LENGTH + ? /*istanbul ignore next*/ + fullName.substring(0, MAX_NAME_LENGTH - 3) + '...' + : fullName; + + return ( + +
    +
    + {userImage && userImage !== 'null' ? ( + /*istanbul ignore next*/ + {`profile + ) : ( + + )} +
    +
    + + {displayedName} + + + {`${userRole}`} + +
    +
    + + + + userRole === 'User' + ? navigate(`/user/settings`) + : navigate(`/member/${userID}`) + } + aria-label="View Profile" + > + View Profile + + + Logout + + +
    + ); +}; + +export default profileDropdown; diff --git a/src/components/RecurrenceOptions/CustomRecurrence.test.tsx b/src/components/RecurrenceOptions/CustomRecurrence.test.tsx new file mode 100644 index 0000000000..f21553c5af --- /dev/null +++ b/src/components/RecurrenceOptions/CustomRecurrence.test.tsx @@ -0,0 +1,721 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { + act, + render, + screen, + fireEvent, + waitFor, +} from '@testing-library/react'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import 'jest-location-mock'; +import { I18nextProvider } from 'react-i18next'; + +import OrganizationEvents from '../../screens/OrganizationEvents/OrganizationEvents'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import userEvent from '@testing-library/user-event'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { toast } from 'react-toastify'; +import { createTheme } from '@mui/material'; +import { ThemeProvider } from 'react-bootstrap'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { MOCKS } from '../../screens/OrganizationEvents/OrganizationEventsMocks'; + +const theme = createTheme({ + palette: { + primary: { + main: '#31bb6b', + }, + }, +}); + +const link = new StaticMockLink(MOCKS, true); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +const translations = JSON.parse( + JSON.stringify( + i18nForTest.getDataByLanguage('en')?.translation.organizationEvents, + ), +); + +jest.mock('@mui/x-date-pickers/DateTimePicker', () => { + return { + DateTimePicker: jest.requireActual( + '@mui/x-date-pickers/DesktopDateTimePicker', + ).DesktopDateTimePicker, + }; +}); + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + warning: jest.fn(), + error: jest.fn(), + }, +})); + +describe('Testing the creaction of recurring events with custom recurrence patterns', () => { + const formData = { + title: 'Dummy Org', + description: 'This is a dummy organization', + startDate: '03/28/2022', + endDate: '03/30/2022', + recurrenceEndDate: '04/15/2023', + location: 'New Delhi', + startTime: '09:00 AM', + endTime: '05:00 PM', + }; + + test('Changing the recurrence frequency', async () => { + render( + + + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('createEventModalBtn')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('createEventModalBtn')); + + await waitFor(() => { + expect(screen.getByTestId('recurringCheck')).toBeInTheDocument(); + }); + + expect(screen.queryByTestId('recurrenceOptions')).not.toBeInTheDocument(); + + userEvent.click(screen.getByTestId('recurringCheck')); + + await waitFor(() => { + expect(screen.getByTestId('recurrenceOptions')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('recurrenceOptions')); + + await waitFor(() => { + expect(screen.getByTestId('customRecurrence')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('customRecurrence')); + + await waitFor(() => { + expect( + screen.getByTestId('customRecurrenceFrequencyDropdown'), + ).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('customRecurrenceFrequencyDropdown')); + + await waitFor(() => { + expect(screen.getByTestId('customDailyRecurrence')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('customDailyRecurrence')); + + await waitFor(() => { + expect( + screen.getByTestId('customRecurrenceFrequencyDropdown'), + ).toHaveTextContent('Day'); + }); + + userEvent.click(screen.getByTestId('customRecurrenceFrequencyDropdown')); + + await waitFor(() => { + expect(screen.getByTestId('customWeeklyRecurrence')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('customWeeklyRecurrence')); + + await waitFor(() => { + expect( + screen.getByTestId('customRecurrenceFrequencyDropdown'), + ).toHaveTextContent('Week'); + }); + + userEvent.click(screen.getByTestId('customRecurrenceFrequencyDropdown')); + + await waitFor(() => { + expect(screen.getByTestId('customMonthlyRecurrence')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('customMonthlyRecurrence')); + + await waitFor(() => { + expect( + screen.getByTestId('customRecurrenceFrequencyDropdown'), + ).toHaveTextContent('Month'); + }); + + userEvent.click(screen.getByTestId('customRecurrenceFrequencyDropdown')); + + await waitFor(() => { + expect(screen.getByTestId('customYearlyRecurrence')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('customYearlyRecurrence')); + + await waitFor(() => { + expect( + screen.getByTestId('customRecurrenceFrequencyDropdown'), + ).toHaveTextContent('Year'); + }); + + userEvent.click(screen.getByTestId('customRecurrenceSubmitBtn')); + await waitFor(() => { + expect( + screen.queryByTestId('customRecurrenceSubmitBtn'), + ).not.toBeInTheDocument(); + }); + }); + + test('Selecting and unselecting recurrence weekdays', async () => { + render( + + + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('createEventModalBtn')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('createEventModalBtn')); + + await waitFor(() => { + expect(screen.getByTestId('recurringCheck')).toBeInTheDocument(); + }); + + expect(screen.queryByTestId('recurrenceOptions')).not.toBeInTheDocument(); + + userEvent.click(screen.getByTestId('recurringCheck')); + + await waitFor(() => { + expect(screen.getByTestId('recurrenceOptions')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('recurrenceOptions')); + + await waitFor(() => { + expect(screen.getByTestId('customRecurrence')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('customRecurrence')); + + await waitFor(() => { + expect( + screen.getByTestId('customRecurrenceSubmitBtn'), + ).toBeInTheDocument(); + }); + + const weekDaysOptions = screen.getAllByTestId('recurrenceWeekDay'); + + weekDaysOptions.forEach((weekDay) => { + userEvent.click(weekDay); + }); + + weekDaysOptions.forEach((weekDay) => { + userEvent.click(weekDay); + }); + + userEvent.click(screen.getByTestId('customRecurrenceSubmitBtn')); + await waitFor(() => { + expect( + screen.queryByTestId('customRecurrenceSubmitBtn'), + ).not.toBeInTheDocument(); + }); + }); + + test('Selecting different monthly recurrence options from the dropdown menu', async () => { + render( + + + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('createEventModalBtn')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('createEventModalBtn')); + + const startDatePicker = screen.getByLabelText('Start Date'); + fireEvent.change(startDatePicker, { + target: { value: formData.startDate }, + }); + + const endDatePicker = screen.getByLabelText('End Date'); + fireEvent.change(endDatePicker, { + target: { value: formData.endDate }, + }); + + await waitFor(() => { + expect(screen.getByTestId('recurringCheck')).toBeInTheDocument(); + }); + + expect(screen.queryByTestId('recurrenceOptions')).not.toBeInTheDocument(); + + userEvent.click(screen.getByTestId('recurringCheck')); + + await waitFor(() => { + expect(screen.getByTestId('recurrenceOptions')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('recurrenceOptions')); + + await waitFor(() => { + expect(screen.getByTestId('customRecurrence')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('customRecurrence')); + + await waitFor(() => { + expect( + screen.getByTestId('customRecurrenceFrequencyDropdown'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('customRecurrenceFrequencyDropdown')); + + await waitFor(() => { + expect(screen.getByTestId('customMonthlyRecurrence')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('customMonthlyRecurrence')); + + await waitFor(() => { + expect( + screen.getByTestId('customRecurrenceFrequencyDropdown'), + ).toHaveTextContent('Month'); + }); + + await waitFor(() => { + expect(screen.getByTestId('monthlyRecurrenceOptions')).toHaveTextContent( + 'Monthly on Day 28', + ); + }); + + userEvent.click(screen.getByTestId('monthlyRecurrenceOptions')); + + await waitFor(() => { + expect( + screen.getByTestId('monthlyRecurrenceOptionOnThatOccurence'), + ).toBeInTheDocument(); + }); + userEvent.click( + screen.getByTestId('monthlyRecurrenceOptionOnThatOccurence'), + ); + + await waitFor(() => { + expect(screen.getByTestId('monthlyRecurrenceOptions')).toHaveTextContent( + 'Monthly on Fourth Monday', + ); + }); + + userEvent.click(screen.getByTestId('monthlyRecurrenceOptions')); + + await waitFor(() => { + expect( + screen.getByTestId('monthlyRecurrenceOptionOnLastOccurence'), + ).toBeInTheDocument(); + }); + userEvent.click( + screen.getByTestId('monthlyRecurrenceOptionOnLastOccurence'), + ); + + await waitFor(() => { + expect(screen.getByTestId('monthlyRecurrenceOptions')).toHaveTextContent( + 'Monthly on Last Monday', + ); + }); + + userEvent.click(screen.getByTestId('monthlyRecurrenceOptions')); + + await waitFor(() => { + expect( + screen.getByTestId('monthlyRecurrenceOptionOnThatDay'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('monthlyRecurrenceOptionOnThatDay')); + + await waitFor(() => { + expect(screen.getByTestId('monthlyRecurrenceOptions')).toHaveTextContent( + 'Monthly on Day 28', + ); + }); + }); + + test('Selecting the "Ends on" option for specifying the end of recurrence', async () => { + // i.e. when would the recurring event end: never, on a certain date, or after a certain number of occurences + render( + + + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('createEventModalBtn')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('createEventModalBtn')); + + await waitFor(() => { + expect(screen.getByTestId('recurringCheck')).toBeInTheDocument(); + }); + + expect(screen.queryByTestId('recurrenceOptions')).not.toBeInTheDocument(); + + userEvent.click(screen.getByTestId('recurringCheck')); + + await waitFor(() => { + expect(screen.getByTestId('recurrenceOptions')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('recurrenceOptions')); + + await waitFor(() => { + expect(screen.getByTestId('customRecurrence')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('customRecurrence')); + + await waitFor(() => { + expect(screen.getByTestId('never')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('never')); + userEvent.click(screen.getByTestId('on')); + userEvent.click(screen.getByTestId('after')); + userEvent.click(screen.getByTestId('never')); + + userEvent.click(screen.getByTestId('customRecurrenceSubmitBtn')); + await waitFor(() => { + expect( + screen.queryByTestId('customRecurrenceSubmitBtn'), + ).not.toBeInTheDocument(); + }); + }); + + test('Creating a bi monthly recurring event through custom recurrence modal', async () => { + render( + + + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('createEventModalBtn')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('createEventModalBtn')); + + await waitFor(() => { + expect(screen.getByPlaceholderText(/Enter Title/i)).toBeInTheDocument(); + }); + + userEvent.type(screen.getByPlaceholderText(/Enter Title/i), formData.title); + + userEvent.type( + screen.getByPlaceholderText(/Enter Description/i), + formData.description, + ); + + userEvent.type( + screen.getByPlaceholderText(/Enter Location/i), + formData.location, + ); + + const startDatePicker = screen.getByLabelText('Start Date'); + fireEvent.change(startDatePicker, { + target: { value: formData.startDate }, + }); + + const eventEndDatePicker = screen.getByLabelText('End Date'); + fireEvent.change(eventEndDatePicker, { + target: { value: formData.endDate }, + }); + + userEvent.click(screen.getByTestId('recurringCheck')); + + await waitFor(() => { + expect(screen.getByTestId('recurrenceOptions')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('recurrenceOptions')); + + await waitFor(() => { + expect(screen.getByTestId('customRecurrence')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('customRecurrence')); + + userEvent.click(screen.getByTestId('customRecurrenceFrequencyDropdown')); + + await waitFor(() => { + expect(screen.getByTestId('customMonthlyRecurrence')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('customMonthlyRecurrence')); + + await waitFor(() => { + expect( + screen.getByTestId('customRecurrenceFrequencyDropdown'), + ).toHaveTextContent('Month'); + }); + + userEvent.click(screen.getByTestId('monthlyRecurrenceOptions')); + + await waitFor(() => { + expect( + screen.getByTestId('monthlyRecurrenceOptionOnThatOccurence'), + ).toBeInTheDocument(); + }); + userEvent.click( + screen.getByTestId('monthlyRecurrenceOptionOnThatOccurence'), + ); + + await waitFor(() => { + expect(screen.getByTestId('on')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('on')); + + await waitFor(() => { + expect(screen.getByTestId('on')).toBeChecked(); + }); + + await waitFor(() => { + expect(screen.getAllByLabelText('End Date')[1]).toBeEnabled(); + }); + + const recurrenceEndDatePicker = screen.getAllByLabelText('End Date')[1]; + fireEvent.change(recurrenceEndDatePicker, { + target: { value: formData.recurrenceEndDate }, + }); + + await waitFor(() => { + expect( + screen.getByTestId('customRecurrenceIntervalInput'), + ).toBeInTheDocument(); + }); + + const recurrenceCount = screen.getByTestId('customRecurrenceIntervalInput'); + fireEvent.change(recurrenceCount, { + target: { value: 2 }, + }); + + userEvent.click(screen.getByTestId('customRecurrenceSubmitBtn')); + await waitFor(() => { + expect( + screen.queryByTestId('customRecurrenceSubmitBtn'), + ).not.toBeInTheDocument(); + }); + + expect(screen.getByTestId('recurrenceOptions')).toHaveTextContent( + 'Every 2 months on Fourth Monday, until April...', + // "..." because of the overlay component that would trim the recurrence rule text at 45 characters + ); + + userEvent.click(screen.getByTestId('createEventBtn')); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.eventCreated); + }); + + await waitFor(() => { + expect( + screen.queryByTestId('createEventModalCloseBtn'), + ).not.toBeInTheDocument(); + }); + }); + + test('Creating a daily recurring event with a certain number of occurences', async () => { + render( + + + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('createEventModalBtn')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('createEventModalBtn')); + + await waitFor(() => { + expect(screen.getByPlaceholderText(/Enter Title/i)).toBeInTheDocument(); + }); + + userEvent.type(screen.getByPlaceholderText(/Enter Title/i), formData.title); + + userEvent.type( + screen.getByPlaceholderText(/Enter Description/i), + formData.description, + ); + + userEvent.type( + screen.getByPlaceholderText(/Enter Location/i), + formData.location, + ); + + const startDatePicker = screen.getByLabelText('Start Date'); + const endDatePicker = screen.getByLabelText('End Date'); + + fireEvent.change(startDatePicker, { + target: { value: formData.startDate }, + }); + + fireEvent.change(endDatePicker, { + target: { value: formData.endDate }, + }); + + userEvent.click(screen.getByTestId('recurringCheck')); + + await waitFor(() => { + expect(screen.getByTestId('recurrenceOptions')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('recurrenceOptions')); + + await waitFor(() => { + expect(screen.getByTestId('customRecurrence')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('customRecurrence')); + + userEvent.click(screen.getByTestId('customRecurrenceFrequencyDropdown')); + + await waitFor(() => { + expect(screen.getByTestId('customDailyRecurrence')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('customDailyRecurrence')); + + await waitFor(() => { + expect( + screen.getByTestId('customRecurrenceFrequencyDropdown'), + ).toHaveTextContent('Day'); + }); + + await waitFor(() => { + expect(screen.getByTestId('after')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('after')); + + await waitFor(() => { + expect(screen.getByTestId('after')).toBeChecked(); + }); + + await waitFor(() => { + expect( + screen.getByTestId('customRecurrenceCountInput'), + ).toBeInTheDocument(); + }); + + const recurrenceCount = screen.getByTestId('customRecurrenceCountInput'); + fireEvent.change(recurrenceCount, { + target: { value: 100 }, + }); + + await waitFor(() => { + expect(screen.getByTestId('customRecurrenceCountInput')).toHaveValue(100); + }); + + userEvent.click(screen.getByTestId('customRecurrenceSubmitBtn')); + await waitFor(() => { + expect( + screen.queryByTestId('customRecurrenceSubmitBtn'), + ).not.toBeInTheDocument(); + }); + + expect(screen.getByTestId('recurrenceOptions')).toHaveTextContent( + 'Daily, 100 times', + ); + + userEvent.click(screen.getByTestId('createEventBtn')); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.eventCreated); + }); + + await waitFor(() => { + expect( + screen.queryByTestId('createEventModalCloseBtn'), + ).not.toBeInTheDocument(); + }); + }); +}); diff --git a/src/components/RecurrenceOptions/CustomRecurrenceModal.module.css b/src/components/RecurrenceOptions/CustomRecurrenceModal.module.css new file mode 100644 index 0000000000..5fe5d33c47 --- /dev/null +++ b/src/components/RecurrenceOptions/CustomRecurrenceModal.module.css @@ -0,0 +1,59 @@ +.titlemodal { + color: #707070; + font-weight: 600; + font-size: 20px; + margin-bottom: 20px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 65%; +} + +.recurrenceRuleNumberInput { + width: 70px; +} + +.recurrenceRuleDateBox { + width: 70%; +} + +.recurrenceDayButton { + width: 33px; + height: 33px; + border: 1px solid var(--bs-gray); + cursor: pointer; + transition: background-color 0.3s; + display: inline-flex; + justify-content: center; + align-items: center; + margin-right: 0.5rem; + border-radius: 50%; +} + +.recurrenceDayButton:hover { + background-color: var(--bs-gray); +} + +.recurrenceDayButton.selected { + background-color: var(--bs-primary); + border-color: var(--bs-primary); + color: var(--bs-white); +} + +.recurrenceDayButton span { + color: var(--bs-gray); + padding: 0.25rem; + text-align: center; +} + +.recurrenceDayButton:hover span { + color: var(--bs-white); +} + +.recurrenceDayButton.selected span { + color: var(--bs-white); +} + +.recurrenceRuleSubmitBtn { + margin-left: 82%; + padding: 7px 15px; +} diff --git a/src/components/RecurrenceOptions/CustomRecurrenceModal.tsx b/src/components/RecurrenceOptions/CustomRecurrenceModal.tsx new file mode 100644 index 0000000000..890caaabdb --- /dev/null +++ b/src/components/RecurrenceOptions/CustomRecurrenceModal.tsx @@ -0,0 +1,398 @@ +import React, { useEffect, useState } from 'react'; +import { Button, Dropdown, Form, FormControl, Modal } from 'react-bootstrap'; +import styles from './CustomRecurrenceModal.module.css'; +import { DatePicker } from '@mui/x-date-pickers'; +import { + Days, + Frequency, + daysOptions, + endsAfter, + endsNever, + endsOn, + frequencies, + getRecurrenceRuleText, + getWeekDayOccurenceInMonth, + isLastOccurenceOfWeekDay, + recurrenceEndOptions, +} from 'utils/recurrenceUtils'; +import type { + InterfaceRecurrenceRuleState, + RecurrenceEndOption, + WeekDays, +} from 'utils/recurrenceUtils'; +import type { Dayjs } from 'dayjs'; +import dayjs from 'dayjs'; + +interface InterfaceCustomRecurrenceModalProps { + recurrenceRuleState: InterfaceRecurrenceRuleState; + recurrenceRuleText: string; + setRecurrenceRuleState: ( + state: React.SetStateAction, + ) => void; + customRecurrenceModalIsOpen: boolean; + hideCustomRecurrenceModal: () => void; + setCustomRecurrenceModalIsOpen: ( + state: React.SetStateAction, + ) => void; + t: (key: string) => string; +} + +const CustomRecurrenceModal: React.FC = ({ + recurrenceRuleState, + recurrenceRuleText, + setRecurrenceRuleState, + customRecurrenceModalIsOpen, + hideCustomRecurrenceModal, + setCustomRecurrenceModalIsOpen, + t, +}) => { + const { + recurrenceStartDate, + recurrenceEndDate, + frequency, + weekDays, + interval, + count, + } = recurrenceRuleState; + const [selectedRecurrenceEndOption, setSelectedRecurrenceEndOption] = + useState(endsNever); + + useEffect(() => { + if (recurrenceEndDate) { + setSelectedRecurrenceEndOption(endsOn); + } else if (count) { + setSelectedRecurrenceEndOption(endsAfter); + } + }, [recurrenceRuleState]); + + const handleRecurrenceEndOptionChange = ( + e: React.ChangeEvent, + ): void => { + const selectedRecurrenceEndOption = e.target.value as RecurrenceEndOption; + setSelectedRecurrenceEndOption(selectedRecurrenceEndOption); + if (selectedRecurrenceEndOption === endsNever) { + setRecurrenceRuleState({ + ...recurrenceRuleState, + recurrenceEndDate: null, + count: undefined, + }); + } + if (selectedRecurrenceEndOption === endsOn) { + setRecurrenceRuleState({ + ...recurrenceRuleState, + recurrenceEndDate: dayjs().add(1, 'month').toDate(), + count: undefined, + }); + } + if (selectedRecurrenceEndOption === endsAfter) { + setRecurrenceRuleState({ + ...recurrenceRuleState, + recurrenceEndDate: null, + count: 10, + }); + } + }; + + const handleDayClick = (day: WeekDays): void => { + if (weekDays !== undefined && weekDays.includes(day)) { + setRecurrenceRuleState({ + ...recurrenceRuleState, + weekDays: weekDays.filter((d) => d !== day), + weekDayOccurenceInMonth: undefined, + }); + } else { + setRecurrenceRuleState({ + ...recurrenceRuleState, + weekDays: [...(weekDays ?? []), day], + weekDayOccurenceInMonth: undefined, + }); + } + }; + + const handleCustomRecurrenceSubmit = (): void => { + setCustomRecurrenceModalIsOpen(!customRecurrenceModalIsOpen); + }; + + return ( + <> + + +

    {t('customRecurrence')}

    + +
    + +
    + + {t('repeatsEvery')} + {' '} + + setRecurrenceRuleState({ + ...recurrenceRuleState, + interval: Number(e.target.value), + }) + } + /> + + + {`${frequencies[frequency]}${interval && interval > 1 ? 's' : ''}`} + + + + + setRecurrenceRuleState({ + ...recurrenceRuleState, + frequency: Frequency.DAILY, + weekDayOccurenceInMonth: undefined, + }) + } + data-testid="customDailyRecurrence" + > + {interval && interval > 1 ? 'Days' : 'Day'} + + + setRecurrenceRuleState({ + ...recurrenceRuleState, + frequency: Frequency.WEEKLY, + weekDays: [Days[recurrenceStartDate.getDay()]], + weekDayOccurenceInMonth: undefined, + }) + } + data-testid="customWeeklyRecurrence" + > + {interval && interval > 1 ? 'Weeks' : 'Week'} + + + setRecurrenceRuleState({ + ...recurrenceRuleState, + frequency: Frequency.MONTHLY, + weekDayOccurenceInMonth: undefined, + }) + } + data-testid="customMonthlyRecurrence" + > + {interval && interval > 1 ? 'Months' : 'Month'} + + + setRecurrenceRuleState({ + ...recurrenceRuleState, + frequency: Frequency.YEARLY, + weekDayOccurenceInMonth: undefined, + }) + } + data-testid="customYearlyRecurrence" + > + {interval && interval > 1 ? 'Years' : 'Year'} + + + +
    + + {frequency === Frequency.WEEKLY && ( +
    + + {t('repeatsOn')} + +
    +
    + {daysOptions.map((day, index) => ( +
    handleDayClick(Days[index])} + data-testid="recurrenceWeekDay" + > + {day} +
    + ))} +
    +
    + )} + + {frequency === Frequency.MONTHLY && ( +
    + + + {recurrenceRuleText} + + + + setRecurrenceRuleState({ + ...recurrenceRuleState, + frequency: Frequency.MONTHLY, + weekDayOccurenceInMonth: undefined, + }) + } + data-testid="monthlyRecurrenceOptionOnThatDay" + > + + {getRecurrenceRuleText({ + ...recurrenceRuleState, + frequency: Frequency.MONTHLY, + weekDayOccurenceInMonth: undefined, + })} + + + {getWeekDayOccurenceInMonth(recurrenceStartDate) !== 5 && ( + + setRecurrenceRuleState({ + ...recurrenceRuleState, + frequency: Frequency.MONTHLY, + weekDays: [Days[recurrenceStartDate.getDay()]], + weekDayOccurenceInMonth: + getWeekDayOccurenceInMonth(recurrenceStartDate), + }) + } + data-testid="monthlyRecurrenceOptionOnThatOccurence" + > + + {getRecurrenceRuleText({ + ...recurrenceRuleState, + frequency: Frequency.MONTHLY, + weekDays: [Days[recurrenceStartDate.getDay()]], + weekDayOccurenceInMonth: + getWeekDayOccurenceInMonth(recurrenceStartDate), + })} + + + )} + {isLastOccurenceOfWeekDay(recurrenceStartDate) && ( + + setRecurrenceRuleState({ + ...recurrenceRuleState, + frequency: Frequency.MONTHLY, + weekDays: [Days[recurrenceStartDate.getDay()]], + weekDayOccurenceInMonth: -1, + }) + } + data-testid="monthlyRecurrenceOptionOnLastOccurence" + > + + {getRecurrenceRuleText({ + ...recurrenceRuleState, + frequency: Frequency.MONTHLY, + weekDays: [Days[recurrenceStartDate.getDay()]], + weekDayOccurenceInMonth: -1, + })} + + + )} + + +
    + )} + +
    + {t('ends')} +
    +
    + {recurrenceEndOptions.map((option, index) => ( +
    + + + {option === endsOn && ( +
    + { + /* istanbul ignore next */ + if (date) { + setRecurrenceRuleState({ + ...recurrenceRuleState, + recurrenceEndDate: date?.toDate(), + }); + } + }} + /> +
    + )} + {option === endsAfter && ( + <> + + setRecurrenceRuleState({ + ...recurrenceRuleState, + count: Number(e.target.value), + }) + } + className={`${styles.recurrenceRuleNumberInput} ms-1 me-2 d-inline-block py-2`} + disabled={selectedRecurrenceEndOption !== endsAfter} + data-testid="customRecurrenceCountInput" + />{' '} + {t('occurences')} + + )} +
    + ))} +
    +
    +
    + +
    + +
    + +
    +
    +
    + + ); +}; + +export default CustomRecurrenceModal; diff --git a/src/components/RecurrenceOptions/RecurrenceOptions.test.tsx b/src/components/RecurrenceOptions/RecurrenceOptions.test.tsx new file mode 100644 index 0000000000..5e32a6ec8b --- /dev/null +++ b/src/components/RecurrenceOptions/RecurrenceOptions.test.tsx @@ -0,0 +1,583 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { + act, + render, + screen, + fireEvent, + waitFor, +} from '@testing-library/react'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import 'jest-location-mock'; +import { I18nextProvider } from 'react-i18next'; + +import OrganizationEvents from '../../screens/OrganizationEvents/OrganizationEvents'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import userEvent from '@testing-library/user-event'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { toast } from 'react-toastify'; +import { createTheme } from '@mui/material'; +import { ThemeProvider } from 'react-bootstrap'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { MOCKS } from '../../screens/OrganizationEvents/OrganizationEventsMocks'; + +const theme = createTheme({ + palette: { + primary: { + main: '#31bb6b', + }, + }, +}); + +const link = new StaticMockLink(MOCKS, true); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +const translations = JSON.parse( + JSON.stringify( + i18nForTest.getDataByLanguage('en')?.translation.organizationEvents, + ), +); + +jest.mock('@mui/x-date-pickers/DateTimePicker', () => { + return { + DateTimePicker: jest.requireActual( + '@mui/x-date-pickers/DesktopDateTimePicker', + ).DesktopDateTimePicker, + }; +}); + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + warning: jest.fn(), + error: jest.fn(), + }, +})); + +describe('Testing the creaction of recurring events through recurrence options', () => { + const formData = { + title: 'Dummy Org', + description: 'This is a dummy organization', + startDate: '03/28/2022', + endDate: '03/30/2022', + location: 'New Delhi', + startTime: '09:00 AM', + endTime: '05:00 PM', + }; + + test('Recurrence options Dropdown shows up after checking the Recurring switch', async () => { + render( + + + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('createEventModalBtn')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('createEventModalBtn')); + + await waitFor(() => { + expect(screen.getByTestId('recurringCheck')).toBeInTheDocument(); + }); + + expect(screen.queryByTestId('recurrenceOptions')).not.toBeInTheDocument(); + + userEvent.click(screen.getByTestId('recurringCheck')); + + await waitFor(() => { + expect(screen.getByTestId('recurrenceOptions')).toBeInTheDocument(); + }); + }); + + test('Showing different recurrence options through the Dropdown', async () => { + render( + + + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('createEventModalBtn')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('createEventModalBtn')); + + await waitFor(() => { + expect(screen.getByTestId('recurringCheck')).toBeInTheDocument(); + }); + + expect(screen.queryByTestId('recurrenceOptions')).not.toBeInTheDocument(); + + userEvent.click(screen.getByTestId('recurringCheck')); + + await waitFor(() => { + expect(screen.getByTestId('recurrenceOptions')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('recurrenceOptions')); + + await waitFor(() => { + expect(screen.getByTestId('customRecurrence')).toBeInTheDocument(); + }); + }); + + test('Toggling of custom recurrence modal', async () => { + render( + + + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('createEventModalBtn')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('createEventModalBtn')); + + await waitFor(() => { + expect(screen.getByTestId('recurringCheck')).toBeInTheDocument(); + }); + + expect(screen.queryByTestId('recurrenceOptions')).not.toBeInTheDocument(); + + userEvent.click(screen.getByTestId('recurringCheck')); + + await waitFor(() => { + expect(screen.getByTestId('recurrenceOptions')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('recurrenceOptions')); + + await waitFor(() => { + expect(screen.getByTestId('customRecurrence')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('customRecurrence')); + + await waitFor(() => { + expect( + screen.getByTestId('customRecurrenceModalCloseBtn'), + ).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('customRecurrenceModalCloseBtn')); + + await waitFor(() => { + expect( + screen.queryByTestId('customRecurrenceModalCloseBtn'), + ).not.toBeInTheDocument(); + }); + }); + + test('Selecting different recurrence options from the dropdown menu', async () => { + render( + + + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('createEventModalBtn')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('createEventModalBtn')); + + const startDatePicker = screen.getByLabelText('Start Date'); + const endDatePicker = screen.getByLabelText('End Date'); + + fireEvent.change(startDatePicker, { + target: { value: formData.startDate }, + }); + + fireEvent.change(endDatePicker, { + target: { value: formData.endDate }, + }); + + await waitFor(() => { + expect(screen.getByTestId('recurringCheck')).toBeInTheDocument(); + }); + + expect(screen.queryByTestId('recurrenceOptions')).not.toBeInTheDocument(); + + userEvent.click(screen.getByTestId('recurringCheck')); + + await waitFor(() => { + expect(screen.getByTestId('recurrenceOptions')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('recurrenceOptions')); + + await waitFor(() => { + expect(screen.getByTestId('dailyRecurrence')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('dailyRecurrence')); + + userEvent.click(screen.getByTestId('recurrenceOptions')); + + await waitFor(() => { + expect(screen.getByTestId('weeklyRecurrence')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('weeklyRecurrence')); + + userEvent.click(screen.getByTestId('recurrenceOptions')); + + await waitFor(() => { + expect( + screen.getByTestId('monthlyRecurrenceOnThatDay'), + ).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('monthlyRecurrenceOnThatDay')); + + userEvent.click(screen.getByTestId('recurrenceOptions')); + + await waitFor(() => { + expect( + screen.getByTestId('monthlyRecurrenceOnThatOccurence'), + ).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('monthlyRecurrenceOnThatOccurence')); + + userEvent.click(screen.getByTestId('recurrenceOptions')); + + await waitFor(() => { + expect( + screen.getByTestId('monthlyRecurrenceOnLastOccurence'), + ).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('monthlyRecurrenceOnLastOccurence')); + + // changing the startDate would change the weekDayOccurenceInMonth, if it is defined + fireEvent.change(startDatePicker, { + target: { value: formData.endDate }, + }); + + userEvent.click(screen.getByTestId('recurrenceOptions')); + + await waitFor(() => { + expect(screen.getByTestId('yearlyRecurrence')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('yearlyRecurrence')); + + userEvent.click(screen.getByTestId('recurrenceOptions')); + + await waitFor(() => { + expect( + screen.getByTestId('mondayToFridayRecurrence'), + ).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('mondayToFridayRecurrence')); + + await waitFor(() => { + expect(screen.getByTestId('recurrenceOptions')).toHaveTextContent( + 'Monday to Friday', + ); + }); + }, 30000); + + test('Creating a recurring event with the daily recurrence option', async () => { + render( + + + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('createEventModalBtn')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('createEventModalBtn')); + + await waitFor(() => { + expect(screen.getByPlaceholderText(/Enter Title/i)).toBeInTheDocument(); + }); + + userEvent.type(screen.getByPlaceholderText(/Enter Title/i), formData.title); + + userEvent.type( + screen.getByPlaceholderText(/Enter Description/i), + formData.description, + ); + + userEvent.type( + screen.getByPlaceholderText(/Enter Location/i), + formData.location, + ); + + const startDatePicker = screen.getByLabelText('Start Date'); + const endDatePicker = screen.getByLabelText('End Date'); + + fireEvent.change(startDatePicker, { + target: { value: formData.startDate }, + }); + + fireEvent.change(endDatePicker, { + target: { value: formData.endDate }, + }); + + userEvent.click(screen.getByTestId('alldayCheck')); + + await waitFor(() => { + expect(screen.getByLabelText(translations.startTime)).toBeInTheDocument(); + }); + + const startTimePicker = screen.getByLabelText(translations.startTime); + const endTimePicker = screen.getByLabelText(translations.endTime); + + fireEvent.change(startTimePicker, { + target: { value: formData.startTime }, + }); + + fireEvent.change(endTimePicker, { + target: { value: formData.endTime }, + }); + + await waitFor(() => { + expect(screen.getByTestId('recurringCheck')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('recurringCheck')); + + await waitFor(() => { + expect(screen.getByTestId('recurrenceOptions')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('recurrenceOptions')); + + await waitFor(() => { + expect(screen.getByTestId('dailyRecurrence')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('dailyRecurrence')); + + expect(screen.getByPlaceholderText(/Enter Title/i)).toHaveValue( + formData.title, + ); + expect(screen.getByPlaceholderText(/Enter Location/i)).toHaveValue( + formData.location, + ); + expect(screen.getByPlaceholderText(/Enter Description/i)).toHaveValue( + formData.description, + ); + expect(startDatePicker).toHaveValue(formData.startDate); + expect(endDatePicker).toHaveValue(formData.endDate); + expect(startTimePicker).toHaveValue(formData.startTime); + expect(endTimePicker).toHaveValue(formData.endTime); + expect(screen.getByTestId('alldayCheck')).not.toBeChecked(); + expect(screen.getByTestId('recurringCheck')).toBeChecked(); + + expect(screen.getByTestId('recurrenceOptions')).toHaveTextContent('Daily'); + + userEvent.click(screen.getByTestId('createEventBtn')); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.eventCreated); + }); + + await waitFor(() => { + expect( + screen.queryByTestId('createEventModalCloseBtn'), + ).not.toBeInTheDocument(); + }); + }); + + test('Creating a recurring event with the monday to friday recurrence option', async () => { + render( + + + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('createEventModalBtn')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('createEventModalBtn')); + + await waitFor(() => { + expect(screen.getByPlaceholderText(/Enter Title/i)).toBeInTheDocument(); + }); + + userEvent.type(screen.getByPlaceholderText(/Enter Title/i), formData.title); + + userEvent.type( + screen.getByPlaceholderText(/Enter Description/i), + formData.description, + ); + + userEvent.type( + screen.getByPlaceholderText(/Enter Location/i), + formData.location, + ); + + const startDatePicker = screen.getByLabelText('Start Date'); + const endDatePicker = screen.getByLabelText('End Date'); + + fireEvent.change(startDatePicker, { + target: { value: formData.startDate }, + }); + + fireEvent.change(endDatePicker, { + target: { value: formData.endDate }, + }); + + userEvent.click(screen.getByTestId('alldayCheck')); + + await waitFor(() => { + expect(screen.getByLabelText(translations.startTime)).toBeInTheDocument(); + }); + + const startTimePicker = screen.getByLabelText(translations.startTime); + const endTimePicker = screen.getByLabelText(translations.endTime); + + fireEvent.change(startTimePicker, { + target: { value: formData.startTime }, + }); + + fireEvent.change(endTimePicker, { + target: { value: formData.endTime }, + }); + + await waitFor(() => { + expect(screen.getByTestId('recurringCheck')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('recurringCheck')); + + await waitFor(() => { + expect(screen.getByTestId('recurrenceOptions')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('recurrenceOptions')); + + await waitFor(() => { + expect( + screen.getByTestId('mondayToFridayRecurrence'), + ).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('mondayToFridayRecurrence')); + + expect(screen.getByPlaceholderText(/Enter Title/i)).toHaveValue( + formData.title, + ); + expect(screen.getByPlaceholderText(/Enter Location/i)).toHaveValue( + formData.location, + ); + expect(screen.getByPlaceholderText(/Enter Description/i)).toHaveValue( + formData.description, + ); + expect(startDatePicker).toHaveValue(formData.startDate); + expect(endDatePicker).toHaveValue(formData.endDate); + expect(startTimePicker).toHaveValue(formData.startTime); + expect(endTimePicker).toHaveValue(formData.endTime); + expect(screen.getByTestId('alldayCheck')).not.toBeChecked(); + expect(screen.getByTestId('recurringCheck')).toBeChecked(); + + expect(screen.getByTestId('recurrenceOptions')).toHaveTextContent( + 'Monday to Friday', + ); + + userEvent.click(screen.getByTestId('createEventBtn')); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.eventCreated); + }); + + await waitFor(() => { + expect( + screen.queryByTestId('createEventModalCloseBtn'), + ).not.toBeInTheDocument(); + }); + }); +}); diff --git a/src/components/RecurrenceOptions/RecurrenceOptions.tsx b/src/components/RecurrenceOptions/RecurrenceOptions.tsx new file mode 100644 index 0000000000..cf93410dab --- /dev/null +++ b/src/components/RecurrenceOptions/RecurrenceOptions.tsx @@ -0,0 +1,228 @@ +import React, { useState } from 'react'; +import { Dropdown, OverlayTrigger } from 'react-bootstrap'; +import { + Days, + Frequency, + type InterfaceRecurrenceRuleState, + getRecurrenceRuleText, + getWeekDayOccurenceInMonth, + isLastOccurenceOfWeekDay, + mondayToFriday, +} from 'utils/recurrenceUtils'; +import CustomRecurrenceModal from './CustomRecurrenceModal'; + +interface InterfaceRecurrenceOptionsProps { + recurrenceRuleState: InterfaceRecurrenceRuleState; + recurrenceRuleText: string; + setRecurrenceRuleState: ( + state: React.SetStateAction, + ) => void; + popover: JSX.Element; + t: (key: string) => string; +} + +const RecurrenceOptions: React.FC = ({ + recurrenceRuleState, + recurrenceRuleText, + setRecurrenceRuleState, + popover, + t, +}) => { + const [customRecurrenceModalIsOpen, setCustomRecurrenceModalIsOpen] = + useState(false); + + const { recurrenceStartDate } = recurrenceRuleState; + + const hideCustomRecurrenceModal = (): void => { + setCustomRecurrenceModalIsOpen(false); + }; + + return ( + <> + + + {recurrenceRuleText.length > 45 ? ( + + + {`${recurrenceRuleText.substring(0, 45)}...`} + + + ) : ( + {recurrenceRuleText} + )} + + + + + setRecurrenceRuleState({ + ...recurrenceRuleState, + frequency: Frequency.DAILY, + weekDayOccurenceInMonth: undefined, + }) + } + data-testid="dailyRecurrence" + > + + {getRecurrenceRuleText({ + ...recurrenceRuleState, + frequency: Frequency.DAILY, + })} + + + + setRecurrenceRuleState({ + ...recurrenceRuleState, + frequency: Frequency.WEEKLY, + weekDays: [Days[recurrenceStartDate.getDay()]], + weekDayOccurenceInMonth: undefined, + }) + } + data-testid="weeklyRecurrence" + > + + {getRecurrenceRuleText({ + ...recurrenceRuleState, + frequency: Frequency.WEEKLY, + weekDays: [Days[recurrenceStartDate.getDay()]], + })} + + + + setRecurrenceRuleState({ + ...recurrenceRuleState, + frequency: Frequency.MONTHLY, + weekDayOccurenceInMonth: undefined, + }) + } + data-testid="monthlyRecurrenceOnThatDay" + > + + {getRecurrenceRuleText({ + ...recurrenceRuleState, + frequency: Frequency.MONTHLY, + weekDayOccurenceInMonth: undefined, + })} + + + {getWeekDayOccurenceInMonth(recurrenceStartDate) !== 5 && ( + + setRecurrenceRuleState({ + ...recurrenceRuleState, + frequency: Frequency.MONTHLY, + weekDays: [Days[recurrenceStartDate.getDay()]], + weekDayOccurenceInMonth: + getWeekDayOccurenceInMonth(recurrenceStartDate), + }) + } + data-testid="monthlyRecurrenceOnThatOccurence" + > + + {getRecurrenceRuleText({ + ...recurrenceRuleState, + frequency: Frequency.MONTHLY, + weekDays: [Days[recurrenceStartDate.getDay()]], + weekDayOccurenceInMonth: + getWeekDayOccurenceInMonth(recurrenceStartDate), + })} + + + )} + {isLastOccurenceOfWeekDay(recurrenceStartDate) && ( + + setRecurrenceRuleState({ + ...recurrenceRuleState, + frequency: Frequency.MONTHLY, + weekDays: [Days[recurrenceStartDate.getDay()]], + weekDayOccurenceInMonth: -1, + }) + } + data-testid="monthlyRecurrenceOnLastOccurence" + > + + {getRecurrenceRuleText({ + ...recurrenceRuleState, + frequency: Frequency.MONTHLY, + weekDays: [Days[recurrenceStartDate.getDay()]], + weekDayOccurenceInMonth: -1, + })} + + + )} + + setRecurrenceRuleState({ + ...recurrenceRuleState, + frequency: Frequency.YEARLY, + weekDayOccurenceInMonth: undefined, + }) + } + data-testid="yearlyRecurrence" + > + + {getRecurrenceRuleText({ + ...recurrenceRuleState, + frequency: Frequency.YEARLY, + weekDayOccurenceInMonth: undefined, + })} + + + + setRecurrenceRuleState({ + ...recurrenceRuleState, + frequency: Frequency.WEEKLY, + weekDays: mondayToFriday, + weekDayOccurenceInMonth: undefined, + }) + } + data-testid="mondayToFridayRecurrence" + > + + {getRecurrenceRuleText({ + ...recurrenceRuleState, + frequency: Frequency.WEEKLY, + weekDays: mondayToFriday, + })} + + + setCustomRecurrenceModalIsOpen(true)} + data-testid="customRecurrence" + > + Custom... + + + + + {/* Custom Recurrence Modal */} + + + ); +}; + +export default RecurrenceOptions; diff --git a/src/components/RequestsTableItem/RequestsTableItem.module.css b/src/components/RequestsTableItem/RequestsTableItem.module.css new file mode 100644 index 0000000000..9f12bfe996 --- /dev/null +++ b/src/components/RequestsTableItem/RequestsTableItem.module.css @@ -0,0 +1,66 @@ +.tableItem { + width: 100%; +} + +.tableItem td { + padding: 0.5rem; +} + +.tableItem .index { + padding-left: 2.5rem; + padding-top: 1rem; +} + +.tableItem .name { + padding-left: 1.5rem; + padding-top: 1rem; +} + +.tableItem .email { + padding-left: 1.5rem; + padding-top: 1rem; +} + +.acceptButton { + background: #31bb6b; + width: 120px; + height: 46px; + margin-left: -1rem; +} + +.rejectButton { + background: #dc3545; + width: 120px; + height: 46px; + margin-left: -1rem; +} + +@media (max-width: 1020px) { + .tableItem .index { + padding-left: 2rem; + } + + .tableItem .name, + .tableItem .email { + padding-left: 1rem; + } + + .acceptButton, + .rejectButton { + margin-left: -0.25rem; + } +} + +@media (max-width: 520px) { + .tableItem .index, + .tableItem .name, + .tableItem .email { + padding-left: 1rem; + } + + .acceptButton, + .rejectButton { + margin-left: 0; + width: 100%; + } +} diff --git a/src/components/RequestsTableItem/RequestsTableItem.test.tsx b/src/components/RequestsTableItem/RequestsTableItem.test.tsx new file mode 100644 index 0000000000..866abc7f68 --- /dev/null +++ b/src/components/RequestsTableItem/RequestsTableItem.test.tsx @@ -0,0 +1,147 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { act, render, screen } from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18nForTest from 'utils/i18nForTest'; +import type { InterfaceRequestsListItem } from './RequestsTableItem'; +import { MOCKS } from './RequestsTableItemMocks'; +import RequestsTableItem from './RequestsTableItem'; +import { BrowserRouter } from 'react-router-dom'; +const link = new StaticMockLink(MOCKS, true); +import useLocalStorage from 'utils/useLocalstorage'; +import userEvent from '@testing-library/user-event'; + +const { setItem } = useLocalStorage(); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} +const resetAndRefetchMock = jest.fn(); + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + warning: jest.fn(), + }, +})); + +beforeEach(() => { + setItem('id', '123'); +}); + +afterEach(() => { + localStorage.clear(); + jest.clearAllMocks(); +}); + +describe('Testing User Table Item', () => { + console.error = jest.fn((message) => { + if (message.includes('validateDOMNesting')) { + return; + } + console.warn(message); + }); + test('Should render props and text elements test for the page component', async () => { + const props: { + request: InterfaceRequestsListItem; + index: number; + resetAndRefetch: () => void; + } = { + request: { + _id: '123', + user: { + firstName: 'John', + lastName: 'Doe', + email: 'john@example.com', + }, + }, + index: 1, + resetAndRefetch: resetAndRefetchMock, + }; + + render( + + + + + + + , + ); + + await wait(); + expect(screen.getByText(/2./i)).toBeInTheDocument(); + expect(screen.getByText(/John Doe/i)).toBeInTheDocument(); + expect(screen.getByText(/john@example.com/i)).toBeInTheDocument(); + }); + + test('Accept MembershipRequest Button works properly', async () => { + const props: { + request: InterfaceRequestsListItem; + index: number; + resetAndRefetch: () => void; + } = { + request: { + _id: '123', + user: { + firstName: 'John', + lastName: 'Doe', + email: 'john@example.com', + }, + }, + index: 1, + resetAndRefetch: resetAndRefetchMock, + }; + + render( + + + + + + + , + ); + + await wait(); + userEvent.click(screen.getByTestId('acceptMembershipRequestBtn123')); + }); + + test('Reject MembershipRequest Button works properly', async () => { + const props: { + request: InterfaceRequestsListItem; + index: number; + resetAndRefetch: () => void; + } = { + request: { + _id: '123', + user: { + firstName: 'John', + lastName: 'Doe', + email: 'john@example.com', + }, + }, + index: 1, + resetAndRefetch: resetAndRefetchMock, + }; + + render( + + + + + + + , + ); + + await wait(); + userEvent.click(screen.getByTestId('rejectMembershipRequestBtn123')); + }); +}); diff --git a/src/components/RequestsTableItem/RequestsTableItem.tsx b/src/components/RequestsTableItem/RequestsTableItem.tsx new file mode 100644 index 0000000000..9c4c042324 --- /dev/null +++ b/src/components/RequestsTableItem/RequestsTableItem.tsx @@ -0,0 +1,109 @@ +import { useMutation } from '@apollo/client'; +import { + ACCEPT_ORGANIZATION_REQUEST_MUTATION, + REJECT_ORGANIZATION_REQUEST_MUTATION, +} from 'GraphQl/Mutations/mutations'; +import React from 'react'; +import { Button } from 'react-bootstrap'; +import { useTranslation } from 'react-i18next'; +import { toast } from 'react-toastify'; +import { errorHandler } from 'utils/errorHandler'; +import styles from './RequestsTableItem.module.css'; + +export interface InterfaceRequestsListItem { + _id: string; + user: { + firstName: string; + lastName: string; + email: string; + }; +} + +type Props = { + request: InterfaceRequestsListItem; + index: number; + resetAndRefetch: () => void; +}; + +const RequestsTableItem = (props: Props): JSX.Element => { + const { t } = useTranslation('translation', { keyPrefix: 'requests' }); + const { request, index, resetAndRefetch } = props; + const [acceptUser] = useMutation(ACCEPT_ORGANIZATION_REQUEST_MUTATION); + const [rejectUser] = useMutation(REJECT_ORGANIZATION_REQUEST_MUTATION); + + const handleAcceptUser = async ( + membershipRequestId: string, + ): Promise => { + try { + const { data } = await acceptUser({ + variables: { + id: membershipRequestId, + }, + }); + /* istanbul ignore next */ + if (data) { + toast.success(t('acceptedSuccessfully')); + resetAndRefetch(); + } + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + + const handleRejectUser = async ( + membershipRequestId: string, + ): Promise => { + try { + const { data } = await rejectUser({ + variables: { + id: membershipRequestId, + }, + }); + /* istanbul ignore next */ + if (data) { + toast.success(t('rejectedSuccessfully')); + resetAndRefetch(); + } + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + + return ( + + {index + 1}. + {`${request.user.firstName} ${request.user.lastName}`} + {request.user.email} + + + + + + + + ); +}; + +export default RequestsTableItem; diff --git a/src/components/RequestsTableItem/RequestsTableItemMocks.ts b/src/components/RequestsTableItem/RequestsTableItemMocks.ts new file mode 100644 index 0000000000..22ea245d3a --- /dev/null +++ b/src/components/RequestsTableItem/RequestsTableItemMocks.ts @@ -0,0 +1,37 @@ +import { + ACCEPT_ORGANIZATION_REQUEST_MUTATION, + REJECT_ORGANIZATION_REQUEST_MUTATION, +} from 'GraphQl/Mutations/mutations'; + +export const MOCKS = [ + { + request: { + query: ACCEPT_ORGANIZATION_REQUEST_MUTATION, + variables: { + id: '1', + }, + }, + result: { + data: { + acceptMembershipRequest: { + _id: '1', + }, + }, + }, + }, + { + request: { + query: REJECT_ORGANIZATION_REQUEST_MUTATION, + variables: { + id: '1', + }, + }, + result: { + data: { + rejectMembershipRequest: { + _id: '1', + }, + }, + }, + }, +]; diff --git a/src/components/SecuredRoute/SecuredRoute.tsx b/src/components/SecuredRoute/SecuredRoute.tsx index ebed98518a..4bf361eb77 100644 --- a/src/components/SecuredRoute/SecuredRoute.tsx +++ b/src/components/SecuredRoute/SecuredRoute.tsx @@ -1,15 +1,17 @@ import React from 'react'; -import { Redirect, Route } from 'react-router-dom'; +import { Navigate, Outlet } from 'react-router-dom'; import { toast } from 'react-toastify'; +import PageNotFound from 'screens/PageNotFound/PageNotFound'; +import useLocalStorage from 'utils/useLocalstorage'; +const { getItem, setItem } = useLocalStorage(); -const SecuredRoute = (props: any): JSX.Element => { - const isLoggedIn = localStorage.getItem('IsLoggedIn'); +const SecuredRoute = (): JSX.Element => { + const isLoggedIn = getItem('IsLoggedIn'); + const adminFor = getItem('AdminFor'); return isLoggedIn === 'TRUE' ? ( - <> - - + <>{adminFor != null ? : } ) : ( - + ); }; @@ -32,7 +34,7 @@ setInterval(() => { toast.warn('Kindly relogin as sessison has expired'); window.location.href = '/'; - localStorage.setItem('IsLoggedIn', 'FALSE'); + setItem('IsLoggedIn', 'FALSE'); } }, inactiveIntervalMilsec); diff --git a/src/components/SuperAdminScreen/SuperAdminScreen.module.css b/src/components/SuperAdminScreen/SuperAdminScreen.module.css index 681ac8823d..9496ef95fa 100644 --- a/src/components/SuperAdminScreen/SuperAdminScreen.module.css +++ b/src/components/SuperAdminScreen/SuperAdminScreen.module.css @@ -6,7 +6,7 @@ } .expand { - padding-left: 1.5rem; + padding-left: 4rem; animation: moveLeft 0.5s ease-in-out; } @@ -15,27 +15,68 @@ animation: moveRight 0.5s ease-in-out; } +.collapseSidebarButton { + position: fixed; + height: 40px; + bottom: 0; + z-index: 9999; + width: calc(300px + 2rem); + background-color: rgba(245, 245, 245, 0.7); + color: black; + border: none; + border-radius: 0px; +} + +.collapseSidebarButton:hover, +.opendrawer:hover { + opacity: 1; + color: black !important; +} +.opendrawer { + position: fixed; + display: flex; + align-items: center; + justify-content: center; + top: 0; + left: 0; + width: 40px; + height: 100vh; + z-index: 9999; + background-color: rgba(245, 245, 245); + border: none; + border-radius: 0px; + margin-right: 20px; + color: black; +} + @media (max-width: 1120px) { .contract { padding-left: calc(250px + 2rem + 1.5rem); } + .collapseSidebarButton { + width: calc(250px + 2rem); + } } /* For tablets */ @media (max-width: 820px) { .pageContainer { - padding-left: 1.5rem; + padding-left: 2.5rem; + } + + .opendrawer { + width: 25px; } .contract, .expand { animation: none; } -} -@media (max-width: 820px) { - .pageContainer { - padding: 1rem; + .collapseSidebarButton { + width: 100%; + left: 0; + right: 0; } } diff --git a/src/components/SuperAdminScreen/SuperAdminScreen.test.tsx b/src/components/SuperAdminScreen/SuperAdminScreen.test.tsx index e578b0bb4f..84b740ab12 100644 --- a/src/components/SuperAdminScreen/SuperAdminScreen.test.tsx +++ b/src/components/SuperAdminScreen/SuperAdminScreen.test.tsx @@ -1,42 +1,51 @@ import React from 'react'; import { MockedProvider } from '@apollo/react-testing'; -import { render, screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import 'jest-localstorage-mock'; +import { fireEvent, render, screen } from '@testing-library/react'; import 'jest-location-mock'; import { I18nextProvider } from 'react-i18next'; import { Provider } from 'react-redux'; import { BrowserRouter } from 'react-router-dom'; import { store } from 'state/store'; import i18nForTest from 'utils/i18nForTest'; -import type { InterfaceSuperAdminScreenProps } from './SuperAdminScreen'; import SuperAdminScreen from './SuperAdminScreen'; -const props: InterfaceSuperAdminScreenProps = { - title: 'Organizations', - screenName: 'Organizations', - children:
    Testing ...
    , +const resizeWindow = (width: number): void => { + window.innerWidth = width; + fireEvent(window, new Event('resize')); +}; + +const clickToggleMenuBtn = (toggleButton: HTMLElement): void => { + fireEvent.click(toggleButton); }; describe('Testing LeftDrawer in SuperAdminScreen', () => { test('Testing LeftDrawer in page functionality', async () => { - localStorage.setItem('UserType', 'SUPERADMIN'); - render( - + - + , ); - // Expand LeftDrawer - userEvent.click(screen.getByTestId('menuBtn')); - // Contract LeftDrawer - userEvent.click(screen.getByTestId('menuBtn')); + const toggleButton = screen.getByTestId('closeMenu') as HTMLElement; + const icon = toggleButton.querySelector('i'); + + // Resize window to a smaller width + resizeWindow(800); + clickToggleMenuBtn(toggleButton); + expect(icon).toHaveClass('fa fa-angle-double-left'); + + // Resize window back to a larger width + resizeWindow(1000); + clickToggleMenuBtn(toggleButton); + expect(icon).toHaveClass('fa fa-angle-double-right'); + + clickToggleMenuBtn(toggleButton); + expect(icon).toHaveClass('fa fa-angle-double-left'); }); }); diff --git a/src/components/SuperAdminScreen/SuperAdminScreen.tsx b/src/components/SuperAdminScreen/SuperAdminScreen.tsx index 214b8bd1ed..f7191289eb 100644 --- a/src/components/SuperAdminScreen/SuperAdminScreen.tsx +++ b/src/components/SuperAdminScreen/SuperAdminScreen.tsx @@ -1,56 +1,86 @@ -import MenuIcon from '@mui/icons-material/Menu'; import LeftDrawer from 'components/LeftDrawer/LeftDrawer'; -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import Button from 'react-bootstrap/Button'; +import { useTranslation } from 'react-i18next'; +import { Outlet, useLocation } from 'react-router-dom'; import styles from './SuperAdminScreen.module.css'; +import ProfileDropdown from 'components/ProfileDropdown/ProfileDropdown'; -export interface InterfaceSuperAdminScreenProps { - title: string; // Multilingual Page title - screenName: string; // Internal Screen name for developers - children: React.ReactNode; -} -const superAdminScreen = ({ - title, - screenName, - children, -}: InterfaceSuperAdminScreenProps): JSX.Element => { +const superAdminScreen = (): JSX.Element => { + const location = useLocation(); + const titleKey = map[location.pathname.split('/')[1]]; + const { t } = useTranslation('translation', { keyPrefix: titleKey }); const [hideDrawer, setHideDrawer] = useState(null); + const handleResize = (): void => { + if (window.innerWidth <= 820) { + setHideDrawer(!hideDrawer); + } + }; + + useEffect(() => { + handleResize(); + window.addEventListener('resize', handleResize); + return () => { + window.removeEventListener('resize', handleResize); + }; + }, []); + return ( <> - + {hideDrawer ? ( + + ) : ( + + )} +
    -

    {title}

    +

    {t('title')}

    - +
    - {children} +
    ); }; export default superAdminScreen; + +const map: Record< + string, + 'orgList' | 'requests' | 'users' | 'memberDetail' | 'communityProfile' +> = { + orglist: 'orgList', + requests: 'requests', + users: 'users', + member: 'memberDetail', + communityProfile: 'communityProfile', +}; diff --git a/src/components/TableLoader/TableLoader.test.tsx b/src/components/TableLoader/TableLoader.test.tsx index b6526a65c7..e8400c84ef 100644 --- a/src/components/TableLoader/TableLoader.test.tsx +++ b/src/components/TableLoader/TableLoader.test.tsx @@ -18,7 +18,7 @@ describe('Testing Loader component', () => { render( - + , ); // Check if header titles are rendered properly const data = props.headerTitles as string[]; @@ -29,11 +29,11 @@ describe('Testing Loader component', () => { // Check if elements are rendered properly for (let rowIndex = 0; rowIndex < props.noOfRows; rowIndex++) { expect( - screen.getByTestId(`row-${rowIndex}-tableLoading`) + screen.getByTestId(`row-${rowIndex}-tableLoading`), ).toBeInTheDocument(); for (let colIndex = 0; colIndex < data.length; colIndex++) { expect( - screen.getByTestId(`row-${rowIndex}-col-${colIndex}-tableLoading`) + screen.getByTestId(`row-${rowIndex}-col-${colIndex}-tableLoading`), ).toBeInTheDocument(); } } @@ -46,7 +46,7 @@ describe('Testing Loader component', () => { render( - + , ); // Check if header titles are rendered properly const data = [...Array(props.noOfCols)]; @@ -54,11 +54,11 @@ describe('Testing Loader component', () => { // Check if elements are rendered properly for (let rowIndex = 0; rowIndex < props.noOfRows; rowIndex++) { expect( - screen.getByTestId(`row-${rowIndex}-tableLoading`) + screen.getByTestId(`row-${rowIndex}-tableLoading`), ).toBeInTheDocument(); for (let colIndex = 0; colIndex < data.length; colIndex++) { expect( - screen.getByTestId(`row-${rowIndex}-col-${colIndex}-tableLoading`) + screen.getByTestId(`row-${rowIndex}-col-${colIndex}-tableLoading`), ).toBeInTheDocument(); } } @@ -71,7 +71,7 @@ describe('Testing Loader component', () => { render( - + , ); }).toThrowError(); }); diff --git a/src/components/TableLoader/TableLoader.tsx b/src/components/TableLoader/TableLoader.tsx index 2da4b1d172..6d99d6fe3f 100644 --- a/src/components/TableLoader/TableLoader.tsx +++ b/src/components/TableLoader/TableLoader.tsx @@ -14,7 +14,7 @@ const tableLoader = (props: InterfaceTableLoader): JSX.Element => { useEffect(() => { if (headerTitles == undefined && noOfCols == undefined) { throw new Error( - 'TableLoader error Either headerTitles or noOfCols is required !' + 'TableLoader error Either headerTitles or noOfCols is required !', ); } }, []); @@ -53,7 +53,7 @@ const tableLoader = (props: InterfaceTableLoader): JSX.Element => {
    ); - } + }, )} ); diff --git a/src/components/TaskListItem/TaskListItem.test.tsx b/src/components/TaskListItem/TaskListItem.test.tsx deleted file mode 100644 index 9047f72541..0000000000 --- a/src/components/TaskListItem/TaskListItem.test.tsx +++ /dev/null @@ -1,130 +0,0 @@ -import React from 'react'; -import { fireEvent, render, waitFor } from '@testing-library/react'; -import { TaskListItem } from './TaskListItem'; -import { BrowserRouter } from 'react-router-dom'; -import { Provider } from 'react-redux'; -import { store } from 'state/store'; -import { I18nextProvider } from 'react-i18next'; -import i18nForTest from 'utils/i18nForTest'; -import { ToastContainer } from 'react-toastify'; -import { MockedProvider } from '@apollo/react-testing'; -import { LocalizationProvider } from '@mui/x-date-pickers'; -import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; - -describe('Testing Delete Event Project Modal', () => { - const props = { - organization: { - _id: '123', - members: [ - { - _id: 'abc1', - firstName: 'John', - lastName: 'Doe', - }, - { - _id: 'abc2', - firstName: 'John2', - lastName: 'Doe2', - }, - ], - }, - task: { - _id: 'xyz1', - title: 'Task 1', - deadline: '22/04/2025', - description: 'Task description', - completed: false, - volunteers: [], - }, - refetchData: jest.fn(), - }; - - test('The modal should be rendered and data should be displayed correctly', async () => { - const { queryByText, queryByRole } = render( - - - - - - - - - - - - - ); - - await waitFor(() => - expect(queryByText(props.task.title)).toBeInTheDocument() - ); - - await waitFor(() => - expect(queryByText(props.task.description)).toBeInTheDocument() - ); - - // Open the Update Task Modal - fireEvent.click(queryByText('View') as Element); - - await waitFor(() => - expect(queryByText('Update the Event Task')).toBeInTheDocument() - ); - - // Close the Update Task Modal - fireEvent.click(queryByRole('button', { name: /close/i }) as HTMLElement); - - await waitFor(() => - expect(queryByText('Update the Event Task')).not.toBeInTheDocument() - ); - }); - - test('The task should have the right when it is not completed', async () => { - const { queryByTestId } = render( - - - - - - - - - - - - - ); - - await waitFor(() => - expect(queryByTestId('AssignmentIcon')).toBeInTheDocument() - ); - await waitFor(() => - expect(queryByTestId('AssignmentTurnedInIcon')).not.toBeInTheDocument() - ); - }); - - test('The task should have the right when it is completed', async () => { - props.task.completed = true; - - const { queryByTestId } = render( - - - - - - - - - - - - - ); - - await waitFor(() => - expect(queryByTestId('AssignmentIcon')).not.toBeInTheDocument() - ); - await waitFor(() => - expect(queryByTestId('AssignmentTurnedInIcon')).toBeInTheDocument() - ); - }); -}); diff --git a/src/components/TaskListItem/TaskListItem.tsx b/src/components/TaskListItem/TaskListItem.tsx deleted file mode 100644 index 5840ca136f..0000000000 --- a/src/components/TaskListItem/TaskListItem.tsx +++ /dev/null @@ -1,106 +0,0 @@ -import React, { useState } from 'react'; -import ListItem from '@mui/material/ListItem'; -import Divider from '@mui/material/Divider'; -import ListItemText from '@mui/material/ListItemText'; -import Chip from '@mui/material/Chip'; -import Typography from '@mui/material/Typography'; -import ListItemAvatar from '@mui/material/ListItemAvatar'; -import Avatar from '@mui/material/Avatar'; -import EditOutlinedIcon from '@mui/icons-material/EditOutlined'; -import { common } from '@mui/material/colors'; -import AssignmentIcon from '@mui/icons-material/Assignment'; -import AssignmentTurnedInIcon from '@mui/icons-material/AssignmentTurnedIn'; -import { UpdateTaskModal } from 'components/TaskModals/UpdateTaskModal'; - -interface InterfaceUser { - _id: string; - firstName: string; - lastName: string; -} -interface InterfaceTask { - _id: string; - title: string; - deadline: string; - description: string; - completed: boolean; - volunteers: InterfaceUser[]; -} - -type PropType = { - task: InterfaceTask; - refetchData: () => void; - organization: { - _id: string; - members: InterfaceUser[]; - }; -}; - -export const TaskListItem = ({ - task, - refetchData, - organization: organizationData, -}: PropType): JSX.Element => { - const [showUpdateTaskModal, setShowUpdateTaskModal] = useState(false); - - return ( - <> -
    - - - - {' '} - {task.completed ? ( - - ) : ( - - )} - - - - - {task.description} - - - } - /> - } - label="View" - variant="outlined" - onClick={(): void => { - setShowUpdateTaskModal(true); - }} - /> - - -
    - {/* Wrapper Div for all the relevant modals */} - { - setShowUpdateTaskModal(false); - }} - task={task} - refetchData={refetchData} - organization={organizationData} - /> -
    -
    - - ); -}; diff --git a/src/components/TaskModals/AddTaskModal.test.tsx b/src/components/TaskModals/AddTaskModal.test.tsx deleted file mode 100644 index ca7aa895ac..0000000000 --- a/src/components/TaskModals/AddTaskModal.test.tsx +++ /dev/null @@ -1,150 +0,0 @@ -import React from 'react'; -import { fireEvent, render, waitFor } from '@testing-library/react'; -import { MockedProvider } from '@apollo/react-testing'; -import { AddTaskModal } from './AddTaskModal'; -import { ADD_EVENT_PROJECT_TASK_MUTATION } from 'GraphQl/Mutations/mutations'; -import { BrowserRouter } from 'react-router-dom'; -import { Provider } from 'react-redux'; -import { store } from 'state/store'; -import { I18nextProvider } from 'react-i18next'; -import i18nForTest from 'utils/i18nForTest'; -import { ToastContainer } from 'react-toastify'; -import dayjs from 'dayjs'; -import { LocalizationProvider } from '@mui/x-date-pickers'; -import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; - -const today = dayjs(new Date()); -const taskDatetime = today.add(7, 'days'); - -const successfulMutationMock = [ - { - request: { - query: ADD_EVENT_PROJECT_TASK_MUTATION, - variables: { - title: 'Title', - description: 'Description', - projectId: '123', - deadline: null, - }, - }, - result: { - data: { - createTask: { - _id: '456', - }, - }, - }, - }, -]; - -const unsuccessfulMutationMock = [ - { - request: { - query: ADD_EVENT_PROJECT_TASK_MUTATION, - variables: { - title: 'Title', - description: 'Description', - projectId: '123', - deadline: taskDatetime, - }, - }, - error: new Error('Oops'), - }, -]; - -describe('Testing Add Event Task Modal', () => { - const props = { - show: true, - projectId: '123', - handleClose: jest.fn(), - refetchData: jest.fn(), - }; - - test('The modal should be rendered and add button should not work with blank values', async () => { - const { queryByText, queryByLabelText } = render( - - - - - - - - - - - - - ); - - await waitFor(() => - expect(queryByText('Add an Event Task')).toBeInTheDocument() - ); - - fireEvent.click(queryByText('Create Task') as Element); - - // Check for blank entry warning modals - await waitFor(() => - expect(queryByText('Title cannot be empty!')).toBeInTheDocument() - ); - await waitFor(() => - expect(queryByText('Description cannot be empty!')).toBeInTheDocument() - ); - - // Type in the title and the description of the event project - fireEvent.change(queryByLabelText('Title') as Element, { - target: { value: 'Title' }, - }); - fireEvent.change(queryByLabelText('Description') as Element, { - target: { value: 'Description' }, - }); - fireEvent.change(queryByLabelText('Deadline') as Element, { - target: { value: taskDatetime }, - }); - - fireEvent.click(queryByText('Create Task') as Element); - - await waitFor(() => - expect(queryByText('Adding the task...')).toBeInTheDocument() - ); - - await waitFor(() => - expect(queryByText('Added the task successfully!')).toBeInTheDocument() - ); - }); - - test('The modal should be rendered and error message should be shown if mutation fails', async () => { - const { queryByText, queryByLabelText } = render( - - - - - - - - - - - - - ); - - // Type in the title and the description of the event project - fireEvent.change(queryByLabelText('Title') as Element, { - target: { value: 'Title' }, - }); - fireEvent.change(queryByLabelText('Description') as Element, { - target: { value: 'Description' }, - }); - fireEvent.change(queryByLabelText('Deadline') as Element, { - target: { value: taskDatetime }, - }); - - fireEvent.click(queryByText('Create Task') as Element); - - await waitFor(() => - expect( - queryByText('There was an error in adding the task!') - ).toBeInTheDocument() - ); - }); -}); diff --git a/src/components/TaskModals/AddTaskModal.tsx b/src/components/TaskModals/AddTaskModal.tsx deleted file mode 100644 index 0134077afe..0000000000 --- a/src/components/TaskModals/AddTaskModal.tsx +++ /dev/null @@ -1,114 +0,0 @@ -import React, { useState } from 'react'; -import { Modal, Button, Form } from 'react-bootstrap'; -import { toast } from 'react-toastify'; -import { useMutation } from '@apollo/client'; -import type { Dayjs } from 'dayjs'; -import dayjs from 'dayjs'; -import { DateTimePicker } from '@mui/x-date-pickers/DateTimePicker'; -import { ADD_EVENT_PROJECT_TASK_MUTATION } from 'GraphQl/Mutations/mutations'; - -type ModalPropType = { - show: boolean; - projectId: string; - handleClose: () => void; - refetchData: () => void; -}; - -export const AddTaskModal = ({ - show, - handleClose, - refetchData, - projectId, -}: ModalPropType): JSX.Element => { - const today = dayjs(new Date()); - - const [title, setTitle] = useState(''); - const [description, setDescription] = useState(''); - const [deadline, setDeadline] = useState(today); - - const [addMutation] = useMutation(ADD_EVENT_PROJECT_TASK_MUTATION); - const notify = async (e: React.FormEvent): Promise => { - e.preventDefault(); - toast.promise(handleSubmit, { - pending: 'Adding the task...', - success: 'Added the task successfully!', - error: 'There was an error in adding the task!', - }); - }; - const handleSubmit = async (): Promise => { - let toSubmit = true; - - if (title.trim().length == 0) { - toast.error('Title cannot be empty!'); - toSubmit = false; - } - if (description.trim().length == 0) { - toast.error('Description cannot be empty!'); - toSubmit = false; - } - if (!toSubmit) return Promise.reject(); - await addMutation({ - variables: { - title, - description, - projectId, - deadline, - }, - }); - refetchData(); - setTitle(''); - setDescription(''); - handleClose(); - }; - - return ( - <> - - - Add an Event Task - -
    - - - Title - setTitle(e.target.value)} - /> - - - - Description - setDescription(e.target.value)} - /> - - - - { - setDeadline(date); - }} - disablePast - /> - - - - - -
    -
    - - ); -}; diff --git a/src/components/TaskModals/DeleteTaskModal.test.tsx b/src/components/TaskModals/DeleteTaskModal.test.tsx deleted file mode 100644 index 4eb40e53a8..0000000000 --- a/src/components/TaskModals/DeleteTaskModal.test.tsx +++ /dev/null @@ -1,100 +0,0 @@ -import React from 'react'; -import { fireEvent, render, waitFor } from '@testing-library/react'; -import { MockedProvider } from '@apollo/react-testing'; -import { DeleteTaskModal } from './DeleteTaskModal'; -import { DELETE_EVENT_TASK_MUTATION } from 'GraphQl/Mutations/mutations'; -import { BrowserRouter } from 'react-router-dom'; -import { Provider } from 'react-redux'; -import { store } from 'state/store'; -import { I18nextProvider } from 'react-i18next'; -import i18nForTest from 'utils/i18nForTest'; -import { ToastContainer } from 'react-toastify'; - -const successfulMutationMock = [ - { - request: { - query: DELETE_EVENT_TASK_MUTATION, - variables: { id: '123' }, - }, - result: { - data: { - removeTask: { - _id: '123', - }, - }, - }, - }, -]; - -const unsuccessfulMutationMock = [ - { - request: { - query: DELETE_EVENT_TASK_MUTATION, - variables: { - id: '123', - }, - }, - error: new Error('Oops'), - }, -]; - -describe('Testing Delete Event Project Modal', () => { - const props = { - show: true, - taskId: '123', - handleClose: jest.fn(), - refetchData: jest.fn(), - }; - - test('The modal should be rendered and delete button should work', async () => { - const { queryByText } = render( - - - - - - - - - - - ); - - await waitFor(() => expect(queryByText('Delete Task')).toBeInTheDocument()); - - fireEvent.click(queryByText('Delete') as Element); - await waitFor(() => - expect(queryByText('Deleting the task...')).toBeInTheDocument() - ); - await waitFor(() => - expect(queryByText('Deleted the task successfully!')).toBeInTheDocument() - ); - }); - - test('The modal should be rendered and error message should be shown if mutation fails', async () => { - const { queryByText } = render( - - - - - - - - - - - ); - - await waitFor(() => expect(queryByText('Delete Task')).toBeInTheDocument()); - - fireEvent.click(queryByText('Delete') as Element); - await waitFor(() => - expect(queryByText('Deleting the task...')).toBeInTheDocument() - ); - await waitFor(() => - expect( - queryByText('There was an error in deleting the task!') - ).toBeInTheDocument() - ); - }); -}); diff --git a/src/components/TaskModals/DeleteTaskModal.tsx b/src/components/TaskModals/DeleteTaskModal.tsx deleted file mode 100644 index 73baff5775..0000000000 --- a/src/components/TaskModals/DeleteTaskModal.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import React from 'react'; -import { Modal, Button } from 'react-bootstrap'; -import { toast } from 'react-toastify'; -import { useMutation } from '@apollo/client'; -import { DELETE_EVENT_TASK_MUTATION } from 'GraphQl/Mutations/mutations'; - -type ModalPropType = { - show: boolean; - taskId: string; - handleClose: () => void; - refetchData: () => void; -}; - -export const DeleteTaskModal = (props: ModalPropType): JSX.Element => { - const [deleteMutation] = useMutation(DELETE_EVENT_TASK_MUTATION); - const notify = (): Promise => { - return toast.promise(deleteProject, { - pending: 'Deleting the task...', - success: 'Deleted the task successfully!', - error: 'There was an error in deleting the task!', - }); - }; - const deleteProject = async (): Promise => { - await deleteMutation({ - variables: { - id: props.taskId, - }, - }); - props.refetchData(); - props.handleClose(); - }; - - return ( - <> - - - Delete Task - - -
    - Are you sure you want to delete this? -
    -
    - - - - -
    - - ); -}; diff --git a/src/components/TaskModals/ManageVolunteerModal.test.tsx b/src/components/TaskModals/ManageVolunteerModal.test.tsx deleted file mode 100644 index e284984969..0000000000 --- a/src/components/TaskModals/ManageVolunteerModal.test.tsx +++ /dev/null @@ -1,135 +0,0 @@ -import React from 'react'; -import { fireEvent, render, waitFor } from '@testing-library/react'; -import { MockedProvider } from '@apollo/react-testing'; -import { ManageVolunteerModal } from './ManageVolunteerModal'; -import { SET_TASK_VOLUNTEERS_MUTATION } from 'GraphQl/Mutations/mutations'; -import { BrowserRouter } from 'react-router-dom'; -import { Provider } from 'react-redux'; -import { store } from 'state/store'; -import { I18nextProvider } from 'react-i18next'; -import i18nForTest from 'utils/i18nForTest'; -import { ToastContainer } from 'react-toastify'; -import { LocalizationProvider } from '@mui/x-date-pickers'; -import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; - -const successfulMutationMock = [ - { - request: { - query: SET_TASK_VOLUNTEERS_MUTATION, - variables: { - id: '123', - volunteers: ['user1'], - }, - }, - result: { - data: { - setTaskVolunteers: { - _id: '456', - }, - }, - }, - }, -]; - -const unsuccessfulMutationMock = [ - { - request: { - query: SET_TASK_VOLUNTEERS_MUTATION, - variables: { - id: '123', - volunteers: [], - }, - }, - error: new Error('Oops'), - }, -]; - -describe('Testing Manage Volunteers Modal', () => { - const props = { - show: true, - taskId: '123', - organization: { - _id: 'testorg', - members: [ - { _id: 'user1', firstName: 'John1', lastName: 'Doe1' }, - { _id: 'user2', firstName: 'John2', lastName: 'Doe2' }, - { _id: 'user3', firstName: 'John3', lastName: 'Doe3' }, - ], - }, - volunteers: [], - handleClose: jest.fn(), - refetchData: jest.fn(), - }; - - test('The modal should be rendered and update button should work properly', async () => { - const { queryByText, queryByLabelText } = render( - - - - - - - - - - - - - ); - - await waitFor(() => - expect(queryByText('Manage Volunteers')).toBeInTheDocument() - ); - - // Fill out the autocomplete with volunteer information - const volunteerInput = queryByLabelText('Assign Volunteers'); - expect(volunteerInput).toBeInTheDocument(); - - fireEvent.change(volunteerInput as Element, { - target: { value: 'John1 Doe1' }, - }); - fireEvent.keyDown(volunteerInput as HTMLElement, { key: 'Enter' }); - - // Click the update button - fireEvent.click(queryByText('Update Volunteers') as Element); - - await waitFor(() => - expect(queryByText('Updating the volunteers...')).toBeInTheDocument() - ); - - await waitFor(() => - expect( - queryByText('Successfully updated the volunteers!') - ).toBeInTheDocument() - ); - }); - - test('The modal should be rendered and error message should be shown if mutation fails', async () => { - const { queryByText } = render( - - - - - - - - - - - - - ); - - fireEvent.click(queryByText('Update Volunteers') as Element); - - await waitFor(() => - expect(queryByText('Updating the volunteers...')).toBeInTheDocument() - ); - - await waitFor(() => - expect( - queryByText('There was an error in updating the volunteers!') - ).toBeInTheDocument() - ); - }); -}); diff --git a/src/components/TaskModals/ManageVolunteerModal.tsx b/src/components/TaskModals/ManageVolunteerModal.tsx deleted file mode 100644 index 162fda4a02..0000000000 --- a/src/components/TaskModals/ManageVolunteerModal.tsx +++ /dev/null @@ -1,102 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import { Modal } from 'react-bootstrap'; -import Autocomplete from '@mui/material/Autocomplete'; -import TextField from '@mui/material/TextField'; -import Stack from '@mui/material/Stack'; -import { Button } from 'react-bootstrap'; -import { useMutation } from '@apollo/client'; -import { SET_TASK_VOLUNTEERS_MUTATION } from 'GraphQl/Mutations/mutations'; -import { toast } from 'react-toastify'; - -interface InterfaceUser { - _id: string; - firstName: string; - lastName: string; -} - -type ModalPropType = { - show: boolean; - taskId: string; - organization: { - _id: string; - members: InterfaceUser[]; - }; - volunteers: InterfaceUser[]; - handleClose: () => void; - refetchData: () => void; -}; - -export const ManageVolunteerModal = (props: ModalPropType): JSX.Element => { - const [volunteers, setVolunteers] = useState([]); - - useEffect(() => setVolunteers(props.volunteers), [props.volunteers]); - - const [setMutation] = useMutation(SET_TASK_VOLUNTEERS_MUTATION); - const notify = (): Promise => { - return toast.promise(handleSubmit, { - pending: 'Updating the volunteers...', - success: 'Successfully updated the volunteers!', - error: 'There was an error in updating the volunteers!', - }); - }; - const handleSubmit = async (): Promise => { - await setMutation({ - variables: { - id: props.taskId, - volunteers: volunteers.map((volunteer) => volunteer._id), - }, - }); - props.refetchData(); - props.handleClose(); - }; - - return ( - <> - - - Manage Volunteers - - -

    - All the members of the organization of the event can be added as - volunteers for a task. -

    - - - `${memberOption.firstName} ${memberOption.lastName}` - } - filterSelectedOptions={true} - onChange={(_, value): void => { - setVolunteers(value); - }} - autoHighlight={true} - renderInput={(params): React.ReactNode => ( - - )} - /> - -
    -
    - - - -
    - - ); -}; diff --git a/src/components/TaskModals/UpdateTaskModal.test.tsx b/src/components/TaskModals/UpdateTaskModal.test.tsx deleted file mode 100644 index 9541d6d26b..0000000000 --- a/src/components/TaskModals/UpdateTaskModal.test.tsx +++ /dev/null @@ -1,262 +0,0 @@ -import React from 'react'; -import { fireEvent, render, waitFor } from '@testing-library/react'; -import { MockedProvider } from '@apollo/react-testing'; -import { UpdateTaskModal } from './UpdateTaskModal'; -import { UPDATE_EVENT_PROJECT_TASK_MUTATION } from 'GraphQl/Mutations/mutations'; -import { BrowserRouter } from 'react-router-dom'; -import { Provider } from 'react-redux'; -import { store } from 'state/store'; -import { I18nextProvider } from 'react-i18next'; -import i18nForTest from 'utils/i18nForTest'; -import { ToastContainer } from 'react-toastify'; -import dayjs from 'dayjs'; -import { LocalizationProvider } from '@mui/x-date-pickers'; -import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; -import type { ModalPropType } from './UpdateTaskModal'; - -const today = dayjs(new Date()); -const oldDeadline = today.add(7, 'days'); -const newDeadline = today.add(10, 'days'); - -const successfulMutationMock = [ - { - request: { - query: UPDATE_EVENT_PROJECT_TASK_MUTATION, - variables: { - title: 'Title', - description: 'Description', - taskId: 'task1', - completed: true, - deadline: null, - }, - }, - result: { - data: { - updateTask: { - _id: '456', - }, - }, - }, - }, -]; - -const unsuccessfulMutationMock = [ - { - request: { - query: UPDATE_EVENT_PROJECT_TASK_MUTATION, - variables: { - title: 'Title', - description: 'Description', - taskId: 'task1', - completed: true, - deadline: null, - }, - }, - error: new Error('Oops'), - }, -]; - -describe('Testing Update Event Task Modal', () => { - const props = { - show: true, - task: { - _id: 'task1', - title: 'Task 1', - description: 'Description 1', - deadline: oldDeadline.toString(), - completed: false, - volunteers: [], - }, - organization: { - _id: 'org1', - members: [], - }, - handleClose: jest.fn(), - refetchData: jest.fn(), - }; - - test('The modal should be rendered and update button should not work with blank values', async () => { - const { queryByText, queryByLabelText } = render( - - - - - - - - - - - - - ); - - await waitFor(() => - expect(queryByText('Update the Event Task')).toBeInTheDocument() - ); - - // Set the title and the description of the event task to blank - fireEvent.change(queryByLabelText('Title') as Element, { - target: { value: '' }, - }); - fireEvent.change(queryByLabelText('Description') as Element, { - target: { value: '' }, - }); - - fireEvent.click(queryByText('Update Task') as Element); - - // Check for blank entry warning modals - await waitFor(() => - expect(queryByText('Title cannot be empty!')).toBeInTheDocument() - ); - await waitFor(() => - expect(queryByText('Description cannot be empty!')).toBeInTheDocument() - ); - - // Type in the title and the description of the event task - fireEvent.change(queryByLabelText('Title') as Element, { - target: { value: 'Title' }, - }); - fireEvent.change(queryByLabelText('Description') as Element, { - target: { value: 'Description' }, - }); - fireEvent.change(queryByLabelText('Deadline') as Element, { - target: { value: newDeadline }, - }); - fireEvent.click(queryByLabelText('Completed') as Element); - - // Click the update button - fireEvent.click(queryByText('Update Task') as Element); - - await waitFor(() => - expect(queryByText('Updating the task...')).toBeInTheDocument() - ); - - await waitFor(() => - expect(queryByText('Updated the task successfully!')).toBeInTheDocument() - ); - }); - - test('The modal should show message when there are no volunteers', async () => { - const { queryByText } = render( - - - - - - - - - - - - - ); - - await waitFor(() => - expect( - queryByText('There are no volunteers assigned for this task.') - ).toBeInTheDocument() - ); - }); - - test('The modal should not show message when there are no volunteers', async () => { - const customProps: ModalPropType = { ...props }; - customProps.task.volunteers = [ - { - _id: 'user1', - firstName: 'John', - lastName: 'Doe', - }, - ]; - - const { queryByText } = render( - - - - - - - - - - - - - ); - - await waitFor(() => - expect( - queryByText('There are no volunteers assigned for this task.') - ).not.toBeInTheDocument() - ); - - await waitFor(() => expect(queryByText('John Doe')).toBeInTheDocument()); - }); - - test('The modal should be rendered and error message should be shown if mutation fails', async () => { - const { queryByText, queryByLabelText } = render( - - - - - - - - - - - - - ); - - // Type in the title and the description of the event project - fireEvent.change(queryByLabelText('Title') as Element, { - target: { value: 'Title' }, - }); - fireEvent.change(queryByLabelText('Description') as Element, { - target: { value: 'Description' }, - }); - fireEvent.change(queryByLabelText('Deadline') as Element, { - target: { value: newDeadline }, - }); - fireEvent.click(queryByLabelText('Completed') as Element); - - fireEvent.click(queryByText('Update Task') as Element); - - await waitFor(() => - expect( - queryByText('There was an error in updating the task!') - ).toBeInTheDocument() - ); - }); - - test('Manage volunteer modal and delete task modal should open and close properly', async () => { - const { queryByText, queryAllByRole } = render( - - - - - - - - - - - - - ); - - // Manage Volunteer Modal - fireEvent.click(queryByText('Manage Volunteers') as Element); - queryAllByRole('button', { name: /close/i }).forEach((ele) => - fireEvent.click(ele as HTMLElement) - ); - - // Delete Task Modal - fireEvent.click(queryByText('Delete Task') as Element); - queryAllByRole('button', { name: /close/i }).forEach((ele) => - fireEvent.click(ele as HTMLElement) - ); - }); -}); diff --git a/src/components/TaskModals/UpdateTaskModal.tsx b/src/components/TaskModals/UpdateTaskModal.tsx deleted file mode 100644 index d79dd19a36..0000000000 --- a/src/components/TaskModals/UpdateTaskModal.tsx +++ /dev/null @@ -1,222 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import { Modal, Button as BootstrapButton, Form } from 'react-bootstrap'; -import { toast } from 'react-toastify'; -import { useMutation } from '@apollo/client'; -import type { Dayjs } from 'dayjs'; -import dayjs from 'dayjs'; -import { DateTimePicker } from '@mui/x-date-pickers/DateTimePicker'; -import { UPDATE_EVENT_PROJECT_TASK_MUTATION } from 'GraphQl/Mutations/mutations'; -import { DeleteTaskModal } from './DeleteTaskModal'; -import { ManageVolunteerModal } from './ManageVolunteerModal'; -import Chip from '@mui/material/Chip'; -import Stack from '@mui/material/Stack'; -import Avatar from '@mui/material/Avatar'; -import ModeEditIcon from '@mui/icons-material/ModeEdit'; -import Button from '@mui/material/Button'; - -interface InterfaceUser { - _id: string; - firstName: string; - lastName: string; -} -interface InterfaceTask { - _id: string; - title: string; - deadline: string; - description: string; - completed: boolean; - volunteers: InterfaceUser[]; -} - -export type ModalPropType = { - show: boolean; - task: InterfaceTask; - organization: { - _id: string; - members: InterfaceUser[]; - }; - handleClose: () => void; - refetchData: () => void; -}; - -export const UpdateTaskModal = (props: ModalPropType): JSX.Element => { - const [title, setTitle] = useState(''); - const [description, setDescription] = useState(''); - const [deadline, setDeadline] = useState(null); - const [completed, setCompleted] = useState(false); - - const [showDeleteTaskModal, setShowDeleteTaskModal] = useState(false); - const [showManageVolunteerModal, setShowManageVolunteerModal] = - useState(false); - - useEffect(() => { - setTitle(props.task.title); - setDescription(props.task.description); - setDeadline(dayjs(props.task.deadline)); - setCompleted(props.task.completed); - }, [props.task]); - - const [updateMutation] = useMutation(UPDATE_EVENT_PROJECT_TASK_MUTATION); - const notify = (e: React.FormEvent): Promise => { - e.preventDefault(); - return toast.promise(handleSubmit, { - pending: 'Updating the task...', - success: 'Updated the task successfully!', - error: 'There was an error in updating the task!', - }); - }; - const handleSubmit = async (): Promise => { - let toSubmit = true; - - if (title.trim().length == 0) { - toast.error('Title cannot be empty!'); - toSubmit = false; - } - if (description.trim().length == 0) { - toast.error('Description cannot be empty!'); - toSubmit = false; - } - if (!toSubmit) return Promise.reject(); - - await updateMutation({ - variables: { - taskId: props.task._id, - title, - description, - deadline, - completed, - }, - }); - props.refetchData(); - props.handleClose(); - }; - - return ( - <> - - - - Update the Event Task - - -
    - - - Title - setTitle(e.target.value)} - /> - - - - Description - setDescription(e.target.value)} - /> - - - { - setDeadline(date); - }} - disablePast - className="mb-1" - /> - - - Completed - setCompleted(!completed)} - /> - - - - Volunteers -
    - {!props.task.volunteers.length - ? `There are no volunteers assigned for this task.` - : null} - - {props.task.volunteers.map( - (user): React.ReactNode => ( - {`${user.firstName[0].toUpperCase()}${user.lastName[0].toUpperCase()}`} - } - label={`${user.firstName} ${user.lastName}`} - variant="outlined" - /> - ) - )} - - -
    -
    -
    - - - Update Task - - { - setShowDeleteTaskModal(true); - props.handleClose(); - }} - > - Delete Task - - -
    -
    - { - setShowDeleteTaskModal(false); - }} - /> - { - setShowManageVolunteerModal(false); - }} - volunteers={props.task.volunteers} - organization={props.organization} - taskId={props.task._id} - /> - - ); -}; diff --git a/src/components/UserListCard/UserListCard.test.tsx b/src/components/UserListCard/UserListCard.test.tsx index 894571a597..9f59bb92ce 100644 --- a/src/components/UserListCard/UserListCard.test.tsx +++ b/src/components/UserListCard/UserListCard.test.tsx @@ -41,12 +41,8 @@ describe('Testing User List Card', () => { test('Should render props and text elements test for the page component', async () => { const props = { - key: '123', + key: 123, id: '456', - memberName: 'John Doe', - joinDate: '07/05/2022', - memberImage: 'image', - memberEmail: 'johndoe@gmail.com', }; render( @@ -56,26 +52,18 @@ describe('Testing User List Card', () => { - + , ); await wait(); userEvent.click(screen.getByText(/Add Admin/i)); - - expect(screen.getByText('Joined:')).toBeInTheDocument(); - expect(screen.getByText(props.memberName)).toBeInTheDocument(); - expect(screen.getByText(props.joinDate)).toBeInTheDocument(); }); test('Should render text elements when props value is not passed', async () => { const props = { - key: '123', + key: 123, id: '456', - memberName: '', - joinDate: '09/05/2022', - memberImage: '', - memberEmail: '', }; render( @@ -85,14 +73,10 @@ describe('Testing User List Card', () => { - + , ); await wait(); - userEvent.click(screen.getByText(/Add Admin/i)); - - expect(screen.getByText('Joined:')).toBeInTheDocument(); - expect(screen.getByText(props.joinDate)).toBeInTheDocument(); }); }); diff --git a/src/components/UserListCard/UserListCard.tsx b/src/components/UserListCard/UserListCard.tsx index 9bdda78636..5954e22e6c 100644 --- a/src/components/UserListCard/UserListCard.tsx +++ b/src/components/UserListCard/UserListCard.tsx @@ -1,6 +1,4 @@ import React from 'react'; -import Row from 'react-bootstrap/Row'; -import Col from 'react-bootstrap/Col'; import Button from 'react-bootstrap/Button'; import { useMutation } from '@apollo/client'; import { toast } from 'react-toastify'; @@ -8,21 +6,16 @@ import { useTranslation } from 'react-i18next'; import { ADD_ADMIN_MUTATION } from 'GraphQl/Mutations/mutations'; import styles from './UserListCard.module.css'; -import { Link } from 'react-router-dom'; -import defaultImg from 'assets/images/blank.png'; +import { useParams } from 'react-router-dom'; import { errorHandler } from 'utils/errorHandler'; interface InterfaceUserListCardProps { - key: string; + key: number; id: string; - memberName: string; - joinDate: string; - memberImage: string; - memberEmail: string; } function userListCard(props: InterfaceUserListCardProps): JSX.Element { - const currentUrl = window.location.href.split('=')[1]; + const { orgId: currentUrl } = useParams(); const [adda] = useMutation(ADD_ADMIN_MUTATION); const { t } = useTranslation('translation', { @@ -53,41 +46,9 @@ function userListCard(props: InterfaceUserListCardProps): JSX.Element { return ( <> -
    - - {props.memberImage ? ( - - ) : ( - - )} - -
    - - {props.memberName ? <>{props.memberName} : <>Dogs Care} - -

    {props.memberEmail}

    -
    -
    -

    - {t('joined')}: {props.joinDate} -

    - -
    - -
    -
    -
    + ); } diff --git a/src/components/UserPasswordUpdate/UserPasswordUpdate.module.css b/src/components/UserPasswordUpdate/UserPasswordUpdate.module.css index 54cf1c020c..90b5c09be3 100644 --- a/src/components/UserPasswordUpdate/UserPasswordUpdate.module.css +++ b/src/components/UserPasswordUpdate/UserPasswordUpdate.module.css @@ -53,7 +53,9 @@ font-weight: 600; cursor: pointer; float: left; - transition: transform 0.2s, box-shadow 0.2s; + transition: + transform 0.2s, + box-shadow 0.2s; } .greenregbtn { margin: 1rem 0 0; @@ -70,7 +72,9 @@ outline: none; font-weight: 600; cursor: pointer; - transition: transform 0.2s, box-shadow 0.2s; + transition: + transform 0.2s, + box-shadow 0.2s; } .radio_buttons { width: 55%; diff --git a/src/components/UserPasswordUpdate/UserPasswordUpdate.test.tsx b/src/components/UserPasswordUpdate/UserPasswordUpdate.test.tsx index 285b430c59..2aa5756717 100644 --- a/src/components/UserPasswordUpdate/UserPasswordUpdate.test.tsx +++ b/src/components/UserPasswordUpdate/UserPasswordUpdate.test.tsx @@ -69,32 +69,32 @@ describe('Testing User Password Update', () => { - + , ); await wait(); userEvent.type( screen.getByPlaceholderText(/Previous Password/i), - formData.previousPassword + formData.previousPassword, ); userEvent.type( screen.getAllByPlaceholderText(/New Password/i)[0], - formData.newPassword + formData.newPassword, ); userEvent.type( screen.getByPlaceholderText(/Confirm New Password/i), - formData.confirmNewPassword + formData.confirmNewPassword, ); userEvent.click(screen.getByText(/Save Changes/i)); expect(screen.getByText(/Cancel/i)).toBeTruthy(); expect( - screen.getByPlaceholderText(/Previous Password/i) + screen.getByPlaceholderText(/Previous Password/i), ).toBeInTheDocument(); expect( - screen.getByPlaceholderText(/Confirm New Password/i) + screen.getByPlaceholderText(/Confirm New Password/i), ).toBeInTheDocument(); }); @@ -104,14 +104,14 @@ describe('Testing User Password Update', () => { - + , ); userEvent.click(screen.getByText(/Save Changes/i)); await wait(); expect(mockToast.error).toHaveBeenCalledWith( - 'The password field cannot be empty.' + 'The password field cannot be empty.', ); }); @@ -121,22 +121,22 @@ describe('Testing User Password Update', () => { - + , ); await wait(); userEvent.type( screen.getByPlaceholderText(/Previous Password/i), - formData.previousPassword + formData.previousPassword, ); userEvent.type( screen.getAllByPlaceholderText(/New Password/i)[0], - formData.wrongPassword + formData.wrongPassword, ); userEvent.type( screen.getByPlaceholderText(/Confirm New Password/i), - formData.confirmNewPassword + formData.confirmNewPassword, ); userEvent.click(screen.getByText(/Save Changes/i)); @@ -144,7 +144,7 @@ describe('Testing User Password Update', () => { expect(screen.getByText(/Cancel/i)).toBeTruthy(); await wait(); expect(mockToast.error).toHaveBeenCalledWith( - 'New and Confirm password do not match.' + 'New and Confirm password do not match.', ); }); }); diff --git a/src/components/UserPasswordUpdate/UserPasswordUpdate.tsx b/src/components/UserPasswordUpdate/UserPasswordUpdate.tsx index 2fc2874360..cbb771be0e 100644 --- a/src/components/UserPasswordUpdate/UserPasswordUpdate.tsx +++ b/src/components/UserPasswordUpdate/UserPasswordUpdate.tsx @@ -11,11 +11,9 @@ interface InterfaceUserPasswordUpdateProps { id: string; } -// eslint-disable-next-line @typescript-eslint/no-unused-vars -const UserUpdate: React.FC = ({ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - id, -}): JSX.Element => { +const UserUpdate: React.FC< + InterfaceUserPasswordUpdateProps +> = (): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'userPasswordUpdate', }); diff --git a/src/components/UserPortal/ChatRoom/ChatRoom.test.tsx b/src/components/UserPortal/ChatRoom/ChatRoom.test.tsx new file mode 100644 index 0000000000..9b63779582 --- /dev/null +++ b/src/components/UserPortal/ChatRoom/ChatRoom.test.tsx @@ -0,0 +1,72 @@ +import React from 'react'; + +import { act, render, screen, fireEvent } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider } from 'react-i18next'; + +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import ContactCard from './ChatRoom'; + +const link = new StaticMockLink([], true); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Testing Chatroom Component [User Portal]', () => { + test('Component should be rendered properly if the selectedContact is undefined', async () => { + render( + + + + + + + + + , + ); + await wait(); + }); + + test('Component should be rendered properly if selectedContact is not undefined', async () => { + render( + + + + + + + + + , + ); + await wait(); + }); + + test('Message should change when the user types in the input', async () => { + render( + + + + + + + + + , + ); + const input = screen.getByTestId('messageInput') as HTMLInputElement; + fireEvent.change(input, { target: { value: 'Hello' } }); + + expect(input.value).toBe('Hello'); + }); +}); diff --git a/src/components/UserPortal/ChatRoom/ChatRoom.tsx b/src/components/UserPortal/ChatRoom/ChatRoom.tsx index c7ada20a13..ac65a76199 100644 --- a/src/components/UserPortal/ChatRoom/ChatRoom.tsx +++ b/src/components/UserPortal/ChatRoom/ChatRoom.tsx @@ -66,6 +66,7 @@ export default function chatRoom(props: InterfaceChatRoomProps): JSX.Element { placeholder={t('sendMessage')} aria-label="Send Message" value={newMessage} + data-testid="messageInput" onChange={handleNewMessageChange} className={styles.backgroundWhite} /> diff --git a/src/components/UserPortal/CommentCard/CommentCard.test.tsx b/src/components/UserPortal/CommentCard/CommentCard.test.tsx index c586809132..35b81167fc 100644 --- a/src/components/UserPortal/CommentCard/CommentCard.test.tsx +++ b/src/components/UserPortal/CommentCard/CommentCard.test.tsx @@ -11,6 +11,9 @@ import { StaticMockLink } from 'utils/StaticMockLink'; import CommentCard from './CommentCard'; import userEvent from '@testing-library/user-event'; import { LIKE_COMMENT, UNLIKE_COMMENT } from 'GraphQl/Mutations/mutations'; +import useLocalStorage from 'utils/useLocalstorage'; + +const { getItem, setItem } = useLocalStorage(); async function wait(ms = 100): Promise { await act(() => { @@ -53,6 +56,8 @@ const MOCKS = [ }, ]; +const handleLikeComment = jest.fn(); +const handleDislikeComment = jest.fn(); const link = new StaticMockLink(MOCKS, true); describe('Testing CommentCard Component [User Portal]', () => { @@ -78,10 +83,12 @@ describe('Testing CommentCard Component [User Portal]', () => { }, ], text: 'testComment', + handleLikeComment: handleLikeComment, + handleDislikeComment: handleDislikeComment, }; - const beforeUserId = localStorage.getItem('userId'); - localStorage.setItem('userId', '2'); + const beforeUserId = getItem('userId'); + setItem('userId', '2'); render( @@ -92,12 +99,12 @@ describe('Testing CommentCard Component [User Portal]', () => { - + , ); await wait(); if (beforeUserId) { - localStorage.setItem('userId', beforeUserId); + setItem('userId', beforeUserId); } }); @@ -117,10 +124,12 @@ describe('Testing CommentCard Component [User Portal]', () => { }, ], text: 'testComment', + handleLikeComment: handleLikeComment, + handleDislikeComment: handleDislikeComment, }; - const beforeUserId = localStorage.getItem('userId'); - localStorage.setItem('userId', '1'); + const beforeUserId = getItem('userId'); + setItem('userId', '1'); render( @@ -131,12 +140,12 @@ describe('Testing CommentCard Component [User Portal]', () => { - + , ); await wait(); if (beforeUserId) { - localStorage.setItem('userId', beforeUserId); + setItem('userId', beforeUserId); } }); @@ -156,10 +165,12 @@ describe('Testing CommentCard Component [User Portal]', () => { }, ], text: 'testComment', + handleLikeComment: handleLikeComment, + handleDislikeComment: handleDislikeComment, }; - const beforeUserId = localStorage.getItem('userId'); - localStorage.setItem('userId', '2'); + const beforeUserId = getItem('userId'); + setItem('userId', '2'); render( @@ -170,7 +181,7 @@ describe('Testing CommentCard Component [User Portal]', () => { - + , ); await wait(); @@ -180,7 +191,7 @@ describe('Testing CommentCard Component [User Portal]', () => { await wait(); if (beforeUserId) { - localStorage.setItem('userId', beforeUserId); + setItem('userId', beforeUserId); } }); @@ -200,10 +211,12 @@ describe('Testing CommentCard Component [User Portal]', () => { }, ], text: 'testComment', + handleLikeComment: handleLikeComment, + handleDislikeComment: handleDislikeComment, }; - const beforeUserId = localStorage.getItem('userId'); - localStorage.setItem('userId', '1'); + const beforeUserId = getItem('userId'); + setItem('userId', '1'); render( @@ -214,7 +227,7 @@ describe('Testing CommentCard Component [User Portal]', () => { - + , ); await wait(); @@ -222,7 +235,7 @@ describe('Testing CommentCard Component [User Portal]', () => { userEvent.click(screen.getByTestId('likeCommentBtn')); if (beforeUserId) { - localStorage.setItem('userId', beforeUserId); + setItem('userId', beforeUserId); } }); }); diff --git a/src/components/UserPortal/CommentCard/CommentCard.tsx b/src/components/UserPortal/CommentCard/CommentCard.tsx index 8b2d5a8fca..955f136cb5 100644 --- a/src/components/UserPortal/CommentCard/CommentCard.tsx +++ b/src/components/UserPortal/CommentCard/CommentCard.tsx @@ -7,6 +7,7 @@ import { LIKE_COMMENT, UNLIKE_COMMENT } from 'GraphQl/Mutations/mutations'; import { toast } from 'react-toastify'; import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; import ThumbUpOffAltIcon from '@mui/icons-material/ThumbUpOffAlt'; +import useLocalStorage from 'utils/useLocalstorage'; interface InterfaceCommentCardProps { id: string; @@ -21,12 +22,15 @@ interface InterfaceCommentCardProps { id: string; }[]; text: string; + handleLikeComment: (commentId: string) => void; + handleDislikeComment: (commentId: string) => void; } function commentCard(props: InterfaceCommentCardProps): JSX.Element { const creatorName = `${props.creator.firstName} ${props.creator.lastName}`; - const userId = localStorage.getItem('userId'); + const { getItem } = useLocalStorage(); + const userId = getItem('userId'); const likedByUser = props.likedBy.some((likedBy) => likedBy.id === userId); const [likes, setLikes] = React.useState(props.likeCount); @@ -47,6 +51,7 @@ function commentCard(props: InterfaceCommentCardProps): JSX.Element { if (data) { setLikes((likes) => likes - 1); setIsLikedByUser(false); + props.handleDislikeComment(props.id); } } catch (error: any) { /* istanbul ignore next */ @@ -63,6 +68,7 @@ function commentCard(props: InterfaceCommentCardProps): JSX.Element { if (data) { setLikes((likes) => likes + 1); setIsLikedByUser(true); + props.handleLikeComment(props.id); } } catch (error: any) { /* istanbul ignore next */ diff --git a/src/components/UserPortal/ContactCard/ContactCard.test.tsx b/src/components/UserPortal/ContactCard/ContactCard.test.tsx index cb7aaec882..7e7530bc58 100644 --- a/src/components/UserPortal/ContactCard/ContactCard.test.tsx +++ b/src/components/UserPortal/ContactCard/ContactCard.test.tsx @@ -43,7 +43,7 @@ describe('Testing ContactCard Component [User Portal]', () => { - + , ); await wait(); @@ -64,7 +64,7 @@ describe('Testing ContactCard Component [User Portal]', () => { - + , ); await wait(); @@ -80,7 +80,7 @@ describe('Testing ContactCard Component [User Portal]', () => { - + , ); await wait(); @@ -104,7 +104,7 @@ describe('Testing ContactCard Component [User Portal]', () => { - + , ); await wait(); diff --git a/src/components/UserPortal/ContactCard/ContactCard.tsx b/src/components/UserPortal/ContactCard/ContactCard.tsx index 8dd5352b43..be4247205b 100644 --- a/src/components/UserPortal/ContactCard/ContactCard.tsx +++ b/src/components/UserPortal/ContactCard/ContactCard.tsx @@ -1,5 +1,6 @@ import React from 'react'; import styles from './ContactCard.module.css'; +import Avatar from 'components/Avatar/Avatar'; interface InterfaceContactCardProps { id: string; @@ -14,9 +15,6 @@ interface InterfaceContactCardProps { function contactCard(props: InterfaceContactCardProps): JSX.Element { const contactName = `${props.firstName} ${props.lastName}`; - const imageUrl = props.image - ? props.image - : `https://api.dicebear.com/5.x/initials/svg?seed=${contactName}`; const handleSelectedContactChange = (): void => { props.setSelectedContact(props.id); @@ -24,7 +22,7 @@ function contactCard(props: InterfaceContactCardProps): JSX.Element { }; const [isSelected, setIsSelected] = React.useState( - props.selectedContact === props.id + props.selectedContact === props.id, ); React.useEffect(() => { @@ -40,7 +38,19 @@ function contactCard(props: InterfaceContactCardProps): JSX.Element { onClick={handleSelectedContactChange} data-testid="contactContainer" > - {contactName} + {props.image ? ( + {contactName} + ) : ( + + )}
    {contactName} {props.email} diff --git a/src/components/UserPortal/DonationCard/DonationCard.module.css b/src/components/UserPortal/DonationCard/DonationCard.module.css index 76fcaf3b0c..3fa737ada2 100644 --- a/src/components/UserPortal/DonationCard/DonationCard.module.css +++ b/src/components/UserPortal/DonationCard/DonationCard.module.css @@ -1,19 +1,38 @@ .mainContainer { - width: 100%; + width: 49%; + height: 8rem; + min-width: max-content; display: flex; - flex-direction: row; - padding: 10px; - cursor: pointer; + justify-content: space-between; + gap: 1rem; + padding: 1rem; background-color: white; + border: 1px solid #dddddd; border-radius: 10px; - box-shadow: 2px 2px 8px 0px #c8c8c8; overflow: hidden; } +.img { + height: 100%; + aspect-ratio: 1/1; + background-color: rgba(49, 187, 107, 12%); +} + +.btn { + display: flex; + align-items: flex-end; +} + +.btn button { + padding-inline: 2rem !important; + border-radius: 5px; +} + .personDetails { display: flex; flex-direction: column; justify-content: center; + min-width: max-content; } .personImage { diff --git a/src/screens/UserPortal/UserLoginPage/UserLoginPage.test.tsx b/src/components/UserPortal/DonationCard/DonationCard.test.tsx similarity index 65% rename from src/screens/UserPortal/UserLoginPage/UserLoginPage.test.tsx rename to src/components/UserPortal/DonationCard/DonationCard.test.tsx index d60e37c682..4e49ed8b26 100644 --- a/src/screens/UserPortal/UserLoginPage/UserLoginPage.test.tsx +++ b/src/components/UserPortal/DonationCard/DonationCard.test.tsx @@ -1,14 +1,17 @@ import React from 'react'; -import { MockedProvider } from '@apollo/react-testing'; import { act, render } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; import { I18nextProvider } from 'react-i18next'; -import { Provider } from 'react-redux'; + import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; import { store } from 'state/store'; -import { StaticMockLink } from 'utils/StaticMockLink'; import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import DonationCard from './DonationCard'; +import { type InterfaceDonationCardProps } from 'screens/UserPortal/Donate/Donate'; -import UserLoginPage from './UserLoginPage'; +const link = new StaticMockLink([], true); async function wait(ms = 100): Promise { await act(() => { @@ -18,20 +21,27 @@ async function wait(ms = 100): Promise { }); } -const link = new StaticMockLink([], true); +const props: InterfaceDonationCardProps = { + id: '1', + name: 'John Doe', + amount: '20', + userId: '1234', + payPalId: 'id', + updatedAt: String(new Date()), +}; -describe('Testing User Login Page Screen [User Portal]', () => { - test('Screen should be rendered properly', async () => { +describe('Testing ContactCard Component [User Portal]', () => { + test('Component should be rendered properly', async () => { render( - + - + , ); await wait(); diff --git a/src/components/UserPortal/DonationCard/DonationCard.tsx b/src/components/UserPortal/DonationCard/DonationCard.tsx index 436e3049b8..696c5fb57b 100644 --- a/src/components/UserPortal/DonationCard/DonationCard.tsx +++ b/src/components/UserPortal/DonationCard/DonationCard.tsx @@ -1,21 +1,31 @@ import React from 'react'; import styles from './DonationCard.module.css'; - -interface InterfaceDonationCardProps { - id: string; - name: string; - amount: string; - userId: string; - payPalId: string; -} +import { type InterfaceDonationCardProps } from 'screens/UserPortal/Donate/Donate'; +import { Button } from 'react-bootstrap'; function donationCard(props: InterfaceDonationCardProps): JSX.Element { + const date = new Date(props.updatedAt); + const formattedDate = new Intl.DateTimeFormat('en-US', { + weekday: 'short', + year: 'numeric', + month: 'short', + day: 'numeric', + }).format(date); + return ( -
    +
    +
    - {props.name} + + {props.name} + Amount: {props.amount} - PayPal Id: {props.payPalId} + Date: {formattedDate} +
    +
    +
    ); diff --git a/src/components/UserPortal/EventCard/EventCard.test.tsx b/src/components/UserPortal/EventCard/EventCard.test.tsx index 8e5079767e..78aa32abcf 100644 --- a/src/components/UserPortal/EventCard/EventCard.test.tsx +++ b/src/components/UserPortal/EventCard/EventCard.test.tsx @@ -11,6 +11,10 @@ import { Provider } from 'react-redux'; import { store } from 'state/store'; import { StaticMockLink } from 'utils/StaticMockLink'; import userEvent from '@testing-library/user-event'; +import { debug } from 'jest-preview'; +import useLocalStorage from 'utils/useLocalstorage'; + +const { setItem } = useLocalStorage(); const MOCKS = [ { @@ -46,8 +50,8 @@ describe('Testing Event Card In User portal', () => { endDate: '2023-04-15', isRegisterable: true, isPublic: true, - endTime: '19:49:12Z', - startTime: '17:49:12Z', + endTime: '19:49:12', + startTime: '17:49:12', recurring: false, allDay: true, creator: { @@ -73,23 +77,28 @@ describe('Testing Event Card In User portal', () => { - + , ); + debug(); await waitFor(() => expect(queryByText('Test Event')).toBeInTheDocument()); await waitFor(() => - expect(queryByText('This is a test event')).toBeInTheDocument() + expect(queryByText('This is a test event')).toBeInTheDocument(), ); await waitFor(() => expect(queryByText('Location')).toBeInTheDocument()); await waitFor(() => expect(queryByText('Virtual')).toBeInTheDocument()); await waitFor(() => expect(queryByText('Starts')).toBeInTheDocument()); - await waitFor(() => expect(queryByText('5:49:12 PM')).toBeInTheDocument()); await waitFor(() => - expect(queryByText(`13 April '23`)).toBeInTheDocument() + expect(screen.getByTestId('startTime')).toBeInTheDocument(), + ); + await waitFor(() => + expect(queryByText(`13 April '23`)).toBeInTheDocument(), ); await waitFor(() => expect(queryByText('Ends')).toBeInTheDocument()); - await waitFor(() => expect(queryByText('7:49:12 PM')).toBeInTheDocument()); await waitFor(() => - expect(queryByText(`15 April '23`)).toBeInTheDocument() + expect(screen.getByTestId('endTime')).toBeInTheDocument(), + ); + await waitFor(() => + expect(queryByText(`15 April '23`)).toBeInTheDocument(), ); await waitFor(() => expect(queryByText('Creator')).toBeInTheDocument()); await waitFor(() => expect(queryByText('Joe David')).toBeInTheDocument()); @@ -97,7 +106,7 @@ describe('Testing Event Card In User portal', () => { }); test('When the user is already registered', async () => { - localStorage.setItem('userId', '234'); + setItem('userId', '234'); const { queryByText } = render( @@ -108,15 +117,15 @@ describe('Testing Event Card In User portal', () => { - + , ); await waitFor(() => - expect(queryByText('Already registered')).toBeInTheDocument() + expect(queryByText('Already registered')).toBeInTheDocument(), ); }); test('Handle register should work properly', async () => { - localStorage.setItem('userId', '456'); + setItem('userId', '456'); const { queryByText } = render( @@ -127,13 +136,13 @@ describe('Testing Event Card In User portal', () => { - + , ); userEvent.click(screen.getByText('Register')); await waitFor(() => expect( - queryByText('Successfully registered for Test Event') - ).toBeInTheDocument() + queryByText('Successfully registered for Test Event'), + ).toBeInTheDocument(), ); }); }); @@ -175,11 +184,11 @@ describe('Event card when start and end time are not given', () => { - + , ); await waitFor(() => - expect(container.querySelector(':empty')).toBeInTheDocument() + expect(container.querySelector(':empty')).toBeInTheDocument(), ); }); }); diff --git a/src/components/UserPortal/EventCard/EventCard.tsx b/src/components/UserPortal/EventCard/EventCard.tsx index 5aac562c06..20c08bab2b 100644 --- a/src/components/UserPortal/EventCard/EventCard.tsx +++ b/src/components/UserPortal/EventCard/EventCard.tsx @@ -10,6 +10,8 @@ import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; import { REGISTER_EVENT } from 'GraphQl/Mutations/mutations'; import { useTranslation } from 'react-i18next'; +import useLocalStorage from 'utils/useLocalstorage'; + interface InterfaceEventCardProps { id: string; title: string; @@ -37,10 +39,11 @@ function eventCard(props: InterfaceEventCardProps): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'userEventCard', }); - const userId = localStorage.getItem('userId'); + const { getItem } = useLocalStorage(); + const userId = getItem('userId'); const creatorName = `${props.creator.firstName} ${props.creator.lastName}`; const isInitiallyRegistered = props.registrants.some( - (registrant) => registrant.id === userId + (registrant) => registrant.id === userId, ); const [registerEventMutation, { loading }] = useMutation(REGISTER_EVENT); @@ -84,7 +87,9 @@ function eventCard(props: InterfaceEventCardProps): JSX.Element {
    {`${t('starts')} `} {props.startTime ? ( - {dayjs(`2015-03-04T${props.startTime}`).format('h:mm:ss A')} + + {dayjs(`2015-03-04T${props.startTime}`).format('h:mm:ss A')} + ) : ( <> )} @@ -93,7 +98,9 @@ function eventCard(props: InterfaceEventCardProps): JSX.Element {
    {`${t('ends')} `} {props.endTime ? ( - {dayjs(`2015-03-04T${props.endTime}`).format('h:mm:ss A')} + + {dayjs(`2015-03-04T${props.endTime}`).format('h:mm:ss A')} + ) : ( <> )}{' '} diff --git a/src/components/UserPortal/Login/Login.test.tsx b/src/components/UserPortal/Login/Login.test.tsx index 2ce9ebe9cc..a59d9d9063 100644 --- a/src/components/UserPortal/Login/Login.test.tsx +++ b/src/components/UserPortal/Login/Login.test.tsx @@ -28,11 +28,21 @@ const MOCKS = [ login: { user: { _id: '1', - userType: 'ADMIN', - adminApproved: true, + firstName: 'firstname', + lastName: 'secondname', + email: 'tempemail@example.com', + image: 'image', }, accessToken: 'accessToken', refreshToken: 'refreshToken', + appUserProfile: { + adminFor: [ + { + _id: 'id', + }, + ], + isSuperAdmin: true, + }, }, }, }, @@ -50,8 +60,14 @@ const MOCKS = [ login: { user: { _id: '1', - userType: 'ADMIN', - adminApproved: false, + firstName: 'firstname', + lastName: 'secondname', + email: 'tempemail@example.com', + image: 'image', + }, + appUserProfile: { + adminFor: {}, + isSuperAdmin: false, }, accessToken: 'accessToken', refreshToken: 'refreshToken', @@ -88,6 +104,11 @@ jest.mock('react-toastify', () => ({ error: jest.fn(), }, })); +const mockNavigate = jest.fn(); +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useNavigate: () => mockNavigate, +})); const setCurrentMode: React.Dispatch> = jest.fn(); @@ -106,7 +127,7 @@ describe('Testing Login Component [User Portal]', () => { - + , ); await wait(); @@ -122,7 +143,7 @@ describe('Testing Login Component [User Portal]', () => { - + , ); await wait(); @@ -142,7 +163,7 @@ describe('Testing Login Component [User Portal]', () => { - + , ); await wait(); @@ -150,7 +171,7 @@ describe('Testing Login Component [User Portal]', () => { userEvent.click(screen.getByTestId('loginBtn')); expect(toast.error).toBeCalledWith( - 'Please enter a valid email and password.' + 'Please enter a valid email and password.', ); }); @@ -169,19 +190,19 @@ describe('Testing Login Component [User Portal]', () => { - + , ); await wait(); userEvent.type( screen.getByPlaceholderText(/Enter your email address/i), - formData.email + formData.email, ); userEvent.click(screen.getByTestId('loginBtn')); expect(toast.error).toBeCalledWith( - 'Please enter a valid email and password.' + 'Please enter a valid email and password.', ); }); @@ -200,19 +221,19 @@ describe('Testing Login Component [User Portal]', () => { - + , ); await wait(); userEvent.type( screen.getByPlaceholderText(/Enter your email address/i), - formData.email + formData.email, ); userEvent.type( screen.getByPlaceholderText(/Enter your password/i), - formData.password + formData.password, ); userEvent.click(screen.getByTestId('loginBtn')); @@ -237,24 +258,25 @@ describe('Testing Login Component [User Portal]', () => { - + , ); await wait(); userEvent.type( screen.getByPlaceholderText(/Enter your email address/i), - formData.email + formData.email, ); userEvent.type( screen.getByPlaceholderText(/Enter your password/i), - formData.password + formData.password, ); userEvent.click(screen.getByTestId('loginBtn')); await wait(); + expect(mockNavigate).toHaveBeenCalledWith('/user/organizations'); }); test('Current user has not been approved by admin.', async () => { @@ -272,19 +294,19 @@ describe('Testing Login Component [User Portal]', () => { - + , ); await wait(); userEvent.type( screen.getByPlaceholderText(/Enter your email address/i), - formData.email + formData.email, ); userEvent.type( screen.getByPlaceholderText(/Enter your password/i), - formData.password + formData.password, ); userEvent.click(screen.getByTestId('loginBtn')); diff --git a/src/components/UserPortal/Login/Login.tsx b/src/components/UserPortal/Login/Login.tsx index 326d416c06..9fd40c3615 100644 --- a/src/components/UserPortal/Login/Login.tsx +++ b/src/components/UserPortal/Login/Login.tsx @@ -1,16 +1,17 @@ +import { useMutation } from '@apollo/client'; +import { LockOutlined } from '@mui/icons-material'; +import EmailOutlinedIcon from '@mui/icons-material/EmailOutlined'; import type { ChangeEvent, SetStateAction } from 'react'; import React from 'react'; import { Button, Form, InputGroup } from 'react-bootstrap'; import { useTranslation } from 'react-i18next'; -import EmailOutlinedIcon from '@mui/icons-material/EmailOutlined'; -import { LockOutlined } from '@mui/icons-material'; -import { Link } from 'react-router-dom'; -import { useMutation } from '@apollo/client'; +import { Link, useNavigate } from 'react-router-dom'; import { toast } from 'react-toastify'; import { LOGIN_MUTATION } from 'GraphQl/Mutations/mutations'; -import styles from './Login.module.css'; import { errorHandler } from 'utils/errorHandler'; +import useLocalStorage from 'utils/useLocalstorage'; +import styles from './Login.module.css'; interface InterfaceLoginProps { setCurrentMode: React.Dispatch>; @@ -19,8 +20,12 @@ interface InterfaceLoginProps { export default function login(props: InterfaceLoginProps): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'userLogin' }); + const navigate = useNavigate(); + const { setCurrentMode } = props; + const { setItem } = useLocalStorage(); + const handleModeChangeToRegister = (): void => { setCurrentMode('register'); }; @@ -44,18 +49,10 @@ export default function login(props: InterfaceLoginProps): JSX.Element { }, }); - if (data) { - localStorage.setItem('token', data.login.accessToken); - localStorage.setItem('userId', data.login.user._id); - - navigator.clipboard.writeText(''); - /* istanbul ignore next */ - window.location.assign('/user/organizations'); - } else { - toast.warn(t('notAuthorised')); - } + setItem('token', data.login.accessToken); + setItem('userId', data.login.user._id); + navigate('/user/organizations'); } catch (error: any) { - /* istanbul ignore next */ errorHandler(t, error); } } @@ -84,7 +81,6 @@ export default function login(props: InterfaceLoginProps): JSX.Element { return ( <>

    {t('login')}

    -
    {t('loginIntoYourAccount')}
    {t('emailAddress')}
    diff --git a/src/components/UserPortal/OrganizationCard/OrganizationCard.module.css b/src/components/UserPortal/OrganizationCard/OrganizationCard.module.css index dd3cd90378..15634f7ad0 100644 --- a/src/components/UserPortal/OrganizationCard/OrganizationCard.module.css +++ b/src/components/UserPortal/OrganizationCard/OrganizationCard.module.css @@ -1,22 +1,149 @@ -.mainContainer { - width: 100%; +.orgCard { + background-color: var(--bs-white); + margin: 0.5rem; + height: calc(120px + 2rem); + padding: 1rem; + border-radius: 8px; + outline: 1px solid var(--bs-gray-200); + position: relative; +} + +.orgCard .innerContainer { display: flex; - flex-direction: row; - padding: 10px; - cursor: pointer; - background-color: white; - border-radius: 10px; - box-shadow: 2px 2px 8px 0px #c8c8c8; - overflow: hidden; } -.organizationDetails { +.orgCard .innerContainer .orgImgContainer { display: flex; - flex-direction: column; justify-content: center; + align-items: center; + position: relative; + overflow: hidden; + border-radius: 4px; + width: 125px; + height: 120px; + object-fit: contain; + background-color: var(--bs-gray-200); +} + +.orgCard .innerContainer .content { + flex: 1; + margin-left: 1rem; + width: 70%; + margin-top: 0.7rem; +} + +.orgCard button { + position: absolute; + bottom: 1rem; + right: 1rem; + z-index: 1; +} + +.joinBtn { + display: flex; + justify-content: space-around; + width: 8rem; + border-width: medium; +} + +.joinedBtn { + display: flex; + justify-content: space-around; + width: 8rem; +} + +.withdrawBtn { + display: flex; + justify-content: space-around; + width: 8rem; +} + +.orgName { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + font-size: 1rem; } -.removeDecoration { - text-decoration: none !important; - color: black; +.orgdesc { + font-size: 0.9rem; + color: var(--bs-gray-600); + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 1; + line-clamp: 1; + -webkit-box-orient: vertical; + max-width: 20rem; +} + +.orgadmin { + font-size: 0.9rem; +} + +.orgmember { + font-size: 0.9rem; +} + +.address { + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 1; + line-clamp: 1; + -webkit-box-orient: vertical; + align-items: center; +} + +.address h6 { + font-size: 0.9rem; + color: var(--bs-gray-600); +} + +@media (max-width: 1420px) { + .orgCard { + width: 100%; + } +} + +@media (max-width: 550px) { + .orgCard { + width: 100%; + } + + .orgCard { + height: unset; + margin: 0.5rem 0; + padding: 1.25rem 1.5rem; + } + + .orgCard .innerContainer .orgImgContainer { + margin-bottom: 0.8rem; + } + + .orgCard .innerContainer { + flex-direction: column; + } + + .orgCard .innerContainer .orgImgContainer img { + height: auto; + width: 100%; + } + + .orgCard .innerContainer .content { + margin-left: 0; + } + + .orgCard button { + bottom: 0; + right: 0; + position: relative; + margin-left: auto; + display: block; + } + .joinBtn, + .joinedBtn, + .withdrawBtn { + display: flex; + justify-content: space-around; + width: 100%; + } } diff --git a/src/components/UserPortal/OrganizationCard/OrganizationCard.test.tsx b/src/components/UserPortal/OrganizationCard/OrganizationCard.test.tsx index fa4339e810..dba4286290 100644 --- a/src/components/UserPortal/OrganizationCard/OrganizationCard.test.tsx +++ b/src/components/UserPortal/OrganizationCard/OrganizationCard.test.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { act, render } from '@testing-library/react'; +import { act, fireEvent, render, screen } from '@testing-library/react'; import { MockedProvider } from '@apollo/react-testing'; import { I18nextProvider } from 'react-i18next'; @@ -9,8 +9,145 @@ import { store } from 'state/store'; import i18nForTest from 'utils/i18nForTest'; import { StaticMockLink } from 'utils/StaticMockLink'; import OrganizationCard from './OrganizationCard'; +import { + USER_JOINED_ORGANIZATIONS, + USER_ORGANIZATION_CONNECTION, +} from 'GraphQl/Queries/OrganizationQueries'; +import useLocalStorage from 'utils/useLocalstorage'; +import { + SEND_MEMBERSHIP_REQUEST, + JOIN_PUBLIC_ORGANIZATION, +} from 'GraphQl/Mutations/OrganizationMutations'; +import { toast } from 'react-toastify'; -const link = new StaticMockLink([], true); +const { getItem } = useLocalStorage(); + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +const MOCKS = [ + { + request: { + query: SEND_MEMBERSHIP_REQUEST, + variables: { + organizationId: '1', + }, + }, + result: { + data: { + sendMembershipRequest: { + _id: 'edgwrgui4y28urfejwiwfw', + organization: { + _id: '1', + name: 'organizationName', + }, + user: { + _id: '1', + }, + }, + }, + }, + }, + { + request: { + query: JOIN_PUBLIC_ORGANIZATION, + variables: { + organizationId: '2', + }, + }, + result: { + data: { + joinPublicOrganization: { + _id: 'edgwrgui4y28urfejwiwfw', + }, + }, + }, + }, + { + request: { + query: USER_JOINED_ORGANIZATIONS, + variables: { + id: '1', + }, + }, + result: { + data: { + users: { + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '2', + image: 'organizationImage', + name: 'organizationName', + description: 'organizationDescription', + }, + ], + }, + }, + }, + }, + { + request: { + query: USER_ORGANIZATION_CONNECTION, + variables: { + id: '1', + }, + }, + result: { + data: { + organizationsConnection: [ + { + __typename: 'Organization', + _id: '2', + image: 'organizationImage', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + name: 'organizationName', + description: 'organizationDescription', + userRegistrationRequired: false, + createdAt: '12345678900', + creator: { __typename: 'User', firstName: 'John', lastName: 'Doe' }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: getItem('userId'), + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + }, + ], + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); async function wait(ms = 100): Promise { await act(() => { @@ -25,6 +162,29 @@ let props = { name: 'organizationName', image: '', description: 'organizationDescription', + admins: [ + { + id: '123', + }, + ], + members: [], + address: { + city: 'Sample City', + countryCode: 'US', + line1: '123 Sample Street', + postalCode: '', + state: '', + }, + membershipRequestStatus: '', + userRegistrationRequired: true, + membershipRequests: [ + { + _id: '', + user: { + _id: '', + }, + }, + ], }; describe('Testing OrganizationCard Component [User Portal]', () => { @@ -38,7 +198,7 @@ describe('Testing OrganizationCard Component [User Portal]', () => { - + , ); await wait(); @@ -59,9 +219,95 @@ describe('Testing OrganizationCard Component [User Portal]', () => { - + , + ); + + await wait(); + }); + + test('Send membership request', async () => { + props = { + ...props, + image: 'organizationImage', + }; + + render( + + + + + + + + + , + ); + + await wait(); + + expect(screen.getByTestId('joinBtn')).toBeInTheDocument(); + + fireEvent.click(screen.getByTestId('joinBtn')); + await wait(); + + expect(toast.success).toHaveBeenCalledWith('users.MembershipRequestSent'); + }); + + test('send membership request to public org', async () => { + const cardProps = { + ...props, + id: '2', + image: 'organizationImage', + userRegistrationRequired: false, + }; + + render( + + + + + + + + + , ); await wait(); + + expect(screen.getByTestId('joinBtn')).toBeInTheDocument(); + + fireEvent.click(screen.getByTestId('joinBtn')); + await wait(); + + expect(toast.success).toHaveBeenCalledTimes(2); + }); + + test('withdraw membership request', async () => { + const cardProps = { + ...props, + id: '3', + image: 'organizationImage', + userRegistrationRequired: true, + membershipRequestStatus: 'pending', + }; + + render( + + + + + + + + + , + ); + + await wait(); + + expect(screen.getByTestId('withdrawBtn')).toBeInTheDocument(); + + fireEvent.click(screen.getByTestId('withdrawBtn')); }); }); diff --git a/src/components/UserPortal/OrganizationCard/OrganizationCard.tsx b/src/components/UserPortal/OrganizationCard/OrganizationCard.tsx index 427d29366d..1d83eeac15 100644 --- a/src/components/UserPortal/OrganizationCard/OrganizationCard.tsx +++ b/src/components/UserPortal/OrganizationCard/OrganizationCard.tsx @@ -1,29 +1,195 @@ import React from 'react'; -import aboutImg from 'assets/images/defaultImg.png'; import styles from './OrganizationCard.module.css'; -import { Link } from 'react-router-dom'; +import { Button } from 'react-bootstrap'; +import { Tooltip } from '@mui/material'; +import { useTranslation } from 'react-i18next'; +import { toast } from 'react-toastify'; +import { + CANCEL_MEMBERSHIP_REQUEST, + JOIN_PUBLIC_ORGANIZATION, + SEND_MEMBERSHIP_REQUEST, +} from 'GraphQl/Mutations/OrganizationMutations'; +import { useMutation, useQuery } from '@apollo/client'; +import { + USER_JOINED_ORGANIZATIONS, + USER_ORGANIZATION_CONNECTION, +} from 'GraphQl/Queries/OrganizationQueries'; +import useLocalStorage from 'utils/useLocalstorage'; +import Avatar from 'components/Avatar/Avatar'; +import { useNavigate } from 'react-router-dom'; + +const { getItem } = useLocalStorage(); interface InterfaceOrganizationCardProps { id: string; name: string; image: string; description: string; + admins: { + id: string; + }[]; + members: { + id: string; + }[]; + address: { + city: string; + countryCode: string; + line1: string; + postalCode: string; + state: string; + }; + membershipRequestStatus: string; + userRegistrationRequired: boolean; + membershipRequests: { + _id: string; + user: { + _id: string; + }; + }[]; } +const userId: string | null = getItem('userId'); + function organizationCard(props: InterfaceOrganizationCardProps): JSX.Element { - const imageUrl = props.image ? props.image : aboutImg; - const redirectLink = `/user/organization/id=${props.id}`; + const { t } = useTranslation('translation', { + keyPrefix: 'users', + }); + + const navigate = useNavigate(); + + const [sendMembershipRequest] = useMutation(SEND_MEMBERSHIP_REQUEST, { + refetchQueries: [ + { query: USER_ORGANIZATION_CONNECTION, variables: { id: props.id } }, + ], + }); + const [joinPublicOrganization] = useMutation(JOIN_PUBLIC_ORGANIZATION, { + refetchQueries: [ + { query: USER_ORGANIZATION_CONNECTION, variables: { id: props.id } }, + ], + }); + const [cancelMembershipRequest] = useMutation(CANCEL_MEMBERSHIP_REQUEST, { + refetchQueries: [ + { query: USER_ORGANIZATION_CONNECTION, variables: { id: props.id } }, + ], + }); + const { refetch } = useQuery(USER_JOINED_ORGANIZATIONS, { + variables: { id: userId }, + }); + + async function joinOrganization(): Promise { + try { + if (props.userRegistrationRequired) { + await sendMembershipRequest({ + variables: { + organizationId: props.id, + }, + }); + toast.success(t('MembershipRequestSent')); + } else { + await joinPublicOrganization({ + variables: { + organizationId: props.id, + }, + }); + toast.success(t('orgJoined')); + } + refetch(); + } catch (error: any) { + /* istanbul ignore next */ + if (error.message === 'User is already a member') { + toast.error(t('AlreadyJoined')); + } else { + toast.error(t('errorOccured')); + } + } + } + + async function withdrawMembershipRequest(): Promise { + const membershipRequest = props.membershipRequests.find( + (request) => request.user._id === userId, + ); + + await cancelMembershipRequest({ + variables: { + membershipRequestId: membershipRequest?._id, + }, + }); + } return ( - -
    - -
    - {props.name} - {props.description} + <> +
    +
    +
    + {props.image ? ( + {`${props.name} + ) : ( + + )} +
    +
    + +

    {props.name}

    +
    +
    + {props.description} +
    + {props.address && props.address.city && ( +
    +
    + {props.address.line1}, + {props.address.city}, + + {props.address.countryCode} + +
    +
    + )} +
    + {t('admins')}: {props.admins?.length}     +   {t('members')}: {props.members?.length} +
    +
    + {props.membershipRequestStatus === 'accepted' && ( + + )} + + {props.membershipRequestStatus === 'pending' && ( + + )} + {props.membershipRequestStatus === '' && ( + + )}
    - + ); } diff --git a/src/components/UserPortal/OrganizationNavbar/OrganizationNavbar.test.tsx b/src/components/UserPortal/OrganizationNavbar/OrganizationNavbar.test.tsx index a5c1859ccd..027234b641 100644 --- a/src/components/UserPortal/OrganizationNavbar/OrganizationNavbar.test.tsx +++ b/src/components/UserPortal/OrganizationNavbar/OrganizationNavbar.test.tsx @@ -1,45 +1,155 @@ import React from 'react'; import { MockedProvider } from '@apollo/react-testing'; +import 'jest-localstorage-mock'; import { act, render, screen } from '@testing-library/react'; import { I18nextProvider } from 'react-i18next'; import { Provider } from 'react-redux'; -import { BrowserRouter } from 'react-router-dom'; +import { BrowserRouter, Router } from 'react-router-dom'; import { store } from 'state/store'; import i18nForTest from 'utils/i18nForTest'; import cookies from 'js-cookie'; import { StaticMockLink } from 'utils/StaticMockLink'; -import * as getOrganizationId from 'utils/getOrganizationId'; import OrganizationNavbar from './OrganizationNavbar'; import userEvent from '@testing-library/user-event'; import { USER_ORGANIZATION_CONNECTION } from 'GraphQl/Queries/Queries'; +import { PLUGIN_SUBSCRIPTION } from 'GraphQl/Mutations/mutations'; -const MOCKS = [ +import { createMemoryHistory } from 'history'; +import useLocalStorage from 'utils/useLocalstorage'; + +const { setItem, removeItem } = useLocalStorage(); + +const organizationId = 'org1234'; + +const MOCK_ORGANIZATION_CONNECTION = { + request: { + query: USER_ORGANIZATION_CONNECTION, + variables: { + id: organizationId, + }, + }, + result: { + data: { + organizationsConnection: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + image: '', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + name: 'anyOrganization1', + description: 'desc', + userRegistrationRequired: true, + createdAt: '12345678900', + creator: { __typename: 'User', firstName: 'John', lastName: 'Doe' }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + }, + ], + }, + }, +}; + +const MOCKS = [MOCK_ORGANIZATION_CONNECTION]; + +const PLUGIN_SUBSCRIPTION_1 = [ + MOCK_ORGANIZATION_CONNECTION, { request: { - query: USER_ORGANIZATION_CONNECTION, - variables: { - id: '', + query: PLUGIN_SUBSCRIPTION, + }, + result: { + data: { + onPluginUpdate: { + pluginName: 'TestPlugin1', + _id: '123', + pluginDesc: 'desc', + uninstalledOrgs: [organizationId], + }, }, + _loadingSub: false, + }, + }, +]; + +const PLUGIN_SUBSCRIPTION_2 = [ + MOCK_ORGANIZATION_CONNECTION, + { + request: { + query: PLUGIN_SUBSCRIPTION, }, result: { data: { - organizationsConnection: [ - { - __typename: 'Organization', - _id: '6401ff65ce8e8406b8f07af2', - image: '', - name: 'anyOrganization1', - description: 'desc', - isPublic: true, - creator: { __typename: 'User', firstName: 'John', lastName: 'Doe' }, - }, - ], + onPluginUpdate: { + pluginName: 'TestPlugin1', + _id: '123', + pluginDesc: 'desc', + uninstalledOrgs: [], + }, + }, + _loadingSub: false, + }, + }, +]; + +const PLUGIN_SUBSCRIPTION_3 = [ + MOCK_ORGANIZATION_CONNECTION, + { + request: { + query: PLUGIN_SUBSCRIPTION, + }, + result: { + data: { + onPluginUpdate: { + pluginName: 'TestPlugin100', + _id: '123', + pluginDesc: 'desc', + uninstalledOrgs: [organizationId], + }, }, + _loadingSub: false, }, }, ]; +const testPlugins = [ + { + pluginName: 'TestPlugin1', + alias: 'testPlugin1', + link: '/testPlugin1', + translated: 'Test Plugin 1', + view: true, + }, +]; + async function wait(ms = 100): Promise { await act(() => { return new Promise((resolve) => { @@ -49,14 +159,20 @@ async function wait(ms = 100): Promise { } const link = new StaticMockLink(MOCKS, true); +const link2 = new StaticMockLink(PLUGIN_SUBSCRIPTION_1, true); +const link3 = new StaticMockLink(PLUGIN_SUBSCRIPTION_2, true); +const link4 = new StaticMockLink(PLUGIN_SUBSCRIPTION_3, true); const navbarProps = { currentPage: 'home', }; -describe('Testing OrganizationNavbar Component [User Portal]', () => { - jest.mock('utils/getOrganizationId'); +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: organizationId }), +})); +describe('Testing OrganizationNavbar Component [User Portal]', () => { Object.defineProperty(window, 'matchMedia', { writable: true, value: jest.fn().mockImplementation((query) => ({ @@ -71,12 +187,6 @@ describe('Testing OrganizationNavbar Component [User Portal]', () => { })), }); - const getOrganizationIdSpy = jest - .spyOn(getOrganizationId, 'default') - .mockImplementation(() => { - return ''; - }); - afterEach(async () => { await act(async () => { await i18nForTest.changeLanguage('en'); @@ -93,12 +203,11 @@ describe('Testing OrganizationNavbar Component [User Portal]', () => { - + , ); await wait(); - expect(getOrganizationIdSpy).toHaveBeenCalled(); expect(screen.queryByText('anyOrganization1')).toBeInTheDocument(); // Check if navigation links are rendered expect(screen.getByText('Home')).toBeInTheDocument(); @@ -108,6 +217,29 @@ describe('Testing OrganizationNavbar Component [User Portal]', () => { // expect(screen.getByText('Chat')).toBeInTheDocument(); }); + test('should navigate correctly on clicking a plugin', async () => { + const history = createMemoryHistory(); + render( + + + + + + + + + , + ); + + const peoplePlugin = screen.getByText('People'); + expect(peoplePlugin).toBeInTheDocument(); + + userEvent.click(peoplePlugin); + + await wait(); + expect(history.location.pathname).toBe(`/user/people/${organizationId}`); + }); + test('The language is switched to English', async () => { render( @@ -118,7 +250,7 @@ describe('Testing OrganizationNavbar Component [User Portal]', () => { - + , ); await wait(); @@ -148,7 +280,7 @@ describe('Testing OrganizationNavbar Component [User Portal]', () => { - + , ); await wait(); @@ -172,7 +304,7 @@ describe('Testing OrganizationNavbar Component [User Portal]', () => { - + , ); await wait(); @@ -196,7 +328,7 @@ describe('Testing OrganizationNavbar Component [User Portal]', () => { - + , ); await wait(); @@ -220,7 +352,7 @@ describe('Testing OrganizationNavbar Component [User Portal]', () => { - + , ); await wait(); @@ -233,4 +365,88 @@ describe('Testing OrganizationNavbar Component [User Portal]', () => { expect(cookies.get('i18next')).toBe('zh'); }); + + test('Component should be rendered properly if plugins are present in localStorage', async () => { + setItem('talawaPlugins', JSON.stringify(testPlugins)); + + render( + + + + + + + + + , + ); + + await wait(); + + testPlugins.forEach((plugin) => { + expect(screen.queryByText(plugin.translated)).toBeInTheDocument(); + }); + + removeItem('talawaPlugins'); + }); + + test('should remove plugin if uninstalledOrgs contains organizationId', async () => { + setItem('talawaPlugins', JSON.stringify(testPlugins)); + + render( + + + + + + + + + , + ); + + await wait(); + + testPlugins.forEach((plugin) => { + expect(screen.queryByText(plugin.translated)).not.toBeInTheDocument(); + }); + }); + + test('should render plugin if uninstalledOrgs does not contain organizationId', async () => { + setItem('talawaPlugins', JSON.stringify(testPlugins)); + + render( + + + + + + + + + , + ); + + await wait(); + + testPlugins.forEach((plugin) => { + expect(screen.queryByText(plugin.translated)).toBeInTheDocument(); + }); + }); + + test('should do nothing if pluginName is not found in the rendered plugins', async () => { + render( + + + + + + + + + , + ); + + await wait(); + }); }); diff --git a/src/components/UserPortal/OrganizationNavbar/OrganizationNavbar.tsx b/src/components/UserPortal/OrganizationNavbar/OrganizationNavbar.tsx index 4bcaca4a8e..7ecde0f275 100644 --- a/src/components/UserPortal/OrganizationNavbar/OrganizationNavbar.tsx +++ b/src/components/UserPortal/OrganizationNavbar/OrganizationNavbar.tsx @@ -10,10 +10,10 @@ import LanguageIcon from '@mui/icons-material/Language'; import { useTranslation } from 'react-i18next'; import { useQuery, useSubscription } from '@apollo/client'; import { USER_ORGANIZATION_CONNECTION } from 'GraphQl/Queries/Queries'; -import getOrganizationId from 'utils/getOrganizationId'; import type { DropDirection } from 'react-bootstrap/esm/DropdownContext'; -import { Link, useHistory } from 'react-router-dom'; +import { Link, useNavigate, useParams } from 'react-router-dom'; import { PLUGIN_SUBSCRIPTION } from 'GraphQl/Mutations/mutations'; +import useLocalStorage from 'utils/useLocalstorage'; interface InterfaceNavbarProps { currentPage: string | null; } @@ -31,13 +31,13 @@ function organizationNavbar(props: InterfaceNavbarProps): JSX.Element { keyPrefix: 'userNavbar', }); - const history = useHistory(); + const navigate = useNavigate(); const [organizationDetails, setOrganizationDetails]: any = React.useState({}); // const dropDirection: DropDirection = screen.width > 767 ? 'start' : 'down'; const dropDirection: DropDirection = 'start'; - const organizationId = getOrganizationId(window.location.href); + const { orgId: organizationId } = useParams(); const { data } = useQuery(USER_ORGANIZATION_CONNECTION, { variables: { id: organizationId }, @@ -45,42 +45,44 @@ function organizationNavbar(props: InterfaceNavbarProps): JSX.Element { const [currentLanguageCode, setCurrentLanguageCode] = React.useState( /* istanbul ignore next */ - cookies.get('i18next') || 'en' + cookies.get('i18next') || 'en', ); + const { getItem, setItem } = useLocalStorage(); + /* istanbul ignore next */ const handleLogout = (): void => { localStorage.clear(); - window.location.replace('/user'); + window.location.replace('/'); }; - const userName = localStorage.getItem('name'); + const userName = getItem('name'); React.useEffect(() => { if (data) { setOrganizationDetails(data.organizationsConnection[0]); } }, [data]); - const homeLink = `/user/organization/id=${organizationId}`; + const homeLink = `/user/organization/${organizationId}`; let plugins: Plugin[] = [ { pluginName: 'People', alias: 'people', - link: `/user/people/id=${organizationId}`, + link: `/user/people/${organizationId}`, translated: t('people'), view: true, }, { pluginName: 'Events', alias: 'events', - link: `/user/events/id=${organizationId}`, + link: `/user/events/${organizationId}`, translated: t('events'), view: true, }, { pluginName: 'Donation', alias: 'donate', - link: `/user/donate/id=${organizationId}`, + link: `/user/donate/${organizationId}`, translated: t('donate'), view: true, }, @@ -92,22 +94,17 @@ function organizationNavbar(props: InterfaceNavbarProps): JSX.Element { // view: true, // }, ]; - if (localStorage.getItem('talawaPlugins')) { - const talawaPlugins: string = localStorage.getItem('talawaPlugins') || '{}'; + if (getItem('talawaPlugins')) { + const talawaPlugins: string = getItem('talawaPlugins') || '{}'; plugins = JSON.parse(talawaPlugins); } - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { data: updatedPluginData, loading: _loadingSub } = useSubscription( - PLUGIN_SUBSCRIPTION + + const { data: updatedPluginData } = useSubscription( + PLUGIN_SUBSCRIPTION, // { variables: { } } ); function getPluginIndex(pluginName: string, pluginsArray: Plugin[]): number { - for (let i = 0; i < pluginsArray.length; i++) { - if (pluginsArray[i].pluginName === pluginName) { - return i; // Return the index of the matching object - } - } - return -1; // Return -1 if not found + return pluginsArray.findIndex((plugin) => plugin.pluginName === pluginName); } if (updatedPluginData != undefined) { @@ -117,7 +114,7 @@ function organizationNavbar(props: InterfaceNavbarProps): JSX.Element { if (uninstalledOrgs.includes(organizationId)) { if (pluginIndexToRemove != -1) { plugins[pluginIndexToRemove].view = false; - localStorage.setItem('talawaPlugins', JSON.stringify(plugins)); + setItem('talawaPlugins', JSON.stringify(plugins)); console.log(`Plugin ${pluginName} has been removed.`); } else { console.log(`Plugin ${pluginName} is not present.`); @@ -125,7 +122,7 @@ function organizationNavbar(props: InterfaceNavbarProps): JSX.Element { } else { if (pluginIndexToRemove != -1) { plugins[pluginIndexToRemove].view = true; - localStorage.setItem('talawaPlugins', JSON.stringify(plugins)); + setItem('talawaPlugins', JSON.stringify(plugins)); } } } @@ -156,7 +153,7 @@ function organizationNavbar(props: InterfaceNavbarProps): JSX.Element { active={props.currentPage === 'home'} onClick={ /* istanbul ignore next */ - (): void => history.push(homeLink) + (): void => navigate(homeLink) } > {t('home')} @@ -166,12 +163,12 @@ function organizationNavbar(props: InterfaceNavbarProps): JSX.Element { plugin.view && ( history.push(plugin.link)} + onClick={(): void => navigate(plugin.link)} key={idx} > {plugin.translated} - ) + ), )} @@ -228,11 +225,6 @@ function organizationNavbar(props: InterfaceNavbarProps): JSX.Element { {t('settings')} - - - {t('myTasks')} - - { }); }); } +let mockId = ''; +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: mockId }), +})); describe('Testing OrganizationSidebar Component [User Portal]', () => { - jest.mock('utils/getOrganizationId'); - test('Component should be rendered properly when members and events list is empty', async () => { - const getOrganizationIdSpy = jest - .spyOn(getOrganizationId, 'default') - .mockImplementation(() => { - return ''; - }); - render( @@ -111,23 +109,17 @@ describe('Testing OrganizationSidebar Component [User Portal]', () => { - + , ); await wait(); - expect(getOrganizationIdSpy).toHaveBeenCalled(); expect(screen.queryByText('No Members to show')).toBeInTheDocument(); expect(screen.queryByText('No Events to show')).toBeInTheDocument(); }); test('Component should be rendered properly when events list is not empty', async () => { - const getOrganizationIdSpy = jest - .spyOn(getOrganizationId, 'default') - .mockImplementation(() => { - return 'events'; - }); - + mockId = 'events'; render( @@ -137,23 +129,17 @@ describe('Testing OrganizationSidebar Component [User Portal]', () => { - + , ); await wait(); - expect(getOrganizationIdSpy).toHaveBeenCalled(); expect(screen.queryByText('No Members to show')).toBeInTheDocument(); expect(screen.queryByText('No Events to show')).not.toBeInTheDocument(); expect(screen.queryByText('Event')).toBeInTheDocument(); }); test('Component should be rendered properly when members list is not empty', async () => { - const getOrganizationIdSpy = jest - .spyOn(getOrganizationId, 'default') - .mockImplementation(() => { - return 'members'; - }); - + mockId = 'members'; render( @@ -163,11 +149,10 @@ describe('Testing OrganizationSidebar Component [User Portal]', () => { - + , ); await wait(); - expect(getOrganizationIdSpy).toHaveBeenCalled(); expect(screen.queryByText('No Members to show')).not.toBeInTheDocument(); expect(screen.queryByText('No Events to show')).toBeInTheDocument(); }); diff --git a/src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.tsx b/src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.tsx index 570ea9de85..17365dcddf 100644 --- a/src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.tsx +++ b/src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.tsx @@ -3,8 +3,7 @@ import { ListGroup } from 'react-bootstrap'; import AboutImg from 'assets/images/defaultImg.png'; import styles from './OrganizationSidebar.module.css'; import ChevronRightIcon from '@mui/icons-material/ChevronRight'; -import { Link } from 'react-router-dom'; -import getOrganizationId from 'utils/getOrganizationId'; +import { Link, useParams } from 'react-router-dom'; import { useQuery } from '@apollo/client'; import { ORGANIZATIONS_MEMBER_CONNECTION_LIST, @@ -20,7 +19,7 @@ export default function organizationSidebar(): JSX.Element { keyPrefix: 'organizationSidebar', }); - const organizationId = getOrganizationId(window.location.href); + const { orgId: organizationId } = useParams(); const [members, setMembers]: any = React.useState([]); const [events, setEvents]: any = React.useState([]); const eventsLink = `/user/events/id=${organizationId}`; @@ -34,7 +33,7 @@ export default function organizationSidebar(): JSX.Element { first: 3, skip: 0, }, - } + }, ); const { data: eventsData, loading: eventsLoading } = useQuery( @@ -45,7 +44,7 @@ export default function organizationSidebar(): JSX.Element { first: 3, skip: 0, }, - } + }, ); /* istanbul ignore next */ diff --git a/src/components/UserPortal/PeopleCard/PeopleCard.module.css b/src/components/UserPortal/PeopleCard/PeopleCard.module.css index 76fcaf3b0c..fe9fc3bcbd 100644 --- a/src/components/UserPortal/PeopleCard/PeopleCard.module.css +++ b/src/components/UserPortal/PeopleCard/PeopleCard.module.css @@ -19,4 +19,15 @@ .personImage { border-radius: 50%; margin-right: 20px; + max-width: 70px; +} + +.borderBox { + border: 1px solid #dddddd; + box-shadow: 5px 5px 4px 0px #31bb6b1f; + border-radius: 4px; +} + +.greenText { + color: #31bb6b; } diff --git a/src/components/UserPortal/PeopleCard/PeopleCard.test.tsx b/src/components/UserPortal/PeopleCard/PeopleCard.test.tsx index d0bad51b11..5cadfa923b 100644 --- a/src/components/UserPortal/PeopleCard/PeopleCard.test.tsx +++ b/src/components/UserPortal/PeopleCard/PeopleCard.test.tsx @@ -25,6 +25,8 @@ let props = { name: 'First Last', image: '', email: 'first@last.com', + role: 'Admin', + sno: '1', }; describe('Testing PeopleCard Component [User Portal]', () => { @@ -38,7 +40,7 @@ describe('Testing PeopleCard Component [User Portal]', () => { - + , ); await wait(); @@ -59,7 +61,7 @@ describe('Testing PeopleCard Component [User Portal]', () => { - + , ); await wait(); diff --git a/src/components/UserPortal/PeopleCard/PeopleCard.tsx b/src/components/UserPortal/PeopleCard/PeopleCard.tsx index 578cf31194..ec06122359 100644 --- a/src/components/UserPortal/PeopleCard/PeopleCard.tsx +++ b/src/components/UserPortal/PeopleCard/PeopleCard.tsx @@ -7,22 +7,38 @@ interface InterfaceOrganizationCardProps { name: string; image: string; email: string; + role: string; + sno: string; } function peopleCard(props: InterfaceOrganizationCardProps): JSX.Element { const imageUrl = props.image ? props.image : aboutImg; return ( -
    - -
    - {props.name} - {props.email} +
    + + + {props.sno} + + + + + + + {props.name} + + + {props.email} + +
    +
    + {props.role} +
    ); diff --git a/src/components/UserPortal/PostCard/PostCard.test.tsx b/src/components/UserPortal/PostCard/PostCard.test.tsx index acd6176b02..aa170f63a8 100644 --- a/src/components/UserPortal/PostCard/PostCard.test.tsx +++ b/src/components/UserPortal/PostCard/PostCard.test.tsx @@ -14,7 +14,12 @@ import { CREATE_COMMENT_POST, LIKE_POST, UNLIKE_POST, + LIKE_COMMENT, + UNLIKE_COMMENT, } from 'GraphQl/Mutations/mutations'; +import useLocalStorage from 'utils/useLocalstorage'; + +const { setItem, getItem } = useLocalStorage(); const MOCKS = [ { @@ -74,6 +79,36 @@ const MOCKS = [ }, }, }, + { + request: { + query: LIKE_COMMENT, + variables: { + commentId: '1', + }, + }, + result: { + data: { + likeComment: { + _id: '1', + }, + }, + }, + }, + { + request: { + query: UNLIKE_COMMENT, + variables: { + commentId: '1', + }, + }, + result: { + data: { + unlikeComment: { + _id: '1', + }, + }, + }, + }, ]; async function wait(ms = 100): Promise { @@ -104,7 +139,7 @@ describe('Testing PostCard Component [User Portal]', () => { commentCount: 1, comments: [ { - _id: '64eb13beca85de60ebe0ed0e', + id: '64eb13beca85de60ebe0ed0e', creator: { _id: '63d6064458fce20ee25c3bf7', firstName: 'Noble', @@ -136,15 +171,15 @@ describe('Testing PostCard Component [User Portal]', () => { - + , ); await wait(); }); test('Component should be rendered properly if user has liked the post', async () => { - const beforeUserId = localStorage.getItem('userId'); - localStorage.setItem('userId', '2'); + const beforeUserId = getItem('userId'); + setItem('userId', '2'); const cardProps = { id: '', @@ -179,19 +214,19 @@ describe('Testing PostCard Component [User Portal]', () => { - + , ); await wait(); if (beforeUserId) { - localStorage.setItem('userId', beforeUserId); + setItem('userId', beforeUserId); } }); test('Component should be rendered properly if user unlikes a post', async () => { - const beforeUserId = localStorage.getItem('userId'); - localStorage.setItem('userId', '2'); + const beforeUserId = getItem('userId'); + setItem('userId', '2'); const cardProps = { id: '', @@ -226,7 +261,7 @@ describe('Testing PostCard Component [User Portal]', () => { - + , ); await wait(); @@ -234,13 +269,13 @@ describe('Testing PostCard Component [User Portal]', () => { userEvent.click(screen.getByTestId('likePostBtn')); if (beforeUserId) { - localStorage.setItem('userId', beforeUserId); + setItem('userId', beforeUserId); } }); test('Component should be rendered properly if user likes a post', async () => { - const beforeUserId = localStorage.getItem('userId'); - localStorage.setItem('userId', '2'); + const beforeUserId = getItem('userId'); + setItem('userId', '2'); const cardProps = { id: '', @@ -275,7 +310,7 @@ describe('Testing PostCard Component [User Portal]', () => { - + , ); await wait(); @@ -283,7 +318,7 @@ describe('Testing PostCard Component [User Portal]', () => { userEvent.click(screen.getByTestId('likePostBtn')); if (beforeUserId) { - localStorage.setItem('userId', beforeUserId); + setItem('userId', beforeUserId); } }); @@ -321,7 +356,7 @@ describe('Testing PostCard Component [User Portal]', () => { - + , ); await wait(); @@ -361,7 +396,7 @@ describe('Testing PostCard Component [User Portal]', () => { - + , ); const randomComment = 'testComment'; @@ -374,6 +409,145 @@ describe('Testing PostCard Component [User Portal]', () => { await wait(); }); + test(`Comment should be liked when like button is clicked`, async () => { + const cardProps = { + id: '1', + creator: { + firstName: 'test', + lastName: 'user', + email: 'test@user.com', + id: '1', + }, + image: 'testImage', + video: '', + text: 'This is post test text', + title: 'This is post test title', + likeCount: 1, + commentCount: 1, + comments: [ + { + id: '1', + creator: { + _id: '1', + id: '1', + firstName: 'test', + lastName: 'user', + email: 'test@user.com', + }, + likeCount: 1, + likedBy: [ + { + id: '1', + }, + ], + text: 'testComment', + }, + ], + likedBy: [ + { + firstName: 'test', + lastName: 'user', + id: '1', + }, + ], + }; + const beforeUserId = getItem('userId'); + setItem('userId', '2'); + + render( + + + + + + + + + , + ); + + const showCommentsButton = screen.getByTestId('showCommentsBtn'); + + userEvent.click(showCommentsButton); + + userEvent.click(screen.getByTestId('likeCommentBtn')); + + await wait(); + + if (beforeUserId) { + setItem('userId', beforeUserId); + } + }); + + test(`Comment should be unliked when like button is clicked, if already liked`, async () => { + const cardProps = { + id: '1', + creator: { + firstName: 'test', + lastName: 'user', + email: 'test@user.com', + id: '1', + }, + image: 'testImage', + video: '', + text: 'This is post test text', + title: 'This is post test title', + likeCount: 1, + commentCount: 1, + comments: [ + { + id: '1', + creator: { + _id: '1', + id: '1', + firstName: 'test', + lastName: 'user', + email: 'test@user.com', + }, + likeCount: 1, + likedBy: [ + { + id: '1', + }, + ], + text: 'testComment', + }, + ], + likedBy: [ + { + firstName: 'test', + lastName: 'user', + id: '1', + }, + ], + }; + const beforeUserId = getItem('userId'); + setItem('userId', '1'); + + render( + + + + + + + + + , + ); + + const showCommentsButton = screen.getByTestId('showCommentsBtn'); + + userEvent.click(showCommentsButton); + + userEvent.click(screen.getByTestId('likeCommentBtn')); + + await wait(); + + if (beforeUserId) { + setItem('userId', beforeUserId); + } + }); test('Comment modal pops when show comments button is clicked.', async () => { const cardProps = { id: '', @@ -408,7 +582,7 @@ describe('Testing PostCard Component [User Portal]', () => { - + , ); await wait(); diff --git a/src/components/UserPortal/PostCard/PostCard.tsx b/src/components/UserPortal/PostCard/PostCard.tsx index 0374858f23..2574505a81 100644 --- a/src/components/UserPortal/PostCard/PostCard.tsx +++ b/src/components/UserPortal/PostCard/PostCard.tsx @@ -17,40 +17,8 @@ import { useTranslation } from 'react-i18next'; import SendIcon from '@mui/icons-material/Send'; import { errorHandler } from 'utils/errorHandler'; import CommentCard from '../CommentCard/CommentCard'; - -interface InterfacePostCardProps { - id: string; - creator: { - firstName: string; - lastName: string; - email: string; - id: string; - }; - image: string; - video: string; - text: string; - title: string; - likeCount: number; - commentCount: number; - comments: { - creator: { - _id: string; - firstName: string; - lastName: string; - email: string; - }; - likeCount: number; - likedBy: { - id: string; - }[]; - text: string; - }[]; - likedBy: { - firstName: string; - lastName: string; - id: string; - }[]; -} +import useLocalStorage from 'utils/useLocalstorage'; +import type { InterfacePostCard } from 'utils/interfaces'; interface InterfaceCommentCardProps { id: string; @@ -65,14 +33,18 @@ interface InterfaceCommentCardProps { id: string; }[]; text: string; + handleLikeComment: (commentId: string) => void; + handleDislikeComment: (commentId: string) => void; } -export default function postCard(props: InterfacePostCardProps): JSX.Element { +export default function postCard(props: InterfacePostCard): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'postCard', }); - const userId = localStorage.getItem('userId'); + const { getItem } = useLocalStorage(); + + const userId = getItem('userId'); const likedByUser = props.likedBy.some((likedBy) => likedBy.id === userId); const [comments, setComments] = React.useState(props.comments); const [numComments, setNumComments] = React.useState(props.commentCount); @@ -128,12 +100,47 @@ export default function postCard(props: InterfacePostCardProps): JSX.Element { }; const handleCommentInput = ( - event: React.ChangeEvent + event: React.ChangeEvent, ): void => { const comment = event.target.value; setCommentInput(comment); }; + const handleDislikeComment = (commentId: string): void => { + const updatedComments = comments.map((comment) => { + let updatedComment = { ...comment }; + if ( + comment.id === commentId && + comment.likedBy.some((user) => user.id === userId) + ) { + updatedComment = { + ...comment, + likedBy: comment.likedBy.filter((user) => user.id !== userId), + likeCount: comment.likeCount - 1, + }; + } + return updatedComment; + }); + setComments(updatedComments); + }; + const handleLikeComment = (commentId: string): void => { + const updatedComments = comments.map((comment) => { + let updatedComment = { ...comment }; + if ( + comment.id === commentId && + !comment.likedBy.some((user) => user.id === userId) + ) { + updatedComment = { + ...comment, + likedBy: [...comment.likedBy, { id: userId }], + likeCount: comment.likeCount + 1, + }; + } + return updatedComment; + }); + setComments(updatedComments); + }; + const createComment = async (): Promise => { try { const { data: createEventData } = await create({ @@ -159,6 +166,8 @@ export default function postCard(props: InterfacePostCardProps): JSX.Element { likeCount: createEventData.createComment.likeCount, likedBy: createEventData.createComment.likedBy, text: createEventData.createComment.text, + handleLikeComment: handleLikeComment, + handleDislikeComment: handleDislikeComment, }; setComments([...comments, newComment]); @@ -170,7 +179,7 @@ export default function postCard(props: InterfacePostCardProps): JSX.Element { }; return ( - <> +
    @@ -255,6 +264,8 @@ export default function postCard(props: InterfacePostCardProps): JSX.Element { likeCount: comment.likeCount, likedBy: comment.likedBy, text: comment.text, + handleLikeComment: handleLikeComment, + handleDislikeComment: handleDislikeComment, }; return ; @@ -286,6 +297,6 @@ export default function postCard(props: InterfacePostCardProps): JSX.Element { - +
    ); } diff --git a/src/components/UserPortal/PromotedPost/PromotedPost.module.css b/src/components/UserPortal/PromotedPost/PromotedPost.module.css index cdc13e621b..676d30a83a 100644 --- a/src/components/UserPortal/PromotedPost/PromotedPost.module.css +++ b/src/components/UserPortal/PromotedPost/PromotedPost.module.css @@ -54,3 +54,8 @@ color: white; cursor: pointer; } + +.admedia { + object-fit: cover; + height: 30rem; +} diff --git a/src/components/UserPortal/PromotedPost/PromotedPost.test.tsx b/src/components/UserPortal/PromotedPost/PromotedPost.test.tsx index 6b68509a51..b5d753551c 100644 --- a/src/components/UserPortal/PromotedPost/PromotedPost.test.tsx +++ b/src/components/UserPortal/PromotedPost/PromotedPost.test.tsx @@ -37,7 +37,7 @@ describe('Testing PromotedPost Test', () => { - + , ); await wait(); @@ -58,7 +58,7 @@ describe('Testing PromotedPost Test', () => { - + , ); await wait(); @@ -75,7 +75,7 @@ test('Component should display the icon correctly', async () => { - + , ); await waitFor(() => { @@ -94,7 +94,7 @@ test('Component should display the text correctly', async () => { - + , ); await waitFor(() => { @@ -117,7 +117,7 @@ test('Component should display the image correctly', async () => { - + , ); await waitFor(() => { diff --git a/src/components/UserPortal/PromotedPost/PromotedPost.tsx b/src/components/UserPortal/PromotedPost/PromotedPost.tsx index 81f3aa0e7e..72ee107217 100644 --- a/src/components/UserPortal/PromotedPost/PromotedPost.tsx +++ b/src/components/UserPortal/PromotedPost/PromotedPost.tsx @@ -8,7 +8,7 @@ interface InterfacePostCardProps { title: string; } export default function promotedPost( - props: InterfacePostCardProps + props: InterfacePostCardProps, ): JSX.Element { return ( <> diff --git a/src/components/UserPortal/Register/Register.test.tsx b/src/components/UserPortal/Register/Register.test.tsx index 8020ac03fa..cdcfb9ebc0 100644 --- a/src/components/UserPortal/Register/Register.test.tsx +++ b/src/components/UserPortal/Register/Register.test.tsx @@ -81,7 +81,7 @@ describe('Testing Register Component [User Portal]', () => { - + , ); await wait(); @@ -97,7 +97,7 @@ describe('Testing Register Component [User Portal]', () => { - + , ); await wait(); @@ -117,7 +117,7 @@ describe('Testing Register Component [User Portal]', () => { - + , ); await wait(); @@ -137,7 +137,7 @@ describe('Testing Register Component [User Portal]', () => { - + , ); await wait(); @@ -158,7 +158,7 @@ describe('Testing Register Component [User Portal]', () => { - + , ); await wait(); @@ -182,7 +182,7 @@ describe('Testing Register Component [User Portal]', () => { - + , ); await wait(); @@ -208,7 +208,7 @@ describe('Testing Register Component [User Portal]', () => { - + , ); await wait(); @@ -224,7 +224,7 @@ describe('Testing Register Component [User Portal]', () => { userEvent.click(screen.getByTestId('registerBtn')); expect(toast.error).toBeCalledWith( - "Password doesn't match. Confirm Password and try again." + "Password doesn't match. Confirm Password and try again.", ); }); @@ -238,7 +238,7 @@ describe('Testing Register Component [User Portal]', () => { - + , ); await wait(); @@ -247,7 +247,7 @@ describe('Testing Register Component [User Portal]', () => { userEvent.type( screen.getByTestId('confirmPasswordInput'), - formData.confirmPassword + formData.confirmPassword, ); userEvent.type(screen.getByTestId('emailInput'), formData.email); @@ -261,7 +261,7 @@ describe('Testing Register Component [User Portal]', () => { await wait(); expect(toast.success).toBeCalledWith( - 'Successfully registered. Please wait for admin to approve your request.' + 'Successfully registered. Please wait for admin to approve your request.', ); }); }); diff --git a/src/components/UserPortal/Register/Register.tsx b/src/components/UserPortal/Register/Register.tsx index 1867eceecc..f67674b4f8 100644 --- a/src/components/UserPortal/Register/Register.tsx +++ b/src/components/UserPortal/Register/Register.tsx @@ -107,7 +107,7 @@ export default function register(props: InterfaceRegisterProps): JSX.Element { /* istanbul ignore next */ const handleConfirmPasswordChange = ( - e: ChangeEvent + e: ChangeEvent, ): void => { const confirmPassword = e.target.value; diff --git a/src/components/UserPortal/SecuredRouteForUser/SecuredRouteForUser.test.tsx b/src/components/UserPortal/SecuredRouteForUser/SecuredRouteForUser.test.tsx index 72ee402369..93b71b14f1 100644 --- a/src/components/UserPortal/SecuredRouteForUser/SecuredRouteForUser.test.tsx +++ b/src/components/UserPortal/SecuredRouteForUser/SecuredRouteForUser.test.tsx @@ -1,29 +1,31 @@ import React from 'react'; -import { MemoryRouter, Route } from 'react-router-dom'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; import { render, screen, waitFor } from '@testing-library/react'; import SecuredRouteForUser from './SecuredRouteForUser'; +import useLocalStorage from 'utils/useLocalstorage'; + +const { setItem } = useLocalStorage(); describe('SecuredRouteForUser', () => { test('renders the route when the user is logged in', () => { - // Set the 'IsLoggedIn' value to 'TRUE' in localStorage to simulate a logged-in user - localStorage.setItem('IsLoggedIn', 'TRUE'); + // Set the 'IsLoggedIn' value to 'TRUE' in localStorage to simulate a logged-in user and do not set 'AdminFor' so that it remains undefined. + setItem('IsLoggedIn', 'TRUE'); render( - ( - + }> + ( + element={
    Organizations Component
    - )} + } /> - )} - /> -
    + + + , ); expect(screen.getByTestId('organizations-content')).toBeInTheDocument(); @@ -31,24 +33,64 @@ describe('SecuredRouteForUser', () => { test('redirects to /user when the user is not logged in', async () => { // Set the user as not logged in in local storage - localStorage.setItem('IsLoggedIn', 'FALSE'); + setItem('IsLoggedIn', 'FALSE'); render( - - ( - -
    Secured Content
    -
    - )} - /> -
    + + + User Login Page
    } /> + }> + + Organizations Component +
    + } + /> + + + , ); await waitFor(() => { - expect(window.location.pathname).toBe('/'); + expect(screen.getByText('User Login Page')).toBeInTheDocument(); }); }); + + test('renders the route when the user is logged in and user is ADMIN', () => { + // Set the 'IsLoggedIn' value to 'TRUE' in localStorage to simulate a logged-in user and set 'AdminFor' to simulate ADMIN of some Organization. + setItem('IsLoggedIn', 'TRUE'); + setItem('AdminFor', [ + { + _id: '6537904485008f171cf29924', + __typename: 'Organization', + }, + ]); + + render( + + + Oops! The Page you requested was not found!
    } + /> + }> + + Organizations Component +
    + } + /> + + + , + ); + + expect( + screen.getByText(/Oops! The Page you requested was not found!/i), + ).toBeTruthy(); + }); }); diff --git a/src/components/UserPortal/SecuredRouteForUser/SecuredRouteForUser.tsx b/src/components/UserPortal/SecuredRouteForUser/SecuredRouteForUser.tsx index 967e6c00a0..f21047579d 100644 --- a/src/components/UserPortal/SecuredRouteForUser/SecuredRouteForUser.tsx +++ b/src/components/UserPortal/SecuredRouteForUser/SecuredRouteForUser.tsx @@ -1,14 +1,16 @@ import React from 'react'; -import { Redirect, Route } from 'react-router-dom'; +import { Navigate, Outlet } from 'react-router-dom'; +import PageNotFound from 'screens/PageNotFound/PageNotFound'; +import useLocalStorage from 'utils/useLocalstorage'; -const SecuredRouteForUser = (props: any): JSX.Element => { - const isLoggedIn = localStorage.getItem('IsLoggedIn'); +const SecuredRouteForUser = (): JSX.Element => { + const { getItem } = useLocalStorage(); + const isLoggedIn = getItem('IsLoggedIn'); + const adminFor = getItem('AdminFor'); return isLoggedIn === 'TRUE' ? ( - <> - - + <>{adminFor == undefined ? : } ) : ( - + ); }; diff --git a/src/components/UserPortal/StartPostModal/StartPostModal.module.css b/src/components/UserPortal/StartPostModal/StartPostModal.module.css new file mode 100644 index 0000000000..8b709f584d --- /dev/null +++ b/src/components/UserPortal/StartPostModal/StartPostModal.module.css @@ -0,0 +1,50 @@ +.userImage { + display: flex; + width: 50px; + height: 50px; + align-items: center; + justify-content: center; + overflow: hidden; + border-radius: 50%; + position: relative; + border: 2px solid #31bb6b; +} + +.userImage img { + position: absolute; + top: 0; + left: 0; + width: 100%; + scale: 1.5; +} + +.previewImage { + overflow: hidden; + display: flex; + justify-content: center; + align-items: center; + margin-bottom: 1rem; +} + +.previewImage img { + border-radius: 8px; +} + +.icons { + width: 25px; +} + +.icons svg { + stroke: #000; +} + +.icons.dark { + cursor: pointer; + border: none; + outline: none; + background-color: transparent; +} + +.icons.dark svg { + stroke: #000; +} diff --git a/src/components/UserPortal/StartPostModal/StartPostModal.test.tsx b/src/components/UserPortal/StartPostModal/StartPostModal.test.tsx new file mode 100644 index 0000000000..65faca9fa1 --- /dev/null +++ b/src/components/UserPortal/StartPostModal/StartPostModal.test.tsx @@ -0,0 +1,225 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import type { RenderResult } from '@testing-library/react'; +import { act, fireEvent, render, screen } from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import userEvent from '@testing-library/user-event'; +import { CREATE_POST_MUTATION } from 'GraphQl/Mutations/mutations'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { toast } from 'react-toastify'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18nForTest from 'utils/i18nForTest'; +import StartPostModal from './StartPostModal'; + +jest.mock('react-toastify', () => ({ + toast: { + error: jest.fn(), + info: jest.fn(), + success: jest.fn(), + }, +})); + +const MOCKS = [ + { + request: { + query: CREATE_POST_MUTATION, + variables: { + title: 'Dummy Post', + text: 'This is dummy text', + organizationId: '123', + }, + result: { + data: { + createPost: { + _id: '453', + }, + }, + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); + +afterEach(() => { + localStorage.clear(); +}); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +const renderStartPostModal = ( + visibility: boolean, + image: string | null, +): RenderResult => { + const cardProps = { + show: visibility, + onHide: jest.fn(), + fetchPosts: jest.fn(), + userData: { + user: { + __typename: 'User', + _id: '123', + image: image, + firstName: 'Glen', + lastName: 'dsza', + email: 'glen@dsza.com', + appLanguageCode: 'en', + pluginCreationAllowed: true, + createdAt: '2023-02-18T09:22:27.969Z', + adminFor: [], + createdOrganizations: [], + joinedOrganizations: [], + createdEvents: [], + registeredEvents: [], + eventAdmin: [], + membershipRequests: [], + organizationsBlockedBy: [], + }, + appUserProfile: { + __typename: 'AppUserProfile', + _id: '123', + isSuperAdmin: true, + adminFor: [], + createdOrganizations: [], + createdEvents: [], + eventAdmin: [], + }, + }, + organizationId: '123', + }; + + return render( + + + + + + + + + , + ); +}; + +describe('Testing StartPostModal Component: User Portal', () => { + afterAll(() => { + jest.clearAllMocks(); + }); + + test('Check if StartPostModal renders properly', async () => { + renderStartPostModal(true, null); + + const modal = await screen.findByTestId('startPostModal'); + expect(modal).toBeInTheDocument(); + }); + + test('triggers file input when the upload icon is clicked', async () => { + const clickSpy = jest.spyOn(HTMLInputElement.prototype, 'click'); + renderStartPostModal(true, null); + + await wait(); + const postImageInput = screen.getByTestId('postImageInput'); + expect(postImageInput).toHaveAttribute('type', 'file'); + expect(postImageInput).toHaveStyle({ display: 'inline-block' }); + + const iconButton = screen.getByTestId('addMediaBtn'); + fireEvent.click(iconButton); + + expect(clickSpy).toHaveBeenCalled(); + clickSpy.mockRestore(); + }); + + test('On invalid post submission with empty body Error toast should be shown', async () => { + const toastSpy = jest.spyOn(toast, 'error'); + renderStartPostModal(true, null); + await wait(); + + userEvent.click(screen.getByTestId('createPostBtn')); + expect(toastSpy).toBeCalledWith("Can't create a post with an empty body."); + }); + + test('On valid post submission Info toast should be shown', async () => { + renderStartPostModal(true, null); + await wait(); + + const randomPostInput = 'test post input'; + userEvent.type(screen.getByTestId('postInput'), randomPostInput); + expect(screen.queryByText(randomPostInput)).toBeInTheDocument(); + + userEvent.click(screen.getByTestId('createPostBtn')); + + expect(toast.error).not.toBeCalledWith(); + expect(toast.info).toBeCalledWith('Processing your post. Please wait.'); + }); + + test('If user image is null then default image should be shown', async () => { + renderStartPostModal(true, null); + await wait(); + + const userImage = screen.getByTestId('userImage'); + expect(userImage).toHaveAttribute( + 'src', + '/src/assets/images/defaultImg.png', + ); + }); + + test('If user image is not null then user image should be shown', async () => { + renderStartPostModal(true, 'image.png'); + await wait(); + + const userImage = screen.getByTestId('userImage'); + expect(userImage).toHaveAttribute('src', 'image.png'); + }); + + test('should update post image state when a file is selected', async () => { + renderStartPostModal(true, null); + await wait(); + + const file = new File(['(⌐□_□)'], 'chad.png', { type: 'image/png' }); + const input = screen.getByTestId('postImageInput') as HTMLInputElement; + await act(async () => { + fireEvent.change(input, { target: { files: [file] } }); + }); + + expect(input.files?.[0]).toEqual(file); + const previewImage = await screen.findByAltText('Post Image Preview'); + expect(previewImage).toBeInTheDocument(); + }); + + test('should not update post image state when no file is selected', async () => { + renderStartPostModal(true, null); + await wait(); + + const input = screen.getByTestId('postImageInput') as HTMLInputElement; + await act(async () => { + fireEvent.change(input, { target: { files: null } }); + }); + + const previewImage = screen.queryByAltText('Post Image Preview'); + expect(previewImage).not.toBeInTheDocument(); + }); + + test('triggers file input when fileInputRef exists', async () => { + const clickSpy = jest.spyOn(HTMLInputElement.prototype, 'click'); + const refMock = { current: { click: clickSpy } }; + + renderStartPostModal(true, null); + await wait(); + + jest.spyOn(React, 'useRef').mockReturnValueOnce(refMock); + + const iconButton = screen.getByTestId('addMediaBtn'); + fireEvent.click(iconButton); + + expect(clickSpy).toHaveBeenCalled(); + clickSpy.mockRestore(); + }); +}); diff --git a/src/components/UserPortal/StartPostModal/StartPostModal.tsx b/src/components/UserPortal/StartPostModal/StartPostModal.tsx new file mode 100644 index 0000000000..20fe4aae2d --- /dev/null +++ b/src/components/UserPortal/StartPostModal/StartPostModal.tsx @@ -0,0 +1,188 @@ +import React, { useRef, useState } from 'react'; +import type { ChangeEvent } from 'react'; +import { Button, Form, Image, Modal } from 'react-bootstrap'; +import { toast } from 'react-toastify'; +import { useMutation } from '@apollo/client'; +import { useTranslation } from 'react-i18next'; + +import { errorHandler } from 'utils/errorHandler'; +import convertToBase64 from 'utils/convertToBase64'; +import UserDefault from '../../../assets/images/defaultImg.png'; +import styles from './StartPostModal.module.css'; +import { CREATE_POST_MUTATION } from 'GraphQl/Mutations/mutations'; +import type { InterfaceQueryUserListItem } from 'utils/interfaces'; + +interface InterfaceStartPostModalProps { + show: boolean; + onHide: () => void; + fetchPosts: () => void; + userData: InterfaceQueryUserListItem | undefined; + organizationId: string; +} + +const startPostModal = ({ + show, + onHide, + fetchPosts, + userData, + organizationId, +}: InterfaceStartPostModalProps): JSX.Element => { + const { t } = useTranslation('translation', { keyPrefix: 'home' }); + const [postContent, setPostContent] = useState(''); + const [postImage, setPostImage] = useState(''); + const fileInputRef = useRef(null); + + const [createPost] = useMutation(CREATE_POST_MUTATION); + + const handlePostInput = (e: ChangeEvent): void => { + setPostContent(e.target.value); + }; + + const handleHide = (): void => { + setPostContent(''); + setPostImage(''); + onHide(); + }; + + const uploadMedia = (e: React.MouseEvent): void => { + e.preventDefault(); + fileInputRef.current?.click(); + }; + + const handlePost = async (): Promise => { + try { + if (!postContent) { + throw new Error("Can't create a post with an empty body."); + } + toast.info('Processing your post. Please wait.'); + + const { data } = await createPost({ + variables: { + title: '', + text: postContent, + organizationId: organizationId, + file: postImage, + }, + }); + /* istanbul ignore next */ + if (data) { + toast.dismiss(); + toast.success('Your post is now visible in the feed.'); + fetchPosts(); + handleHide(); + } + } catch (error: unknown) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + + return ( + + + + + + + + {`${userData?.user?.firstName} ${userData?.user?.lastName}`} + + + +
    + + + , + ): Promise => { + const file = e.target.files && e.target.files[0]; + if (file) { + const image = await convertToBase64(file); + setPostImage(image); + } else { + toast.info('Error uploading image. Please try again.'); + } + }} + /> + {postImage && ( +
    + Post Image Preview +
    + )} +
    + +
    +
    + + + +
    +
    + ); +}; + +export default startPostModal; diff --git a/src/components/UserPortal/TaskCard/TaskCard.module.css b/src/components/UserPortal/TaskCard/TaskCard.module.css deleted file mode 100644 index bf11a53e48..0000000000 --- a/src/components/UserPortal/TaskCard/TaskCard.module.css +++ /dev/null @@ -1,41 +0,0 @@ -.mainContainer { - width: 100%; - padding: 15px; - cursor: pointer; - border-radius: 10px; - /* box-shadow: 2px 2px 8px 0px #c8c8c8; */ - overflow: hidden; - background-color: rgba(50, 187, 107, 0.15); -} - -.cardDetails { - display: flex; - flex-direction: column; -} - -.cardDetail { - display: flex; - flex-direction: row; - gap: 10px; - margin: 5px; -} - -.fillPrimary { - fill: var(--bs-primary) !important; -} - -.badge { - display: flex; - width: fit-content; - background-color: var(--bs-secondary) !important; - justify-content: center; - align-items: center; -} - -.fitContent { - width: fit-content; -} - -.marginTop { - margin-top: 10px; -} diff --git a/src/components/UserPortal/TaskCard/TaskCard.test.tsx b/src/components/UserPortal/TaskCard/TaskCard.test.tsx deleted file mode 100644 index 1dcec3179c..0000000000 --- a/src/components/UserPortal/TaskCard/TaskCard.test.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import React from 'react'; -import { act, render, screen } from '@testing-library/react'; -import { MockedProvider } from '@apollo/react-testing'; -import { I18nextProvider } from 'react-i18next'; - -import { BrowserRouter } from 'react-router-dom'; -import { Provider } from 'react-redux'; -import { store } from 'state/store'; -import i18nForTest from 'utils/i18nForTest'; -import { StaticMockLink } from 'utils/StaticMockLink'; -import TaskCard from './TaskCard'; - -const link = new StaticMockLink([], true); - -async function wait(ms = 100): Promise { - await act(() => { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); - }); -} - -let props = { - id: '1', - title: 'Test Task Card', - deadline: '2023-09-28T16:25:47.000Z', - description: 'Test Description', - volunteers: [ - { - id: '1', - firstName: 'Test', - lastName: 'User', - email: 'test@user.com', - }, - ], - creator: { - id: '2', - firstName: 'Test', - lastName: 'User', - }, - event: { - id: '3', - title: 'Test Event', - organization: { - id: '1', - name: 'Test Organization', - image: '', - }, - }, - createdAt: '2023-09-21T13:24:31.217Z', - completed: false, -}; - -describe('Testing TaskCard Component [User Portal]', () => { - test('Component should be rendered properly if task.completed === false', async () => { - render( - - - - - - - - - - ); - - await wait(); - - expect(screen.queryAllByText('Test Task Card')).not.toBe([]); - }); - - test('Component should be rendered properly if task.completed === true', async () => { - props = { - ...props, - completed: true, - }; - - render( - - - - - - - - - - ); - - await wait(); - - expect(screen.queryAllByText('Test Task Card')).not.toBe([]); - }); -}); diff --git a/src/components/UserPortal/TaskCard/TaskCard.tsx b/src/components/UserPortal/TaskCard/TaskCard.tsx deleted file mode 100644 index 72b8cfd66a..0000000000 --- a/src/components/UserPortal/TaskCard/TaskCard.tsx +++ /dev/null @@ -1,131 +0,0 @@ -import React from 'react'; -import styles from './TaskCard.module.css'; -import TimerIcon from '@mui/icons-material/Timer'; -import DescriptionIcon from '@mui/icons-material/Description'; -import AssignmentIndIcon from '@mui/icons-material/AssignmentInd'; -import CreateIcon from '@mui/icons-material/Create'; -import EventIcon from '@mui/icons-material/Event'; -import CorporateFareIcon from '@mui/icons-material/CorporateFare'; -import { Badge } from 'react-bootstrap'; -import { Tooltip } from '@mui/material'; -import dayjs from 'dayjs'; -import { useTranslation } from 'react-i18next'; - -interface InterfaceTaskCardProps { - id: string; - title: string; - deadline: string; - description: string; - volunteers: { - id: string; - firstName: string; - lastName: string; - email: string; - }[]; - creator: { - id: string; - firstName: string; - lastName: string; - }; - event: { - id: string; - title: string; - organization: { - id: string; - name: string; - image: string | null; - }; - }; - createdAt: string; - completed: boolean; -} - -function taskCard(props: InterfaceTaskCardProps): JSX.Element { - const { t } = useTranslation('translation', { - keyPrefix: 'userTaskCard', - }); - - const creatorName = `${props.creator.firstName} ${props.creator.lastName}`; - - return ( -
    -
    -
    - {props.title} -
    - -
    - - - {' '} - {props.event.title} -
    - -
    - - - {' '} - {props.event.organization.name} -
    - -
    - - - {' '} - {props.description} -
    - -
    - - - {' '} - {dayjs(props.deadline).format('llll')} -
    - -
    - - - {' '} - {`${dayjs(props.createdAt).format('llll')} by ${creatorName}`} -
    - -
    - - - - {props.volunteers.map((volunteer: any, index) => { - const name = `${volunteer.firstName} ${volunteer.lastName}`; - - return ( - - {name} - - ); - })} -
    - - {props.completed ? ( - - - {t('completed')} - - - ) : ( - - - {t('incomplete')} - - - )} -
    -
    - ); -} - -export default taskCard; diff --git a/src/components/UserPortal/UserNavbar/UserNavbar.test.tsx b/src/components/UserPortal/UserNavbar/UserNavbar.test.tsx index 57d478b8d0..59e3585aa0 100644 --- a/src/components/UserPortal/UserNavbar/UserNavbar.test.tsx +++ b/src/components/UserPortal/UserNavbar/UserNavbar.test.tsx @@ -49,7 +49,7 @@ describe('Testing UserNavbar Component [User Portal]', () => { - + , ); await wait(); @@ -65,7 +65,7 @@ describe('Testing UserNavbar Component [User Portal]', () => { - + , ); await wait(); @@ -89,7 +89,7 @@ describe('Testing UserNavbar Component [User Portal]', () => { - + , ); await wait(); @@ -113,7 +113,7 @@ describe('Testing UserNavbar Component [User Portal]', () => { - + , ); await wait(); @@ -137,7 +137,7 @@ describe('Testing UserNavbar Component [User Portal]', () => { - + , ); await wait(); @@ -161,7 +161,7 @@ describe('Testing UserNavbar Component [User Portal]', () => { - + , ); await wait(); @@ -174,4 +174,44 @@ describe('Testing UserNavbar Component [User Portal]', () => { expect(cookies.get('i18next')).toBe('zh'); }); + + test('User can see and interact with the dropdown menu', async () => { + render( + + + + + + + + + , + ); + + await wait(); + + userEvent.click(screen.getByTestId('logoutDropdown')); + expect(screen.getByText('Settings')).toBeInTheDocument(); + expect(screen.getByTestId('logoutBtn')).toBeInTheDocument(); + }); + + test('User can navigate to the "Settings" page', async () => { + render( + + + + + + + + + , + ); + + await wait(); + + userEvent.click(screen.getByTestId('logoutDropdown')); + userEvent.click(screen.getByText('Settings')); + expect(window.location.pathname).toBe('/user/settings'); + }); }); diff --git a/src/components/UserPortal/UserNavbar/UserNavbar.tsx b/src/components/UserPortal/UserNavbar/UserNavbar.tsx index e10268e85e..d724c6b777 100644 --- a/src/components/UserPortal/UserNavbar/UserNavbar.tsx +++ b/src/components/UserPortal/UserNavbar/UserNavbar.tsx @@ -8,11 +8,15 @@ import cookies from 'js-cookie'; import PermIdentityIcon from '@mui/icons-material/PermIdentity'; import LanguageIcon from '@mui/icons-material/Language'; import { useTranslation } from 'react-i18next'; -import { Link } from 'react-router-dom'; import { useMutation } from '@apollo/client'; import { REVOKE_REFRESH_TOKEN } from 'GraphQl/Mutations/mutations'; +import { useNavigate } from 'react-router-dom'; +import useLocalStorage from 'utils/useLocalstorage'; function userNavbar(): JSX.Element { + const { getItem } = useLocalStorage(); + const navigate = useNavigate(); + const { t } = useTranslation('translation', { keyPrefix: 'userNavbar', }); @@ -21,18 +25,18 @@ function userNavbar(): JSX.Element { const [currentLanguageCode, setCurrentLanguageCode] = React.useState( /* istanbul ignore next */ - cookies.get('i18next') || 'en' + cookies.get('i18next') || 'en', ); + const userName = getItem('name'); + /* istanbul ignore next */ const handleLogout = (): void => { revokeRefreshToken(); localStorage.clear(); - window.location.replace('/user'); + navigate('/'); }; - const userName = localStorage.getItem('name'); - return ( @@ -95,15 +99,11 @@ function userNavbar(): JSX.Element { {userName} - - - {t('settings')} - - - - - {t('myTasks')} - + navigate('/user/settings')} + className={styles.link} + > + {t('settings')} {t('logout')} diff --git a/src/components/UserPortal/UserSidebar/UserSidebar.module.css b/src/components/UserPortal/UserSidebar/UserSidebar.module.css index 00eb9b631f..a9d330339f 100644 --- a/src/components/UserPortal/UserSidebar/UserSidebar.module.css +++ b/src/components/UserPortal/UserSidebar/UserSidebar.module.css @@ -1,71 +1,239 @@ -.mainContainer { +.leftDrawer { + width: calc(300px + 2rem); + position: fixed; + top: 0; + bottom: 0; + z-index: 100; display: flex; - overflow: hidden; flex-direction: column; - align-items: center; - padding: 0px 10px; - padding-top: 50px; - flex-grow: 1; - width: 250px; + padding: 1rem 1rem 0 1rem; background-color: var(--bs-white); + transition: 0.5s; + font-family: var(--bs-leftDrawer-font-family); } -@media screen and (max-width: 700px) { - .mainContainer { - display: none; - } +.activeDrawer { + width: calc(300px + 2rem); + position: fixed; + top: 0; + left: 0; + bottom: 0; + animation: comeToRightBigScreen 0.5s ease-in-out; +} + +.inactiveDrawer { + position: fixed; + top: 0; + left: calc(-300px - 2rem); + bottom: 0; + animation: goToLeftBigScreen 0.5s ease-in-out; } -.userDetails { +.leftDrawer .talawaLogo { + width: 100%; + height: 65px; +} + +.leftDrawer .talawaText { + font-size: 20px; + text-align: center; + font-weight: 500; +} + +.leftDrawer .titleHeader { + margin: 2rem 0 1rem 0; + font-weight: 600; +} + +.leftDrawer .optionList button { display: flex; - flex-direction: column; align-items: center; - padding-top: 20px; + width: 100%; + text-align: start; + margin-bottom: 0.8rem; + border-radius: 16px; + outline: none; + border: none; } -.boxShadow { - box-shadow: 4px 4px 8px 4px #c8c8c8; +.leftDrawer .optionList button .iconWrapper { + width: 36px; } -.organizationsConatiner { +.leftDrawer .profileContainer { + border: none; width: 100%; - padding-top: 50px; + padding: 2.1rem 0.5rem; + height: 52px; + display: flex; + align-items: center; + background-color: var(--bs-white); } -.heading { - text-align: center; - padding: 10px 0px; +.leftDrawer .profileContainer:focus { + outline: none; + background-color: var(--bs-gray-100); +} + +.leftDrawer .imageContainer { + width: 68px; } -.orgName { - font-size: 16px; +.leftDrawer .profileContainer img { + height: 52px; + width: 52px; + border-radius: 50%; +} + +.leftDrawer .profileContainer .profileText { + flex: 1; + text-align: start; +} + +.leftDrawer .profileContainer .profileText .primaryText { + font-size: 1.1rem; font-weight: 600; - margin-top: 4px; } -.alignRight { - width: 100%; - text-align: right; - padding: 5px; +.leftDrawer .profileContainer .profileText .secondaryText { + font-size: 0.8rem; + font-weight: 400; + color: var(--bs-secondary); + display: block; + text-transform: capitalize; +} + +@media (max-width: 1120px) { + .leftDrawer { + width: calc(250px + 2rem); + padding: 1rem 1rem 0 1rem; + } +} + +/* For tablets */ +@media (max-width: 820px) { + .hideElemByDefault { + display: none; + } + + .leftDrawer { + width: 100%; + left: 0; + right: 0; + } + + .inactiveDrawer { + opacity: 0; + left: 0; + z-index: -1; + animation: closeDrawer 0.4s ease-in-out; + } + + .activeDrawer { + display: flex; + z-index: 100; + animation: openDrawer 0.6s ease-in-out; + } + + .logout { + margin-bottom: 2.5rem !important; + } } -.link { - text-decoration: none !important; - color: black; +@keyframes goToLeftBigScreen { + from { + left: 0; + } + + to { + opacity: 0.1; + left: calc(-300px - 2rem); + } } -.rounded { - border-radius: 10px !important; +/* Webkit prefix for older browser compatibility */ +@-webkit-keyframes goToLeftBigScreen { + from { + left: 0; + } + + to { + opacity: 0.1; + left: calc(-300px - 2rem); + } } -.colorLight { - background-color: #f5f5f5; +@keyframes comeToRightBigScreen { + from { + opacity: 0.4; + left: calc(-300px - 2rem); + } + + to { + opacity: 1; + left: 0; + } } -.marginTop { - margin-top: -2px; +/* Webkit prefix for older browser compatibility */ +@-webkit-keyframes comeToRightBigScreen { + from { + opacity: 0.4; + left: calc(-300px - 2rem); + } + + to { + opacity: 1; + left: 0; + } } -.personImage { - border-radius: 50%; +@keyframes closeDrawer { + from { + left: 0; + opacity: 1; + } + + to { + left: -1000px; + opacity: 0; + } +} + +/* Webkit prefix for older browser compatibility */ +@-webkit-keyframes closeDrawer { + from { + left: 0; + opacity: 1; + } + + to { + left: -1000px; + opacity: 0; + } +} + +@keyframes openDrawer { + from { + opacity: 0; + left: -1000px; + } + + to { + left: 0; + opacity: 1; + } +} + +/* Webkit prefix for older browser compatibility */ +@-webkit-keyframes openDrawer { + from { + opacity: 0; + left: -1000px; + } + + to { + left: 0; + opacity: 1; + } } diff --git a/src/components/UserPortal/UserSidebar/UserSidebar.test.tsx b/src/components/UserPortal/UserSidebar/UserSidebar.test.tsx index 36327f6c93..2984604951 100644 --- a/src/components/UserPortal/UserSidebar/UserSidebar.test.tsx +++ b/src/components/UserPortal/UserSidebar/UserSidebar.test.tsx @@ -1,5 +1,6 @@ import React from 'react'; -import { act, render } from '@testing-library/react'; +import type { RenderResult } from '@testing-library/react'; +import { act, fireEvent, render, screen } from '@testing-library/react'; import { MockedProvider } from '@apollo/react-testing'; import { I18nextProvider } from 'react-i18next'; @@ -13,72 +14,182 @@ import { store } from 'state/store'; import i18nForTest from 'utils/i18nForTest'; import { StaticMockLink } from 'utils/StaticMockLink'; import UserSidebar from './UserSidebar'; +import useLocalStorage from 'utils/useLocalstorage'; +const { setItem } = useLocalStorage(); + +const resizeWindow = (width: number): void => { + window.innerWidth = width; + fireEvent(window, new Event('resize')); +}; + +const props = { + hideDrawer: true, + setHideDrawer: jest.fn(), +}; const MOCKS = [ { request: { query: USER_DETAILS, variables: { - id: localStorage.getItem('userId'), + id: 'properId', }, }, result: { data: { user: { - __typename: 'User', - image: null, - firstName: 'Noble', - lastName: 'Mittal', - email: 'noble@mittal.com', - role: 'SUPERADMIN', - appLanguageCode: 'en', - userType: 'SUPERADMIN', - pluginCreationAllowed: true, - adminApproved: true, - createdAt: '2023-02-18T09:22:27.969Z', - adminFor: [], - createdOrganizations: [], - joinedOrganizations: [], - organizationUserBelongsTo: null, - organizationsBlockedBy: [], - createdEvents: [], - registeredEvents: [], - eventAdmin: [], - membershipRequests: [], + user: { + _id: 'properId', + image: null, + firstName: 'Noble', + lastName: 'Mittal', + email: 'noble@mittal.com', + createdAt: '2023-02-18T09:22:27.969Z', + joinedOrganizations: [], + membershipRequests: [], + registeredEvents: [], + gender: '', + birthDate: '2024-03-14', + educationGrade: '', + employmentStatus: '', + maritalStatus: '', + address: { + line1: '', + countryCode: '', + city: '', + state: '', + }, + phone: { + mobile: '', + }, + }, + appUserProfile: { + _id: 'properId', + adminFor: [], + createdOrganizations: [], + createdEvents: [], + eventAdmin: [], + isSuperAdmin: true, + pluginCreationAllowed: true, + appLanguageCode: 'en', + }, }, }, }, }, + { + request: { + query: USER_JOINED_ORGANIZATIONS, + variables: { + id: 'properId', + }, + }, + result: { + data: { + users: [ + { + user: { + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + name: 'Any Organization', + image: '', + description: 'New Desc', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + createdAt: '1234567890', + userRegistrationRequired: true, + creator: { + __typename: 'User', + firstName: 'John', + lastName: 'Doe', + }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + }, + ], + }, + }, + ], + }, + }, + }, { request: { query: USER_DETAILS, variables: { - id: '2', + id: 'imagePresent', }, }, result: { data: { user: { - __typename: 'User', - image: 'adssda', - firstName: 'Noble', - lastName: 'Mittal', - email: 'noble@mittal.com', - role: 'SUPERADMIN', - appLanguageCode: 'en', - userType: 'SUPERADMIN', - pluginCreationAllowed: true, - adminApproved: true, - createdAt: '2023-02-18T09:22:27.969Z', - adminFor: [], - createdOrganizations: [], - joinedOrganizations: [], - organizationUserBelongsTo: null, - organizationsBlockedBy: [], - createdEvents: [], - registeredEvents: [], - eventAdmin: [], - membershipRequests: [], + user: { + _id: '2', + image: 'adssda', + firstName: 'Noble', + lastName: 'Mittal', + email: 'noble@mittal.com', + createdAt: '2023-02-18T09:22:27.969Z', + joinedOrganizations: [], + membershipRequests: [], + registeredEvents: [], + gender: '', + birthDate: '2024-03-14', + educationGrade: '', + employmentStatus: '', + maritalStatus: '', + address: { + line1: '', + countryCode: '', + city: '', + state: '', + }, + phone: { + mobile: '', + }, + }, + appUserProfile: { + _id: '2', + adminFor: [], + createdOrganizations: [], + createdEvents: [], + eventAdmin: [], + isSuperAdmin: true, + pluginCreationAllowed: true, + appLanguageCode: 'en', + }, }, }, }, @@ -87,22 +198,65 @@ const MOCKS = [ request: { query: USER_JOINED_ORGANIZATIONS, variables: { - id: localStorage.getItem('userId'), + id: 'imagePresent', }, }, result: { data: { users: [ { - joinedOrganizations: [ - { - __typename: 'Organization', - _id: '6401ff65ce8e8406b8f07af2', - name: 'Any Organization', - image: '', - description: 'New Desc', - }, - ], + user: { + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + name: 'Any Organization', + image: 'dadsa', + description: 'New Desc', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + createdAt: '1234567890', + userRegistrationRequired: true, + creator: { + __typename: 'User', + firstName: 'John', + lastName: 'Doe', + }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + }, + ], + }, }, ], }, @@ -110,26 +264,50 @@ const MOCKS = [ }, { request: { - query: USER_JOINED_ORGANIZATIONS, + query: USER_DETAILS, variables: { - id: '2', + id: 'orgEmpty', }, }, result: { data: { - users: [ - { - joinedOrganizations: [ - { - __typename: 'Organization', - _id: '6401ff65ce8e8406b8f07af2', - name: 'Any Organization', - image: 'dadsa', - description: 'New Desc', - }, - ], + user: { + user: { + _id: 'orgEmpty', + image: null, + firstName: 'Noble', + lastName: 'Mittal', + email: 'noble@mittal.com', + createdAt: '2023-02-18T09:22:27.969Z', + joinedOrganizations: [], + membershipRequests: [], + registeredEvents: [], + gender: '', + birthDate: '2024-03-14', + educationGrade: '', + employmentStatus: '', + maritalStatus: '', + address: { + line1: '', + countryCode: '', + city: '', + state: '', + }, + phone: { + mobile: '', + }, }, - ], + appUserProfile: { + _id: 'orgEmpty', + adminFor: [], + createdOrganizations: [], + createdEvents: [], + eventAdmin: [], + isSuperAdmin: true, + pluginCreationAllowed: true, + appLanguageCode: 'en', + }, + }, }, }, }, @@ -137,14 +315,16 @@ const MOCKS = [ request: { query: USER_JOINED_ORGANIZATIONS, variables: { - id: '3', + id: 'orgEmpty', }, }, result: { data: { users: [ { - joinedOrganizations: [], + user: { + joinedOrganizations: [], + }, }, ], }, @@ -162,91 +342,76 @@ async function wait(ms = 100): Promise { }); } +const renderUserSidebar = ( + userId: string, + link: StaticMockLink, +): RenderResult => { + setItem('userId', userId); + return render( + + + + + + + + + , + ); +}; + describe('Testing UserSidebar Component [User Portal]', () => { - test('Component should be rendered properly', async () => { - render( - - - - - - - - - - ); + beforeEach(() => { + jest.clearAllMocks(); + }); + test('Component should be rendered properly', async () => { + renderUserSidebar('properId', link); await wait(); }); - test('Component should be rendered properly when userImage is not undefined', async () => { - const beforeUserId = localStorage.getItem('userId'); - - localStorage.setItem('userId', '2'); - - render( - - - - - - - - - - ); - + test('Component should be rendered properly when userImage is present', async () => { + renderUserSidebar('imagePresent', link); await wait(); - if (beforeUserId) { - localStorage.setItem('userId', beforeUserId); - } }); - test('Component should be rendered properly when organizationImage is not undefined', async () => { - const beforeUserId = localStorage.getItem('userId'); - - localStorage.setItem('userId', '2'); - - render( - - - - - - - - - - ); - + test('Component should be rendered properly when organizationImage is present', async () => { + renderUserSidebar('imagePresent', link); await wait(); - - if (beforeUserId) { - localStorage.setItem('userId', beforeUserId); - } }); test('Component should be rendered properly when joinedOrganizations list is empty', async () => { - const beforeUserId = localStorage.getItem('userId'); - - localStorage.setItem('userId', '3'); + renderUserSidebar('orgEmpty', link); + await wait(); + }); + test('Testing Drawer when the screen size is less than or equal to 820px', () => { + resizeWindow(800); render( - + - + , ); + expect(screen.getByText('My Organizations')).toBeInTheDocument(); + expect(screen.getByText('Settings')).toBeInTheDocument(); + expect(screen.getByText('Talawa User Portal')).toBeInTheDocument(); + const settingsBtn = screen.getByText('Settings'); - await wait(); + const orgsBtn = screen.getAllByTestId(/orgsBtn/i); - if (beforeUserId) { - localStorage.setItem('userId', beforeUserId); - } + orgsBtn[0].click(); + expect( + orgsBtn[0].className.includes('text-white btn btn-success'), + ).toBeTruthy(); + settingsBtn.click(); + expect( + settingsBtn.className.includes('text-white btn btn-success'), + ).toBeTruthy(); }); }); diff --git a/src/components/UserPortal/UserSidebar/UserSidebar.tsx b/src/components/UserPortal/UserSidebar/UserSidebar.tsx index 2e455358b0..d7c362a5b2 100644 --- a/src/components/UserPortal/UserSidebar/UserSidebar.tsx +++ b/src/components/UserPortal/UserSidebar/UserSidebar.tsx @@ -1,123 +1,93 @@ import React from 'react'; -import AboutImg from 'assets/images/defaultImg.png'; -import styles from './UserSidebar.module.css'; -import { ListGroup } from 'react-bootstrap'; -import { Link } from 'react-router-dom'; -import ChevronRightIcon from '@mui/icons-material/ChevronRight'; -import { useQuery } from '@apollo/client'; -import { - USER_DETAILS, - USER_JOINED_ORGANIZATIONS, -} from 'GraphQl/Queries/Queries'; +import Button from 'react-bootstrap/Button'; import { useTranslation } from 'react-i18next'; -import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; - -function userSidebar(): JSX.Element { - const { t } = useTranslation('translation', { - keyPrefix: 'userSidebar', - }); - - const [organizations, setOrganizations] = React.useState([]); - const [details, setDetails] = React.useState({} as any); - - const userId: string | null = localStorage.getItem('userId'); - - const { data, loading: loadingJoinedOrganizations } = useQuery( - USER_JOINED_ORGANIZATIONS, - { - variables: { id: userId }, - } - ); +import { NavLink } from 'react-router-dom'; +import { ReactComponent as OrganizationsIcon } from 'assets/svgs/organizations.svg'; +import { ReactComponent as SettingsIcon } from 'assets/svgs/settings.svg'; +import { ReactComponent as TalawaLogo } from 'assets/svgs/talawa.svg'; +import styles from './UserSidebar.module.css'; - const { data: data2, loading: loadingUserDetails } = useQuery(USER_DETAILS, { - variables: { id: userId }, - }); +export interface InterfaceUserSidebarProps { + hideDrawer: boolean | null; + setHideDrawer: React.Dispatch>; +} - /* istanbul ignore next */ - React.useEffect(() => { - if (data) { - setOrganizations(data.users[0].joinedOrganizations); - } - }, [data]); +const userSidebar = ({ + hideDrawer, + setHideDrawer, +}: InterfaceUserSidebarProps): JSX.Element => { + const { t } = useTranslation('translation', { keyPrefix: 'userSidebarOrg' }); - /* istanbul ignore next */ - React.useEffect(() => { - if (data2) { - setDetails(data2.user); + const handleLinkClick = (): void => { + if (window.innerWidth <= 820) { + setHideDrawer(true); } - }, [data2]); + }; return ( -
    - {loadingJoinedOrganizations || loadingUserDetails ? ( - <> - Loading... - - ) : ( - <> - -
    -
    - {`${details.firstName} ${details.lastName}`} -
    -
    {details.email}
    -
    -
    -
    - {t('yourOrganizations')} -
    - - {organizations.length ? ( - organizations.map((organization: any, index) => { - const organizationUrl = `/user/organization/id=${organization._id}`; - - return ( - - -
    - -
    - {organization.name} -
    -
    - -
    - ); - }) - ) : ( -
    {t('noOrganizations')}
    - )} -
    -
    - - {t('viewAll')} - - -
    -
    - - )} -
    + <> +
    + +

    {t('talawaUserPortal')}

    +
    {t('menu')}
    +
    + + {({ isActive }) => ( + + )} + + + {({ isActive }) => ( + + )} + +
    +
    + ); -} +}; export default userSidebar; diff --git a/src/components/LeftDrawerEvent/LeftDrawerEvent.module.css b/src/components/UserPortal/UserSidebarOrg/UserSidebarOrg.module.css similarity index 60% rename from src/components/LeftDrawerEvent/LeftDrawerEvent.module.css rename to src/components/UserPortal/UserSidebarOrg/UserSidebarOrg.module.css index af654f9043..b300eb7e89 100644 --- a/src/components/LeftDrawerEvent/LeftDrawerEvent.module.css +++ b/src/components/UserPortal/UserSidebarOrg/UserSidebarOrg.module.css @@ -1,5 +1,6 @@ .leftDrawer { width: calc(300px + 2rem); + min-height: 100%; position: fixed; top: 0; bottom: 0; @@ -9,23 +10,7 @@ padding: 0.8rem 1rem 0 1rem; background-color: var(--bs-white); transition: 0.5s; - overflow-y: scroll; -} - -.leftDrawer::-webkit-scrollbar { - width: 6px; -} - -.leftDrawer::-webkit-scrollbar-track { - background: #f1f1f1; -} - -.leftDrawer::-webkit-scrollbar-thumb { - background: var(--bs-gray-500); -} - -.leftDrawer::-webkit-scrollbar-thumb:hover { - background: var(--bs-gray-600); + font-family: var(--bs-leftDrawer-font-family); } .activeDrawer { @@ -45,10 +30,6 @@ animation: goToLeftBigScreen 0.5s ease-in-out; } -.leftDrawer .closeModalBtn { - display: none; -} - .leftDrawer .brandingContainer { display: flex; justify-content: flex-start; @@ -57,26 +38,30 @@ .leftDrawer .organizationContainer button { position: relative; - margin: 1.25rem 0; + margin: 0.7rem 0; padding: 2.5rem 0.1rem; - border-radius: 0.5rem; - border: 1px solid var(--bs-gray-300); - background-color: var(--bs-gray-100); + border-radius: 16px; } .leftDrawer .talawaLogo { - width: 42px; - height: 42px; - margin-right: 0.5rem; + width: 50px; + height: 50px; + margin-right: 0.3rem; } .leftDrawer .talawaText { - font-size: 1.1rem; + font-size: 18px; + font-weight: 500; } .leftDrawer .titleHeader { - margin-bottom: 1rem; font-weight: 600; + margin: 0.6rem 0rem; +} + +.leftDrawer .optionList { + height: 100%; + overflow-y: auto; } .leftDrawer .optionList button { @@ -85,17 +70,21 @@ width: 100%; text-align: start; margin-bottom: 0.8rem; - border: 1px solid var(--bs-gray-200); - border-radius: 8px; + border-radius: 16px; + font-size: 16px; + padding: 0.6rem; + padding-left: 0.8rem; + outline: none; + border: none; } .leftDrawer button .iconWrapper { width: 36px; - transform: translateY(3px) translateY(-2px); } .leftDrawer .optionList .collapseBtn { height: 48px; + border: none; } .leftDrawer button .iconWrapperSm { @@ -105,24 +94,28 @@ align-items: center; } +.leftDrawer .organizationContainer .profileContainer { + background-color: #31bb6b33; + padding-right: 10px; +} + .leftDrawer .profileContainer { border: none; width: 100%; - margin-top: 5rem; height: 52px; - border-radius: 8px; - background-color: var(--bs-white); + border-radius: 16px; display: flex; align-items: center; + background-color: var(--bs-white); } .leftDrawer .profileContainer:focus { outline: none; - background-color: var(--bs-gray-100); } .leftDrawer .imageContainer { width: 68px; + margin-right: 8px; } .leftDrawer .profileContainer img { @@ -134,11 +127,18 @@ .leftDrawer .profileContainer .profileText { flex: 1; text-align: start; + overflow: hidden; } .leftDrawer .profileContainer .profileText .primaryText { font-size: 1.1rem; font-weight: 600; + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 2; /* number of lines to show */ + -webkit-box-orient: vertical; + word-wrap: break-word; + white-space: normal; } .leftDrawer .profileContainer .profileText .secondaryText { @@ -157,6 +157,72 @@ } /* For tablets */ +@media (max-height: 900px) { + .leftDrawer { + width: calc(300px + 1rem); + } + .leftDrawer .talawaLogo { + width: 38px; + height: 38px; + margin-right: 0.4rem; + } + .leftDrawer .talawaText { + font-size: 1rem; + } + .leftDrawer .organizationContainer button { + margin: 0.6rem 0; + padding: 2.2rem 0.1rem; + } + .leftDrawer .optionList button { + margin-bottom: 0.05rem; + font-size: 16px; + padding-left: 0.8rem; + } + .leftDrawer .profileContainer .profileText .primaryText { + font-size: 1rem; + } + .leftDrawer .profileContainer .profileText .secondaryText { + font-size: 0.8rem; + } +} +@media (max-height: 650px) { + .leftDrawer { + padding: 0.5rem 0.8rem 0 0.8rem; + width: calc(250px); + } + .leftDrawer .talawaText { + font-size: 0.8rem; + } + .leftDrawer .organizationContainer button { + margin: 0.2rem 0; + padding: 1.6rem 0rem; + } + .leftDrawer .titleHeader { + font-size: 16px; + } + .leftDrawer .optionList button { + margin-bottom: 0.05rem; + font-size: 14px; + padding: 0.4rem; + padding-left: 0.8rem; + } + .leftDrawer .profileContainer .profileText .primaryText { + font-size: 0.8rem; + } + .leftDrawer .profileContainer .profileText .secondaryText { + font-size: 0.6rem; + } + .leftDrawer .imageContainer { + width: 40px; + margin-left: 5px; + margin-right: 12px; + } + .leftDrawer .imageContainer img { + width: 40px; + height: 100%; + } +} + @media (max-width: 820px) { .hideElemByDefault { display: none; @@ -168,27 +234,21 @@ right: 0; } - .leftDrawer .closeModalBtn { - display: block; - position: absolute; - top: 1rem; - right: 1rem; - z-index: 10; - } - - /* For smaller devices .activeDrawer in real behaves like inactive */ - .activeDrawer { + .inactiveDrawer { opacity: 0; left: 0; z-index: -1; - animation: closeDrawer 0.4s ease-in-out; + animation: closeDrawer 0.2s ease-in-out; } - /* For smaller devices .inactiveDrawer in real behaves like active */ - .inactiveDrawer { + .activeDrawer { display: flex; z-index: 100; - animation: openDrawer 0.6s ease-in-out; + animation: openDrawer 0.4s ease-in-out; + } + + .logout { + margin-bottom: 2.5rem; } } diff --git a/src/components/UserPortal/UserSidebarOrg/UserSidebarOrg.test.tsx b/src/components/UserPortal/UserSidebarOrg/UserSidebarOrg.test.tsx new file mode 100644 index 0000000000..d9d70478b3 --- /dev/null +++ b/src/components/UserPortal/UserSidebarOrg/UserSidebarOrg.test.tsx @@ -0,0 +1,419 @@ +import React from 'react'; +import { fireEvent, render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import 'jest-localstorage-mock'; +import { I18nextProvider } from 'react-i18next'; +import { BrowserRouter } from 'react-router-dom'; + +import i18nForTest from 'utils/i18nForTest'; +import type { InterfaceUserSidebarOrgProps } from './UserSidebarOrg'; +import UserSidebarOrg from './UserSidebarOrg'; +import { Provider } from 'react-redux'; +import { MockedProvider } from '@apollo/react-testing'; +import { store } from 'state/store'; +import { ORGANIZATIONS_LIST } from 'GraphQl/Queries/Queries'; +import { act } from 'react-dom/test-utils'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { REVOKE_REFRESH_TOKEN } from 'GraphQl/Mutations/mutations'; +import useLocalStorage from 'utils/useLocalstorage'; + +const { setItem } = useLocalStorage(); + +const props: InterfaceUserSidebarOrgProps = { + orgId: '123', + targets: [ + { + name: 'Posts', + url: '/user/organization/123', + }, + { + name: 'People', + url: '/user/people/123', + }, + { + name: 'Events', + url: '/user/events/123', + }, + { + name: 'Donations', + url: '/user/donate/123', + }, + { + name: 'Settings', + url: '/user/settings', + }, + { + name: 'All Organizations', + url: '/user/organizations/', + }, + ], + hideDrawer: false, + setHideDrawer: jest.fn(), +}; + +const MOCKS = [ + { + request: { + query: REVOKE_REFRESH_TOKEN, + }, + result: { + data: { + revokeRefreshTokenForUser: true, + }, + }, + }, + { + request: { + query: ORGANIZATIONS_LIST, + variables: { id: '123' }, + }, + result: { + data: { + organizations: [ + { + _id: '123', + image: null, + creator: { + firstName: 'John', + lastName: 'Doe', + email: 'JohnDoe@example.com', + }, + name: 'Test Organization', + description: 'Testing this organization', + address: { + city: 'Delhi', + countryCode: 'IN', + dependentLocality: 'Some Dependent Locality', + line1: '123 Random Street', + line2: 'Apartment 456', + postalCode: '110001', + sortingCode: 'ABC-123', + state: 'Delhi', + }, + userRegistrationRequired: true, + visibleInSearch: true, + members: [ + { + _id: 'john123', + firstName: 'John', + lastName: 'Doe', + email: 'JohnDoe@example.com', + createdAt: '4567890234', + }, + { + _id: 'jane123', + firstName: 'Jane', + lastName: 'Doe', + email: 'JaneDoe@example.com', + createdAt: '4567890234', + }, + ], + admins: [ + { + _id: 'john123', + firstName: 'John', + lastName: 'Doe', + email: 'JohnDoe@example.com', + createdAt: '4567890234', + }, + ], + membershipRequests: [], + blockedUsers: [], + }, + ], + }, + }, + }, +]; + +const MOCKS_WITH_IMAGE = [ + { + request: { + query: ORGANIZATIONS_LIST, + variables: { id: '123' }, + }, + result: { + data: { + organizations: [ + { + _id: '123', + image: + 'https://api.dicebear.com/5.x/initials/svg?seed=Test%20Organization', + creator: { + firstName: 'John', + lastName: 'Doe', + email: 'JohnDoe@example.com', + }, + name: 'Test Organization', + description: 'Testing this organization', + address: { + city: 'Delhi', + countryCode: 'IN', + dependentLocality: 'Some Dependent Locality', + line1: '123 Random Street', + line2: 'Apartment 456', + postalCode: '110001', + sortingCode: 'ABC-123', + state: 'Delhi', + }, + userRegistrationRequired: true, + visibleInSearch: true, + members: [ + { + _id: 'john123', + firstName: 'John', + lastName: 'Doe', + email: 'JohnDoe@example.com', + createdAt: '4567890234', + }, + { + _id: 'jane123', + firstName: 'Jane', + lastName: 'Doe', + email: 'JaneDoe@example.com', + createdAt: '4567890234', + }, + ], + admins: [ + { + _id: 'john123', + firstName: 'John', + lastName: 'Doe', + email: 'JohnDoe@example.com', + createdAt: '4567890234', + }, + ], + membershipRequests: [], + blockedUsers: [], + }, + ], + }, + }, + }, +]; + +const MOCKS_EMPTY = [ + { + request: { + query: ORGANIZATIONS_LIST, + variables: { id: '123' }, + }, + result: { + data: { + organizations: [], + }, + }, + }, +]; + +const defaultScreens = [ + 'People', + 'Events', + 'Posts', + 'Donations', + 'All Organizations', +]; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }, +})); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +const resizeWindow = (width: number): void => { + window.innerWidth = width; + fireEvent(window, new Event('resize')); +}; + +beforeEach(() => { + setItem('FirstName', 'John'); + setItem('LastName', 'Doe'); + setItem( + 'UserImage', + 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', + ); +}); + +afterEach(() => { + jest.clearAllMocks(); + localStorage.clear(); +}); + +const link = new StaticMockLink(MOCKS, true); +const linkImage = new StaticMockLink(MOCKS_WITH_IMAGE, true); +const linkEmpty = new StaticMockLink(MOCKS_EMPTY, true); + +describe('Testing LeftDrawerOrg component for SUPERADMIN', () => { + test('Component should be rendered properly', async () => { + setItem('UserImage', ''); + setItem('SuperAdmin', true); + setItem('FirstName', 'John'); + setItem('LastName', 'Doe'); + render( + + + + + + + + + , + ); + await wait(); + defaultScreens.map((screenName) => { + expect(screen.getByText(screenName)).toBeInTheDocument(); + }); + }); + + test('Testing Profile Page & Organization Detail Modal', async () => { + setItem('UserImage', ''); + setItem('SuperAdmin', true); + setItem('FirstName', 'John'); + setItem('LastName', 'Doe'); + render( + + + + + + + + + , + ); + await wait(); + expect(screen.getByTestId(/orgBtn/i)).toBeInTheDocument(); + }); + + test('Testing Menu Buttons', async () => { + setItem('UserImage', ''); + setItem('SuperAdmin', true); + setItem('FirstName', 'John'); + setItem('LastName', 'Doe'); + render( + + + + + + + + + , + ); + await wait(); + userEvent.click(screen.getByText('People')); + expect(global.window.location.pathname).toContain('/user/people/123'); + }); + + test('Testing when screen size is less than 820px', async () => { + setItem('SuperAdmin', true); + render( + + + + + + + + + , + ); + await wait(); + resizeWindow(800); + expect(screen.getByText(/People/i)).toBeInTheDocument(); + + const peopelBtn = screen.getByTestId(/People/i); + userEvent.click(peopelBtn); + await wait(); + expect(window.location.pathname).toContain('user/people/123'); + }); + + test('Testing when image is present for Organization', async () => { + setItem('UserImage', ''); + setItem('SuperAdmin', true); + setItem('FirstName', 'John'); + setItem('LastName', 'Doe'); + render( + + + + + + + + + , + ); + await wait(); + }); + + test('Testing when Organization does not exists', async () => { + setItem('UserImage', ''); + setItem('SuperAdmin', true); + setItem('FirstName', 'John'); + setItem('LastName', 'Doe'); + render( + + + + + + + + + , + ); + await wait(); + expect( + screen.getByText(/Error Occured while loading the Organization/i), + ).toBeInTheDocument(); + }); + + test('Testing Drawer when hideDrawer is null', () => { + setItem('UserImage', ''); + setItem('SuperAdmin', true); + setItem('FirstName', 'John'); + setItem('LastName', 'Doe'); + render( + + + + + + + + + , + ); + }); + + test('Testing Drawer when hideDrawer is true', () => { + setItem('UserImage', ''); + setItem('SuperAdmin', true); + setItem('FirstName', 'John'); + setItem('LastName', 'Doe'); + render( + + + + + + + + + , + ); + }); +}); diff --git a/src/components/UserPortal/UserSidebarOrg/UserSidebarOrg.tsx b/src/components/UserPortal/UserSidebarOrg/UserSidebarOrg.tsx new file mode 100644 index 0000000000..03fbbd9c4f --- /dev/null +++ b/src/components/UserPortal/UserSidebarOrg/UserSidebarOrg.tsx @@ -0,0 +1,171 @@ +import { useQuery } from '@apollo/client'; +import { WarningAmberOutlined } from '@mui/icons-material'; +import { ORGANIZATIONS_LIST } from 'GraphQl/Queries/Queries'; +import CollapsibleDropdown from 'components/CollapsibleDropdown/CollapsibleDropdown'; +import IconComponent from 'components/IconComponent/IconComponent'; +import React, { useEffect, useState } from 'react'; +import Button from 'react-bootstrap/Button'; +import { useTranslation } from 'react-i18next'; +import { NavLink } from 'react-router-dom'; +import type { TargetsType } from 'state/reducers/routesReducer'; +import type { InterfaceQueryOrganizationsListObject } from 'utils/interfaces'; +import { ReactComponent as AngleRightIcon } from 'assets/svgs/angleRight.svg'; +import { ReactComponent as TalawaLogo } from 'assets/svgs/talawa.svg'; +import styles from './UserSidebarOrg.module.css'; +import Avatar from 'components/Avatar/Avatar'; + +export interface InterfaceUserSidebarOrgProps { + orgId: string; + targets: TargetsType[]; + hideDrawer: boolean | null; + setHideDrawer: React.Dispatch>; +} + +const UserSidebarOrg = ({ + targets, + orgId, + hideDrawer, + setHideDrawer, +}: InterfaceUserSidebarOrgProps): JSX.Element => { + const { t } = useTranslation('translation', { keyPrefix: 'userSidebarOrg' }); + const [showDropdown, setShowDropdown] = React.useState(false); + + const [organization, setOrganization] = + useState(); + const { + data, + loading, + }: { + data: + | { organizations: InterfaceQueryOrganizationsListObject[] } + | undefined; + loading: boolean; + } = useQuery(ORGANIZATIONS_LIST, { + variables: { id: orgId }, + }); + // Set organization data + useEffect(() => { + let isMounted = true; + if (data && isMounted) { + setOrganization(data?.organizations[0]); + console.log(targets, 'targets'); + } + return () => { + isMounted = false; + }; + }, [data]); + + const handleLinkClick = (): void => { + if (window.innerWidth <= 820) { + setHideDrawer(true); + } + }; + + return ( + <> +
    + {/* Branding Section */} +
    + + {t('talawaUserPortal')} +
    + + {/* Organization Section */} +
    + {loading ? ( + <> + + + ) : ( + + )} +
    + + {/* Options List */} +
    +
    + {t('menu')} +
    + {targets.map(({ name, url }, index) => { + return url ? ( + + {({ isActive }) => ( + + )} + + ) : ( + + ); + })} +
    +
    + + ); +}; + +export default UserSidebarOrg; diff --git a/src/components/UserProfileSettings/DeleteUser.test.tsx b/src/components/UserProfileSettings/DeleteUser.test.tsx new file mode 100644 index 0000000000..34ab44fbe5 --- /dev/null +++ b/src/components/UserProfileSettings/DeleteUser.test.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { BrowserRouter } from 'react-router-dom'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; +import DeleteUser from './DeleteUser'; + +describe('Delete User component', () => { + test('renders delete user correctly', () => { + const { getByText, getAllByText } = render( + + + + + + + , + ); + + expect( + getByText( + 'By clicking on Delete User button your user will be permanently deleted along with its events, tags and all related data.', + ), + ).toBeInTheDocument(); + expect(getAllByText('Delete User')[0]).toBeInTheDocument(); + }); +}); diff --git a/src/components/UserProfileSettings/DeleteUser.tsx b/src/components/UserProfileSettings/DeleteUser.tsx new file mode 100644 index 0000000000..3a90542883 --- /dev/null +++ b/src/components/UserProfileSettings/DeleteUser.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import { Button, Card } from 'react-bootstrap'; +import { useTranslation } from 'react-i18next'; +import styles from './UserProfileSettings.module.css'; + +const DeleteUser: React.FC = () => { + const { t } = useTranslation('translation', { + keyPrefix: 'settings', + }); + return ( + <> + +
    +
    {t('deleteUser')}
    +
    + +

    {t('deleteUserMessage')}

    + +
    +
    + + ); +}; + +export default DeleteUser; diff --git a/src/components/UserProfileSettings/OtherSettings.test.tsx b/src/components/UserProfileSettings/OtherSettings.test.tsx new file mode 100644 index 0000000000..990a430931 --- /dev/null +++ b/src/components/UserProfileSettings/OtherSettings.test.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { BrowserRouter } from 'react-router-dom'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; +import OtherSettings from './OtherSettings'; + +describe('Delete User component', () => { + test('renders delete user correctly', () => { + const { getByText } = render( + + + + + + + , + ); + + expect(getByText('Other Settings')).toBeInTheDocument(); + expect(getByText('Change Language')).toBeInTheDocument(); + }); +}); diff --git a/src/components/UserProfileSettings/OtherSettings.tsx b/src/components/UserProfileSettings/OtherSettings.tsx new file mode 100644 index 0000000000..1e9723c2d6 --- /dev/null +++ b/src/components/UserProfileSettings/OtherSettings.tsx @@ -0,0 +1,26 @@ +import ChangeLanguageDropDown from 'components/ChangeLanguageDropdown/ChangeLanguageDropDown'; +import React from 'react'; +import { Card, Form } from 'react-bootstrap'; +import { useTranslation } from 'react-i18next'; +import styles from './UserProfileSettings.module.css'; + +const OtherSettings: React.FC = () => { + const { t } = useTranslation('translation', { + keyPrefix: 'settings', + }); + return ( + +
    +
    {t('otherSettings')}
    +
    + + + {t('changeLanguage')} + + + +
    + ); +}; + +export default OtherSettings; diff --git a/src/components/UserProfileSettings/UserProfile.test.tsx b/src/components/UserProfileSettings/UserProfile.test.tsx new file mode 100644 index 0000000000..979310685f --- /dev/null +++ b/src/components/UserProfileSettings/UserProfile.test.tsx @@ -0,0 +1,38 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import UserProfile from './UserProfile'; +import { MockedProvider } from '@apollo/react-testing'; +import { BrowserRouter } from 'react-router-dom'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; + +describe('UserProfile component', () => { + test('renders user profile details correctly', () => { + const userDetails = { + firstName: 'John', + lastName: 'Doe', + email: 'john.doe@example.com', + image: 'profile-image-url', + }; + const { getByText, getByAltText } = render( + + + + + + + , + ); + + expect(getByText('John')).toBeInTheDocument(); + expect(getByText('john.doe@example.com')).toBeInTheDocument(); + + const profileImage = getByAltText('profile picture'); + expect(profileImage).toBeInTheDocument(); + expect(profileImage).toHaveAttribute('src', 'profile-image-url'); + + expect(getByText('Joined 1st May, 2021')).toBeInTheDocument(); + + expect(getByText('Copy Profile Link')).toBeInTheDocument(); + }); +}); diff --git a/src/components/UserProfileSettings/UserProfile.tsx b/src/components/UserProfileSettings/UserProfile.tsx new file mode 100644 index 0000000000..4c77d4ccef --- /dev/null +++ b/src/components/UserProfileSettings/UserProfile.tsx @@ -0,0 +1,65 @@ +import Avatar from 'components/Avatar/Avatar'; +import React from 'react'; +import { Button, Card } from 'react-bootstrap'; +import CalendarMonthOutlinedIcon from '@mui/icons-material/CalendarMonthOutlined'; +import { useTranslation } from 'react-i18next'; +import styles from './UserProfileSettings.module.css'; + +interface InterfaceUserProfile { + firstName: string; + lastName: string; + email: string; + image: string; +} + +const UserProfile: React.FC = ({ + firstName, + lastName, + email, + image, +}): JSX.Element => { + const { t } = useTranslation('translation', { + keyPrefix: 'settings', + }); + return ( + <> + +
    +
    {t('profileDetails')}
    +
    + +
    +
    + {image && image !== 'null' ? ( + {`profile + ) : ( + + )} +
    +
    + + {`${firstName}`.charAt(0).toUpperCase() + + `${firstName}`.slice(1)} + + {email} + + + + {t('joined')} 1st May, 2021 + + +
    +
    +
    + +
    +
    +
    + + ); +}; + +export default UserProfile; diff --git a/src/components/UserProfileSettings/UserProfileSettings.module.css b/src/components/UserProfileSettings/UserProfileSettings.module.css new file mode 100644 index 0000000000..603c5a677d --- /dev/null +++ b/src/components/UserProfileSettings/UserProfileSettings.module.css @@ -0,0 +1,76 @@ +.cardHeader { + padding: 1.25rem 1rem 1rem 1rem; + border-bottom: 1px solid var(--bs-gray-200); + display: flex; + justify-content: space-between; + align-items: center; +} + +.cardHeader .cardTitle { + font-size: 1.2rem; + font-weight: 600; +} + +.cardBody { + padding: 1.25rem 1rem 1.5rem 1rem; + display: flex; + flex-direction: column; +} + +.cardLabel { + font-weight: bold; + padding-bottom: 1px; + font-size: 14px; + color: #707070; + margin-bottom: 10px; +} + +.cardControl { + margin-bottom: 20px; +} + +.cardButton { + width: fit-content; +} + +.imgContianer { + margin: 0 2rem 0 0; +} + +.imgContianer img { + height: 120px; + width: 120px; + border-radius: 50%; +} + +.profileDetails { + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-evenly; +} + +@media screen and (max-width: 1280px) and (min-width: 992px) { + .imgContianer { + margin: 1rem auto; + } + .profileContainer { + flex-direction: column; + } +} + +@media screen and (max-width: 992px) { + .profileContainer { + align-items: center; + justify-content: center; + } +} + +@media screen and (max-width: 420px) { + .imgContianer { + margin: 1rem auto; + } + .profileContainer { + flex-direction: column; + } +} diff --git a/src/components/UserUpdate/UserUpdate.module.css b/src/components/UserUpdate/UserUpdate.module.css deleted file mode 100644 index 54cf1c020c..0000000000 --- a/src/components/UserUpdate/UserUpdate.module.css +++ /dev/null @@ -1,93 +0,0 @@ -/* .userupdatediv{ - border: 1px solid #e8e5e5; - box-shadow: 2px 1px #e8e5e5; - padding:25px 16px; - border-radius: 5px; - background:#fdfdfd; -} */ -.settingstitle { - color: #707070; - font-size: 20px; - margin-bottom: 30px; - text-align: center; - margin-top: -10px; -} -.dispflex { - display: flex; - justify-content: flex-start; - margin: 0 auto; -} -.dispbtnflex { - width: 90%; - margin-top: 20px; - display: flex; - margin: 0 30%; -} -.dispflex > div { - width: 50%; - margin-right: 50px; -} - -.radio_buttons > input { - margin-bottom: 20px; - border: none; - box-shadow: none; - padding: 0 0; - border-radius: 5px; - background: none; - width: 50%; -} - -.whitebtn { - margin: 1rem 0 0; - margin-top: 10px; - border: 1px solid #e8e5e5; - box-shadow: 0 2px 2px #e8e5e5; - padding: 10px 20px; - border-radius: 5px; - background: none; - width: 20%; - font-size: 16px; - color: #31bb6b; - outline: none; - font-weight: 600; - cursor: pointer; - float: left; - transition: transform 0.2s, box-shadow 0.2s; -} -.greenregbtn { - margin: 1rem 0 0; - margin-top: 10px; - margin-right: 30px; - border: 1px solid #e8e5e5; - box-shadow: 0 2px 2px #e8e5e5; - padding: 10px 10px; - border-radius: 5px; - background-color: #31bb6b; - width: 20%; - font-size: 16px; - color: white; - outline: none; - font-weight: 600; - cursor: pointer; - transition: transform 0.2s, box-shadow 0.2s; -} -.radio_buttons { - width: 55%; - margin-top: 10px; - display: flex; - color: #707070; - font-weight: 600; - font-size: 14px; -} -.radio_buttons > input { - transform: scale(1.2); -} -.radio_buttons > label { - margin-top: -4px; - margin-left: 0px; - margin-right: 7px; -} -.idtitle { - width: 88%; -} diff --git a/src/components/UserUpdate/UserUpdate.test.tsx b/src/components/UserUpdate/UserUpdate.test.tsx deleted file mode 100644 index e10f4a5b4e..0000000000 --- a/src/components/UserUpdate/UserUpdate.test.tsx +++ /dev/null @@ -1,159 +0,0 @@ -import React from 'react'; -import { act, render, screen } from '@testing-library/react'; -import { MockedProvider } from '@apollo/react-testing'; -import userEvent from '@testing-library/user-event'; -import { I18nextProvider } from 'react-i18next'; -import { BrowserRouter as Router } from 'react-router-dom'; -import UserUpdate from './UserUpdate'; -import { UPDATE_USER_MUTATION } from 'GraphQl/Mutations/mutations'; -import i18nForTest from 'utils/i18nForTest'; -import { USER_DETAILS } from 'GraphQl/Queries/Queries'; -import { StaticMockLink } from 'utils/StaticMockLink'; -import { toast } from 'react-toastify'; - -const MOCKS = [ - { - request: { - query: USER_DETAILS, - variables: { - id: '1', - }, - }, - result: { - data: { - user: { - __typename: 'User', - image: null, - firstName: '', - lastName: '', - email: '', - role: 'SUPERADMIN', - appLanguageCode: 'en', - userType: 'SUPERADMIN', - pluginCreationAllowed: true, - adminApproved: true, - createdAt: '2023-02-18T09:22:27.969Z', - adminFor: [], - createdOrganizations: [], - joinedOrganizations: [], - organizationUserBelongsTo: null, - organizationsBlockedBy: [], - createdEvents: [], - registeredEvents: [], - eventAdmin: [], - membershipRequests: [], - }, - }, - }, - }, - { - request: { - query: UPDATE_USER_MUTATION, - variable: { - firstName: '', - lastName: '', - email: '', - }, - }, - result: { - data: { - users: [ - { - _id: '1', - }, - ], - }, - }, - }, -]; - -const link = new StaticMockLink(MOCKS, true); - -async function wait(ms = 5): Promise { - await act(() => { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); - }); -} - -describe('Testing User Update', () => { - const props = { - key: '123', - id: '1', - toggleStateValue: jest.fn(), - }; - - const formData = { - firstName: 'Ansh', - lastName: 'Goyal', - email: 'ansh@gmail.com', - image: new File(['hello'], 'hello.png', { type: 'image/png' }), - }; - - global.alert = jest.fn(); - - test('should render props and text elements test for the page component', async () => { - render( - - - - - - - - ); - - await wait(); - - userEvent.type( - screen.getByPlaceholderText(/First Name/i), - formData.firstName - ); - userEvent.type( - screen.getByPlaceholderText(/Last Name/i), - formData.lastName - ); - userEvent.type(screen.getByPlaceholderText(/Email/i), formData.email); - userEvent.selectOptions(screen.getByTestId('applangcode'), 'Français'); - userEvent.upload(screen.getByLabelText(/Display Image:/i), formData.image); - await wait(); - - userEvent.click(screen.getByText(/Save Changes/i)); - - expect(screen.getByPlaceholderText(/First Name/i)).toHaveValue( - formData.firstName - ); - expect(screen.getByPlaceholderText(/Last Name/i)).toHaveValue( - formData.lastName - ); - expect(screen.getByPlaceholderText(/Email/i)).toHaveValue(formData.email); - - expect(screen.getByText(/Cancel/i)).toBeTruthy(); - expect(screen.getByPlaceholderText(/First Name/i)).toBeInTheDocument(); - expect(screen.getByPlaceholderText(/Last Name/i)).toBeInTheDocument(); - expect(screen.getByPlaceholderText(/Email/i)).toBeInTheDocument(); - expect(screen.getByText(/Display Image/i)).toBeInTheDocument(); - }); - test('should display warnings for blank form submission', async () => { - jest.spyOn(toast, 'warning'); - - render( - - - - - - - - ); - - await wait(); - - userEvent.click(screen.getByText(/Save Changes/i)); - - expect(toast.warning).toHaveBeenCalledWith('First Name cannot be blank!'); - expect(toast.warning).toHaveBeenCalledWith('Last Name cannot be blank!'); - expect(toast.warning).toHaveBeenCalledWith('Email cannot be blank!'); - }); -}); diff --git a/src/components/UserUpdate/UserUpdate.tsx b/src/components/UserUpdate/UserUpdate.tsx deleted file mode 100644 index a58740b965..0000000000 --- a/src/components/UserUpdate/UserUpdate.tsx +++ /dev/null @@ -1,257 +0,0 @@ -import React from 'react'; -import { useMutation, useQuery } from '@apollo/client'; -import { UPDATE_USER_MUTATION } from 'GraphQl/Mutations/mutations'; -import { useTranslation } from 'react-i18next'; -import Button from 'react-bootstrap/Button'; -import styles from './UserUpdate.module.css'; -import convertToBase64 from 'utils/convertToBase64'; -import { USER_DETAILS } from 'GraphQl/Queries/Queries'; -import { useLocation } from 'react-router-dom'; - -import { languages } from 'utils/languages'; -import { toast } from 'react-toastify'; -import { errorHandler } from 'utils/errorHandler'; -import { Form } from 'react-bootstrap'; -import Loader from 'components/Loader/Loader'; - -interface InterfaceUserUpdateProps { - id: string; - toggleStateValue: () => void; -} - -// eslint-disable-next-line @typescript-eslint/no-unused-vars -const UserUpdate: React.FC = ({ - id, - toggleStateValue, -}): JSX.Element => { - const location = useLocation(); - const currentUrl = location.state?.id || localStorage.getItem('id') || id; - const { t } = useTranslation('translation', { - keyPrefix: 'userUpdate', - }); - const [formState, setFormState] = React.useState({ - firstName: '', - lastName: '', - email: '', - password: '', - applangcode: '', - file: '', - }); - - const [updateUser] = useMutation(UPDATE_USER_MUTATION); - - const { - data: data, - loading: loading, - error: error, - } = useQuery(USER_DETAILS, { - variables: { id: currentUrl }, // For testing we are sending the id as a prop - }); - React.useEffect(() => { - if (data) { - setFormState({ - ...formState, - firstName: data?.user?.firstName, - lastName: data?.user?.lastName, - email: data?.user?.email, - }); - } - }, [data]); - - if (loading) { - return ; - } - - /* istanbul ignore next */ - if (error) { - window.location.assign(`/orgsettings/id=${currentUrl}`); - } - - const loginLink = async (): Promise => { - try { - const firstName = formState.firstName; - const lastName = formState.lastName; - const email = formState.email; - const file = formState.file; - let toSubmit = true; - if (firstName.trim().length == 0 || !firstName) { - toast.warning('First Name cannot be blank!'); - toSubmit = false; - } - if (lastName.trim().length == 0 || !lastName) { - toast.warning('Last Name cannot be blank!'); - toSubmit = false; - } - if (email.trim().length == 0 || !email) { - toast.warning('Email cannot be blank!'); - toSubmit = false; - } - if (!toSubmit) return; - const { data } = await updateUser({ - variables: { - //Currently on these fields are supported by the api - firstName, - lastName, - email, - file, - }, - }); - /* istanbul ignore next */ - if (data) { - setFormState({ - firstName: '', - lastName: '', - email: '', - password: '', - applangcode: '', - file: '', - }); - localStorage.setItem('FirstName', firstName); - localStorage.setItem('LastName', lastName); - localStorage.setItem('Email', email); - localStorage.setItem('UserImage', file); - toast.success('Successful updated'); - - toggleStateValue(); - } - } catch (error: any) { - /* istanbul ignore next */ - errorHandler(t, error); - } - }; - - /* istanbul ignore next */ - const cancelUpdate = (): void => { - toggleStateValue(); - }; - - return ( - <> -
    -
    - {/*

    Update Your Details

    */} -
    -
    - - { - setFormState({ - ...formState, - firstName: e.target.value, - }); - }} - /> -
    -
    -
    -
    - - { - setFormState({ - ...formState, - lastName: e.target.value, - }); - }} - /> -
    -
    -
    -
    - - { - setFormState({ - ...formState, - email: e.target.value, - }); - }} - /> -
    -
    - -
    -
    - -
    -
    - -
    - - -
    -
    -
    - - ); -}; -export default UserUpdate; diff --git a/src/components/UsersTableItem/UserTableItem.test.tsx b/src/components/UsersTableItem/UserTableItem.test.tsx index 0e67a02022..e89288ff28 100644 --- a/src/components/UsersTableItem/UserTableItem.test.tsx +++ b/src/components/UsersTableItem/UserTableItem.test.tsx @@ -8,8 +8,11 @@ import i18nForTest from 'utils/i18nForTest'; import type { InterfaceQueryUserListItem } from 'utils/interfaces'; import { MOCKS } from './UserTableItemMocks'; import UsersTableItem from './UsersTableItem'; - +import { BrowserRouter } from 'react-router-dom'; const link = new StaticMockLink(MOCKS, true); +import useLocalStorage from 'utils/useLocalstorage'; + +const { setItem } = useLocalStorage(); async function wait(ms = 100): Promise { await act(() => { @@ -35,18 +38,16 @@ Object.defineProperty(window, 'location', { writable: true, }); -const mockHistoryPush = jest.fn(); +const mockNavgatePush = jest.fn(); jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), - useHistory: () => ({ - push: mockHistoryPush, - }), + useNavigate: () => mockNavgatePush, })); beforeEach(() => { - localStorage.setItem('UserType', 'SUPERADMIN'); - localStorage.setItem('id', '123'); + setItem('SuperAdmin', true); + setItem('id', '123'); }); afterEach(() => { @@ -70,79 +71,124 @@ describe('Testing User Table Item', () => { resetAndRefetch: () => void; } = { user: { - _id: '123', - firstName: 'John', - lastName: 'Doe', - image: null, - email: 'john@example.com', - userType: 'SUPERADMIN', - adminApproved: true, - adminFor: [ - { - _id: 'abc', - }, - ], - createdAt: '2023-09-29T15:39:36.355Z', - organizationsBlockedBy: [ - { - _id: 'xyz', - name: 'XYZ', - image: null, - location: 'Jamaica', - createdAt: '2023-01-29T15:39:36.355Z', - creator: { - _id: '123', - firstName: 'John', - lastName: 'Doe', + user: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + createdAt: '2023-09-29T15:39:36.355Z', + organizationsBlockedBy: [ + { + _id: 'xyz', + name: 'XYZ', image: null, - email: 'john@example.com', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '2023-01-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, }, - }, - { - _id: 'mno', - name: 'MNO', - image: null, - location: 'Jamaica', - createdAt: '2023-01-29T15:39:36.355Z', - creator: { - _id: '123', - firstName: 'John', - lastName: 'Doe', + { + _id: 'mno', + name: 'MNO', image: null, - email: 'john@example.com', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '2023-01-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, }, - }, - ], - joinedOrganizations: [ - { - _id: 'abc', - name: 'Joined Organization 1', - image: null, - location: 'Jamaica', - createdAt: '2023-06-29T15:39:36.355Z', - creator: { - _id: '123', - firstName: 'John', - lastName: 'Doe', + ], + joinedOrganizations: [ + { + _id: 'abc', + name: 'Joined Organization 1', image: null, - email: 'john@example.com', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '2023-06-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, }, - }, - { - _id: 'def', - name: 'Joined Organization 2', - image: null, - location: 'Jamaica', - createdAt: '2023-07-29T15:39:36.355Z', - creator: { - _id: '123', - firstName: 'John', - lastName: 'Doe', + { + _id: 'def', + name: 'Joined Organization 2', image: null, - email: 'john@example.com', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '2023-07-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, }, - }, - ], + ], + registeredEvents: [], + membershipRequests: [], + }, + appUserProfile: { + _id: '123', + isSuperAdmin: true, + createdOrganizations: [], + createdEvents: [], + eventAdmin: [], + adminFor: [ + { + _id: 'abc', + }, + ], + }, }, index: 0, loggedInUserId: '123', @@ -151,23 +197,21 @@ describe('Testing User Table Item', () => { render( - - - - + + + + + + , ); await wait(); expect(screen.getByText(/1/i)).toBeInTheDocument(); expect(screen.getByText(/John Doe/i)).toBeInTheDocument(); expect(screen.getByText(/john@example.com/i)).toBeInTheDocument(); - expect(screen.getByTestId(`changeRole${123}`)).toBeInTheDocument(); - expect(screen.getByTestId(`changeRole${123}`)).toHaveValue( - `SUPERADMIN?${123}` - ); expect(screen.getByTestId(`showJoinedOrgsBtn${123}`)).toBeInTheDocument(); expect( - screen.getByTestId(`showBlockedByOrgsBtn${123}`) + screen.getByTestId(`showBlockedByOrgsBtn${123}`), ).toBeInTheDocument(); }); @@ -179,21 +223,30 @@ describe('Testing User Table Item', () => { resetAndRefetch: () => void; } = { user: { - _id: '123', - firstName: 'John', - lastName: 'Doe', - image: null, - email: 'john@example.com', - userType: 'SUPERADMIN', - adminApproved: true, - adminFor: [ - { - _id: 'abc', - }, - ], - createdAt: '2023-09-29T15:39:36.355Z', - organizationsBlockedBy: [], - joinedOrganizations: [], + user: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + createdAt: '2023-09-29T15:39:36.355Z', + organizationsBlockedBy: [], + joinedOrganizations: [], + registeredEvents: [], + membershipRequests: [], + }, + appUserProfile: { + _id: '123', + isSuperAdmin: true, + createdOrganizations: [], + createdEvents: [], + eventAdmin: [], + adminFor: [ + { + _id: 'abc', + }, + ], + }, }, index: 0, loggedInUserId: '123', @@ -204,32 +257,32 @@ describe('Testing User Table Item', () => { - + , ); await wait(); const showJoinedOrgsBtn = screen.getByTestId(`showJoinedOrgsBtn${123}`); // 123 is userId const showBlockedByOrgsBtn = screen.getByTestId( - `showBlockedByOrgsBtn${123}` + `showBlockedByOrgsBtn${123}`, ); // 123 is userId // Open JoinedOrgs Modal -> Expect modal to contain text and no search box -> Close Modal fireEvent.click(showJoinedOrgsBtn); expect( - screen.queryByTestId(`searchByNameJoinedOrgs`) + screen.queryByTestId(`searchByNameJoinedOrgs`), ).not.toBeInTheDocument(); expect( - screen.getByText(/John Doe has not joined any organization/i) + screen.getByText(/John Doe has not joined any organization/i), ).toBeInTheDocument(); fireEvent.click(screen.getByTestId(`closeJoinedOrgsBtn${123}`)); // Open BlockedByOrgs Modal -> Expect modal to contain text and no search box -> Close Modal fireEvent.click(showBlockedByOrgsBtn); expect( - screen.queryByTestId(`searchByNameOrgsBlockedBy`) + screen.queryByTestId(`searchByNameOrgsBlockedBy`), ).not.toBeInTheDocument(); expect( - screen.getByText(/John Doe is not blocked by any organization/i) + screen.getByText(/John Doe is not blocked by any organization/i), ).toBeInTheDocument(); fireEvent.click(screen.getByTestId(`closeBlockedByOrgsBtn${123}`)); }); @@ -242,81 +295,124 @@ describe('Testing User Table Item', () => { resetAndRefetch: () => void; } = { user: { - _id: '123', - firstName: 'John', - lastName: 'Doe', - image: null, - email: 'john@example.com', - userType: 'SUPERADMIN', - adminApproved: true, - adminFor: [ - { - _id: 'abc', - }, - ], - createdAt: '2022-09-29T15:39:36.355Z', - organizationsBlockedBy: [ - { - _id: 'xyz', - name: 'Blocked Organization 1', - image: null, - location: 'Jamaica', - createdAt: '2023-08-29T15:39:36.355Z', - creator: { - _id: '123', - firstName: 'John', - lastName: 'Doe', + user: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + createdAt: '2023-09-29T15:39:36.355Z', + organizationsBlockedBy: [ + { + _id: 'xyz', + name: 'XYZ', image: null, - email: 'john@example.com', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '2023-01-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, }, - }, - { - _id: 'mno', - name: 'Blocked Organization 2', - image: null, - location: 'Jamaica', - createdAt: '2023-09-29T15:39:36.355Z', - creator: { - _id: '123', - firstName: 'John', - lastName: 'Doe', + { + _id: 'mno', + name: 'MNO', image: null, - email: 'john@example.com', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '2023-01-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, }, - }, - ], - joinedOrganizations: [ - { - _id: 'abc', - name: 'Joined Organization 1', - image: - 'https://api.dicebear.com/5.x/initials/svg?seed=Joined%20Organization%201', - location: 'Jamaica', - createdAt: '2023-08-29T15:39:36.355Z', - creator: { - _id: '123', - firstName: 'John', - lastName: 'Doe', - image: - 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', - email: 'john@example.com', + ], + joinedOrganizations: [ + { + _id: 'abc', + name: 'Joined Organization 1', + image: null, + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '2023-06-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, }, - }, - { - _id: 'def', - name: 'Joined Organization 2', - image: null, - location: 'Jamaica', - createdAt: '2023-09-19T15:39:36.355Z', - creator: { - _id: '123', - firstName: 'John', - lastName: 'Doe', + { + _id: 'def', + name: 'Joined Organization 2', image: null, - email: 'john@example.com', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '2023-07-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, }, - }, - ], + ], + registeredEvents: [], + membershipRequests: [], + }, + appUserProfile: { + _id: '123', + isSuperAdmin: true, + createdOrganizations: [], + createdEvents: [], + eventAdmin: [], + adminFor: [ + { + _id: 'abc', + }, + ], + }, }, index: 0, loggedInUserId: '123', @@ -328,7 +424,7 @@ describe('Testing User Table Item', () => { - + , ); await wait(); @@ -345,13 +441,13 @@ describe('Testing User Table Item', () => { charCode: 27, }); expect( - screen.queryByRole('dialog')?.className.includes('show') + screen.queryByRole('dialog')?.className.includes('show'), ).toBeFalsy(); fireEvent.click(showJoinedOrgsBtn); // Close using close button and reopen fireEvent.click(screen.getByTestId(`closeJoinedOrgsBtn${123}`)); expect( - screen.queryByRole('dialog')?.className.includes('show') + screen.queryByRole('dialog')?.className.includes('show'), ).toBeFalsy(); fireEvent.click(showJoinedOrgsBtn); @@ -361,38 +457,47 @@ describe('Testing User Table Item', () => { expect(inputBox).toBeInTheDocument(); expect(screen.getByText(/Joined Organization 1/i)).toBeInTheDocument(); expect(screen.getByText(/Joined Organization 2/i)).toBeInTheDocument(); - expect(screen.getAllByText(/Jamaica/i)).toHaveLength(2); - expect(screen.getByText(/29-08-2023/i)).toBeInTheDocument(); - expect(screen.getByText(/19-09-2023/i)).toBeInTheDocument(); + const elementsWithKingston = screen.getAllByText(/Kingston/i); + elementsWithKingston.forEach((element) => { + expect(element).toBeInTheDocument(); + }); + expect(screen.getByText(/29-06-2023/i)).toBeInTheDocument(); + expect(screen.getByText(/29-07-2023/i)).toBeInTheDocument(); expect(screen.getByTestId('removeUserFromOrgBtnabc')).toBeInTheDocument(); expect(screen.getByTestId('removeUserFromOrgBtndef')).toBeInTheDocument(); - expect(screen.getByTestId(`changeRoleInOrgabc`)).toHaveValue('ADMIN?abc'); - expect(screen.getByTestId(`changeRoleInOrgdef`)).toHaveValue('USER?def'); // Search for Joined Organization 1 - fireEvent.change(inputBox, { target: { value: 'Joined Organization 1' } }); + const searchBtn = screen.getByTestId(`searchBtnJoinedOrgs`); + fireEvent.keyUp(inputBox, { + target: { value: 'Joined Organization 1' }, + }); + fireEvent.click(searchBtn); expect(screen.getByText(/Joined Organization 1/i)).toBeInTheDocument(); expect( - screen.queryByText(/Joined Organization 2/i) + screen.queryByText(/Joined Organization 2/i), ).not.toBeInTheDocument(); // Search for an Organization which does not exist - fireEvent.change(inputBox, { target: { value: 'Joined Organization 3' } }); + fireEvent.keyUp(inputBox, { + key: 'Enter', + target: { value: 'Joined Organization 3' }, + }); expect( - screen.getByText(`No results found for "Joined Organization 3"`) + screen.getByText(`No results found for "Joined Organization 3"`), ).toBeInTheDocument(); // Now clear the search box - fireEvent.change(inputBox, { target: { value: '' } }); - + fireEvent.keyUp(inputBox, { key: 'Enter', target: { value: '' } }); + fireEvent.keyUp(inputBox, { target: { value: '' } }); + fireEvent.click(searchBtn); // Click on Creator Link fireEvent.click(screen.getByTestId(`creatorabc`)); expect(toast.success).toBeCalledWith('Profile Page Coming Soon !'); // Click on Organization Link fireEvent.click(screen.getByText(/Joined Organization 1/i)); - expect(window.location.replace).toBeCalledWith('/orgdash/id=abc'); - expect(mockHistoryPush).toBeCalledWith('/orgdash/id=abc'); + expect(window.location.replace).toBeCalledWith('/orgdash/abc'); + expect(mockNavgatePush).toBeCalledWith('/orgdash/abc'); fireEvent.click(screen.getByTestId(`closeJoinedOrgsBtn${123}`)); }); @@ -404,84 +509,124 @@ describe('Testing User Table Item', () => { resetAndRefetch: () => void; } = { user: { - _id: '123', - firstName: 'John', - lastName: 'Doe', - image: 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', - email: 'john@example.com', - userType: 'SUPERADMIN', - adminApproved: true, - adminFor: [ - { - _id: 'abc', - }, - { - _id: 'xyz', - }, - ], - createdAt: '2022-09-29T15:39:36.355Z', - organizationsBlockedBy: [ - { - _id: 'xyz', - name: 'Blocked Organization 1', - image: - 'https://api.dicebear.com/5.x/initials/svg?seed=Blocked%20Organization%201', - location: 'Jamaica', - createdAt: '2023-08-29T15:39:36.355Z', - creator: { - _id: '123', - firstName: 'John', - lastName: 'Doe', - image: - 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', - email: 'john@example.com', + user: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + createdAt: '2023-09-29T15:39:36.355Z', + organizationsBlockedBy: [ + { + _id: 'xyz', + name: 'XYZ', + image: null, + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '2023-01-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, }, - }, - { - _id: 'mno', - name: 'Blocked Organization 2', - image: null, - location: 'Jamaica', - createdAt: '2023-09-29T15:39:36.355Z', - creator: { - _id: '123', - firstName: 'John', - lastName: 'Doe', + { + _id: 'mno', + name: 'MNO', image: null, - email: 'john@example.com', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '2023-03-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, }, - }, - ], - joinedOrganizations: [ - { - _id: 'abc', - name: 'Joined Organization 1', - image: null, - location: 'Jamaica', - createdAt: '2023-08-29T15:39:36.355Z', - creator: { - _id: '123', - firstName: 'John', - lastName: 'Doe', + ], + joinedOrganizations: [ + { + _id: 'abc', + name: 'Joined Organization 1', image: null, - email: 'john@example.com', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '2023-06-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, }, - }, - { - _id: 'def', - name: 'Joined Organization 2', - image: null, - location: 'Jamaica', - createdAt: '2023-09-19T15:39:36.355Z', - creator: { - _id: '123', - firstName: 'John', - lastName: 'Doe', + { + _id: 'def', + name: 'Joined Organization 2', image: null, - email: 'john@example.com', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '2023-07-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, + }, + ], + registeredEvents: [], + membershipRequests: [], + }, + appUserProfile: { + _id: '123', + isSuperAdmin: true, + createdOrganizations: [], + createdEvents: [], + eventAdmin: [], + adminFor: [ + { + _id: 'xyz', }, - }, - ], + ], + }, }, index: 0, loggedInUserId: '123', @@ -490,15 +635,17 @@ describe('Testing User Table Item', () => { render( - - - - + + + + + + , ); await wait(); const showBlockedByOrgsBtn = screen.getByTestId( - `showBlockedByOrgsBtn${123}` + `showBlockedByOrgsBtn${123}`, ); expect(showBlockedByOrgsBtn).toBeInTheDocument(); fireEvent.click(showBlockedByOrgsBtn); @@ -512,13 +659,13 @@ describe('Testing User Table Item', () => { charCode: 27, }); expect( - screen.queryByRole('dialog')?.className.includes('show') + screen.queryByRole('dialog')?.className.includes('show'), ).toBeFalsy(); fireEvent.click(showBlockedByOrgsBtn); // Close using close button and reopen fireEvent.click(screen.getByTestId(`closeBlockedByOrgsBtn${123}`)); expect( - screen.queryByRole('dialog')?.className.includes('show') + screen.queryByRole('dialog')?.className.includes('show'), ).toBeFalsy(); fireEvent.click(showBlockedByOrgsBtn); @@ -527,39 +674,47 @@ describe('Testing User Table Item', () => { const inputBox = screen.getByTestId(`searchByNameOrgsBlockedBy`); expect(inputBox).toBeInTheDocument(); - expect(screen.getByText(/Blocked Organization 1/i)).toBeInTheDocument(); - expect(screen.getByText(/Blocked Organization 2/i)).toBeInTheDocument(); - expect(screen.getAllByText(/Jamaica/i)).toHaveLength(2); - expect(screen.getByText(/29-08-2023/i)).toBeInTheDocument(); - expect(screen.getByText(/29-09-2023/i)).toBeInTheDocument(); + expect(screen.getByText(/XYZ/i)).toBeInTheDocument(); + expect(screen.getByText(/MNO/i)).toBeInTheDocument(); + const elementsWithKingston = screen.getAllByText(/Kingston/i); + elementsWithKingston.forEach((element) => { + expect(element).toBeInTheDocument(); + }); + expect(screen.getByText(/29-01-2023/i)).toBeInTheDocument(); + expect(screen.getByText(/29-03-2023/i)).toBeInTheDocument(); expect(screen.getByTestId('removeUserFromOrgBtnxyz')).toBeInTheDocument(); expect(screen.getByTestId('removeUserFromOrgBtnmno')).toBeInTheDocument(); - expect(screen.getByTestId(`changeRoleInOrgxyz`)).toHaveValue('ADMIN?xyz'); - expect(screen.getByTestId(`changeRoleInOrgmno`)).toHaveValue('USER?mno'); // Click on Creator Link fireEvent.click(screen.getByTestId(`creatorxyz`)); expect(toast.success).toBeCalledWith('Profile Page Coming Soon !'); // Search for Blocked Organization 1 - fireEvent.change(inputBox, { target: { value: 'Blocked Organization 1' } }); - expect(screen.getByText(/Blocked Organization 1/i)).toBeInTheDocument(); - expect( - screen.queryByText(/Blocked Organization 2/i) - ).not.toBeInTheDocument(); + const searchBtn = screen.getByTestId(`searchBtnOrgsBlockedBy`); + fireEvent.keyUp(inputBox, { + target: { value: 'XYZ' }, + }); + fireEvent.click(searchBtn); + expect(screen.getByText(/XYZ/i)).toBeInTheDocument(); + expect(screen.queryByText(/MNO/i)).not.toBeInTheDocument(); // Search for an Organization which does not exist - fireEvent.change(inputBox, { target: { value: 'Blocked Organization 3' } }); + fireEvent.keyUp(inputBox, { + key: 'Enter', + target: { value: 'Blocked Organization 3' }, + }); expect( - screen.getByText(`No results found for "Blocked Organization 3"`) + screen.getByText(`No results found for "Blocked Organization 3"`), ).toBeInTheDocument(); // Now clear the search box - fireEvent.change(inputBox, { target: { value: '' } }); + fireEvent.keyUp(inputBox, { key: 'Enter', target: { value: '' } }); + fireEvent.keyUp(inputBox, { target: { value: '' } }); + fireEvent.click(searchBtn); // Click on Organization Link - fireEvent.click(screen.getByText(/Blocked Organization 1/i)); - expect(window.location.replace).toBeCalledWith('/orgdash/id=xyz'); - expect(mockHistoryPush).toBeCalledWith('/orgdash/id=xyz'); + fireEvent.click(screen.getByText(/XYZ/i)); + expect(window.location.replace).toBeCalledWith('/orgdash/xyz'); + expect(mockNavgatePush).toBeCalledWith('/orgdash/xyz'); fireEvent.click(screen.getByTestId(`closeBlockedByOrgsBtn${123}`)); }); @@ -571,84 +726,124 @@ describe('Testing User Table Item', () => { resetAndRefetch: () => void; } = { user: { - _id: '123', - firstName: 'John', - lastName: 'Doe', - image: 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', - email: 'john@example.com', - userType: 'SUPERADMIN', - adminApproved: true, - adminFor: [ - { - _id: 'abc', - }, - { - _id: 'xyz', - }, - ], - createdAt: '2022-09-29T15:39:36.355Z', - organizationsBlockedBy: [ - { - _id: 'xyz', - name: 'Blocked Organization 1', - image: - 'https://api.dicebear.com/5.x/initials/svg?seed=Blocked%20Organization%201', - location: 'Jamaica', - createdAt: '2023-08-29T15:39:36.355Z', - creator: { - _id: '123', - firstName: 'John', - lastName: 'Doe', - image: - 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', - email: 'john@example.com', + user: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + createdAt: '2023-09-29T15:39:36.355Z', + organizationsBlockedBy: [ + { + _id: 'xyz', + name: 'XYZ', + image: null, + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '2023-01-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, }, - }, - { - _id: 'mno', - name: 'Blocked Organization 2', - image: null, - location: 'Jamaica', - createdAt: '2023-09-29T15:39:36.355Z', - creator: { - _id: '123', - firstName: 'John', - lastName: 'Doe', + { + _id: 'mno', + name: 'MNO', image: null, - email: 'john@example.com', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '2023-01-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, }, - }, - ], - joinedOrganizations: [ - { - _id: 'abc', - name: 'Joined Organization 1', - image: null, - location: 'Jamaica', - createdAt: '2023-08-29T15:39:36.355Z', - creator: { - _id: '123', - firstName: 'John', - lastName: 'Doe', + ], + joinedOrganizations: [ + { + _id: 'abc', + name: 'Joined Organization 1', image: null, - email: 'john@example.com', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '2023-06-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, }, - }, - { - _id: 'def', - name: 'Joined Organization 2', - image: null, - location: 'Jamaica', - createdAt: '2023-09-19T15:39:36.355Z', - creator: { - _id: '123', - firstName: 'John', - lastName: 'Doe', + { + _id: 'def', + name: 'Joined Organization 2', image: null, - email: 'john@example.com', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '2023-07-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, }, - }, - ], + ], + registeredEvents: [], + membershipRequests: [], + }, + appUserProfile: { + _id: '123', + isSuperAdmin: true, + createdOrganizations: [], + createdEvents: [], + eventAdmin: [], + adminFor: [ + { + _id: 'abc', + }, + ], + }, }, index: 0, loggedInUserId: '123', @@ -657,10 +852,12 @@ describe('Testing User Table Item', () => { render( - - - - + + + + + + , ); await wait(); @@ -682,7 +879,7 @@ describe('Testing User Table Item', () => { expect( screen .queryAllByRole('dialog') - .some((el) => el.className.includes('show')) + .some((el) => el.className.includes('show')), ).toBeTruthy(); fireEvent.click(showJoinedOrgsBtn); // Close using close button and reopen @@ -690,7 +887,7 @@ describe('Testing User Table Item', () => { expect( screen .queryAllByRole('dialog') - .some((el) => el.className.includes('show')) + .some((el) => el.className.includes('show')), ).toBeTruthy(); fireEvent.click(showJoinedOrgsBtn); @@ -709,84 +906,129 @@ describe('Testing User Table Item', () => { resetAndRefetch: () => void; } = { user: { - _id: '123', - firstName: 'John', - lastName: 'Doe', - image: 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', - email: 'john@example.com', - userType: 'SUPERADMIN', - adminApproved: true, - adminFor: [ - { - _id: 'abc', - }, - { - _id: 'xyz', - }, - ], - createdAt: '2022-09-29T15:39:36.355Z', - organizationsBlockedBy: [ - { - _id: 'xyz', - name: 'Blocked Organization 1', - image: - 'https://api.dicebear.com/5.x/initials/svg?seed=Blocked%20Organization%201', - location: 'Jamaica', - createdAt: '2023-08-29T15:39:36.355Z', - creator: { - _id: '123', - firstName: 'John', - lastName: 'Doe', + user: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', + email: 'john@example.com', + createdAt: '2022-09-29T15:39:36.355Z', + organizationsBlockedBy: [ + { + _id: 'xyz', + name: 'Blocked Organization 1', image: - 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', - email: 'john@example.com', + 'https://api.dicebear.com/5.x/initials/svg?seed=Blocked%20Organization%201', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '2023-08-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: + 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', + email: 'john@example.com', + }, }, - }, - { - _id: 'mno', - name: 'Blocked Organization 2', - image: null, - location: 'Jamaica', - createdAt: '2023-09-29T15:39:36.355Z', - creator: { - _id: '123', - firstName: 'John', - lastName: 'Doe', + { + _id: 'mno', + name: 'Blocked Organization 2', image: null, - email: 'john@example.com', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '2023-09-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, }, - }, - ], - joinedOrganizations: [ - { - _id: 'abc', - name: 'Joined Organization 1', - image: null, - location: 'Jamaica', - createdAt: '2023-08-29T15:39:36.355Z', - creator: { - _id: '123', - firstName: 'John', - lastName: 'Doe', + ], + joinedOrganizations: [ + { + _id: 'abc', + name: 'Joined Organization 1', image: null, - email: 'john@example.com', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '2023-08-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, }, - }, - { - _id: 'def', - name: 'Joined Organization 2', - image: null, - location: 'Jamaica', - createdAt: '2023-09-19T15:39:36.355Z', - creator: { - _id: '123', - firstName: 'John', - lastName: 'Doe', + { + _id: 'def', + name: 'Joined Organization 2', image: null, - email: 'john@example.com', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '2023-09-19T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + }, + }, + ], + registeredEvents: [], + membershipRequests: [], + }, + appUserProfile: { + _id: '123', + isSuperAdmin: true, + createdOrganizations: [], + createdEvents: [], + eventAdmin: [], + adminFor: [ + { + _id: 'abc', + }, + { + _id: 'xyz', }, - }, - ], + ], + }, }, index: 0, loggedInUserId: '123', @@ -795,15 +1037,17 @@ describe('Testing User Table Item', () => { render( - - - - + + + + + + , ); await wait(); const showBlockedByOrgsBtn = screen.getByTestId( - `showBlockedByOrgsBtn${123}` + `showBlockedByOrgsBtn${123}`, ); expect(showBlockedByOrgsBtn).toBeInTheDocument(); fireEvent.click(showBlockedByOrgsBtn); @@ -822,7 +1066,7 @@ describe('Testing User Table Item', () => { expect( screen .queryAllByRole('dialog') - .some((el) => el.className.includes('show')) + .some((el) => el.className.includes('show')), ).toBeTruthy(); fireEvent.click(showBlockedByOrgsBtn); // Close using close button and reopen @@ -830,7 +1074,7 @@ describe('Testing User Table Item', () => { expect( screen .queryAllByRole('dialog') - .some((el) => el.className.includes('show')) + .some((el) => el.className.includes('show')), ).toBeTruthy(); fireEvent.click(showBlockedByOrgsBtn); @@ -840,215 +1084,4 @@ describe('Testing User Table Item', () => { fireEvent.click(confirmRemoveBtn); }); - - test('Should be able to change userType of a user if not self', async () => { - const props: { - user: InterfaceQueryUserListItem; - index: number; - loggedInUserId: string; - resetAndRefetch: () => void; - } = { - user: { - _id: '123', - firstName: 'John', - lastName: 'Doe', - image: 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', - email: 'john@example.com', - userType: 'USER', - adminApproved: true, - adminFor: [ - { - _id: 'abc', - }, - { - _id: 'xyz', - }, - ], - createdAt: '2022-09-29T15:39:36.355Z', - organizationsBlockedBy: [ - { - _id: 'xyz', - name: 'Blocked Organization 1', - image: - 'https://api.dicebear.com/5.x/initials/svg?seed=Blocked%20Organization%201', - location: 'Jamaica', - createdAt: '2023-08-29T15:39:36.355Z', - creator: { - _id: '123', - firstName: 'John', - lastName: 'Doe', - image: - 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', - email: 'john@example.com', - }, - }, - { - _id: 'mno', - name: 'Blocked Organization 2', - image: null, - location: 'Jamaica', - createdAt: '2023-09-29T15:39:36.355Z', - creator: { - _id: '123', - firstName: 'John', - lastName: 'Doe', - image: null, - email: 'john@example.com', - }, - }, - ], - joinedOrganizations: [ - { - _id: 'abc', - name: 'Joined Organization 1', - image: null, - location: 'Jamaica', - createdAt: '2023-08-29T15:39:36.355Z', - creator: { - _id: '123', - firstName: 'John', - lastName: 'Doe', - image: null, - email: 'john@example.com', - }, - }, - { - _id: 'def', - name: 'Joined Organization 2', - image: null, - location: 'Jamaica', - createdAt: '2023-09-19T15:39:36.355Z', - creator: { - _id: '123', - firstName: 'John', - lastName: 'Doe', - image: null, - email: 'john@example.com', - }, - }, - ], - }, - index: 0, - loggedInUserId: '456', - resetAndRefetch: resetAndRefetchMock, - }; - - render( - - - - - - ); - - await wait(); - fireEvent.select(screen.getByTestId(`changeRole123`), { - target: { value: 'ADMIN?123' }, - }); - }); - - test('Should be not able to change userType of self', async () => { - const props: { - user: InterfaceQueryUserListItem; - index: number; - loggedInUserId: string; - resetAndRefetch: () => void; - } = { - user: { - _id: '123', - firstName: 'John', - lastName: 'Doe', - image: 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', - email: 'john@example.com', - userType: 'ADMIN', - adminApproved: true, - adminFor: [ - { - _id: 'abc', - }, - { - _id: 'xyz', - }, - ], - createdAt: '2022-09-29T15:39:36.355Z', - organizationsBlockedBy: [ - { - _id: 'xyz', - name: 'Blocked Organization 1', - image: - 'https://api.dicebear.com/5.x/initials/svg?seed=Blocked%20Organization%201', - location: 'Jamaica', - createdAt: '2023-08-29T15:39:36.355Z', - creator: { - _id: '123', - firstName: 'John', - lastName: 'Doe', - image: - 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', - email: 'john@example.com', - }, - }, - { - _id: 'mno', - name: 'Blocked Organization 2', - image: null, - location: 'Jamaica', - createdAt: '2023-09-29T15:39:36.355Z', - creator: { - _id: '123', - firstName: 'John', - lastName: 'Doe', - image: null, - email: 'john@example.com', - }, - }, - ], - joinedOrganizations: [ - { - _id: 'abc', - name: 'Joined Organization 1', - image: null, - location: 'Jamaica', - createdAt: '2023-08-29T15:39:36.355Z', - creator: { - _id: '123', - firstName: 'John', - lastName: 'Doe', - image: null, - email: 'john@example.com', - }, - }, - { - _id: 'def', - name: 'Joined Organization 2', - image: null, - location: 'Jamaica', - createdAt: '2023-09-19T15:39:36.355Z', - creator: { - _id: '123', - firstName: 'John', - lastName: 'Doe', - image: null, - email: 'john@example.com', - }, - }, - ], - }, - index: 0, - loggedInUserId: '123', - resetAndRefetch: resetAndRefetchMock, - }; - - render( - - - - - - ); - - await wait(); - expect(screen.getByTestId(`changeRole123`)).toBeDisabled(); - expect(screen.getByTestId(`changeRole123`)).toHaveValue('ADMIN?123'); - }); }); diff --git a/src/components/UsersTableItem/UserTableItemMocks.ts b/src/components/UsersTableItem/UserTableItemMocks.ts index 5f81c8cfe9..02c430f959 100644 --- a/src/components/UsersTableItem/UserTableItemMocks.ts +++ b/src/components/UsersTableItem/UserTableItemMocks.ts @@ -1,28 +1,9 @@ import { REMOVE_MEMBER_MUTATION, - UPDATE_USERTYPE_MUTATION, UPDATE_USER_ROLE_IN_ORG_MUTATION, } from 'GraphQl/Mutations/mutations'; export const MOCKS = [ - { - request: { - query: UPDATE_USERTYPE_MUTATION, - variables: { - id: '123', - userType: 'ADMIN', - }, - }, - result: { - data: { - updateUserType: { - data: { - id: '123', - }, - }, - }, - }, - }, { request: { query: REMOVE_MEMBER_MUTATION, diff --git a/src/components/UsersTableItem/UsersTableItem.tsx b/src/components/UsersTableItem/UsersTableItem.tsx index dbf51e809a..507a85316d 100644 --- a/src/components/UsersTableItem/UsersTableItem.tsx +++ b/src/components/UsersTableItem/UsersTableItem.tsx @@ -2,18 +2,18 @@ import { useMutation } from '@apollo/client'; import { Search } from '@mui/icons-material'; import { REMOVE_MEMBER_MUTATION, - UPDATE_USERTYPE_MUTATION, UPDATE_USER_ROLE_IN_ORG_MUTATION, } from 'GraphQl/Mutations/mutations'; import dayjs from 'dayjs'; import React, { useState } from 'react'; import { Button, Form, Modal, Row, Table } from 'react-bootstrap'; import { useTranslation } from 'react-i18next'; -import { useHistory } from 'react-router-dom'; +import { useNavigate } from 'react-router-dom'; import { toast } from 'react-toastify'; import { errorHandler } from 'utils/errorHandler'; import type { InterfaceQueryUserListItem } from 'utils/interfaces'; import styles from './UsersTableItem.module.css'; +import Avatar from 'components/Avatar/Avatar'; type Props = { user: InterfaceQueryUserListItem; @@ -24,7 +24,7 @@ type Props = { const UsersTableItem = (props: Props): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'users' }); - const { user, index, loggedInUserId, resetAndRefetch } = props; + const { user, index, resetAndRefetch } = props; const [showJoinedOrganizations, setShowJoinedOrganizations] = useState(false); const [showBlockedOrganizations, setShowBlockedOrganizations] = @@ -39,46 +39,22 @@ const UsersTableItem = (props: Props): JSX.Element => { orgId: '', setShowOnCancel: '', }); - const [joinedOrgs, setJoinedOrgs] = useState(user.joinedOrganizations); + const [joinedOrgs, setJoinedOrgs] = useState(user.user.joinedOrganizations); const [orgsBlockedBy, setOrgsBlockedBy] = useState( - user.organizationsBlockedBy + user.user.organizationsBlockedBy, ); const [searchByNameJoinedOrgs, setSearchByNameJoinedOrgs] = useState(''); const [searchByNameOrgsBlockedBy, setSearchByNameOrgsBlockedBy] = useState(''); - const [updateUserType] = useMutation(UPDATE_USERTYPE_MUTATION); const [removeUser] = useMutation(REMOVE_MEMBER_MUTATION); const [updateUserInOrgType] = useMutation(UPDATE_USER_ROLE_IN_ORG_MUTATION); - const history = useHistory(); - - /* istanbul ignore next */ - const changeRole = async (e: any): Promise => { - const { value } = e.target; - - const inputData = value.split('?'); - - try { - const { data } = await updateUserType({ - variables: { - id: inputData[1], - userType: inputData[0], - }, - }); - if (data) { - toast.success(t('roleUpdated')); - resetAndRefetch(); - } - } catch (error: any) { - /* istanbul ignore next */ - errorHandler(t, error); - } - }; + const navigate = useNavigate(); const confirmRemoveUser = async (): Promise => { try { const { data } = await removeUser({ variables: { - userid: user._id, + userid: user.user._id, orgid: removeUserProps.orgId, }, }); @@ -102,7 +78,7 @@ const UsersTableItem = (props: Props): JSX.Element => { try { const { data } = await updateUserInOrgType({ variables: { - userId: user._id, + userId: user.user._id, role: inputData[0], organizationId: inputData[1], }, @@ -118,39 +94,62 @@ const UsersTableItem = (props: Props): JSX.Element => { }; function goToOrg(_id: string): void { - const url = '/orgdash/id=' + _id; + const url = '/orgdash/' + _id; // Dont change the below two lines window.location.replace(url); - history.push(url); + navigate(url); } function handleCreator(): void { toast.success('Profile Page Coming Soon !'); } - function handleSearchJoinedOrgs(e: any): void { - const { value } = e.target; + const searchJoinedOrgs = (value: string): void => { setSearchByNameJoinedOrgs(value); if (value == '') { - setJoinedOrgs(user.joinedOrganizations); + setJoinedOrgs(user.user.joinedOrganizations); } else { - const filteredOrgs = user.joinedOrganizations.filter((org) => - org.name.toLowerCase().includes(value.toLowerCase()) + const filteredOrgs = user.user.joinedOrganizations.filter((org) => + org.name.toLowerCase().includes(value.toLowerCase()), ); setJoinedOrgs(filteredOrgs); } - } - function handleSearcgByOrgsBlockedBy(e: any): void { - const { value } = e.target; + }; + const searchOrgsBlockedBy = (value: string): void => { setSearchByNameOrgsBlockedBy(value); if (value == '') { - setOrgsBlockedBy(user.organizationsBlockedBy); + setOrgsBlockedBy(user.user.organizationsBlockedBy); } else { - const filteredOrgs = user.organizationsBlockedBy.filter((org) => - org.name.toLowerCase().includes(value.toLowerCase()) + const filteredOrgs = user.user.organizationsBlockedBy.filter((org) => + org.name.toLowerCase().includes(value.toLowerCase()), ); setOrgsBlockedBy(filteredOrgs); } - } + }; + const handleSearchJoinedOrgs = (e: any): void => { + if (e.key === 'Enter') { + const { value } = e.target; + searchJoinedOrgs(value); + } + }; + const handleSearcgByOrgsBlockedBy = (e: any): void => { + if (e.key === 'Enter') { + const { value } = e.target; + searchOrgsBlockedBy(value); + } + }; + const handleSearchButtonClickJoinedOrgs = (): void => { + const inputValue = + (document.getElementById('orgname-joined-orgs') as HTMLInputElement) + ?.value || ''; + searchJoinedOrgs(inputValue); + }; + + const handleSearchButtonClickOrgsBlockedBy = (): void => { + const inputValue = + (document.getElementById('orgname-blocked-by') as HTMLInputElement) + ?.value || ''; + searchOrgsBlockedBy(inputValue); + }; /* istanbul ignore next */ function onHideRemoveUserModal(): void { @@ -161,42 +160,32 @@ const UsersTableItem = (props: Props): JSX.Element => { setShowBlockedOrganizations(true); } } + + const isSuperAdmin = user.appUserProfile.isSuperAdmin; + return ( <> {/* Table Item */} {index + 1} - {`${user.firstName} ${user.lastName}`} - {user.email} - - - - - - - + {`${user.user.firstName} ${user.user.lastName}`} + {user.user.email} @@ -205,41 +194,44 @@ const UsersTableItem = (props: Props): JSX.Element => { show={showJoinedOrganizations} key={`modal-joined-org-${index}`} size="xl" - data-testid={`modal-joined-org-${user._id}`} + data-testid={`modal-joined-org-${user.user._id}`} onHide={() => setShowJoinedOrganizations(false)} > - {t('orgJoinedBy')} {`${user.firstName}`} {`${user.lastName}`} ( - {user.joinedOrganizations.length}) + {t('orgJoinedBy')} {`${user.user.firstName}`}{' '} + {`${user.user.lastName}`} ({user.user.joinedOrganizations.length}) - {user.joinedOrganizations.length !== 0 && ( + {user.user.joinedOrganizations.length !== 0 && (
    )} - {user.joinedOrganizations.length == 0 ? ( + {user.user.joinedOrganizations.length == 0 ? (

    - {user.firstName} {user.lastName} {t('hasNotJoinedAnyOrg')} + {user.user.firstName} {user.user.lastName}{' '} + {t('hasNotJoinedAnyOrg')}

    ) : joinedOrgs.length == 0 ? ( @@ -256,7 +248,7 @@ const UsersTableItem = (props: Props): JSX.Element => { Name - Location + Address Created on Created By Users Role @@ -268,7 +260,7 @@ const UsersTableItem = (props: Props): JSX.Element => { {joinedOrgs.map((org) => { // Check user is admin for this organization or not let isAdmin = false; - user.adminFor.map((item) => { + user.appUserProfile.adminFor.map((item) => { if (item._id == org._id) { isAdmin = true; } @@ -281,18 +273,15 @@ const UsersTableItem = (props: Props): JSX.Element => { className="p-0" onClick={() => goToOrg(org._id)} > - orgImage + {org.image ? ( + orgImage + ) : ( + + )} {org.name} - {org.location} + {org.address && {org.address.city}} {dayjs(org.createdAt).format('DD-MM-YYYY')} - {isAdmin ? 'ADMIN' : 'USER'} + + {isSuperAdmin + ? 'SUPERADMIN' + : isAdmin + ? 'ADMIN' + : 'USER'} + - {isAdmin ? ( + {isSuperAdmin ? ( + <> + + + + + ) : isAdmin ? ( <>
    + } + /> + + + + + , + ); +}; + +describe('Event Management', () => { + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId', eventId: 'eventId' }), + })); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + test('Testing Event Management Screen', async () => { + renderEventManagement(); + + const dashboardTab = await screen.findByTestId('eventDashboadTab'); + expect(dashboardTab).toBeInTheDocument(); + + const dashboardButton = screen.getByTestId('dashboardBtn'); + userEvent.click(dashboardButton); + + expect(dashboardTab).toBeInTheDocument(); + }); + test('Testing back button navigation when userType is SuperAdmin', async () => { + setItem('SuperAdmin', true); + renderEventManagement(); + + const backButton = screen.getByTestId('backBtn'); + userEvent.click(backButton); + await waitFor(() => { + const eventsScreen = screen.getByTestId('eventsScreen'); + expect(eventsScreen).toBeInTheDocument(); + }); + }); + + test('Testing event management tab switching', async () => { + renderEventManagement(); + + const registrantsButton = screen.getByTestId('registrantsBtn'); + userEvent.click(registrantsButton); + + const registrantsTab = screen.getByTestId('eventRegistrantsTab'); + expect(registrantsTab).toBeInTheDocument(); + + const eventActionsButton = screen.getByTestId('eventActionsBtn'); + userEvent.click(eventActionsButton); + + const eventActionsTab = screen.getByTestId('eventActionsTab'); + expect(eventActionsTab).toBeInTheDocument(); + + const eventStatsButton = screen.getByTestId('eventStatsBtn'); + userEvent.click(eventStatsButton); + + const eventStatsTab = screen.getByTestId('eventStatsTab'); + expect(eventStatsTab).toBeInTheDocument(); + }); +}); diff --git a/src/screens/EventManagement/EventManagement.tsx b/src/screens/EventManagement/EventManagement.tsx new file mode 100644 index 0000000000..869992cc0f --- /dev/null +++ b/src/screens/EventManagement/EventManagement.tsx @@ -0,0 +1,157 @@ +import React, { useState } from 'react'; +import Row from 'react-bootstrap/Row'; +import Col from 'react-bootstrap/Col'; +import styles from './EventManagement.module.css'; +import { Navigate, useNavigate, useParams } from 'react-router-dom'; +import { ReactComponent as AngleLeftIcon } from 'assets/svgs/angleLeft.svg'; +import { ReactComponent as EventDashboardIcon } from 'assets/svgs/eventDashboard.svg'; +import { ReactComponent as EventRegistrantsIcon } from 'assets/svgs/people.svg'; +import { ReactComponent as EventActionsIcon } from 'assets/svgs/settings.svg'; +import { ReactComponent as EventStatisticsIcon } from 'assets/svgs/eventStats.svg'; +import { useTranslation } from 'react-i18next'; +import { Button } from 'react-bootstrap'; +import EventDashboard from 'components/EventManagement/Dashboard/EventDashboard'; +import EventActionItems from 'components/EventManagement/EventActionItems/EventActionItems'; +import useLocalStorage from 'utils/useLocalstorage'; + +const eventDashboardTabs: { + value: TabOptions; + icon: JSX.Element; +}[] = [ + { + value: 'dashboard', + icon: , + }, + { + value: 'registrants', + icon: , + }, + { + value: 'eventActions', + icon: , + }, + { + value: 'eventStats', + icon: , + }, +]; + +type TabOptions = 'dashboard' | 'registrants' | 'eventActions' | 'eventStats'; + +const EventManagement = (): JSX.Element => { + const { t } = useTranslation('translation', { + keyPrefix: 'eventManagement', + }); + + const { getItem } = useLocalStorage(); + + const superAdmin = getItem('SuperAdmin'); + const adminFor = getItem('AdminFor'); + /*istanbul ignore next*/ + const userRole = superAdmin + ? 'SUPERADMIN' + : adminFor?.length > 0 + ? 'ADMIN' + : 'USER'; + + const { eventId, orgId } = useParams(); + /*istanbul ignore next*/ + if (!eventId || !orgId) { + return ; + } + + const navigate = useNavigate(); + const [tab, setTab] = useState('dashboard'); + + const handleClick = (value: TabOptions): void => { + setTab(value); + }; + + const renderButton = ({ + value, + icon, + }: { + value: TabOptions; + icon: React.ReactNode; + }): JSX.Element => { + const selected = tab === value; + const variant = selected ? 'success' : 'light'; + const translatedText = t(value); + const className = selected + ? 'px-4' + : 'text-secondary border-secondary-subtle px-4'; + const props = { + variant, + className, + key: value, + size: 'sm' as 'sm' | 'lg', + onClick: () => handleClick(value), + 'data-testid': `${value}Btn`, + }; + + return ( + + ); + }; + + return ( +
    +
    + { + /*istanbul ignore next*/ + userRole === 'USER' + ? navigate(`/user/events/${orgId}`) + : navigate(`/orgevents/${orgId}`); + }} + className="mt-1" + /> +
    + {eventDashboardTabs.map(renderButton)} +
    +
    + + + {(() => { + switch (tab) { + case 'dashboard': + return ( +
    + +
    + ); + case 'registrants': + return ( +
    +

    Event Registrants

    +
    + ); + case 'eventActions': + return ( +
    + +
    + ); + case 'eventStats': + return ( +
    +

    Event Statistics

    +
    + ); + } + })()} + +
    +
    + ); +}; + +export default EventManagement; diff --git a/src/screens/ForgotPassword/ForgotPassword.test.tsx b/src/screens/ForgotPassword/ForgotPassword.test.tsx index 94db5b2839..7a9ba855b9 100644 --- a/src/screens/ForgotPassword/ForgotPassword.test.tsx +++ b/src/screens/ForgotPassword/ForgotPassword.test.tsx @@ -7,49 +7,65 @@ import 'jest-location-mock'; import { I18nextProvider } from 'react-i18next'; import { Provider } from 'react-redux'; import { BrowserRouter } from 'react-router-dom'; +import { ToastContainer } from 'react-toastify'; -import { - FORGOT_PASSWORD_MUTATION, - GENERATE_OTP_MUTATION, -} from 'GraphQl/Mutations/mutations'; +import { GENERATE_OTP_MUTATION } from 'GraphQl/Mutations/mutations'; import { store } from 'state/store'; import { StaticMockLink } from 'utils/StaticMockLink'; -import i18nForTest from 'utils/i18nForTest'; +// import i18nForTest from 'utils/i18nForTest'; import ForgotPassword from './ForgotPassword'; +import i18n from 'utils/i18nForTest'; +import useLocalStorage from 'utils/useLocalstorage'; + +const { setItem, removeItem } = useLocalStorage(); const MOCKS = [ { request: { - query: FORGOT_PASSWORD_MUTATION, + query: GENERATE_OTP_MUTATION, variables: { - userOtp: '12345', - newPassword: 'johndoe', - otpToken: 'otpToken', + email: 'johndoe@gmail.com', }, }, result: { data: { - forgotPassword: true, + otp: { + otpToken: 'otpToken', + }, }, }, }, + { request: { query: GENERATE_OTP_MUTATION, variables: { - email: 'johndoe@gmail.com', + email: 'notexists@gmail.com', }, }, - result: { - data: { - otp: { - otpToken: 'otpToken', - }, + error: new Error('User not found'), + }, +]; + +const MOCKS_INTERNET_UNAVAILABLE = [ + { + request: { + query: GENERATE_OTP_MUTATION, + variables: { + email: 'johndoe@gmail.com', }, }, + error: new Error('Failed to fetch'), }, ]; + const link = new StaticMockLink(MOCKS, true); +const notWorkingLink = new StaticMockLink([], true); +const talawaApiUnavailableLink = new StaticMockLink( + MOCKS_INTERNET_UNAVAILABLE, + true, +); + async function wait(ms = 100): Promise { await act(() => { return new Promise((resolve) => { @@ -57,8 +73,15 @@ async function wait(ms = 100): Promise { }); }); } + +const translations = JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.forgotPassword ?? {}, + ), +); + beforeEach(() => { - localStorage.setItem('IsLoggedIn', 'FALSE'); + setItem('IsLoggedIn', 'FALSE'); }); afterEach(() => { localStorage.clear(); @@ -72,12 +95,12 @@ describe('Testing Forgot Password screen', () => { - + - + , ); await wait(); @@ -90,18 +113,18 @@ describe('Testing Forgot Password screen', () => { }); test('Testing, If user is already loggedIn', async () => { - localStorage.setItem('IsLoggedIn', 'TRUE'); + setItem('IsLoggedIn', 'TRUE'); render( - + - + , ); await wait(); @@ -116,19 +139,19 @@ describe('Testing Forgot Password screen', () => { - + - + , ); await wait(); userEvent.type( screen.getByPlaceholderText(/Registered email/i), - formData.email + formData.email, ); userEvent.click(screen.getByText('Get OTP')); @@ -147,19 +170,60 @@ describe('Testing Forgot Password screen', () => { - + + + + + + , + ); + + await wait(); + + userEvent.type( + screen.getByPlaceholderText(/Registered email/i), + formData.email, + ); + + userEvent.click(screen.getByText('Get OTP')); + await wait(); + + userEvent.type(screen.getByPlaceholderText('e.g. 12345'), formData.userOtp); + userEvent.type(screen.getByTestId('newPassword'), formData.newPassword); + userEvent.type( + screen.getByTestId('confirmNewPassword'), + formData.confirmNewPassword, + ); + setItem('otpToken', 'lorem ipsum'); + userEvent.click(screen.getByText('Change Password')); + await wait(); + }); + + test('Testing forgot password functionality, if the otp got deleted from the local storage', async () => { + const formData = { + userOtp: '12345', + newPassword: 'johnDoe', + confirmNewPassword: 'johnDoe', + email: 'johndoe@gmail.com', + }; + + render( + + + + - + , ); await wait(); userEvent.type( screen.getByPlaceholderText(/Registered email/i), - formData.email + formData.email, ); userEvent.click(screen.getByText('Get OTP')); @@ -169,9 +233,9 @@ describe('Testing Forgot Password screen', () => { userEvent.type(screen.getByTestId('newPassword'), formData.newPassword); userEvent.type( screen.getByTestId('confirmNewPassword'), - formData.confirmNewPassword + formData.confirmNewPassword, ); - localStorage.setItem('otpToken', 'lorem ipsum'); + removeItem('otpToken'); userEvent.click(screen.getByText('Change Password')); await wait(); }); @@ -188,19 +252,19 @@ describe('Testing Forgot Password screen', () => { - + - + , ); await wait(); userEvent.type( screen.getByPlaceholderText(/Registered email/i), - formData.email + formData.email, ); userEvent.click(screen.getByText('Get OTP')); @@ -210,12 +274,97 @@ describe('Testing Forgot Password screen', () => { userEvent.type(screen.getByTestId('newPassword'), formData.newPassword); userEvent.type( screen.getByTestId('confirmNewPassword'), - formData.confirmNewPassword + formData.confirmNewPassword, ); userEvent.click(screen.getByText('Change Password')); }); + test('Testing forgot password functionality, when the user is not found', async () => { + const formData = { + email: 'notexists@gmail.com', + }; + // setItem('otpToken', ''); + render( + + + + + + + + + + , + ); + + await wait(); + + userEvent.type( + screen.getByPlaceholderText(/Registered email/i), + formData.email, + ); + + userEvent.click(screen.getByText('Get OTP')); + await wait(); + + expect( + await screen.findByText(translations.emailNotRegistered), + ).toBeInTheDocument(); + }); + + test('Testing forgot password functionality, when there is an error except unregistered email and api failure', async () => { + render( + + + + + + + + + + , + ); + userEvent.click(screen.getByText('Get OTP')); + await wait(); + + expect( + await screen.findByText(translations.errorSendingMail), + ).toBeInTheDocument(); + }); + + test('Testing forgot password functionality, when talawa api failed', async () => { + const formData = { + email: 'johndoe@gmail.com', + }; + render( + + + + + + + + + + , + ); + + await wait(); + + userEvent.type( + screen.getByPlaceholderText(/Registered email/i), + formData.email, + ); + userEvent.click(screen.getByText('Get OTP')); + await wait(); + + expect( + await screen.findByText(translations.talawaApiUnavailable), + ).toBeInTheDocument(); + }); + test('Testing forgot password functionality, when otp token is not present', async () => { const formData = { userOtp: '12345', @@ -224,25 +373,25 @@ describe('Testing Forgot Password screen', () => { email: 'johndoe@gmail.com', }; - localStorage.setItem('otpToken', ''); + setItem('otpToken', ''); render( - + - + , ); await wait(); userEvent.type( screen.getByPlaceholderText(/Registered email/i), - formData.email + formData.email, ); userEvent.click(screen.getByText('Get OTP')); @@ -252,7 +401,7 @@ describe('Testing Forgot Password screen', () => { userEvent.type(screen.getByTestId('newPassword'), formData.newPassword); userEvent.type( screen.getByTestId('confirmNewPassword'), - formData.confirmNewPassword + formData.confirmNewPassword, ); userEvent.click(screen.getByText('Change Password')); }); diff --git a/src/screens/ForgotPassword/ForgotPassword.tsx b/src/screens/ForgotPassword/ForgotPassword.tsx index 10b4c4db0b..57e5b151d2 100644 --- a/src/screens/ForgotPassword/ForgotPassword.tsx +++ b/src/screens/ForgotPassword/ForgotPassword.tsx @@ -17,6 +17,7 @@ import Button from 'react-bootstrap/Button'; import { useTranslation } from 'react-i18next'; import { errorHandler } from 'utils/errorHandler'; import styles from './ForgotPassword.module.css'; +import useLocalStorage from 'utils/useLocalstorage'; const ForgotPassword = (): JSX.Element => { const { t } = useTranslation('translation', { @@ -25,6 +26,8 @@ const ForgotPassword = (): JSX.Element => { document.title = t('title'); + const { getItem, removeItem, setItem } = useLocalStorage(); + const [showEnterEmail, setShowEnterEmail] = useState(true); const [registeredEmail, setregisteredEmail] = useState(''); @@ -37,15 +40,15 @@ const ForgotPassword = (): JSX.Element => { const [otp, { loading: otpLoading }] = useMutation(GENERATE_OTP_MUTATION); const [forgotPassword, { loading: forgotPasswordLoading }] = useMutation( - FORGOT_PASSWORD_MUTATION + FORGOT_PASSWORD_MUTATION, ); - const isLoggedIn = localStorage.getItem('IsLoggedIn'); + const isLoggedIn = getItem('IsLoggedIn'); useEffect(() => { if (isLoggedIn == 'TRUE') { window.location.replace('/orglist'); } return () => { - localStorage.removeItem('otpToken'); + removeItem('otpToken'); }; }, []); @@ -60,7 +63,7 @@ const ForgotPassword = (): JSX.Element => { }); if (data) { - localStorage.setItem('otpToken', data.otp.otpToken); + setItem('otpToken', data.otp.otpToken); toast.success(t('OTPsent')); setShowEnterEmail(false); } @@ -76,7 +79,7 @@ const ForgotPassword = (): JSX.Element => { }; const submitForgotPassword = async ( - e: ChangeEvent + e: ChangeEvent, ): Promise => { e.preventDefault(); const { userOtp, newPassword, confirmNewPassword } = forgotPassFormData; @@ -86,7 +89,7 @@ const ForgotPassword = (): JSX.Element => { return; } - const otpToken = localStorage.getItem('otpToken'); + const otpToken = getItem('otpToken'); if (!otpToken) { return; diff --git a/src/screens/FundCampaignPledge/FundCampaignPledge.module.css b/src/screens/FundCampaignPledge/FundCampaignPledge.module.css new file mode 100644 index 0000000000..8ddc6c01b1 --- /dev/null +++ b/src/screens/FundCampaignPledge/FundCampaignPledge.module.css @@ -0,0 +1,53 @@ +.pledgeContainer { + margin: 0.6rem 0; +} + +.createPledgeBtn { + position: absolute; + top: 1.3rem; + right: 2rem; +} +.container { + min-height: 100vh; +} + +.pledgeModal { + max-width: 80vw; + margin-top: 2vh; + margin-left: 13vw; +} +.titlemodal { + color: var(--bs-gray-600); + font-weight: 600; + font-size: 20px; + margin-bottom: 20px; + padding-bottom: 5px; + border-bottom: 3px solid var(--bs-primary); + width: 65%; +} +.greenregbtn { + margin: 1rem 0 0; + margin-top: 15px; + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + padding: 10px 10px; + border-radius: 5px; + background-color: #31bb6b; + width: 100%; + font-size: 16px; + color: white; + outline: none; + font-weight: 600; + cursor: pointer; + transition: + transform 0.2s, + box-shadow 0.2s; + width: 100%; +} +.message { + margin-top: 25%; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; +} diff --git a/src/screens/FundCampaignPledge/FundCampaignPledge.test.tsx b/src/screens/FundCampaignPledge/FundCampaignPledge.test.tsx new file mode 100644 index 0000000000..b8a73f73ba --- /dev/null +++ b/src/screens/FundCampaignPledge/FundCampaignPledge.test.tsx @@ -0,0 +1,443 @@ +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { + fireEvent, + render, + screen, + waitFor, + waitForElementToBeRemoved, +} from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { act } from 'react-dom/test-utils'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { toast } from 'react-toastify'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18nForTest from '../../utils/i18nForTest'; +import FundCampaignPledge from './FundCampaignPledge'; +import { + EMPTY_MOCKS, + MOCKS, + MOCKS_CREATE_PLEDGE_ERROR, + MOCKS_DELETE_PLEDGE_ERROR, + MOCKS_FUND_CAMPAIGN_PLEDGE_ERROR, + MOCKS_UPDATE_PLEDGE_ERROR, +} from './PledgesMocks'; +import React from 'react'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); +jest.mock('@mui/x-date-pickers/DateTimePicker', () => { + return { + DateTimePicker: jest.requireActual( + '@mui/x-date-pickers/DesktopDateTimePicker', + ).DesktopDateTimePicker, + }; +}); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(MOCKS_FUND_CAMPAIGN_PLEDGE_ERROR); +const link3 = new StaticMockLink(MOCKS_CREATE_PLEDGE_ERROR); +const link4 = new StaticMockLink(MOCKS_UPDATE_PLEDGE_ERROR); +const link5 = new StaticMockLink(MOCKS_DELETE_PLEDGE_ERROR); +const link6 = new StaticMockLink(EMPTY_MOCKS); +const translations = JSON.parse( + JSON.stringify(i18nForTest.getDataByLanguage('en')?.translation.pledges), +); + +describe('Testing Campaign Pledge Screen', () => { + const formData = { + pledgeAmount: 100, + pledgeCurrency: 'USD', + pledgeEndDate: '03/10/2024', + pledgeStartDate: '03/10/2024', + }; + + it('should render the Campaign Pledge screen', async () => { + const { getByText } = render( + + + + + {} + + + + , + ); + await wait(); + await waitFor(() => { + expect(getByText(translations.addPledge)).toBeInTheDocument(); + }); + }); + it('should render the Campaign Pledge screen with error', async () => { + const { queryByText } = render( + + + + + {} + + + + , + ); + await wait(); + await waitFor(() => + expect(queryByText(translations.addPledge)).not.toBeInTheDocument(), + ); + await waitFor(() => + expect(screen.getByTestId('errorMsg')).toBeInTheDocument(), + ); + }); + + it('open and closes Create Pledge modal', async () => { + render( + + + + + + {} + + + + + , + ); + await wait(); + await waitFor(() => + expect(screen.getByTestId('addPledgeBtn')).toBeInTheDocument(), + ); + userEvent.click(screen.getByTestId('addPledgeBtn')); + await waitFor(() => { + return expect( + screen.findByTestId('createPledgeCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('createPledgeCloseBtn')); + await waitForElementToBeRemoved(() => + screen.queryByTestId('createPledgeCloseBtn'), + ); + }); + it('creates a pledge', async () => { + render( + + + + + + {} + + + + + , + ); + await wait(); + await waitFor(() => + expect(screen.getByTestId('addPledgeBtn')).toBeInTheDocument(), + ); + userEvent.click(screen.getByTestId('addPledgeBtn')); + await waitFor(() => { + return expect( + screen.findByTestId('createPledgeCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + const currency = screen.getByTestId('currencySelect'); + fireEvent.change(currency, { target: { value: formData.pledgeCurrency } }); + const startDate = screen.getByLabelText(translations.startDate); + const endDate = screen.getByLabelText(translations.endDate); + fireEvent.change(startDate, { + target: { value: formData.pledgeStartDate }, + }); + fireEvent.change(endDate, { target: { value: formData.pledgeEndDate } }); + userEvent.type( + screen.getByPlaceholderText('Enter Pledge Amount'), + formData.pledgeAmount.toString(), + ); + userEvent.click(screen.getByTestId('createPledgeBtn')); + await waitFor(() => { + return expect(toast.success).toHaveBeenCalledWith( + translations.pledgeCreated, + ); + }); + }); + it('toasts an error on unsuccessful pledge creation', async () => { + render( + + + + + + {} + + + + + , + ); + await wait(); + await waitFor(() => + expect(screen.getByTestId('addPledgeBtn')).toBeInTheDocument(), + ); + userEvent.click(screen.getByTestId('addPledgeBtn')); + await waitFor(() => { + return expect( + screen.findByTestId('createPledgeCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + const currency = screen.getByTestId('currencySelect'); + fireEvent.change(currency, { target: { value: formData.pledgeCurrency } }); + const startDate = screen.getByLabelText(translations.startDate); + const endDate = screen.getByLabelText(translations.endDate); + fireEvent.change(startDate, { + target: { value: formData.pledgeStartDate }, + }); + fireEvent.change(endDate, { target: { value: formData.pledgeEndDate } }); + userEvent.type( + screen.getByPlaceholderText('Enter Pledge Amount'), + formData.pledgeAmount.toString(), + ); + userEvent.click(screen.getByTestId('createPledgeBtn')); + await waitFor(() => { + return expect(toast.error).toHaveBeenCalled(); + }); + }); + + it('open and closes update pledge modal', async () => { + render( + + + + + + {} + + + + + , + ); + await wait(); + await waitFor(() => + expect(screen.getAllByTestId('editPledgeBtn')[0]).toBeInTheDocument(), + ); + userEvent.click(screen.getAllByTestId('editPledgeBtn')[0]); + await waitFor(() => { + return expect( + screen.findByTestId('updatePledgeCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('updatePledgeCloseBtn')); + await waitForElementToBeRemoved(() => + screen.queryByTestId('updatePledgeCloseBtn'), + ); + }); + it('updates a pledge', async () => { + render( + + + + + + {} + + + + + , + ); + await wait(); + await waitFor(() => + expect(screen.getAllByTestId('editPledgeBtn')[0]).toBeInTheDocument(), + ); + userEvent.click(screen.getAllByTestId('editPledgeBtn')[0]); + await waitFor(() => { + return expect( + screen.findByTestId('updatePledgeCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + const currency = screen.getByTestId('currencySelect'); + fireEvent.change(currency, { target: { value: 'INR' } }); + const startDate = screen.getByLabelText(translations.startDate); + const endDate = screen.getByLabelText(translations.endDate); + fireEvent.change(startDate, { + target: { value: formData.pledgeStartDate }, + }); + fireEvent.change(endDate, { target: { value: formData.pledgeEndDate } }); + userEvent.type( + screen.getByPlaceholderText('Enter Pledge Amount'), + formData.pledgeAmount.toString(), + ); + userEvent.click(screen.getByTestId('updatePledgeBtn')); + await waitFor(() => { + return expect(toast.success).toHaveBeenCalledWith( + translations.pledgeUpdated, + ); + }); + }); + it('toasts an error on unsuccessful pledge update', async () => { + render( + + + + + + {} + + + + + , + ); + await wait(); + await waitFor(() => + expect(screen.getAllByTestId('editPledgeBtn')[0]).toBeInTheDocument(), + ); + userEvent.click(screen.getAllByTestId('editPledgeBtn')[0]); + await waitFor(() => { + return expect( + screen.findByTestId('updatePledgeCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + const currency = screen.getByTestId('currencySelect'); + fireEvent.change(currency, { target: { value: 'INR' } }); + const startDate = screen.getByLabelText(translations.startDate); + const endDate = screen.getByLabelText(translations.endDate); + fireEvent.change(startDate, { + target: { value: formData.pledgeStartDate }, + }); + fireEvent.change(endDate, { target: { value: formData.pledgeEndDate } }); + userEvent.type( + screen.getByPlaceholderText('Enter Pledge Amount'), + formData.pledgeAmount.toString(), + ); + userEvent.click(screen.getByTestId('updatePledgeBtn')); + await waitFor(() => { + return expect(toast.error).toHaveBeenCalled(); + }); + }); + it('open and closes delete pledge modal', async () => { + render( + + + + + + {} + + + + + , + ); + await wait(); + await waitFor(() => + expect(screen.getAllByTestId('deletePledgeBtn')[0]).toBeInTheDocument(), + ); + userEvent.click(screen.getAllByTestId('deletePledgeBtn')[0]); + await waitFor(() => { + return expect( + screen.findByTestId('deletePledgeCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('deletePledgeCloseBtn')); + await waitForElementToBeRemoved(() => + screen.queryByTestId('deletePledgeCloseBtn'), + ); + }); + it('deletes a pledge', async () => { + render( + + + + + + {} + + + + + , + ); + await wait(); + await waitFor(() => + expect(screen.getAllByTestId('deletePledgeBtn')[0]).toBeInTheDocument(), + ); + userEvent.click(screen.getAllByTestId('deletePledgeBtn')[0]); + await waitFor(() => { + return expect( + screen.findByTestId('deletePledgeCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('deleteyesbtn')); + await waitFor(() => { + return expect(toast.success).toHaveBeenCalledWith( + translations.pledgeDeleted, + ); + }); + }); + it('toasts an error on unsuccessful pledge deletion', async () => { + render( + + + + + + {} + + + + + , + ); + await wait(); + await waitFor(() => + expect(screen.getAllByTestId('deletePledgeBtn')[0]).toBeInTheDocument(), + ); + userEvent.click(screen.getAllByTestId('deletePledgeBtn')[0]); + await waitFor(() => { + return expect( + screen.findByTestId('deletePledgeCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('deleteyesbtn')); + await waitFor(() => { + return expect(toast.error).toHaveBeenCalled(); + }); + }); + it('renders the empty pledge component', async () => { + render( + + + + + + {} + + + + + , + ); + await wait(); + await waitFor(() => + expect(screen.getByText(translations.noPledges)).toBeInTheDocument(), + ); + }); +}); diff --git a/src/screens/FundCampaignPledge/FundCampaignPledge.tsx b/src/screens/FundCampaignPledge/FundCampaignPledge.tsx new file mode 100644 index 0000000000..42bb266640 --- /dev/null +++ b/src/screens/FundCampaignPledge/FundCampaignPledge.tsx @@ -0,0 +1,359 @@ +import { useMutation, useQuery } from '@apollo/client'; +import { WarningAmberRounded } from '@mui/icons-material'; +import { + CREATE_PlEDGE, + DELETE_PLEDGE, + UPDATE_PLEDGE, +} from 'GraphQl/Mutations/PledgeMutation'; +import { FUND_CAMPAIGN_PLEDGE } from 'GraphQl/Queries/fundQueries'; +import Loader from 'components/Loader/Loader'; +import dayjs from 'dayjs'; +import React, { useState, type ChangeEvent } from 'react'; +import { Button, Col, Row } from 'react-bootstrap'; +import { useTranslation } from 'react-i18next'; +import { useParams } from 'react-router-dom'; +import { toast } from 'react-toastify'; +import { currencySymbols } from 'utils/currency'; +import type { + InterfaceCreatePledge, + InterfacePledgeInfo, + InterfaceQueryFundCampaignsPledges, +} from 'utils/interfaces'; +import useLocalStorage from 'utils/useLocalstorage'; +import styles from './FundCampaignPledge.module.css'; +import PledgeCreateModal from './PledgeCreateModal'; +import PledgeDeleteModal from './PledgeDeleteModal'; +import PledgeEditModal from './PledgeEditModal'; +const fundCampaignPledge = (): JSX.Element => { + const { fundCampaignId: currentUrl } = useParams(); + const { getItem } = useLocalStorage(); + const { t } = useTranslation('translation', { + keyPrefix: 'pledges', + }); + + const [createPledgeModalIsOpen, setCreatePledgeModalIsOpen] = + useState(false); + const [updatePledgeModalIsOpen, setUpdatePledgeModalIsOpen] = + useState(false); + const [deletePledgeModalIsOpen, setDeletePledgeModalIsOpen] = + useState(false); + const [pledge, setPledge] = useState(null); + + const [formState, setFormState] = useState({ + pledgeAmount: 0, + pledgeCurrency: 'USD', + pledgeEndDate: new Date(), + pledgeStartDate: new Date(), + }); + const [createPledge] = useMutation(CREATE_PlEDGE); + const [updatePledge] = useMutation(UPDATE_PLEDGE); + const [deletePledge] = useMutation(DELETE_PLEDGE); + + const { + data: fundCampaignPledgeData, + loading: fundCampaignPledgeLoading, + error: fundCampaignPledgeError, + refetch: refetchFundCampaignPledge, + }: { + data?: { + getFundraisingCampaignById: InterfaceQueryFundCampaignsPledges; + }; + loading: boolean; + error?: Error | undefined; + refetch: any; + } = useQuery(FUND_CAMPAIGN_PLEDGE, { + variables: { + id: currentUrl, + }, + }); + console.log(fundCampaignPledgeData); + + const showCreatePledgeModal = (): void => { + setCreatePledgeModalIsOpen(true); + }; + const hideCreatePledgeModal = (): void => { + setCreatePledgeModalIsOpen(false); + }; + const showUpdatePledgeModal = (): void => { + setUpdatePledgeModalIsOpen(true); + }; + const hideUpdatePledgeModal = (): void => { + setUpdatePledgeModalIsOpen(false); + }; + const showDeletePledgeModal = (): void => { + setDeletePledgeModalIsOpen(true); + }; + const hideDeletePledgeModal = (): void => { + setDeletePledgeModalIsOpen(false); + }; + const handleEditClick = (pledge: InterfacePledgeInfo): void => { + setFormState({ + pledgeAmount: pledge.amount, + pledgeCurrency: pledge.currency, + pledgeEndDate: new Date(pledge.endDate), + pledgeStartDate: new Date(pledge.startDate), + }); + setPledge(pledge); + showUpdatePledgeModal(); + }; + const handleDeleteClick = (pledge: InterfacePledgeInfo): void => { + setPledge(pledge); + showDeletePledgeModal(); + }; + const createPledgeHandler = async ( + e: ChangeEvent, + ): Promise => { + try { + e.preventDefault(); + const userId = getItem('userId'); + await createPledge({ + variables: { + campaignId: currentUrl, + amount: formState.pledgeAmount, + currency: formState.pledgeCurrency, + startDate: dayjs(formState.pledgeStartDate).format('YYYY-MM-DD'), + endDate: dayjs(formState.pledgeEndDate).format('YYYY-MM-DD'), + userIds: [userId], + }, + }); + await refetchFundCampaignPledge(); + hideCreatePledgeModal(); + toast.success(t('pledgeCreated')); + setFormState({ + pledgeAmount: 0, + pledgeCurrency: 'USD', + pledgeEndDate: new Date(), + pledgeStartDate: new Date(), + }); + } catch (error: unknown) { + toast.error((error as Error).message); + console.log(error); + } + }; + const updatePledgeHandler = async ( + e: ChangeEvent, + ): Promise => { + try { + e.preventDefault(); + const updatedFields: { [key: string]: any } = {}; + if (formState.pledgeAmount !== pledge?.amount) { + updatedFields.amount = formState.pledgeAmount; + } + if (formState.pledgeCurrency !== pledge?.currency) { + updatedFields.currency = formState.pledgeCurrency; + } + if ( + dayjs(formState.pledgeStartDate).format('YYYY-MM-DD') !== + dayjs(pledge?.startDate).format('YYYY-MM-DD') + ) { + updatedFields.startDate = dayjs(formState.pledgeStartDate).format( + 'YYYY-MM-DD', + ); + } + if ( + dayjs(formState.pledgeEndDate).format('YYYY-MM-DD') !== + dayjs(pledge?.endDate).format('YYYY-MM-DD') + ) { + updatedFields.endDate = dayjs(formState.pledgeEndDate).format( + 'YYYY-MM-DD', + ); + } + + await updatePledge({ + variables: { + id: pledge?._id, + ...updatedFields, + }, + }); + await refetchFundCampaignPledge(); + hideUpdatePledgeModal(); + toast.success(t('pledgeUpdated')); + } catch (error: unknown) { + toast.error((error as Error).message); + console.log(error); + } + }; + const deleteHandler = async (): Promise => { + try { + await deletePledge({ + variables: { + id: pledge?._id, + }, + }); + await refetchFundCampaignPledge(); + hideDeletePledgeModal(); + toast.success(t('pledgeDeleted')); + } catch (error: unknown) { + toast.error((error as Error).message); + console.log(error); + } + }; + if (fundCampaignPledgeLoading) return ; + if (fundCampaignPledgeError) { + return ( +
    +
    + +
    + Error occured while loading Funds +
    + {fundCampaignPledgeError.message} +
    +
    +
    + ); + } + return ( +
    + +
    +
    + + +
    {t('volunteers')}
    + + +
    {t('startDate')}
    + + +
    {t('endDate')}
    + + +
    {t('pledgeAmount')}
    + + +
    {t('pledgeOptions')}
    + +
    +
    + {fundCampaignPledgeData?.getFundraisingCampaignById.pledges.map( + (pledge, index) => ( +
    + + +
    + {pledge.users.map((user, index) => ( + + {user.firstName} + {index !== pledge.users.length - 1 && ', '} + + ))} +
    + + +
    + {dayjs(pledge.startDate).format('DD/MM/YYYY')} +
    + + +
    {dayjs(pledge.endDate).format('DD/MM/YYYY')}
    + + +
    + { + currencySymbols[ + pledge.currency as keyof typeof currencySymbols + ] + } + {pledge.amount} +
    + + + + + +
    + {fundCampaignPledgeData.getFundraisingCampaignById.pledges && + index !== + fundCampaignPledgeData.getFundraisingCampaignById.pledges + .length - + 1 &&
    } +
    + ), + )} + + {fundCampaignPledgeData?.getFundraisingCampaignById.pledges + .length === 0 && ( +
    +
    {t('noPledges')}
    +
    + )} +
    +
    +
    + + {/* Create Pledge Modal */} + + + {/* Update Pledge Modal */} + + + {/* Delete Pledge Modal */} + +
    + ); +}; +export default fundCampaignPledge; diff --git a/src/screens/FundCampaignPledge/PledgeCreateModal.tsx b/src/screens/FundCampaignPledge/PledgeCreateModal.tsx new file mode 100644 index 0000000000..2c296ff216 --- /dev/null +++ b/src/screens/FundCampaignPledge/PledgeCreateModal.tsx @@ -0,0 +1,148 @@ +import { DatePicker } from '@mui/x-date-pickers'; +import dayjs, { type Dayjs } from 'dayjs'; +import { type ChangeEvent } from 'react'; +import { Button, Form, Modal } from 'react-bootstrap'; +import { currencyOptions } from 'utils/currency'; +import type { InterfaceCreatePledge } from 'utils/interfaces'; +import styles from './FundCampaignPledge.module.css'; +import React from 'react'; + +interface InterfaceCreatePledgeModal { + createCamapignModalIsOpen: boolean; + hideCreateCampaignModal: () => void; + formState: InterfaceCreatePledge; + setFormState: (state: React.SetStateAction) => void; + createPledgeHandler: (e: ChangeEvent) => Promise; + startDate: Date; + endDate: Date; + t: (key: string) => string; +} + +const PledgeCreateModal: React.FC = ({ + createCamapignModalIsOpen, + hideCreateCampaignModal, + formState, + setFormState, + createPledgeHandler, + startDate, + endDate, + t, +}) => { + return ( + <> + + +

    {t('createPledge')}

    + +
    + +
    + +
    + { + if (date) { + setFormState({ + ...formState, + pledgeStartDate: date.toDate(), + pledgeEndDate: + formState.pledgeEndDate && + (formState.pledgeEndDate < date?.toDate() + ? date.toDate() + : formState.pledgeEndDate), + }); + } + }} + minDate={dayjs(startDate)} + /> +
    +
    + { + if (date) { + setFormState({ + ...formState, + pledgeEndDate: date.toDate(), + }); + } + }} + minDate={dayjs(startDate)} + /> +
    +
    + + + {t('currency')} +
    + { + setFormState({ + ...formState, + pledgeCurrency: e.target.value, + }); + }} + > + + {currencyOptions.map((currency) => ( + + ))} + +
    +
    + + {t('amount')} + { + if (parseInt(e.target.value) > 0) { + setFormState({ + ...formState, + pledgeAmount: parseInt(e.target.value), + }); + } + }} + /> + +
    + +
    +
    +
    + + ); +}; +export default PledgeCreateModal; diff --git a/src/screens/FundCampaignPledge/PledgeDeleteModal.tsx b/src/screens/FundCampaignPledge/PledgeDeleteModal.tsx new file mode 100644 index 0000000000..b6bc9fb20e --- /dev/null +++ b/src/screens/FundCampaignPledge/PledgeDeleteModal.tsx @@ -0,0 +1,58 @@ +import { Button, Modal } from 'react-bootstrap'; +import styles from './FundCampaignPledge.module.css'; +import React from 'react'; + +interface InterfaceDeletePledgeModal { + deletePledgeModalIsOpen: boolean; + hideDeletePledgeModal: () => void; + deletePledgeHandler: () => Promise; + t: (key: string) => string; +} +const PledgeDeleteModal: React.FC = ({ + deletePledgeModalIsOpen, + hideDeletePledgeModal, + deletePledgeHandler, + t, +}) => { + return ( + <> + + +

    {t('deletePledge')}

    + +
    + +

    {t('deletePledgeMsg')}

    +
    + + + + +
    + + ); +}; +export default PledgeDeleteModal; diff --git a/src/screens/FundCampaignPledge/PledgeEditModal.tsx b/src/screens/FundCampaignPledge/PledgeEditModal.tsx new file mode 100644 index 0000000000..afad814b86 --- /dev/null +++ b/src/screens/FundCampaignPledge/PledgeEditModal.tsx @@ -0,0 +1,147 @@ +import { DatePicker } from '@mui/x-date-pickers'; +import dayjs, { type Dayjs } from 'dayjs'; +import type { ChangeEvent } from 'react'; +import { Button, Form, Modal } from 'react-bootstrap'; +import { currencyOptions } from 'utils/currency'; +import type { InterfaceCreatePledge } from 'utils/interfaces'; +import styles from './FundCampaignPledge.module.css'; +import React from 'react'; + +interface InterfaceUpdatePledgeModal { + updatePledgeModalIsOpen: boolean; + hideUpdatePledgeModal: () => void; + formState: InterfaceCreatePledge; + setFormState: (state: React.SetStateAction) => void; + updatePledgeHandler: (e: ChangeEvent) => Promise; + startDate: Date; + endDate: Date; + t: (key: string) => string; +} +const PledgeEditModal: React.FC = ({ + updatePledgeModalIsOpen, + hideUpdatePledgeModal, + formState, + setFormState, + updatePledgeHandler, + startDate, + endDate, + t, +}) => { + return ( + <> + + +

    {t('editPledge')}

    + +
    + +
    + +
    + { + if (date) { + setFormState({ + ...formState, + pledgeStartDate: date.toDate(), + pledgeEndDate: + formState.pledgeEndDate && + (formState.pledgeEndDate < date?.toDate() + ? date.toDate() + : formState.pledgeEndDate), + }); + } + }} + minDate={dayjs(startDate)} + /> +
    +
    + { + if (date) { + setFormState({ + ...formState, + pledgeEndDate: date.toDate(), + }); + } + }} + minDate={dayjs(startDate)} + /> +
    +
    + + + {t('currency')} +
    + { + setFormState({ + ...formState, + pledgeCurrency: e.target.value, + }); + }} + > + + {currencyOptions.map((currency) => ( + + ))} + +
    +
    + + {t('amount')} + { + if (parseInt(e.target.value) > 0) { + setFormState({ + ...formState, + pledgeAmount: parseInt(e.target.value), + }); + } + }} + /> + +
    + +
    +
    +
    + + ); +}; +export default PledgeEditModal; diff --git a/src/screens/FundCampaignPledge/PledgesMocks.ts b/src/screens/FundCampaignPledge/PledgesMocks.ts new file mode 100644 index 0000000000..e5d668d53e --- /dev/null +++ b/src/screens/FundCampaignPledge/PledgesMocks.ts @@ -0,0 +1,312 @@ +import { + CREATE_PlEDGE, + DELETE_PLEDGE, + UPDATE_PLEDGE, +} from 'GraphQl/Mutations/PledgeMutation'; +import { FUND_CAMPAIGN_PLEDGE } from 'GraphQl/Queries/fundQueries'; + +export const MOCKS = [ + { + request: { + query: FUND_CAMPAIGN_PLEDGE, + variables: { + id: undefined, + }, + }, + result: { + data: { + getFundraisingCampaignById: { + startDate: '2024-01-01', + endDate: '2024-01-01', + pledges: [ + { + _id: '1', + amount: 100, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-01-01', + users: [ + { + _id: '1', + firstName: 'John', + }, + ], + }, + { + _id: '2', + amount: 200, + currency: 'USD', + startDate: '2024-03-03', + endDate: '2024-04-03', + users: [ + { + _id: '2', + firstName: 'Jane', + }, + ], + }, + ], + }, + }, + }, + }, + { + request: { + query: CREATE_PlEDGE, + variables: { + campaignId: undefined, + amount: 100, + currency: 'USD', + startDate: '2024-03-10', + endDate: '2024-03-10', + userIds: [null], + }, + }, + result: { + data: { + createFundraisingCampaignPledge: { + _id: '3', + }, + }, + }, + }, + { + request: { + query: UPDATE_PLEDGE, + variables: { + id: '1', + amount: 100100, + currency: 'INR', + startDate: '2024-03-10', + endDate: '2024-03-10', + }, + }, + result: { + data: { + updateFundraisingCampaignPledge: { + _id: '1', + }, + }, + }, + }, + { + request: { + query: DELETE_PLEDGE, + variables: { + id: '1', + }, + }, + result: { + data: { + removeFundraisingCampaignPledge: { + _id: '1', + }, + }, + }, + }, +]; +export const MOCKS_FUND_CAMPAIGN_PLEDGE_ERROR = [ + { + request: { + query: FUND_CAMPAIGN_PLEDGE, + variables: { + id: undefined, + }, + }, + error: new Error('Error fetching pledges'), + }, +]; + +export const MOCKS_CREATE_PLEDGE_ERROR = [ + { + request: { + query: FUND_CAMPAIGN_PLEDGE, + variables: { + id: undefined, + }, + }, + result: { + data: { + getFundraisingCampaignById: { + startDate: '2024-01-01', + endDate: '2024-01-01', + pledges: [ + { + _id: '1', + amount: 100, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-01-01', + users: [ + { + _id: '1', + firstName: 'John', + }, + ], + }, + { + _id: '2', + amount: 200, + currency: 'USD', + startDate: '2024-03-03', + endDate: '2024-04-03', + users: [ + { + _id: '2', + firstName: 'Jane', + }, + ], + }, + ], + }, + }, + }, + }, + { + request: { + query: CREATE_PlEDGE, + variables: { + campaignId: undefined, + amount: 100, + currency: 'USD', + startDate: '2024-03-10', + endDate: '2024-03-10', + userIds: null, + }, + }, + error: new Error('Error creating pledge'), + }, +]; +export const MOCKS_UPDATE_PLEDGE_ERROR = [ + { + request: { + query: FUND_CAMPAIGN_PLEDGE, + variables: { + id: undefined, + }, + }, + result: { + data: { + getFundraisingCampaignById: { + startDate: '2024-01-01', + endDate: '2024-01-01', + pledges: [ + { + _id: '1', + amount: 100, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-01-01', + users: [ + { + _id: '1', + firstName: 'John', + }, + ], + }, + { + _id: '2', + amount: 200, + currency: 'USD', + startDate: '2024-03-03', + endDate: '2024-04-03', + users: [ + { + _id: '2', + firstName: 'Jane', + }, + ], + }, + ], + }, + }, + }, + }, + { + request: { + query: UPDATE_PLEDGE, + variables: { + id: '1', + amount: 200, + currency: 'USD', + startDate: '2024-03-10', + endDate: '2024-03-10', + }, + }, + error: new Error('Error updating pledge'), + }, +]; +export const MOCKS_DELETE_PLEDGE_ERROR = [ + { + request: { + query: FUND_CAMPAIGN_PLEDGE, + variables: { + id: undefined, + }, + }, + result: { + data: { + getFundraisingCampaignById: { + startDate: '2024-01-01', + endDate: '2024-01-01', + pledges: [ + { + _id: '1', + amount: 100, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-01-01', + users: [ + { + _id: '1', + firstName: 'John', + }, + ], + }, + { + _id: '2', + amount: 200, + currency: 'USD', + startDate: '2024-03-03', + endDate: '2024-04-03', + users: [ + { + _id: '2', + firstName: 'Jane', + }, + ], + }, + ], + }, + }, + }, + }, + { + request: { + query: DELETE_PLEDGE, + variables: { + id: '1', + }, + }, + error: new Error('Error deleting pledge'), + }, +]; +export const EMPTY_MOCKS = [ + { + request: { + query: FUND_CAMPAIGN_PLEDGE, + variables: { + id: undefined, + }, + }, + result: { + data: { + getFundraisingCampaignById: { + startDate: '2024-01-01', + endDate: '2024-01-01', + pledges: [], + }, + }, + }, + }, +]; diff --git a/src/screens/LoginPage/LoginPage.module.css b/src/screens/LoginPage/LoginPage.module.css index 8e8e314ba9..dba42696d7 100644 --- a/src/screens/LoginPage/LoginPage.module.css +++ b/src/screens/LoginPage/LoginPage.module.css @@ -2,6 +2,10 @@ min-height: 100vh; } +.communityLogo { + object-fit: contain; +} + .row .left_portion { display: flex; justify-content: center; @@ -34,14 +38,20 @@ margin: 0; position: absolute; top: 1rem; - left: 2rem; + left: 1rem; +} + +.langChangeBtnStyle { + width: 7.5rem; + height: 2.2rem; + padding: 0; } .row .right_portion .talawa_logo { - height: 150px; - width: 150px; + height: 5rem; + width: 5rem; display: block; - margin: 1rem auto; + margin: 1.5rem auto 1rem; -webkit-animation: zoomIn 0.3s ease-in-out; animation: zoomIn 0.3s ease-in-out; } @@ -49,10 +59,10 @@ .row .orText { display: block; position: absolute; - top: calc(-0.7rem - 0.5rem); + top: 0; left: calc(50% - 2.6rem); margin: 0 auto; - padding: 0.5rem 2rem; + padding: 0.35rem 2rem; z-index: 100; background: var(--bs-white); color: var(--bs-secondary); @@ -102,6 +112,10 @@ margin-bottom: 0; padding: 1rem; } + + .socialIcons { + margin-bottom: 1rem; + } } @media (max-width: 577px) { @@ -124,6 +138,10 @@ height: 120px; margin: 0 auto 2rem auto; } + + .socialIcons { + margin-bottom: 1rem; + } } .active_tab { @@ -186,3 +204,28 @@ transform: translateY(0); } } + +.socialIcons { + display: flex; + gap: 16px; + justify-content: center; +} + +.password_checks { + display: flex; + justify-content: space-between; + align-items: flex-start; + flex-direction: column; +} + +.password_check_element { + margin-top: -10px; +} + +.password_check_element_top { + margin-top: 18px; +} + +.password_check_element_bottom { + margin-bottom: -20px; +} diff --git a/src/screens/LoginPage/LoginPage.test.tsx b/src/screens/LoginPage/LoginPage.test.tsx index c92ba07e43..bac7b264db 100644 --- a/src/screens/LoginPage/LoginPage.test.tsx +++ b/src/screens/LoginPage/LoginPage.test.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { MockedProvider } from '@apollo/react-testing'; -import { act, render, screen } from '@testing-library/react'; +import { act, render, screen, fireEvent } from '@testing-library/react'; import { Provider } from 'react-redux'; import { BrowserRouter } from 'react-router-dom'; import userEvent from '@testing-library/user-event'; @@ -13,9 +13,13 @@ import { LOGIN_MUTATION, RECAPTCHA_MUTATION, SIGNUP_MUTATION, + UPDATE_COMMUNITY, } from 'GraphQl/Mutations/mutations'; import { store } from 'state/store'; import i18nForTest from 'utils/i18nForTest'; +import { BACKEND_URL } from 'Constant/constant'; +import useLocalStorage from 'utils/useLocalstorage'; +import { GET_COMMUNITY_DATA } from 'GraphQl/Queries/Queries'; const MOCKS = [ { @@ -31,8 +35,10 @@ const MOCKS = [ login: { user: { _id: '1', - userType: 'ADMIN', - adminApproved: true, + }, + appUserProfile: { + isSuperAdmin: false, + adminFor: ['123', '456'], }, accessToken: 'accessToken', refreshToken: 'refreshToken', @@ -75,9 +81,49 @@ const MOCKS = [ }, }, }, + { + request: { + query: GET_COMMUNITY_DATA, + }, + result: { + data: { + getCommunityData: null, + }, + }, + }, +]; +const MOCKS2 = [ + { + request: { + query: GET_COMMUNITY_DATA, + }, + result: { + data: { + getCommunityData: { + _id: 'communitId', + websiteLink: 'http://link.com', + name: 'testName', + logoUrl: 'image.png', + __typename: 'Community', + socialMediaUrls: { + facebook: 'http://url.com', + gitHub: 'http://url.com', + youTube: 'http://url.com', + instagram: 'http://url.com', + linkedIn: 'http://url.com', + reddit: 'http://url.com', + slack: 'http://url.com', + twitter: null, + __typename: 'SocialMediaUrls', + }, + }, + }, + }, + }, ]; const link = new StaticMockLink(MOCKS, true); +const link2 = new StaticMockLink(MOCKS2, true); async function wait(ms = 100): Promise { await act(() => { @@ -101,51 +147,45 @@ jest.mock('Constant/constant.ts', () => ({ RECAPTCHA_SITE_KEY: 'xxx', })); -describe('Talawa-API server fetch check', () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - - test('Checks if Talawa-API resource is loaded successfully', async () => { - global.fetch = jest.fn(() => Promise.resolve({} as unknown as Response)); - - await act(async () => { - render( - - - - - - - - - - ); - }); - - expect(fetch).toHaveBeenCalledWith('http://localhost:4000/graphql/'); - }); - - test('displays warning message when resource loading fails', async () => { - const mockError = new Error('Network error'); - global.fetch = jest.fn(() => Promise.reject(mockError)); +const mockNavigate = jest.fn(); +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useNavigate: () => mockNavigate, +})); - await act(async () => { - render( - - - - - - - - - +jest.mock('react-google-recaptcha', () => { + const react = jest.requireActual('react'); + const recaptcha = react.forwardRef( + ( + props: { + onChange: (value: string) => void; + } & React.InputHTMLAttributes, + ref: React.LegacyRef | undefined, + ): JSX.Element => { + const { onChange, ...otherProps } = props; + + const handleChange = ( + event: React.ChangeEvent, + ): void => { + if (onChange) { + onChange(event.target.value); + } + }; + + return ( + <> + + ); - }); - - expect(fetch).toHaveBeenCalledWith('http://localhost:4000/graphql/'); - }); + }, + ); + return recaptcha; }); describe('Testing Login Page Screen', () => { @@ -161,22 +201,69 @@ describe('Testing Login Page Screen', () => { - + , ); await wait(); - - expect(screen.getByText(/Admin Portal/i)).toBeInTheDocument(); + const adminLink = screen.getByText(/Admin/i); + userEvent.click(adminLink); + await wait(); + expect(screen.getByText(/Admin/i)).toBeInTheDocument(); expect(window.location).toBeAt('/orglist'); }); + test('There should be default values of pre-login data when queried result is null', async () => { + render( + + + + + + + + + , + ); + await wait(); + + expect(screen.getByTestId('PalisadoesLogo')).toBeInTheDocument(); + expect( + screen.getAllByTestId('PalisadoesSocialMedia')[0], + ).toBeInTheDocument(); + + await wait(); + expect(screen.queryByTestId('preLoginLogo')).not.toBeInTheDocument(); + expect(screen.queryAllByTestId('preLoginSocialMedia')[0]).toBeUndefined(); + }); + + test('There should be a different values of pre-login data if the queried result is not null', async () => { + render( + + + + + + + + + , + ); + await wait(); + expect(screen.getByTestId('preLoginLogo')).toBeInTheDocument(); + expect(screen.getAllByTestId('preLoginSocialMedia')[0]).toBeInTheDocument(); + + await wait(); + expect(screen.queryByTestId('PalisadoesLogo')).not.toBeInTheDocument(); + expect(screen.queryAllByTestId('PalisadoesSocialMedia')[0]).toBeUndefined(); + }); + test('Testing registration functionality', async () => { const formData = { firstName: 'John', lastName: 'Doe', email: 'johndoe@gmail.com', - password: 'johndoe', - confirmPassword: 'johndoe', + password: 'John@123', + confirmPassword: 'John@123', }; render( @@ -188,7 +275,7 @@ describe('Testing Login Page Screen', () => { - + , ); await wait(); @@ -199,19 +286,63 @@ describe('Testing Login Page Screen', () => { userEvent.type( screen.getByPlaceholderText(/First Name/i), - formData.firstName + formData.firstName, ); userEvent.type( screen.getByPlaceholderText(/Last name/i), - formData.lastName + formData.lastName, ); userEvent.type(screen.getByTestId(/signInEmail/i), formData.email); userEvent.type(screen.getByPlaceholderText('Password'), formData.password); userEvent.type( screen.getByPlaceholderText('Confirm Password'), - formData.confirmPassword + formData.confirmPassword, + ); + + userEvent.click(screen.getByTestId('registrationBtn')); + }); + + test('Testing registration functionality when all inputs are invalid', async () => { + const formData = { + firstName: '1234', + lastName: '8890', + email: 'j@l.co', + password: 'john@123', + confirmPassword: 'john@123', + }; + + render( + + + + + + + + + , ); + await wait(); + + userEvent.click(screen.getByTestId(/goToRegisterPortion/i)); + + await wait(); + + userEvent.type( + screen.getByPlaceholderText(/First Name/i), + formData.firstName, + ); + userEvent.type( + screen.getByPlaceholderText(/Last name/i), + formData.lastName, + ); + userEvent.type(screen.getByTestId(/signInEmail/i), formData.email); + userEvent.type(screen.getByPlaceholderText('Password'), formData.password); + userEvent.type( + screen.getByPlaceholderText('Confirm Password'), + formData.confirmPassword, + ); userEvent.click(screen.getByTestId('registrationBtn')); }); @@ -220,8 +351,8 @@ describe('Testing Login Page Screen', () => { firstName: 'John', lastName: 'Doe', email: 'johndoe@gmail.com', - password: 'johndoe', - confirmPassword: 'doeJohn', + password: 'johnDoe@1', + confirmPassword: 'doeJohn@2', }; render( @@ -233,7 +364,7 @@ describe('Testing Login Page Screen', () => { - + , ); await wait(); @@ -242,17 +373,17 @@ describe('Testing Login Page Screen', () => { userEvent.type( screen.getByPlaceholderText(/First Name/i), - formData.firstName + formData.firstName, ); userEvent.type( screen.getByPlaceholderText(/Last Name/i), - formData.lastName + formData.lastName, ); userEvent.type(screen.getByTestId(/signInEmail/i), formData.email); userEvent.type(screen.getByPlaceholderText('Password'), formData.password); userEvent.type( screen.getByPlaceholderText('Confirm Password'), - formData.confirmPassword + formData.confirmPassword, ); userEvent.click(screen.getByTestId('registrationBtn')); @@ -276,7 +407,7 @@ describe('Testing Login Page Screen', () => { - + , ); await wait(); @@ -285,22 +416,70 @@ describe('Testing Login Page Screen', () => { userEvent.type( screen.getByPlaceholderText(/First Name/i), - formData.firstName + formData.firstName, ); userEvent.type( screen.getByPlaceholderText(/Last Name/i), - formData.lastName + formData.lastName, ); userEvent.type(screen.getByTestId(/signInEmail/i), formData.email); userEvent.type(screen.getByPlaceholderText('Password'), formData.password); userEvent.type( screen.getByPlaceholderText('Confirm Password'), - formData.confirmPassword + formData.confirmPassword, ); userEvent.click(screen.getByTestId('registrationBtn')); }); + test('switches to login tab on successful registration', async () => { + const formData = { + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@gmail.com', + password: 'johndoe', + confirmPassword: 'johndoe', + }; + + render( + + + + + + + + + , + ); + + await wait(); + + userEvent.click(screen.getByTestId(/goToRegisterPortion/i)); + userEvent.type( + screen.getByPlaceholderText(/First Name/i), + formData.firstName, + ); + userEvent.type( + screen.getByPlaceholderText(/Last name/i), + formData.lastName, + ); + userEvent.type(screen.getByTestId(/signInEmail/i), formData.email); + userEvent.type(screen.getByPlaceholderText('Password'), formData.password); + userEvent.type( + screen.getByPlaceholderText('Confirm Password'), + formData.confirmPassword, + ); + + userEvent.click(screen.getByTestId('registrationBtn')); + + await wait(); + + // Check if the login tab is now active by checking for elements that only appear in the login tab + expect(screen.getByTestId('loginBtn')).toBeInTheDocument(); + expect(screen.getByTestId('goToRegisterPortion')).toBeInTheDocument(); + }); + test('Testing toggle login register portion', async () => { render( @@ -311,7 +490,7 @@ describe('Testing Login Page Screen', () => { - + , ); await wait(); @@ -338,7 +517,7 @@ describe('Testing Login Page Screen', () => { - + , ); await wait(); @@ -346,7 +525,7 @@ describe('Testing Login Page Screen', () => { userEvent.type(screen.getByTestId(/loginEmail/i), formData.email); userEvent.type( screen.getByPlaceholderText(/Enter Password/i), - formData.password + formData.password, ); userEvent.click(screen.getByTestId('loginBtn')); @@ -364,7 +543,7 @@ describe('Testing Login Page Screen', () => { - + , ); await wait(); @@ -393,7 +572,7 @@ describe('Testing Login Page Screen', () => { - + , ); await wait(); @@ -424,7 +603,7 @@ describe('Testing Login Page Screen', () => { - + , ); await wait(); @@ -455,7 +634,7 @@ describe('Testing Login Page Screen', () => { - + , ); await wait(); @@ -476,7 +655,7 @@ describe('Testing Login Page Screen', () => { - + , ); await wait(); @@ -505,7 +684,7 @@ describe('Testing Login Page Screen', () => { - + , ); await wait(); @@ -534,7 +713,7 @@ describe('Testing Login Page Screen', () => { - + , ); await wait(); @@ -563,7 +742,7 @@ describe('Testing Login Page Screen', () => { - + , ); await wait(); @@ -579,4 +758,144 @@ describe('Testing Login Page Screen', () => { expect(screen.queryByTestId('passwordCheck')).toBeNull(); }); + + test('Component Should be rendered properly for user login', async () => { + window.location.assign('/user/organizations'); + + render( + + + + + + + + + , + ); + + await wait(); + const userLink = screen.getByText(/User/i); + userEvent.click(userLink); + await wait(); + expect(screen.getByText(/User Login/i)).toBeInTheDocument(); + expect(window.location).toBeAt('/user/organizations'); + }); + + test('on value change of ReCAPTCHA onChange event should be triggered in both the captcha', async () => { + render( + + + + + + + + + , + ); + await wait(); + + const recaptchaElements = screen.getAllByTestId('mock-recaptcha'); + + for (const recaptchaElement of recaptchaElements) { + const inputElement = recaptchaElement as HTMLInputElement; + + fireEvent.input(inputElement, { + target: { value: 'test-token' }, + }); + + fireEvent.change(inputElement, { + target: { value: 'test-token2' }, + }); + + expect(recaptchaElement).toHaveValue('test-token2'); + } + }); +}); + +describe('Testing redirect if already logged in', () => { + test('Logged in as USER', async () => { + const { setItem } = useLocalStorage(); + setItem('IsLoggedIn', 'TRUE'); + setItem('userId', 'id'); + render( + + + + + + + + + , + ); + await wait(); + expect(mockNavigate).toHaveBeenCalledWith('/user/organizations'); + }); + test('Logged in as Admin or SuperAdmin', async () => { + const { setItem } = useLocalStorage(); + setItem('IsLoggedIn', 'TRUE'); + setItem('userId', null); + render( + + + + + + + + + , + ); + await wait(); + expect(mockNavigate).toHaveBeenCalledWith('/orglist'); + }); +}); + +describe('Talawa-API server fetch check', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + test('Checks if Talawa-API resource is loaded successfully', async () => { + global.fetch = jest.fn(() => Promise.resolve({} as unknown as Response)); + + await act(async () => { + render( + + + + + + + + + , + ); + }); + + expect(fetch).toHaveBeenCalledWith(BACKEND_URL); + }); + + test('displays warning message when resource loading fails', async () => { + const mockError = new Error('Network error'); + global.fetch = jest.fn(() => Promise.reject(mockError)); + + await act(async () => { + render( + + + + + + + + + , + ); + }); + + expect(fetch).toHaveBeenCalledWith(BACKEND_URL); + }); }); diff --git a/src/screens/LoginPage/LoginPage.tsx b/src/screens/LoginPage/LoginPage.tsx index 481f8d09c2..4508684778 100644 --- a/src/screens/LoginPage/LoginPage.tsx +++ b/src/screens/LoginPage/LoginPage.tsx @@ -1,35 +1,56 @@ -import { useMutation } from '@apollo/client'; +import { useQuery, useMutation } from '@apollo/client'; +import { Check, Clear } from '@mui/icons-material'; import type { ChangeEvent } from 'react'; -import React, { useEffect, useRef, useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { Form } from 'react-bootstrap'; import Button from 'react-bootstrap/Button'; import Col from 'react-bootstrap/Col'; import Row from 'react-bootstrap/Row'; import ReCAPTCHA from 'react-google-recaptcha'; import { useTranslation } from 'react-i18next'; -import { Link } from 'react-router-dom'; +import { Link, useNavigate } from 'react-router-dom'; import { toast } from 'react-toastify'; -import { REACT_APP_USE_RECAPTCHA, RECAPTCHA_SITE_KEY } from 'Constant/constant'; +import EmailOutlinedIcon from '@mui/icons-material/EmailOutlined'; +import { + BACKEND_URL, + REACT_APP_USE_RECAPTCHA, + RECAPTCHA_SITE_KEY, +} from 'Constant/constant'; import { LOGIN_MUTATION, RECAPTCHA_MUTATION, SIGNUP_MUTATION, } from 'GraphQl/Mutations/mutations'; -import { ReactComponent as TalawaLogo } from 'assets/svgs/talawa.svg'; +import { GET_COMMUNITY_DATA } from 'GraphQl/Queries/Queries'; import { ReactComponent as PalisadoesLogo } from 'assets/svgs/palisadoes.svg'; +import { ReactComponent as TalawaLogo } from 'assets/svgs/talawa.svg'; import ChangeLanguageDropDown from 'components/ChangeLanguageDropdown/ChangeLanguageDropDown'; import Loader from 'components/Loader/Loader'; +import LoginPortalToggle from 'components/LoginPortalToggle/LoginPortalToggle'; import { errorHandler } from 'utils/errorHandler'; +import useLocalStorage from 'utils/useLocalstorage'; +import { socialMediaLinks } from '../../constants'; import styles from './LoginPage.module.css'; -import EmailOutlinedIcon from '@mui/icons-material/EmailOutlined'; -function loginPage(): JSX.Element { +const loginPage = (): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'loginPage' }); + const navigate = useNavigate(); + + const { getItem, setItem } = useLocalStorage(); document.title = t('title'); + type PasswordValidation = { + lowercaseChar: boolean; + uppercaseChar: boolean; + numericValue: boolean; + specialChar: boolean; + }; + + const [recaptchaToken, setRecaptchaToken] = useState(null); const [showTab, setShowTab] = useState<'LOGIN' | 'REGISTER'>('LOGIN'); + const [role, setRole] = useState<'admin' | 'user'>('admin'); const [componentLoader, setComponentLoader] = useState(true); const [isInputFocused, setIsInputFocused] = useState(false); const [signformState, setSignFormState] = useState({ @@ -46,12 +67,37 @@ function loginPage(): JSX.Element { const [showPassword, setShowPassword] = useState(false); const [showConfirmPassword, setShowConfirmPassword] = useState(false); - const recaptchaRef = useRef(null); + const [showAlert, setShowAlert] = useState({ + lowercaseChar: true, + uppercaseChar: true, + numericValue: true, + specialChar: true, + }); + + const passwordValidationRegExp = { + lowercaseCharRegExp: new RegExp('[a-z]'), + uppercaseCharRegExp: new RegExp('[A-Z]'), + numericalValueRegExp: new RegExp('\\d'), + specialCharRegExp: new RegExp('[!@#$%^&*()_+{}\\[\\]:;<>,.?~\\\\/-]'), + }; + + const handlePasswordCheck = (pass: string): void => { + setShowAlert({ + lowercaseChar: !passwordValidationRegExp.lowercaseCharRegExp.test(pass), + uppercaseChar: !passwordValidationRegExp.uppercaseCharRegExp.test(pass), + numericValue: !passwordValidationRegExp.numericalValueRegExp.test(pass), + specialChar: !passwordValidationRegExp.specialCharRegExp.test(pass), + }); + }; + + const handleRoleToggle = (role: 'admin' | 'user'): void => { + setRole(role); + }; useEffect(() => { - const isLoggedIn = localStorage.getItem('IsLoggedIn'); + const isLoggedIn = getItem('IsLoggedIn'); if (isLoggedIn == 'TRUE') { - window.location.assign('/orglist'); + navigate(getItem('userId') !== null ? '/user/organizations' : '/orglist'); } setComponentLoader(false); }, []); @@ -60,20 +106,20 @@ function loginPage(): JSX.Element { const toggleConfirmPassword = (): void => setShowConfirmPassword(!showConfirmPassword); - // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { data, loading, refetch } = useQuery(GET_COMMUNITY_DATA); + useEffect(() => { + // refetching the data if the pre-login data updates + refetch(); + }, [data]); const [login, { loading: loginLoading }] = useMutation(LOGIN_MUTATION); - // eslint-disable-next-line @typescript-eslint/no-unused-vars const [signup, { loading: signinLoading }] = useMutation(SIGNUP_MUTATION); - // eslint-disable-next-line @typescript-eslint/no-unused-vars const [recaptcha, { loading: recaptchaLoading }] = useMutation(RECAPTCHA_MUTATION); - useEffect(() => { async function loadResource(): Promise { try { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const response = await fetch('http://localhost:4000/graphql/'); - } catch (error: any) { + await fetch(BACKEND_URL as string); + } catch (error) { /* istanbul ignore next */ errorHandler(t, error); } @@ -83,7 +129,7 @@ function loginPage(): JSX.Element { }, []); const verifyRecaptcha = async ( - recaptchaToken: any + recaptchaToken: string | null, ): Promise => { try { /* istanbul ignore next */ @@ -97,33 +143,50 @@ function loginPage(): JSX.Element { }); return data.recaptcha; - } catch (error: any) { + } catch (error) { /* istanbul ignore next */ toast.error(t('captchaError')); } }; + const handleCaptcha = (token: string | null): void => { + setRecaptchaToken(token); + }; + const signupLink = async (e: ChangeEvent): Promise => { e.preventDefault(); const { signfirstName, signlastName, signEmail, signPassword, cPassword } = signformState; - const recaptchaToken = recaptchaRef.current?.getValue(); - recaptchaRef.current?.reset(); - const isVerified = await verifyRecaptcha(recaptchaToken); /* istanbul ignore next */ if (!isVerified) { toast.error(t('Please_check_the_captcha')); return; } + const isValidatedString = (value: string): boolean => + /^[a-zA-Z]+$/.test(value); + + const validatePassword = (password: string): boolean => { + const lengthCheck = new RegExp('^.{6,}$'); + return ( + lengthCheck.test(password) && + passwordValidationRegExp.lowercaseCharRegExp.test(password) && + passwordValidationRegExp.uppercaseCharRegExp.test(password) && + passwordValidationRegExp.numericalValueRegExp.test(password) && + passwordValidationRegExp.specialCharRegExp.test(password) + ); + }; if ( + isValidatedString(signfirstName) && + isValidatedString(signlastName) && signfirstName.length > 1 && signlastName.length > 1 && signEmail.length >= 8 && - signPassword.length > 1 + signPassword.length > 1 && + validatePassword(signPassword) ) { if (cPassword == signPassword) { try { @@ -139,9 +202,9 @@ function loginPage(): JSX.Element { /* istanbul ignore next */ if (signUpData) { toast.success( - 'Successfully Registered. Please wait until you will be approved.' + t(role === 'admin' ? 'successfullyRegistered' : 'afterRegister'), ); - + setShowTab('LOGIN'); setSignFormState({ signfirstName: '', signlastName: '', @@ -150,7 +213,7 @@ function loginPage(): JSX.Element { cPassword: '', }); } - } catch (error: any) { + } catch (error) { /* istanbul ignore next */ errorHandler(t, error); } @@ -158,16 +221,23 @@ function loginPage(): JSX.Element { toast.warn(t('passwordMismatches')); } } else { - toast.warn(t('fillCorrectly')); + if (!isValidatedString(signfirstName)) { + toast.warn(t('firstName_invalid')); + } + if (!isValidatedString(signlastName)) { + toast.warn(t('lastName_invalid')); + } + if (!validatePassword(signPassword)) { + toast.warn(t('password_invalid')); + } + if (signEmail.length < 8) { + toast.warn(t('email_invalid')); + } } }; const loginLink = async (e: ChangeEvent): Promise => { e.preventDefault(); - - const recaptchaToken = recaptchaRef.current?.getValue(); - recaptchaRef.current?.reset(); - const isVerified = await verifyRecaptcha(recaptchaToken); /* istanbul ignore next */ if (!isVerified) { @@ -185,34 +255,78 @@ function loginPage(): JSX.Element { /* istanbul ignore next */ if (loginData) { - if ( - loginData.login.user.userType === 'SUPERADMIN' || - (loginData.login.user.userType === 'ADMIN' && - loginData.login.user.adminApproved === true) - ) { - localStorage.setItem('token', loginData.login.accessToken); - localStorage.setItem('refreshToken', loginData.login.refreshToken); - localStorage.setItem('id', loginData.login.user._id); - localStorage.setItem('IsLoggedIn', 'TRUE'); - localStorage.setItem('UserType', loginData.login.user.userType); - if (localStorage.getItem('IsLoggedIn') == 'TRUE') { - window.location.replace('/orglist'); - } - } else { + const { login } = loginData; + const { user, appUserProfile } = login; + const isAdmin: boolean = + appUserProfile.isSuperAdmin || appUserProfile.adminFor.length !== 0; + + if (role === 'admin' && !isAdmin) { toast.warn(t('notAuthorised')); + return; } + const loggedInUserId = user._id; + + setItem('token', login.accessToken); + setItem('refreshToken', login.refreshToken); + setItem('IsLoggedIn', 'TRUE'); + setItem('name', `${user.firstName} ${user.lastName}`); + setItem('email', user.email); + setItem('FirstName', user.firstName); + setItem('LastName', user.lastName); + setItem('UserImage', user.image); + + if (role === 'admin') { + setItem('id', loggedInUserId); + setItem('SuperAdmin', appUserProfile.isSuperAdmin); + setItem('AdminFor', appUserProfile.adminFor); + } else { + setItem('userId', loggedInUserId); + } + + navigate(role === 'admin' ? '/orglist' : '/user/organizations'); } else { toast.warn(t('notFound')); } - } catch (error: any) { + } catch (error) { /* istanbul ignore next */ errorHandler(t, error); } }; - if (componentLoader || loginLoading || signinLoading || recaptchaLoading) { + if ( + componentLoader || + loginLoading || + signinLoading || + recaptchaLoading || + loading + ) { return ; } + const socialIconsList = socialMediaLinks.map(({ href, logo, tag }, index) => + data?.getCommunityData ? ( + data.getCommunityData?.socialMediaUrls?.[tag] && ( + + + + ) + ) : ( + + + + ), + ); return ( <> @@ -220,20 +334,50 @@ function loginPage(): JSX.Element {
    - -

    {t('fromPalisadoes')}

    + {data?.getCommunityData ? ( + + Community Logo +

    {data.getCommunityData.name}

    +
    + ) : ( + + +

    {t('fromPalisadoes')}

    +
    + )}
    +
    {socialIconsList}
    + + + {/* LOGIN FORM */}

    - {t('login_to_admin_portal')} + {role === 'admin' ? t('login') : t('userLogin')}

    {t('email')}
    - {t('password')} + {t('password')}
    ) : ( @@ -329,7 +472,7 @@ function loginPage(): JSX.Element { > {t('login')} -
    +

    {t('OR')}
    @@ -397,29 +540,31 @@ function loginPage(): JSX.Element {
    - {t('email')}
    - { - setSignFormState({ - ...signformState, - signEmail: e.target.value.toLowerCase(), - }); - }} - /> - + {t('email')} +
    + { + setSignFormState({ + ...signformState, + signEmail: e.target.value.toLowerCase(), + }); + }} + /> + +
    @@ -439,6 +584,7 @@ function loginPage(): JSX.Element { ...signformState, signPassword: e.target.value, }); + handlePasswordCheck(e.target.value); }} />
    - {isInputFocused && - signformState.signPassword.length < 8 && ( -
    + {isInputFocused ? ( + signformState.signPassword.length < 6 ? ( +
    +

    + + + + {t('atleast_6_char_long')} +

    +
    + ) : ( +

    + + + + {t('atleast_6_char_long')} +

    + ) + ) : null} + + {!isInputFocused && + signformState.signPassword.length > 0 && + signformState.signPassword.length < 6 && ( +
    + + + + {t('atleast_6_char_long')} +
    + )} + {isInputFocused && ( +

    - {t('atleast_8_char_long')} -

    + {showAlert.lowercaseChar ? ( + + + + ) : ( + + + + )} + {t('lowercase_check')} +

    )} - {!isInputFocused && - signformState.signPassword.length > 0 && - signformState.signPassword.length < 8 && ( -
    - {t('atleast_8_char_long')} -
    + {showAlert.uppercaseChar ? ( + + + + ) : ( + + + + )} + {t('uppercase_check')} +

    )} + {isInputFocused && ( +

    + {showAlert.numericValue ? ( + + + + ) : ( + + + + )} + {t('numeric_value_check')} +

    + )} + {isInputFocused && ( +

    + {showAlert.specialChar ? ( + + + + ) : ( + + + + )} + {t('special_char_check')} +

    + )} +
    {t('confirmPassword')} @@ -516,11 +764,11 @@ function loginPage(): JSX.Element { {REACT_APP_USE_RECAPTCHA === 'yes' ? (
    ) : ( @@ -559,6 +807,6 @@ function loginPage(): JSX.Element { ); -} +}; export default loginPage; diff --git a/src/screens/MemberDetail/MemberDetail.module.css b/src/screens/MemberDetail/MemberDetail.module.css index 101dcb64e3..603e55d1d9 100644 --- a/src/screens/MemberDetail/MemberDetail.module.css +++ b/src/screens/MemberDetail/MemberDetail.module.css @@ -152,7 +152,9 @@ outline: none; font-weight: 600; cursor: pointer; - transition: transform 0.2s, box-shadow 0.2s; + transition: + transform 0.2s, + box-shadow 0.2s; background-color: #31bb6b; margin-right: 13px; } @@ -242,7 +244,9 @@ outline: none; font-weight: 600; cursor: pointer; - transition: transform 0.2s, box-shadow 0.2s; + transition: + transform 0.2s, + box-shadow 0.2s; width: 100%; } @@ -444,3 +448,76 @@ .inactiveBtn:hover i { color: #31bb6b; } + +.topRadius { + border-top-left-radius: 16px; + border-top-right-radius: 16px; +} + +.inputColor { + background: #f1f3f6; +} + +.width60 { + width: 60%; +} + +.maxWidth40 { + max-width: 40%; +} + +.allRound { + border-radius: 16px; +} + +.WidthFit { + width: fit-content; +} + +.datebox { + border-radius: 7px; + border-color: #e8e5e5; + outline: none; + box-shadow: none; + padding-top: 2px; + padding-bottom: 2px; + padding-right: 5px; + padding-left: 5px; + margin-right: 5px; + margin-left: 5px; +} + +.datebox > div > input { + padding: 0.5rem 0 0.5rem 0.5rem !important; /* top, right, bottom, left */ + background-color: #f1f3f6; + border-radius: var(--bs-border-radius) !important; + border: none !important; +} + +.datebox > div > div { + margin-left: 0px !important; +} + +.datebox > div > fieldset { + border: none !important; + /* background-color: #f1f3f6; */ + border-radius: var(--bs-border-radius) !important; +} + +.datebox > div { + margin: 0.5rem !important; + background-color: #f1f3f6; +} + +input::file-selector-button { + background-color: black; + color: white; +} + +.noOutline { + outline: none; +} + +.Outline { + outline: 1px solid var(--bs-gray-400); +} diff --git a/src/screens/MemberDetail/MemberDetail.test.tsx b/src/screens/MemberDetail/MemberDetail.test.tsx index a4b29fb604..e094354552 100644 --- a/src/screens/MemberDetail/MemberDetail.test.tsx +++ b/src/screens/MemberDetail/MemberDetail.test.tsx @@ -1,17 +1,22 @@ import React from 'react'; +import { + act, + fireEvent, + render, + screen, + waitFor, +} from '@testing-library/react'; import { MockedProvider } from '@apollo/react-testing'; -import { act, render, screen, waitFor } from '@testing-library/react'; -import { ADD_ADMIN_MUTATION } from 'GraphQl/Mutations/mutations'; -import { USER_DETAILS } from 'GraphQl/Queries/Queries'; -import 'jest-location-mock'; -import { I18nextProvider } from 'react-i18next'; -import { Provider } from 'react-redux'; +import userEvent from '@testing-library/user-event'; import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; import { store } from 'state/store'; +import { I18nextProvider } from 'react-i18next'; +import { USER_DETAILS } from 'GraphQl/Queries/Queries'; import i18nForTest from 'utils/i18nForTest'; -import MemberDetail, { getLanguageName, prettyDate } from './MemberDetail'; -import userEvent from '@testing-library/user-event'; import { StaticMockLink } from 'utils/StaticMockLink'; +import MemberDetail, { getLanguageName, prettyDate } from './MemberDetail'; +import { toast } from 'react-toastify'; const MOCKS1 = [ { @@ -24,44 +29,91 @@ const MOCKS1 = [ result: { data: { user: { - __typename: 'User', - image: null, - firstName: 'Rishav', - lastName: 'Jha', - email: 'ris@gmail.com', - role: 'SUPERADMIN', - appLanguageCode: 'en', - userType: 'SUPERADMIN', - pluginCreationAllowed: true, - adminApproved: true, - createdAt: '2023-02-18T09:22:27.969Z', - adminFor: [], - createdOrganizations: [], - joinedOrganizations: [], - organizationUserBelongsTo: null, - organizationsBlockedBy: [], - createdEvents: [], - registeredEvents: [], - eventAdmin: [], - membershipRequests: [], + __typename: 'UserData', + appUserProfile: { + _id: '1', + __typename: 'AppUserProfile', + adminFor: [ + { + __typename: 'Organization', + _id: '65e0df0906dd1228350cfd4a', + }, + { + __typename: 'Organization', + _id: '65e0e2abb92c9f3e29503d4e', + }, + ], + isSuperAdmin: false, + appLanguageCode: 'en', + createdEvents: [ + { + __typename: 'Event', + _id: '65e32a5b2a1f4288ca1f086a', + }, + ], + createdOrganizations: [ + { + __typename: 'Organization', + _id: '65e0df0906dd1228350cfd4a', + }, + { + __typename: 'Organization', + _id: '65e0e2abb92c9f3e29503d4e', + }, + ], + eventAdmin: [ + { + __typename: 'Event', + _id: '65e32a5b2a1f4288ca1f086a', + }, + ], + pluginCreationAllowed: true, + }, + user: { + _id: '1', + __typename: 'User', + createdAt: '2024-02-26T10:36:33.098Z', + email: 'adi790u@gmail.com', + firstName: 'Aditya', + image: null, + lastName: 'Agarwal', + gender: '', + birthDate: '2024-03-14', + educationGrade: '', + employmentStatus: '', + maritalStatus: '', + address: { + line1: '', + countryCode: '', + city: '', + state: '', + }, + phone: { + mobile: '', + }, + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '65e0df0906dd1228350cfd4a', + }, + { + __typename: 'Organization', + _id: '65e0e2abb92c9f3e29503d4e', + }, + ], + membershipRequests: [], + organizationsBlockedBy: [], + registeredEvents: [ + { + __typename: 'Event', + _id: '65e32a5b2a1f4288ca1f086a', + }, + ], + }, }, }, }, }, - { - request: { - query: ADD_ADMIN_MUTATION, - variables: { - userid: '123', - orgid: '456', - }, - }, - result: { - data: { - success: true, - }, - }, - }, ]; const MOCKS2 = [ @@ -75,55 +127,188 @@ const MOCKS2 = [ result: { data: { user: { - __typename: 'User', - image: 'https://placeholder.com/200x200', - firstName: 'Rishav', - lastName: 'Jha', - email: 'ris@gmail.com', - role: 'SUPERADMIN', - appLanguageCode: 'en', - userType: 'SUPERADMIN', - pluginCreationAllowed: false, - adminApproved: false, - createdAt: '2023-02-18T09:22:27.969Z', - adminFor: [], - createdOrganizations: [], - joinedOrganizations: [], - organizationUserBelongsTo: null, - organizationsBlockedBy: [], - createdEvents: [], - registeredEvents: [], - eventAdmin: [], - membershipRequests: [], + __typename: 'UserData', + appUserProfile: { + _id: '1', + __typename: 'AppUserProfile', + adminFor: [], + isSuperAdmin: false, + appLanguageCode: 'en', + createdEvents: [ + { + __typename: 'Event', + _id: '65e32a5b2a1f4288ca1f086a', + }, + ], + createdOrganizations: [ + { + __typename: 'Organization', + _id: '65e0df0906dd1228350cfd4a', + }, + { + __typename: 'Organization', + _id: '65e0e2abb92c9f3e29503d4e', + }, + ], + eventAdmin: [ + { + __typename: 'Event', + _id: '65e32a5b2a1f4288ca1f086a', + }, + ], + pluginCreationAllowed: true, + }, + user: { + _id: '1', + __typename: 'User', + createdAt: '2024-02-26T10:36:33.098Z', + email: 'adi790u@gmail.com', + firstName: 'Aditya', + image: 'https://placeholder.com/200x200', + lastName: 'Agarwal', + gender: '', + birthDate: '2024-03-14', + educationGrade: '', + employmentStatus: '', + maritalStatus: '', + address: { + line1: '', + countryCode: '', + city: '', + state: '', + }, + phone: { + mobile: '', + }, + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '65e0df0906dd1228350cfd4a', + }, + { + __typename: 'Organization', + _id: '65e0e2abb92c9f3e29503d4e', + }, + ], + membershipRequests: [], + organizationsBlockedBy: [], + registeredEvents: [ + { + __typename: 'Event', + _id: '65e32a5b2a1f4288ca1f086a', + }, + ], + }, }, }, }, }, +]; +const MOCKS3 = [ { request: { - query: ADD_ADMIN_MUTATION, + query: USER_DETAILS, variables: { - userid: '123', - orgid: '456', + id: 'rishav-jha-mech', }, }, result: { data: { - success: true, + user: { + __typename: 'UserData', + appUserProfile: { + _id: '1', + __typename: 'AppUserProfile', + adminFor: [], + isSuperAdmin: true, + appLanguageCode: 'en', + createdEvents: [ + { + __typename: 'Event', + _id: '65e32a5b2a1f4288ca1f086a', + }, + ], + createdOrganizations: [ + { + __typename: 'Organization', + _id: '65e0df0906dd1228350cfd4a', + }, + { + __typename: 'Organization', + _id: '65e0e2abb92c9f3e29503d4e', + }, + ], + eventAdmin: [ + { + __typename: 'Event', + _id: '65e32a5b2a1f4288ca1f086a', + }, + ], + pluginCreationAllowed: true, + }, + user: { + _id: '1', + __typename: 'User', + createdAt: '2024-02-26T10:36:33.098Z', + email: 'adi790u@gmail.com', + firstName: 'Aditya', + image: 'https://placeholder.com/200x200', + lastName: 'Agarwal', + gender: '', + birthDate: '2024-03-14', + educationGrade: '', + employmentStatus: '', + maritalStatus: '', + address: { + line1: '', + countryCode: '', + city: '', + state: '', + }, + phone: { + mobile: '', + }, + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '65e0df0906dd1228350cfd4a', + }, + { + __typename: 'Organization', + _id: '65e0e2abb92c9f3e29503d4e', + }, + ], + membershipRequests: [], + organizationsBlockedBy: [], + registeredEvents: [ + { + __typename: 'Event', + _id: '65e32a5b2a1f4288ca1f086a', + }, + ], + }, + }, }, }, }, ]; + const link1 = new StaticMockLink(MOCKS1, true); const link2 = new StaticMockLink(MOCKS2, true); -async function wait(ms = 2): Promise { - await act(() => { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); - }); +const link3 = new StaticMockLink(MOCKS3, true); + +async function wait(ms = 20): Promise { + await act(() => new Promise((resolve) => setTimeout(resolve, ms))); } +jest.mock('@mui/x-date-pickers/DateTimePicker', () => { + return { + DateTimePicker: jest.requireActual( + '@mui/x-date-pickers/DesktopDateTimePicker', + ).DesktopDateTimePicker, + }; +}); + jest.mock('react-toastify'); describe('MemberDetail', () => { @@ -134,8 +319,8 @@ describe('MemberDetail', () => { id: 'rishav-jha-mech', }; - const { container, getByTestId } = render( - + render( + @@ -143,47 +328,34 @@ describe('MemberDetail', () => { - + , ); - expect(container.textContent).not.toBe('Loading data...'); + expect(screen.queryByText('Loading data...')).not.toBeInTheDocument(); await wait(); - - userEvent.click(screen.getByText(/Add Admin/i)); - - expect(getByTestId(/dashboardTitleBtn/i)).toBeInTheDocument(); - expect(getByTestId(/dashboardTitleBtn/i)).toHaveTextContent('User Details'); expect(screen.getAllByText(/Email/i)).toBeTruthy(); - expect(screen.getAllByText(/Main/i)).toBeTruthy(); expect(screen.getAllByText(/First name/i)).toBeTruthy(); expect(screen.getAllByText(/Last name/i)).toBeTruthy(); - expect(screen.getAllByText(/Member of Organization/i)).toBeTruthy(); expect(screen.getAllByText(/Language/i)).toBeTruthy(); - expect(screen.getByText(/Admin approved/i)).toBeInTheDocument(); expect(screen.getByText(/Plugin creation allowed/i)).toBeInTheDocument(); - expect(screen.getAllByText(/Created on/i)).toBeTruthy(); - expect(screen.getAllByText(/Admin for organizations/i)).toBeTruthy(); - expect(screen.getAllByText(/Membership requests/i)).toBeTruthy(); - expect(screen.getAllByText(/Events/i)).toBeTruthy(); - expect(screen.getAllByText(/Admin for events/i)).toBeTruthy(); - - expect(screen.getAllByText(/Created On/i)).toHaveLength(2); - expect(screen.getAllByText(/User Details/i)).toHaveLength(3); - expect(screen.getAllByText(/Role/i)).toHaveLength(2); - expect(screen.getAllByText(/Created/i)).toHaveLength(4); - expect(screen.getAllByText(/Joined/i)).toHaveLength(2); - expect(screen.getByTestId('stateBtn')).toBeInTheDocument(); - userEvent.click(screen.getByTestId('stateBtn')); + expect(screen.getAllByText(/Joined on/i)).toBeTruthy(); + expect(screen.getAllByText(/Joined On/i)).toHaveLength(1); + expect(screen.getAllByText(/Personal Information/i)).toHaveLength(1); + expect(screen.getAllByText(/Profile Details/i)).toHaveLength(1); + expect(screen.getAllByText(/Actions/i)).toHaveLength(1); + expect(screen.getAllByText(/Contact Information/i)).toHaveLength(1); }); + test('prettyDate function should work properly', () => { // If the date is provided const datePretty = jest.fn(prettyDate); expect(datePretty('2023-02-18T09:22:27.969Z')).toBe( - prettyDate('2023-02-18T09:22:27.969Z') + prettyDate('2023-02-18T09:22:27.969Z'), ); // If there's some error in formatting the date expect(datePretty('')).toBe('Unavailable'); }); + test('getLanguageName function should work properly', () => { const getLangName = jest.fn(getLanguageName); // If the language code is provided @@ -192,13 +364,25 @@ describe('MemberDetail', () => { expect(getLangName('')).toBe('Unavailable'); }); - test('Should display dicebear image if image is null', async () => { + test('should render props and text elements test for the page component', async () => { const props = { - id: 'rishav-jha-mech', + id: '1', }; - const { container } = render( - + const formData = { + firstName: 'Ansh', + lastName: 'Goyal', + email: 'ansh@gmail.com', + image: new File(['hello'], 'hello.png', { type: 'image/png' }), + address: 'abc', + countryCode: 'IN', + state: 'abc', + city: 'abc', + phoneNumber: '1234567890', + birthDate: '03/28/2022', + }; + render( + @@ -206,28 +390,64 @@ describe('MemberDetail', () => { - + , ); + expect(screen.queryByText('Loading data...')).not.toBeInTheDocument(); + await wait(); + expect(screen.getAllByText(/Email/i)).toBeTruthy(); + expect(screen.getByText('User')).toBeInTheDocument(); + const birthDateDatePicker = screen.getByTestId('birthDate'); + fireEvent.change(birthDateDatePicker, { + target: { value: formData.birthDate }, + }); + + userEvent.type( + screen.getByPlaceholderText(/First Name/i), + formData.firstName, + ); + userEvent.type( + screen.getByPlaceholderText(/Last Name/i), + formData.lastName, + ); + userEvent.type(screen.getByPlaceholderText(/Address/i), formData.address); + userEvent.type( + screen.getByPlaceholderText(/Country Code/i), + formData.countryCode, + ); + userEvent.type(screen.getByPlaceholderText(/State/i), formData.state); + userEvent.type(screen.getByPlaceholderText(/City/i), formData.city); + userEvent.type(screen.getByPlaceholderText(/Email/i), formData.email); + userEvent.type(screen.getByPlaceholderText(/Phone/i), formData.phoneNumber); + userEvent.click(screen.getByPlaceholderText(/pluginCreationAllowed/i)); + userEvent.selectOptions(screen.getByTestId('applangcode'), 'Français'); + userEvent.upload(screen.getByLabelText(/Display Image:/i), formData.image); + await wait(); - expect(container.textContent).not.toBe('Loading data...'); - const user = MOCKS1[0].result.data.user; + userEvent.click(screen.getByText(/Save Changes/i)); - waitFor(() => - expect(screen.getByTestId(/userImageAbsent/i)).toBeInTheDocument() + expect(screen.getByPlaceholderText(/First Name/i)).toHaveValue( + formData.firstName, ); - waitFor(() => - expect(screen.getByTestId(/userImageAbsent/i).getAttribute('src')).toBe( - `https://api.dicebear.com/5.x/initials/svg?seed=${user?.firstName} ${user?.lastName}` - ) + expect(screen.getByPlaceholderText(/Last Name/i)).toHaveValue( + formData.lastName, ); + expect(birthDateDatePicker).toHaveValue(formData.birthDate); + expect(screen.getByPlaceholderText(/Email/i)).toHaveValue(formData.email); + expect(screen.getByPlaceholderText(/First Name/i)).toBeInTheDocument(); + expect(screen.getByPlaceholderText(/Last Name/i)).toBeInTheDocument(); + expect(screen.getByPlaceholderText(/Email/i)).toBeInTheDocument(); + expect(screen.getByText(/Display Image/i)).toBeInTheDocument(); }); - test('Should display image if image is present', async () => { + test('should display warnings for blank form submission', async () => { + jest.spyOn(toast, 'warning'); const props = { - id: 'rishav-jha-mech', + key: '123', + id: '1', + toggleStateValue: jest.fn(), }; - const { container } = render( + render( @@ -236,27 +456,67 @@ describe('MemberDetail', () => { - + , ); - expect(container.textContent).not.toBe('Loading data...'); + await wait(); + + userEvent.click(screen.getByText(/Save Changes/i)); - const user = MOCKS2[0].result.data.user; + expect(toast.warning).toHaveBeenCalledWith('First Name cannot be blank!'); + expect(toast.warning).toHaveBeenCalledWith('Last Name cannot be blank!'); + expect(toast.warning).toHaveBeenCalledWith('Email cannot be blank!'); + }); + test('display admin', async () => { + const props = { + id: 'rishav-jha-mech', + }; - waitFor(() => - expect(screen.getByTestId(/userImagePresent/i)).toBeInTheDocument() + render( + + + + + + + + + , ); - waitFor(() => - expect(screen.getByTestId(/userImagePresent/i).getAttribute('src')).toBe( - user?.image - ) + + expect(screen.queryByText('Loading data...')).not.toBeInTheDocument(); + await wait(); + expect(screen.getByText('Admin')).toBeInTheDocument(); + }); + test('display super admin', async () => { + const props = { + id: 'rishav-jha-mech', + }; + + render( + + + + + + + + + , ); + + expect(screen.queryByText('Loading data...')).not.toBeInTheDocument(); + await wait(); + expect(screen.getByText('Super Admin')).toBeInTheDocument(); }); - test('should call setState with 2 when button is clicked', async () => { + + test('Should display dicebear image if image is null', async () => { const props = { id: 'rishav-jha-mech', + from: 'orglist', }; - const { container } = render( + + render( @@ -265,19 +525,25 @@ describe('MemberDetail', () => { - + , ); + expect(screen.queryByText('Loading data...')).not.toBeInTheDocument(); - expect(container.textContent).not.toBe('Loading data...'); + const dicebearUrl = `mocked-data-uri`; - waitFor(() => userEvent.click(screen.getByText(/Edit Profile/i))); + const userImage = await screen.findByTestId('userImageAbsent'); + expect(userImage).toBeInTheDocument(); + expect(userImage.getAttribute('src')).toBe(dicebearUrl); }); - test('should show Yes if plugin creation is allowed and admin approved', async () => { + + test('Should display image if image is present', async () => { const props = { id: 'rishav-jha-mech', + from: 'orglist', }; + render( - + @@ -285,11 +551,18 @@ describe('MemberDetail', () => { - + , ); - waitFor(() => expect(screen.getByText('Yes')).toHaveLength(2)); + + expect(screen.queryByText('Loading data...')).not.toBeInTheDocument(); + + const user = MOCKS2[0].result?.data?.user?.user; + const userImage = await screen.findByTestId('userImagePresent'); + expect(userImage).toBeInTheDocument(); + expect(userImage.getAttribute('src')).toBe(user?.image); }); - test('should show No if plugin creation is not allowed and not admin approved', async () => { + + test('should call setState with 2 when button is clicked', async () => { const props = { id: 'rishav-jha-mech', }; @@ -302,8 +575,26 @@ describe('MemberDetail', () => { - + , + ); + + expect(screen.queryByText('Loading data...')).not.toBeInTheDocument(); + + waitFor(() => userEvent.click(screen.getByText(/Edit Profile/i))); + }); + + test('should be redirected to / if member id is undefined', async () => { + render( + + + + + + + + + , ); - waitFor(() => expect(screen.getAllByText('No')).toHaveLength(2)); + expect(window.location.pathname).toEqual('/'); }); }); diff --git a/src/screens/MemberDetail/MemberDetail.tsx b/src/screens/MemberDetail/MemberDetail.tsx index d190b47246..7e9213bd3e 100644 --- a/src/screens/MemberDetail/MemberDetail.tsx +++ b/src/screens/MemberDetail/MemberDetail.tsx @@ -1,316 +1,553 @@ -import React, { useState } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import { useMutation, useQuery } from '@apollo/client'; -import Col from 'react-bootstrap/Col'; -import Row from 'react-bootstrap/Row'; import Button from 'react-bootstrap/Button'; import { useTranslation } from 'react-i18next'; import { useLocation } from 'react-router-dom'; -import UserUpdate from 'components/UserUpdate/UserUpdate'; - -import OrganizationScreen from 'components/OrganizationScreen/OrganizationScreen'; import { USER_DETAILS } from 'GraphQl/Queries/Queries'; import styles from './MemberDetail.module.css'; import { languages } from 'utils/languages'; -import { ADD_ADMIN_MUTATION } from 'GraphQl/Mutations/mutations'; +import { UPDATE_USER_MUTATION } from 'GraphQl/Mutations/mutations'; import { toast } from 'react-toastify'; import { errorHandler } from 'utils/errorHandler'; import Loader from 'components/Loader/Loader'; +import useLocalStorage from 'utils/useLocalstorage'; +import Avatar from 'components/Avatar/Avatar'; +import { + CalendarIcon, + DatePicker, + LocalizationProvider, +} from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { Form } from 'react-bootstrap'; +import convertToBase64 from 'utils/convertToBase64'; +import sanitizeHtml from 'sanitize-html'; +import type { Dayjs } from 'dayjs'; +import dayjs from 'dayjs'; +import { + educationGradeEnum, + maritalStatusEnum, + genderEnum, + employmentStatusEnum, +} from 'utils/formEnumFields'; +import DynamicDropDown from 'components/DynamicDropDown/DynamicDropDown'; type MemberDetailProps = { - id: string; // This is the userId + id?: string; // This is the userId }; const MemberDetail: React.FC = ({ id }): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'memberDetail', }); - - const [state, setState] = useState(1); - - const location = useLocation(); - const currentUrl = location.state?.id || localStorage.getItem('id') || id; + const location = useLocation(); + const isMounted = useRef(true); + const { getItem, setItem } = useLocalStorage(); + const currentUrl = location.state?.id || getItem('id') || id; document.title = t('title'); - - const [adda] = useMutation(ADD_ADMIN_MUTATION); - const { - data: userData, - loading: loading, - error: error, - refetch: refetch, - } = useQuery(USER_DETAILS, { + const [formState, setFormState] = useState({ + firstName: '', + lastName: '', + email: '', + appLanguageCode: '', + image: '', + gender: '', + birthDate: '2024-03-14', + grade: '', + empStatus: '', + maritalStatus: '', + phoneNumber: '', + address: '', + state: '', + city: '', + country: '', + pluginCreationAllowed: false, + }); + // Handle date change + const handleDateChange = (date: Dayjs | null): void => { + if (date) { + setFormState((prevState) => ({ + ...prevState, + birthDate: dayjs(date).format('YYYY-MM-DD'), // Convert Dayjs object to JavaScript Date object + })); + } + }; + const [updateUser] = useMutation(UPDATE_USER_MUTATION); + const { data: user, loading: loading } = useQuery(USER_DETAILS, { variables: { id: currentUrl }, // For testing we are sending the id as a prop }); + const userData = user?.user; - /* istanbul ignore next */ - const toggleStateValue = (): void => { - if (state === 1) setState(2); - else setState(1); - refetch(); + useEffect(() => { + if (userData && isMounted) { + // console.log(userData); + setFormState({ + ...formState, + firstName: userData?.user?.firstName, + lastName: userData?.user?.lastName, + email: userData?.user?.email, + appLanguageCode: userData?.appUserProfile?.appLanguageCode, + gender: userData?.user?.gender, + birthDate: userData?.user?.birthDate || '2020-03-14', + grade: userData?.user?.educationGrade, + empStatus: userData?.user?.employmentStatus, + maritalStatus: userData?.user?.maritalStatus, + phoneNumber: userData?.user?.phone?.mobile, + address: userData.user?.address?.line1, + state: userData?.user?.address?.state, + city: userData?.user?.address?.city, + country: userData?.user?.address?.countryCode, + pluginCreationAllowed: userData?.appUserProfile?.pluginCreationAllowed, + image: userData?.user?.image || '', + }); + } + }, [userData, user]); + + useEffect(() => { + // check component is mounted or not + return () => { + isMounted.current = false; + }; + }, []); + + const handleChange = (e: React.ChangeEvent): void => { + const { name, value } = e.target; + // setFormState({ + // ...formState, + // [name]: value, + // }); + // console.log(name, value); + setFormState((prevState) => ({ + ...prevState, + [name]: value, + })); + // console.log(formState); }; - if (loading) { - return ; - } + // const handlePhoneChange = (e: React.ChangeEvent): void => { + // const { name, value } = e.target; + // setFormState({ + // ...formState, + // phoneNumber: { + // ...formState.phoneNumber, + // [name]: value, + // }, + // }); + // // console.log(formState); + // }; - /* istanbul ignore next */ - if (error) { - window.location.assign(`/orgpeople/id=${currentUrl}`); - } + const handleToggleChange = (e: React.ChangeEvent): void => { + // console.log(e.target.checked); + const { name, checked } = e.target; + setFormState((prevState) => ({ + ...prevState, + [name]: checked, + })); + // console.log(formState); + }; - const addAdmin = async (): Promise => { + const loginLink = async (): Promise => { try { - const { data } = await adda({ - variables: { - userid: location.state?.id, - orgid: currentUrl, - }, - }); - - /* istanbul ignore next */ - if (data) { - toast.success(t('addedAsAdmin')); - setTimeout(() => { - window.location.reload(); - }, 2000); + // console.log(formState); + const firstName = formState.firstName; + const lastName = formState.lastName; + const email = formState.email; + // const appLanguageCode = formState.appLanguageCode; + const image = formState.image; + // const gender = formState.gender; + let toSubmit = true; + if (firstName.trim().length == 0 || !firstName) { + toast.warning('First Name cannot be blank!'); + toSubmit = false; + } + if (lastName.trim().length == 0 || !lastName) { + toast.warning('Last Name cannot be blank!'); + toSubmit = false; + } + if (email.trim().length == 0 || !email) { + toast.warning('Email cannot be blank!'); + toSubmit = false; } - } catch (error: any) { + if (!toSubmit) return; + try { + const { data } = await updateUser({ + variables: { + //! Currently only some fields are supported by the api + id: currentUrl, + ...formState, + }, + }); + /* istanbul ignore next */ + if (data) { + if (getItem('id') === currentUrl) { + setItem('FirstName', firstName); + setItem('LastName', lastName); + setItem('Email', email); + setItem('UserImage', image); + } + toast.success('Successful updated'); + } + } catch (error: unknown) { + if (error instanceof Error) { + errorHandler(t, error); + } + } + } catch (error: unknown) { /* istanbul ignore next */ - errorHandler(t, error); + if (error instanceof Error) { + errorHandler(t, error); + } } }; + if (loading) { + return ; + } + + const sanitizedSrc = sanitizeHtml(formState.image, { + allowedTags: ['img'], + allowedAttributes: { + img: ['src', 'alt'], + }, + }); + return ( - <> - - - -
    -
    -
    - +
    +
    +

    {t('educationGrade')}

    + +
    +
    +

    {t('employmentStatus')}

    + +
    +
    +

    {t('maritalStatus')}

    + +
    +

    + +

    - - - {state == 1 ? ( -
    - -

    {t('title')}

    -
    - - + {/* Contact Info */} +
    +
    +

    {t('contactInfoHeading')}

    +
    +
    +
    +

    {t('phone')}

    + +
    +
    +

    {t('email')}

    + +
    +
    +

    {t('address')}

    + +
    +
    +

    {t('countryCode')}

    + +
    +
    +

    {t('city')}

    + +
    +
    +

    {t('state')}

    + +
    +
    +
    +
    +
    + {/* Personal */} +
    +
    +

    {t('personalDetailsHeading')}

    +
    +
    +
    + {formState.image ? ( + + ) : ( + <> + + + )} +
    +
    +

    {formState?.firstName}

    +
    +

    + {userData?.appUserProfile?.isSuperAdmin + ? 'Super Admin' + : userData?.appUserProfile?.adminFor.length > 0 + ? 'Admin' + : 'User'} +

    - - - -
    - {userData?.user?.image ? ( - - ) : ( - - )} -
    - - - {/* User section */} +

    {formState.email}

    +

    + + Joined on {prettyDate(userData?.user?.createdAt)} +

    +
    +
    +
    + + {/* Actions */} +
    +
    +

    {t('actionsHeading')}

    +
    +
    +
    +
    + +

    + {`${t('pluginCreationAllowed')} (API not supported yet)`} +

    +
    +
    +
    +
    -

    - - {userData?.user?.firstName} {userData?.user?.lastName} - -

    -

    - {t('role')} :{' '} - {userData?.user?.userType} -

    -

    - {t('email')} :{' '} - {userData?.user?.email} -

    -

    - {t('createdOn')} :{' '} - {prettyDate(userData?.user?.createdAt)} -

    +
    - - -
    -
    -
    - {/* Main Section And Activity section */} -
    - - {/* Main Section */} - -
    -
    -
    - {t('main')} -
    -
    -
    - - {t('firstName')} - {userData?.user?.firstName} - - - {t('lastName')} - {userData?.user?.lastName} - - - {t('role')} - {userData?.user?.userType} - - - {t('memberOfOrganization')} - - {userData?.user?.organizationUserBelongsTo ?? - 'None'} - - - - {t('language')} - - {getLanguageName(userData?.user?.appLanguageCode)} - - - - {t('adminApproved')} - - {userData?.user?.adminApproved ? 'Yes' : 'No'} - - - - {t('pluginCreationAllowed')} - - {userData?.user?.pluginCreationAllowed - ? 'Yes' - : 'No'} - - - - {t('createdOn')} - - {prettyDate(userData?.user?.createdAt)} - - -
    -
    - - {/* Activity Section */} - - {/* Organizations */} -
    -
    -
    - {t('organizations')} -
    -
    -
    - - {t('created')} - - {userData?.user?.createdOrganizations?.length} - - - - {t('joined')} - - {userData?.user?.joinedOrganizations?.length} - - - - {t('adminForOrganizations')} - {userData?.user?.adminFor?.length} - - - {t('membershipRequests')} - - {userData?.user?.membershipRequests?.length} - - -
    -
    - {/* Events */} -
    -
    -
    - {t('events')} -
    -
    -
    - - {t('created')} - - {userData?.user?.createdEvents?.length} - - - - {t('joined')} - - {userData?.user?.registeredEvents?.length} - - - - {t('adminForEvents')} - - {userData?.user?.eventAdmin?.length} - - -
    -
    - -
    -
    +
    +
    + + +
    +
    - ) : ( - - )} - - - - +
    +
    + +
    +
    +
    +
    + ); }; - export const prettyDate = (param: string): string => { const date = new Date(param); if (date?.toDateString() === 'Invalid Date') { return 'Unavailable'; } - return `${date?.toDateString()} ${date.toLocaleTimeString()}`; + const day = date.getDate(); + const month = date.toLocaleString('default', { month: 'long' }); + const year = date.getFullYear(); + return `${day} ${month} ${year}`; }; - export const getLanguageName = (code: string): string => { let language = 'Unavailable'; languages.map((data) => { @@ -320,5 +557,4 @@ export const getLanguageName = (code: string): string => { }); return language; }; - export default MemberDetail; diff --git a/src/screens/OrgContribution/OrgContribution.module.css b/src/screens/OrgContribution/OrgContribution.module.css index 1a3930690c..7ca9333bf7 100644 --- a/src/screens/OrgContribution/OrgContribution.module.css +++ b/src/screens/OrgContribution/OrgContribution.module.css @@ -43,7 +43,6 @@ height: 100%; } .sidebar:after { - content: ''; background-color: #f7f7f7; position: absolute; width: 2px; @@ -135,7 +134,9 @@ outline: none; font-weight: 600; cursor: pointer; - transition: transform 0.2s, box-shadow 0.2s; + transition: + transform 0.2s, + box-shadow 0.2s; } .flexdir { display: flex; @@ -198,7 +199,9 @@ outline: none; font-weight: 600; cursor: pointer; - transition: transform 0.2s, box-shadow 0.2s; + transition: + transform 0.2s, + box-shadow 0.2s; width: 100%; } .sidebarsticky > input { diff --git a/src/screens/OrgContribution/OrgContribution.test.tsx b/src/screens/OrgContribution/OrgContribution.test.tsx index 3f22371014..d2abc134df 100644 --- a/src/screens/OrgContribution/OrgContribution.test.tsx +++ b/src/screens/OrgContribution/OrgContribution.test.tsx @@ -32,7 +32,7 @@ describe('Organisation Contribution Page', () => { - + , ); expect(container.textContent).not.toBe('Loading data...'); diff --git a/src/screens/OrgList/OrgList.module.css b/src/screens/OrgList/OrgList.module.css index e1f1729d18..9da1ecbb70 100644 --- a/src/screens/OrgList/OrgList.module.css +++ b/src/screens/OrgList/OrgList.module.css @@ -12,6 +12,25 @@ border: None; } +.enableEverythingBtn { + width: 100%; + border: None; +} + +.pluginStoreBtn { + width: 100%; + background-color: white; + color: #31bb6b; + border: 0.5px solid #31bb6b; +} + +.pluginStoreBtn:hover, +.pluginStoreBtn:focus { + background-color: #dfe1e2 !important; + color: #31bb6b !important; + border-color: #31bb6b !important; +} + .line::before { content: ''; display: inline-block; @@ -119,7 +138,7 @@ flex-direction: column; } -@media (max-width: 1120px) { +@media (max-width: 1440px) { .contract { padding-left: calc(250px + 2rem + 1.5rem); } @@ -241,13 +260,6 @@ form > input { margin-bottom: 0.8rem; } -.cancel > i { - margin-top: 5px; - transform: scale(1.2); - cursor: pointer; - color: #707070; -} - .modalbody { width: 50px; } @@ -257,51 +269,12 @@ form > input { gap: 1rem; } -.greenregbtn { - margin: 1rem 0 0; - margin-top: 10px; - border: 1px solid #e8e5e5; - box-shadow: 0 2px 2px #e8e5e5; - padding: 10px 10px; - border-radius: 5px; - background-color: #31bb6b; - width: 100%; - font-size: 16px; - color: white; - outline: none; - font-weight: 600; - cursor: pointer; - transition: transform 0.2s, box-shadow 0.2s; - width: 100%; -} - .itemCard .loadingWrapper .innerContainer .content h6[title='Location'] { display: block; width: 45%; height: 18px; } -.secondbtn { - display: flex; - align-items: center; - justify-content: center; - margin: 1rem 0 0; - margin-top: 10px; - border: 1px solid #d0cfcf; - box-shadow: 0 2px 2px #d0cfcf; - padding: 10px 10px; - border-radius: 5px; - background-color: white; - width: 100%; - font-size: 16px; - color: #31bb6b; - outline: none; - font-weight: 600; - cursor: pointer; - transition: transform 0.2s, box-shadow 0.2s; - width: 100%; -} - .itemCard .loadingWrapper .innerContainer .content h6 { display: block; width: 30%; diff --git a/src/screens/OrgList/OrgList.test.tsx b/src/screens/OrgList/OrgList.test.tsx index ca2e89ad98..b848b72c90 100644 --- a/src/screens/OrgList/OrgList.test.tsx +++ b/src/screens/OrgList/OrgList.test.tsx @@ -1,6 +1,14 @@ +// SKIP_LOCALSTORAGE_CHECK import React from 'react'; import { MockedProvider } from '@apollo/react-testing'; -import { act, render, screen } from '@testing-library/react'; +import { + act, + render, + screen, + fireEvent, + cleanup, + waitFor, +} from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import 'jest-localstorage-mock'; import 'jest-location-mock'; @@ -11,7 +19,19 @@ import { store } from 'state/store'; import { StaticMockLink } from 'utils/StaticMockLink'; import i18nForTest from 'utils/i18nForTest'; import OrgList from './OrgList'; -import { MOCKS, MOCKS_ADMIN, MOCKS_EMPTY } from './OrgListMocks'; + +import { + MOCKS, + MOCKS_ADMIN, + MOCKS_EMPTY, + MOCKS_WITH_ERROR, +} from './OrgListMocks'; +import { ToastContainer, toast } from 'react-toastify'; + +jest.setTimeout(30000); +import useLocalStorage from 'utils/useLocalstorage'; + +const { setItem } = useLocalStorage(); async function wait(ms = 100): Promise { await act(() => { @@ -23,23 +43,60 @@ async function wait(ms = 100): Promise { afterEach(() => { localStorage.clear(); + cleanup(); }); describe('Organisations Page testing as SuperAdmin', () => { - localStorage.setItem('id', '123'); + setItem('id', '123'); const link = new StaticMockLink(MOCKS, true); const link2 = new StaticMockLink(MOCKS_EMPTY, true); + const link3 = new StaticMockLink(MOCKS_WITH_ERROR, true); const formData = { name: 'Dummy Organization', description: 'This is a dummy organization', - location: 'Delhi, India', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, image: new File(['hello'], 'hello.png', { type: 'image/png' }), }; + test('Should display organisations for superAdmin even if admin For field is empty', async () => { + window.location.assign('/'); + setItem('id', '123'); + setItem('SuperAdmin', true); + setItem('AdminFor', []); + + render( + + + + + + + + + , + ); + + await wait(); + expect( + screen.queryByText('Organizations Not Found'), + ).not.toBeInTheDocument(); + }); + + test('Testing search functionality by pressing enter', async () => { + setItem('id', '123'); + setItem('SuperAdmin', true); + setItem('AdminFor', [{ name: 'adi', _id: '1234', image: '' }]); - test('Testing search functionality', async () => { - localStorage.setItem('id', '123'); render( @@ -49,19 +106,44 @@ describe('Organisations Page testing as SuperAdmin', () => { - + , ); await wait(); // Test that the search bar filters organizations by name const searchBar = screen.getByTestId(/searchByName/i); expect(searchBar).toBeInTheDocument(); + userEvent.type(searchBar, 'Dummy{enter}'); + }); + + test('Testing search functionality by Btn click', async () => { + setItem('id', '123'); + setItem('SuperAdmin', true); + setItem('AdminFor', [{ name: 'adi', _id: '1234', image: '' }]); + render( + + + + + + + + + , + ); + await wait(); + + const searchBar = screen.getByTestId('searchByName'); + const searchBtn = screen.getByTestId('searchBtn'); userEvent.type(searchBar, 'Dummy'); + fireEvent.click(searchBtn); }); test('Should render no organisation warning alert when there are no organization', async () => { window.location.assign('/'); - localStorage.setItem('id', '123'); + setItem('id', '123'); + setItem('SuperAdmin', true); + setItem('AdminFor', [{ name: 'adi', _id: '1234', image: '' }]); render( @@ -72,18 +154,22 @@ describe('Organisations Page testing as SuperAdmin', () => { - + , ); await wait(); expect(screen.queryByText('Organizations Not Found')).toBeInTheDocument(); expect( - screen.queryByText('Please create an organization through dashboard') + screen.queryByText('Please create an organization through dashboard'), ).toBeInTheDocument(); expect(window.location).toBeAt('/'); }); test('Testing Organization data is not present', async () => { + setItem('id', '123'); + setItem('SuperAdmin', false); + setItem('AdminFor', [{ name: 'adi', _id: '1234', image: '' }]); + render( @@ -91,17 +177,19 @@ describe('Organisations Page testing as SuperAdmin', () => { - + , ); await wait(); }); test('Testing create organization modal', async () => { - localStorage.setItem('id', '123'); + setItem('id', '123'); + setItem('SuperAdmin', true); + setItem('AdminFor', [{ name: 'adi', _id: '1234', image: '' }]); render( - + @@ -109,80 +197,289 @@ describe('Organisations Page testing as SuperAdmin', () => { - + , ); - await wait(); - const createOrgBtn = screen.getByTestId(/createOrganizationBtn/i); - expect(createOrgBtn).toBeInTheDocument(); - userEvent.click(createOrgBtn); - userEvent.click(screen.getByTestId(/closeModalBtn/i)); + screen.debug(); + + expect(localStorage.setItem).toHaveBeenLastCalledWith( + 'Talawa-admin_AdminFor', + JSON.stringify([{ name: 'adi', _id: '1234', image: '' }]), + ); + + expect(screen.getByTestId(/createOrganizationBtn/i)).toBeInTheDocument(); }); test('Create organization model should work properly', async () => { - localStorage.setItem('id', '123'); - localStorage.setItem('UserType', 'SUPERADMIN'); - await act(async () => { - render( - - - + setItem('id', '123'); + setItem('SuperAdmin', true); + setItem('AdminFor', [{ name: 'adi', _id: '1234', image: '' }]); + + render( + + + + + - - - - ); + + + + , + ); - await wait(500); + await wait(500); - expect(localStorage.setItem).toHaveBeenLastCalledWith( - 'UserType', - 'SUPERADMIN' - ); + expect(localStorage.setItem).toHaveBeenLastCalledWith( + 'Talawa-admin_AdminFor', + JSON.stringify([{ name: 'adi', _id: '1234', image: '' }]), + ); - userEvent.click(screen.getByTestId(/createOrganizationBtn/i)); + userEvent.click(screen.getByTestId(/createOrganizationBtn/i)); - userEvent.type( - screen.getByTestId(/modalOrganizationName/i), - formData.name - ); - userEvent.type( - screen.getByPlaceholderText(/Description/i), - formData.description - ); - userEvent.type( - screen.getByPlaceholderText(/Location/i), - formData.location - ); - userEvent.click(screen.getByTestId(/isPublic/i)); - userEvent.click(screen.getByTestId(/visibleInSearch/i)); - userEvent.upload(screen.getByLabelText(/Display Image/i), formData.image); + userEvent.type(screen.getByTestId(/modalOrganizationName/i), formData.name); + userEvent.type( + screen.getByPlaceholderText(/Description/i), + formData.description, + ); + userEvent.type(screen.getByPlaceholderText(/City/i), formData.address.city); + userEvent.type( + screen.getByPlaceholderText(/Postal Code/i), + formData.address.postalCode, + ); + userEvent.type( + screen.getByPlaceholderText(/State \/ Province/i), + formData.address.state, + ); + + userEvent.selectOptions( + screen.getByTestId('countrycode'), + formData.address.countryCode, + ); + userEvent.type( + screen.getByPlaceholderText(/Line 1/i), + formData.address.line1, + ); + userEvent.type( + screen.getByPlaceholderText(/Line 2/i), + formData.address.line2, + ); + userEvent.type( + screen.getByPlaceholderText(/Sorting Code/i), + formData.address.sortingCode, + ); + userEvent.type( + screen.getByPlaceholderText(/Dependent Locality/i), + formData.address.dependentLocality, + ); + userEvent.click(screen.getByTestId(/userRegistrationRequired/i)); + userEvent.click(screen.getByTestId(/visibleInSearch/i)); - await wait(500); + expect(screen.getByTestId(/modalOrganizationName/i)).toHaveValue( + formData.name, + ); + expect(screen.getByPlaceholderText(/Description/i)).toHaveValue( + formData.description, + ); + //Checking the fields for the address object in the formdata. + const { address } = formData; + expect(screen.getByPlaceholderText(/City/i)).toHaveValue(address.city); + expect(screen.getByPlaceholderText(/State \/ Province/i)).toHaveValue( + address.state, + ); + expect(screen.getByPlaceholderText(/Dependent Locality/i)).toHaveValue( + address.dependentLocality, + ); + expect(screen.getByPlaceholderText(/Line 1/i)).toHaveValue(address.line1); + expect(screen.getByPlaceholderText(/Line 2/i)).toHaveValue(address.line2); + expect(screen.getByPlaceholderText(/Postal Code/i)).toHaveValue( + address.postalCode, + ); + expect(screen.getByTestId(/countrycode/i)).toHaveValue(address.countryCode); + expect(screen.getByPlaceholderText(/Sorting Code/i)).toHaveValue( + address.sortingCode, + ); + expect(screen.getByTestId(/userRegistrationRequired/i)).not.toBeChecked(); + expect(screen.getByTestId(/visibleInSearch/i)).toBeChecked(); + expect(screen.getByLabelText(/Display Image/i)).toBeTruthy(); + const displayImage = screen.getByTestId('organisationImage'); + userEvent.upload(displayImage, formData.image); + userEvent.click(screen.getByTestId(/submitOrganizationForm/i)); + await waitFor(() => { + expect( + screen.queryByText(/Congratulation the Organization is created/i), + ).toBeInTheDocument(); }); + }); + + test('Plugin Notification model should work properly', async () => { + setItem('id', '123'); + setItem('SuperAdmin', true); + setItem('AdminFor', [{ name: 'adi', _id: '1234', image: '' }]); + + render( + + + + + + + + + + , + ); + + await wait(500); + + expect(localStorage.setItem).toHaveBeenLastCalledWith( + 'Talawa-admin_AdminFor', + JSON.stringify([{ name: 'adi', _id: '1234', image: '' }]), + ); + + userEvent.click(screen.getByTestId(/createOrganizationBtn/i)); + + userEvent.type(screen.getByTestId(/modalOrganizationName/i), formData.name); + userEvent.type( + screen.getByPlaceholderText(/Description/i), + formData.description, + ); + userEvent.type(screen.getByPlaceholderText(/City/i), formData.address.city); + userEvent.type( + screen.getByPlaceholderText(/State \/ Province/i), + formData.address.state, + ); + userEvent.type( + screen.getByPlaceholderText(/Postal Code/i), + formData.address.postalCode, + ); + userEvent.selectOptions( + screen.getByTestId('countrycode'), + formData.address.countryCode, + ); + userEvent.type( + screen.getByPlaceholderText(/Line 1/i), + formData.address.line1, + ); + userEvent.type( + screen.getByPlaceholderText(/Line 2/i), + formData.address.line2, + ); + userEvent.type( + screen.getByPlaceholderText(/Sorting Code/i), + formData.address.sortingCode, + ); + userEvent.type( + screen.getByPlaceholderText(/Dependent Locality/i), + formData.address.dependentLocality, + ); + userEvent.click(screen.getByTestId(/userRegistrationRequired/i)); + userEvent.click(screen.getByTestId(/visibleInSearch/i)); expect(screen.getByTestId(/modalOrganizationName/i)).toHaveValue( - formData.name + formData.name, ); expect(screen.getByPlaceholderText(/Description/i)).toHaveValue( - formData.description + formData.description, + ); + //Checking the fields for the address object in the formdata. + const { address } = formData; + expect(screen.getByPlaceholderText(/City/i)).toHaveValue(address.city); + expect(screen.getByPlaceholderText(/State \/ Province/i)).toHaveValue( + address.state, ); - expect(screen.getByPlaceholderText(/Location/i)).toHaveValue( - formData.location + expect(screen.getByPlaceholderText(/Dependent Locality/i)).toHaveValue( + address.dependentLocality, ); - expect(screen.getByTestId(/isPublic/i)).not.toBeChecked(); + expect(screen.getByPlaceholderText(/Line 1/i)).toHaveValue(address.line1); + expect(screen.getByPlaceholderText(/Line 2/i)).toHaveValue(address.line2); + expect(screen.getByPlaceholderText(/Postal Code/i)).toHaveValue( + address.postalCode, + ); + expect(screen.getByTestId(/countrycode/i)).toHaveValue(address.countryCode); + expect(screen.getByPlaceholderText(/Sorting Code/i)).toHaveValue( + address.sortingCode, + ); + expect(screen.getByTestId(/userRegistrationRequired/i)).not.toBeChecked(); expect(screen.getByTestId(/visibleInSearch/i)).toBeChecked(); expect(screen.getByLabelText(/Display Image/i)).toBeTruthy(); userEvent.click(screen.getByTestId(/submitOrganizationForm/i)); - }, 10000); + // await act(async () => { + // await new Promise((resolve) => setTimeout(resolve, 1000)); + // }); + await waitFor(() => + expect( + screen.queryByText(/Congratulation the Organization is created/i), + ).toBeInTheDocument(), + ); + await waitFor(() => { + screen.findByTestId(/pluginNotificationHeader/i); + }); + // userEvent.click(screen.getByTestId(/enableEverythingForm/i)); + userEvent.click(screen.getByTestId(/enableEverythingForm/i)); + }); + + test('Testing create sample organization working properly', async () => { + setItem('id', '123'); + setItem('SuperAdmin', true); + setItem('AdminFor', [{ name: 'adi', _id: '1234', image: '' }]); + + render( + + + + + + + + + + , + ); + await wait(); + userEvent.click(screen.getByTestId(/createOrganizationBtn/i)); + userEvent.click(screen.getByTestId(/createSampleOrganizationBtn/i)); + await waitFor(() => + expect( + screen.queryByText(/Sample Organization Successfully created/i), + ).toBeInTheDocument(), + ); + }); + test('Testing error handling for CreateSampleOrg', async () => { + setItem('id', '123'); + setItem('SuperAdmin', true); + setItem('AdminFor', [{ name: 'adi', _id: '1234', image: '' }]); + + jest.spyOn(toast, 'error'); + render( + + + + + + + + , + ); + await wait(); + userEvent.click(screen.getByTestId(/createOrganizationBtn/i)); + userEvent.click(screen.getByTestId(/createSampleOrganizationBtn/i)); + await waitFor(() => + expect( + screen.queryByText(/Only one sample organization allowed/i), + ).toBeInTheDocument(), + ); + }); }); describe('Organisations Page testing as Admin', () => { const link = new StaticMockLink(MOCKS_ADMIN, true); test('Create organization modal should not be present in the page for Admin', async () => { - localStorage.setItem('id', '123'); + setItem('id', '123'); + setItem('SuperAdmin', false); + setItem('AdminFor', [{ name: 'adi', _id: '1234', image: '' }]); render( @@ -193,10 +490,47 @@ describe('Organisations Page testing as Admin', () => { - + , ); + await waitFor(() => { + expect(screen.queryByText(/Create Organization/i)).toBeNull(); + }); + }); + test('Testing sort latest and oldest toggle', async () => { + setItem('id', '123'); + setItem('SuperAdmin', false); + setItem('AdminFor', [{ name: 'adi', _id: '1234', image: '' }]); - await wait(); - expect(screen.queryByText(/Create Organization/i)).toBeNull(); + await act(async () => { + render( + + + + + + + + + , + ); + + await wait(); + + const searchInput = screen.getByTestId('sort'); + expect(searchInput).toBeInTheDocument(); + + const inputText = screen.getByTestId('sortOrgs'); + + fireEvent.click(inputText); + const toggleText = screen.getByTestId('latest'); + + fireEvent.click(toggleText); + + expect(searchInput).toBeInTheDocument(); + fireEvent.click(inputText); + const toggleTite = screen.getByTestId('oldest'); + fireEvent.click(toggleTite); + expect(searchInput).toBeInTheDocument(); + }); }); }); diff --git a/src/screens/OrgList/OrgList.tsx b/src/screens/OrgList/OrgList.tsx index 7e0f71ffb9..7382aedd38 100644 --- a/src/screens/OrgList/OrgList.tsx +++ b/src/screens/OrgList/OrgList.tsx @@ -1,57 +1,63 @@ import { useMutation, useQuery } from '@apollo/client'; import { Search } from '@mui/icons-material'; -import FilterListIcon from '@mui/icons-material/FilterList'; import SortIcon from '@mui/icons-material/Sort'; -import { CREATE_ORGANIZATION_MUTATION } from 'GraphQl/Mutations/mutations'; +import { + CREATE_ORGANIZATION_MUTATION, + CREATE_SAMPLE_ORGANIZATION_MUTATION, +} from 'GraphQl/Mutations/mutations'; import { ORGANIZATION_CONNECTION_LIST, USER_ORGANIZATION_LIST, } from 'GraphQl/Queries/Queries'; -import { CREATE_SAMPLE_ORGANIZATION_MUTATION } from 'GraphQl/Mutations/mutations'; - import OrgListCard from 'components/OrgListCard/OrgListCard'; -import SuperAdminScreen from 'components/SuperAdminScreen/SuperAdminScreen'; import type { ChangeEvent } from 'react'; import React, { useEffect, useState } from 'react'; -import { Col, Dropdown, Form, Row } from 'react-bootstrap'; +import { Dropdown, Form } from 'react-bootstrap'; import Button from 'react-bootstrap/Button'; import Modal from 'react-bootstrap/Modal'; import { useTranslation } from 'react-i18next'; import InfiniteScroll from 'react-infinite-scroll-component'; import { Link } from 'react-router-dom'; import { toast } from 'react-toastify'; -import convertToBase64 from 'utils/convertToBase64'; -import debounce from 'utils/debounce'; import { errorHandler } from 'utils/errorHandler'; import type { InterfaceOrgConnectionInfoType, InterfaceOrgConnectionType, InterfaceUserType, } from 'utils/interfaces'; +import useLocalStorage from 'utils/useLocalstorage'; import styles from './OrgList.module.css'; +import OrganizationModal from './OrganizationModal'; function orgList(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'orgList' }); const [dialogModalisOpen, setdialogModalIsOpen] = useState(false); const [dialogRedirectOrgId, setDialogRedirectOrgId] = useState(''); - /* eslint-disable @typescript-eslint/explicit-function-return-type */ - function openDialogModal(redirectOrgId: string) { + + function openDialogModal(redirectOrgId: string): void { setDialogRedirectOrgId(redirectOrgId); // console.log(redirectOrgId, dialogRedirectOrgId); setdialogModalIsOpen(true); } - /* eslint-disable @typescript-eslint/explicit-function-return-type */ - function closeDialogModal() { + const { getItem } = useLocalStorage(); + const superAdmin = getItem('SuperAdmin'); + const adminFor = getItem('AdminFor'); + + function closeDialogModal(): void { setdialogModalIsOpen(false); } - const toggleDialogModal = (): void => + const toggleDialogModal = /* istanbul ignore next */ (): void => setdialogModalIsOpen(!dialogModalisOpen); document.title = t('title'); const perPageResult = 8; const [isLoading, setIsLoading] = useState(true); + const [sortingState, setSortingState] = useState({ + option: '', + selectedOption: t('sort'), + }); const [hasMore, sethasMore] = useState(true); const [isLoadingMore, setIsLoadingMore] = useState(false); const [searchByName, setSearchByName] = useState(''); @@ -59,9 +65,18 @@ function orgList(): JSX.Element { const [formState, setFormState] = useState({ name: '', descrip: '', - ispublic: true, + userRegistrationRequired: true, visible: false, - location: '', + address: { + city: '', + countryCode: '', + dependentLocality: '', + line1: '', + line2: '', + postalCode: '', + sortingCode: '', + state: '', + }, image: '', }); @@ -70,7 +85,7 @@ function orgList(): JSX.Element { const [create] = useMutation(CREATE_ORGANIZATION_MUTATION); const [createSampleOrganization] = useMutation( - CREATE_SAMPLE_ORGANIZATION_MUTATION + CREATE_SAMPLE_ORGANIZATION_MUTATION, ); const { @@ -81,7 +96,10 @@ function orgList(): JSX.Element { loading: boolean; error?: Error | undefined; } = useQuery(USER_ORGANIZATION_LIST, { - variables: { id: localStorage.getItem('id') }, + variables: { userId: getItem('id') }, + context: { + headers: { authorization: `Bearer ${getItem('token')}` }, + }, }); const { @@ -101,6 +119,8 @@ function orgList(): JSX.Element { first: perPageResult, skip: 0, filter: searchByName, + orderBy: + sortingState.option === 'Latest' ? 'createdAt_DESC' : 'createdAt_ASC', }, notifyOnNetworkStatusChange: true, }); @@ -112,9 +132,18 @@ function orgList(): JSX.Element { setFormState({ name: '', descrip: '', - ispublic: true, + userRegistrationRequired: true, visible: false, - location: '', + address: { + city: '', + countryCode: '', + dependentLocality: '', + line1: '', + line2: '', + postalCode: '', + sortingCode: '', + state: '', + }, image: '', }); }; @@ -126,23 +155,23 @@ function orgList(): JSX.Element { /* istanbul ignore next */ const isAdminForCurrentOrg = ( - currentOrg: InterfaceOrgConnectionInfoType + currentOrg: InterfaceOrgConnectionInfoType, ): boolean => { - if (userData?.user?.adminFor.length === 1) { + if (adminFor.length === 1) { // If user is admin for one org only then check if that org is current org - return userData?.user?.adminFor[0]._id === currentOrg._id; + return adminFor[0]._id === currentOrg._id; } else { // If user is admin for more than one org then check if current org is present in adminFor array return ( - userData?.user?.adminFor.some( + adminFor.some( (org: { _id: string; name: string; image: string | null }) => - org._id === currentOrg._id + org._id === currentOrg._id, ) ?? false ); } }; - const triggerCreateSampleOrg = () => { + const triggerCreateSampleOrg = (): void => { createSampleOrganization() .then(() => { toast.success(t('sampleOrgSuccess')); @@ -159,24 +188,24 @@ function orgList(): JSX.Element { const { name: _name, descrip: _descrip, - location: _location, + address: _address, visible, - ispublic, + userRegistrationRequired, image, } = formState; const name = _name.trim(); const descrip = _descrip.trim(); - const location = _location.trim(); + const address = _address; try { const { data } = await create({ variables: { name: name, description: descrip, - location: location, + address: address, visibleInSearch: visible, - isPublic: ispublic, + userRegistrationRequired: userRegistrationRequired, image: image, }, }); @@ -189,9 +218,18 @@ function orgList(): JSX.Element { setFormState({ name: '', descrip: '', - ispublic: true, + userRegistrationRequired: true, visible: false, - location: '', + address: { + city: '', + countryCode: '', + dependentLocality: '', + line1: '', + line2: '', + postalCode: '', + sortingCode: '', + state: '', + }, image: '', }); toggleModal(); @@ -213,15 +251,16 @@ function orgList(): JSX.Element { filter: '', first: perPageResult, skip: 0, + orderBy: + sortingState.option === 'Latest' ? 'createdAt_DESC' : 'createdAt_ASC', }); sethasMore(true); }; /* istanbul ignore next */ - const handleSearchByName = (e: any): void => { - const { value } = e.target; + const handleSearch = (value: string): void => { setSearchByName(value); - if (value == '') { + if (value === '') { resetAllParams(); return; } @@ -230,6 +269,20 @@ function orgList(): JSX.Element { }); }; + const handleSearchByEnter = (e: any): void => { + if (e.key === 'Enter') { + const { value } = e.target; + handleSearch(value); + } + }; + + const handleSearchByBtnClick = (): void => { + const inputElement = document.getElementById( + 'searchOrgname', + ) as HTMLInputElement; + const inputValue = inputElement?.value || ''; + handleSearch(inputValue); + }; /* istanbul ignore next */ const loadMoreOrganizations = (): void => { console.log('loadMoreOrganizations'); @@ -248,7 +301,7 @@ function orgList(): JSX.Element { fetchMoreResult: | { organizationsConnection: InterfaceOrgConnectionType[] } | undefined; - } + }, ): | { organizationsConnection: InterfaceOrgConnectionType[] } | undefined => { @@ -267,159 +320,156 @@ function orgList(): JSX.Element { }); }; - const debouncedHandleSearchByName = debounce(handleSearchByName); + const handleSorting = (option: string): void => { + setSortingState({ + option, + selectedOption: t(option), + }); + + const orderBy = option === 'Latest' ? 'createdAt_DESC' : 'createdAt_ASC'; + + refetchOrgs({ + first: perPageResult, + skip: 0, + filter: searchByName, + orderBy, + }); + }; + return ( <> - - {/* Buttons Container */} -
    -
    - - +
    +
    +
    +
    -
    -
    - - -
    - {userData && userData.user.userType === 'SUPERADMIN' && ( - - )} -
    -
    - {/* Text Infos for list */} - {!isLoading && - ((orgsData?.organizationsConnection.length === 0 && - searchByName.length == 0) || - (userData && - userData.user.userType === 'ADMIN' && - userData.user.adminFor.length === 0)) ? ( - // eslint-disable-next-line -
    -

    {t('noOrgErrorTitle')}

    -
    {t('noOrgErrorDescription')}
    -
    - ) : !isLoading && - orgsData?.organizationsConnection.length == 0 && - /* istanbul ignore next */ - searchByName.length > 0 ? ( - /* istanbul ignore next */ - // eslint-disable-next-line -
    -

    - {t('noResultsFoundFor')} "{searchByName}" -

    + + {sortingState.selectedOption} + + + handleSorting('Latest')} + data-testid="latest" + > + {t('Latest')} + + handleSorting('Earliest')} + data-testid="oldest" + > + {t('Earliest')} + + +
    - ) : ( - <> - - {[...Array(perPageResult)].map((_, index) => ( -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    - ))} - - } - hasMore={hasMore} - className={styles.listBox} - data-testid="organizations-list" - endMessage={ -
    -
    {t('endOfResults')}
    -
    - } + {superAdmin && ( + + )} +
    +
    + {/* Text Infos for list */} + {!isLoading && + (!orgsData?.organizationsConnection || + orgsData.organizationsConnection.length === 0) && + searchByName.length === 0 && + (!userData || adminFor.length === 0 || superAdmin) ? ( +
    +

    {t('noOrgErrorTitle')}

    +
    {t('noOrgErrorDescription')}
    +
    + ) : !isLoading && + orgsData?.organizationsConnection.length == 0 && + /* istanbul ignore next */ + searchByName.length > 0 ? ( + /* istanbul ignore next */ +
    +

    + {t('noResultsFoundFor')} "{searchByName}" +

    +
    + ) : ( + <> + + {[...Array(perPageResult)].map((_, index) => ( +
    +
    +
    +
    +
    +
    +
    +
    +
    -
    +
    - ))} - - ) : userData && userData.user.userType == 'SUPERADMIN' ? ( - orgsData?.organizationsConnection.map((item) => { +
    + ))} + + } + hasMore={hasMore} + className={styles.listBox} + data-testid="organizations-list" + endMessage={ +
    +
    {t('endOfResults')}
    +
    + } + > + {userData && superAdmin + ? orgsData?.organizationsConnection.map((item) => { return (
    ); }) - ) : ( - userData && - userData.user.userType == 'ADMIN' && - userData.user.adminFor.length > 0 && + : userData && + adminFor.length > 0 && orgsData?.organizationsConnection.map((item) => { if (isAdminForCurrentOrg(item)) { return ( @@ -428,220 +478,97 @@ function orgList(): JSX.Element {
    ); } - }) - )} - - - )} - {/* Create Organization Modal */} - + {isLoading && ( + <> + {[...Array(perPageResult)].map((_, index) => ( +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + ))} + + )} + + )} + {/* Create Organization Modal */} + {/** + * Renders the `OrganizationModal` component. + * + * @param showModal - A boolean indicating whether the modal should be displayed. + * @param toggleModal - A function to toggle the visibility of the modal. + * @param formState - The state of the form in the organization modal. + * @param setFormState - A function to update the state of the form in the organization modal. + * @param createOrg - A function to handle the submission of the organization creation form. + * @param t - A translation function for localization. + * @param userData - Information about the current user. + * @param triggerCreateSampleOrg - A function to trigger the creation of a sample organization. + * @returns JSX element representing the `OrganizationModal`. + */} + + {/* Plugin Notification Modal after Org is Created */} + + - - - {t('createOrganization')} - - - - - {t('name')} - { - setFormState({ - ...formState, - name: e.target.value, - }); - }} - /> - {t('description')} - { - setFormState({ - ...formState, - descrip: e.target.value, - }); - }} - /> - {t('location')} - { - setFormState({ - ...formState, - location: e.target.value, - }); - }} - /> + + {t('manageFeatures')} + + + +
    +
    +

    + {t('manageFeaturesInfo')} +

    - - - {t('isPublic')} - - setFormState({ - ...formState, - ispublic: !formState.ispublic, - }) - } - /> - - - - {t('visibleInSearch')} - - - setFormState({ - ...formState, - visible: !formState.visible, - }) - } - /> - - - {t('displayImage')} - => { - const target = e.target as HTMLInputElement; - const file = target.files && target.files[0]; - /* istanbul ignore else */ - if (file) - setFormState({ - ...formState, - image: await convertToBase64(file), - }); - }} - data-testid="organisationImage" - /> - +
    + + {t('goToStore')} + + {/* */} - -
    -
    - {t('OR')} -
    - {userData && - ((userData.user.userType === 'ADMIN' && - userData.user.adminFor.length > 0) || - userData.user.userType === 'SUPERADMIN') && ( -
    - -
    - )} - - - - {' '} - {/* Plugin Notification Modal after Org is Created */} - - -
    -
    -
    -

    {t('manageFeatures')}

    - - - - -
    -

    - {t('manageFeaturesInfo')} -

    - -
    - - {t('goToStore')} - - {/* */} - -
    -
    -
    -
    - +
    +
    +
    +
    ); } diff --git a/src/screens/OrgList/OrgListMocks.ts b/src/screens/OrgList/OrgListMocks.ts index 1a1ab30ab7..0706ec8f1f 100644 --- a/src/screens/OrgList/OrgListMocks.ts +++ b/src/screens/OrgList/OrgListMocks.ts @@ -1,3 +1,7 @@ +import { + CREATE_ORGANIZATION_MUTATION, + CREATE_SAMPLE_ORGANIZATION_MUTATION, +} from 'GraphQl/Mutations/mutations'; import { ORGANIZATION_CONNECTION_LIST, USER_ORGANIZATION_LIST, @@ -12,21 +16,15 @@ const superAdminUser: InterfaceUserType = { user: { firstName: 'John', lastName: 'Doe', - image: '', - email: 'John_Does_Palasidoes@gmail.com', - userType: 'SUPERADMIN', - adminFor: [ - { - _id: '1', - name: 'Akatsuki', - image: '', - }, - ], + email: 'john.doe@akatsuki.com', + image: null, }, }; const adminUser: InterfaceUserType = { - user: { ...superAdminUser.user, userType: 'ADMIN' }, + user: { + ...superAdminUser.user, + }, }; const organizations: InterfaceOrgConnectionInfoType[] = [ @@ -46,11 +44,20 @@ const organizations: InterfaceOrgConnectionInfoType[] = [ _id: '234', }, ], - location: 'Jamaica', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, }, ]; -for (let x = 0; x < 100; x++) { +for (let x = 0; x < 1; x++) { organizations.push({ _id: 'a' + x, image: '', @@ -71,7 +78,16 @@ for (let x = 0; x < 100; x++) { }, ], createdAt: new Date().toISOString(), - location: 'location', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, }); } @@ -84,6 +100,7 @@ const MOCKS = [ first: 8, skip: 0, filter: '', + orderBy: 'createdAt_ASC', }, notifyOnNetworkStatusChange: true, }, @@ -102,6 +119,48 @@ const MOCKS = [ data: superAdminUser, }, }, + { + request: { + query: CREATE_SAMPLE_ORGANIZATION_MUTATION, + }, + result: { + data: { + createSampleOrganization: { + id: '1', + name: 'Sample Organization', + }, + }, + }, + }, + { + request: { + query: CREATE_ORGANIZATION_MUTATION, + variables: { + description: 'This is a dummy organization', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + name: 'Dummy Organization', + visibleInSearch: true, + userRegistrationRequired: false, + image: '', + }, + }, + result: { + data: { + createOrganization: { + _id: '1', + }, + }, + }, + }, ]; const MOCKS_EMPTY = [ { @@ -111,6 +170,7 @@ const MOCKS_EMPTY = [ first: 8, skip: 0, filter: '', + orderBy: 'createdAt_ASC', }, notifyOnNetworkStatusChange: true, }, @@ -130,6 +190,40 @@ const MOCKS_EMPTY = [ }, }, ]; +const MOCKS_WITH_ERROR = [ + { + request: { + query: ORGANIZATION_CONNECTION_LIST, + variables: { + first: 8, + skip: 0, + filter: '', + orderBy: 'createdAt_ASC', + }, + notifyOnNetworkStatusChange: true, + }, + result: { + data: { + organizationsConnection: organizations, + }, + }, + }, + { + request: { + query: USER_ORGANIZATION_LIST, + variables: { id: '123' }, + }, + result: { + data: superAdminUser, + }, + }, + { + request: { + query: CREATE_SAMPLE_ORGANIZATION_MUTATION, + }, + error: new Error('Failed to create sample organization'), + }, +]; // MOCKS FOR ADMIN const MOCKS_ADMIN = [ @@ -140,6 +234,7 @@ const MOCKS_ADMIN = [ first: 8, skip: 0, filter: '', + orderBy: 'createdAt_ASC', }, notifyOnNetworkStatusChange: true, }, @@ -160,4 +255,4 @@ const MOCKS_ADMIN = [ }, ]; -export { MOCKS, MOCKS_ADMIN, MOCKS_EMPTY }; +export { MOCKS, MOCKS_ADMIN, MOCKS_EMPTY, MOCKS_WITH_ERROR }; diff --git a/src/screens/OrgList/OrganizationModal.tsx b/src/screens/OrgList/OrganizationModal.tsx new file mode 100644 index 0000000000..7be39cc246 --- /dev/null +++ b/src/screens/OrgList/OrganizationModal.tsx @@ -0,0 +1,320 @@ +import React from 'react'; +import { Modal, Form, Row, Col, Button } from 'react-bootstrap'; +import convertToBase64 from 'utils/convertToBase64'; +import type { ChangeEvent } from 'react'; +import styles from './OrgList.module.css'; +import type { InterfaceAddress } from 'utils/interfaces'; +import { countryOptions } from 'utils/formEnumFields'; +import useLocalStorage from 'utils/useLocalstorage'; + +/** + * Represents the state of the form in the organization modal. + */ +interface InterfaceFormStateType { + name: string; + descrip: string; + userRegistrationRequired: boolean; + visible: boolean; + address: InterfaceAddress; + image: string; +} + +/** + * Represents a user type. + */ +interface InterfaceUserType { + user: { + firstName: string; + lastName: string; + image: string | null; + email: string; + }; + + // Add more properties if needed +} + +/** + * Represents the properties of the OrganizationModal component. + */ +interface InterfaceOrganizationModalProps { + showModal: boolean; + toggleModal: () => void; + formState: InterfaceFormStateType; + setFormState: (state: React.SetStateAction) => void; + createOrg: (e: ChangeEvent) => Promise; + t: (key: string) => string; + userData: InterfaceUserType | undefined; + triggerCreateSampleOrg: () => void; +} + +/** + * Represents the organization modal component. + */ + +const OrganizationModal: React.FC = ({ + showModal, + toggleModal, + formState, + setFormState, + createOrg, + t, + triggerCreateSampleOrg, +}) => { + // function to update the state of the parameters inside address. + const { getItem } = useLocalStorage(); + const superAdmin = getItem('SuperAdmin'); + const adminFor = getItem('AdminFor'); + + const handleInputChange = (fieldName: string, value: string): void => { + setFormState((prevState) => ({ + ...prevState, + address: { + ...prevState.address, + [fieldName]: value, + }, + })); + }; + return ( + + + + {t('createOrganization')} + + +
    + + {t('name')} + { + const inputText = e.target.value; + if (inputText.length < 50) { + setFormState({ + ...formState, + name: e.target.value, + }); + } + }} + /> + {t('description')} + { + const descriptionText = e.target.value; + if (descriptionText.length < 200) { + setFormState({ + ...formState, + descrip: e.target.value, + }); + } + }} + /> + {t('address')} + + + { + const countryCode = e.target.value; + handleInputChange('countryCode', countryCode); + }} + > + + {countryOptions.map((country) => ( + + ))} + + + + handleInputChange('city', e.target.value)} + /> + + + + + handleInputChange('state', e.target.value)} + /> + + + + handleInputChange('dependentLocality', e.target.value) + } + /> + + + + + handleInputChange('line1', e.target.value)} + /> + + + handleInputChange('line2', e.target.value)} + /> + + + + + + handleInputChange('postalCode', e.target.value) + } + /> + + + + handleInputChange('sortingCode', e.target.value) + } + /> + + + + + + {t('userRegistrationRequired')} + + + setFormState({ + ...formState, + userRegistrationRequired: + !formState.userRegistrationRequired, + }) + } + /> + + + + {t('visibleInSearch')} + + + setFormState({ + ...formState, + visible: !formState.visible, + }) + } + /> + + + {t('displayImage')} + => { + const target = e.target as HTMLInputElement; + const file = target.files && target.files[0]; + /* istanbul ignore else */ + if (file) + setFormState({ + ...formState, + image: await convertToBase64(file), + }); + }} + data-testid="organisationImage" + /> + + + +
    +
    + {t('OR')} +
    + {(adminFor.length > 0 || superAdmin) && ( +
    + +
    + )} + +
    +
    +
    + ); +}; + +export default OrganizationModal; diff --git a/src/screens/OrgPost/OrgPost.module.css b/src/screens/OrgPost/OrgPost.module.css index f9ff4a0794..e674efbc7a 100644 --- a/src/screens/OrgPost/OrgPost.module.css +++ b/src/screens/OrgPost/OrgPost.module.css @@ -167,7 +167,9 @@ outline: none; font-weight: 600; cursor: pointer; - transition: transform 0.2s, box-shadow 0.2s; + transition: + transform 0.2s, + box-shadow 0.2s; } .flexdir { display: flex; diff --git a/src/screens/OrgPost/OrgPost.test.tsx b/src/screens/OrgPost/OrgPost.test.tsx index 85dfc03edc..465da98642 100644 --- a/src/screens/OrgPost/OrgPost.test.tsx +++ b/src/screens/OrgPost/OrgPost.test.tsx @@ -1,75 +1,135 @@ -import React from 'react'; import { MockedProvider } from '@apollo/react-testing'; -import { BrowserRouter } from 'react-router-dom'; -import { act, render, screen, fireEvent } from '@testing-library/react'; +import { act, fireEvent, render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { Provider } from 'react-redux'; import 'jest-location-mock'; import { I18nextProvider } from 'react-i18next'; - -import OrgPost from './OrgPost'; -import { store } from 'state/store'; -import { ORGANIZATION_POST_CONNECTION_LIST } from 'GraphQl/Queries/Queries'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import React from 'react'; import { CREATE_POST_MUTATION } from 'GraphQl/Mutations/mutations'; -import i18nForTest from 'utils/i18nForTest'; -import { StaticMockLink } from 'utils/StaticMockLink'; +import { ORGANIZATION_POST_LIST } from 'GraphQl/Queries/Queries'; import { ToastContainer } from 'react-toastify'; -import { debug } from 'jest-preview'; - +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18nForTest from 'utils/i18nForTest'; +import OrgPost from './OrgPost'; const MOCKS = [ { request: { - query: ORGANIZATION_POST_CONNECTION_LIST, + query: ORGANIZATION_POST_LIST, variables: { id: undefined, - title_contains: '', - text_contains: '', + after: null, + before: null, + first: 6, + last: null, }, }, result: { data: { - postsByOrganizationConnection: { - edges: [ - { - _id: '6411e53835d7ba2344a78e21', - title: 'postone', - text: 'This is the first post', - imageUrl: null, - videoUrl: null, - createdAt: '2023-08-24T09:26:56.524+00:00', - creator: { - _id: '640d98d9eb6a743d75341067', - firstName: 'Aditya', - lastName: 'Shelke', - email: 'adidacreator1@gmail.com', - }, - likeCount: 0, - commentCount: 0, - comments: [], - pinned: false, - likedBy: [], - }, - { - _id: '6411e54835d7ba2344a78e29', - title: 'posttwo', - text: 'Tis is the post two', - imageUrl: null, - videoUrl: null, - createdAt: '2023-08-24T09:26:56.524+00:00', - creator: { - _id: '640d98d9eb6a743d75341067', - firstName: 'Aditya', - lastName: 'Shelke', - email: 'adidacreator1@gmail.com', + organizations: [ + { + posts: { + edges: [ + { + node: { + _id: '6411e53835d7ba2344a78e21', + title: 'postone', + text: 'This is the first post', + imageUrl: null, + videoUrl: null, + createdAt: '2023-08-24T09:26:56.524+00:00', + creator: { + _id: '640d98d9eb6a743d75341067', + firstName: 'Aditya', + lastName: 'Shelke', + email: 'adidacreator1@gmail.com', + }, + likeCount: 0, + commentCount: 0, + comments: [], + pinned: true, + likedBy: [], + }, + cursor: '6411e53835d7ba2344a78e21', + }, + { + node: { + _id: '6411e54835d7ba2344a78e29', + title: 'posttwo', + text: 'Tis is the post two', + imageUrl: null, + videoUrl: null, + createdAt: '2023-08-24T09:26:56.524+00:00', + creator: { + _id: '640d98d9eb6a743d75341067', + firstName: 'Aditya', + lastName: 'Shelke', + email: 'adidacreator1@gmail.com', + }, + likeCount: 0, + commentCount: 0, + pinned: false, + likedBy: [], + comments: [], + }, + cursor: '6411e54835d7ba2344a78e29', + }, + { + node: { + _id: '6411e54835d7ba2344a78e30', + title: 'posttwo', + text: 'Tis is the post two', + imageUrl: null, + videoUrl: null, + createdAt: '2023-08-24T09:26:56.524+00:00', + creator: { + _id: '640d98d9eb6a743d75341067', + firstName: 'Aditya', + lastName: 'Shelke', + email: 'adidacreator1@gmail.com', + }, + likeCount: 0, + commentCount: 0, + pinned: true, + likedBy: [], + comments: [], + }, + cursor: '6411e54835d7ba2344a78e30', + }, + { + node: { + _id: '6411e54835d7ba2344a78e31', + title: 'posttwo', + text: 'Tis is the post two', + imageUrl: null, + videoUrl: null, + createdAt: '2023-08-24T09:26:56.524+00:00', + creator: { + _id: '640d98d9eb6a743d75341067', + firstName: 'Aditya', + lastName: 'Shelke', + email: 'adidacreator1@gmail.com', + }, + likeCount: 0, + commentCount: 0, + pinned: false, + likedBy: [], + comments: [], + }, + cursor: '6411e54835d7ba2344a78e31', + }, + ], + pageInfo: { + startCursor: '6411e53835d7ba2344a78e21', + endCursor: '6411e54835d7ba2344a78e31', + hasNextPage: false, + hasPreviousPage: false, }, - likeCount: 0, - commentCount: 0, - pinned: false, - likedBy: [], - comments: [], + totalCount: 4, }, - ], - }, + }, + ], }, }, }, @@ -127,27 +187,29 @@ describe('Organisation Post Page', () => { }; test('correct mock data should be queried', async () => { - const dataQuery1 = - MOCKS[0]?.result?.data?.postsByOrganizationConnection.edges[0]; + const dataQuery1 = MOCKS[0]?.result?.data?.organizations[0].posts.edges[0]; expect(dataQuery1).toEqual({ - _id: '6411e53835d7ba2344a78e21', - title: 'postone', - text: 'This is the first post', - imageUrl: null, - videoUrl: null, - createdAt: '2023-08-24T09:26:56.524+00:00', - creator: { - _id: '640d98d9eb6a743d75341067', - firstName: 'Aditya', - lastName: 'Shelke', - email: 'adidacreator1@gmail.com', + node: { + _id: '6411e53835d7ba2344a78e21', + title: 'postone', + text: 'This is the first post', + imageUrl: null, + videoUrl: null, + createdAt: '2023-08-24T09:26:56.524+00:00', + creator: { + _id: '640d98d9eb6a743d75341067', + firstName: 'Aditya', + lastName: 'Shelke', + email: 'adidacreator1@gmail.com', + }, + likeCount: 0, + commentCount: 0, + pinned: true, + likedBy: [], + comments: [], }, - likeCount: 0, - commentCount: 0, - pinned: false, - likedBy: [], - comments: [], + cursor: '6411e53835d7ba2344a78e21', }); }); @@ -161,7 +223,7 @@ describe('Organisation Post Page', () => { - + , ); await wait(); @@ -171,14 +233,12 @@ describe('Organisation Post Page', () => { userEvent.type(screen.getByTestId('modalTitle'), formData.posttitle); userEvent.type(screen.getByTestId('modalinfo'), formData.postinfo); - userEvent.upload( - screen.getByTestId('organisationImage'), - formData.postImage - ); - userEvent.upload( - screen.getByTestId('organisationImage'), - formData.postVideo - ); + userEvent.upload(screen.getByTestId('addMediaField'), formData.postImage); + userEvent.upload(screen.getByTestId('addMediaField'), formData.postVideo); + userEvent.upload(screen.getByTestId('addMediaField'), formData.postImage); + userEvent.upload(screen.getByTestId('addMediaField'), formData.postVideo); + userEvent.click(screen.getByTestId('pinPost')); + expect(screen.getByTestId('pinPost')).toBeChecked(); userEvent.click(screen.getByTestId('createPostBtn')); @@ -197,7 +257,7 @@ describe('Organisation Post Page', () => { - + , ); async function debounceWait(ms = 200): Promise { await act(() => { @@ -207,7 +267,7 @@ describe('Organisation Post Page', () => { }); } await debounceWait(); - userEvent.type(screen.getByPlaceholderText(/Search By/i), 'postone'); + userEvent.type(screen.getByPlaceholderText(/Search By/i), 'postone{enter}'); await debounceWait(); const sortDropdown = screen.getByTestId('sort'); userEvent.click(sortDropdown); @@ -224,7 +284,7 @@ describe('Organisation Post Page', () => { - + , ); await wait(); @@ -258,7 +318,7 @@ describe('Organisation Post Page', () => { - + , ); await wait(); @@ -293,7 +353,7 @@ describe('Organisation Post Page', () => { - + , ); await wait(); @@ -320,7 +380,7 @@ describe('Organisation Post Page', () => { - + , ); await wait(); @@ -349,7 +409,7 @@ describe('Organisation Post Page', () => { - + , ); await wait(); @@ -362,18 +422,24 @@ describe('Organisation Post Page', () => { fireEvent.change(postInfoTextarea, { target: { value: 'Test post information' }, }); - const file = new File(['image content'], 'image.png', { + + // Simulate uploading an image + const imageFile = new File(['image content'], 'image.png', { type: 'image/png', }); - const input = screen.getByTestId('organisationImage'); - userEvent.upload(input, file); + const imageInput = screen.getByTestId('addMediaField'); + userEvent.upload(imageInput, imageFile); - await screen.findByAltText('Post Image Preview'); - expect(screen.getByAltText('Post Image Preview')).toBeInTheDocument(); + // Check if the image is displayed + const imagePreview = await screen.findByAltText('Post Image Preview'); + expect(imagePreview).toBeInTheDocument(); - const createPostBtn = screen.getByTestId('createPostBtn'); - fireEvent.click(createPostBtn); - debug(); + // Check if the close button for the image works + const closeButton = screen.getByTestId('mediaCloseButton'); + fireEvent.click(closeButton); + + // Check if the image is removed from the preview + expect(imagePreview).not.toBeInTheDocument(); }, 15000); test('Modal opens and closes', async () => { @@ -386,7 +452,7 @@ describe('Organisation Post Page', () => { - + , ); await wait(); @@ -398,7 +464,7 @@ describe('Organisation Post Page', () => { const modalTitle = screen.getByTestId('modalOrganizationHeader'); expect(modalTitle).toBeInTheDocument(); - const closeButton = screen.getByTestId('closeOrganizationModal'); + const closeButton = screen.getByTestId(/modalOrganizationHeader/i); userEvent.click(closeButton); await wait(); @@ -417,7 +483,7 @@ describe('Organisation Post Page', () => { - + , ); await wait(); @@ -426,8 +492,6 @@ describe('Organisation Post Page', () => { // Check if input fields and buttons are present expect(screen.getByTestId('modalTitle')).toBeInTheDocument(); expect(screen.getByTestId('modalinfo')).toBeInTheDocument(); - expect(screen.getByTestId('organisationImage')).toBeInTheDocument(); - expect(screen.getByTestId('organisationVideo')).toBeInTheDocument(); expect(screen.getByTestId('createPostBtn')).toBeInTheDocument(); }); @@ -442,7 +506,7 @@ describe('Organisation Post Page', () => { - + , ); await wait(); @@ -472,7 +536,7 @@ describe('Organisation Post Page', () => { - + , ); await wait(); @@ -488,13 +552,13 @@ describe('Organisation Post Page', () => { const file = new File(['image content'], 'image.png', { type: 'image/png', }); - const input = screen.getByTestId('organisationImage'); + const input = screen.getByTestId('addMediaField'); userEvent.upload(input, file); await screen.findByAltText('Post Image Preview'); expect(screen.getByAltText('Post Image Preview')).toBeInTheDocument(); - const closeButton = screen.getByTestId('closePreview'); + const closeButton = screen.getByTestId('mediaCloseButton'); fireEvent.click(closeButton); }, 15000); test('Create post, preview image, and close preview', async () => { @@ -509,7 +573,7 @@ describe('Organisation Post Page', () => { - + , ); await wait(); @@ -528,21 +592,71 @@ describe('Organisation Post Page', () => { type: 'video/mp4', }); - const videoInput = screen.getByTestId('organisationVideo'); - fireEvent.change(videoInput, { - target: { - files: [videoFile], - }, - }); + userEvent.upload(screen.getByTestId('addMediaField'), videoFile); // Check if the video is displayed const videoPreview = await screen.findByTestId('videoPreview'); expect(videoPreview).toBeInTheDocument(); // Check if the close button for the video works - const closeVideoPreviewButton = screen.getByTestId('videoclosebutton'); + const closeVideoPreviewButton = screen.getByTestId('mediaCloseButton'); fireEvent.click(closeVideoPreviewButton); expect(videoPreview).not.toBeInTheDocument(); }); }); + test('Sorting posts by pinned status', async () => { + // Mocked data representing posts with different pinned statuses + const mockedPosts = [ + { + _id: '1', + title: 'Post 1', + pinned: true, + }, + { + _id: '2', + title: 'Post 2', + pinned: false, + }, + { + _id: '3', + title: 'Post 3', + pinned: true, + }, + { + _id: '4', + title: 'Post 4', + pinned: true, + }, + ]; + + // Render the OrgPost component and pass the mocked data to it + render( + + + + + + + + + + , + ); + + await wait(); + + const sortedPosts = screen.getAllByTestId('post-item'); + + // Assert that the posts are sorted correctly + expect(sortedPosts).toHaveLength(mockedPosts.length); + expect(sortedPosts[0]).toHaveTextContent( + 'postoneThis is the first po... Aditya Shelke', + ); + expect(sortedPosts[1]).toHaveTextContent( + 'posttwoTis is the post two Aditya Shelke', + ); + expect(sortedPosts[2]).toHaveTextContent( + 'posttwoTis is the post two Aditya Shelke', + ); + }); }); diff --git a/src/screens/OrgPost/OrgPost.tsx b/src/screens/OrgPost/OrgPost.tsx index 9f098c291b..677394e618 100644 --- a/src/screens/OrgPost/OrgPost.tsx +++ b/src/screens/OrgPost/OrgPost.tsx @@ -1,36 +1,46 @@ -import type { ChangeEvent } from 'react'; -import React, { useState, useEffect } from 'react'; +import { useMutation, useQuery, type ApolloError } from '@apollo/client'; import { Search } from '@mui/icons-material'; import SortIcon from '@mui/icons-material/Sort'; -import Row from 'react-bootstrap/Row'; -import Modal from 'react-bootstrap/Modal'; +import { CREATE_POST_MUTATION } from 'GraphQl/Mutations/mutations'; +import { ORGANIZATION_POST_LIST } from 'GraphQl/Queries/Queries'; +import Loader from 'components/Loader/Loader'; +import NotFound from 'components/NotFound/NotFound'; +import OrgPostCard from 'components/OrgPostCard/OrgPostCard'; +import { useNavigate, useParams } from 'react-router-dom'; +import type { ChangeEvent } from 'react'; +import React, { useEffect, useState } from 'react'; import { Form } from 'react-bootstrap'; -import { useMutation, useQuery } from '@apollo/client'; import Button from 'react-bootstrap/Button'; -import { toast } from 'react-toastify'; -import { useTranslation } from 'react-i18next'; import Dropdown from 'react-bootstrap/Dropdown'; -import styles from './OrgPost.module.css'; -import OrgPostCard from 'components/OrgPostCard/OrgPostCard'; -import { ORGANIZATION_POST_CONNECTION_LIST } from 'GraphQl/Queries/Queries'; -import { CREATE_POST_MUTATION } from 'GraphQl/Mutations/mutations'; -import debounce from 'utils/debounce'; +import Modal from 'react-bootstrap/Modal'; +import Row from 'react-bootstrap/Row'; +import { useTranslation } from 'react-i18next'; +import { toast } from 'react-toastify'; import convertToBase64 from 'utils/convertToBase64'; -import NotFound from 'components/NotFound/NotFound'; import { errorHandler } from 'utils/errorHandler'; -import Loader from 'components/Loader/Loader'; -import OrganizationScreen from 'components/OrganizationScreen/OrganizationScreen'; +import type { InterfaceQueryOrganizationPostListItem } from 'utils/interfaces'; +import styles from './OrgPost.module.css'; interface InterfaceOrgPost { _id: string; title: string; text: string; - imageUrl: string; - videoUrl: string; - organizationId: string; - creator: { firstName: string; lastName: string }; + imageUrl: string | null; + videoUrl: string | null; + creator: { _id: string; firstName: string; lastName: string; email: string }; pinned: boolean; createdAt: string; + likeCount: number; + commentCount: number; + likedBy: { _id: string }[]; + comments: { + _id: string; + text: string; + creator: { _id: string }; + createdAt: string; + likeCount: number; + likedBy: { _id: string }[]; + }[]; } function orgPost(): JSX.Element { @@ -45,15 +55,23 @@ function orgPost(): JSX.Element { postinfo: '', postImage: '', postVideo: '', + addMedia: '', + pinPost: false, }); const [sortingOption, setSortingOption] = useState('latest'); + const [file, setFile] = useState(null); + const { orgId: currentUrl } = useParams(); + const navigate = useNavigate(); const [showTitle, setShowTitle] = useState(true); - - const currentUrl = window.location.href.split('=')[1]; + const [after, setAfter] = useState(null); + const [before, setBefore] = useState(null); + const [first, setFirst] = useState(6); + const [last, setLast] = useState(null); const showInviteModal = (): void => { setPostModalIsOpen(true); }; + const hideInviteModal = (): void => { setPostModalIsOpen(false); setPostFormState({ @@ -61,6 +79,8 @@ function orgPost(): JSX.Element { postinfo: '', postImage: '', postVideo: '', + addMedia: '', + pinPost: false, }); }; @@ -69,24 +89,41 @@ function orgPost(): JSX.Element { loading: orgPostListLoading, error: orgPostListError, refetch, - } = useQuery(ORGANIZATION_POST_CONNECTION_LIST, { - variables: { id: currentUrl, title_contains: '', text_contains: '' }, + }: { + data?: { + organizations: InterfaceQueryOrganizationPostListItem[]; + }; + loading: boolean; + error?: ApolloError; + refetch: any; + } = useQuery(ORGANIZATION_POST_LIST, { + variables: { + id: currentUrl, + after: after, + before: before, + first: first, + last: last, + }, }); const [create, { loading: createPostLoading }] = useMutation(CREATE_POST_MUTATION); const [displayedPosts, setDisplayedPosts] = useState( - orgPostListData?.postsByOrganizationConnection.edges || [] + orgPostListData?.organizations[0].posts.edges.map((edge) => edge.node) || + [], ); + // ... + useEffect(() => { - if (orgPostListData && orgPostListData.postsByOrganizationConnection) { - const newDisplayedPosts = sortPosts( - orgPostListData.postsByOrganizationConnection.edges, - sortingOption + if (orgPostListData && orgPostListData.organizations) { + const newDisplayedPosts: InterfaceOrgPost[] = sortPosts( + orgPostListData.organizations[0].posts.edges.map((edge) => edge.node), + sortingOption, ); setDisplayedPosts(newDisplayedPosts); } }, [orgPostListData, sortingOption]); + const createPost = async (e: ChangeEvent): Promise => { e.preventDefault(); @@ -95,6 +132,7 @@ function orgPost(): JSX.Element { postinfo: _postinfo, postImage, postVideo, + pinPost, } = postformState; const posttitle = _posttitle.trim(); @@ -110,35 +148,58 @@ function orgPost(): JSX.Element { title: posttitle, text: postinfo, organizationId: currentUrl, - file: postImage || postVideo, + file: postImage || postVideo || postformState.addMedia, + pinned: pinPost, }, }); + /* istanbul ignore next */ if (data) { - toast.success('Congratulations! You have Posted Something.'); + toast.success(t('postCreatedSuccess')); refetch(); setPostFormState({ posttitle: '', postinfo: '', postImage: '', postVideo: '', + addMedia: '', + pinPost: false, }); - setPostModalIsOpen(false); // close the modal + setPostModalIsOpen(false); } } catch (error: any) { - /* istanbul ignore next */ errorHandler(t, error); } }; + useEffect(() => { + if (orgPostListError) { + navigate('/orglist'); + } + }, [orgPostListError]); + if (createPostLoading || orgPostListLoading) { return ; } - /* istanbul ignore next */ - if (orgPostListError) { - window.location.assign('/orglist'); - } + const handleAddMediaChange = async ( + e: React.ChangeEvent, + ): Promise => { + setPostFormState((prevPostFormState) => ({ + ...prevPostFormState, + addMedia: '', + })); + + const selectedFile = e.target.files?.[0]; + + if (selectedFile) { + setFile(selectedFile); + setPostFormState({ + ...postformState, + addMedia: await convertToBase64(selectedFile), + }); + } + }; const handleSearch = (e: any): void => { const { value } = e.target; @@ -150,27 +211,39 @@ function orgPost(): JSX.Element { refetch(filterData); }; - const debouncedHandleSearch = debounce(handleSearch); + const debouncedHandleSearch = handleSearch; const handleSorting = (option: string): void => { setSortingOption(option); }; - + const handleNextPage = (): void => { + setAfter(orgPostListData?.organizations[0].posts.pageInfo.endCursor); + setBefore(null); + setFirst(6); + setLast(null); + }; + const handlePreviousPage = (): void => { + setBefore(orgPostListData?.organizations[0].posts.pageInfo.startCursor); + setAfter(null); + setFirst(null); + setLast(6); + }; + // console.log(orgPostListData?.organizations[0].posts); const sortPosts = ( posts: InterfaceOrgPost[], - sortingOption: string + sortingOption: string, ): InterfaceOrgPost[] => { const sortedPosts = [...posts]; if (sortingOption === 'latest') { sortedPosts.sort( (a, b) => - new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime() + new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(), ); } else if (sortingOption === 'oldest') { sortedPosts.sort( (a, b) => - new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime() + new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime(), ); } @@ -182,144 +255,168 @@ function orgPost(): JSX.Element { if (a.pinned === b.pinned) { return 0; } - + /* istanbul ignore next */ if (a.pinned) { return -1; } return 1; }); + return ( <> - - -
    -
    -
    - - +
    +
    +
    +
    -
    -
    - - -
    - - + + + {t('sortPost')} + + + handleSorting('latest')} + data-testid="latest" + > + {t('Latest')} + + handleSorting('oldest')} + data-testid="oldest" + > + {t('Oldest')} + + +
    + +
    -
    - {sortedPostsList && sortedPostsList.length > 0 ? ( - sortedPostsList.map( - (datas: { - _id: string; - title: string; - text: string; - imageUrl: string; - videoUrl: string; - organizationId: string; - creator: { firstName: string; lastName: string }; - pinned: boolean; - }) => ( - - ) - ) - ) : ( - - )} -
    - - +
    + {sortedPostsList && sortedPostsList.length > 0 ? ( + sortedPostsList.map( + (datas: { + _id: string; + title: string; + text: string; + imageUrl: string | null; + videoUrl: string | null; + + creator: { firstName: string; lastName: string }; + pinned: boolean; + }) => ( + + ), + ) + ) : ( + + )} +
    +
    +
    +
    + +
    +
    + +
    +
    +
    - {!postformState.postVideo && ( - <> - {t('image')} - - ): Promise => { - setPostFormState((prevPostFormState) => ({ - ...prevPostFormState, - postImage: '', - })); - const file = e.target.files?.[0]; - if (file) { - setPostFormState({ - ...postformState, - postImage: await convertToBase64(file), - }); - } - }} - /> + + + {t('addMedia')} + - {postformState.postImage && ( -
    - Post Image Preview - -
    + {postformState.addMedia && file && ( +
    + {/* Display preview for both image and video */} + {file.type.startsWith('image') ? ( + Post Image Preview + ) : ( + )} - - )} - {!postformState.postImage && ( - <> - {t('video')} - => { - setPostFormState((prevPostFormState) => ({ - ...prevPostFormState, - postVideo: '', - })); - const target = e.target as HTMLInputElement; - const file = target.files && target.files[0]; - if (file) { - const videoBase64 = await convertToBase64(file); - setPostFormState({ - ...postformState, - postVideo: videoBase64, - }); + -
    - )} - + data-testid="mediaCloseButton" + > + + +
    )} + + {t('pinPost')} + + + setPostFormState({ + ...postformState, + pinPost: !postformState.pinPost, + }) + } + /> + + ))} +
    + + + + {t(orgSetting)} + + + {orgSettings.map((setting, index) => ( + setOrgSetting(setting) + } + className={orgSetting === setting ? 'text-secondary' : ''} + > + {t(setting)} + + ))} + + + + +
    +
    - + + {orgSetting === 'general' && ( + + + +
    +
    + {t('updateOrganization')} +
    +
    + + {orgId && } + +
    + + + + +
    +
    {t('otherSettings')}
    +
    + +
    + + {t('changeLanguage')} + + +
    +
    +
    + + + +
    +
    + {t('manageCustomFields')} +
    +
    + + {orgId && } + +
    + +
    + )} + + {orgSetting === 'actionItemCategories' && ( + +
    +
    + {t('actionItemCategories')} +
    +
    +
    + {orgId && } +
    +
    + )} +
    ); } diff --git a/src/screens/OrganizationActionItems/ActionItemCreateModal.tsx b/src/screens/OrganizationActionItems/ActionItemCreateModal.tsx new file mode 100644 index 0000000000..e81459d7e4 --- /dev/null +++ b/src/screens/OrganizationActionItems/ActionItemCreateModal.tsx @@ -0,0 +1,155 @@ +import React from 'react'; +import { Modal, Form, Button } from 'react-bootstrap'; +import type { ChangeEvent } from 'react'; +import styles from './OrganizationActionItems.module.css'; +import { DatePicker } from '@mui/x-date-pickers'; +import dayjs from 'dayjs'; +import type { Dayjs } from 'dayjs'; + +import type { + InterfaceActionItemCategoryInfo, + InterfaceMemberInfo, +} from 'utils/interfaces'; + +interface InterfaceFormStateType { + actionItemCategoryId: string; + assigneeId: string; + eventId?: string; + preCompletionNotes: string; +} + +interface InterfaceActionItemCreateModalProps { + actionItemCreateModalIsOpen: boolean; + hideCreateModal: () => void; + formState: InterfaceFormStateType; + setFormState: (state: React.SetStateAction) => void; + createActionItemHandler: (e: ChangeEvent) => Promise; + t: (key: string) => string; + actionItemCategories: InterfaceActionItemCategoryInfo[] | undefined; + membersData: InterfaceMemberInfo[] | undefined; + dueDate: Date | null; + setDueDate: (state: React.SetStateAction) => void; +} + +const ActionItemCreateModal: React.FC = ({ + actionItemCreateModalIsOpen, + hideCreateModal, + formState, + setFormState, + createActionItemHandler, + t, + actionItemCategories, + membersData, + dueDate, + setDueDate, +}) => { + return ( + <> + + +

    {t('actionItemDetails')}

    + +
    + +
    + + {t('actionItemCategory')} + + setFormState({ + ...formState, + actionItemCategoryId: e.target.value, + }) + } + > + + {actionItemCategories?.map((category, index) => ( + + ))} + + + + + Assignee + + setFormState({ ...formState, assigneeId: e.target.value }) + } + > + + {membersData?.map((member, index) => ( + + ))} + + + + + { + setFormState({ + ...formState, + preCompletionNotes: e.target.value, + }); + }} + /> + +
    + { + if (date) { + setDueDate(date?.toDate()); + } + }} + /> +
    + + + +
    +
    + + ); +}; + +export default ActionItemCreateModal; diff --git a/src/screens/OrganizationActionItems/ActionItemDeleteModal.tsx b/src/screens/OrganizationActionItems/ActionItemDeleteModal.tsx new file mode 100644 index 0000000000..bdb63dad07 --- /dev/null +++ b/src/screens/OrganizationActionItems/ActionItemDeleteModal.tsx @@ -0,0 +1,59 @@ +import React from 'react'; +import { Modal, Button } from 'react-bootstrap'; +import styles from './OrganizationActionItems.module.css'; + +interface InterfaceActionItemCreateModalProps { + actionItemDeleteModalIsOpen: boolean; + deleteActionItemHandler: () => Promise; + toggleDeleteModal: () => void; + t: (key: string) => string; +} + +const ActionItemPreviewModal: React.FC = ({ + actionItemDeleteModalIsOpen, + deleteActionItemHandler, + toggleDeleteModal, + t, +}) => { + return ( + <> + + + + {t('deleteActionItem')} + + + {t('deleteActionItemMsg')} + + + + + + + ); +}; + +export default ActionItemPreviewModal; diff --git a/src/screens/OrganizationActionItems/ActionItemPreviewModal.tsx b/src/screens/OrganizationActionItems/ActionItemPreviewModal.tsx new file mode 100644 index 0000000000..8f2d0b8f1c --- /dev/null +++ b/src/screens/OrganizationActionItems/ActionItemPreviewModal.tsx @@ -0,0 +1,133 @@ +import React from 'react'; +import { Modal, Form, Button } from 'react-bootstrap'; + +import styles from './OrganizationActionItems.module.css'; +import dayjs from 'dayjs'; + +interface InterfaceFormStateType { + assigneeId: string; + assignee: string; + assigner: string; + isCompleted: boolean; + preCompletionNotes: string; + postCompletionNotes: string; +} + +interface InterfaceActionItemCreateModalProps { + actionItemPreviewModalIsOpen: boolean; + hidePreviewModal: () => void; + showUpdateModal: () => void; + toggleDeleteModal: () => void; + formState: InterfaceFormStateType; + t: (key: string) => string; + dueDate: Date | null; + completionDate: Date | null; + assignmentDate: Date | null; +} + +const ActionItemPreviewModal: React.FC = ({ + actionItemPreviewModalIsOpen, + hidePreviewModal, + showUpdateModal, + toggleDeleteModal, + formState, + t, + dueDate, + completionDate, + assignmentDate, +}) => { + return ( + <> + + +

    {t('actionItemDetails')}

    + +
    + +
    +
    +

    + {t('assignee')}:{' '} + {formState.assignee} +

    +

    + {t('assigner')}:{' '} + {formState.assigner} +

    +

    + {t('preCompletionNotes')}: + + {formState.preCompletionNotes} + +

    +

    + {t('postCompletionNotes')}: + + {formState.postCompletionNotes} + +

    +

    + {t('assignmentDate')}:{' '} + + {dayjs(assignmentDate).format('YYYY-MM-DD')} + +

    +

    + {t('dueDate')}:{' '} + + {dayjs(dueDate).format('YYYY-MM-DD')} + +

    +

    + {t('completionDate')}:{' '} + + {dayjs(completionDate).format('YYYY-MM-DD')} + +

    +

    + {t('status')}:{' '} + + {formState.isCompleted ? 'Completed' : 'Active'} + +

    +
    +
    + + +
    +
    +
    +
    + + ); +}; + +export default ActionItemPreviewModal; diff --git a/src/screens/OrganizationActionItems/ActionItemUpdateModal.test.tsx b/src/screens/OrganizationActionItems/ActionItemUpdateModal.test.tsx new file mode 100644 index 0000000000..f52da23530 --- /dev/null +++ b/src/screens/OrganizationActionItems/ActionItemUpdateModal.test.tsx @@ -0,0 +1,235 @@ +import React from 'react'; +import { render, screen, fireEvent } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import ActionItemUpdateModal from './ActionItemUpdateModal'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import type { InterfaceMemberInfo } from 'utils/interfaces'; +import { t } from 'i18next'; + +const mockMembersData: InterfaceMemberInfo[] = [ + { + _id: '1', + firstName: 'John', + lastName: 'Doe', + email: 'john.doe@example.com', + image: 'https://example.com/john-doe.jpg', + createdAt: '2022-01-01T00:00:00.000Z', + organizationsBlockedBy: [], + }, + { + _id: '2', + firstName: 'Jane', + lastName: 'Smith', + email: 'jane.smith@example.com', + image: 'https://example.com/jane-smith.jpg', + createdAt: '2022-02-01T00:00:00.000Z', + organizationsBlockedBy: [], + }, +]; + +const mockFormState = { + assigneeId: '1', + assignee: 'John Doe', + assigner: 'Jane Smith', + isCompleted: false, + preCompletionNotes: 'Test pre-completion notes', + postCompletionNotes: '', +}; + +const mockDueDate = new Date('2023-05-01'); +const mockCompletionDate = new Date('2023-05-15'); + +const mockHideUpdateModal = jest.fn(); +const mockSetFormState = jest.fn(); +const mockUpdateActionItemHandler = jest.fn(); +const mockSetDueDate = jest.fn(); +const mockSetCompletionDate = jest.fn(); +const mockT = (key: string): string => key; + +describe('ActionItemUpdateModal', () => { + test('renders modal correctly', () => { + render( + + + + + + + + + + + , + ); + + expect(screen.getByText('actionItemDetails')).toBeInTheDocument(); + expect( + screen.getByTestId('updateActionItemModalCloseBtn'), + ).toBeInTheDocument(); + expect(screen.getByTestId('formUpdateAssignee')).toBeInTheDocument(); + expect(screen.getByLabelText('preCompletionNotes')).toBeInTheDocument(); + expect(screen.getByLabelText('dueDate')).toBeInTheDocument(); + expect(screen.getByLabelText('completionDate')).toBeInTheDocument(); + expect(screen.getByTestId('editActionItemBtn')).toBeInTheDocument(); + }); + + test('closes modal when close button is clicked', () => { + render( + + + + + + + + + + + , + ); + + fireEvent.click(screen.getByTestId('updateActionItemModalCloseBtn')); + expect(mockHideUpdateModal).toHaveBeenCalled(); + }); + + test('updates form state when assignee is changed', () => { + render( + + + + + + + + + + + , + ); + + const assigneeSelect = screen.getByTestId('formUpdateAssignee'); + userEvent.selectOptions(assigneeSelect, '2'); + expect(mockSetFormState).toHaveBeenCalledWith({ + ...mockFormState, + assigneeId: '2', + }); + }); + + test('tests the condition for formState.preCompletionNotes', () => { + const mockFormState = { + assigneeId: '1', + assignee: 'John Doe', + assigner: 'Jane Smith', + isCompleted: false, + preCompletionNotes: '', + postCompletionNotes: '', + }; + render( + + + + + + + + + + + , + ); + const preCompletionNotesInput = screen.getByLabelText('preCompletionNotes'); + fireEvent.change(preCompletionNotesInput, { + target: { value: 'New pre-completion notes' }, + }); + expect(mockSetFormState).toHaveBeenCalledWith({ + ...mockFormState, + preCompletionNotes: 'New pre-completion notes', + }); + }); + + test('calls updateActionItemHandler when form is submitted', () => { + render( + + + + + + + + + + + , + ); + + fireEvent.submit(screen.getByTestId('editActionItemBtn')); + expect(mockUpdateActionItemHandler).toHaveBeenCalled(); + }); +}); diff --git a/src/screens/OrganizationActionItems/ActionItemUpdateModal.tsx b/src/screens/OrganizationActionItems/ActionItemUpdateModal.tsx new file mode 100644 index 0000000000..10a32254de --- /dev/null +++ b/src/screens/OrganizationActionItems/ActionItemUpdateModal.tsx @@ -0,0 +1,157 @@ +import React from 'react'; +import { Modal, Form, Button } from 'react-bootstrap'; +import type { ChangeEvent } from 'react'; +import { DatePicker } from '@mui/x-date-pickers'; +import dayjs from 'dayjs'; +import type { Dayjs } from 'dayjs'; + +import styles from './OrganizationActionItems.module.css'; +import type { InterfaceMemberInfo } from 'utils/interfaces'; + +interface InterfaceFormStateType { + assigneeId: string; + assignee: string; + assigner: string; + isCompleted: boolean; + preCompletionNotes: string; + postCompletionNotes: string; +} + +interface InterfaceActionItemCreateModalProps { + actionItemUpdateModalIsOpen: boolean; + hideUpdateModal: () => void; + formState: InterfaceFormStateType; + setFormState: (state: React.SetStateAction) => void; + updateActionItemHandler: (e: ChangeEvent) => Promise; + t: (key: string) => string; + membersData: InterfaceMemberInfo[] | undefined; + dueDate: Date | null; + setDueDate: (state: React.SetStateAction) => void; + completionDate: Date | null; + setCompletionDate: (state: React.SetStateAction) => void; +} + +const ActionItemUpdateModal: React.FC = ({ + actionItemUpdateModalIsOpen, + hideUpdateModal, + formState, + setFormState, + updateActionItemHandler, + t, + membersData, + dueDate, + setDueDate, + completionDate, + setCompletionDate, +}) => { + return ( + <> + + +

    {t('actionItemDetails')}

    + +
    + +
    + + Assignee + + setFormState({ ...formState, assigneeId: e.target.value }) + } + > + + {membersData?.map((member, index) => { + const currMemberName = `${member.firstName} ${member.lastName}`; + if (currMemberName !== formState.assignee) { + return ( + + ); + } + })} + + + + + { + setFormState({ + ...formState, + preCompletionNotes: e.target.value, + }); + }} + className="mb-2" + /> + +
    +
    + { + /* istanbul ignore next */ + if (date) { + setDueDate(date?.toDate()); + } + } + } + /> +
    +
    + { + /* istanbul ignore next */ + if (date) { + setCompletionDate(date?.toDate()); + } + } + } + /> +
    +
    + + + +
    +
    + + ); +}; + +export default ActionItemUpdateModal; diff --git a/src/screens/OrganizationActionItems/OrganizationActionItemMocks.ts b/src/screens/OrganizationActionItems/OrganizationActionItemMocks.ts new file mode 100644 index 0000000000..8c92e49939 --- /dev/null +++ b/src/screens/OrganizationActionItems/OrganizationActionItemMocks.ts @@ -0,0 +1,388 @@ +import { CREATE_ACTION_ITEM_MUTATION } from 'GraphQl/Mutations/mutations'; + +import { + ACTION_ITEM_CATEGORY_LIST, + ACTION_ITEM_LIST, + MEMBERS_LIST, +} from 'GraphQl/Queries/Queries'; + +export const MOCKS = [ + { + request: { + query: ACTION_ITEM_CATEGORY_LIST, + variables: { organizationId: '123' }, + }, + result: { + data: { + actionItemCategoriesByOrganization: [ + { + _id: 'actionItemCategory1', + name: 'ActionItemCategory 1', + isDisabled: false, + }, + ], + }, + }, + }, + { + request: { + query: MEMBERS_LIST, + variables: { id: '123' }, + }, + result: { + data: { + organizations: [ + { + _id: '123', + members: [ + { + _id: 'user1', + firstName: 'Harve', + lastName: 'Lance', + email: 'harve@example.com', + image: '', + organizationsBlockedBy: [], + createdAt: '2024-02-14', + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: ACTION_ITEM_LIST, + variables: { + organizationId: '123', + orderBy: 'createdAt_DESC', + actionItemCategoryId: '', + isActive: false, + isCompleted: false, + }, + }, + result: { + data: { + actionItemsByOrganization: [ + { + _id: 'actionItem1', + assignee: { + _id: 'user1', + firstName: 'Harve', + lastName: 'Lance', + }, + actionItemCategory: { + _id: 'actionItemCategory1', + name: 'ActionItemCategory 1', + }, + preCompletionNotes: 'Pre Completion Notes', + postCompletionNotes: 'Post Completion Notes', + assignmentDate: '2024-02-14', + dueDate: '2024-02-21', + completionDate: '2024-02-21', + isCompleted: false, + assigner: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + event: { + _id: 'event1', + title: 'event 1', + }, + creator: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + ], + }, + }, + }, + { + request: { + query: ACTION_ITEM_LIST, + variables: { + organizationId: '123', + eventId: 'event1', + orderBy: 'createdAt_DESC', + }, + }, + result: { + data: { + actionItemsByOrganization: [ + { + _id: 'actionItem1', + assignee: { + _id: 'user1', + firstName: 'Harve', + lastName: 'Lance', + }, + actionItemCategory: { + _id: 'actionItemCategory1', + name: 'ActionItemCategory 1', + }, + preCompletionNotes: 'Pre Completion Notes', + postCompletionNotes: 'Post Completion Notes', + assignmentDate: '2024-02-14', + dueDate: '2024-02-21', + completionDate: '2024-02-21', + isCompleted: false, + assigner: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + event: { + _id: 'event1', + title: 'event 1', + }, + creator: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + ], + }, + }, + }, + { + request: { + query: ACTION_ITEM_LIST, + variables: { + organizationId: '123', + orderBy: 'createdAt_ASC', + actionItemCategoryId: '', + isActive: false, + isCompleted: false, + }, + }, + result: { + data: { + actionItemsByOrganization: [ + { + _id: 'actionItem3', + assignee: { + _id: 'user1', + firstName: 'Praise', + lastName: 'Norris', + }, + actionItemCategory: { + _id: 'actionItemCategory3', + name: 'ActionItemCategory 3', + }, + preCompletionNotes: 'Pre Completion Notes', + postCompletionNotes: 'Post Completion Notes', + assignmentDate: '2024-02-14', + dueDate: '2024-02-21', + completionDate: '2024-02-21', + isCompleted: false, + assigner: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + event: { + _id: 'event1', + title: 'event 1', + }, + creator: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + ], + }, + }, + }, + { + request: { + query: ACTION_ITEM_LIST, + variables: { + organizationId: '123', + orderBy: 'createdAt_ASC', + actionItemCategoryId: '', + isActive: true, + isCompleted: false, + }, + }, + result: { + data: { + actionItemsByOrganization: [ + { + _id: 'actionItem1', + assignee: { + _id: 'user1', + firstName: 'Harve', + lastName: 'Lance', + }, + actionItemCategory: { + _id: 'actionItemCategory1', + name: 'ActionItemCategory 1', + }, + preCompletionNotes: 'Pre Completion Notes', + postCompletionNotes: 'Post Completion Notes', + assignmentDate: '2024-02-14', + dueDate: '2024-02-21', + completionDate: '2024-02-21', + isCompleted: true, + assigner: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + event: { + _id: 'event1', + title: 'event 1', + }, + creator: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + ], + }, + }, + }, + { + request: { + query: ACTION_ITEM_LIST, + variables: { + organizationId: '123', + orderBy: 'createdAt_ASC', + actionItemCategoryId: '', + isActive: false, + isCompleted: true, + }, + }, + result: { + data: { + actionItemsByOrganization: [ + { + _id: 'actionItem1', + assignee: { + _id: 'user1', + firstName: 'Harve', + lastName: 'Lance', + }, + actionItemCategory: { + _id: 'actionItemCategory1', + name: 'ActionItemCategory 1', + }, + preCompletionNotes: 'Pre Completion Notes', + postCompletionNotes: 'Post Completion Notes', + assignmentDate: '2024-02-14', + dueDate: '2024-02-21', + completionDate: '2024-02-21', + isCompleted: true, + assigner: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + event: { + _id: 'event1', + title: 'event 1', + }, + creator: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + ], + }, + }, + }, + { + request: { + query: ACTION_ITEM_LIST, + variables: { + organizationId: '123', + orderBy: 'createdAt_ASC', + actionItemCategoryId: 'actionItemCategory1', + isActive: false, + isCompleted: true, + }, + }, + result: { + data: { + actionItemsByOrganization: [ + { + _id: 'actionItem1', + assignee: { + _id: 'user1', + firstName: 'Harve', + lastName: 'Lance', + }, + actionItemCategory: { + _id: 'actionItemCategory1', + name: 'ActionItemCategory 1', + }, + preCompletionNotes: 'Pre Completion Notes', + postCompletionNotes: 'Post Completion Notes', + assignmentDate: '2024-02-14', + dueDate: '2024-02-21', + completionDate: '2024-02-21', + isCompleted: true, + assigner: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + event: { + _id: 'event1', + title: 'event 1', + }, + creator: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + ], + }, + }, + }, + { + request: { + query: CREATE_ACTION_ITEM_MUTATION, + variables: { + actionItemCategoryId: 'actionItemCategory1', + assigneeId: 'user1', + preCompletionNotes: 'pre completion notes', + dueDate: '2024-02-14', + }, + }, + result: { + data: { + createActionItem: { + _id: 'actionItem2', + }, + }, + }, + }, + { + request: { + query: CREATE_ACTION_ITEM_MUTATION, + variables: { + eventId: 'event1', + actionItemCategoryId: 'actionItemCategory1', + assigneeId: 'user1', + preCompletionNotes: 'pre completion notes', + dueDate: '2024-02-14', + }, + }, + result: { + data: { + createActionItem: { + _id: 'actionItem2', + }, + }, + }, + }, +]; diff --git a/src/screens/OrganizationActionItems/OrganizationActionItems.module.css b/src/screens/OrganizationActionItems/OrganizationActionItems.module.css new file mode 100644 index 0000000000..7a67362c8b --- /dev/null +++ b/src/screens/OrganizationActionItems/OrganizationActionItems.module.css @@ -0,0 +1,168 @@ +.actionItemsContainer { + height: 90vh; +} + +.actionItemModal { + max-width: 80vw; + margin-top: 2vh; + margin-left: 13vw; +} + +.btnsContainer { + display: flex; + gap: 10px; +} + +.btnsContainer .btnsBlock { + display: flex; + gap: 10px; +} + +.btnsContainer button { + display: flex; + justify-content: center; + align-items: center; +} + +.container { + min-height: 100vh; +} + +.datediv { + display: flex; + flex-direction: row; +} + +.datebox { + width: 90%; + border-radius: 7px; + outline: none; + box-shadow: none; + padding-top: 2px; + padding-bottom: 2px; + padding-right: 5px; + padding-left: 5px; + margin-right: 5px; + margin-left: 5px; +} + +.dropdown { + display: block; +} + +.dropdownToggle { + margin-bottom: 0; + display: flex; +} + +.dropdownModalToggle { + width: 50%; +} + +.errorIcon { + transform: scale(1.5); + color: var(--bs-danger); + margin-bottom: 1rem; +} + +.greenregbtn { + margin: 1rem 0 0; + margin-top: 15px; + border: 1px solid var(--bs-gray-300); + box-shadow: 0 2px 2px var(--bs-gray-300); + padding: 10px 10px; + border-radius: 5px; + background-color: var(--bs-primary); + width: 100%; + font-size: 16px; + color: var(--bs-white); + outline: none; + font-weight: 600; + cursor: pointer; + transition: + transform 0.2s, + box-shadow 0.2s; + width: 100%; +} + +hr { + border: none; + height: 1px; + background-color: var(--bs-gray-500); + margin: 1rem; +} + +.iconContainer { + display: flex; + justify-content: flex-end; +} +.icon { + margin: 1px; +} + +.message { + margin-top: 25%; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; +} + +.organizationActionItemsContainer h2 { + margin: 0.6rem 0; +} + +.preview { + display: flex; + flex-direction: row; + font-weight: 900; + font-size: 16px; + color: rgb(80, 80, 80); +} + +.removeFilterIcon { + cursor: pointer; +} + +.searchForm { + display: inline; +} + +.titlemodal { + color: var(--bs-gray-600); + font-weight: 600; + font-size: 20px; + margin-bottom: 20px; + padding-bottom: 5px; + border-bottom: 3px solid var(--bs-primary); + width: 65%; +} + +.view { + margin-left: 2%; + font-weight: 600; + font-size: 16px; + color: var(--bs-gray-600); +} + +@media (max-width: 767px) { + .btnsContainer { + margin-bottom: 0; + display: flex; + flex-direction: column; + } + + .btnsContainer .btnsBlock .dropdownToggle { + flex-grow: 1; + } + + .btnsContainer button { + width: 100%; + } + + .createActionItemButton { + position: absolute; + top: 1rem; + right: 2rem; + } +} diff --git a/src/screens/OrganizationActionItems/OrganizationActionItems.test.tsx b/src/screens/OrganizationActionItems/OrganizationActionItems.test.tsx new file mode 100644 index 0000000000..d0672aac18 --- /dev/null +++ b/src/screens/OrganizationActionItems/OrganizationActionItems.test.tsx @@ -0,0 +1,599 @@ +import React from 'react'; +import { + render, + screen, + fireEvent, + waitFor, + act, + waitForElementToBeRemoved, +} from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import 'jest-localstorage-mock'; +import { MockedProvider } from '@apollo/client/testing'; +import 'jest-location-mock'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import i18nForTest from 'utils/i18nForTest'; +import { toast } from 'react-toastify'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; + +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; + +import OrganizationActionItems from './OrganizationActionItems'; +import { + MOCKS_ERROR_ACTION_ITEM_CATEGORY_LIST_QUERY, + MOCKS_ERROR_ACTION_ITEM_LIST_QUERY, + MOCKS_ERROR_MEMBERS_LIST_QUERY, + MOCKS_ERROR_MUTATIONS, +} from './OrganizationActionItemsErrorMocks'; +import { MOCKS } from './OrganizationActionItemMocks'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +jest.mock('@mui/x-date-pickers/DateTimePicker', () => { + return { + DateTimePicker: jest.requireActual( + '@mui/x-date-pickers/DesktopDateTimePicker', + ).DesktopDateTimePicker, + }; +}); + +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: '123' }), +})); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +const link = new StaticMockLink(MOCKS, true); +const link2 = new StaticMockLink( + MOCKS_ERROR_ACTION_ITEM_CATEGORY_LIST_QUERY, + true, +); +const link3 = new StaticMockLink(MOCKS_ERROR_MEMBERS_LIST_QUERY, true); +const link4 = new StaticMockLink(MOCKS_ERROR_ACTION_ITEM_LIST_QUERY, true); +const link5 = new StaticMockLink(MOCKS_ERROR_MUTATIONS, true); + +const translations = JSON.parse( + JSON.stringify( + i18nForTest.getDataByLanguage('en')?.translation.organizationActionItems, + ), +); + +describe('Testing Action Item Categories Component', () => { + const formData = { + actionItemCategory: 'ActionItemCategory 1', + assignee: 'Harve Lance', + preCompletionNotes: 'pre completion notes', + dueDate: '02/14/2024', + }; + + test('Component loads correctly', async () => { + const { getByText } = render( + + + + + {} + + + + , + ); + + await wait(); + + await waitFor(() => { + expect(getByText(translations.createActionItem)).toBeInTheDocument(); + }); + }); + + test('render error component on unsuccessful action item category list query', async () => { + const { queryByText } = render( + + + + + {} + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + queryByText(translations.createActionItem), + ).not.toBeInTheDocument(); + }); + }); + + test('render error component on unsuccessful members list query', async () => { + const { queryByText } = render( + + + + + {} + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + queryByText(translations.createActionItem), + ).not.toBeInTheDocument(); + }); + }); + + test('render error component on unsuccessful action item list query', async () => { + const { queryByText } = render( + + + + + {} + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + queryByText(translations.createActionItem), + ).not.toBeInTheDocument(); + }); + }); + + test('sorts action items in earliest or latest first order based on orderBy', async () => { + render( + + + + + {} + + + + , + ); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('sortActionItems')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('sortActionItems')); + + await waitFor(() => { + expect(screen.getByTestId('earliest')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('earliest')); + + await waitFor(() => { + expect(screen.getByTestId('sortActionItems')).toHaveTextContent( + translations.earliest, + ); + }); + + await waitFor(() => { + expect(screen.getByTestId('sortActionItems')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('sortActionItems')); + + await waitFor(() => { + expect(screen.getByTestId('latest')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('latest')); + + await waitFor(() => { + expect(screen.getByTestId('sortActionItems')).toHaveTextContent( + translations.latest, + ); + }); + }); + + test('applies and then clears filters one by one', async () => { + render( + + + + + {} + + + + , + ); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('sortActionItems')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('sortActionItems')); + + await waitFor(() => { + expect(screen.getByTestId('earliest')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('earliest')); + + // all the action items ordered by earliest first + await waitFor(() => { + expect(screen.getByTestId('sortActionItems')).toHaveTextContent( + translations.earliest, + ); + }); + + await waitFor(() => { + expect(screen.getByTestId('selectActionItemStatus')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('selectActionItemStatus')); + + await waitFor(() => { + expect(screen.getByTestId('activeActionItems')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('activeActionItems')); + + // all the action items that are active + await waitFor(() => { + expect(screen.getByTestId('selectActionItemStatus')).toHaveTextContent( + translations.active, + ); + }); + + await waitFor(() => { + expect(screen.getByTestId('selectActionItemStatus')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('selectActionItemStatus')); + + await waitFor(() => { + expect(screen.getByTestId('completedActionItems')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('completedActionItems')); + + // all the action items that are completed + await waitFor(() => { + expect(screen.getByTestId('selectActionItemStatus')).toHaveTextContent( + translations.completed, + ); + }); + + await waitFor(() => { + expect( + screen.getByTestId('selectActionItemCategory'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('selectActionItemCategory')); + + await waitFor(() => { + expect( + screen.getAllByTestId('actionItemCategory')[0], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('actionItemCategory')[0]); + + // action items belonging to this action item category + await waitFor(() => { + expect(screen.getByTestId('selectActionItemCategory')).toHaveTextContent( + 'ActionItemCategory 1', + ); + }); + + await waitFor(() => { + expect( + screen.getByTestId('clearActionItemCategoryFilter'), + ).toBeInTheDocument(); + }); + // remove the action item category filter + userEvent.click(screen.getByTestId('clearActionItemCategoryFilter')); + + await waitFor(() => { + expect( + screen.queryByTestId('clearActionItemCategoryFilter'), + ).not.toBeInTheDocument(); + }); + + await waitFor(() => { + expect( + screen.getByTestId('clearActionItemStatusFilter'), + ).toBeInTheDocument(); + }); + // remove the action item status filter + userEvent.click(screen.getByTestId('clearActionItemStatusFilter')); + + await waitFor(() => { + expect(screen.getByTestId('selectActionItemStatus')).toHaveTextContent( + translations.status, + ); + expect(screen.getByTestId('selectActionItemCategory')).toHaveTextContent( + translations.actionItemCategory, + ); + }); + }); + + test('applies and then clears all the filters', async () => { + render( + + + + + {} + + + + , + ); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('sortActionItems')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('sortActionItems')); + + await waitFor(() => { + expect(screen.getByTestId('earliest')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('earliest')); + + // all the action items ordered by earliest first + await waitFor(() => { + expect(screen.getByTestId('sortActionItems')).toHaveTextContent( + translations.earliest, + ); + }); + + await waitFor(() => { + expect(screen.getByTestId('selectActionItemStatus')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('selectActionItemStatus')); + + await waitFor(() => { + expect(screen.getByTestId('activeActionItems')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('activeActionItems')); + + // all the action items that are active + await waitFor(() => { + expect(screen.getByTestId('selectActionItemStatus')).toHaveTextContent( + translations.active, + ); + }); + + await waitFor(() => { + expect(screen.getByTestId('selectActionItemStatus')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('selectActionItemStatus')); + + await waitFor(() => { + expect(screen.getByTestId('completedActionItems')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('completedActionItems')); + + // all the action items that are completed + await waitFor(() => { + expect(screen.getByTestId('selectActionItemStatus')).toHaveTextContent( + translations.completed, + ); + }); + + await waitFor(() => { + expect( + screen.getByTestId('selectActionItemCategory'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('selectActionItemCategory')); + + await waitFor(() => { + expect( + screen.getAllByTestId('actionItemCategory')[0], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('actionItemCategory')[0]); + + // action items belonging to this action item category + await waitFor(() => { + expect(screen.getByTestId('selectActionItemCategory')).toHaveTextContent( + 'ActionItemCategory 1', + ); + }); + + await waitFor(() => { + expect(screen.getByTestId('clearFilters')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('clearFilters')); + + // filters cleared, all the action items belonging to the organization + await waitFor(() => { + expect(screen.getByTestId('sortActionItems')).toHaveTextContent( + translations.latest, + ); + expect(screen.getByTestId('selectActionItemStatus')).toHaveTextContent( + translations.status, + ); + expect(screen.getByTestId('selectActionItemCategory')).toHaveTextContent( + translations.actionItemCategory, + ); + }); + }); + + test('opens and closes the create action item modal', async () => { + render( + + + + + + {} + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('createActionItemBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('createActionItemBtn')); + + await waitFor(() => { + return expect( + screen.findByTestId('createActionItemModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('createActionItemModalCloseBtn')); + + await waitForElementToBeRemoved(() => + screen.queryByTestId('createActionItemModalCloseBtn'), + ); + }); + + test('creates new action item', async () => { + render( + + + + + + {} + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('createActionItemBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('createActionItemBtn')); + + await waitFor(() => { + return expect( + screen.findByTestId('createActionItemModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + + await waitFor(() => { + expect( + screen.getByTestId('formSelectActionItemCategory'), + ).toBeInTheDocument(); + }); + + userEvent.selectOptions( + screen.getByTestId('formSelectActionItemCategory'), + formData.actionItemCategory, + ); + + userEvent.selectOptions( + screen.getByTestId('formSelectAssignee'), + formData.assignee, + ); + + userEvent.type( + screen.getByPlaceholderText(translations.preCompletionNotes), + formData.preCompletionNotes, + ); + + const dueDatePicker = screen.getByLabelText(translations.dueDate); + fireEvent.change(dueDatePicker, { + target: { value: formData.dueDate }, + }); + + userEvent.click(screen.getByTestId('createActionItemFormSubmitBtn')); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.successfulCreation); + }); + }); + + test('toasts error on unsuccessful creation', async () => { + render( + + + + + + {} + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('createActionItemBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('createActionItemBtn')); + + await waitFor(() => { + return expect( + screen.findByTestId('createActionItemModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + + await waitFor(() => { + expect( + screen.getByTestId('formSelectActionItemCategory'), + ).toBeInTheDocument(); + }); + + userEvent.selectOptions( + screen.getByTestId('formSelectActionItemCategory'), + formData.actionItemCategory, + ); + + userEvent.selectOptions( + screen.getByTestId('formSelectAssignee'), + formData.assignee, + ); + + userEvent.type( + screen.getByPlaceholderText(translations.preCompletionNotes), + formData.preCompletionNotes, + ); + + const dueDatePicker = screen.getByLabelText(translations.dueDate); + fireEvent.change(dueDatePicker, { + target: { value: formData.dueDate }, + }); + + userEvent.click(screen.getByTestId('createActionItemFormSubmitBtn')); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/screens/OrganizationActionItems/OrganizationActionItems.tsx b/src/screens/OrganizationActionItems/OrganizationActionItems.tsx new file mode 100644 index 0000000000..106ab8cf73 --- /dev/null +++ b/src/screens/OrganizationActionItems/OrganizationActionItems.tsx @@ -0,0 +1,390 @@ +import React, { useState } from 'react'; +import type { ChangeEvent } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Button, Dropdown } from 'react-bootstrap'; +import { useParams } from 'react-router-dom'; + +import SortIcon from '@mui/icons-material/Sort'; +import { WarningAmberRounded } from '@mui/icons-material'; +import dayjs from 'dayjs'; +import { toast } from 'react-toastify'; + +import { useMutation, useQuery } from '@apollo/client'; +import { + ACTION_ITEM_CATEGORY_LIST, + ACTION_ITEM_LIST, + MEMBERS_LIST, +} from 'GraphQl/Queries/Queries'; +import { CREATE_ACTION_ITEM_MUTATION } from 'GraphQl/Mutations/mutations'; + +import type { + InterfaceActionItemCategoryList, + InterfaceActionItemList, + InterfaceMembersList, +} from 'utils/interfaces'; +import ActionItemsContainer from 'components/ActionItems/ActionItemsContainer'; +import ActionItemCreateModal from './ActionItemCreateModal'; +import styles from './OrganizationActionItems.module.css'; +import Loader from 'components/Loader/Loader'; + +function organizationActionItems(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'organizationActionItems', + }); + + const { orgId: currentUrl } = useParams(); + + const [actionItemCreateModalIsOpen, setActionItemCreateModalIsOpen] = + useState(false); + const [dueDate, setDueDate] = useState(new Date()); + const [orderBy, setOrderBy] = useState<'Latest' | 'Earliest'>('Latest'); + const [actionItemStatus, setActionItemStatus] = useState(''); + const [actionItemCategoryId, setActionItemCategoryId] = useState(''); + const [actionItemCategoryName, setActionItemCategoryName] = useState(''); + + const [formState, setFormState] = useState({ + actionItemCategoryId: '', + assigneeId: '', + preCompletionNotes: '', + }); + + const { + data: actionItemCategoriesData, + loading: actionItemCategoriesLoading, + error: actionItemCategoriesError, + }: { + data: InterfaceActionItemCategoryList | undefined; + loading: boolean; + error?: Error | undefined; + } = useQuery(ACTION_ITEM_CATEGORY_LIST, { + variables: { + organizationId: currentUrl, + }, + notifyOnNetworkStatusChange: true, + }); + + const { + data: membersData, + loading: membersLoading, + error: membersError, + }: { + data: InterfaceMembersList | undefined; + loading: boolean; + error?: Error | undefined; + } = useQuery(MEMBERS_LIST, { + variables: { id: currentUrl }, + }); + + const { + data: actionItemsData, + loading: actionItemsLoading, + error: actionItemsError, + refetch: actionItemsRefetch, + }: { + data: InterfaceActionItemList | undefined; + loading: boolean; + error?: Error | undefined; + refetch: () => void; + } = useQuery(ACTION_ITEM_LIST, { + variables: { + organizationId: currentUrl, + actionItemCategoryId, + orderBy: orderBy === 'Latest' ? 'createdAt_DESC' : 'createdAt_ASC', + isActive: actionItemStatus === 'Active' ? true : false, + isCompleted: actionItemStatus === 'Completed' ? true : false, + }, + notifyOnNetworkStatusChange: true, + }); + + const [createActionItem] = useMutation(CREATE_ACTION_ITEM_MUTATION); + + const createActionItemHandler = async ( + e: ChangeEvent, + ): Promise => { + e.preventDefault(); + try { + await createActionItem({ + variables: { + assigneeId: formState.assigneeId, + actionItemCategoryId: formState.actionItemCategoryId, + preCompletionNotes: formState.preCompletionNotes, + dueDate: dayjs(dueDate).format('YYYY-MM-DD'), + }, + }); + + setFormState({ + assigneeId: '', + actionItemCategoryId: '', + preCompletionNotes: '', + }); + + setDueDate(new Date()); + + actionItemsRefetch(); + hideCreateModal(); + toast.success(t('successfulCreation')); + } catch (error: unknown) { + if (error instanceof Error) { + toast.error(error.message); + console.log(error.message); + } + } + }; + + const showCreateModal = (): void => { + setActionItemCreateModalIsOpen(!actionItemCreateModalIsOpen); + }; + + const hideCreateModal = (): void => { + setActionItemCreateModalIsOpen(!actionItemCreateModalIsOpen); + }; + + const handleSorting = (sort: string): void => { + if (sort === 'Latest') { + setOrderBy('Latest'); + } else { + setOrderBy('Earliest'); + } + }; + + const handleStatusFilter = (status: string): void => { + if (status === 'Active') { + setActionItemStatus('Active'); + } else { + setActionItemStatus('Completed'); + } + }; + + const handleClearFilters = (): void => { + setActionItemCategoryId(''); + setActionItemCategoryName(''); + setActionItemStatus(''); + setOrderBy('Latest'); + }; + + if (actionItemCategoriesLoading || membersLoading || actionItemsLoading) { + return ; + } + + if (actionItemCategoriesError || membersError || actionItemsError) { + return ( +
    +
    + +
    + Error occured while loading{' '} + {actionItemCategoriesError + ? 'Action Item Categories' + : membersError + ? 'Members List' + : 'Action Items List'}{' '} + Data +
    + {actionItemCategoriesError + ? actionItemCategoriesError.message + : membersError + ? membersError.message + : actionItemsError?.message} +
    +
    +
    + ); + } + + const actionItemCategories = + actionItemCategoriesData?.actionItemCategoriesByOrganization.filter( + (category) => !category.isDisabled, + ); + + return ( +
    +
    +
    +
    +
    + + + + + +
    + +
    + {!actionItemCategoryName && !actionItemStatus && ( +
    + No Filters +
    + )} + + {actionItemCategoryName !== '' && ( +
    + {actionItemCategoryName} + { + setActionItemCategoryName(''); + setActionItemCategoryId(''); + }} + data-testid="clearActionItemCategoryFilter" + /> +
    + )} + + {actionItemStatus !== '' && ( +
    + {actionItemStatus} + setActionItemStatus('')} + data-testid="clearActionItemStatusFilter" + /> +
    + )} +
    + + + +
    +
    + +
    + + +
    + + {/* Create Modal */} + +
    + ); +} + +export default organizationActionItems; diff --git a/src/screens/OrganizationActionItems/OrganizationActionItemsErrorMocks.ts b/src/screens/OrganizationActionItems/OrganizationActionItemsErrorMocks.ts new file mode 100644 index 0000000000..bedba6572b --- /dev/null +++ b/src/screens/OrganizationActionItems/OrganizationActionItemsErrorMocks.ts @@ -0,0 +1,266 @@ +import { CREATE_ACTION_ITEM_MUTATION } from 'GraphQl/Mutations/mutations'; + +import { + ACTION_ITEM_CATEGORY_LIST, + ACTION_ITEM_LIST, + MEMBERS_LIST, +} from 'GraphQl/Queries/Queries'; + +export const MOCKS_ERROR_ACTION_ITEM_CATEGORY_LIST_QUERY = [ + { + request: { + query: ACTION_ITEM_CATEGORY_LIST, + variables: { organizationId: '123' }, + }, + error: new Error('Mock Graphql Error'), + }, +]; + +export const MOCKS_ERROR_MEMBERS_LIST_QUERY = [ + { + request: { + query: ACTION_ITEM_CATEGORY_LIST, + variables: { organizationId: '123' }, + }, + result: { + data: { + actionItemCategoriesByOrganization: [ + { + _id: 'actionItemCategory1', + name: 'ActionItemCategory 1', + isDisabled: false, + }, + ], + }, + }, + }, + { + request: { + query: MEMBERS_LIST, + variables: { id: '123' }, + }, + error: new Error('Mock Graphql Error'), + }, +]; + +export const MOCKS_ERROR_ACTION_ITEM_LIST_QUERY = [ + { + request: { + query: ACTION_ITEM_CATEGORY_LIST, + variables: { organizationId: '123' }, + }, + result: { + data: { + actionItemCategoriesByOrganization: [ + { + _id: 'actionItemCategory1', + name: 'ActionItemCategory 1', + isDisabled: false, + }, + ], + }, + }, + }, + { + request: { + query: MEMBERS_LIST, + variables: { id: '123' }, + }, + result: { + data: { + organizations: [ + { + _id: '123', + members: [ + { + _id: 'user1', + firstName: 'Harve', + lastName: 'Lance', + email: 'harve@example.com', + image: '', + organizationsBlockedBy: [], + createdAt: '2024-02-14', + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: ACTION_ITEM_LIST, + variables: { id: '123' }, + }, + error: new Error('Mock Graphql Error'), + }, +]; + +export const MOCKS_ERROR_MUTATIONS = [ + { + request: { + query: ACTION_ITEM_CATEGORY_LIST, + variables: { organizationId: '123' }, + }, + result: { + data: { + actionItemCategoriesByOrganization: [ + { + _id: 'actionItemCategory1', + name: 'ActionItemCategory 1', + isDisabled: false, + }, + ], + }, + }, + }, + { + request: { + query: MEMBERS_LIST, + variables: { id: '123' }, + }, + result: { + data: { + organizations: [ + { + _id: '123', + members: [ + { + _id: 'user1', + firstName: 'Harve', + lastName: 'Lance', + email: 'harve@example.com', + image: '', + organizationsBlockedBy: [], + createdAt: '2024-02-14', + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: ACTION_ITEM_LIST, + variables: { + organizationId: '123', + orderBy: 'createdAt_DESC', + actionItemCategoryId: '', + isActive: false, + isCompleted: false, + }, + }, + result: { + data: { + actionItemsByOrganization: [ + { + _id: 'actionItem1', + assignee: { + _id: 'user1', + firstName: 'Harve', + lastName: 'Lance', + }, + actionItemCategory: { + _id: 'actionItemCategory1', + name: 'ActionItemCategory 1', + }, + preCompletionNotes: 'Pre Completion Notes', + postCompletionNotes: 'Post Completion Notes', + assignmentDate: '2024-02-14', + dueDate: '2024-02-21', + completionDate: '2024-02-21', + isCompleted: false, + assigner: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + event: { + _id: 'event1', + title: 'event 1', + }, + creator: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + ], + }, + }, + }, + { + request: { + query: ACTION_ITEM_LIST, + variables: { + organizationId: '123', + eventId: 'event1', + orderBy: 'createdAt_DESC', + }, + }, + result: { + data: { + actionItemsByOrganization: [ + { + _id: 'actionItem1', + assignee: { + _id: 'user1', + firstName: 'Harve', + lastName: 'Lance', + }, + actionItemCategory: { + _id: 'actionItemCategory1', + name: 'ActionItemCategory 1', + }, + preCompletionNotes: 'Pre Completion Notes', + postCompletionNotes: 'Post Completion Notes', + assignmentDate: '2024-02-14', + dueDate: '2024-02-21', + completionDate: '2024-02-21', + isCompleted: false, + assigner: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + event: { + _id: 'event1', + title: 'event 1', + }, + creator: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + ], + }, + }, + }, + { + request: { + query: CREATE_ACTION_ITEM_MUTATION, + variables: { + actionItemCategoryId: 'actionItemCategory1', + assigneeId: 'user1', + preCompletionNotes: 'pre completion notes', + dueDate: '2024-02-14', + }, + }, + error: new Error('Mock Graphql Error'), + }, + { + request: { + query: CREATE_ACTION_ITEM_MUTATION, + variables: { + eventId: 'event1', + actionItemCategoryId: 'actionItemCategory1', + assigneeId: 'user1', + preCompletionNotes: 'pre completion notes', + dueDate: '2024-02-14', + }, + }, + error: new Error('Mock Graphql Error'), + }, +]; diff --git a/src/screens/OrganizationDashboard/OrganizationDashboard.module.css b/src/screens/OrganizationDashboard/OrganizationDashboard.module.css index 485200b1ae..f9423de686 100644 --- a/src/screens/OrganizationDashboard/OrganizationDashboard.module.css +++ b/src/screens/OrganizationDashboard/OrganizationDashboard.module.css @@ -4,6 +4,7 @@ display: flex; justify-content: space-between; align-items: center; + margin-bottom: 10px; } .cardHeader .cardTitle { @@ -14,6 +15,10 @@ .cardBody { min-height: 180px; padding-top: 0; + max-height: 570px; + overflow-y: scroll; + width: 100%; + max-width: 400px; } .cardBody .emptyContainer { diff --git a/src/screens/OrganizationDashboard/OrganizationDashboard.test.tsx b/src/screens/OrganizationDashboard/OrganizationDashboard.test.tsx index cb221f94ce..e377826a73 100644 --- a/src/screens/OrganizationDashboard/OrganizationDashboard.test.tsx +++ b/src/screens/OrganizationDashboard/OrganizationDashboard.test.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import { MockedProvider } from '@apollo/react-testing'; import { act, fireEvent, render, screen } from '@testing-library/react'; import 'jest-location-mock'; @@ -6,13 +5,17 @@ import { I18nextProvider } from 'react-i18next'; import { Provider } from 'react-redux'; import { BrowserRouter } from 'react-router-dom'; +import userEvent from '@testing-library/user-event'; +import { toast } from 'react-toastify'; import { store } from 'state/store'; import { StaticMockLink } from 'utils/StaticMockLink'; +import i18nForTest from 'utils/i18nForTest'; +import useLocalStorage from 'utils/useLocalstorage'; import OrganizationDashboard from './OrganizationDashboard'; import { EMPTY_MOCKS, ERROR_MOCKS, MOCKS } from './OrganizationDashboardMocks'; -import i18nForTest from 'utils/i18nForTest'; -import { toast } from 'react-toastify'; -import userEvent from '@testing-library/user-event'; +import React from 'react'; +const { setItem } = useLocalStorage(); +import type { InterfaceQueryOrganizationEventListItem } from 'utils/interfaces'; async function wait(ms = 100): Promise { await act(() => { @@ -32,14 +35,20 @@ jest.mock('react-toastify', () => ({ error: jest.fn(), }, })); +const mockNavgate = jest.fn(); +let mockId: string | undefined = undefined; +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useNavigate: () => mockNavgate, + useParams: () => ({ orgId: mockId }), +})); beforeEach(() => { - localStorage.setItem('FirstName', 'John'); - localStorage.setItem('LastName', 'Doe'); - localStorage.setItem('UserType', 'SUPERADMIN'); - localStorage.setItem( + setItem('FirstName', 'John'); + setItem('LastName', 'Doe'); + setItem( 'UserImage', - 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe' + 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', ); }); @@ -60,15 +69,15 @@ describe('Organisation Dashboard Page', () => { - + , ); }); await wait(); expect(screen.getByText('Members')).toBeInTheDocument(); expect(screen.getByText('Admins')).toBeInTheDocument(); - expect(screen.getAllByText('Posts')).toHaveLength(2); - expect(screen.getAllByText('Events')).toHaveLength(2); + expect(screen.getAllByText('Posts')).toHaveLength(1); + expect(screen.getAllByText('Events')).toHaveLength(1); expect(screen.getByText('Blocked Users')).toBeInTheDocument(); expect(screen.getByText('Requests')).toBeInTheDocument(); expect(screen.getByText('Upcoming Events')).toBeInTheDocument(); @@ -76,7 +85,7 @@ describe('Organisation Dashboard Page', () => { expect(screen.getByText('Membership requests')).toBeInTheDocument(); // Checking if posts are rendered - expect(screen.getByText('Post 15')).toBeInTheDocument(); + expect(screen.getByText('postone')).toBeInTheDocument(); // Checking if membership requests are rendered expect(screen.getByText('Jane Doe')).toBeInTheDocument(); @@ -91,8 +100,8 @@ describe('Organisation Dashboard Page', () => { userEvent.click(adminBtn); userEvent.click(postBtn[0]); userEvent.click(eventBtn[0]); - userEvent.click(postBtn[1]); - userEvent.click(eventBtn[1]); + userEvent.click(postBtn[0]); + userEvent.click(eventBtn[0]); userEvent.click(blockUserBtn); userEvent.click(requestBtn); }); @@ -108,7 +117,7 @@ describe('Organisation Dashboard Page', () => { - + , ); }); @@ -123,10 +132,10 @@ describe('Organisation Dashboard Page', () => { expect(toast.success).toBeCalledWith('Coming soon!'); expect( - screen.getByText(/No membership requests present/i) + screen.getByText(/No membership requests present/i), ).toBeInTheDocument(); expect(screen.getByText(/No upcoming events/i)).toBeInTheDocument(); - expect(screen.getByText(/No posts present/i)).toBeInTheDocument(); + expect(screen.getByText(/No Posts Present/i)).toBeInTheDocument(); }); test('Testing error scenario', async () => { @@ -140,11 +149,54 @@ describe('Organisation Dashboard Page', () => { - + , ); }); await wait(); - expect(window.location).toBeAt('/orglist'); + expect(mockNavgate).toHaveBeenCalledWith('/orglist'); + }); + test('upcomingEvents cardItem component should render when length>0', async () => { + mockId = '123'; + await act(async () => { + render( + + + + + + + + + , + ); + }); + screen.getByTestId('cardItem'); + }); + + test('event data should get updated using useState function', async () => { + mockId = '123'; + const mockSetState = jest.spyOn(React, 'useState'); + jest.doMock('react', () => ({ + ...jest.requireActual('react'), + useState: (initial: InterfaceQueryOrganizationEventListItem[]) => [ + initial, + mockSetState, + ], + })); + await act(async () => { + render( + + + + + + + + + , + ); + }); + expect(mockSetState).toHaveBeenCalled(); }); }); diff --git a/src/screens/OrganizationDashboard/OrganizationDashboard.tsx b/src/screens/OrganizationDashboard/OrganizationDashboard.tsx index 60e31396a5..429ad81a84 100644 --- a/src/screens/OrganizationDashboard/OrganizationDashboard.tsx +++ b/src/screens/OrganizationDashboard/OrganizationDashboard.tsx @@ -1,45 +1,45 @@ -import React, { useEffect, useState } from 'react'; import { useQuery } from '@apollo/client'; +import React, { useEffect, useState } from 'react'; import { Button, Card } from 'react-bootstrap'; import Col from 'react-bootstrap/Col'; import Row from 'react-bootstrap/Row'; import { useTranslation } from 'react-i18next'; +import type { ApolloError } from '@apollo/client'; import { ORGANIZATIONS_LIST, - ORGANIZATION_POST_CONNECTION_LIST, ORGANIZATION_EVENT_CONNECTION_LIST, + ORGANIZATION_POST_LIST, } from 'GraphQl/Queries/Queries'; import { ReactComponent as AdminsIcon } from 'assets/svgs/admin.svg'; import { ReactComponent as BlockedUsersIcon } from 'assets/svgs/blockedUser.svg'; import { ReactComponent as EventsIcon } from 'assets/svgs/events.svg'; import { ReactComponent as PostsIcon } from 'assets/svgs/post.svg'; import { ReactComponent as UsersIcon } from 'assets/svgs/users.svg'; -import DashBoardCard from 'components/OrganizationDashCards/DashboardCard'; -import OrganizationScreen from 'components/OrganizationScreen/OrganizationScreen'; -import styles from './OrganizationDashboard.module.css'; import CardItem from 'components/OrganizationDashCards/CardItem'; -import type { ApolloError } from '@apollo/client'; +import CardItemLoading from 'components/OrganizationDashCards/CardItemLoading'; +import DashBoardCard from 'components/OrganizationDashCards/DashboardCard'; +import DashboardCardLoading from 'components/OrganizationDashCards/DashboardCardLoading'; +import { useNavigate, useParams } from 'react-router-dom'; +import { toast } from 'react-toastify'; import type { InterfaceQueryOrganizationEventListItem, + InterfaceQueryOrganizationPostListItem, InterfaceQueryOrganizationsListObject, } from 'utils/interfaces'; -import { toast } from 'react-toastify'; -import { useHistory } from 'react-router-dom'; -import CardItemLoading from 'components/OrganizationDashCards/CardItemLoading'; -import DashboardCardLoading from 'components/OrganizationDashCards/DashboardCardLoading'; +import styles from './OrganizationDashboard.module.css'; function organizationDashboard(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'dashboard' }); document.title = t('title'); - const currentUrl = window.location.href.split('=')[1]; - const peopleLink = `/orgpeople/id=${currentUrl}`; - const postsLink = `/orgpost/id=${currentUrl}`; - const eventsLink = `/orgevents/id=${currentUrl}`; - const blockUserLink = `/blockuser/id=${currentUrl}`; + const { orgId: currentUrl } = useParams(); + const peopleLink = `/orgpeople/${currentUrl}`; + const postsLink = `/orgpost/${currentUrl}`; + const eventsLink = `/orgevents/${currentUrl}`; + const blockUserLink = `/blockuser/${currentUrl}`; const requestLink = '/requests'; - const history = useHistory(); + const navigate = useNavigate(); const [upcomingEvents, setUpcomingEvents] = useState< InterfaceQueryOrganizationEventListItem[] >([]); @@ -62,8 +62,14 @@ function organizationDashboard(): JSX.Element { data: postData, loading: loadingPost, error: errorPost, - } = useQuery(ORGANIZATION_POST_CONNECTION_LIST, { - variables: { id: currentUrl }, + }: { + data?: { + organizations: InterfaceQueryOrganizationPostListItem[]; + }; + loading: boolean; + error?: ApolloError; + } = useQuery(ORGANIZATION_POST_LIST, { + variables: { id: currentUrl, first: 10 }, }); const { @@ -95,253 +101,250 @@ function organizationDashboard(): JSX.Element { } }, [eventData?.eventsByOrganizationConnection]); - if (errorOrg || errorPost || errorEvent) { - window.location.replace('/orglist'); - } + useEffect(() => { + if (errorOrg || errorPost || errorEvent) { + console.log('error', errorPost?.message); + navigate('/orglist'); + } + }, [errorOrg, errorPost, errorEvent]); return ( <> - - - - {loadingOrgData ? ( - - {[...Array(6)].map((_, index) => { - return ( - - - - ); - })} - - ) : ( - - { - history.push(peopleLink); - }} - > - } - /> - - { - history.push(peopleLink); - }} - > - } - /> - - { - history.push(postsLink); - }} - > - } - /> - - { - history.push(eventsLink); - }} - > - } - /> - - { - history.push(blockUserLink); - }} - > - } - /> - - { - history.push(requestLink); - }} - > - } - /> - - - )} - - - -
    -
    - {t('upcomingEvents')} -
    - -
    - - {loadingEvent ? ( - [...Array(4)].map((_, index) => { - return ; - }) - ) : upcomingEvents.length == 0 ? ( -
    -
    {t('noUpcomingEvents')}
    -
    - ) : ( - upcomingEvents.map( - (event: InterfaceQueryOrganizationEventListItem) => { - return ( - - ); - } - ) - )} -
    -
    + + + {loadingOrgData ? ( + + {[...Array(6)].map((_, index) => { + return ( + + + + ); + })} + + ) : ( + + { + navigate(peopleLink); + }} + > + } + /> - - -
    -
    {t('latestPosts')}
    - -
    - - {loadingPost ? ( - [...Array(4)].map((_, index) => { - return ; - }) - ) : postData?.postsByOrganizationConnection.edges.length == - 0 ? ( - /* eslint-disable */ -
    -
    {t('noPostsPresent')}
    -
    - ) : ( - /* eslint-enable */ - postData?.postsByOrganizationConnection.edges - .slice(0, 5) - .map((post: any) => { - return ( - - ); - }) - )} -
    -
    + { + navigate(peopleLink); + }} + > + } + /> + + { + navigate(postsLink); + }} + > + } + /> + + { + navigate(eventsLink); + }} + > + } + /> + + { + navigate(blockUserLink); + }} + > + } + /> + + { + navigate(requestLink); + }} + > + } + />
    - - - -
    -
    - {t('membershipRequests')} + )} + + + +
    +
    {t('upcomingEvents')}
    +
    - -
    - - {loadingOrgData ? ( - [...Array(4)].map((_, index) => { - return ; - }) - ) : data?.organizations[0].membershipRequests.length == 0 ? ( -
    -
    {t('noMembershipRequests')}
    -
    - ) : ( - data?.organizations[0]?.membershipRequests - .slice(0, 8) - .map((request) => { - return ( - - ); + + {loadingEvent ? ( + [...Array(4)].map((_, index) => { + return ; + }) + ) : upcomingEvents.length == 0 ? ( +
    +
    {t('noUpcomingEvents')}
    +
    + ) : ( + upcomingEvents.map( + (event: InterfaceQueryOrganizationEventListItem) => { + return ( + + ); + }, + ) + )} +
    + + + + +
    +
    {t('latestPosts')}
    + +
    + + {loadingPost ? ( + [...Array(4)].map((_, index) => { + return ; }) - )} - -
    - - - + ) : postData?.organizations[0].posts.totalCount == 0 ? ( + /* eslint-disable */ +
    +
    {t('noPostsPresent')}
    +
    + ) : ( + /* eslint-enable */ + postData?.organizations[0].posts.edges + .slice(0, 5) + .map((edge: any) => { + const post = edge.node; + return ( + + ); + }) + )} +
    + + + + + + +
    +
    {t('membershipRequests')}
    + +
    + + {loadingOrgData ? ( + [...Array(4)].map((_, index) => { + return ; + }) + ) : data?.organizations[0].membershipRequests.length == 0 ? ( +
    +
    {t('noMembershipRequests')}
    +
    + ) : ( + data?.organizations[0]?.membershipRequests + .slice(0, 8) + .map((request) => { + return ( + + ); + }) + )} +
    +
    + + ); } diff --git a/src/screens/OrganizationDashboard/OrganizationDashboardMocks.ts b/src/screens/OrganizationDashboard/OrganizationDashboardMocks.ts index dc1f158709..26e5441f92 100644 --- a/src/screens/OrganizationDashboard/OrganizationDashboardMocks.ts +++ b/src/screens/OrganizationDashboard/OrganizationDashboardMocks.ts @@ -1,9 +1,8 @@ import { ORGANIZATIONS_LIST, ORGANIZATION_EVENT_CONNECTION_LIST, - ORGANIZATION_POST_CONNECTION_LIST, + ORGANIZATION_POST_LIST, } from 'GraphQl/Queries/Queries'; -import dayjs from 'dayjs'; export const MOCKS = [ { @@ -18,8 +17,17 @@ export const MOCKS = [ image: '', name: 'Dummy Organization', description: 'This is a Dummy Organization', - location: 'New Delhi', - isPublic: true, + address: { + city: 'Delhi', + countryCode: 'IN', + dependentLocality: 'Some Dependent Locality', + line1: '123 Random Street', + line2: 'Apartment 456', + postalCode: '110001', + sortingCode: 'ABC-123', + state: 'Delhi', + }, + userRegistrationRequired: true, visibleInSearch: false, creator: { firstName: '', @@ -40,6 +48,7 @@ export const MOCKS = [ firstName: 'John', lastName: 'Doe', email: 'johndoe@gmail.com', + createdAt: '12-03-2024', }, ], membershipRequests: [ @@ -67,91 +76,114 @@ export const MOCKS = [ }, { request: { - query: ORGANIZATION_POST_CONNECTION_LIST, + query: ORGANIZATION_POST_LIST, + variables: { first: 10 }, }, result: { data: { - postsByOrganizationConnection: { - edges: [ - { - _id: '6411e53835d7ba2344a78e21', - title: 'Post 15', - text: 'This is the first post that was made', - imageUrl: null, - videoUrl: null, - creator: { - _id: '640d98d9eb6a743d75341067', - firstName: 'Aditya', - lastName: 'Shelke', - email: 'adidacreator1@gmail.com', - }, - createdAt: dayjs(new Date()).add(1, 'day'), - likeCount: 0, - commentCount: 0, - comments: [], - likedBy: [], - pinned: false, - }, - { - _id: '6411e54835d7ba2344a78e29', - title: 'Post 2', - text: 'Hey, anyone saw my watch that I left at the office?', - imageUrl: null, - videoUrl: null, - creator: { - _id: '640d98d9eb6a743d75341067', - firstName: 'Aditya', - lastName: 'Shelke', - email: 'adidacreator1@gmail.com', - }, - pinned: false, - createdAt: dayjs(new Date()).add(1, 'day'), - likeCount: 0, - commentCount: 2, - comments: [ + organizations: [ + { + posts: { + edges: [ { - _id: '64eb13beca85de60ebe0ed0e', - creator: { - _id: '63d6064458fce20ee25c3bf7', - firstName: 'Noble', - lastName: 'Mittal', - email: 'test@gmail.com', - __typename: 'User', + node: { + _id: '6411e53835d7ba2344a78e21', + title: 'postone', + text: 'This is the first post', + imageUrl: null, + videoUrl: null, + createdAt: '2023-08-24T09:26:56.524+00:00', + creator: { + _id: '640d98d9eb6a743d75341067', + firstName: 'Aditya', + lastName: 'Shelke', + email: 'adidacreator1@gmail.com', + }, + likeCount: 0, + commentCount: 0, + comments: [], + pinned: true, + likedBy: [], }, - likeCount: 1, - likedBy: [ - { - _id: 1, + cursor: '6411e53835d7ba2344a78e21', + }, + { + node: { + _id: '6411e54835d7ba2344a78e29', + title: 'posttwo', + text: 'Tis is the post two', + imageUrl: null, + videoUrl: null, + createdAt: '2023-08-24T09:26:56.524+00:00', + creator: { + _id: '640d98d9eb6a743d75341067', + firstName: 'Aditya', + lastName: 'Shelke', + email: 'adidacreator1@gmail.com', }, - ], - text: 'Yes, that is $50', - __typename: 'Comment', + likeCount: 0, + commentCount: 0, + pinned: false, + likedBy: [], + comments: [], + }, + cursor: '6411e54835d7ba2344a78e29', }, { - _id: '64eb483aca85de60ebe0ef99', - creator: { - _id: '63d6064458fce20ee25c3bf7', - firstName: 'Noble', - lastName: 'Mittal', - email: 'test@gmail.com', - __typename: 'User', + node: { + _id: '6411e54835d7ba2344a78e30', + title: 'posttwo', + text: 'Tis is the post two', + imageUrl: null, + videoUrl: null, + createdAt: '2023-08-24T09:26:56.524+00:00', + creator: { + _id: '640d98d9eb6a743d75341067', + firstName: 'Aditya', + lastName: 'Shelke', + email: 'adidacreator1@gmail.com', + }, + likeCount: 0, + commentCount: 0, + pinned: true, + likedBy: [], + comments: [], }, - likeCount: 0, - likedBy: [], - text: 'Great View', - __typename: 'Comment', + cursor: '6411e54835d7ba2344a78e30', }, - ], - likedBy: [ { - _id: '63d6064458fce20ee25c3bf7', - firstName: 'Comment', - lastName: 'Likkert', + node: { + _id: '6411e54835d7ba2344a78e31', + title: 'posttwo', + text: 'Tis is the post two', + imageUrl: null, + videoUrl: null, + createdAt: '2023-08-24T09:26:56.524+00:00', + creator: { + _id: '640d98d9eb6a743d75341067', + firstName: 'Aditya', + lastName: 'Shelke', + email: 'adidacreator1@gmail.com', + }, + likeCount: 0, + commentCount: 0, + pinned: false, + likedBy: [], + comments: [], + }, + cursor: '6411e54835d7ba2344a78e31', }, ], + pageInfo: { + startCursor: '6411e53835d7ba2344a78e21', + endCursor: '6411e54835d7ba2344a78e31', + hasNextPage: false, + hasPreviousPage: false, + }, + totalCount: 4, }, - ], - }, + }, + ], }, }, }, @@ -169,13 +201,31 @@ export const MOCKS = [ _id: '1', title: 'Sample Event', description: 'Sample Description', - startDate: '2023-10-29T00:00:00.000Z', + startDate: '2025-10-29T00:00:00.000Z', + endDate: '2023-10-29T23:59:59.000Z', + location: 'Sample Location', + startTime: '08:00:00', + endTime: '17:00:00', + allDay: false, + recurring: false, + recurrenceRule: null, + isRecurringEventException: false, + isPublic: true, + isRegisterable: true, + }, + { + _id: '2', + title: 'Sample Event', + description: 'Sample Description', + startDate: '2022-10-29T00:00:00.000Z', endDate: '2023-10-29T23:59:59.000Z', location: 'Sample Location', startTime: '08:00:00', endTime: '17:00:00', allDay: false, recurring: false, + recurrenceRule: null, + isRecurringEventException: false, isPublic: true, isRegisterable: true, }, @@ -198,8 +248,17 @@ export const EMPTY_MOCKS = [ image: '', name: 'Dummy Organization', description: 'This is a Dummy Organization', - location: 'New Delhi', - isPublic: true, + address: { + city: 'Delhi', + countryCode: 'IN', + dependentLocality: 'Some Dependent Locality', + line1: '123 Random Street', + line2: 'Apartment 456', + postalCode: '110001', + sortingCode: 'ABC-123', + state: 'Delhi', + }, + userRegistrationRequired: true, visibleInSearch: false, creator: { firstName: 'John', @@ -220,6 +279,7 @@ export const EMPTY_MOCKS = [ firstName: 'John', lastName: 'Doe', email: 'johndoe@gmail.com', + createdAt: '12-03-2024', }, ], membershipRequests: [], @@ -238,13 +298,25 @@ export const EMPTY_MOCKS = [ }, { request: { - query: ORGANIZATION_POST_CONNECTION_LIST, + query: ORGANIZATION_POST_LIST, + variables: { first: 10 }, }, result: { data: { - postsByOrganizationConnection: { - edges: [], - }, + organizations: [ + { + posts: { + edges: [], + pageInfo: { + startCursor: '', + endCursor: '', + hasNextPage: false, + hasPreviousPage: false, + }, + totalCount: 0, + }, + }, + ], }, }, }, @@ -269,7 +341,7 @@ export const ERROR_MOCKS = [ }, { request: { - query: ORGANIZATION_POST_CONNECTION_LIST, + query: ORGANIZATION_POST_LIST, }, error: new Error('Mock Graphql ORGANIZATION_POST_LIST Error'), }, diff --git a/src/screens/OrganizationEvents/OrganizationEvents.module.css b/src/screens/OrganizationEvents/OrganizationEvents.module.css index 05a70c3fa3..55e86fcaba 100644 --- a/src/screens/OrganizationEvents/OrganizationEvents.module.css +++ b/src/screens/OrganizationEvents/OrganizationEvents.module.css @@ -36,14 +36,8 @@ display: flex; flex-direction: row; } -.sidebar { - z-index: 0; - padding-top: 5px; - margin: 0; - height: 100%; -} + .sidebar:after { - content: ''; background-color: #f7f7f7; position: absolute; width: 2px; @@ -52,12 +46,6 @@ left: 94%; display: block; } -.sidebarsticky { - padding-left: 45px; -} -.sidebarsticky > p { - margin-top: -10px; -} .navitem { padding-left: 27%; @@ -75,15 +63,7 @@ border-bottom: 3px solid #31bb6b; width: 15%; } -.searchtitle { - color: #707070; - font-weight: 600; - font-size: 18px; - margin-bottom: 20px; - padding-bottom: 5px; - border-bottom: 3px solid #31bb6b; - width: 60%; -} + .logintitleadmin { color: #707070; font-weight: 600; @@ -110,22 +90,13 @@ margin-right: -15px; margin-bottom: 20px; } + .justifysp { - display: flex; + display: block; justify-content: space-between; + margin-top: 20px; } -@media screen and (max-width: 575.5px) { - .justifysp { - padding-left: 55px; - display: flex; - justify-content: space-between; - width: 100%; - } - .mainpageright { - width: 90%; - } -} .addbtn { border: 1px solid #e8e5e5; box-shadow: 0 2px 2px #e8e5e5; @@ -136,7 +107,9 @@ outline: none; font-weight: 600; cursor: pointer; - transition: transform 0.2s, box-shadow 0.2s; + transition: + transform 0.2s, + box-shadow 0.2s; } .flexdir { display: flex; @@ -209,21 +182,12 @@ outline: none; font-weight: 600; cursor: pointer; - transition: transform 0.2s, box-shadow 0.2s; + transition: + transform 0.2s, + box-shadow 0.2s; width: 100%; } -.sidebarsticky > input { - text-decoration: none; - margin-bottom: 50px; - border-color: #e8e5e5; - width: 80%; - border-radius: 7px; - padding-top: 5px; - padding-bottom: 5px; - padding-right: 10px; - padding-left: 10px; - box-shadow: none; -} + .datediv { display: flex; flex-direction: row; @@ -239,6 +203,8 @@ padding-bottom: 2px; padding-right: 5px; padding-left: 5px; + margin-right: 5px; + margin-left: 5px; } .checkboxdiv > label { margin-right: 50px; @@ -291,6 +257,7 @@ .dispflex { display: flex; align-items: center; + justify-content: space-between; } .dispflex > input { border: none; @@ -299,11 +266,62 @@ } .checkboxdiv { display: flex; + margin-bottom: 5px; } .checkboxdiv > div { width: 50%; } +.recurrenceRuleNumberInput { + width: 70px; +} + +.recurrenceRuleDateBox { + width: 70%; +} + +.recurrenceDayButton { + width: 33px; + height: 33px; + border: 1px solid var(--bs-gray); + cursor: pointer; + transition: background-color 0.3s; + display: inline-flex; + justify-content: center; + align-items: center; + margin-right: 0.5rem; + border-radius: 50%; +} + +.recurrenceDayButton:hover { + background-color: var(--bs-gray); +} + +.recurrenceDayButton.selected { + background-color: var(--bs-primary); + border-color: var(--bs-primary); + color: var(--bs-white); +} + +.recurrenceDayButton span { + color: var(--bs-gray); + padding: 0.25rem; + text-align: center; +} + +.recurrenceDayButton:hover span { + color: var(--bs-white); +} + +.recurrenceDayButton.selected span { + color: var(--bs-white); +} + +.recurrenceRuleSubmitBtn { + margin-left: 82%; + padding: 7px 15px; +} + @media only screen and (max-width: 600px) { .form_wrapper { width: 90%; diff --git a/src/screens/OrganizationEvents/OrganizationEvents.test.tsx b/src/screens/OrganizationEvents/OrganizationEvents.test.tsx index 9f79991274..0f498a4741 100644 --- a/src/screens/OrganizationEvents/OrganizationEvents.test.tsx +++ b/src/screens/OrganizationEvents/OrganizationEvents.test.tsx @@ -1,107 +1,37 @@ import React from 'react'; import { MockedProvider } from '@apollo/react-testing'; -import { act, render, screen, fireEvent } from '@testing-library/react'; +import { + act, + render, + screen, + fireEvent, + waitFor, +} from '@testing-library/react'; import { Provider } from 'react-redux'; import { BrowserRouter } from 'react-router-dom'; import 'jest-location-mock'; import { I18nextProvider } from 'react-i18next'; import OrganizationEvents from './OrganizationEvents'; -import { ORGANIZATION_EVENT_CONNECTION_LIST } from 'GraphQl/Queries/Queries'; import { store } from 'state/store'; -import { CREATE_EVENT_MUTATION } from 'GraphQl/Mutations/mutations'; import i18nForTest from 'utils/i18nForTest'; import userEvent from '@testing-library/user-event'; import { StaticMockLink } from 'utils/StaticMockLink'; import { toast } from 'react-toastify'; - -const MOCKS = [ - { - request: { - query: ORGANIZATION_EVENT_CONNECTION_LIST, - variables: { - organization_id: undefined, - title_contains: '', - description_contains: '', - location_contains: '', - }, - }, - result: { - data: { - eventsByOrganizationConnection: [ - { - _id: 1, - title: 'Event', - description: 'Event Test', - startDate: '', - endDate: '', - location: 'New Delhi', - startTime: '02:00', - endTime: '06:00', - allDay: false, - recurring: false, - isPublic: true, - isRegisterable: true, - }, - ], - }, - }, - }, - { - request: { - query: ORGANIZATION_EVENT_CONNECTION_LIST, - variables: { - title_contains: '', - description_contains: '', - organization_id: undefined, - location_contains: '', - }, - }, - result: { - data: { - eventsByOrganizationConnection: [ - { - _id: '1', - title: 'Dummy Org', - description: 'This is a dummy organization', - location: 'string', - startDate: '', - endDate: '', - startTime: '02:00', - endTime: '06:00', - allDay: false, - recurring: false, - isPublic: true, - isRegisterable: true, - }, - ], - }, - }, - }, - { - request: { - query: CREATE_EVENT_MUTATION, - variables: { - title: 'Dummy Org', - description: 'This is a dummy organization', - isPublic: false, - recurring: true, - isRegisterable: true, - organizationId: undefined, - startDate: 'Thu Mar 28 20222', - endDate: 'Fri Mar 28 20223', - allDay: true, - }, - }, - result: { - data: { - createEvent: { - _id: '1', - }, - }, +import { createTheme } from '@mui/material'; +import { ThemeProvider } from 'react-bootstrap'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { MOCKS } from './OrganizationEventsMocks'; + +const theme = createTheme({ + palette: { + primary: { + main: '#31bb6b', }, }, -]; +}); + const link = new StaticMockLink(MOCKS, true); const link2 = new StaticMockLink([], true); @@ -113,6 +43,20 @@ async function wait(ms = 100): Promise { }); } +const translations = JSON.parse( + JSON.stringify( + i18nForTest.getDataByLanguage('en')?.translation.organizationEvents, + ), +); + +jest.mock('@mui/x-date-pickers/DateTimePicker', () => { + return { + DateTimePicker: jest.requireActual( + '@mui/x-date-pickers/DesktopDateTimePicker', + ).DesktopDateTimePicker, + }; +}); + jest.mock('react-toastify', () => ({ toast: { success: jest.fn(), @@ -126,10 +70,10 @@ describe('Organisation Events Page', () => { title: 'Dummy Org', description: 'This is a dummy organization', startDate: '03/28/2022', - endDate: '04/15/2023', + endDate: '03/30/2022', location: 'New Delhi', - startTime: '02:00', - endTime: '06:00', + startTime: '09:00 AM', + endTime: '05:00 PM', }; global.alert = jest.fn(); @@ -149,6 +93,8 @@ describe('Organisation Events Page', () => { endTime: '06:00', allDay: false, recurring: false, + recurrenceRule: null, + isRecurringEventException: false, isPublic: true, isRegisterable: true, }, @@ -169,6 +115,8 @@ describe('Organisation Events Page', () => { endTime: '06:00', allDay: false, recurring: false, + recurrenceRule: null, + isRecurringEventException: false, isPublic: true, isRegisterable: true, }, @@ -181,19 +129,21 @@ describe('Organisation Events Page', () => { - - - + + + + + + + - + , ); expect(container.textContent).not.toBe('Loading data...'); await wait(); - expect(container.textContent).toMatch('Events'); - expect(container.textContent).toMatch('Search Date'); - expect(container.textContent).toMatch('Events'); + expect(container.textContent).toMatch('Month'); expect(window.location).toBeAt('/orglist'); }); @@ -202,15 +152,23 @@ describe('Organisation Events Page', () => { - - - + + + + + + + - + , ); await wait(); + + await waitFor(() => { + expect(screen.getByTestId('createEventModalBtn')).toBeInTheDocument(); + }); }); test('Testing toggling of Create event modal', async () => { @@ -218,19 +176,39 @@ describe('Organisation Events Page', () => { - - - + + + + + + + - + , ); await wait(); + await waitFor(() => { + expect(screen.getByTestId('createEventModalBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('createEventModalBtn')); + await waitFor(() => { + expect( + screen.getByTestId('createEventModalCloseBtn'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('createEventModalCloseBtn')); + + await waitFor(() => { + expect( + screen.queryByTestId('createEventModalCloseBtn'), + ).not.toBeInTheDocument(); + }); }); test('Testing Create event modal', async () => { @@ -238,73 +216,80 @@ describe('Organisation Events Page', () => { - - - + + + + + + + - + , ); await wait(); + await waitFor(() => { + expect(screen.getByTestId('createEventModalBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('createEventModalBtn')); + await waitFor(() => { + expect(screen.getByPlaceholderText(/Enter Title/i)).toBeInTheDocument(); + }); + userEvent.type(screen.getByPlaceholderText(/Enter Title/i), formData.title); + userEvent.type( screen.getByPlaceholderText(/Enter Description/i), - formData.description - ); - userEvent.type( - screen.getByPlaceholderText(/Enter Location/i), - formData.location + formData.description, ); userEvent.type( screen.getByPlaceholderText(/Enter Location/i), - formData.location + formData.location, ); - const endDateDatePicker = screen.getByPlaceholderText(/End Date/i); - const startDateDatePicker = screen.getByPlaceholderText(/Start Date/i); - - fireEvent.click(endDateDatePicker); - fireEvent.click(startDateDatePicker); - - await act(async () => { - fireEvent.change(endDateDatePicker, { - target: { - value: formData.endDate, - }, - }); - fireEvent.change(startDateDatePicker, { - target: { - value: formData.startDate, - }, - }); + const endDatePicker = screen.getByLabelText('End Date'); + const startDatePicker = screen.getByLabelText('Start Date'); + + fireEvent.change(endDatePicker, { + target: { value: formData.endDate }, }); - userEvent.click(screen.getByTestId('alldayCheck')); - userEvent.click(screen.getByTestId('recurringCheck')); + fireEvent.change(startDatePicker, { + target: { value: formData.startDate }, + }); + userEvent.click(screen.getByTestId('ispublicCheck')); userEvent.click(screen.getByTestId('registrableCheck')); await wait(); expect(screen.getByPlaceholderText(/Enter Title/i)).toHaveValue( - formData.title + formData.title, ); expect(screen.getByPlaceholderText(/Enter Description/i)).toHaveValue( - formData.description + formData.description, ); - expect(endDateDatePicker).toHaveValue(formData.endDate); - expect(startDateDatePicker).toHaveValue(formData.startDate); - expect(screen.getByTestId('alldayCheck')).not.toBeChecked(); - expect(screen.getByTestId('recurringCheck')).toBeChecked(); + expect(endDatePicker).toHaveValue(formData.endDate); + expect(startDatePicker).toHaveValue(formData.startDate); expect(screen.getByTestId('ispublicCheck')).not.toBeChecked(); expect(screen.getByTestId('registrableCheck')).toBeChecked(); userEvent.click(screen.getByTestId('createEventBtn')); - }, 15000); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.eventCreated); + }); + + await waitFor(() => { + expect( + screen.queryByTestId('createEventModalCloseBtn'), + ).not.toBeInTheDocument(); + }); + }); test('Testing Create event with invalid inputs', async () => { const formData = { @@ -312,7 +297,7 @@ describe('Organisation Events Page', () => { description: ' ', location: ' ', startDate: '03/28/2022', - endDate: '04/15/2023', + endDate: '03/30/2022', startTime: '02:00', endTime: '06:00', allDay: false, @@ -320,54 +305,59 @@ describe('Organisation Events Page', () => { isPublic: true, isRegisterable: true, }; + render( - - - + + + + + + + - + , ); await wait(); + await waitFor(() => { + expect(screen.getByTestId('createEventModalBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('createEventModalBtn')); + await waitFor(() => { + expect(screen.getByPlaceholderText(/Enter Title/i)).toBeInTheDocument(); + }); + userEvent.type(screen.getByPlaceholderText(/Enter Title/i), formData.title); userEvent.type( screen.getByPlaceholderText(/Enter Description/i), - formData.description + formData.description, ); userEvent.type( screen.getByPlaceholderText(/Enter Location/i), - formData.location + formData.location, ); userEvent.type( screen.getByPlaceholderText(/Enter Location/i), - formData.location + formData.location, ); - const endDateDatePicker = screen.getByPlaceholderText(/End Date/i); - const startDateDatePicker = screen.getByPlaceholderText(/Start Date/i); - - fireEvent.click(endDateDatePicker); - fireEvent.click(startDateDatePicker); - - await act(async () => { - fireEvent.change(endDateDatePicker, { - target: { - value: formData.endDate, - }, - }); - fireEvent.change(startDateDatePicker, { - target: { - value: formData.startDate, - }, - }); + const endDatePicker = screen.getByLabelText('End Date'); + const startDatePicker = screen.getByLabelText('Start Date'); + + fireEvent.change(endDatePicker, { + target: { value: formData.endDate }, + }); + fireEvent.change(startDatePicker, { + target: { value: formData.startDate }, }); + userEvent.click(screen.getByTestId('alldayCheck')); userEvent.click(screen.getByTestId('recurringCheck')); userEvent.click(screen.getByTestId('ispublicCheck')); @@ -378,8 +368,8 @@ describe('Organisation Events Page', () => { expect(screen.getByPlaceholderText(/Enter Title/i)).toHaveValue(' '); expect(screen.getByPlaceholderText(/Enter Description/i)).toHaveValue(' '); - expect(endDateDatePicker).toHaveValue(formData.endDate); - expect(startDateDatePicker).toHaveValue(formData.startDate); + expect(endDatePicker).toHaveValue(formData.endDate); + expect(startDatePicker).toHaveValue(formData.startDate); expect(screen.getByTestId('alldayCheck')).not.toBeChecked(); expect(screen.getByTestId('recurringCheck')).toBeChecked(); expect(screen.getByTestId('ispublicCheck')).not.toBeChecked(); @@ -389,42 +379,94 @@ describe('Organisation Events Page', () => { expect(toast.warning).toBeCalledWith('Title can not be blank!'); expect(toast.warning).toBeCalledWith('Description can not be blank!'); expect(toast.warning).toBeCalledWith('Location can not be blank!'); - }, 15000); - test('Testing if the event is not for all day', async () => { + userEvent.click(screen.getByTestId('createEventModalCloseBtn')); + + await waitFor(() => { + expect( + screen.queryByTestId('createEventModalCloseBtn'), + ).not.toBeInTheDocument(); + }); + }); + + test('Testing create event if the event is not for all day', async () => { render( - - - + + + + + + + - + , ); await wait(); + await waitFor(() => { + expect(screen.getByTestId('createEventModalBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('createEventModalBtn')); + + await waitFor(() => { + expect(screen.getByPlaceholderText(/Enter Title/i)).toBeInTheDocument(); + }); + userEvent.type(screen.getByPlaceholderText(/Enter Title/i), formData.title); + userEvent.type( screen.getByPlaceholderText(/Enter Description/i), - formData.description + formData.description, ); + userEvent.type( screen.getByPlaceholderText(/Enter Location/i), - formData.location + formData.location, ); + + const endDatePicker = screen.getByLabelText('End Date'); + const startDatePicker = screen.getByLabelText('Start Date'); + + fireEvent.change(endDatePicker, { + target: { value: formData.endDate }, + }); + fireEvent.change(startDatePicker, { + target: { value: formData.startDate }, + }); + userEvent.click(screen.getByTestId('alldayCheck')); - await wait(); - userEvent.type( - screen.getByPlaceholderText(/Start Time/i), - formData.startTime - ); - userEvent.type(screen.getByPlaceholderText(/End Time/i), formData.endTime); + await waitFor(() => { + expect(screen.getByLabelText(translations.startTime)).toBeInTheDocument(); + }); + + const startTimePicker = screen.getByLabelText(translations.startTime); + const endTimePicker = screen.getByLabelText(translations.endTime); + + fireEvent.change(startTimePicker, { + target: { value: formData.startTime }, + }); + + fireEvent.change(endTimePicker, { + target: { value: formData.endTime }, + }); userEvent.click(screen.getByTestId('createEventBtn')); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.eventCreated); + }); + + await waitFor(() => { + expect( + screen.queryByTestId('createEventModalCloseBtn'), + ).not.toBeInTheDocument(); + }); }); }); diff --git a/src/screens/OrganizationEvents/OrganizationEvents.tsx b/src/screens/OrganizationEvents/OrganizationEvents.tsx index 36852389eb..0bf561381f 100644 --- a/src/screens/OrganizationEvents/OrganizationEvents.tsx +++ b/src/screens/OrganizationEvents/OrganizationEvents.tsx @@ -1,46 +1,74 @@ -import type { ChangeEvent } from 'react'; -import React, { useState } from 'react'; -import Row from 'react-bootstrap/Row'; -import Col from 'react-bootstrap/Col'; +import React, { useState, useEffect } from 'react'; import Button from 'react-bootstrap/Button'; import Modal from 'react-bootstrap/Modal'; -import DatePicker from 'react-datepicker'; -import { Form } from 'react-bootstrap'; +import { Form, Popover } from 'react-bootstrap'; import { useMutation, useQuery } from '@apollo/client'; import { toast } from 'react-toastify'; import { useTranslation } from 'react-i18next'; import EventCalendar from 'components/EventCalendar/EventCalendar'; -import Calendar from 'react-calendar'; -import './calendar.css'; - +import { TimePicker, DatePicker } from '@mui/x-date-pickers'; import styles from './OrganizationEvents.module.css'; import { ORGANIZATION_EVENT_CONNECTION_LIST, ORGANIZATIONS_LIST, } from 'GraphQl/Queries/Queries'; import { CREATE_EVENT_MUTATION } from 'GraphQl/Mutations/mutations'; +import type { Dayjs } from 'dayjs'; import dayjs from 'dayjs'; import { errorHandler } from 'utils/errorHandler'; import Loader from 'components/Loader/Loader'; -import OrganizationScreen from 'components/OrganizationScreen/OrganizationScreen'; +import useLocalStorage from 'utils/useLocalstorage'; +import { useParams, useNavigate } from 'react-router-dom'; +import EventHeader from 'components/EventCalendar/EventHeader'; +import { + Frequency, + Days, + getRecurrenceRuleText, + getWeekDayOccurenceInMonth, +} from 'utils/recurrenceUtils'; +import type { InterfaceRecurrenceRuleState } from 'utils/recurrenceUtils'; +import RecurrenceOptions from 'components/RecurrenceOptions/RecurrenceOptions'; + +const timeToDayJs = (time: string): Dayjs => { + const dateTimeString = dayjs().format('YYYY-MM-DD') + ' ' + time; + return dayjs(dateTimeString, { format: 'YYYY-MM-DD HH:mm:ss' }); +}; + +export enum ViewType { + DAY = 'Day', + MONTH = 'Month View', + YEAR = 'Year View', +} function organizationEvents(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'organizationEvents', }); - document.title = t('title'); - const [eventmodalisOpen, setEventModalIsOpen] = useState(false); - - const [startDate, setStartDate] = React.useState(new Date()); - const [endDate, setEndDate] = React.useState(new Date()); + const { getItem } = useLocalStorage(); + document.title = t('title'); + const [createEventmodalisOpen, setCreateEventmodalisOpen] = useState(false); + const [startDate, setStartDate] = React.useState(new Date()); + const [endDate, setEndDate] = React.useState(new Date()); + const [viewType, setViewType] = useState(ViewType.MONTH); const [alldaychecked, setAllDayChecked] = React.useState(true); const [recurringchecked, setRecurringChecked] = React.useState(false); const [publicchecked, setPublicChecked] = React.useState(true); const [registrablechecked, setRegistrableChecked] = React.useState(false); + const [recurrenceRuleState, setRecurrenceRuleState] = + useState({ + recurrenceStartDate: startDate, + recurrenceEndDate: null, + frequency: Frequency.WEEKLY, + weekDays: [Days[startDate.getDay()]], + interval: 1, + count: undefined, + weekDayOccurenceInMonth: undefined, + }); + const [formState, setFormState] = useState({ title: '', eventdescrip: '', @@ -49,38 +77,65 @@ function organizationEvents(): JSX.Element { startTime: '08:00:00', endTime: '18:00:00', }); - const currentUrl = window.location.href.split('=')[1]; + const { orgId: currentUrl } = useParams(); + const navigate = useNavigate(); const showInviteModal = (): void => { - setEventModalIsOpen(true); + setCreateEventmodalisOpen(true); }; - const hideInviteModal = (): void => { - setEventModalIsOpen(false); + const hideCreateEventModal = (): void => { + setCreateEventmodalisOpen(false); }; - - const { data, loading, error, refetch } = useQuery( - ORGANIZATION_EVENT_CONNECTION_LIST, - { - variables: { - organization_id: currentUrl, - title_contains: '', - description_contains: '', - location_contains: '', - }, + const handleChangeView = (item: string | null): void => { + /*istanbul ignore next*/ + if (item) { + setViewType(item as ViewType); } - ); + }; + + const { + data, + loading, + error: eventDataError, + refetch: refetchEvents, + } = useQuery(ORGANIZATION_EVENT_CONNECTION_LIST, { + variables: { + organization_id: currentUrl, + title_contains: '', + description_contains: '', + location_contains: '', + }, + }); const { data: orgData } = useQuery(ORGANIZATIONS_LIST, { variables: { id: currentUrl }, }); - const userId = localStorage.getItem('id') as string; - const userRole = localStorage.getItem('UserType') as string; + const userId = getItem('id') as string; + const superAdmin = getItem('SuperAdmin'); + const adminFor = getItem('AdminFor'); + const userRole = superAdmin + ? 'SUPERADMIN' + : adminFor?.length > 0 + ? 'ADMIN' + : 'USER'; const [create, { loading: loading2 }] = useMutation(CREATE_EVENT_MUTATION); + const { + recurrenceStartDate, + recurrenceEndDate, + frequency, + weekDays, + interval, + count, + weekDayOccurenceInMonth, + } = recurrenceRuleState; + + const recurrenceRuleText = getRecurrenceRuleText(recurrenceRuleState); + const createEvent = async ( - e: ChangeEvent + e: React.ChangeEvent, ): Promise => { e.preventDefault(); if ( @@ -101,16 +156,35 @@ function organizationEvents(): JSX.Element { endDate: dayjs(endDate).format('YYYY-MM-DD'), allDay: alldaychecked, location: formState.location, - startTime: !alldaychecked ? formState.startTime + 'Z' : null, - endTime: !alldaychecked ? formState.endTime + 'Z' : null, + startTime: !alldaychecked ? formState.startTime + 'Z' : undefined, + endTime: !alldaychecked ? formState.endTime + 'Z' : undefined, + recurrenceStartDate: recurringchecked + ? dayjs(recurrenceStartDate).format('YYYY-MM-DD') + : undefined, + recurrenceEndDate: recurringchecked + ? recurrenceEndDate + ? dayjs(recurrenceEndDate).format('YYYY-MM-DD') + : null + : undefined, + frequency: recurringchecked ? frequency : undefined, + weekDays: + recurringchecked && + (frequency === Frequency.WEEKLY || + (frequency === Frequency.MONTHLY && weekDayOccurenceInMonth)) + ? weekDays + : undefined, + interval: recurringchecked ? interval : undefined, + count: recurringchecked ? count : undefined, + weekDayOccurenceInMonth: recurringchecked + ? weekDayOccurenceInMonth + : undefined, }, }); - /* istanbul ignore next */ if (createEventData) { toast.success(t('eventCreated')); - refetch(); - hideInviteModal(); + refetchEvents(); + hideCreateEventModal(); setFormState({ title: '', eventdescrip: '', @@ -119,10 +193,25 @@ function organizationEvents(): JSX.Element { startTime: '08:00:00', endTime: '18:00:00', }); + setRecurringChecked(false); + setRecurrenceRuleState({ + recurrenceStartDate: new Date(), + recurrenceEndDate: null, + frequency: Frequency.WEEKLY, + weekDays: [Days[new Date().getDay()]], + interval: 1, + count: undefined, + weekDayOccurenceInMonth: undefined, + }); + setStartDate(new Date()); + setEndDate(new Date()); } - } catch (error: any) { + } catch (error: unknown) { /* istanbul ignore next */ - errorHandler(t, error); + if (error instanceof Error) { + console.log(error.message); + errorHandler(t, error); + } } } if (formState.title.trim().length === 0) { @@ -136,59 +225,52 @@ function organizationEvents(): JSX.Element { } }; + useEffect(() => { + if (eventDataError) { + navigate('/orglist'); + } + }, [eventDataError]); + if (loading || loading2) { return ; } - /* istanbul ignore next */ - if (error) { - window.location.assign('/orglist'); - } - - /* istanbul ignore next */ + const popover = ( + + {recurrenceRuleText} + + ); return ( <> - - - -
    -
    -
    Search Date
    - -
    -
    - - -
    - -

    {t('events')}

    - -
    -
    - - -
    -
    +
    +
    + +
    +
    + - + {/* Create Event Modal */} +

    {t('eventDetails')}

    - + setPublicChecked(!publicchecked)} + data-testid="recurringCheck" + checked={recurringchecked} + onChange={(): void => { + setRecurringChecked(!recurringchecked); + }} />
    + + {/* Recurrence Options */} + {recurringchecked && ( + + )} + + + +
    + + {t('campaignName')} + + setFormState({ + ...formState, + campaignName: e.target.value, + }) + } + /> + + +
    + { + if (date) { + setFormState({ + ...formState, + campaignStartDate: date.toDate(), + campaignEndDate: + formState.campaignEndDate && + (formState.campaignEndDate < date?.toDate() + ? date.toDate() + : formState.campaignEndDate), + }); + } + }} + minDate={dayjs(new Date())} + /> +
    +
    + { + if (date) { + setFormState({ + ...formState, + campaignEndDate: date.toDate(), + }); + } + }} + minDate={dayjs(formState.campaignStartDate)} + /> +
    +
    + + + {t('currency')} + + { + setFormState({ + ...formState, + campaignCurrency: e.target.value, + }); + }} + > + + {currencyOptions.map((currency) => ( + + ))} + + + + + {t('fundingGoal')} + { + if (parseInt(e.target.value) > 0) { + setFormState({ + ...formState, + campaignGoal: parseInt(e.target.value), + }); + } + }} + /> + + + +
    +
    + + + ); +}; +export default CampaignCreateModal; diff --git a/src/screens/OrganizationFundCampaign/CampaignDeleteModal.tsx b/src/screens/OrganizationFundCampaign/CampaignDeleteModal.tsx new file mode 100644 index 0000000000..97146c4bc9 --- /dev/null +++ b/src/screens/OrganizationFundCampaign/CampaignDeleteModal.tsx @@ -0,0 +1,53 @@ +import React from 'react'; +import { Button, Modal } from 'react-bootstrap'; +import styles from './OrganizationFundCampaign.module.css'; + +interface InterfaceDeleteCampaignModal { + campaignDeleteModalIsOpen: boolean; + hideDeleteCampaignModal: () => void; + deleteCampaignHandler: () => Promise; + t: (key: string) => string; +} +const CampaignDeleteModal: React.FC = ({ + campaignDeleteModalIsOpen, + hideDeleteCampaignModal, + deleteCampaignHandler, + t, +}) => { + return ( + <> + + +

    {t('deleteCampaign')}

    + +
    + +

    {t('deleteCampaignMsg')}

    +
    + + + + +
    + + ); +}; +export default CampaignDeleteModal; diff --git a/src/screens/OrganizationFundCampaign/CampaignUpdateModal.tsx b/src/screens/OrganizationFundCampaign/CampaignUpdateModal.tsx new file mode 100644 index 0000000000..561c7c9252 --- /dev/null +++ b/src/screens/OrganizationFundCampaign/CampaignUpdateModal.tsx @@ -0,0 +1,170 @@ +import { DatePicker } from '@mui/x-date-pickers'; +import type { Dayjs } from 'dayjs'; +import dayjs from 'dayjs'; +import type { ChangeEvent } from 'react'; +import React from 'react'; +import { Button, Col, Form, Modal } from 'react-bootstrap'; +import { currencyOptions } from 'utils/currency'; +import type { InterfaceCreateCampaign } from 'utils/interfaces'; +import styles from './OrganizationFundCampaign.module.css'; + +interface InterfaceCampaignUpdateModal { + campaignUpdateModalIsOpen: boolean; + hideUpdateCampaignModal: () => void; + formState: InterfaceCreateCampaign; + setFormState: (state: React.SetStateAction) => void; + updateCampaignHandler: (e: ChangeEvent) => Promise; + t: (key: string) => string; + showDeleteCampaignModal: () => void; +} + +const CampaignUpdateModal: React.FC = ({ + campaignUpdateModalIsOpen, + hideUpdateCampaignModal, + formState, + setFormState, + updateCampaignHandler, + t, + showDeleteCampaignModal, +}) => { + return ( + <> + + +

    {t('manageCampaign')}

    + +
    + +
    + + {t('campaignName')} + + setFormState({ + ...formState, + campaignName: e.target.value, + }) + } + /> + + +
    + { + if (date) { + setFormState({ + ...formState, + campaignStartDate: date.toDate(), + campaignEndDate: + formState.campaignEndDate && + (formState.campaignEndDate < date?.toDate() + ? date.toDate() + : formState.campaignEndDate), + }); + } + }} + minDate={dayjs(new Date())} + /> +
    +
    + { + if (date) { + setFormState({ + ...formState, + campaignEndDate: date.toDate(), + }); + } + }} + minDate={dayjs(formState.campaignStartDate)} + /> +
    +
    + + + {t('currency')} + + { + setFormState({ + ...formState, + campaignCurrency: e.target.value, + }); + }} + > + + {currencyOptions.map((currency) => ( + + ))} + + + + + {t('fundingGoal')} + { + if (parseInt(e.target.value) > 0) { + setFormState({ + ...formState, + campaignGoal: parseInt(e.target.value), + }); + } + }} + /> + + +
    + + +
    +
    +
    +
    + + ); +}; +export default CampaignUpdateModal; diff --git a/src/screens/OrganizationFundCampaign/OrganizationFundCampagins.tsx b/src/screens/OrganizationFundCampaign/OrganizationFundCampagins.tsx new file mode 100644 index 0000000000..254616affc --- /dev/null +++ b/src/screens/OrganizationFundCampaign/OrganizationFundCampagins.tsx @@ -0,0 +1,444 @@ +/*eslint-disable*/ +import { useMutation, useQuery } from '@apollo/client'; +import { Search, WarningAmberRounded } from '@mui/icons-material'; +import { + CREATE_CAMPAIGN_MUTATION, + DELETE_CAMPAIGN_MUTATION, + UPDATE_CAMPAIGN_MUTATION, +} from 'GraphQl/Mutations/CampaignMutation'; +import { FUND_CAMPAIGN } from 'GraphQl/Queries/fundQueries'; +import Loader from 'components/Loader/Loader'; +import dayjs from 'dayjs'; +import { useState, type ChangeEvent } from 'react'; +import { Button, Col, Row, Dropdown, Form } from 'react-bootstrap'; +import { useTranslation } from 'react-i18next'; +import { useNavigate, useParams } from 'react-router-dom'; +import { toast } from 'react-toastify'; +import { currencySymbols } from 'utils/currency'; +import FilterAltOutlinedIcon from '@mui/icons-material/FilterAltOutlined'; +import type { + InterfaceCampaignInfo, + InterfaceCreateCampaign, + InterfaceQueryOrganizationFundCampaigns, +} from 'utils/interfaces'; +import CampaignCreateModal from './CampaignCreateModal'; +import CampaignDeleteModal from './CampaignDeleteModal'; +import CampaignUpdateModal from './CampaignUpdateModal'; +import styles from './OrganizationFundCampaign.module.css'; +import { + Paper, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + styled, + tableCellClasses, +} from '@mui/material'; + +const StyledTableCell = styled(TableCell)(({ theme }) => ({ + [`&.${tableCellClasses.head}`]: { + backgroundColor: ['#31bb6b', '!important'], + color: theme.palette.common.white, + }, + [`&.${tableCellClasses.body}`]: { + fontSize: 14, + }, +})); + +const StyledTableRow = styled(TableRow)(() => ({ + '&:last-child td, &:last-child th': { + border: 0, + }, +})); + +const orgFundCampaign = (): JSX.Element => { + const { t } = useTranslation('translation', { + keyPrefix: 'fundCampaign', + }); + const navigate = useNavigate(); + + const { fundId: currentUrl, orgId: orgId } = useParams(); + const [campaignCreateModalIsOpen, setcampaignCreateModalIsOpen] = + useState(false); + const [campaignUpdateModalIsOpen, setcampaignUpdateModalIsOpen] = + useState(false); + const [campaignDeleteModalIsOpen, setcampaignDeleteModalIsOpen] = + useState(false); + + const [campaign, setCampaign] = useState(null); + const [formState, setFormState] = useState({ + campaignName: '', + campaignCurrency: 'USD', + campaignGoal: 0, + campaignStartDate: new Date(), + campaignEndDate: new Date(), + }); + const { + data: fundCampaignData, + loading: fundCampaignLoading, + error: fundCampaignError, + refetch: refetchFundCampaign, + }: { + data?: { + getFundById: InterfaceQueryOrganizationFundCampaigns; + }; + loading: boolean; + error?: Error | undefined; + refetch: any; + } = useQuery(FUND_CAMPAIGN, { + variables: { + id: currentUrl, + }, + }); + + const [createCampaign] = useMutation(CREATE_CAMPAIGN_MUTATION); + const [updateCampaign] = useMutation(UPDATE_CAMPAIGN_MUTATION); + const [deleteCampaign] = useMutation(DELETE_CAMPAIGN_MUTATION); + + const showCreateCampaignModal = (): void => { + setcampaignCreateModalIsOpen(!campaignCreateModalIsOpen); + }; + const hideCreateCampaignModal = (): void => { + setcampaignCreateModalIsOpen(!campaignCreateModalIsOpen); + }; + const showUpdateCampaignModal = (): void => { + setcampaignUpdateModalIsOpen(!campaignUpdateModalIsOpen); + }; + const hideUpdateCampaignModal = (): void => { + setcampaignUpdateModalIsOpen(!campaignUpdateModalIsOpen); + setFormState({ + campaignName: '', + campaignCurrency: 'USD', + campaignGoal: 0, + campaignStartDate: new Date(), + campaignEndDate: new Date(), + }); + }; + const showDeleteCampaignModal = (): void => { + setcampaignDeleteModalIsOpen(!campaignDeleteModalIsOpen); + }; + const hideDeleteCampaignModal = (): void => { + setcampaignDeleteModalIsOpen(!campaignDeleteModalIsOpen); + }; + + const handleEditClick = (campaign: InterfaceCampaignInfo): void => { + setFormState({ + campaignName: campaign.name, + campaignCurrency: campaign.currency, + campaignGoal: campaign.fundingGoal, + campaignStartDate: new Date(campaign.startDate), + campaignEndDate: new Date(campaign.endDate), + }); + setCampaign(campaign); + showUpdateCampaignModal(); + }; + + const createCampaignHandler = async ( + e: ChangeEvent, + ): Promise => { + e.preventDefault(); + try { + await createCampaign({ + variables: { + name: formState.campaignName, + currency: formState.campaignCurrency, + fundingGoal: formState.campaignGoal, + startDate: dayjs(formState.campaignStartDate).format('YYYY-MM-DD'), + endDate: dayjs(formState.campaignEndDate).format('YYYY-MM-DD'), + fundId: currentUrl, + }, + }); + toast.success(t('createdCampaign')); + setFormState({ + campaignName: '', + campaignCurrency: 'USD', + campaignGoal: 0, + campaignStartDate: new Date(), + campaignEndDate: new Date(), + }); + refetchFundCampaign(); + hideCreateCampaignModal(); + } catch (error: unknown) { + if (error instanceof Error) { + toast.error(error.message); + console.log(error.message); + } + } + }; + + const updateCampaignHandler = async ( + e: ChangeEvent, + ): Promise => { + e.preventDefault(); + try { + const updatedFields: { [key: string]: any } = {}; + if (campaign?.name !== formState.campaignName) { + updatedFields.name = formState.campaignName; + } + if (campaign?.currency !== formState.campaignCurrency) { + updatedFields.currency = formState.campaignCurrency; + } + if (campaign?.fundingGoal !== formState.campaignGoal) { + updatedFields.fundingGoal = formState.campaignGoal; + } + if (campaign?.startDate !== formState.campaignStartDate) { + updatedFields.startDate = dayjs(formState.campaignStartDate).format( + 'YYYY-MM-DD', + ); + } + if (campaign?.endDate !== formState.campaignEndDate) { + updatedFields.endDate = dayjs(formState.campaignEndDate).format( + 'YYYY-MM-DD', + ); + } + await updateCampaign({ + variables: { + id: campaign?._id, + ...updatedFields, + }, + }); + setFormState({ + campaignName: '', + campaignCurrency: 'USD', + campaignGoal: 0, + campaignStartDate: new Date(), + campaignEndDate: new Date(), + }); + refetchFundCampaign(); + hideUpdateCampaignModal(); + toast.success(t('updatedCampaign')); + } catch (error: unknown) { + if (error instanceof Error) { + toast.error(error.message); + console.log(error.message); + } + } + }; + + const deleteCampaignHandler = async (): Promise => { + try { + await deleteCampaign({ + variables: { + id: campaign?._id, + }, + }); + toast.success(t('deletedCampaign')); + refetchFundCampaign(); + hideDeleteCampaignModal(); + } catch (error: unknown) { + if (error instanceof Error) { + toast.error(error.message); + console.log(error.message); + } + } + }; + + const handleClick = (campaignId: String) => { + navigate(`/fundCampaignPledge/${orgId}/${campaignId}`); + }; + + const [searchQuery, setSearchQuery] = useState(''); + const [searchText, setSearchText] = useState(''); + const filteredCampaigns = fundCampaignData?.getFundById.campaigns.filter( + (campaign) => + campaign.name.toLowerCase().includes(searchQuery.toLowerCase()), + ); + + if (fundCampaignLoading) { + return ; + } + if (fundCampaignError) { + return ( +
    +
    + +
    + Error occured while loading Campaigns +
    + {fundCampaignError.message} +
    +
    +
    + ); + } + + return ( +
    +
    +
    + { + setSearchText(e.target.value); + }} + data-testid="searchFullName" + /> + +
    +
    +
    + + + + {t('filter')} + + +
    +
    + +
    +
    +
    + +
    + {filteredCampaigns && filteredCampaigns.length > 0 ? ( +
    + + + + + # + + {t('campaignName')} + + + {t('startDate')} + + + {t('endDate')} + + + {t('fundingGoal')} + + + {t('campaignOptions')} + + + + + {filteredCampaigns.map((campaign, index) => ( + + + {index + 1} + + handleClick(campaign._id)} + > + + {campaign.name} + + + + {dayjs(campaign.startDate).format('DD/MM/YYYY')} + + + {dayjs(campaign.endDate).format('DD/MM/YYYY')} + + + + {`${currencySymbols[campaign.currency as keyof typeof currencySymbols]}${campaign.fundingGoal}`} + + + + + + + ))} + +
    +
    +
    + ) : ( +
    +
    {t('noCampaigns')}
    +
    + )} +
    + + {/* Create Campaign Modal */} + + + {/* Update Campaign Modal */} + + + {/* Delete Campaign Modal */} + +
    + ); +}; +export default orgFundCampaign; diff --git a/src/screens/OrganizationFundCampaign/OrganizationFundCampaign.module.css b/src/screens/OrganizationFundCampaign/OrganizationFundCampaign.module.css new file mode 100644 index 0000000000..3ed22aa094 --- /dev/null +++ b/src/screens/OrganizationFundCampaign/OrganizationFundCampaign.module.css @@ -0,0 +1,181 @@ +.organizationFundCampaignContainer { + margin: 0.6rem 0; +} +.goalButton { + border: 1px solid rgba(49, 187, 107, 1) !important; + color: rgba(49, 187, 107, 1) !important; + width: 75%; + padding: 10px; + border-radius: 8px; + display: block; + margin: auto; + box-shadow: 5px 5px 4px 0px rgba(49, 187, 107, 0.12); +} +.container { + min-height: 100vh; +} +.campaignModal { + max-width: 80vw; + margin-top: 2vh; + margin-left: 13vw; +} +.titlemodal { + color: var(--bs-gray-600); + font-weight: 600; + font-size: 20px; + margin-bottom: 20px; + padding-bottom: 5px; + border-bottom: 3px solid var(--bs-primary); + width: 65%; +} +.greenregbtn { + margin: 1rem 0 0; + margin-top: 15px; + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + padding: 10px 10px; + border-radius: 5px; + background-color: #31bb6b; + width: 100%; + font-size: 16px; + color: white; + outline: none; + font-weight: 600; + cursor: pointer; + transition: + transform 0.2s, + box-shadow 0.2s; + width: 100%; + flex: 1; +} + +.redregbtn { + margin: 1rem 0 0; + margin-top: 15px; + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + padding: 10px 10px; + border-radius: 5px; + width: 100%; + font-size: 16px; + color: white; + outline: none; + font-weight: 600; + cursor: pointer; + transition: + transform 0.2s, + box-shadow 0.2s; + width: 100%; + flex: 1; +} +.campaignNameInfo { + font-size: medium; + cursor: pointer; +} +.campaignNameInfo:hover { + color: blue; + transform: translateY(-2px); +} +.message { + margin-top: 25%; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; +} + +.inputField { + background-color: white; + box-shadow: 0 1px 1px #31bb6b; +} + +.dropdown { + background-color: white; + border: 1px solid #31bb6b; + position: relative; + display: inline-block; + color: #31bb6b; +} + +.btnsContainer { + display: flex; + margin: 2.5rem 0 2.5rem 0; +} + +.btnsContainer .btnsBlock { + display: flex; +} + +.btnsContainer .btnsBlock div button { + display: flex; + margin-left: 1rem; + justify-content: center; + align-items: center; +} + +.btnsContainer .input { + flex: 1; + position: relative; +} + +.btnsContainer input { + outline: 1px solid var(--bs-gray-400); +} + +.btnsContainer .input button { + width: 52px; +} + +.mainpageright > hr { + margin-top: 20px; + width: 100%; + margin-left: -15px; + margin-right: -15px; + margin-bottom: 20px; +} + +@media (max-width: 1020px) { + .btnsContainer { + flex-direction: column; + margin: 1.5rem 0; + } + + .btnsContainer .btnsBlock { + margin: 1.5rem 0 0 0; + justify-content: space-between; + } + + .btnsContainer .btnsBlock div button { + margin: 0; + } + + .createFundBtn { + margin-top: 0; + } +} + +@media screen and (max-width: 575.5px) { + .mainpageright { + width: 98%; + } +} + +/* For mobile devices */ + +@media (max-width: 520px) { + .btnsContainer { + margin-bottom: 0; + } + + .btnsContainer .btnsBlock { + display: block; + margin-top: 1rem; + margin-right: 0; + } + + .btnsContainer .btnsBlock div button { + margin-bottom: 1rem; + margin-right: 0; + width: 100%; + } +} diff --git a/src/screens/OrganizationFundCampaign/OrganizationFundCampaign.test.tsx b/src/screens/OrganizationFundCampaign/OrganizationFundCampaign.test.tsx new file mode 100644 index 0000000000..16f069444f --- /dev/null +++ b/src/screens/OrganizationFundCampaign/OrganizationFundCampaign.test.tsx @@ -0,0 +1,663 @@ +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { + fireEvent, + render, + screen, + waitFor, + waitForElementToBeRemoved, +} from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { act } from 'react-dom/test-utils'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { toast } from 'react-toastify'; +import { store } from '../../state/store'; +import { StaticMockLink } from '../../utils/StaticMockLink'; +import i18nForTest from '../../utils/i18nForTest'; +import OrganizaitionFundCampiagn from './OrganizationFundCampagins'; +import { + EMPTY_MOCKS, + MOCKS, + MOCKS_ERROR_CREATE_CAMPAIGN, + MOCKS_ERROR_DELETE_CAMPAIGN, + MOCKS_ERROR_UPDATE_CAMPAIGN, + MOCK_FUND_CAMPAIGN_ERROR, +} from './OrganizationFundCampaignMocks'; +import React from 'react'; + +const mockNavigate = jest.fn(); +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useNavigate: () => mockNavigate, +})); +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); +jest.mock('@mui/x-date-pickers/DateTimePicker', () => { + return { + DateTimePicker: jest.requireActual( + '@mui/x-date-pickers/DesktopDateTimePicker', + ).DesktopDateTimePicker, + }; +}); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} +const link1 = new StaticMockLink(MOCKS, true); +const link2 = new StaticMockLink(MOCK_FUND_CAMPAIGN_ERROR, true); +const link3 = new StaticMockLink(MOCKS_ERROR_CREATE_CAMPAIGN, true); +const link4 = new StaticMockLink(MOCKS_ERROR_UPDATE_CAMPAIGN, true); +const link5 = new StaticMockLink(MOCKS_ERROR_DELETE_CAMPAIGN, true); +const link6 = new StaticMockLink(EMPTY_MOCKS, true); + +const translations = JSON.parse( + JSON.stringify(i18nForTest.getDataByLanguage('en')?.translation.fundCampaign), +); + +describe('Testing FundCampaigns Screen', () => { + const formData = { + campaignName: 'Campaign 1', + campaignCurrency: 'USD', + campaignGoal: 100, + campaignStartDate: '03/10/2024', + campaignEndDate: '03/10/2024', + }; + + it('loads the Fund Campaigns screen', async () => { + const { getByText } = render( + + + + + {} + + + + , + ); + await wait(); + await waitFor(() => { + expect(getByText(translations.addCampaign)).toBeInTheDocument(); + }); + }); + it('renders the campaign screen with error', async () => { + const { queryByText } = render( + + + + + {} + + + + , + ); + await wait(); + await waitFor(() => { + expect(queryByText(translations.addCampaign)).not.toBeInTheDocument(); + }); + }); + it('renders the Error Component', async () => { + render( + + + + + {} + + + + , + ); + await wait(); + await waitFor(() => { + expect(screen.getByTestId('errorMsg')).toBeInTheDocument(); + }); + }); + it("opens and closes the 'Create Campaign' modal", async () => { + render( + + + + + + {} + + + + + , + ); + await wait(); + await waitFor(() => + expect(screen.getByTestId('addCampaignBtn')).toBeInTheDocument(), + ); + userEvent.click(screen.getByTestId('addCampaignBtn')); + await waitFor(() => { + return expect( + screen.findByTestId('createCampaignCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('createCampaignCloseBtn')); + await waitForElementToBeRemoved(() => + screen.queryByTestId('createCampaignCloseBtn'), + ); + }); + it('creates a new Campaign', async () => { + render( + + + + + + {} + + + + + , + ); + await wait(); + await waitFor(() => + expect(screen.getByTestId('addCampaignBtn')).toBeInTheDocument(), + ); + userEvent.click(screen.getByTestId('addCampaignBtn')); + await waitFor(() => { + return expect( + screen.findByTestId('createCampaignCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.type( + screen.getByPlaceholderText('Enter Campaign Name'), + formData.campaignName, + ); + userEvent.type( + screen.getByPlaceholderText('Enter Funding Goal'), + formData.campaignGoal.toString(), + ); + const currency = screen.getByTestId('currencySelect'); + fireEvent.change(currency, { + target: { value: formData.campaignCurrency }, + }); + const startDate = screen.getByLabelText('Start Date'); + const endDate = screen.getByLabelText('End Date'); + fireEvent.change(startDate, { + target: { value: formData.campaignStartDate }, + }); + fireEvent.change(endDate, { + target: { value: formData.campaignEndDate }, + }); + + userEvent.click(screen.getByTestId('createCampaignBtn')); + + await waitFor(() => { + expect(toast.success).toHaveBeenCalledWith(translations.createdCampaign); + }); + }); + it('toast an error on unsuccessful campaign creation', async () => { + render( + + + + + + {} + + + + + , + ); + await wait(); + await waitFor(() => + expect(screen.getByTestId('addCampaignBtn')).toBeInTheDocument(), + ); + userEvent.click(screen.getByTestId('addCampaignBtn')); + await waitFor(() => { + return expect( + screen.findByTestId('createCampaignCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.type( + screen.getByPlaceholderText('Enter Campaign Name'), + formData.campaignName, + ); + userEvent.type( + screen.getByPlaceholderText('Enter Funding Goal'), + formData.campaignGoal.toString(), + ); + const endDateDatePicker = screen.getByLabelText('End Date'); + const startDateDatePicker = screen.getByLabelText('Start Date'); + + fireEvent.change(endDateDatePicker, { + target: { value: formData.campaignEndDate }, + }); + fireEvent.change(startDateDatePicker, { + target: { value: formData.campaignStartDate }, + }); + + userEvent.click(screen.getByTestId('createCampaignBtn')); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); + it('opens and closes the Edit Campaign modal', async () => { + render( + + + + + + {} + + + + + , + ); + await wait(); + await waitFor(() => + expect(screen.getAllByTestId('editCampaignBtn')[0]).toBeInTheDocument(), + ); + userEvent.click(screen.getAllByTestId('editCampaignBtn')[0]); + await waitFor(() => { + return expect( + screen.findByTestId('editCampaignCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('editCampaignCloseBtn')); + await waitForElementToBeRemoved(() => + screen.queryByTestId('editCampaignCloseBtn'), + ); + }); + + it("updates the Campaign's details", async () => { + render( + + + + + + {} + + + + + , + ); + await wait(); + await waitFor(() => + expect(screen.getAllByTestId('editCampaignBtn')[0]).toBeInTheDocument(), + ); + userEvent.click(screen.getAllByTestId('editCampaignBtn')[0]); + await waitFor(() => { + return expect( + screen.findByTestId('editCampaignCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + const campaignName = screen.getByPlaceholderText('Enter Campaign Name'); + fireEvent.change(campaignName, { + target: { value: 'Campaign 4' }, + }); + const fundingGoal = screen.getByPlaceholderText('Enter Funding Goal'); + fireEvent.change(fundingGoal, { + target: { value: 1000 }, + }); + const currency = screen.getByTestId('currencySelect'); + fireEvent.change(currency, { + target: { value: 'INR' }, + }); + const endDateDatePicker = screen.getByLabelText('End Date'); + const startDateDatePicker = screen.getByLabelText('Start Date'); + + const endDate = + formData.campaignEndDate < formData.campaignStartDate + ? formData.campaignStartDate + : formData.campaignEndDate; + fireEvent.change(endDateDatePicker, { + target: { value: endDate }, + }); + + fireEvent.change(startDateDatePicker, { + target: { value: formData.campaignStartDate }, + }); + + userEvent.click(screen.getByTestId('editCampaignSubmitBtn')); + + await waitFor(() => { + expect(toast.success).toHaveBeenCalledWith(translations.updatedCampaign); + }); + }); + + it("updates the Campaign's details when date is null", async () => { + render( + + + + + + {} + + + + + , + ); + await wait(); + await waitFor(() => + expect(screen.getAllByTestId('editCampaignBtn')[0]).toBeInTheDocument(), + ); + userEvent.click(screen.getAllByTestId('editCampaignBtn')[0]); + await waitFor(() => { + return expect( + screen.findByTestId('editCampaignCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + const endDateDatePicker = screen.getByLabelText('End Date'); + const startDateDatePicker = screen.getByLabelText('Start Date'); + + fireEvent.change(endDateDatePicker, { + target: { value: null }, + }); + + fireEvent.change(startDateDatePicker, { + target: { value: null }, + }); + + expect(startDateDatePicker.getAttribute('value')).toBe(''); + expect(endDateDatePicker.getAttribute('value')).toBe(''); + }); + + it("updates the Campaign's details when endDate is less than date", async () => { + const formData = { + campaignName: 'Campaign 1', + campaignCurrency: 'USD', + campaignGoal: 100, + campaignStartDate: '03/10/2024', + campaignEndDate: '03/10/2023', + }; + render( + + + + + + {} + + + + + , + ); + await wait(); + await waitFor(() => + expect(screen.getAllByTestId('editCampaignBtn')[0]).toBeInTheDocument(), + ); + userEvent.click(screen.getAllByTestId('editCampaignBtn')[0]); + await waitFor(() => { + return expect( + screen.findByTestId('editCampaignCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + + const endDateDatePicker = screen.getByLabelText('End Date'); + const startDateDatePicker = screen.getByLabelText('Start Date'); + + fireEvent.change(endDateDatePicker, { + target: { value: formData.campaignEndDate }, + }); + + fireEvent.change(startDateDatePicker, { + target: { value: formData.campaignStartDate }, + }); + }); + + it("doesn't update when fund field has value less than or equal to 0", async () => { + render( + + + + + + {} + + + + + , + ); + await wait(); + await waitFor(() => + expect(screen.getAllByTestId('editCampaignBtn')[0]).toBeInTheDocument(), + ); + userEvent.click(screen.getAllByTestId('editCampaignBtn')[0]); + await waitFor(() => { + return expect( + screen.findByTestId('editCampaignCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + const fundingGoal = screen.getByPlaceholderText( + 'Enter Funding Goal', + ) as HTMLInputElement; + + const initialValue = fundingGoal.value; //Vakue before updating + + fireEvent.change(fundingGoal, { + target: { value: 0 }, + }); + + expect(fundingGoal.value).toBe(initialValue); //Retains previous value + }); + + it('toast an error on unsuccessful campaign update', async () => { + render( + + + + + + {} + + + + + , + ); + await wait(); + await waitFor(() => + expect(screen.getAllByTestId('editCampaignBtn')[0]).toBeInTheDocument(), + ); + userEvent.click(screen.getAllByTestId('editCampaignBtn')[0]); + await waitFor(() => { + return expect( + screen.findByTestId('editCampaignCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.type( + screen.getByPlaceholderText('Enter Campaign Name'), + formData.campaignName, + ); + + userEvent.click(screen.getByTestId('editCampaignSubmitBtn')); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); + it("opens and closes the 'Delete Campaign' modal", async () => { + render( + + + + + + {} + + + + + , + ); + await wait(); + await waitFor(() => + expect(screen.getAllByTestId('editCampaignBtn')[0]).toBeInTheDocument(), + ); + userEvent.click(screen.getAllByTestId('editCampaignBtn')[0]); + await wait(); + await waitFor(() => + expect(screen.getAllByTestId('deleteCampaignBtn')[0]).toBeInTheDocument(), + ); + userEvent.click(screen.getAllByTestId('deleteCampaignBtn')[0]); + await waitFor(() => { + return expect( + screen.findByTestId('deleteCampaignCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('deleteCampaignCloseBtn')); + await waitForElementToBeRemoved(() => + screen.queryByTestId('deleteCampaignCloseBtn'), + ); + }); + it('deletes a Campaign', async () => { + render( + + + + + + {} + + + + + , + ); + await wait(); + await waitFor(() => + expect(screen.getAllByTestId('editCampaignBtn')[0]).toBeInTheDocument(), + ); + userEvent.click(screen.getAllByTestId('editCampaignBtn')[0]); + await wait(); + await waitFor(() => + expect(screen.getAllByTestId('deleteCampaignBtn')[0]).toBeInTheDocument(), + ); + userEvent.click(screen.getAllByTestId('deleteCampaignBtn')[0]); + await waitFor(() => { + return expect( + screen.findByTestId('deleteCampaignCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('deleteyesbtn')); + await waitFor(() => { + expect(toast.success).toHaveBeenCalledWith(translations.deletedCampaign); + }); + }); + it('toast an error on unsuccessful campaign deletion', async () => { + render( + + + + + + {} + + + + + , + ); + await wait(); + await waitFor(() => + expect(screen.getAllByTestId('editCampaignBtn')[0]).toBeInTheDocument(), + ); + userEvent.click(screen.getAllByTestId('editCampaignBtn')[0]); + await wait(); + await waitFor(() => + expect(screen.getAllByTestId('deleteCampaignBtn')[0]).toBeInTheDocument(), + ); + userEvent.click(screen.getAllByTestId('deleteCampaignBtn')[0]); + await waitFor(() => { + return expect( + screen.findByTestId('deleteCampaignCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('deleteyesbtn')); + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); + it('renders the Empty Campaigns Component', async () => { + render( + + + + + + {} + + + + + , + ); + await wait(); + await waitFor(() => { + expect(screen.getByText(translations.noCampaigns)).toBeInTheDocument(); + }); + }); + it("redirects to 'FundCampaignPledge' screen", async () => { + render( + + + + + + {} + + + + + , + ); + await wait(); + await waitFor(() => + expect(screen.getAllByTestId('campaignName')[0]).toBeInTheDocument(), + ); + userEvent.click(screen.getAllByTestId('campaignName')[0]); + await waitFor(() => { + expect(mockNavigate).toHaveBeenCalledWith( + '/fundCampaignPledge/undefined/1', + ); + }); + }); + + it('search funds by name', async () => { + render( + + + + + {} + + + + , + ); + await wait(); + userEvent.type(screen.getByTestId('searchFullName'), 'Funndds'); + await wait(); + userEvent.click(screen.getByTestId('searchBtn')); + }); +}); diff --git a/src/screens/OrganizationFundCampaign/OrganizationFundCampaignMocks.tsx b/src/screens/OrganizationFundCampaign/OrganizationFundCampaignMocks.tsx new file mode 100644 index 0000000000..09fbb9f4b2 --- /dev/null +++ b/src/screens/OrganizationFundCampaign/OrganizationFundCampaignMocks.tsx @@ -0,0 +1,265 @@ +import { + CREATE_CAMPAIGN_MUTATION, + DELETE_CAMPAIGN_MUTATION, + UPDATE_CAMPAIGN_MUTATION, +} from 'GraphQl/Mutations/CampaignMutation'; +import { FUND_CAMPAIGN } from 'GraphQl/Queries/fundQueries'; + +export const MOCKS = [ + { + request: { + query: FUND_CAMPAIGN, + variables: { + id: undefined, + }, + }, + result: { + data: { + getFundById: { + campaigns: [ + { + _id: '1', + name: 'Campaign 1', + fundingGoal: 100, + startDate: '2024-01-01', + endDate: '2024-01-01', + currency: 'USD', + }, + { + _id: '2', + name: 'Campaign 2', + fundingGoal: 200, + startDate: '2021-01-01', + endDate: '2021-01-01', + currency: 'USD', + }, + ], + }, + }, + }, + }, + { + request: { + query: CREATE_CAMPAIGN_MUTATION, + variables: { + fundId: undefined, + name: 'Campaign 1', + fundingGoal: 100, + startDate: '2024-03-10', + endDate: '2024-03-10', + currency: 'USD', + }, + }, + result: { + data: { + createFundraisingCampaign: { + _id: '3', + }, + }, + }, + }, + { + request: { + query: UPDATE_CAMPAIGN_MUTATION, + variables: { + id: '1', + name: 'Campaign 4', + startDate: '2024-03-10', + endDate: '2024-03-10', + fundingGoal: 1000, + currency: 'INR', + }, + }, + result: { + data: { + updateFundraisingCampaign: { + _id: '1', + }, + }, + }, + }, + { + request: { + query: DELETE_CAMPAIGN_MUTATION, + variables: { + id: '1', + }, + }, + result: { + data: { + removeFundraisingCampaign: { + _id: '1', + }, + }, + }, + }, +]; + +export const MOCK_FUND_CAMPAIGN_ERROR = [ + { + request: { + query: FUND_CAMPAIGN, + variables: { + id: undefined, + }, + }, + error: new Error('An error occurred'), + }, +]; +export const MOCKS_ERROR_CREATE_CAMPAIGN = [ + { + request: { + query: FUND_CAMPAIGN, + variables: { + id: undefined, + }, + }, + result: { + data: { + getFundById: { + campaigns: [ + { + _id: '1', + name: 'Campaign 1', + fundingGoal: 100, + startDate: '2021-01-01', + endDate: '2021-01-01', + currency: 'USD', + }, + { + _id: '2', + name: 'Campaign 2', + fundingGoal: 200, + startDate: '2021-01-01', + endDate: '2021-01-01', + currency: 'USD', + }, + ], + }, + }, + }, + }, + + { + request: { + query: CREATE_CAMPAIGN_MUTATION, + variables: { + fundId: undefined, + name: 'Campaign 1', + fundingGoal: 100, + startDate: '2024-03-10', + endDate: '2024-03-10', + currency: 'USD', + }, + }, + error: new Error('An error occurred'), + }, +]; +export const MOCKS_ERROR_UPDATE_CAMPAIGN = [ + { + request: { + query: FUND_CAMPAIGN, + variables: { + id: undefined, + }, + }, + result: { + data: { + getFundById: { + campaigns: [ + { + _id: '1', + name: 'Campaign 1', + fundingGoal: 100, + startDate: '2021-01-01', + endDate: '2021-01-01', + currency: 'USD', + }, + { + _id: '2', + name: 'Campaign 2', + fundingGoal: 200, + startDate: '2021-01-01', + endDate: '2021-01-01', + currency: 'USD', + }, + ], + }, + }, + }, + }, + { + request: { + query: UPDATE_CAMPAIGN_MUTATION, + variables: { + id: undefined, + name: 'Campaign 1', + fundingGoal: 100, + startDate: '2024-03-10', + endDate: '2024-03-10', + currency: 'USD', + }, + }, + error: new Error('An error occurred'), + }, +]; +export const MOCKS_ERROR_DELETE_CAMPAIGN = [ + { + request: { + query: FUND_CAMPAIGN, + variables: { + id: undefined, + }, + }, + result: { + data: { + getFundById: { + campaigns: [ + { + _id: '1', + name: 'Campaign 1', + fundingGoal: 100, + startDate: '2021-01-01', + endDate: '2021-01-01', + currency: 'USD', + }, + { + _id: '2', + name: 'Campaign 2', + fundingGoal: 200, + startDate: '2021-01-01', + endDate: '2021-01-01', + currency: 'USD', + }, + ], + }, + }, + }, + }, + { + request: { + query: DELETE_CAMPAIGN_MUTATION, + variables: { + id: '1', + }, + }, + error: new Error('An error occurred'), + }, +]; +export const EMPTY_MOCKS = [ + { + request: { + query: FUND_CAMPAIGN, + variables: { + id: undefined, + }, + }, + result: { + data: { + getFundById: { + campaigns: [], + }, + }, + }, + }, +]; diff --git a/src/screens/OrganizationFunds/FundCreateModal.tsx b/src/screens/OrganizationFunds/FundCreateModal.tsx new file mode 100644 index 0000000000..4dcf32c265 --- /dev/null +++ b/src/screens/OrganizationFunds/FundCreateModal.tsx @@ -0,0 +1,118 @@ +import React from 'react'; +import type { ChangeEvent } from 'react'; +import { Button, Form, Modal } from 'react-bootstrap'; +import type { InterfaceCreateFund } from 'utils/interfaces'; +import styles from './OrganizationFunds.module.css'; + +interface InterfaceFundCreateModal { + fundCreateModalIsOpen: boolean; + hideCreateModal: () => void; + formState: InterfaceCreateFund; + setFormState: (state: React.SetStateAction) => void; + createFundHandler: (e: ChangeEvent) => Promise; + taxDeductible: boolean; + setTaxDeductible: (state: React.SetStateAction) => void; + isDefault: boolean; + setIsDefault: (state: React.SetStateAction) => void; + t: (key: string) => string; +} + +const FundCreateModal: React.FC = ({ + fundCreateModalIsOpen, + hideCreateModal, + formState, + setFormState, + createFundHandler, + taxDeductible, + setTaxDeductible, + isDefault, + setIsDefault, + t, +}) => { + return ( + <> + + +

    {t('fundCreate')}

    + +
    + +
    + + {t('fundName')} + + setFormState({ + ...formState, + fundName: e.target.value, + }) + } + /> + + + {t('fundId')} + + setFormState({ + ...formState, + fundRef: e.target.value, + }) + } + /> + +
    + +
    + + setTaxDeductible(!taxDeductible)} + /> +
    +
    + +
    + + setIsDefault(!isDefault)} + /> +
    +
    +
    + +
    +
    +
    + + ); +}; +export default FundCreateModal; diff --git a/src/screens/OrganizationFunds/FundUpdateModal.tsx b/src/screens/OrganizationFunds/FundUpdateModal.tsx new file mode 100644 index 0000000000..2a351a1c8c --- /dev/null +++ b/src/screens/OrganizationFunds/FundUpdateModal.tsx @@ -0,0 +1,155 @@ +import type { ChangeEvent } from 'react'; +import React from 'react'; +import { Button, Form, Modal } from 'react-bootstrap'; +import type { InterfaceCreateFund } from 'utils/interfaces'; +import styles from './OrganizationFunds.module.css'; + +interface InterfaceFundUpdateModal { + fundUpdateModalIsOpen: boolean; + hideUpdateModal: () => void; + formState: InterfaceCreateFund; + setFormState: (state: React.SetStateAction) => void; + updateFundHandler: (e: ChangeEvent) => Promise; + taxDeductible: boolean; + setTaxDeductible: (state: React.SetStateAction) => void; + isArchived: boolean; + deleteFundHandler: () => Promise; + setIsArchived: (state: React.SetStateAction) => void; + isDefault: boolean; + setIsDefault: (state: React.SetStateAction) => void; + t: (key: string) => string; +} + +const FundUpdateModal: React.FC = ({ + fundUpdateModalIsOpen, + hideUpdateModal, + formState, + setFormState, + updateFundHandler, + taxDeductible, + setTaxDeductible, + isArchived, + deleteFundHandler, + setIsArchived, + isDefault, + setIsDefault, + t, +}) => { + return ( + <> + + +

    {t('manageFund')}

    + +
    + +
    + + {t('fundName')} + + setFormState({ + ...formState, + fundName: e.target.value, + }) + } + /> + + + {t('fundId')} + + setFormState({ + ...formState, + fundRef: e.target.value, + }) + } + /> + + +
    +
    + +
    + + setTaxDeductible(!taxDeductible)} + /> +
    +
    + +
    + + setIsDefault(!isDefault)} + /> +
    +
    +
    +
    + +
    + + setIsArchived(!isArchived)} + /> +
    +
    +
    +
    +
    + + +
    +
    +
    +
    + + ); +}; +export default FundUpdateModal; diff --git a/src/screens/OrganizationFunds/OrganizationFunds.module.css b/src/screens/OrganizationFunds/OrganizationFunds.module.css new file mode 100644 index 0000000000..07e16ad0a8 --- /dev/null +++ b/src/screens/OrganizationFunds/OrganizationFunds.module.css @@ -0,0 +1,177 @@ +.list_box { + height: auto; + overflow-y: auto; + width: 100%; +} + +.inputField { + margin-top: 10px; + margin-bottom: 10px; + background-color: white; + box-shadow: 0 1px 1px #31bb6b; +} + +.inputField > button { + padding-top: 10px; + padding-bottom: 10px; +} + +.dropdown { + background-color: white; + border: 1px solid #31bb6b; + position: relative; + display: inline-block; + margin-top: 10px; + margin-bottom: 10px; + color: #31bb6b; +} + +.createFundBtn { + margin-top: 10px; +} + +.fundName { + font-weight: 600; + cursor: pointer; +} +.fundModal { + max-width: 80vw; + margin-top: 2vh; + margin-left: 13vw; +} + +.modalHeader { + border: none; + padding-bottom: 0; +} + +.label { + color: var(--bs-emphasis-color); +} + +.titlemodal { + font-weight: 600; + font-size: 25px; + margin-top: 1rem; + width: 65%; +} +.greenregbtn { + margin: 1rem 0 0; + margin-top: 15px; + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + padding: 10px 10px; + border-radius: 5px; + background-color: #31bb6b; + width: 100%; + font-size: 16px; + color: white; + outline: none; + font-weight: 600; + cursor: pointer; + transition: + transform 0.2s, + box-shadow 0.2s; + width: 100%; +} + +.manageBtn { + margin: 1rem 0 0; + margin-top: 15px; + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + padding: 10px 10px; + border-radius: 5px; + font-size: 16px; + color: white; + outline: none; + font-weight: 600; + cursor: pointer; + width: 45%; + transition: + transform 0.2s, + box-shadow 0.2s; +} + +.btnsContainer { + display: flex; + margin: 2.5rem 0 2.5rem 0; +} + +.btnsContainer .btnsBlock { + display: flex; +} + +.btnsContainer .btnsBlock div button { + display: flex; + margin-left: 1rem; + justify-content: center; + align-items: center; +} + +.btnsContainer .input { + flex: 1; + position: relative; +} + +.btnsContainer input { + outline: 1px solid var(--bs-gray-400); +} + +.btnsContainer .input button { + width: 52px; +} + +.mainpageright > hr { + margin-top: 20px; + width: 100%; + margin-left: -15px; + margin-right: -15px; + margin-bottom: 20px; +} + +@media (max-width: 1020px) { + .btnsContainer { + flex-direction: column; + margin: 1.5rem 0; + } + + .btnsContainer .btnsBlock { + margin: 1.5rem 0 0 0; + justify-content: space-between; + } + + .btnsContainer .btnsBlock div button { + margin: 0; + } + + .createFundBtn { + margin-top: 0; + } +} + +@media screen and (max-width: 575.5px) { + .mainpageright { + width: 98%; + } +} + +/* For mobile devices */ + +@media (max-width: 520px) { + .btnsContainer { + margin-bottom: 0; + } + + .btnsContainer .btnsBlock { + display: block; + margin-top: 1rem; + margin-right: 0; + } + + .btnsContainer .btnsBlock div button { + margin-bottom: 1rem; + margin-right: 0; + width: 100%; + } +} diff --git a/src/screens/OrganizationFunds/OrganizationFunds.test.tsx b/src/screens/OrganizationFunds/OrganizationFunds.test.tsx new file mode 100644 index 0000000000..93be2c281c --- /dev/null +++ b/src/screens/OrganizationFunds/OrganizationFunds.test.tsx @@ -0,0 +1,407 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/client/testing'; +import { + act, + fireEvent, + render, + screen, + waitFor, + waitForElementToBeRemoved, +} from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { toast } from 'react-toastify'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18nForTest from 'utils/i18nForTest'; +import OrganizationFunds from './OrganizationFunds'; +import { + MOCKS, + MOCKS_ERROR_CREATE_FUND, + MOCKS_ERROR_ORGANIZATIONS_FUNDS, + MOCKS_ERROR_REMOVE_FUND, + MOCKS_ERROR_UPDATE_FUND, + NO_FUNDS, +} from './OrganizationFundsMocks'; +const mockNavigate = jest.fn(); +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useNavigate: () => mockNavigate, +})); +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} +const link1 = new StaticMockLink(MOCKS, true); +const link2 = new StaticMockLink(MOCKS_ERROR_ORGANIZATIONS_FUNDS, true); +const link3 = new StaticMockLink(MOCKS_ERROR_CREATE_FUND, true); +const link4 = new StaticMockLink(MOCKS_ERROR_UPDATE_FUND, true); +const link5 = new StaticMockLink(MOCKS_ERROR_REMOVE_FUND, true); +const link6 = new StaticMockLink(NO_FUNDS, true); + +const translations = JSON.parse( + JSON.stringify(i18nForTest.getDataByLanguage('en')?.translation.funds), +); +describe('Testing OrganizationFunds screen', () => { + const formData = { + fundName: 'Test Fund', + fundRef: '1', + }; + it("loads the OrganizationFunds screen and it's components", async () => { + const { getByText } = render( + + + + + {} + + + + , + ); + await wait(); + await waitFor(() => { + expect(getByText(translations.createFund)).toBeInTheDocument(); + }); + }); + it("renders the OrganizationFunds screen and it's components with error", async () => { + const { queryByText } = render( + + + + + {} + + + + , + ); + await wait(); + await waitFor(() => { + expect(queryByText(translations.createFund)).not.toBeInTheDocument(); + }); + }); + it('renders the Error component', async () => { + render( + + + + + {} + + + + , + ); + await wait(); + await waitFor(() => { + expect(screen.getByTestId('errorMsg')).toBeInTheDocument(); + }); + }); + it('renders the funds component based on fund type', async () => { + render( + + + + + {} + + + + , + ); + await wait(); + await waitFor(() => { + expect(screen.getAllByTestId('fundtype')[0]).toBeInTheDocument(); + }); + await waitFor(() => { + expect(screen.getAllByTestId('fundtype')[0]).toHaveTextContent( + translations.nonArchive, + ); + }); + expect(screen.getAllByTestId('fundtype')[1]).toHaveTextContent( + translations.archived, + ); + }); + it("opens and closes the 'Create Fund' modal", async () => { + render( + + + + + {} + + + + , + ); + await wait(); + await waitFor(() => { + expect(screen.getByTestId('createFundBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('createFundBtn')); + await waitFor(() => { + return expect( + screen.findByTestId('createFundModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('setTaxDeductibleSwitch')); + userEvent.click(screen.getByTestId('setDefaultSwitch')); + userEvent.click(screen.getByTestId('createFundModalCloseBtn')); + await waitForElementToBeRemoved(() => + screen.queryByTestId('createFundModalCloseBtn'), + ); + }); + it('noFunds to be in the document', async () => { + render( + + + + + {} + + + + , + ); + await wait(); + await waitFor(() => { + expect(screen.getByText(translations.noFundsFound)).toBeInTheDocument(); + }); + }); + it('creates a new fund', async () => { + render( + + + + + {} + + + + , + ); + await wait(); + await waitFor(() => { + expect(screen.getByTestId('createFundBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('createFundBtn')); + await waitFor(() => { + return expect( + screen.findByTestId('createFundModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.type( + screen.getByPlaceholderText(translations.enterfundName), + formData.fundName, + ); + userEvent.type( + screen.getByPlaceholderText(translations.enterfundId), + formData.fundRef, + ); + userEvent.click(screen.getByTestId('setTaxDeductibleSwitch')); + userEvent.click(screen.getByTestId('setDefaultSwitch')); + userEvent.click(screen.getByTestId('setTaxDeductibleSwitch')); + userEvent.click(screen.getByTestId('setDefaultSwitch')); + await wait(); + userEvent.click(screen.getByTestId('createFundFormSubmitBtn')); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.fundCreated); + }); + }); + it('updates fund successfully', async () => { + render( + + + + + {} + + + + , + ); + await wait(); + userEvent.click(screen.getAllByTestId('editFundBtn')[0]); + await wait(); + userEvent.clear(screen.getByTestId('fundNameInput')); + userEvent.clear(screen.getByTestId('fundIdInput')); + userEvent.type(screen.getByTestId('fundNameInput'), 'Test Fund'); + userEvent.type(screen.getByTestId('fundIdInput'), '1'); + expect(screen.getByTestId('taxDeductibleSwitch')).toBeInTheDocument(); + expect(screen.getByTestId('defaultSwitch')).toBeInTheDocument(); + expect(screen.getByTestId('archivedSwitch')).toBeInTheDocument(); + expect(screen.getByTestId('updateFormBtn')).toBeInTheDocument(); + userEvent.click(screen.getByTestId('taxDeductibleSwitch')); + userEvent.click(screen.getByTestId('defaultSwitch')); + userEvent.click(screen.getByTestId('archivedSwitch')); + await wait(); + userEvent.click(screen.getByTestId('updateFormBtn')); + await wait(); + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.fundUpdated); + }); + }); + it('toast error on unsuccessful fund creation', async () => { + render( + + + + + {} + + + + , + ); + await wait(); + await waitFor(() => { + expect(screen.getByTestId('createFundBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('createFundBtn')); + await waitFor(() => { + return expect( + screen.findByTestId('createFundModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.type( + screen.getByPlaceholderText(translations.enterfundName), + formData.fundName, + ); + userEvent.type( + screen.getByPlaceholderText(translations.enterfundId), + formData.fundRef, + ); + userEvent.click(screen.getByTestId('createFundFormSubmitBtn')); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); + it('toast error on unsuccessful fund update', async () => { + render( + + + + + {} + + + + , + ); + await wait(); + await waitFor(() => { + expect(screen.getAllByTestId('editFundBtn')[0]).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('editFundBtn')[0]); + await waitFor(() => { + return expect( + screen.findByTestId('editFundModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.type( + screen.getByPlaceholderText(translations.enterfundName), + 'Test Fund Updated', + ); + userEvent.click(screen.getByTestId('updateFormBtn')); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); + it('redirects to campaign screen when clicked on fund name', async () => { + render( + + + + + {} + + + + , + ); + await wait(); + await waitFor(() => { + expect(screen.getAllByTestId('fundName')[0]).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('fundName')[0]); + await waitFor(() => { + expect(mockNavigate).toBeCalledWith('/orgfundcampaign/undefined/1'); + }); + }); + it('delete fund succesfully', async () => { + render( + + + + + {} + + + + , + ); + await wait(); + userEvent.click(screen.getAllByTestId('editFundBtn')[0]); + await wait(); + userEvent.click(screen.getByTestId('fundDeleteModalDeleteBtn')); + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.fundDeleted); + }); + }); + it('throws error on unsuccessful fund deletion', async () => { + render( + + + + + {} + + + + , + ); + await wait(); + userEvent.click(screen.getAllByTestId('editFundBtn')[0]); + await wait(); + userEvent.click(screen.getByTestId('fundDeleteModalDeleteBtn')); + await waitFor(() => { + expect(toast.error).toBeCalled(); + }); + }); + it('search funds by name', async () => { + render( + + + + + {} + + + + , + ); + await wait(); + userEvent.click(screen.getAllByTestId('editFundBtn')[0]); + await wait(); + userEvent.click(screen.getByTestId('editFundModalCloseBtn')); + await wait(); + userEvent.type(screen.getByTestId('searchFullName'), 'Funndds'); + await wait(); + userEvent.click(screen.getByTestId('searchBtn')); + }); +}); diff --git a/src/screens/OrganizationFunds/OrganizationFunds.tsx b/src/screens/OrganizationFunds/OrganizationFunds.tsx new file mode 100644 index 0000000000..2f67f61edc --- /dev/null +++ b/src/screens/OrganizationFunds/OrganizationFunds.tsx @@ -0,0 +1,424 @@ +/*eslint-disable*/ +import { useMutation, useQuery } from '@apollo/client'; +import { Search, WarningAmberRounded } from '@mui/icons-material'; +import { + CREATE_FUND_MUTATION, + REMOVE_FUND_MUTATION, + UPDATE_FUND_MUTATION, +} from 'GraphQl/Mutations/FundMutation'; +import Loader from 'components/Loader/Loader'; +import { useState, type ChangeEvent } from 'react'; +import { Button, Col, Dropdown, Form, Row } from 'react-bootstrap'; +import { useTranslation } from 'react-i18next'; +import { useNavigate, useParams } from 'react-router-dom'; +import { toast } from 'react-toastify'; +import type { + InterfaceCreateFund, + InterfaceFundInfo, + InterfaceQueryOrganizationFunds, +} from 'utils/interfaces'; +import FundCreateModal from './FundCreateModal'; +import FundUpdateModal from './FundUpdateModal'; +import FilterAltOutlinedIcon from '@mui/icons-material/FilterAltOutlined'; +import styles from './OrganizationFunds.module.css'; +import { + Paper, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + styled, + tableCellClasses, +} from '@mui/material'; +import dayjs from 'dayjs'; +import { FUND_LIST } from 'GraphQl/Queries/fundQueries'; + +const StyledTableCell = styled(TableCell)(({ theme }) => ({ + [`&.${tableCellClasses.head}`]: { + backgroundColor: ['#31bb6b', '!important'], + color: theme.palette.common.white, + }, + [`&.${tableCellClasses.body}`]: { + fontSize: 14, + }, +})); + +const StyledTableRow = styled(TableRow)(() => ({ + '&:last-child td, &:last-child th': { + border: 0, + }, +})); + +const organizationFunds = (): JSX.Element => { + const { t } = useTranslation('translation', { + keyPrefix: 'funds', + }); + + const { orgId: currentUrl } = useParams(); + const navigate = useNavigate(); + const [fundCreateModalIsOpen, setFundCreateModalIsOpen] = + useState(false); + const [fundUpdateModalIsOpen, setFundUpdateModalIsOpen] = + useState(false); + + const [taxDeductible, setTaxDeductible] = useState(true); + const [isArchived, setIsArchived] = useState(false); + const [isDefault, setIsDefault] = useState(false); + const [fund, setFund] = useState(null); + const [formState, setFormState] = useState({ + fundName: '', + fundRef: '', + }); + + const { + data: fundData, + loading: fundLoading, + error: fundError, + refetch: refetchFunds, + }: { + data?: { + fundsByOrganization: InterfaceQueryOrganizationFunds[]; + }; + loading: boolean; + error?: Error | undefined; + refetch: any; + } = useQuery(FUND_LIST, { + variables: { + organizationId: currentUrl, + }, + }); + + const [fullName, setFullName] = useState(''); + const handleSearch = (): void => { + refetchFunds({ organizationId: currentUrl, filter: fullName }); + }; + + const [createFund] = useMutation(CREATE_FUND_MUTATION); + const [updateFund] = useMutation(UPDATE_FUND_MUTATION); + const [deleteFund] = useMutation(REMOVE_FUND_MUTATION); + + const showCreateModal = (): void => { + setFundCreateModalIsOpen(!fundCreateModalIsOpen); + }; + const hideCreateModal = (): void => { + setFundCreateModalIsOpen(!fundCreateModalIsOpen); + }; + const showUpdateModal = (): void => { + setFundUpdateModalIsOpen(!fundUpdateModalIsOpen); + }; + const hideUpdateModal = (): void => { + setFundUpdateModalIsOpen(!fundUpdateModalIsOpen); + }; + const toggleDeleteModal = (): void => { + setFundUpdateModalIsOpen(!fundUpdateModalIsOpen); + }; + const handleEditClick = (fund: InterfaceFundInfo): void => { + setFormState({ + fundName: fund.name, + fundRef: fund.refrenceNumber, + }); + setTaxDeductible(fund.taxDeductible); + setIsArchived(fund.isArchived); + setIsDefault(fund.isDefault); + setFund(fund); + showUpdateModal(); + }; + const createFundHandler = async ( + e: ChangeEvent, + ): Promise => { + e.preventDefault(); + try { + await createFund({ + variables: { + name: formState.fundName, + refrenceNumber: formState.fundRef, + organizationId: currentUrl, + taxDeductible: taxDeductible, + isArchived: isArchived, + isDefault: isDefault, + }, + }); + + setFormState({ + fundName: '', + fundRef: '', + }); + toast.success(t('fundCreated')); + refetchFunds(); + hideCreateModal(); + } catch (error: unknown) { + if (error instanceof Error) { + toast.error(error.message); + console.log(error.message); + } + } + }; + const updateFundHandler = async ( + e: ChangeEvent, + ): Promise => { + e.preventDefault(); + try { + const updatedFields: { [key: string]: any } = {}; + if (formState.fundName != fund?.name) { + updatedFields.name = formState.fundName; + } + if (formState.fundRef != fund?.refrenceNumber) { + updatedFields.refrenceNumber = formState.fundRef; + } + if (taxDeductible != fund?.taxDeductible) { + updatedFields.taxDeductible = taxDeductible; + } + if (isArchived != fund?.isArchived) { + updatedFields.isArchived = isArchived; + } + if (isDefault != fund?.isDefault) { + updatedFields.isDefault = isDefault; + } + + await updateFund({ + variables: { + id: fund?._id, + ...updatedFields, + }, + }); + setFormState({ + fundName: '', + fundRef: '', + }); + refetchFunds(); + hideUpdateModal(); + toast.success(t('fundUpdated')); + } catch (error: unknown) { + if (error instanceof Error) { + toast.error(error.message); + console.log(error.message); + } + } + }; + const deleteFundHandler = async (): Promise => { + try { + await deleteFund({ + variables: { + id: fund?._id, + }, + }); + refetchFunds(); + toggleDeleteModal(); + toast.success(t('fundDeleted')); + } catch (error: unknown) { + if (error instanceof Error) { + toast.error(error.message); + console.log(error.message); + } + } + }; + + const handleClick = (fundId: String) => { + navigate(`/orgfundcampaign/${currentUrl}/${fundId}`); + }; + + if (fundLoading) { + return ; + } + if (fundError) { + return ( +
    +
    + +
    + Error occured while loading Funds +
    + {fundError.message} +
    +
    +
    + ); + } + + return ( + <> + +
    +
    +
    + ) => { + setFullName(e.target.value); + }} + data-testid="searchFullName" + /> + +
    +
    +
    + + + + {t('filter')} + + +
    +
    + +
    +
    +
    +
    +
    +
    +
    + {fundData?.fundsByOrganization && + fundData.fundsByOrganization.length > 0 ? ( +
    + + + + + # + + {t('fundName')} + + + {t('createdBy')} + + + {t('createdOn')} + + + {t('status')} + + + {t('manageFund')} + + + + + {fundData.fundsByOrganization.map( + (fund: any, index: number) => ( + + + {index + 1} + + handleClick(fund._id)} + > + + {fund.name} + + + + {fund.creator.firstName} {fund.creator.lastName} + + + {dayjs(fund.createdAt).format('DD/MM/YYYY')} + + + + + + + + + ), + )} + +
    +
    +
    + ) : ( +
    +
    {t('noFundsFound')}
    +
    + )} +
    + {/* + + {/* +
    + + ); +}; + +export default organizationFunds; diff --git a/src/screens/OrganizationFunds/OrganizationFundsMocks.ts b/src/screens/OrganizationFunds/OrganizationFundsMocks.ts new file mode 100644 index 0000000000..cb1e07d78f --- /dev/null +++ b/src/screens/OrganizationFunds/OrganizationFundsMocks.ts @@ -0,0 +1,368 @@ +import { + CREATE_FUND_MUTATION, + REMOVE_FUND_MUTATION, + UPDATE_FUND_MUTATION, +} from 'GraphQl/Mutations/FundMutation'; +import { FUND_LIST } from 'GraphQl/Queries/fundQueries'; + +export const MOCKS = [ + { + request: { + query: FUND_LIST, + variables: { + id: undefined, + }, + }, + result: { + data: { + fundsByOrganization: [ + { + _id: '1', + name: 'Fund 1', + refrenceNumber: '123', + taxDeductible: true, + isArchived: false, + isDefault: false, + createdAt: '2021-07-01T00:00:00.000Z', + organizationId: 'organizationId1', + creator: { + _id: 'creatorId1', + firstName: 'John', + lastName: 'Doe', + }, + }, + { + _id: '99', + name: 'Funndds', + refrenceNumber: '1234', + taxDeductible: true, + isArchived: true, + isDefault: false, + createdAt: '2021-07-01T00:00:00.000Z', + organizationId: 'organizationId1', + creator: { + _id: 'creatorId1', + firstName: 'John', + lastName: 'Doe', + }, + }, + ], + }, + }, + }, + { + request: { + query: CREATE_FUND_MUTATION, + variables: { + name: 'Test Fund', + refrenceNumber: '1', + taxDeductible: true, + isArchived: false, + isDefault: false, + organizationId: undefined, + }, + }, + result: { + data: { + createFund: { + _id: '3', + }, + }, + }, + }, + { + request: { + query: UPDATE_FUND_MUTATION, + variables: { + id: '1', + name: 'Test Fund', + refrenceNumber: '1', + taxDeductible: false, + isArchived: true, + isDefault: true, + }, + }, + result: { + data: { + updateFund: { + _id: '1', + }, + }, + }, + }, + { + request: { + query: REMOVE_FUND_MUTATION, + variables: { + id: '1', + }, + }, + result: { + data: { + removeFund: { + _id: '1', + }, + }, + }, + }, +]; +export const NO_FUNDS = [ + { + request: { + query: FUND_LIST, + variables: { + id: undefined, + }, + }, + result: { + data: { + fundsByOrganization: [], + }, + }, + }, +]; +export const MOCKS_ERROR_ORGANIZATIONS_FUNDS = [ + { + request: { + query: FUND_LIST, + variables: { + organizationId: '1', + }, + }, + error: new Error('Mock graphql error'), + }, +]; +export const MOCKS_ERROR_CREATE_FUND = [ + { + request: { + query: FUND_LIST, + variables: { + id: undefined, + }, + }, + result: { + data: { + fundsByOrganization: [ + { + _id: '1', + name: 'Fund 1', + refrenceNumber: '123', + taxDeductible: true, + isArchived: false, + isDefault: false, + createdAt: '2021-07-01T00:00:00.000Z', + organizationId: 'organizationId1', + creator: { + _id: 'creatorId1', + firstName: 'John', + lastName: 'Doe', + }, + }, + { + _id: '2', + name: 'Fund 2', + refrenceNumber: '456', + taxDeductible: false, + isArchived: false, + isDefault: false, + createdAt: '2021-07-01T00:00:00.000Z', + organizationId: 'organizationId2', + creator: { + _id: 'creatorId2', + firstName: 'Jane', + lastName: 'Doe', + }, + }, + ], + }, + }, + }, + { + request: { + query: CREATE_FUND_MUTATION, + variables: { + name: 'Fund 3', + refrenceNumber: '789', + taxDeductible: true, + isArchived: false, + isDefault: false, + organizationId: undefined, + }, + }, + error: new Error('Mock graphql error'), + }, +]; +export const MOCKS_ERROR_UPDATE_FUND = [ + { + request: { + query: FUND_LIST, + variables: { + id: undefined, + }, + }, + result: { + data: { + fundsByOrganization: [ + { + _id: '1', + name: 'Fund 1', + refrenceNumber: '123', + taxDeductible: true, + isArchived: false, + isDefault: false, + createdAt: '2021-07-01T00:00:00.000Z', + organizationId: 'organizationId1', + creator: { + _id: 'creatorId1', + firstName: 'John', + lastName: 'Doe', + }, + }, + { + _id: '2', + name: 'Fund 2', + refrenceNumber: '456', + taxDeductible: false, + isArchived: false, + isDefault: false, + createdAt: '2021-07-01T00:00:00.000Z', + organizationId: 'organizationId2', + creator: { + _id: 'creatorId2', + firstName: 'Jane', + lastName: 'Doe', + }, + }, + ], + }, + }, + }, + { + request: { + query: CREATE_FUND_MUTATION, + variables: { + name: 'Fund 3', + refrenceNumber: '789', + taxDeductible: true, + isArchived: false, + isDefault: false, + organizationId: undefined, + }, + }, + result: { + data: { + createFund: { + _id: '3', + }, + }, + }, + }, + { + request: { + query: UPDATE_FUND_MUTATION, + variables: { + id: undefined, + name: 'Fund 1', + refrenceNumber: '789', + taxDeductible: true, + isArchived: false, + isDefault: false, + }, + }, + error: new Error('Mock graphql error'), + }, +]; +export const MOCKS_ERROR_REMOVE_FUND = [ + { + request: { + query: FUND_LIST, + variables: { + id: undefined, + }, + }, + result: { + data: { + fundsByOrganization: [ + { + _id: '3', + name: 'Fund 1', + refrenceNumber: '123', + taxDeductible: true, + isArchived: false, + isDefault: false, + createdAt: '2021-07-01T00:00:00.000Z', + organizationId: 'organizationId1', + creator: { + _id: 'creatorId1', + firstName: 'John', + lastName: 'Doe', + }, + }, + { + _id: '2', + name: 'Fund 2', + refrenceNumber: '456', + taxDeductible: false, + isArchived: false, + isDefault: false, + createdAt: '2021-07-01T00:00:00.000Z', + organizationId: 'organizationId2', + creator: { + _id: 'creatorId2', + firstName: 'Jane', + lastName: 'Doe', + }, + }, + ], + }, + }, + }, + { + request: { + query: CREATE_FUND_MUTATION, + variables: { + name: 'Fund 3', + refrenceNumber: '789', + taxDeductible: true, + isArchived: false, + isDefault: false, + organizationId: undefined, + }, + }, + result: { + data: { + createFund: { + _id: '3', + }, + }, + }, + }, + { + request: { + query: UPDATE_FUND_MUTATION, + variables: { + id: undefined, + name: 'Fund 1', + taxDeductible: true, + isArchived: false, + isDefault: false, + }, + }, + result: { + data: { + updateFund: { + _id: '1', + }, + }, + }, + }, + { + request: { + query: REMOVE_FUND_MUTATION, + variables: { + id: undefined, + }, + }, + error: new Error('Mock graphql error'), + }, +]; diff --git a/src/screens/OrganizationPeople/AddMember.tsx b/src/screens/OrganizationPeople/AddMember.tsx new file mode 100644 index 0000000000..696436c2bc --- /dev/null +++ b/src/screens/OrganizationPeople/AddMember.tsx @@ -0,0 +1,562 @@ +import { useLazyQuery, useMutation, useQuery } from '@apollo/client'; +import { Search } from '@mui/icons-material'; +import EmailOutlinedIcon from '@mui/icons-material/EmailOutlined'; +import Paper from '@mui/material/Paper'; +import Table from '@mui/material/Table'; +import TableBody from '@mui/material/TableBody'; +import TableCell, { tableCellClasses } from '@mui/material/TableCell'; +import TableContainer from '@mui/material/TableContainer'; +import TableHead from '@mui/material/TableHead'; +import TableRow from '@mui/material/TableRow'; +import { styled } from '@mui/material/styles'; +import { + ADD_MEMBER_MUTATION, + SIGNUP_MUTATION, +} from 'GraphQl/Mutations/mutations'; +import { + ORGANIZATIONS_LIST, + ORGANIZATIONS_MEMBER_CONNECTION_LIST, + USERS_CONNECTION_LIST, +} from 'GraphQl/Queries/Queries'; +import Loader from 'components/Loader/Loader'; +import type { ChangeEvent } from 'react'; +import React, { useEffect, useState } from 'react'; +import { Button, Dropdown, Form, InputGroup, Modal } from 'react-bootstrap'; +import { useTranslation } from 'react-i18next'; +import { Link, useParams } from 'react-router-dom'; +import { toast } from 'react-toastify'; +import { errorHandler } from 'utils/errorHandler'; +import type { + InterfaceQueryOrganizationsListObject, + InterfaceQueryUserListItem, +} from 'utils/interfaces'; +import styles from './OrganizationPeople.module.css'; + +const StyledTableCell = styled(TableCell)(({ theme }) => ({ + [`&.${tableCellClasses.head}`]: { + backgroundColor: ['#31bb6b', '!important'], + color: theme.palette.common.white, + }, + [`&.${tableCellClasses.body}`]: { + fontSize: 14, + }, +})); + +const StyledTableRow = styled(TableRow)(() => ({ + '&:last-child td, &:last-child th': { + border: 0, + }, +})); + +function AddMember(): JSX.Element { + const { t: translateOrgPeople } = useTranslation('translation', { + keyPrefix: 'organizationPeople', + }); + + const { t: translateAddMember } = useTranslation('translation', { + keyPrefix: 'addMember', + }); + + document.title = translateOrgPeople('title'); + + const [addUserModalisOpen, setAddUserModalIsOpen] = useState(false); + + function openAddUserModal(): void { + setAddUserModalIsOpen(true); + } + + const toggleDialogModal = /* istanbul ignore next */ (): void => + setAddUserModalIsOpen(!addUserModalisOpen); + + const [createNewUserModalisOpen, setCreateNewUserModalIsOpen] = + useState(false); + function openCreateNewUserModal(): void { + setCreateNewUserModalIsOpen(true); + } + + function closeCreateNewUserModal(): void { + setCreateNewUserModalIsOpen(false); + } + const toggleCreateNewUserModal = /* istanbul ignore next */ (): void => + setCreateNewUserModalIsOpen(!addUserModalisOpen); + + const [addMember] = useMutation(ADD_MEMBER_MUTATION); + + const createMember = async (userId: string): Promise => { + try { + await addMember({ + variables: { + userid: userId, + orgid: currentUrl, + }, + }); + toast.success('Member added to the organization.'); + memberRefetch({ + orgId: currentUrl, + }); + } catch (error: unknown) { + if (error instanceof Error) { + toast.error(error.message); + console.log(error.message); + } + } + }; + + const { orgId: currentUrl } = useParams(); + + const [showPassword, setShowPassword] = useState(false); + const [showConfirmPassword, setShowConfirmPassword] = + useState(false); + + const togglePassword = (): void => setShowPassword(!showPassword); + const toggleConfirmPassword = (): void => + setShowConfirmPassword(!showConfirmPassword); + + const [userName, setUserName] = useState(''); + + const { + data: organizationData, + }: { + data?: { + organizations: InterfaceQueryOrganizationsListObject[]; + }; + } = useQuery(ORGANIZATIONS_LIST, { + variables: { id: currentUrl }, + }); + + const getMembersId = (): string[] => { + if (memberData) { + const ids = memberData?.organizationsMemberConnection.edges.map( + (member: { _id: string }) => member._id, + ); + return ids; + } + return []; + }; + + const { data: memberData, refetch: memberRefetch } = useLazyQuery( + ORGANIZATIONS_MEMBER_CONNECTION_LIST, + { + variables: { + firstName_contains: '', + lastName_contains: '', + orgId: currentUrl, + }, + }, + )[1]; + + const { + data: allUsersData, + loading: allUsersLoading, + refetch: allUsersRefetch, + } = useQuery(USERS_CONNECTION_LIST, { + variables: { + id_not_in: getMembersId(), + firstName_contains: '', + lastName_contains: '', + }, + }); + + useEffect(() => { + memberRefetch({ + orgId: currentUrl, + }); + }); + + const [registerMutation] = useMutation(SIGNUP_MUTATION); + + const [createUserVariables, setCreateUserVariables] = React.useState({ + firstName: '', + lastName: '', + email: '', + password: '', + confirmPassword: '', + }); + + const handleCreateUser = async (): Promise => { + if ( + !( + createUserVariables.email && + createUserVariables.password && + createUserVariables.firstName && + createUserVariables.lastName + ) + ) { + toast.error(translateOrgPeople('invalidDetailsMessage')); + } else if ( + createUserVariables.password !== createUserVariables.confirmPassword + ) { + toast.error(translateOrgPeople('passwordNotMatch')); + } else { + try { + const registeredUser = await registerMutation({ + variables: { + firstName: createUserVariables.firstName, + lastName: createUserVariables.lastName, + email: createUserVariables.email, + password: createUserVariables.password, + orgId: currentUrl, + }, + }); + const createdUserId = registeredUser?.data.signUp.user._id; + + await createMember(createdUserId); + + closeCreateNewUserModal(); + + /* istanbul ignore next */ + setCreateUserVariables({ + firstName: '', + lastName: '', + email: '', + password: '', + confirmPassword: '', + }); + } catch (error: unknown) { + /* istanbul ignore next */ + errorHandler(translateOrgPeople, error); + } + } + }; + + /* istanbul ignore next */ + const handleFirstName = (e: ChangeEvent): void => { + const firstName = e.target.value; + + setCreateUserVariables({ ...createUserVariables, firstName }); + }; + + /* istanbul ignore next */ + const handleLastName = (e: ChangeEvent): void => { + const lastName = e.target.value; + + setCreateUserVariables({ ...createUserVariables, lastName }); + }; + + /* istanbul ignore next */ + const handleEmailChange = (e: ChangeEvent): void => { + const email = e.target.value; + + setCreateUserVariables({ ...createUserVariables, email }); + }; + + /* istanbul ignore next */ + const handlePasswordChange = (e: ChangeEvent): void => { + const password = e.target.value; + + setCreateUserVariables({ ...createUserVariables, password }); + }; + + /* istanbul ignore next */ + const handleConfirmPasswordChange = ( + e: ChangeEvent, + ): void => { + const confirmPassword = e.target.value; + + setCreateUserVariables({ ...createUserVariables, confirmPassword }); + }; + + const handleUserModalSearchChange = (e: React.FormEvent): void => { + e.preventDefault(); + /* istanbul ignore next */ + const [firstName, lastName] = userName.split(' '); + + const newFilterData = { + firstName_contains: firstName || '', + lastName_contains: lastName || '', + }; + + allUsersRefetch({ + ...newFilterData, + }); + }; + + return ( + <> + + + {translateOrgPeople('addMembers')} + + + { + openAddUserModal(); + }} + > + + {translateOrgPeople('existingUser')} + + + { + openCreateNewUserModal(); + }} + > + + + + + + + + {translateOrgPeople('addMembers')} + + + {allUsersLoading ? ( + <> + + + ) : ( + <> +
    +
    + { + const { value } = e.target; + setUserName(value); + }} + /> + + +
    + + + + + # + + {translateAddMember('user')} + + + {translateAddMember('addMember')} + + + + + {allUsersData && + allUsersData.users.length > 0 && + allUsersData.users.map( + ( + userDetails: InterfaceQueryUserListItem, + index: number, + ) => ( + + + {index + 1} + + + + {userDetails.user.firstName + + ' ' + + userDetails.user.lastName} +
    + {userDetails.user.email} + +
    + + + +
    + ), + )} +
    +
    +
    + + )} +
    +
    + + + + Create User + + +
    +
    +
    +
    {translateOrgPeople('firstName')}
    + + + +
    +
    +
    {translateOrgPeople('lastName')}
    + + + +
    +
    +
    {translateOrgPeople('emailAddress')}
    + + + + + + +
    {translateOrgPeople('password')}
    + + + + {showPassword ? ( + + ) : ( + + )} + + +
    {translateOrgPeople('confirmPassword')}
    + + + + {showConfirmPassword ? ( + + ) : ( + + )} + + +
    {translateOrgPeople('organization')}
    + + + +
    +
    + + +
    +
    +
    + + ); +} + +export default AddMember; +// | typeof ORGANIZATIONS_MEMBER_CONNECTION_LIST +// | typeof ORGANIZATIONS_LIST +// | typeof USER_LIST_FOR_TABLE +// | typeof ADD_MEMBER_MUTATION; +// { +// id?: string; +// orgId?: string; +// orgid?: string; +// fristNameContains?: string; +// lastNameContains?: string; +// firstName_contains?: string; +// lastName_contains?: string; +// id_not_in?: string[]; +// userid?: string; +// }; diff --git a/src/screens/OrganizationPeople/MockDataTypes.ts b/src/screens/OrganizationPeople/MockDataTypes.ts new file mode 100644 index 0000000000..c12bb05531 --- /dev/null +++ b/src/screens/OrganizationPeople/MockDataTypes.ts @@ -0,0 +1,77 @@ +import type { DocumentNode } from 'graphql'; +import type { InterfaceQueryOrganizationsListObject } from 'utils/interfaces'; +type User = { + __typename: string; + firstName: string; + lastName: string; + image: string | null; + _id: string; + email: string; + createdAt: string; + joinedOrganizations: { + __typename: string; + _id: string; + name?: string; + creator?: { + _id: string; + firstName: string; + lastName: string; + email: string; + image: null; + createdAt: string; + }; + }[]; +}; +type Edge = { + _id?: string; + firstName?: string; + lastName?: string; + image?: string | null; + email?: string; + createdAt?: string; + user?: Edge; +}; +export type TestMock = { + request: { + query: DocumentNode; + variables: { + id?: string; + orgId?: string; + orgid?: string; + firstNameContains?: string; + lastNameContains?: string; + firstName_contains?: string; + lastName_contains?: string; + id_not_in?: string[]; + userid?: string; + firstName?: string; + lastName?: string; + email?: string; + password?: string; + }; + }; + result: { + __typename?: string; + data: { + __typename?: string; + createMember?: { + __typename: string; + _id: string; + }; + signUp?: { + user?: { + _id: string; + }; + accessToken?: string; + refreshToken?: string; + }; + users?: { user?: User }[]; + organizations?: InterfaceQueryOrganizationsListObject[]; + organizationsMemberConnection?: { + edges?: Edge[]; + user?: Edge[]; + }; + }; + }; + newData?: () => TestMock['result']; +}; diff --git a/src/screens/OrganizationPeople/OrganizationPeople.module.css b/src/screens/OrganizationPeople/OrganizationPeople.module.css index 13972524d7..4442bdb58f 100644 --- a/src/screens/OrganizationPeople/OrganizationPeople.module.css +++ b/src/screens/OrganizationPeople/OrganizationPeople.module.css @@ -1,257 +1,102 @@ -.navbarbg { - height: 60px; +@media screen and (max-width: 575.5px) { + .mainpageright { + width: 98%; + } +} +.modalContent { + width: 670px; + max-width: 680px; +} +.dropdown { background-color: white; - display: flex; - margin-bottom: 30px; - z-index: 1; + border: 1px solid #31bb6b; + position: relative; + display: inline-block; + margin-top: 10px; + margin-bottom: 10px; + color: #31bb6b; +} +.input { + flex: 1; position: relative; - flex-direction: row; - justify-content: space-between; - box-shadow: 0px 0px 8px 2px #c8c8c8; } -.logo { - color: #707070; - margin-left: 0; +.btnsContainer { display: flex; - align-items: center; - text-decoration: none; + margin: 2.5rem 0 2.5rem 0; } -.logo img { - margin-top: 0px; - margin-left: 10px; - height: 64px; - width: 70px; +.btnsContainer .btnsBlock { + display: flex; } -.logo > strong { - line-height: 1.5rem; - margin-left: -5px; - font-family: sans-serif; - font-size: 19px; - color: #707070; -} -.mainpage { +.btnsContainer .btnsBlock button { + margin-left: 1rem; display: flex; - flex-direction: row; -} -.sidebar { - z-index: 0; - padding-top: 10px; - margin: 0; - height: 100%; -} -.sidebar:after { - content: ''; - background-color: #f7f7f7; - position: absolute; - width: 2px; - height: 600px; - top: 10px; - left: 94%; - display: block; -} -.sidebarsticky { - padding-left: 45px; -} -.sidebarsticky > p { - margin-top: -10px; + justify-content: center; + align-items: center; } -.navitem { - padding-left: 27%; - padding-top: 12px; - padding-bottom: 12px; - cursor: pointer; +.btnsContainer .input { + flex: 1; + position: relative; } -.logintitle { - color: #707070; - font-weight: 600; - font-size: 20px; - margin-bottom: 30px; - padding-bottom: 5px; - border-bottom: 3px solid #31bb6b; - width: 15%; -} -.searchtitle { - color: #707070; - font-weight: 600; - font-size: 20px; - margin-bottom: 20px; - padding-bottom: 5px; - border-bottom: 3px solid #31bb6b; - width: 60%; -} -.justifysp { - display: flex; - justify-content: space-between; -} -@media screen and (max-width: 575.5px) { - .justifysp { - padding-left: 55px; - display: flex; - justify-content: space-between; - width: 100%; - } +input { + outline: 1px solid var(--bs-gray-400); } -.logintitleadmin { - color: #707070; - font-weight: 600; - font-size: 18px; - margin-top: 50px; - margin-bottom: 40px; - padding-bottom: 5px; - border-bottom: 3px solid #31bb6b; - width: 40%; +.btnsContainer .input button { + width: 52px; } -.admindetails { - display: flex; - justify-content: space-between; + +.inputField { + margin-top: 10px; + margin-bottom: 10px; + background-color: white; + box-shadow: 0 1px 1px #31bb6b; } -.admindetails > p { - margin-top: -12px; - margin-right: 30px; +.inputFieldModal { + margin-bottom: 10px; + background-color: white; + box-shadow: 0 1px 1px #31bb6b; } -.mainpageright > hr { - margin-top: 20px; - width: 97%; - margin-left: -15px; - margin-right: -15px; - margin-bottom: 20px; +.inputField > button { + padding-top: 10px; + padding-bottom: 10px; } -.addbtnmain { - width: 60%; - margin-right: 50px; +.TableImage { + object-fit: cover; + width: 50px !important; + height: 50px !important; + border-radius: 100% !important; } -.addbtn { - float: right; - width: 23%; - border: 1px solid #e8e5e5; - box-shadow: 0 2px 2px #e8e5e5; - border-radius: 5px; - background-color: #31bb6b; - height: 40px; - font-size: 16px; +.tableHead { + background-color: #31bb6b !important; color: white; - outline: none; - font-weight: 600; - cursor: pointer; - margin-left: 30px; - transition: transform 0.2s, box-shadow 0.2s; -} -.flexdir { - display: flex; - flex-direction: row; - justify-content: space-between; - border: none; + border-radius: 20px !important; + padding: 20px; + margin-top: 20px; } -.form_wrapper { - margin-top: 27px; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - position: absolute; - display: flex; - flex-direction: column; - padding: 40px 30px; - background: #ffffff; - border-color: #e8e5e5; - border-width: 5px; - border-radius: 10px; +.tableHead :nth-first-child() { + border-top-left-radius: 20px; } -.form_wrapper form { - display: flex; - align-items: left; - justify-content: left; - flex-direction: column; -} -.logintitleinvite { - color: #707070; - font-weight: 600; - font-size: 20px; - margin-bottom: 20px; - padding-bottom: 5px; - border-bottom: 3px solid #31bb6b; - width: 40%; -} -.cancel > i { - margin-top: 5px; - transform: scale(1.2); - cursor: pointer; - color: #707070; -} -.modalbody { - width: 50px; -} -.greenregbtn { - margin: 1rem 0 0; +.mainpageright > hr { margin-top: 10px; - border: 1px solid #e8e5e5; - box-shadow: 0 2px 2px #e8e5e5; - padding: 10px 10px; - border-radius: 5px; - background-color: #31bb6b; - width: 100%; - font-size: 16px; - color: white; - outline: none; - font-weight: 600; - cursor: pointer; - transition: transform 0.2s, box-shadow 0.2s; width: 100%; + margin-left: -15px; + margin-right: -15px; + margin-bottom: 20px; } -.sidebarsticky > input { - text-decoration: none; - margin-bottom: 50px; - border-color: #e8e5e5; - width: 80%; - border-radius: 7px; - padding-top: 5px; - padding-bottom: 5px; - padding-right: 10px; - padding-left: 10px; - box-shadow: none; -} - -.loader, -.loader:after { - border-radius: 50%; - width: 10em; - height: 10em; -} -.loader { - margin: 60px auto; - margin-top: 35vh !important; - font-size: 10px; - position: relative; - text-indent: -9999em; - border-top: 1.1em solid rgba(255, 255, 255, 0.2); - border-right: 1.1em solid rgba(255, 255, 255, 0.2); - border-bottom: 1.1em solid rgba(255, 255, 255, 0.2); - border-left: 1.1em solid #febc59; - -webkit-transform: translateZ(0); - -ms-transform: translateZ(0); - transform: translateZ(0); - -webkit-animation: load8 1.1s infinite linear; - animation: load8 1.1s infinite linear; -} -.radio_buttons { - color: #707070; - font-weight: 600; - font-size: 14px; -} -.radio_buttons > input { - transform: scale(1.2); +.rowBackground { + background-color: var(--bs-white); } -.radio_buttons > label { - margin-top: -4px; - margin-left: 5px; - margin-right: 15px; +.tableHeader { + background-color: var(--bs-primary); + color: var(--bs-white); + font-size: 16px; } @-webkit-keyframes load8 { @@ -274,9 +119,3 @@ transform: rotate(360deg); } } -.list_box { - height: 70vh; - overflow-y: auto; - width: auto; - padding-right: 50px; -} diff --git a/src/screens/OrganizationPeople/OrganizationPeople.test.tsx b/src/screens/OrganizationPeople/OrganizationPeople.test.tsx index 605c01f785..8ea7b30219 100644 --- a/src/screens/OrganizationPeople/OrganizationPeople.test.tsx +++ b/src/screens/OrganizationPeople/OrganizationPeople.test.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { MockedProvider } from '@apollo/react-testing'; -import { act, render, screen } from '@testing-library/react'; +import { act, fireEvent, render, screen } from '@testing-library/react'; import { Provider } from 'react-redux'; import { BrowserRouter } from 'react-router-dom'; import userEvent from '@testing-library/user-event'; @@ -10,63 +10,23 @@ import { store } from 'state/store'; import { ORGANIZATIONS_LIST, ORGANIZATIONS_MEMBER_CONNECTION_LIST, - USER_LIST, + USERS_CONNECTION_LIST, + USER_LIST_FOR_TABLE, } from 'GraphQl/Queries/Queries'; import 'jest-location-mock'; import i18nForTest from 'utils/i18nForTest'; import { StaticMockLink } from 'utils/StaticMockLink'; - -// This loop creates dummy data for members, admin and users -const members: any[] = []; -const admins: any[] = []; -const users: any[] = []; - -for (let i = 0; i < 100; i++) { - members.push({ - __typename: 'User', - _id: i + '1', - firstName: 'firstName', - lastName: 'lastName', - image: null, - email: 'email', - createdAt: new Date().toISOString(), - }); - - admins.push({ - __typename: 'User', - _id: i + '1', - firstName: 'firstName', - lastName: 'lastName', - image: null, - email: 'email', - createdAt: new Date().toISOString(), - }); - - users.push({ - __typename: 'User', - firstName: 'firstName', - lastName: 'lastName', - image: null, - _id: i + 'id', - email: 'email', - userType: ['SUPERADMIN', 'USER'][i < 50 ? 0 : 1], - adminApproved: true, - organizationsBlockedBy: [], - createdAt: new Date().toISOString(), - joinedOrganizations: [ - { - __typename: 'Organization', - _id: `6411a8f197d5631eb0765857${i}`, - }, - ], - }); -} +import { + ADD_MEMBER_MUTATION, + SIGNUP_MUTATION, +} from 'GraphQl/Mutations/mutations'; +import type { TestMock } from './MockDataTypes'; const createMemberMock = ( orgId = '', firstNameContains = '', - lastNameContains = '' -): any => ({ + lastNameContains = '', +): TestMock => ({ request: { query: ORGANIZATIONS_MEMBER_CONNECTION_LIST, variables: { @@ -78,10 +38,8 @@ const createMemberMock = ( result: { data: { organizationsMemberConnection: { - __typename: 'UserConnection', edges: [ { - __typename: 'User', _id: '64001660a711c62d5b4076a2', firstName: 'Aditya', lastName: 'Memberguy', @@ -96,16 +54,17 @@ const createMemberMock = ( newData: () => ({ data: { organizationsMemberConnection: { - __typename: 'UserConnection', edges: [ { - __typename: 'User', - _id: '64001660a711c62d5b4076a2', - firstName: 'Aditya', - lastName: 'Memberguy', - image: null, - email: 'member@gmail.com', - createdAt: '2023-03-02T03:22:08.101Z', + user: { + __typename: 'User', + _id: '64001660a711c62d5b4076a2', + firstName: 'Aditya', + lastName: 'Memberguy', + image: null, + email: 'member@gmail.com', + createdAt: '2023-03-02T03:22:08.101Z', + }, }, ], }, @@ -117,32 +76,29 @@ const createAdminMock = ( orgId = '', firstNameContains = '', lastNameContains = '', - adminFor = '' -): any => ({ +): TestMock => ({ request: { query: ORGANIZATIONS_MEMBER_CONNECTION_LIST, variables: { orgId, firstNameContains, lastNameContains, - adminFor, }, }, result: { data: { organizationsMemberConnection: { - __typename: 'UserConnection', edges: [ { - __typename: 'User', - _id: '64001660a711c62d5b4076a2', - firstName: 'Aditya', - lastName: 'Adminguy', - image: null, - email: 'admin@gmail.com', - createdAt: '2023-03-02T03:22:08.101Z', + user: { + _id: '64001660a711c62d5b4076a2', + firstName: 'Aditya', + lastName: 'Adminguy', + image: null, + email: 'admin@gmail.com', + createdAt: '2023-03-02T03:22:08.101Z', + }, }, - ...admins, ], }, }, @@ -153,14 +109,16 @@ const createAdminMock = ( __typename: 'UserConnection', edges: [ { - __typename: 'User', - _id: '64001660a711c62d5b4076a2', - firstName: 'Aditya', - lastName: 'Adminguy', - image: null, - email: 'admin@gmail.com', - createdAt: '2023-03-02T03:22:08.101Z', - lol: true, + user: { + __typename: 'User', + _id: '64001660a711c62d5b4076a2', + firstName: 'Aditya', + lastName: 'Adminguy', + image: null, + email: 'admin@gmail.com', + createdAt: '2023-03-02T03:22:08.101Z', + lol: true, + }, }, ], }, @@ -170,10 +128,10 @@ const createAdminMock = ( const createUserMock = ( firstNameContains = '', - lastNameContains = '' -): any => ({ + lastNameContains = '', +): TestMock => ({ request: { - query: USER_LIST, + query: USER_LIST_FOR_TABLE, variables: { firstNameContains, lastNameContains, @@ -183,47 +141,45 @@ const createUserMock = ( data: { users: [ { - __typename: 'User', - firstName: 'Aditya', - lastName: 'Userguy', - image: null, - _id: '64001660a711c62d5b4076a2', - email: 'adidacreator1@gmail.com', - userType: 'SUPERADMIN', - adminApproved: true, - organizationsBlockedBy: [], - createdAt: '2023-03-02T03:22:08.101Z', - joinedOrganizations: [ - { - __typename: 'Organization', - _id: '6401ff65ce8e8406b8f07af1', - }, - ], + user: { + __typename: 'User', + firstName: 'Aditya', + lastName: 'Userguy', + image: 'tempUrl', + _id: '64001660a711c62d5b4076a2', + email: 'adidacreator1@gmail.com', + createdAt: '2023-03-02T03:22:08.101Z', + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af1', + }, + ], + }, }, { - __typename: 'User', - firstName: 'Aditya', - lastName: 'Userguytwo', - image: null, - _id: '6402030dce8e8406b8f07b0e', - email: 'adi1@gmail.com', - userType: 'USER', - adminApproved: true, - organizationsBlockedBy: [], - createdAt: '2023-03-03T14:24:13.084Z', - joinedOrganizations: [ - { - __typename: 'Organization', - _id: '6401ff65ce8e8406b8f07af2', - }, - ], + user: { + __typename: 'User', + firstName: 'Aditya', + lastName: 'Userguytwo', + image: 'tempUrl', + _id: '6402030dce8e8406b8f07b0e', + email: 'adi1@gmail.com', + createdAt: '2023-03-03T14:24:13.084Z', + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + }, + ], + }, }, ], }, }, }); -const MOCKS: any[] = [ +const MOCKS: TestMock[] = [ { request: { query: ORGANIZATIONS_LIST, @@ -244,33 +200,53 @@ const MOCKS: any[] = [ }, name: 'name', description: 'description', - location: 'location', - members: { - _id: 'id', - firstName: 'firstName', - lastName: 'lastName', - email: 'email', - }, - admins: { - _id: 'id', - firstName: 'firstName', - lastName: 'lastName', - email: 'email', + userRegistrationRequired: false, + visibleInSearch: false, + address: { + city: 'string', + countryCode: 'string', + dependentLocality: 'string', + line1: 'string', + line2: 'string', + postalCode: 'string', + sortingCode: 'string', + state: 'string', }, - membershipRequests: { - _id: 'id', - user: { + members: [ + { + _id: 'id', firstName: 'firstName', lastName: 'lastName', email: 'email', }, - }, - blockedUsers: { - _id: 'id', - firstName: 'firstName', - lastName: 'lastName', - email: 'email', - }, + ], + admins: [ + { + _id: 'id', + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + createdAt: '12-03-2024', + }, + ], + membershipRequests: [ + { + _id: 'id', + user: { + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + }, + ], + blockedUsers: [ + { + _id: 'id', + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + ], }, ], }, @@ -290,10 +266,8 @@ const MOCKS: any[] = [ result: { data: { organizationsMemberConnection: { - __typename: 'UserConnection', edges: [ { - __typename: 'User', _id: '64001660a711c62d5b4076a2', firstName: 'Aditya', lastName: 'Memberguy', @@ -301,7 +275,6 @@ const MOCKS: any[] = [ email: 'member@gmail.com', createdAt: '2023-03-02T03:22:08.101Z', }, - ...members, ], }, }, @@ -310,10 +283,8 @@ const MOCKS: any[] = [ //A function if multiple request are sent data: { organizationsMemberConnection: { - __typename: 'UserConnection', edges: [ { - __typename: 'User', _id: '64001660a711c62d5b4076a2', firstName: 'Aditya', lastName: 'Memberguy', @@ -321,7 +292,6 @@ const MOCKS: any[] = [ email: 'member@gmail.com', createdAt: '2023-03-02T03:22:08.101Z', }, - ...members, ], }, }, @@ -335,16 +305,13 @@ const MOCKS: any[] = [ orgId: 'orgid', firstName_contains: '', lastName_contains: '', - admin_for: 'orgid', }, }, result: { data: { organizationsMemberConnection: { - __typename: 'UserConnection', edges: [ { - __typename: 'User', _id: '64001660a711c62d5b4076a2', firstName: 'Aditya', lastName: 'Adminguy', @@ -352,7 +319,6 @@ const MOCKS: any[] = [ email: 'admin@gmail.com', createdAt: '2023-03-02T03:22:08.101Z', }, - ...admins, ], }, }, @@ -372,7 +338,6 @@ const MOCKS: any[] = [ createdAt: '2023-03-02T03:22:08.101Z', lol: true, }, - ...admins, ], }, }, @@ -382,7 +347,7 @@ const MOCKS: any[] = [ { //This is mock for user list request: { - query: USER_LIST, + query: USER_LIST_FOR_TABLE, variables: { firstName_contains: '', lastName_contains: '', @@ -392,42 +357,39 @@ const MOCKS: any[] = [ data: { users: [ { - __typename: 'User', - firstName: 'Aditya', - lastName: 'Userguy', - image: null, - _id: '64001660a711c62d5b4076a2', - email: 'adidacreator1@gmail.com', - userType: 'SUPERADMIN', - adminApproved: true, - organizationsBlockedBy: [], - createdAt: '2023-03-02T03:22:08.101Z', - joinedOrganizations: [ - { - __typename: 'Organization', - _id: '6401ff65ce8e8406b8f07af1', - }, - ], + user: { + __typename: 'User', + firstName: 'Aditya', + lastName: 'Userguy', + image: 'tempUrl', + _id: '64001660a711c62d5b4076a2', + email: 'adidacreator1@gmail.com', + createdAt: '2023-03-02T03:22:08.101Z', + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af1', + }, + ], + }, }, { - __typename: 'User', - firstName: 'Aditya', - lastName: 'Userguytwo', - image: null, - _id: '6402030dce8e8406b8f07b0e', - email: 'adi1@gmail.com', - userType: 'USER', - adminApproved: true, - organizationsBlockedBy: [], - createdAt: '2023-03-03T14:24:13.084Z', - joinedOrganizations: [ - { - __typename: 'Organization', - _id: '6401ff65ce8e8406b8f07af2', - }, - ], + user: { + __typename: 'User', + firstName: 'Aditya', + lastName: 'Userguytwo', + image: 'tempUrl', + _id: '6402030dce8e8406b8f07b0e', + email: 'adi1@gmail.com', + createdAt: '2023-03-03T14:24:13.084Z', + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + }, + ], + }, }, - ...users, ], }, }, @@ -437,230 +399,269 @@ const MOCKS: any[] = [ createMemberMock('orgid', '', 'Memberguy'), createMemberMock('orgid', 'Aditya', 'Memberguy'), - createAdminMock('orgid', 'Aditya', '', 'orgid'), - createAdminMock('orgid', '', 'Adminguy', 'orgid'), - createAdminMock('orgid', 'Aditya', 'Adminguy', 'orgid'), + createAdminMock('orgid', 'Aditya', ''), + createAdminMock('orgid', '', 'Adminguy'), + createAdminMock('orgid', 'Aditya', 'Adminguy'), createUserMock('Aditya', ''), createUserMock('', 'Userguytwo'), createUserMock('Aditya', 'Userguytwo'), -]; - -const link = new StaticMockLink(MOCKS, true); -async function wait(ms = 2): Promise { - await act(() => { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); - }); -} - -// TODO - REMOVE THE NEXT LINE IT IS TO SUPPRESS THE ERROR -// FOR THE FIRST TEST WHICH CAME OUT OF NOWHERE -console.error = jest.fn(); - -describe('Organization People Page', () => { - const searchData = { - firstName: 'Aditya', - lastNameMember: 'Memberguy', - lastNameAdmin: 'Adminguy', - lastNameUser: 'Userguytwo', - location: 'Delhi, India', - event: 'Event', - }; - - test('The number of organizations people rendered on the DOM should be equal to the rowsPerPage state value', async () => { - window.location.assign('orgpeople/id=6401ff65ce8e8406b8f07af1'); - - render( - - - - - - - - - - ); - - await wait(); - - await screen.findByTestId('rowsPPSelect'); - - // Get the reference to all userTypes through the radio buttons in the DOM - // => users, members, admins - const allPeopleTypes = Array.from( - screen.getByTestId('usertypelist').querySelectorAll('input[type="radio"]') - ).map((radioButton: HTMLInputElement | any) => radioButton.dataset?.testid); - - // This variable represents the array index of currently selected UserType(i.e "member" or "admin" or "user") - let peopleTypeIndex = 0; - - const changeRowsPerPage = async (currRowPPindex: number): Promise => { - // currRowPPindex is the index of the currently selected option of rows per page dropdown - - await screen.findByTestId('rowsPPSelect'); - - //Get the reference to the dropdown for rows per page - const rowsPerPageSelect: HTMLSelectElement | null = - screen.getByTestId('rowsPPSelect').querySelector('select') || null; - - if (rowsPerPageSelect === null) { - throw new Error('rowsPerPageSelect is null'); - } - - // Get all possible dropdown options - // => -1, 5, 10, 30 - const rowsPerPageOptions: any[] = Array.from( - rowsPerPageSelect?.querySelectorAll('option') - ); - - // Change the selected option of dropdown to the value of the current option - userEvent.selectOptions( - rowsPerPageSelect, - rowsPerPageOptions[currRowPPindex].textContent - ); - - const expectedUsersLength = MOCKS[3]?.result?.data?.users?.filter( - (datas: { - _id: string; - lastName: string; - firstName: string; - image: string; - email: string; - createdAt: string; - joinedOrganizations: { - __typename: string; - _id: string; - }[]; - }) => { - window.location.assign('/orgpeople/id=6401ff65ce8e8406b8f07af1'); - const pathname = window.location.pathname; - const id = pathname.split('=')[1]; - return datas.joinedOrganizations.some((org) => org._id === id); - } - ).length; - - await wait(); - const totalNumPeople = screen.getAllByTestId('orgpeoplelist').length; - expect(totalNumPeople).toBe(expectedUsersLength); - - if (rowsPerPageOptions[currRowPPindex].textContent === 'All') { - peopleTypeIndex += 1; - - await changePeopleType(); - - return; - } - - if (currRowPPindex < rowsPerPageOptions.length) { - currRowPPindex += 1; - await changeRowsPerPage(currRowPPindex); - } - }; - - const changePeopleType = async (): Promise => { - if (peopleTypeIndex === allPeopleTypes.length - 1) return; - - const peopleTypeButton = screen - .getByTestId('usertypelist') - .querySelector(`input[data-testid=${allPeopleTypes[peopleTypeIndex]}]`); - - if (peopleTypeButton === null) { - throw new Error('peopleTypeButton is null'); - } - - // Change people type - userEvent.click(peopleTypeButton); - - await changeRowsPerPage(1); - }; - - await changePeopleType(); - }, 15000); - - test('Correct mock data should be queried', async () => { - window.location.assign('/orgpeople/id=orgid'); - - const dataQuery1 = - MOCKS[1]?.result?.data?.organizationsMemberConnection?.edges; - const dataQuery2 = - MOCKS[2]?.result?.data?.organizationsMemberConnection?.edges; - - const dataQuery3 = MOCKS[3]?.result?.data?.users; - - expect(dataQuery1).toEqual([ - { - __typename: 'User', - _id: '64001660a711c62d5b4076a2', - firstName: 'Aditya', - lastName: 'Memberguy', - image: null, - email: 'member@gmail.com', - createdAt: '2023-03-02T03:22:08.101Z', - }, - ...members, - ]); - expect(dataQuery2).toEqual([ - { - __typename: 'User', - _id: '64001660a711c62d5b4076a2', - firstName: 'Aditya', - lastName: 'Adminguy', - image: null, - email: 'admin@gmail.com', - createdAt: '2023-03-02T03:22:08.101Z', + { + request: { + query: USERS_CONNECTION_LIST, + variables: { + id_not_in: ['64001660a711c62d5b4076a2'], + firstName_contains: '', + lastName_contains: '', }, - ...admins, - ]); - - expect(dataQuery3).toEqual([ - { - __typename: 'User', - firstName: 'Aditya', - lastName: 'Userguy', - image: null, - _id: '64001660a711c62d5b4076a2', - email: 'adidacreator1@gmail.com', - userType: 'SUPERADMIN', - adminApproved: true, - organizationsBlockedBy: [], - createdAt: '2023-03-02T03:22:08.101Z', - joinedOrganizations: [ + }, + result: { + data: { + users: [ { - __typename: 'Organization', - _id: '6401ff65ce8e8406b8f07af1', + user: { + firstName: 'Vyvyan', + lastName: 'Kerry', + image: null, + _id: '65378abd85008f171cf2990d', + email: 'testadmin1@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + joinedOrganizations: [ + { + _id: '6537904485008f171cf29924', + name: 'Unity Foundation', + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + }, + __typename: 'Organization', + }, + ], + __typename: 'User', + }, }, ], }, + }, + }, + { + request: { + query: SIGNUP_MUTATION, + variables: { + firstName: 'Disha', + lastName: 'Talreja', + email: 'test@gmail.com', + password: 'dishatalreja', + orgId: 'orgId', + }, + }, + result: { + data: { + signUp: { + user: { + _id: '', + }, + accessToken: 'accessToken', + refreshToken: 'refreshToken', + }, + }, + }, + }, + { + request: { + query: ADD_MEMBER_MUTATION, + variables: { + userid: '65378abd85008f171cf2990d', + orgid: 'orgid', + }, + }, + result: { + data: { + createMember: { + _id: '6437904485008f171cf29924', + __typename: 'Organization', + }, + }, + }, + }, +]; + +const EMPTYMOCKS: TestMock[] = [ + { + request: { + query: ORGANIZATIONS_LIST, + variables: { + id: 'orgid', + }, + }, + result: { + data: { + organizations: [], + }, + }, + }, + + { + //These are mocks for 1st query (member list) + request: { + query: ORGANIZATIONS_MEMBER_CONNECTION_LIST, + variables: { + orgId: 'orgid', + firstName_contains: '', + lastName_contains: '', + }, + }, + result: { + data: { + organizationsMemberConnection: { + edges: [], + }, + }, + }, + }, + + { + request: { + query: ORGANIZATIONS_MEMBER_CONNECTION_LIST, + variables: { + orgId: 'orgid', + firstName_contains: '', + lastName_contains: '', + }, + }, + result: { + data: { + organizationsMemberConnection: { + edges: [], + }, + }, + }, + }, + + { + //This is mock for user list + request: { + query: USER_LIST_FOR_TABLE, + variables: { + firstName_contains: '', + lastName_contains: '', + }, + }, + result: { + data: { + users: [], + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); +const link2 = new StaticMockLink(EMPTYMOCKS, true); +async function wait(ms = 2): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} +const linkURL = 'orgid'; +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: linkURL }), +})); + +// TODO - REMOVE THE NEXT LINE IT IS TO SUPPRESS THE ERROR +// FOR THE FIRST TEST WHICH CAME OUT OF NOWHERE +console.error = jest.fn(); + +describe('Organization People Page', () => { + const searchData = { + fullNameMember: 'Aditya Memberguy', + fullNameAdmin: 'Aditya Adminguy', + fullNameUser: 'Aditya Userguytwo', + location: 'Delhi, India', + event: 'Event', + }; + + test('Correct mock data should be queried', async () => { + window.location.assign('/orgpeople/orgid'); + + const dataQuery1 = + MOCKS[1]?.result?.data?.organizationsMemberConnection?.edges; + expect(dataQuery1).toEqual([ { - __typename: 'User', + _id: '64001660a711c62d5b4076a2', firstName: 'Aditya', - lastName: 'Userguytwo', + lastName: 'Memberguy', image: null, - _id: '6402030dce8e8406b8f07b0e', - email: 'adi1@gmail.com', - userType: 'USER', - adminApproved: true, - organizationsBlockedBy: [], - createdAt: '2023-03-03T14:24:13.084Z', - joinedOrganizations: [ - { - __typename: 'Organization', - _id: '6401ff65ce8e8406b8f07af2', - }, - ], + email: 'member@gmail.com', + createdAt: '2023-03-02T03:22:08.101Z', + }, + ]); + + const dataQuery2 = + MOCKS[2]?.result?.data?.organizationsMemberConnection?.edges; + + const dataQuery3 = MOCKS[3]?.result?.data?.users; + + expect(dataQuery3).toEqual([ + { + user: { + __typename: 'User', + firstName: 'Aditya', + lastName: 'Userguy', + image: 'tempUrl', + _id: '64001660a711c62d5b4076a2', + email: 'adidacreator1@gmail.com', + createdAt: '2023-03-02T03:22:08.101Z', + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af1', + }, + ], + }, + }, + { + user: { + __typename: 'User', + firstName: 'Aditya', + lastName: 'Userguytwo', + image: 'tempUrl', + _id: '6402030dce8e8406b8f07b0e', + email: 'adi1@gmail.com', + createdAt: '2023-03-03T14:24:13.084Z', + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + }, + ], + }, }, - ...users, ]); - expect(window.location).toBeAt('/orgpeople/id=orgid'); + expect(dataQuery2).toEqual([ + { + _id: '64001660a711c62d5b4076a2', + firstName: 'Aditya', + lastName: 'Adminguy', + image: null, + email: 'admin@gmail.com', + createdAt: '2023-03-02T03:22:08.101Z', + }, + ]); + + expect(window.location).toBeAt('/orgpeople/orgid'); }); test('It is necessary to query the correct mock data.', async () => { - window.location.assign('/orgpeople/id=orgid'); + window.location.assign('/orgpeople/orgid'); const { container } = render( @@ -671,21 +672,18 @@ describe('Organization People Page', () => { - + , ); expect(container.textContent).not.toBe('Loading data...'); await wait(); - expect(container.textContent).toMatch('Members'); - expect(container.textContent).toMatch('Filter by Name'); - - expect(window.location).toBeAt('/orgpeople/id=orgid'); + expect(window.location).toBeAt('/orgpeople/orgid'); }); test('Testing MEMBERS list', async () => { - window.location.assign('/orgpeople/id=orgid'); + window.location.assign('/orgpeople/orgid'); render( { - + , ); await wait(); + const dropdownToggles = screen.getAllByTestId('role'); - userEvent.click(screen.getByLabelText(/Members/i)); - await wait(); - expect(screen.getByLabelText(/Members/i)).toBeChecked(); + dropdownToggles.forEach((dropdownToggle) => { + userEvent.click(dropdownToggle); + }); + + const memebersDropdownItem = screen.getByTestId('members'); + userEvent.click(memebersDropdownItem); await wait(); const findtext = screen.getByText(/Aditya Memberguy/i); @@ -716,20 +718,20 @@ describe('Organization People Page', () => { expect(findtext).toBeInTheDocument(); userEvent.type( - screen.getByPlaceholderText(/Enter First Name/i), - searchData.firstName + screen.getByPlaceholderText(/Enter Full Name/i), + searchData.fullNameMember, ); await wait(); - expect(screen.getByPlaceholderText(/Enter First Name/i)).toHaveValue( - searchData.firstName + expect(screen.getByPlaceholderText(/Enter Full Name/i)).toHaveValue( + searchData.fullNameMember, ); await wait(); - expect(window.location).toBeAt('/orgpeople/id=orgid'); + expect(window.location).toBeAt('/orgpeople/orgid'); }); test('Testing MEMBERS list with filters', async () => { - window.location.assign('/orgpeople/id=orgid'); + window.location.assign('/orgpeople/orgid'); render( { - + , ); await wait(); - userEvent.click(screen.getByLabelText(/Members/i)); - await wait(); - expect(screen.getByLabelText(/Members/i)).toBeChecked(); - await wait(); - - const firstNameInput = screen.getByPlaceholderText(/Enter First Name/i); - const lastNameInput = screen.getByPlaceholderText(/Enter Last Name/i); + const fullNameInput = screen.getByPlaceholderText(/Enter Full Name/i); // Only First Name - userEvent.type(firstNameInput, searchData.firstName); + userEvent.type(fullNameInput, searchData.fullNameMember); await wait(); let findtext = screen.getByText(/Aditya Memberguy/i); await wait(); expect(findtext).toBeInTheDocument(); - // First & Last Name - userEvent.type(lastNameInput, searchData.lastNameMember); - await wait(); - findtext = screen.getByText(/Aditya Memberguy/i); await wait(); expect(findtext).toBeInTheDocument(); - - // Only Last Name - userEvent.type(firstNameInput, ''); - await wait(); - - findtext = screen.getByText(/Aditya Memberguy/i); - await wait(); - expect(findtext).toBeInTheDocument(); - await wait(); - expect(window.location).toBeAt('/orgpeople/id=orgid'); + expect(window.location).toBeAt('/orgpeople/orgid'); }); test('Testing ADMIN LIST', async () => { - window.location.assign('/orgpeople/id=orgid'); + window.location.assign('/orgpeople/orgid'); render( { - + , ); await wait(); - userEvent.click(screen.getByLabelText(/Admins/i)); - await wait(); - expect(screen.getByLabelText(/Admins/i)).toBeChecked(); - await wait(); + // Get all dropdown toggles by test id + const dropdownToggles = screen.getAllByTestId('role'); - const findtext = screen.getByText('Aditya Adminguy'); - expect(findtext).toBeInTheDocument(); + // Click the dropdown toggle to open the dropdown menu + dropdownToggles.forEach((dropdownToggle) => { + userEvent.click(dropdownToggle); + }); + + // Click the "Admin" dropdown item + const adminDropdownItem = screen.getByTestId('admins'); + userEvent.click(adminDropdownItem); + + // Wait for any asynchronous operations to complete + await wait(); + // remove this comment when table fecthing functionality is fixed + // Assert that the "Aditya Adminguy" text is present + // const findtext = screen.getByText('Aditya Adminguy'); + // expect(findtext).toBeInTheDocument(); + // Type in the full name input field userEvent.type( - screen.getByPlaceholderText(/Enter First Name/i), - searchData.firstName + screen.getByPlaceholderText(/Enter Full Name/i), + searchData.fullNameAdmin, ); + + // Wait for any asynchronous operations to complete await wait(); - expect(screen.getByPlaceholderText(/Enter First Name/i)).toHaveValue( - searchData.firstName + + // Assert the value of the full name input field + expect(screen.getByPlaceholderText(/Enter Full Name/i)).toHaveValue( + searchData.fullNameAdmin, ); await wait(); + // Wait for any asynchronous operations to complete await wait(); - expect(window.location).toBeAt('/orgpeople/id=orgid'); + expect(window.location).toBeAt('/orgpeople/orgid'); }); test('Testing ADMIN list with filters', async () => { - window.location.assign('/orgpeople/id=orgid'); + window.location.assign('/orgpeople/orgid'); render( { - + , ); + // Wait for the component to finish rendering await wait(); - userEvent.click(screen.getByLabelText(/Admins/i)); + // Click on the dropdown toggle to open the menu + userEvent.click(screen.getByTestId('role')); await wait(); - expect(screen.getByLabelText(/Admins/i)).toBeChecked(); + + // Click on the "Admins" option in the dropdown menu + userEvent.click(screen.getByTestId('admins')); await wait(); - const firstNameInput = screen.getByPlaceholderText(/Enter First Name/i); - const lastNameInput = screen.getByPlaceholderText(/Enter Last Name/i); + // Type the full name into the input field + const fullNameInput = screen.getByPlaceholderText(/Enter Full Name/i); + userEvent.type(fullNameInput, searchData.fullNameAdmin); - // Only First Name - userEvent.type(firstNameInput, searchData.firstName); + // Wait for the results to update + await wait(); + const btn = screen.getByTestId('searchbtn'); + userEvent.click(btn); + // remove this comment when table fecthing functionality is fixed + // Check if the expected name is present in the results + // let findtext = screen.getByText(/Aditya Adminguy/i); + // expect(findtext).toBeInTheDocument(); + + // Ensure that the name is still present after filtering await wait(); + expect(window.location).toBeAt('/orgpeople/orgid'); + }); - let findtext = screen.getByText(/Aditya Adminguy/i); + test('Testing add existing user modal', async () => { + window.location.assign('/orgpeople/6401ff65ce8e8406b8f07af1'); + render( + + + + + + + + + , + ); + + // Wait for the component to finish rendering await wait(); - expect(findtext).toBeInTheDocument(); - // First & Last Name - userEvent.type(lastNameInput, searchData.lastNameAdmin); + // Click on the dropdown toggle to open the menu + userEvent.click(screen.getByTestId('addMembers')); + await wait(); + + expect(screen.getByTestId('existingUser')).toBeInTheDocument(); + + // Click on the "Admins" option in the dropdown menu + userEvent.click(screen.getByTestId('existingUser')); await wait(); - findtext = screen.getByText(/Aditya Adminguy/i); + expect(screen.getByTestId('addExistingUserModal')).toBeInTheDocument(); await wait(); - expect(findtext).toBeInTheDocument(); - // Only Last Name - userEvent.type(firstNameInput, ''); + userEvent.click(screen.getByTestId('addBtn')); + }); + + test('Open and search existing user', async () => { + window.location.assign('/orgpeople/orgid'); + render( + + + + + + + + + , + ); + + // Wait for the component to finish rendering await wait(); - findtext = screen.getByText(/Aditya Adminguy/i); + // Click on the dropdown toggle to open the menu + userEvent.click(screen.getByTestId('addMembers')); await wait(); - expect(findtext).toBeInTheDocument(); + // Click on the "Admins" option in the dropdown menu + userEvent.click(screen.getByTestId('existingUser')); await wait(); - expect(window.location).toBeAt('/orgpeople/id=orgid'); - }); - test('Testing USERS list', async () => { - const dataQueryForUsers = MOCKS[3]?.result?.data?.users; - window.location.assign('/orgpeople/id=6401ff65ce8e8406b8f07af1'); + expect(screen.getByTestId('addExistingUserModal')).toBeInTheDocument(); + + fireEvent.change(screen.getByTestId('searchUser'), { + target: { value: 'Disha' }, + }); + }); + test('Open and close add new user modal', async () => { + window.location.assign('/orgpeople/orgid'); render( { - + , ); + + // Wait for the component to finish rendering await wait(); - userEvent.click(screen.getByLabelText(/Users/i)); + + // Click on the dropdown toggle to open the menu + userEvent.click(screen.getByTestId('addMembers')); await wait(); - expect(screen.getByLabelText(/Users/i)).toBeChecked(); + + // Click on the "Admins" option in the dropdown menu + userEvent.click(screen.getByTestId('newUser')); await wait(); - const orgUsers = dataQueryForUsers?.filter( - (datas: { - _id: string; - lastName: string; - firstName: string; - image: string; - email: string; - createdAt: string; - joinedOrganizations: { - __typename: string; - _id: string; - }[]; - }) => { - window.location.assign('/orgpeople/id=6401ff65ce8e8406b8f07af1'); - const pathname = window.location.pathname; - const id = pathname.split('=')[1]; - return datas.joinedOrganizations?.some((org) => org._id === id); - } + + expect(screen.getByTestId('addNewUserModal')).toBeInTheDocument(); + + userEvent.click(screen.getByTestId('closeBtn')); + }); + + test('Testing add new user modal', async () => { + window.location.assign('/orgpeople/orgid'); + render( + + + + + + + + + , ); + + // Wait for the component to finish rendering await wait(); - expect(orgUsers?.length).toBe(1); + // Click on the dropdown toggle to open the menu + userEvent.click(screen.getByTestId('addMembers')); await wait(); - expect(window.location).toBeAt('/orgpeople/id=6401ff65ce8e8406b8f07af1'); - }); - test('Testing USERS list with filters', async () => { - window.location.assign('/orgpeople/id=6401ff65ce8e8406b8f07af2'); - const dataQueryForUsers = MOCKS[3]?.result?.data?.users; + // Click on the "Admins" option in the dropdown menu + userEvent.click(screen.getByTestId('newUser')); + await wait(); + + expect(screen.getByTestId('addNewUserModal')).toBeInTheDocument(); + + fireEvent.change(screen.getByTestId('firstNameInput'), { + target: { value: 'Disha' }, + }); + expect(screen.getByTestId('firstNameInput')).toHaveValue('Disha'); + + fireEvent.change(screen.getByTestId('lastNameInput'), { + target: { value: 'Talreja' }, + }); + expect(screen.getByTestId('lastNameInput')).toHaveValue('Talreja'); + fireEvent.change(screen.getByTestId('emailInput'), { + target: { value: 'test@gmail.com' }, + }); + expect(screen.getByTestId('emailInput')).toHaveValue('test@gmail.com'); + + fireEvent.change(screen.getByTestId('passwordInput'), { + target: { value: 'dishatalreja' }, + }); + userEvent.click(screen.getByTestId('showPassword')); + expect(screen.getByTestId('passwordInput')).toHaveValue('dishatalreja'); + + fireEvent.change(screen.getByTestId('confirmPasswordInput'), { + target: { value: 'dishatalreja' }, + }); + userEvent.click(screen.getByTestId('showConfirmPassword')); + expect(screen.getByTestId('confirmPasswordInput')).toHaveValue( + 'dishatalreja', + ); + + userEvent.click(screen.getByTestId('createBtn')); + }); + + test('Throw invalid details error in add new user modal', async () => { + window.location.assign('/orgpeople/orgid'); render( { - + , ); + + // Wait for the component to finish rendering await wait(); - userEvent.click(screen.getByLabelText(/Users/i)); + + // Click on the dropdown toggle to open the menu + userEvent.click(screen.getByTestId('addMembers')); await wait(); - expect(screen.getByLabelText(/Users/i)).toBeChecked(); + + // Click on the "Admins" option in the dropdown menu + userEvent.click(screen.getByTestId('newUser')); await wait(); - const firstNameInput = screen.getByPlaceholderText(/Enter First Name/i); + expect(screen.getByTestId('addNewUserModal')).toBeInTheDocument(); - // Only First Name - userEvent.type(firstNameInput, searchData.firstName); + fireEvent.change(screen.getByTestId('firstNameInput'), { + target: { value: 'Disha' }, + }); + expect(screen.getByTestId('firstNameInput')).toHaveValue('Disha'); + + fireEvent.change(screen.getByTestId('lastNameInput'), { + target: { value: 'Talreja' }, + }); + expect(screen.getByTestId('lastNameInput')).toHaveValue('Talreja'); + + fireEvent.change(screen.getByTestId('emailInput'), { + target: { value: 'test@gmail.com' }, + }); + expect(screen.getByTestId('emailInput')).toHaveValue('test@gmail.com'); + + fireEvent.change(screen.getByTestId('passwordInput'), { + target: { value: 'dishatalreja' }, + }); + userEvent.click(screen.getByTestId('showPassword')); + expect(screen.getByTestId('passwordInput')).toHaveValue('dishatalreja'); + + fireEvent.change(screen.getByTestId('confirmPasswordInput'), { + target: { value: 'disha' }, + }); + userEvent.click(screen.getByTestId('showConfirmPassword')); + expect(screen.getByTestId('confirmPasswordInput')).toHaveValue('disha'); + + userEvent.click(screen.getByTestId('createBtn')); + }); + + test('Throw passwordNotMatch error in add new user modal', async () => { + window.location.assign('/orgpeople/orgid'); + render( + + + + + + + + + , + ); + + // Wait for the component to finish rendering + await wait(); + + // Click on the dropdown toggle to open the menu + userEvent.click(screen.getByTestId('addMembers')); + await wait(); + + // Click on the "Admins" option in the dropdown menu + userEvent.click(screen.getByTestId('newUser')); await wait(); - const orgUsers = dataQueryForUsers?.filter( - (datas: { - _id: string; - lastName: string; - firstName: string; - image: string; - email: string; - createdAt: string; - joinedOrganizations: { - __typename: string; - _id: string; - }[]; - }) => { - window.location.assign('/orgpeople/id=6401ff65ce8e8406b8f07af2'); - const pathname = window.location.pathname; - const id = pathname.split('=')[1]; - return datas.joinedOrganizations?.some((org) => org._id === id); - } + expect(screen.getByTestId('addNewUserModal')).toBeInTheDocument(); + + fireEvent.change(screen.getByTestId('firstNameInput'), { + target: { value: 'Disha' }, + }); + expect(screen.getByTestId('firstNameInput')).toHaveValue('Disha'); + + fireEvent.change(screen.getByTestId('lastNameInput'), { + target: { value: 'Talreja' }, + }); + expect(screen.getByTestId('lastNameInput')).toHaveValue('Talreja'); + + fireEvent.change(screen.getByTestId('passwordInput'), { + target: { value: 'dishatalreja' }, + }); + userEvent.click(screen.getByTestId('showPassword')); + expect(screen.getByTestId('passwordInput')).toHaveValue('dishatalreja'); + + fireEvent.change(screen.getByTestId('confirmPasswordInput'), { + target: { value: 'dishatalreja' }, + }); + userEvent.click(screen.getByTestId('showConfirmPassword')); + expect(screen.getByTestId('confirmPasswordInput')).toHaveValue( + 'dishatalreja', + ); + + userEvent.click(screen.getByTestId('createBtn')); + }); + + test('Testing USERS list', async () => { + window.location.assign('/orgpeople/6401ff65ce8e8406b8f07af1'); + + render( + + + + + + + + + , ); await wait(); - expect(orgUsers?.length).toBe(1); + const orgUsers = MOCKS[3]?.result?.data?.users; + expect(orgUsers?.length).toBe(2); + + const dropdownToggles = screen.getAllByTestId('role'); + + dropdownToggles.forEach((dropdownToggle) => { + userEvent.click(dropdownToggle); + }); + + const usersDropdownItem = screen.getByTestId('users'); + userEvent.click(usersDropdownItem); + await wait(); + const btn = screen.getByTestId('searchbtn'); + userEvent.click(btn); await wait(); - expect(window.location).toBeAt('/orgpeople/id=6401ff65ce8e8406b8f07af2'); + expect(window.location).toBeAt('/orgpeople/6401ff65ce8e8406b8f07af1'); }); - test('No Mock Data test', async () => { - window.location.assign('/orgpeople/id=orgid'); + test('Testing USERS list with filters', async () => { + window.location.assign('/orgpeople/6401ff65ce8e8406b8f07af2'); render( - + @@ -1016,18 +1249,107 @@ describe('Organization People Page', () => { - + , ); + await wait(); + + const fullNameInput = screen.getByPlaceholderText(/Enter Full Name/i); + // Only Full Name + userEvent.type(fullNameInput, searchData.fullNameUser); + const btn = screen.getByTestId('searchbtn'); + userEvent.click(btn); await wait(); + expect(window.location).toBeAt('/orgpeople/6401ff65ce8e8406b8f07af2'); + }); - userEvent.click(screen.getByLabelText(/Admins/i)); + test('Add Member component renders', async () => { + render( + + + + + + + + + , + ); + await wait(); + userEvent.click(screen.getByTestId('addMembers')); + await wait(); + userEvent.click(screen.getByTestId('existingUser')); + await wait(); + const btn = screen.getByTestId('submitBtn'); + userEvent.click(btn); + }); + test('Datagrid renders with members data', async () => { + render( + + + + + + + , + ); + + await wait(); + const dataGrid = screen.getByRole('grid'); + expect(dataGrid).toBeInTheDocument(); + const removeButtons = screen.getAllByTestId('removeMemberModalBtn'); + userEvent.click(removeButtons[0]); + }); + + test('Datagrid renders with admin data', async () => { + window.location.assign('/orgpeople/orgid'); + render( + + + + + + + , + ); + + await wait(); + const dropdownToggles = screen.getAllByTestId('role'); + dropdownToggles.forEach((dropdownToggle) => { + userEvent.click(dropdownToggle); + }); + const adminDropdownItem = screen.getByTestId('admins'); + userEvent.click(adminDropdownItem); await wait(); + const removeButtons = screen.getAllByTestId('removeAdminModalBtn'); + userEvent.click(removeButtons[0]); + }); + + test('No Mock Data test', async () => { + window.location.assign('/orgpeople/orgid'); - userEvent.click(screen.getByLabelText(/Users/i)); + render( + + + + + + + + + , + ); await wait(); - expect(window.location).toBeAt('/orgpeople/id=orgid'); + expect(window.location).toBeAt('/orgpeople/orgid'); + expect(screen.queryByText(/Nothing Found !!/i)).toBeInTheDocument(); }); }); diff --git a/src/screens/OrganizationPeople/OrganizationPeople.tsx b/src/screens/OrganizationPeople/OrganizationPeople.tsx index 9d33ae2833..62be3becaf 100644 --- a/src/screens/OrganizationPeople/OrganizationPeople.tsx +++ b/src/screens/OrganizationPeople/OrganizationPeople.tsx @@ -1,25 +1,26 @@ import { useLazyQuery } from '@apollo/client'; -import dayjs from 'dayjs'; -import React, { useEffect, useState } from 'react'; -import { Container, Form } from 'react-bootstrap'; -import Col from 'react-bootstrap/Col'; -import Row from 'react-bootstrap/Row'; - +import { Search, Sort } from '@mui/icons-material'; import { + ORGANIZATIONS_LIST, ORGANIZATIONS_MEMBER_CONNECTION_LIST, - USER_LIST, + USER_LIST_FOR_TABLE, } from 'GraphQl/Queries/Queries'; -import NotFound from 'components/NotFound/NotFound'; +import Loader from 'components/Loader/Loader'; import OrgAdminListCard from 'components/OrgAdminListCard/OrgAdminListCard'; import OrgPeopleListCard from 'components/OrgPeopleListCard/OrgPeopleListCard'; -import OrganizationScreen from 'components/OrganizationScreen/OrganizationScreen'; -import PaginationList from 'components/PaginationList/PaginationList'; -import UserListCard from 'components/UserListCard/UserListCard'; +import dayjs from 'dayjs'; +import React, { useEffect, useState } from 'react'; +import { Button, Dropdown, Form } from 'react-bootstrap'; +import Row from 'react-bootstrap/Row'; import { useTranslation } from 'react-i18next'; -import debounce from 'utils/debounce'; -import styles from './OrganizationPeople.module.css'; - +import { Link, useLocation, useParams } from 'react-router-dom'; import { toast } from 'react-toastify'; +import AddMember from './AddMember'; +import styles from './OrganizationPeople.module.css'; +import { DataGrid } from '@mui/x-data-grid'; +import type { GridColDef, GridCellParams } from '@mui/x-data-grid'; +import { Stack } from '@mui/material'; +import Avatar from 'components/Avatar/Avatar'; function organizationPeople(): JSX.Element { const { t } = useTranslation('translation', { @@ -28,16 +29,40 @@ function organizationPeople(): JSX.Element { document.title = t('title'); - const currentUrl = window.location.href.split('=')[1]; + const location = useLocation(); + const role = location?.state; + + const { orgId: currentUrl } = useParams(); - const [state, setState] = useState(0); - const [page, setPage] = useState(0); - const [rowsPerPage, setRowsPerPage] = useState(5); + const [state, setState] = useState(role?.role || 0); const [filterData, setFilterData] = useState({ firstName_contains: '', lastName_contains: '', }); + const [adminFilteredData, setAdminFilteredData] = useState(); + + const [userName, setUserName] = useState(''); + const [showRemoveModal, setShowRemoveModal] = React.useState(false); + const [selectedAdminId, setSelectedAdminId] = React.useState< + string | undefined + >(); + const [selectedMemId, setSelectedMemId] = React.useState< + string | undefined + >(); + const toggleRemoveModal = (): void => { + setShowRemoveModal((prev) => !prev); + }; + const toggleRemoveMemberModal = (id: string): void => { + setSelectedMemId(id); + setSelectedAdminId(undefined); + toggleRemoveModal(); + }; + const toggleRemoveAdminModal = (id: string): void => { + setSelectedAdminId(id); + setSelectedMemId(undefined); + toggleRemoveModal(); + }; const { data: memberData, @@ -57,12 +82,9 @@ function organizationPeople(): JSX.Element { loading: adminLoading, error: adminError, refetch: adminRefetch, - } = useLazyQuery(ORGANIZATIONS_MEMBER_CONNECTION_LIST, { + } = useLazyQuery(ORGANIZATIONS_LIST, { variables: { - firstName_contains: '', - lastName_contains: '', - orgId: currentUrl, - admin_for: currentUrl, + id: currentUrl, }, })[1]; @@ -71,7 +93,7 @@ function organizationPeople(): JSX.Element { loading: usersLoading, error: usersError, refetch: usersRefetch, - } = useLazyQuery(USER_LIST, { + } = useLazyQuery(USER_LIST_FOR_TABLE, { variables: { firstName_contains: '', lastName_contains: '', @@ -86,116 +108,204 @@ function organizationPeople(): JSX.Element { }); } else if (state === 1) { adminRefetch({ - ...filterData, - orgId: currentUrl, - admin_for: currentUrl, + id: currentUrl, }); + setAdminFilteredData(adminData?.organizations[0].admins); } else { usersRefetch({ ...filterData, }); } - }, [state]); + }, [state, adminData]); /* istanbul ignore next */ if (memberError || usersError || adminError) { const error = memberError ?? usersError ?? adminError; toast.error(error?.message); } + if (memberLoading || usersLoading || adminLoading) { + return ( +
    + +
    + ); + } - /* istanbul ignore next */ - const handleFirstNameSearchChange = (filterData: any): void => { + const handleFullNameSearchChange = (e: React.FormEvent): void => { + e.preventDefault(); /* istanbul ignore next */ + const [firstName, lastName] = userName.split(' '); + const newFilterData = { + firstName_contains: firstName || '', + lastName_contains: lastName || '', + }; + + setFilterData(newFilterData); + if (state === 0) { memberRefetch({ - ...filterData, + ...newFilterData, orgId: currentUrl, }); } else if (state === 1) { - adminRefetch({ - ...filterData, - orgId: currentUrl, - admin_for: currentUrl, - }); + const filterData = adminData.organizations[0].admins.filter( + (value: { + _id: string; + firstName: string; + lastName: string; + createdAt: string; + }) => { + return (value.firstName + value.lastName) + .toLowerCase() + .includes(userName.toLowerCase()); + }, + ); + setAdminFilteredData(filterData); } else { usersRefetch({ - ...filterData, + ...newFilterData, }); } }; - /* istanbul ignore next */ - const handleChangePage = ( - event: React.MouseEvent | null, - newPage: number - ): void => { - setPage(newPage); - }; - - /* istanbul ignore next */ - const handleChangeRowsPerPage = ( - event: React.ChangeEvent - ): void => { - setRowsPerPage(parseInt(event.target.value, 10)); - setPage(0); - }; - - const debouncedHandleFirstNameSearchChange = debounce( - handleFirstNameSearchChange - ); - + const columns: GridColDef[] = [ + { + field: 'profile', + headerName: 'Profile', + flex: 1, + minWidth: 50, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return params.row?.image ? ( + avatar + ) : ( + + ); + }, + }, + { + field: 'name', + headerName: 'Name', + flex: 2, + minWidth: 150, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return ( + + {params.row?.firstName + ' ' + params.row?.lastName} + + ); + }, + }, + { + field: 'email', + headerName: 'Email', + minWidth: 150, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + flex: 2, + sortable: false, + }, + { + field: 'joined', + headerName: 'Joined', + flex: 2, + minWidth: 100, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return dayjs(params.row.createdAt).format('DD/MM/YYYY'); + }, + }, + { + field: 'action', + headerName: 'Action', + flex: 1, + minWidth: 100, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return state === 1 ? ( + + ) : ( + + ); + }, + }, + ]; return ( <> - - - -
    -
    -
    {t('filterByName')}
    - { - const { value } = e.target; - - const newFilterData = { - ...filterData, - firstName_contains: value?.trim(), - }; - - setFilterData(newFilterData); - debouncedHandleFirstNameSearchChange(newFilterData); - }} - /> + +
    +
    +
    +
    { const { value } = e.target; - - const newFilterData = { - ...filterData, - lastName_contains: value?.trim(), - }; - - setFilterData(newFilterData); - debouncedHandleFirstNameSearchChange(newFilterData); + setUserName(value); }} /> -
    - + + +
    +
    + + + + {t('sort')} + + + { setState(2); }} - /> - - + {t('users')} + + { setState(0); }} - /> - - + + + { setState(1); }} - /> - -
    -
    + > + + + +
    - - - -
    - -

    - {state == 0 - ? t('members') - : state == 1 - ? t('admins') - : t('users')} -

    -
    - {memberLoading || usersLoading || adminLoading ? ( - <> -
    - - ) : ( -
    - { - /* istanbul ignore next */ - state == 0 ? ( - memberData && - memberData.organizationsMemberConnection.edges.length > - 0 ? ( - (rowsPerPage > 0 - ? memberData.organizationsMemberConnection.edges.slice( - page * rowsPerPage, - page * rowsPerPage + rowsPerPage - ) - : memberData.organizationsMemberConnection.edges - ).map( - (datas: { - _id: string; - lastName: string; - firstName: string; - image: string; - email: string; - createdAt: string; - }) => { - return ( - - ); - } - ) - ) : ( - - ) - ) : state == 1 ? ( - adminData && - adminData.organizationsMemberConnection.edges.length > - 0 ? ( - (rowsPerPage > 0 - ? adminData.organizationsMemberConnection.edges.slice( - page * rowsPerPage, - page * rowsPerPage + rowsPerPage - ) - : adminData.organizationsMemberConnection.edges - ).map( - (datas: { - _id: string; - lastName: string; - firstName: string; - image: string; - email: string; - createdAt: string; - }) => { - return ( - - ); - } - ) - ) : ( - - ) - ) : state == 2 ? ( - usersData && usersData.users.length > 0 ? ( - (rowsPerPage > 0 - ? usersData.users.slice( - page * rowsPerPage, - page * rowsPerPage + rowsPerPage - ) - : usersData.users - ).map( - (datas: { - _id: string; - lastName: string; - firstName: string; - image: string; - email: string; - createdAt: string; - }) => { - return ( - - ); - } - ) - ) : ( - - ) - ) : ( - /* istanbul ignore next */ - - ) - } -
    - )} -
    -
    - + + + + + + {((state == 0 && memberData) || + (state == 1 && adminFilteredData) || + (state == 2 && usersData)) && ( +
    + row._id} + components={{ + NoRowsOverlay: () => ( + -
    - - <> - - - - -
    -
    -
    - - - + Nothing Found !! + + ), + }} + sx={{ + '&.MuiDataGrid-root .MuiDataGrid-cell:focus-within': { + outline: 'none !important', + }, + '&.MuiDataGrid-root .MuiDataGrid-columnHeader:focus-within': { + outline: 'none', + }, + '& .MuiDataGrid-row:hover': { + backgroundColor: 'transparent', + }, + '& .MuiDataGrid-row.Mui-hovered': { + backgroundColor: 'transparent', + }, + }} + getRowClassName={() => `${styles.rowBackground}`} + autoHeight + rowHeight={70} + rows={ + state === 0 + ? memberData.organizationsMemberConnection.edges + : state === 1 + ? adminFilteredData + : convertObject(usersData) + } + columns={columns} + isRowSelectable={() => false} + /> +
    + )} + {showRemoveModal && selectedMemId && ( + + )} + {showRemoveModal && selectedAdminId && ( + + )} ); } export default organizationPeople; + +// This code is used to remove 'user' object from the array index of userData and directly use store the properties at array index, this formatting is needed for DataGrid. + +interface InterfaceUser { + _id: string; + firstName: string; + lastName: string; + email: string; + image: string; + createdAt: string; +} +interface InterfaceOriginalObject { + users: { user: InterfaceUser }[]; +} +interface InterfaceConvertedObject { + users: InterfaceUser[]; +} +function convertObject(original: InterfaceOriginalObject): InterfaceUser[] { + const convertedObject: InterfaceConvertedObject = { + users: [], + }; + original.users.forEach((item) => { + convertedObject.users.push({ + firstName: item.user?.firstName, + lastName: item.user?.lastName, + email: item.user?.email, + image: item.user?.image, + createdAt: item.user?.createdAt, + _id: item.user?._id, + }); + }); + return convertedObject.users; +} diff --git a/src/screens/OrganizationVenues/OrganizationVenues.module.css b/src/screens/OrganizationVenues/OrganizationVenues.module.css new file mode 100644 index 0000000000..e4ac9d7575 --- /dev/null +++ b/src/screens/OrganizationVenues/OrganizationVenues.module.css @@ -0,0 +1,879 @@ +.navbarbg { + height: 60px; + background-color: white; + display: flex; + margin-bottom: 30px; + z-index: 1; + position: relative; + flex-direction: row; + justify-content: space-between; + box-shadow: 0px 0px 8px 2px #c8c8c8; +} + +.logo { + color: #707070; + margin-left: 0; + display: flex; + align-items: center; + text-decoration: none; +} + +.logo img { + margin-top: 0px; + margin-left: 10px; + height: 64px; + width: 70px; +} + +.logo > strong { + line-height: 1.5rem; + margin-left: -5px; + font-family: sans-serif; + font-size: 19px; + color: #707070; +} +.mainpage { + display: flex; + flex-direction: row; +} + +.sidebar:after { + background-color: #f7f7f7; + position: absolute; + width: 2px; + height: 600px; + top: 10px; + left: 94%; + display: block; +} + +.navitem { + padding-left: 27%; + padding-top: 12px; + padding-bottom: 12px; + cursor: pointer; +} + +.logintitle { + color: #707070; + font-weight: 600; + font-size: 20px; + margin-bottom: 30px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 15%; +} + +.logintitleadmin { + color: #707070; + font-weight: 600; + font-size: 18px; + margin-top: 50px; + margin-bottom: 40px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 30%; +} +.admindetails { + display: flex; + justify-content: space-between; +} +.admindetails > p { + margin-top: -12px; + margin-right: 30px; +} + +.mainpageright > hr { + margin-top: 20px; + width: 100%; + margin-left: -15px; + margin-right: -15px; + margin-bottom: 20px; +} +.justifysp { + display: flex; + justify-content: space-between; + margin-top: 20px; +} + +.addbtn { + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + border-radius: 5px; + font-size: 16px; + height: 60%; + color: white; + outline: none; + font-weight: 600; + cursor: pointer; + transition: + transform 0.2s, + box-shadow 0.2s; +} +.flexdir { + display: flex; + flex-direction: row; + justify-content: space-between; + border: none; +} + +.form_wrapper { + margin-top: 27px; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + position: absolute; + display: flex; + flex-direction: column; + padding: 40px 30px; + background: #ffffff; + border-color: #e8e5e5; + border-width: 5px; + border-radius: 10px; + max-height: 86vh; + overflow: auto; +} + +.form_wrapper form { + display: flex; + align-items: left; + justify-content: left; + flex-direction: column; +} +.logintitleinvite { + color: #707070; + font-weight: 600; + font-size: 20px; + margin-bottom: 20px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 40%; +} +.titlemodal { + color: #707070; + font-weight: 600; + font-size: 20px; + margin-bottom: 20px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 65%; +} +.cancel > i { + margin-top: 5px; + transform: scale(1.2); + cursor: pointer; + color: #707070; +} +.modalbody { + width: 50px; +} +.greenregbtn { + margin: 1rem 0 0; + margin-top: 15px; + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + padding: 10px 10px; + border-radius: 5px; + background-color: #31bb6b; + width: 100%; + font-size: 16px; + color: white; + outline: none; + font-weight: 600; + cursor: pointer; + transition: + transform 0.2s, + box-shadow 0.2s; + width: 100%; +} + +.datediv { + display: flex; + flex-direction: row; + margin-bottom: 15px; +} +.datebox { + width: 90%; + border-radius: 7px; + border-color: #e8e5e5; + outline: none; + box-shadow: none; + padding-top: 2px; + padding-bottom: 2px; + padding-right: 5px; + padding-left: 5px; + margin-right: 5px; + margin-left: 5px; +} +.checkboxdiv > label { + margin-right: 50px; +} +.checkboxdiv > label > input { + margin-left: 10px; +} +.loader, +.loader:after { + border-radius: 50%; + width: 10em; + height: 10em; +} +.loader { + margin: 60px auto; + margin-top: 35vh !important; + font-size: 10px; + position: relative; + text-indent: -9999em; + border-top: 1.1em solid rgba(255, 255, 255, 0.2); + border-right: 1.1em solid rgba(255, 255, 255, 0.2); + border-bottom: 1.1em solid rgba(255, 255, 255, 0.2); + border-left: 1.1em solid #febc59; + -webkit-transform: translateZ(0); + -ms-transform: translateZ(0); + transform: translateZ(0); + -webkit-animation: load8 1.1s infinite linear; + animation: load8 1.1s infinite linear; +} +@-webkit-keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} +@keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} +.dispflex { + display: flex; + align-items: center; +} +.dispflex > input { + border: none; + box-shadow: none; + margin-top: 5px; +} +.checkboxdiv { + display: flex; +} +.checkboxdiv > div { + width: 50%; +} + +@media only screen and (max-width: 600px) { + .form_wrapper { + width: 90%; + top: 45%; + } +} + +.navbarbg { + height: 60px; + background-color: white; + display: flex; + margin-bottom: 30px; + z-index: 1; + position: relative; + flex-direction: row; + justify-content: space-between; + box-shadow: 0px 0px 8px 2px #c8c8c8; +} + +.logo { + color: #707070; + margin-left: 0; + display: flex; + align-items: center; + text-decoration: none; +} + +.logo img { + margin-top: 0px; + margin-left: 10px; + height: 64px; + width: 70px; +} + +.logo > strong { + line-height: 1.5rem; + margin-left: -5px; + font-family: sans-serif; + font-size: 19px; + color: #707070; +} +.mainpage { + display: flex; + flex-direction: row; +} +.sidebar { + display: flex; + width: 100%; + justify-content: space-between; + z-index: 0; + padding-top: 10px; + margin: 0; + height: 100%; +} + +.navitem { + padding-left: 27%; + padding-top: 12px; + padding-bottom: 12px; + cursor: pointer; +} + +.logintitle { + color: #707070; + font-weight: 600; + font-size: 20px; + margin-bottom: 30px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 15%; +} +.searchtitle { + color: #707070; + font-weight: 600; + font-size: 20px; + margin-bottom: 20px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 60%; +} +.justifysp { + display: flex; + justify-content: space-between; +} +@media screen and (max-width: 575.5px) { + .justifysp { + padding-left: 55px; + display: flex; + justify-content: space-between; + width: 100%; + } + .mainpageright { + width: 98%; + } +} + +.logintitleadmin { + color: #707070; + font-weight: 600; + font-size: 18px; + margin-top: 50px; + margin-bottom: 40px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 40%; +} +.admindetails { + display: flex; + justify-content: space-between; +} +.admindetails > p { + margin-top: -12px; + margin-right: 30px; +} +.mainpageright > hr { + margin-top: 10px; + width: 97%; + margin-left: -15px; + margin-right: -15px; + margin-bottom: 20px; +} +.addbtnmain { + width: 60%; + margin-right: 50px; +} +.addbtn { + float: right; + width: 23%; + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + border-radius: 5px; + background-color: #31bb6b; + height: 40px; + font-size: 16px; + color: white; + outline: none; + font-weight: 600; + cursor: pointer; + margin-left: 30px; + transition: + transform 0.2s, + box-shadow 0.2s; +} +.flexdir { + display: flex; + flex-direction: row; + justify-content: space-between; + border: none; +} + +.form_wrapper { + margin-top: 27px; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + position: absolute; + display: flex; + flex-direction: column; + padding: 40px 30px; + background: #ffffff; + border-color: #e8e5e5; + border-width: 5px; + border-radius: 10px; +} + +.form_wrapper form { + display: flex; + align-items: left; + justify-content: left; + flex-direction: column; +} +.logintitleinvite { + color: #707070; + font-weight: 600; + font-size: 20px; + margin-bottom: 20px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 40%; +} +.cancel > i { + margin-top: 5px; + transform: scale(1.2); + cursor: pointer; + color: #707070; +} +.modalbody { + width: 50px; +} +.greenregbtn { + margin: 1rem 0 0; + margin-top: 10px; + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + padding: 10px 10px; + border-radius: 5px; + background-color: #31bb6b; + width: 100%; + font-size: 16px; + color: white; + outline: none; + font-weight: 600; + cursor: pointer; + transition: + transform 0.2s, + box-shadow 0.2s; + width: 100%; +} +.dropdown { + background-color: white; + border: 1px solid #31bb6b; + position: relative; + display: inline-block; + margin-top: 10px; + margin-bottom: 10px; + color: #31bb6b; +} +.input { + flex: 1; + position: relative; +} +/* .btnsContainer { + display: flex; + margin: 2.5rem 0 2.5rem 0; + width: 100%; + flex-direction: row; + justify-content: space-between; + } */ + +.btnsContainer { + display: flex; + margin: 2.5rem 0 2.5rem 0; +} + +.btnsContainer .input { + flex: 1; + position: relative; + min-width: 18rem; + width: 25rem; +} + +.btnsContainer .input button { + width: 52px; +} +.searchBtn { + margin-bottom: 10px; +} + +.inputField { + margin-top: 10px; + margin-bottom: 10px; + background-color: white; + box-shadow: 0 1px 1px #31bb6b; +} +.inputField > button { + padding-top: 10px; + padding-bottom: 10px; +} +.TableImage { + background-color: #31bb6b !important; + width: 50px !important; + height: 50px !important; + border-radius: 100% !important; + margin-right: 10px !important; +} +.tableHead { + background-color: #31bb6b !important; + color: white; + border-radius: 20px !important; + padding: 20px; + margin-top: 20px; +} + +.tableHead :nth-first-child() { + border-top-left-radius: 20px; +} + +.mainpageright > hr { + margin-top: 10px; + width: 100%; + margin-left: -15px; + margin-right: -15px; + margin-bottom: 20px; +} + +.loader, +.loader:after { + border-radius: 50%; + width: 10em; + height: 10em; +} +.loader { + margin: 60px auto; + margin-top: 35vh !important; + font-size: 10px; + position: relative; + text-indent: -9999em; + border-top: 1.1em solid rgba(255, 255, 255, 0.2); + border-right: 1.1em solid rgba(255, 255, 255, 0.2); + border-bottom: 1.1em solid rgba(255, 255, 255, 0.2); + border-left: 1.1em solid #febc59; + -webkit-transform: translateZ(0); + -ms-transform: translateZ(0); + transform: translateZ(0); + -webkit-animation: load8 1.1s infinite linear; + animation: load8 1.1s infinite linear; +} +.radio_buttons { + display: flex; + flex-direction: column; + gap: 0.5rem; + color: #707070; + font-weight: 600; + font-size: 14px; +} +.radio_buttons > input { + transform: scale(1.2); +} +.radio_buttons > label { + margin-top: -4px; + margin-left: 5px; + margin-right: 15px; +} +.preview { + display: flex; + position: relative; + width: 100%; + margin-top: 10px; + justify-content: center; +} +.preview img { + width: 400px; + height: auto; +} +.postimage { + border-radius: 0px; + width: 100%; + height: 12rem; + max-width: 100%; + max-height: 12rem; + object-fit: cover; + position: relative; + color: black; +} +.closeButtonP { + position: absolute; + top: 0px; + right: 0px; + background: transparent; + transform: scale(1.2); + cursor: pointer; + border: none; + color: #707070; + font-weight: 600; + font-size: 16px; + cursor: pointer; +} +.addbtn { + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + border-radius: 5px; + font-size: 16px; + height: 60%; + color: white; + outline: none; + font-weight: 600; + cursor: pointer; + transition: + transform 0.2s, + box-shadow 0.2s; +} +@-webkit-keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} +@keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} +.list_box { + height: 65vh; + overflow-y: auto; + width: auto; +} + +.cards h2 { + font-size: 20px; +} +.cards > h3 { + font-size: 17px; +} +.card { + width: 100%; + height: 20rem; + margin-bottom: 2rem; +} +.postimage { + border-radius: 0px; + width: 100%; + height: 12rem; + max-width: 100%; + max-height: 12rem; + object-fit: cover; + position: relative; + color: black; +} +.preview { + display: flex; + position: relative; + width: 100%; + margin-top: 10px; + justify-content: center; +} +.preview img { + width: 400px; + height: auto; +} +.preview video { + width: 400px; + height: auto; +} +.novenueimage { + border-radius: 0px; + width: 100%; + height: 12rem; + max-height: 12rem; + object-fit: cover; + position: relative; +} +.cards:hover { + filter: brightness(0.8); +} +.cards:hover::before { + opacity: 0.5; +} +.knowMoreText { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + opacity: 0; + color: white; + padding: 10px; + font-weight: bold; + font-size: 1.5rem; + transition: opacity 0.3s ease-in-out; +} + +.cards:hover .knowMoreText { + opacity: 1; +} +.modal { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + background-color: rgba( + 0, + 0, + 0, + 0.9 + ); /* Dark grey modal background with transparency */ + z-index: 9999; +} + +.modalContent { + display: flex; + align-items: center; + justify-content: center; + background-color: #fff; + padding: 20px; + max-width: 800px; + max-height: 600px; + overflow: auto; +} + +.modalImage { + flex: 1; + margin-right: 20px; + width: 25rem; + height: 15rem; +} +.nomodalImage { + flex: 1; + margin-right: 20px; + width: 100%; + height: 15rem; +} + +.modalImage img, +.modalImage video { + border-radius: 0px; + width: 100%; + height: 25rem; + max-width: 25rem; + max-height: 15rem; + object-fit: cover; + position: relative; +} +.modalInfo { + flex: 1; +} +.title { + font-size: 16px; + color: #000; + font-weight: 600; +} +.text { + font-size: 13px; + color: #000; + font-weight: 300; +} +.closeButton { + position: relative; + bottom: 5rem; + right: 10px; + padding: 4px; + background-color: red; /* Red close button color */ + color: #fff; + border: none; + cursor: pointer; +} +.closeButtonP { + position: absolute; + top: 0px; + right: 0px; + background: transparent; + transform: scale(1.2); + cursor: pointer; + border: none; + color: #707070; + font-weight: 600; + font-size: 16px; + cursor: pointer; +} +.cards:hover::after { + opacity: 1; + mix-blend-mode: normal; +} +.cards > p { + font-size: 14px; + margin-top: 0px; + margin-bottom: 7px; +} + +.cards:last-child:nth-last-child(odd) { + grid-column: auto / span 2; +} +.cards:first-child:nth-last-child(even), +.cards:first-child:nth-last-child(even) ~ .box { + grid-column: auto / span 1; +} + +.capacityLabel { + background-color: #31bb6b !important; + color: white; + height: 22.19px; + font-size: 12px; + font-weight: bolder; + padding: 0.1rem 0.3rem; + border-radius: 0.5rem; + position: relative; + overflow: hidden; +} + +.capacityLabel svg { + margin-bottom: 3px; +} + +::-webkit-scrollbar { + width: 20px; +} + +::-webkit-scrollbar-track { + background-color: transparent; +} + +::-webkit-scrollbar-thumb { + background-color: #d6dee1; +} + +::-webkit-scrollbar-thumb { + background-color: #d6dee1; + border-radius: 20px; +} + +::-webkit-scrollbar-thumb { + background-color: #d6dee1; + border-radius: 20px; + border: 6px solid transparent; + background-clip: content-box; +} diff --git a/src/screens/OrganizationVenues/OrganizationVenues.test.tsx b/src/screens/OrganizationVenues/OrganizationVenues.test.tsx new file mode 100644 index 0000000000..5b8b9933a1 --- /dev/null +++ b/src/screens/OrganizationVenues/OrganizationVenues.test.tsx @@ -0,0 +1,497 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import type { RenderResult } from '@testing-library/react'; +import { + act, + render, + screen, + fireEvent, + waitFor, +} from '@testing-library/react'; +import { Provider } from 'react-redux'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; +import 'jest-location-mock'; +import { I18nextProvider } from 'react-i18next'; +import OrganizationVenues from './OrganizationVenues'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { VENUE_LIST } from 'GraphQl/Queries/OrganizationQueries'; +import type { ApolloLink } from '@apollo/client'; +import { DELETE_VENUE_MUTATION } from 'GraphQl/Mutations/VenueMutations'; + +const MOCKS = [ + { + request: { + query: VENUE_LIST, + variables: { + orgId: 'orgId', + orderBy: 'capacity_ASC', + where: { + name_starts_with: '', + description_starts_with: undefined, + }, + }, + }, + result: { + data: { + getVenueByOrgId: [ + { + _id: 'venue1', + capacity: 1000, + description: 'Updated description for venue 1', + imageUrl: null, + name: 'Updated Venue 1', + organization: { + __typename: 'Organization', + _id: 'orgId', + }, + __typename: 'Venue', + }, + { + _id: 'venue2', + capacity: 1500, + description: 'Updated description for venue 2', + imageUrl: null, + name: 'Updated Venue 2', + organization: { + __typename: 'Organization', + _id: 'orgId', + }, + __typename: 'Venue', + }, + { + _id: 'venue3', + name: 'Venue with a name longer than 25 characters that should be truncated', + description: + 'Venue description that should be truncated because it is longer than 75 characters', + capacity: 2000, + imageUrl: null, + organization: { + _id: 'orgId', + __typename: 'Organization', + }, + __typename: 'Venue', + }, + ], + }, + }, + }, + { + request: { + query: VENUE_LIST, + variables: { + orgId: 'orgId', + orderBy: 'capacity_DESC', + where: { + name_starts_with: '', + description_starts_with: undefined, + }, + }, + }, + result: { + data: { + getVenueByOrgId: [ + { + _id: 'venue3', + name: 'Venue with a name longer than 25 characters that should be truncated', + description: + 'Venue description that should be truncated because it is longer than 75 characters', + capacity: 2000, + imageUrl: null, + organization: { + _id: 'orgId', + __typename: 'Organization', + }, + __typename: 'Venue', + }, + { + _id: 'venue2', + capacity: 1500, + description: 'Updated description for venue 2', + imageUrl: null, + name: 'Updated Venue 2', + organization: { + __typename: 'Organization', + _id: 'orgId', + }, + __typename: 'Venue', + }, + { + _id: 'venue1', + capacity: 1000, + description: 'Updated description for venue 1', + imageUrl: null, + name: 'Updated Venue 1', + organization: { + __typename: 'Organization', + _id: 'orgId', + }, + __typename: 'Venue', + }, + ], + }, + }, + }, + { + request: { + query: VENUE_LIST, + variables: { + orgId: 'orgId', + orderBy: 'capacity_DESC', + where: { + name_starts_with: 'Updated Venue 1', + description_starts_with: undefined, + }, + }, + }, + result: { + data: { + getVenueByOrgId: [ + { + _id: 'venue1', + capacity: 1000, + description: 'Updated description for venue 1', + imageUrl: null, + name: 'Updated Venue 1', + organization: { + __typename: 'Organization', + _id: 'orgId', + }, + __typename: 'Venue', + }, + ], + }, + }, + }, + { + request: { + query: VENUE_LIST, + variables: { + orgId: 'orgId', + orderBy: 'capacity_DESC', + where: { + name_starts_with: undefined, + description_starts_with: 'Updated description for venue 1', + }, + }, + }, + result: { + data: { + getVenueByOrgId: [ + { + _id: 'venue1', + capacity: 1000, + description: 'Updated description for venue 1', + imageUrl: null, + name: 'Updated Venue 1', + organization: { + __typename: 'Organization', + _id: 'orgId', + }, + __typename: 'Venue', + }, + ], + }, + }, + }, + { + request: { + query: DELETE_VENUE_MUTATION, + variables: { + id: 'venue1', + }, + }, + result: { + data: { + deleteVenue: { + _id: 'venue1', + __typename: 'Venue', + }, + }, + }, + }, + { + request: { + query: DELETE_VENUE_MUTATION, + variables: { + id: 'venue2', + }, + }, + result: { + data: { + deleteVenue: { + _id: 'venue2', + __typename: 'Venue', + }, + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + warning: jest.fn(), + error: jest.fn(), + }, +})); + +const renderOrganizationVenue = (link: ApolloLink): RenderResult => { + return render( + + + + + + } + /> + paramsError
    } + /> + + + + + , + ); +}; + +describe('OrganizationVenue with missing orgId', () => { + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: undefined }), + })); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + test('Redirect to /orglist when orgId is falsy/undefined', async () => { + render( + + + + + + } /> +
    } + /> + + + + + , + ); + + await waitFor(() => { + const paramsError = screen.getByTestId('paramsError'); + expect(paramsError).toBeInTheDocument(); + }); + }); +}); + +describe('Organisation Venues', () => { + global.alert = jest.fn(); + + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId' }), + })); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + test('searches the venue list correctly by Name', async () => { + renderOrganizationVenue(link); + await wait(); + + fireEvent.click(screen.getByTestId('searchByDrpdwn')); + fireEvent.click(screen.getByTestId('name')); + + const searchInput = screen.getByTestId('searchBy'); + fireEvent.change(searchInput, { + target: { value: 'Updated Venue 1' }, + }); + await waitFor(() => { + expect(screen.getByTestId('venue-item1')).toBeInTheDocument(); + expect(screen.queryByTestId('venue-item2')).not.toBeInTheDocument(); + }); + }); + + test('searches the venue list correctly by Description', async () => { + renderOrganizationVenue(link); + await waitFor(() => + expect(screen.getByTestId('orgvenueslist')).toBeInTheDocument(), + ); + + fireEvent.click(screen.getByTestId('searchByDrpdwn')); + fireEvent.click(screen.getByTestId('desc')); + + const searchInput = screen.getByTestId('searchBy'); + fireEvent.change(searchInput, { + target: { value: 'Updated description for venue 1' }, + }); + + await waitFor(() => { + expect(screen.getByTestId('venue-item1')).toBeInTheDocument(); + expect(screen.queryByTestId('venue-item2')).not.toBeInTheDocument(); + }); + }); + + test('sorts the venue list by lowest capacity correctly', async () => { + renderOrganizationVenue(link); + await waitFor(() => + expect(screen.getByTestId('orgvenueslist')).toBeInTheDocument(), + ); + + fireEvent.click(screen.getByTestId('sortVenues')); + fireEvent.click(screen.getByTestId('lowest')); + await waitFor(() => { + expect(screen.getByTestId('venue-item1')).toHaveTextContent( + /Updated Venue 1/i, + ); + expect(screen.getByTestId('venue-item2')).toHaveTextContent( + /Updated Venue 2/i, + ); + }); + }); + + test('sorts the venue list by highest capacity correctly', async () => { + renderOrganizationVenue(link); + await waitFor(() => + expect(screen.getByTestId('orgvenueslist')).toBeInTheDocument(), + ); + + fireEvent.click(screen.getByTestId('sortVenues')); + fireEvent.click(screen.getByTestId('highest')); + await waitFor(() => { + expect(screen.getByTestId('venue-item1')).toHaveTextContent( + /Venue with a name longer .../i, + ); + expect(screen.getByTestId('venue-item2')).toHaveTextContent( + /Updated Venue 2/i, + ); + }); + }); + + test('renders venue name with ellipsis if name is longer than 25 characters', async () => { + renderOrganizationVenue(link); + await waitFor(() => + expect(screen.getByTestId('orgvenueslist')).toBeInTheDocument(), + ); + + const venue = screen.getByTestId('venue-item1'); + expect(venue).toHaveTextContent(/Venue with a name longer .../i); + }); + + test('renders full venue name if name is less than or equal to 25 characters', async () => { + renderOrganizationVenue(link); + await waitFor(() => + expect(screen.getByTestId('orgvenueslist')).toBeInTheDocument(), + ); + + const venueName = screen.getByTestId('venue-item3'); + expect(venueName).toHaveTextContent('Updated Venue 1'); + }); + + test('renders venue description with ellipsis if description is longer than 75 characters', async () => { + renderOrganizationVenue(link); + await waitFor(() => + expect(screen.getByTestId('orgvenueslist')).toBeInTheDocument(), + ); + + const venue = screen.getByTestId('venue-item1'); + expect(venue).toHaveTextContent( + 'Venue description that should be truncated because it is longer than 75 cha...', + ); + }); + + test('renders full venue description if description is less than or equal to 75 characters', async () => { + renderOrganizationVenue(link); + await waitFor(() => + expect(screen.getByTestId('orgvenueslist')).toBeInTheDocument(), + ); + + const venue = screen.getByTestId('venue-item3'); + expect(venue).toHaveTextContent('Updated description for venue 1'); + }); + + test('Render modal to edit venue', async () => { + renderOrganizationVenue(link); + await waitFor(() => + expect(screen.getByTestId('orgvenueslist')).toBeInTheDocument(), + ); + + fireEvent.click(screen.getByTestId('updateVenueBtn1')); + await waitFor(() => { + expect(screen.getByTestId('venueForm')).toBeInTheDocument(); + }); + }); + + test('Render Modal to add event', async () => { + renderOrganizationVenue(link); + await waitFor(() => + expect(screen.getByTestId('orgvenueslist')).toBeInTheDocument(), + ); + + fireEvent.click(screen.getByTestId('createVenueBtn')); + await waitFor(() => { + expect(screen.getByTestId('venueForm')).toBeInTheDocument(); + }); + }); + + test('calls handleDelete when delete button is clicked', async () => { + renderOrganizationVenue(link); + await waitFor(() => + expect(screen.getByTestId('orgvenueslist')).toBeInTheDocument(), + ); + + const deleteButton = screen.getByTestId('deleteVenueBtn3'); + fireEvent.click(deleteButton); + await wait(); + await waitFor(() => { + const deletedVenue = screen.queryByTestId('venue-item3'); + expect(deletedVenue).not.toHaveTextContent(/Updated Venue 2/i); + }); + }); + + test('displays loader when data is loading', () => { + renderOrganizationVenue(link); + expect(screen.getByTestId('spinner-wrapper')).toBeInTheDocument(); + }); + + test('renders without crashing', async () => { + renderOrganizationVenue(link); + waitFor(() => { + expect(screen.findByTestId('orgvenueslist')).toBeInTheDocument(); + }); + }); + + test('renders the venue list correctly', async () => { + renderOrganizationVenue(link); + waitFor(() => { + expect(screen.getByTestId('venueRow2')).toBeInTheDocument(); + expect(screen.getByTestId('venueRow1')).toBeInTheDocument(); + }); + }); +}); diff --git a/src/screens/OrganizationVenues/OrganizationVenues.tsx b/src/screens/OrganizationVenues/OrganizationVenues.tsx new file mode 100644 index 0000000000..4005816d16 --- /dev/null +++ b/src/screens/OrganizationVenues/OrganizationVenues.tsx @@ -0,0 +1,249 @@ +import React, { useEffect, useState } from 'react'; +import Button from 'react-bootstrap/Button'; +import { useTranslation } from 'react-i18next'; +import styles from './OrganizationVenues.module.css'; +import { errorHandler } from 'utils/errorHandler'; +import { useMutation, useQuery } from '@apollo/client'; +import Col from 'react-bootstrap/Col'; +import { VENUE_LIST } from 'GraphQl/Queries/OrganizationQueries'; +import Loader from 'components/Loader/Loader'; +import { Navigate, useParams } from 'react-router-dom'; +import VenueModal from 'components/Venues/VenueModal'; +import { Dropdown, Form } from 'react-bootstrap'; +import { Search, Sort } from '@mui/icons-material'; +import { DELETE_VENUE_MUTATION } from 'GraphQl/Mutations/VenueMutations'; +import type { InterfaceQueryVenueListItem } from 'utils/interfaces'; +import VenueCard from 'components/Venues/VenueCard'; + +function organizationVenues(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'organizationVenues', + }); + + document.title = t('title'); + const [venueModal, setVenueModal] = useState(false); + const [venueModalMode, setVenueModalMode] = useState<'edit' | 'create'>( + 'create', + ); + const [searchTerm, setSearchTerm] = useState(''); + const [searchBy, setSearchBy] = useState<'name' | 'desc'>('name'); + const [sortOrder, setSortOrder] = useState<'highest' | 'lowest'>('highest'); + const [editVenueData, setEditVenueData] = + useState(null); + const [venues, setVenues] = useState([]); + + const { orgId } = useParams(); + if (!orgId) { + return ; + } + + const { + data: venueData, + loading: venueLoading, + error: venueError, + refetch: venueRefetch, + } = useQuery(VENUE_LIST, { + variables: { + orgId: orgId, + orderBy: sortOrder === 'highest' ? 'capacity_DESC' : 'capacity_ASC', + where: { + name_starts_with: searchBy === 'name' ? searchTerm : undefined, + description_starts_with: searchBy === 'desc' ? searchTerm : undefined, + }, + }, + }); + + const [deleteVenue] = useMutation(DELETE_VENUE_MUTATION); + + const handleDelete = async (venueId: string): Promise => { + try { + await deleteVenue({ + variables: { id: venueId }, + }); + venueRefetch(); + } catch (error) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + + const handleSearchChange = ( + event: React.ChangeEvent, + ): void => { + setSearchTerm(event.target.value); + }; + + const handleSortChange = (order: 'highest' | 'lowest'): void => { + setSortOrder(order); + }; + + const toggleVenueModal = (): void => { + setVenueModal(!venueModal); + }; + + const showEditVenueModal = (venueItem: InterfaceQueryVenueListItem): void => { + setVenueModalMode('edit'); + setEditVenueData(venueItem); + toggleVenueModal(); + }; + + const showCreateVenueModal = (): void => { + setVenueModalMode('create'); + setEditVenueData(null); + toggleVenueModal(); + }; + /* istanbul ignore next */ + if (venueError) { + errorHandler(t, venueError); + } + + useEffect(() => { + if (venueData && venueData.getVenueByOrgId) { + setVenues(venueData.getVenueByOrgId); + } + }, [venueData]); + + return ( + <> +
    +
    + + +
    +
    +
    + + +
    + +
    +
    + + +
    + {venueLoading ? ( + <> + + + ) : ( +
    + {venues.length ? ( + venues.map( + (venueItem: InterfaceQueryVenueListItem, index: number) => ( + + ), + ) + ) : ( +
    {t('noVenues')}
    + )} +
    + )} +
    + + + + ); +} + +export default organizationVenues; diff --git a/src/screens/PageNotFound/PageNotFound.test.tsx b/src/screens/PageNotFound/PageNotFound.test.tsx index f02b5ccfd0..af9325ca7d 100644 --- a/src/screens/PageNotFound/PageNotFound.test.tsx +++ b/src/screens/PageNotFound/PageNotFound.test.tsx @@ -7,9 +7,38 @@ import { I18nextProvider } from 'react-i18next'; import { store } from 'state/store'; import PageNotFound from './PageNotFound'; import i18nForTest from 'utils/i18nForTest'; +import useLocalStorage from 'utils/useLocalstorage'; + +const { setItem } = useLocalStorage(); describe('Testing Page not found component', () => { - test('Component should be rendered properly', () => { + test('Component should be rendered properly for User', () => { + //setItem('AdminFor', undefined); + render( + + + + + + + , + ); + + expect(screen.getByText(/Talawa User/i)).toBeTruthy(); + expect(screen.getByText(/404/i)).toBeTruthy(); + expect( + screen.getByText(/Oops! The Page you requested was not found!/i), + ).toBeTruthy(); + expect(screen.getByText(/Back to Home/i)).toBeTruthy(); + }); + + test('Component should be rendered properly for ADMIN or SUPERADMIN', () => { + setItem('AdminFor', [ + { + _id: '6537904485008f171cf29924', + __typename: 'Organization', + }, + ]); render( @@ -17,13 +46,13 @@ describe('Testing Page not found component', () => { - + , ); expect(screen.getByText(/Talawa Admin/i)).toBeTruthy(); expect(screen.getByText(/404/i)).toBeTruthy(); expect( - screen.getByText(/Oops! The Page you requested was not found!/i) + screen.getByText(/Oops! The Page you requested was not found!/i), ).toBeTruthy(); expect(screen.getByText(/Back to Home/i)).toBeTruthy(); }); diff --git a/src/screens/PageNotFound/PageNotFound.tsx b/src/screens/PageNotFound/PageNotFound.tsx index ddc56cdcac..445868b4e8 100644 --- a/src/screens/PageNotFound/PageNotFound.tsx +++ b/src/screens/PageNotFound/PageNotFound.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { Link } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; +import useLocalStorage from 'utils/useLocalstorage'; import styles from './PageNotFound.module.css'; import Logo from 'assets/images/talawa-logo-200x200.png'; @@ -12,20 +13,36 @@ const PageNotFound = (): JSX.Element => { document.title = t('title'); + const { getItem } = useLocalStorage(); + const adminFor = getItem('AdminFor'); + return (
    Logo -

    {t('talawaAdmin')}

    + {adminFor != undefined ? ( +

    {t('talawaAdmin')}

    + ) : ( +

    {t('talawaUser')}

    + )}

    {t('404')}

    {t('notFoundMsg')}

    - - {t('backToHome')} - + {adminFor != undefined ? ( + + {t('backToHome')} + + ) : ( + + {t('backToHome')} + + )}
    ); diff --git a/src/screens/Requests/Requests.module.css b/src/screens/Requests/Requests.module.css index 0750dba108..b23869c8d0 100644 --- a/src/screens/Requests/Requests.module.css +++ b/src/screens/Requests/Requests.module.css @@ -18,17 +18,23 @@ flex: 1; position: relative; } + .btnsContainer .input { - width: 70%; + width: 50%; position: relative; } .btnsContainer input { - outline: 1px solid var(--bs-gray-400); + box-sizing: border-box; + background: #fcfcfc; + border: 1px solid #dddddd; + box-shadow: 5px 5px 4px rgba(49, 187, 107, 0.12); + border-radius: 8px; } .btnsContainer .inputContainer button { - width: 52px; + width: 55px; + height: 55px; } .listBox { @@ -36,6 +42,29 @@ flex: 1; } +.listTable { + width: 100%; + box-sizing: border-box; + background: #ffffff; + border: 1px solid #0000001f; + border-radius: 24px; +} + +.listBox .customTable { + margin-bottom: 0%; +} + +.requestsTable thead th { + font-size: 20px; + font-weight: 400; + line-height: 24px; + letter-spacing: 0em; + text-align: left; + color: #000000; + border-bottom: 1px solid #dddddd; + padding: 1.5rem; +} + .notFound { flex: 1; display: flex; @@ -83,10 +112,6 @@ flex: 1; } - .btnsContainer .btnsBlock div[title='Sort organizations'] { - margin-right: 0.5rem; - } - .btnsContainer .btnsBlock button { margin-bottom: 1rem; margin-right: 0; diff --git a/src/screens/Requests/Requests.test.tsx b/src/screens/Requests/Requests.test.tsx index f8247905bc..9380653e7e 100644 --- a/src/screens/Requests/Requests.test.tsx +++ b/src/screens/Requests/Requests.test.tsx @@ -6,18 +6,32 @@ import 'jest-location-mock'; import { I18nextProvider } from 'react-i18next'; import { Provider } from 'react-redux'; import { BrowserRouter } from 'react-router-dom'; - -import userEvent from '@testing-library/user-event'; import { ToastContainer } from 'react-toastify'; +import userEvent from '@testing-library/user-event'; import { store } from 'state/store'; import { StaticMockLink } from 'utils/StaticMockLink'; import i18nForTest from 'utils/i18nForTest'; import Requests from './Requests'; -import { EMPTY_ORG_MOCKS, MOCKS, ORG_LIST_MOCK } from './RequestsMocks'; +import { + EMPTY_MOCKS, + MOCKS_WITH_ERROR, + MOCKS, + MOCKS2, + EMPTY_REQUEST_MOCKS, + MOCKS3, + MOCKS4, +} from './RequestsMocks'; +import useLocalStorage from 'utils/useLocalstorage'; + +const { setItem, removeItem } = useLocalStorage(); const link = new StaticMockLink(MOCKS, true); -const link2 = new StaticMockLink(EMPTY_ORG_MOCKS, true); -const link3 = new StaticMockLink(ORG_LIST_MOCK, true); +const link2 = new StaticMockLink(EMPTY_MOCKS, true); +const link3 = new StaticMockLink(EMPTY_REQUEST_MOCKS, true); +const link4 = new StaticMockLink(MOCKS2, true); +const link5 = new StaticMockLink(MOCKS_WITH_ERROR, true); +const link6 = new StaticMockLink(MOCKS3, true); +const link7 = new StaticMockLink(MOCKS4, true); async function wait(ms = 100): Promise { await act(() => { @@ -28,20 +42,20 @@ async function wait(ms = 100): Promise { } beforeEach(() => { - localStorage.setItem('UserType', 'SUPERADMIN'); - localStorage.setItem('FirstName', 'John'); - localStorage.setItem('LastName', 'Doe'); + setItem('id', 'user1'); + setItem('AdminFor', [{ _id: 'org1', __typename: 'Organization' }]); + setItem('SuperAdmin', false); }); afterEach(() => { localStorage.clear(); }); -describe('Testing Request screen', () => { +describe('Testing Requests screen', () => { test('Component should be rendered properly', async () => { - window.location.assign('/orglist'); + const loadMoreRequests = jest.fn(); render( - + @@ -49,17 +63,35 @@ describe('Testing Request screen', () => { - + , ); await wait(); - expect(screen.getByTestId(/searchByName/i)).toBeInTheDocument(); - expect(window.location).toBeAt('/orglist'); + expect(screen.getByTestId('testComp')).toBeInTheDocument(); + expect(screen.getByText('Scott Tony')).toBeInTheDocument(); }); - test('Testing, If userType is not SUPERADMIN', async () => { - localStorage.setItem('UserType', 'USER'); + test(`Component should be rendered properly when user is not Admin + and or userId does not exists in localstorage`, async () => { + setItem('id', ''); + removeItem('AdminFor'); + removeItem('SuperAdmin'); + render( + + + + + + + + + , + ); + + await wait(); + }); + test('Component should be rendered properly when user is Admin', async () => { render( @@ -69,15 +101,16 @@ describe('Testing Request screen', () => { - + , ); await wait(); }); - test('Testing seach by name functionality', async () => { + test('Redirecting on error', async () => { + setItem('SuperAdmin', true); render( - + @@ -85,13 +118,52 @@ describe('Testing Request screen', () => { - + , ); await wait(); + expect(window.location.href).toEqual('http://localhost/'); }); - test('Testing accept user functionality', async () => { + test('Testing Search requests functionality', async () => { + render( + + + + + + + + + , + ); + + await wait(); + const searchBtn = screen.getByTestId('searchButton'); + const search1 = 'John'; + userEvent.type(screen.getByTestId(/searchByName/i), search1); + userEvent.click(searchBtn); + await wait(); + + const search2 = 'Pete{backspace}{backspace}{backspace}{backspace}'; + userEvent.type(screen.getByTestId(/searchByName/i), search2); + + const search3 = + 'John{backspace}{backspace}{backspace}{backspace}Sam{backspace}{backspace}{backspace}'; + userEvent.type(screen.getByTestId(/searchByName/i), search3); + + const search4 = 'Sam{backspace}{backspace}P{backspace}'; + userEvent.type(screen.getByTestId(/searchByName/i), search4); + + const search5 = 'Xe'; + userEvent.type(screen.getByTestId(/searchByName/i), search5); + userEvent.clear(screen.getByTestId(/searchByName/i)); + userEvent.type(screen.getByTestId(/searchByName/i), ''); + userEvent.click(searchBtn); + await wait(); + }); + + test('Testing search not found', async () => { render( @@ -101,14 +173,18 @@ describe('Testing Request screen', () => { - + , ); await wait(); - userEvent.click(screen.getByTestId(/acceptUser456/i)); + + const search = 'hello{enter}'; + await act(() => + userEvent.type(screen.getByTestId(/searchByName/i), search), + ); }); - test('Testing reject user functionality', async () => { + test('Testing Request data is not present', async () => { render( @@ -118,15 +194,15 @@ describe('Testing Request screen', () => { - + , ); await wait(); - userEvent.click(screen.getByTestId(/rejectUser456/i)); + expect(screen.getByText(/No Request Found/i)).toBeTruthy(); }); test('Should render warning alert when there are no organizations', async () => { - const { container } = render( + render( @@ -136,19 +212,19 @@ describe('Testing Request screen', () => { - + , ); await wait(200); - - expect(container.textContent).toMatch( - 'Organizations not found, please create an organization through dashboard' - ); + expect(screen.queryByText('Organizations Not Found')).toBeInTheDocument(); + expect( + screen.queryByText('Please create an organization through dashboard'), + ).toBeInTheDocument(); }); test('Should not render warning alert when there are organizations present', async () => { const { container } = render( - + @@ -157,13 +233,60 @@ describe('Testing Request screen', () => { - + , ); await wait(); expect(container.textContent).not.toMatch( - 'Organizations not found, please create an organization through dashboard' + 'Organizations not found, please create an organization through dashboard', + ); + }); + + test('Should render properly when there are no organizations present in requestsData', async () => { + render( + + + + + + + + + + , + ); + + await wait(); + }); + + test('check for rerendering', async () => { + const { rerender } = render( + + + + + + + + + + , ); + + await wait(); + rerender( + + + + + + + + + + , + ); + await wait(); }); }); diff --git a/src/screens/Requests/Requests.tsx b/src/screens/Requests/Requests.tsx index b0b0a5f6ad..16a85f15cd 100644 --- a/src/screens/Requests/Requests.tsx +++ b/src/screens/Requests/Requests.tsx @@ -1,87 +1,80 @@ -import React from 'react'; -import { useMutation, useQuery } from '@apollo/client'; -import type { ApolloError } from '@apollo/client'; -import { useEffect, useState } from 'react'; -import { Dropdown, Form, Table } from 'react-bootstrap'; +import { useQuery } from '@apollo/client'; +import React, { useEffect, useState } from 'react'; +import { Form, Table } from 'react-bootstrap'; import Button from 'react-bootstrap/Button'; import { useTranslation } from 'react-i18next'; import { toast } from 'react-toastify'; - import { Search } from '@mui/icons-material'; -import FilterListIcon from '@mui/icons-material/FilterList'; -import SortIcon from '@mui/icons-material/Sort'; -import { - ACCEPT_ADMIN_MUTATION, - REJECT_ADMIN_MUTATION, -} from 'GraphQl/Mutations/mutations'; import { + MEMBERSHIP_REQUEST, ORGANIZATION_CONNECTION_LIST, - USER_LIST_REQUEST, - USER_ORGANIZATION_LIST, } from 'GraphQl/Queries/Queries'; -import SuperAdminScreen from 'components/SuperAdminScreen/SuperAdminScreen'; import TableLoader from 'components/TableLoader/TableLoader'; +import RequestsTableItem from 'components/RequestsTableItem/RequestsTableItem'; import InfiniteScroll from 'react-infinite-scroll-component'; -import debounce from 'utils/debounce'; -import { errorHandler } from 'utils/errorHandler'; -import type { - InterfaceOrgConnectionType, - InterfaceQueryRequestListItem, - InterfaceUserType, -} from 'utils/interfaces'; +import type { InterfaceQueryMembershipRequestsListItem } from 'utils/interfaces'; import styles from './Requests.module.css'; +import useLocalStorage from 'utils/useLocalstorage'; +import { useParams } from 'react-router-dom'; + +interface InterfaceRequestsListItem { + _id: string; + user: { + firstName: string; + lastName: string; + email: string; + }; +} const Requests = (): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'requests' }); document.title = t('title'); - const perPageResult = 12; + const { getItem } = useLocalStorage(); + + const perPageResult = 8; const [isLoading, setIsLoading] = useState(true); - const [hasMore, sethasMore] = useState(true); + const [hasMore, setHasMore] = useState(true); const [isLoadingMore, setIsLoadingMore] = useState(false); - const [searchByName, setSearchByName] = useState(''); + const [searchByName, setSearchByName] = useState(''); + const userRole = getItem('SuperAdmin') + ? 'SUPERADMIN' + : getItem('AdminFor') + ? 'ADMIN' + : 'USER'; + const { orgId = '' } = useParams(); + const organizationId = orgId; - const [acceptAdminFunc] = useMutation(ACCEPT_ADMIN_MUTATION); - const [rejectAdminFunc] = useMutation(REJECT_ADMIN_MUTATION); - const { - data: currentUserData, - }: { - data?: InterfaceUserType; - error?: ApolloError; - } = useQuery(USER_ORGANIZATION_LIST, { - variables: { id: localStorage.getItem('id') }, - }); - - const { - data: usersData, - loading: loading, - fetchMore, - refetch: refetchUsers, - }: { - data?: { users: InterfaceQueryRequestListItem[] }; - loading: boolean; - fetchMore: any; - refetch: any; - error?: ApolloError; - } = useQuery(USER_LIST_REQUEST, { + const { data, loading, fetchMore, refetch } = useQuery(MEMBERSHIP_REQUEST, { variables: { + id: organizationId, first: perPageResult, skip: 0, - userType: 'ADMIN', - adminApproved: false, - firstName_contains: searchByName, - lastName_contains: '', + firstName_contains: '', }, notifyOnNetworkStatusChange: true, }); - const { - data: dataOrgs, - }: { - data?: InterfaceOrgConnectionType; - error?: ApolloError; - } = useQuery(ORGANIZATION_CONNECTION_LIST); + const { data: orgsData } = useQuery(ORGANIZATION_CONNECTION_LIST); + const [displayedRequests, setDisplayedRequests] = useState( + data?.organizations[0]?.membershipRequests || [], + ); + + // Manage loading more state + useEffect(() => { + if (!data) { + return; + } + + const membershipRequests = data.organizations[0].membershipRequests; + + if (membershipRequests.length < perPageResult) { + setHasMore(false); + } + + setDisplayedRequests(membershipRequests); + }, [data]); // To clear the search when the component is unmounted useEffect(() => { @@ -90,34 +83,24 @@ const Requests = (): JSX.Element => { }; }, []); - // To manage loading states + // Warn if there is no organization useEffect(() => { - if (!usersData) { + if (!orgsData) { return; } - if (usersData.users.length < perPageResult) { - sethasMore(false); + + if (orgsData.organizationsConnection.length === 0) { + toast.warning(t('noOrgError')); } - }, [usersData]); + }, [orgsData]); - // If the user is not Superadmin, redirect to Organizations screen + // Send to orgList page if user is not admin useEffect(() => { - const userType = localStorage.getItem('UserType'); - if (userType != 'SUPERADMIN') { + if (userRole != 'ADMIN' && userRole != 'SUPERADMIN') { window.location.assign('/orglist'); } }, []); - // Check if there are no organizations then show a warning - useEffect(() => { - if (!dataOrgs) { - return; - } - if (dataOrgs.organizationsConnection.length === 0) { - toast.warning(t('noOrgError')); - } - }, [dataOrgs]); - // Manage the loading state useEffect(() => { if (loading && isLoadingMore == false) { @@ -127,108 +110,85 @@ const Requests = (): JSX.Element => { } }, [loading]); - /* istanbul ignore next */ + const handleSearch = (value: string): void => { + setSearchByName(value); + if (value === '') { + resetAndRefetch(); + return; + } + refetch({ + id: organizationId, + firstName_contains: value, + // Later on we can add several search and filter options + }); + }; + + const handleSearchByEnter = ( + e: React.KeyboardEvent, + ): void => { + if (e.key === 'Enter') { + const { value } = e.currentTarget; + handleSearch(value); + } + }; + + const handleSearchByBtnClick = (): void => { + const inputElement = document.getElementById( + 'searchRequests', + ) as HTMLInputElement; + const inputValue = inputElement?.value || ''; + handleSearch(inputValue); + }; + const resetAndRefetch = (): void => { - refetchUsers({ + refetch({ first: perPageResult, skip: 0, - userType: 'ADMIN', - adminApproved: false, firstName_contains: '', - lastName_contains: '', }); - sethasMore(true); + setHasMore(true); }; /* istanbul ignore next */ const loadMoreRequests = (): void => { setIsLoadingMore(true); fetchMore({ variables: { - skip: usersData?.users.length || 0, - userType: 'ADMIN', - adminApproved: false, + id: organizationId, + skip: data?.organizations?.[0]?.membershipRequests?.length || 0, firstName_contains: searchByName, - lastName_contains: '', }, updateQuery: ( - prev: { users: InterfaceQueryRequestListItem[] } | undefined, + prev: InterfaceQueryMembershipRequestsListItem | undefined, { fetchMoreResult, }: { - fetchMoreResult: - | { users: InterfaceQueryRequestListItem[] } - | undefined; - } - ): { users: InterfaceQueryRequestListItem[] } | undefined => { + fetchMoreResult: InterfaceQueryMembershipRequestsListItem | undefined; + }, + ): InterfaceQueryMembershipRequestsListItem | undefined => { setIsLoadingMore(false); if (!fetchMoreResult) return prev; - if (fetchMoreResult.users.length < perPageResult) { - sethasMore(false); + const newMembershipRequests = + fetchMoreResult.organizations[0].membershipRequests || []; + if (newMembershipRequests.length < perPageResult) { + setHasMore(false); } return { - users: [...(prev?.users || []), ...(fetchMoreResult.users || [])], + organizations: [ + { + _id: organizationId, + membershipRequests: [ + ...(prev?.organizations[0].membershipRequests || []), + ...newMembershipRequests, + ], + }, + ], }; }, }); }; - const acceptAdmin = async (userId: any): Promise => { - try { - const { data } = await acceptAdminFunc({ - variables: { - id: userId, - }, - }); - - /* istanbul ignore next */ - if (data) { - toast.success(t('userApproved')); - resetAndRefetch(); - } - } catch (error: any) { - /* istanbul ignore next */ - errorHandler(t, error); - } - }; - - const rejectAdmin = async (userId: any): Promise => { - try { - const { data } = await rejectAdminFunc({ - variables: { - id: userId, - }, - }); - - /* istanbul ignore next */ - if (data) { - toast.success(t('userRejected')); - resetAndRefetch(); - } - } catch (error: any) { - /* istanbul ignore next */ - errorHandler(t, error); - } - }; - - /* istanbul ignore next */ - const handleSearchByName = async (e: any): Promise => { - const { value } = e.target; - setSearchByName(value); - if (value === '') { - resetAndRefetch(); - return; - } - await refetchUsers({ - firstName_contains: value, - lastName_contains: '', - // Later on we can add several search and filter options - }); - }; - - const debouncedHandleSearchByName = debounce(handleSearchByName); - const headerTitles: string[] = [ - '#', + t('sl_no'), t('name'), t('email'), t('accept'), @@ -237,142 +197,112 @@ const Requests = (): JSX.Element => { return ( <> - - {/* Buttons Container */} -
    -
    -
    +
    +
    + + -
    -
    -
    -
    - - -
    + +
    - {isLoading == false && - usersData?.users.length === 0 && +
    + {!isLoading && orgsData?.organizationsConnection.length === 0 ? ( +
    +

    {t('noOrgErrorTitle')}

    +
    {t('noOrgErrorDescription')}
    +
    + ) : !isLoading && + data && + displayedRequests.length === 0 && searchByName.length > 0 ? ( -
    -

    - {t('noResultsFoundFor')} "{searchByName}" -

    -
    - ) : isLoading == false && usersData?.users.length === 0 ? ( -
    -

    {t('noRequestFound')}

    -
    - ) : isLoading ? ( - - ) : ( - } - hasMore={hasMore} - className={styles.listBox} - data-testid="organizations-list" - endMessage={ -
    -
    {t('endOfResults')}
    -
    - } - > - - - - {headerTitles.map((title: string, index: number) => { - return ( - - ); - })} - - - - {usersData?.users && - usersData.users.map((user, index) => { - return ( - - - - - - - - ); - })} - -
    - {title} -
    {index + 1}{`${user.firstName} ${user.lastName}`}{user.email} - - - -
    -
    - )} - +
    +

    + {t('noResultsFoundFor')} "{searchByName}" +

    +
    + ) : !isLoading && data && displayedRequests.length === 0 ? ( +
    +

    {t('noRequestsFound')}

    +
    + ) : ( +
    + {isLoading ? ( + + ) : ( + + } + hasMore={hasMore} + className={styles.listTable} + data-testid="requests-list" + endMessage={ +
    +
    {t('endOfResults')}
    +
    + } + > + + + + {headerTitles.map((title: string, index: number) => { + return ( + + ); + })} + + + + {data && + displayedRequests.map( + (request: InterfaceRequestsListItem, index: number) => { + return ( + + ); + }, + )} + +
    + {title} +
    +
    + )} +
    + )} ); }; diff --git a/src/screens/Requests/RequestsMocks.ts b/src/screens/Requests/RequestsMocks.ts index a57bff7c83..6dc22dd58e 100644 --- a/src/screens/Requests/RequestsMocks.ts +++ b/src/screens/Requests/RequestsMocks.ts @@ -1,118 +1,194 @@ import { - ACCEPT_ADMIN_MUTATION, - REJECT_ADMIN_MUTATION, -} from 'GraphQl/Mutations/mutations'; -import { + MEMBERSHIP_REQUEST, ORGANIZATION_CONNECTION_LIST, - USER_LIST_REQUEST, - USER_ORGANIZATION_LIST, } from 'GraphQl/Queries/Queries'; -export const MOCKS = [ +export const EMPTY_REQUEST_MOCKS = [ { request: { - query: USER_ORGANIZATION_LIST, - variables: { id: localStorage.getItem('id') }, + query: ORGANIZATION_CONNECTION_LIST, }, result: { data: { - user: { - _id: '123', - userType: 'SUPERADMIN', - firstName: 'John', - lastName: 'Doe', - image: '', - email: 'John_Does_Palasidoes@gmail.com', - adminFor: { - _id: 1, - name: 'Akatsuki', - image: '', + organizationsConnection: [ + { + _id: 'org1', + image: null, + creator: { + firstName: 'John', + lastName: 'Doe', + }, + name: 'Palisadoes', + members: [ + { + _id: 'user1', + }, + ], + admins: [ + { + _id: 'user1', + }, + ], + createdAt: '09/11/2001', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, }, - }, + ], }, }, }, { request: { - query: USER_LIST_REQUEST, + query: MEMBERSHIP_REQUEST, variables: { - adminApproved: false, - first: 12, - firstName_contains: '', - lastName_contains: '', + id: '', skip: 0, - userType: 'ADMIN', + first: 8, + firstName_contains: '', + }, + }, + result: { + data: { + organizations: [ + { + _id: 'org1', + membershipRequests: [], + }, + ], }, - notifyOnNetworkStatusChange: true, + }, + }, +]; + +export const MOCKS = [ + { + request: { + query: ORGANIZATION_CONNECTION_LIST, }, result: { data: { - users: [ + organizationsConnection: [ { - _id: '123', - firstName: 'John', - lastName: 'Doe', - image: 'dummyImage', - email: 'johndoe@gmail.com', - userType: 'SUPERADMIN', - adminApproved: true, - createdAt: '20/06/2022', - organizationsBlockedBy: [ - { - _id: '256', - name: 'ABC', + _id: 'org1', + image: null, + creator: { + firstName: 'John', + lastName: 'Doe', + }, + name: 'Palisadoes', + members: [ + { + _id: 'user1', }, ], - joinedOrganizations: [ + admins: [ { - __typename: 'Organization', - _id: '6401ff65ce8e8406b8f07af1', + _id: 'user1', }, ], + createdAt: '09/11/2001', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, }, + ], + }, + }, + }, + { + request: { + query: MEMBERSHIP_REQUEST, + variables: { + id: '', + skip: 0, + first: 8, + firstName_contains: '', + }, + }, + result: { + data: { + organizations: [ { - _id: '456', - firstName: 'Sam', - lastName: 'Smith', - image: 'dummyImage', - email: 'samsmith@gmail.com', - userType: 'ADMIN', - adminApproved: false, - createdAt: '20/06/2022', - organizationsBlockedBy: [ - { - _id: '256', - name: 'ABC', + _id: '', + membershipRequests: [ + { + _id: '1', + user: { + _id: 'user2', + firstName: 'Scott', + lastName: 'Tony', + email: 'testuser3@example.com', + }, }, - ], - joinedOrganizations: [ { - __typename: 'Organization', - _id: '6401ff65ce8e8406b8f07af2', + _id: '2', + user: { + _id: 'user3', + firstName: 'Teresa', + lastName: 'Bradley', + email: 'testuser4@example.com', + }, }, ], }, + ], + }, + }, + }, +]; + +export const MOCKS4 = [ + { + request: { + query: ORGANIZATION_CONNECTION_LIST, + }, + result: { + data: { + organizationsConnection: [ { - _id: '789', - firstName: 'Peter', - lastName: 'Parker', - image: 'dummyImage', - email: 'peterparker@gmail.com', - userType: 'USER', - adminApproved: true, - createdAt: '20/06/2022', - organizationsBlockedBy: [ - { - _id: '256', - name: 'ABC', + _id: 'org1', + image: null, + creator: { + firstName: 'John', + lastName: 'Doe', + }, + name: 'Palisadoes', + members: [ + { + _id: 'user1', }, ], - joinedOrganizations: [ + admins: [ { - __typename: 'Organization', - _id: '6401ff65ce8e8406b8f07af3', + _id: 'user1', }, ], + createdAt: '09/11/2001', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, }, ], }, @@ -120,73 +196,270 @@ export const MOCKS = [ }, { request: { - query: ACCEPT_ADMIN_MUTATION, + query: MEMBERSHIP_REQUEST, variables: { - id: '123', - userType: 'ADMIN', + id: '', + skip: 0, + first: 8, + firstName_contains: '', }, }, result: { data: { - acceptAdmin: true, + organizations: [ + { + _id: '', + membershipRequests: [ + { + _id: '1', + user: { + _id: 'user2', + firstName: 'Scott', + lastName: 'Tony', + email: 'testuser3@example.com', + }, + }, + { + _id: '2', + user: { + _id: 'user3', + firstName: 'Teresa', + lastName: 'Bradley', + email: 'testuser4@example.com', + }, + }, + { + _id: '3', + user: { + _id: 'user4', + firstName: 'Jesse', + lastName: 'Hart', + email: 'testuser5@example.com', + }, + }, + { + _id: '4', + user: { + _id: 'user5', + firstName: 'Lena', + lastName: 'Mcdonald', + email: 'testuser6@example.com', + }, + }, + { + _id: '5', + user: { + _id: 'user6', + firstName: 'David', + lastName: 'Smith', + email: 'testuser7@example.com', + }, + }, + { + _id: '6', + user: { + _id: 'user7', + firstName: 'Emily', + lastName: 'Johnson', + email: 'testuser8@example.com', + }, + }, + { + _id: '7', + user: { + _id: 'user8', + firstName: 'Michael', + lastName: 'Davis', + email: 'testuser9@example.com', + }, + }, + { + _id: '8', + user: { + _id: 'user9', + firstName: 'Sarah', + lastName: 'Wilson', + email: 'testuser10@example.com', + }, + }, + ], + }, + ], }, }, }, { request: { - query: REJECT_ADMIN_MUTATION, + query: MEMBERSHIP_REQUEST, variables: { - id: '123', - userType: 'ADMIN', + id: '', + skip: 8, + first: 16, + firstName_contains: '', }, }, result: { data: { - rejectAdmin: true, + organizations: [ + { + _id: '', + membershipRequests: [ + { + _id: '9', + user: { + _id: 'user10', + firstName: 'Daniel', + lastName: 'Brown', + email: 'testuser11@example.com', + }, + }, + { + _id: '10', + user: { + _id: 'user11', + firstName: 'Jessica', + lastName: 'Martinez', + email: 'testuser12@example.com', + }, + }, + { + _id: '11', + user: { + _id: 'user12', + firstName: 'Matthew', + lastName: 'Taylor', + email: 'testuser13@example.com', + }, + }, + { + _id: '12', + user: { + _id: 'user13', + firstName: 'Amanda', + lastName: 'Anderson', + email: 'testuser14@example.com', + }, + }, + { + _id: '13', + user: { + _id: 'user14', + firstName: 'Christopher', + lastName: 'Thomas', + email: 'testuser15@example.com', + }, + }, + { + _id: '14', + user: { + _id: 'user15', + firstName: 'Ashley', + lastName: 'Hernandez', + email: 'testuser16@example.com', + }, + }, + { + _id: '15', + user: { + _id: 'user16', + firstName: 'Andrew', + lastName: 'Young', + email: 'testuser17@example.com', + }, + }, + { + _id: '16', + user: { + _id: 'user17', + firstName: 'Nicole', + lastName: 'Garcia', + email: 'testuser18@example.com', + }, + }, + ], + }, + ], }, }, }, ]; -export const EMPTY_ORG_MOCKS = [ +export const MOCKS2 = [ { request: { - query: ACCEPT_ADMIN_MUTATION, - variables: { - id: '123', - userType: 'ADMIN', - }, + query: ORGANIZATION_CONNECTION_LIST, }, result: { - data: undefined, + data: { + organizationsConnection: [ + { + _id: 'org1', + image: null, + creator: { + firstName: 'John', + lastName: 'Doe', + }, + name: 'Palisadoes', + members: [ + { + _id: 'user1', + }, + ], + admins: [ + { + _id: 'user1', + }, + ], + createdAt: '09/11/2001', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + }, + ], + }, }, }, { request: { - query: REJECT_ADMIN_MUTATION, + query: MEMBERSHIP_REQUEST, variables: { - id: '123', - userType: 'ADMIN', + id: 'org1', + skip: 0, + first: 8, + firstName_contains: '', }, }, - result: { - data: undefined, - }, - }, - { - request: { - query: ORGANIZATION_CONNECTION_LIST, - }, result: { data: { - organizationsConnection: [], + organizations: [ + { + _id: 'org1', + membershipRequests: [ + { + _id: '1', + user: { + _id: 'user2', + firstName: 'Scott', + lastName: 'Tony', + email: 'testuser3@example.com', + }, + }, + ], + }, + ], }, }, }, ]; -export const ORG_LIST_MOCK = [ - ...MOCKS, +export const MOCKS3 = [ { request: { query: ORGANIZATION_CONNECTION_LIST, @@ -195,26 +468,106 @@ export const ORG_LIST_MOCK = [ data: { organizationsConnection: [ { - _id: 1, - image: '', - name: 'Akatsuki', + _id: 'org1', + image: null, creator: { firstName: 'John', lastName: 'Doe', }, + name: 'Palisadoes', + members: [ + { + _id: 'user1', + }, + ], admins: [ { - _id: '123', + _id: 'user1', }, ], - members: { - _id: '234', + createdAt: '09/11/2001', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', }, - createdAt: '02/02/2022', - location: 'Washington DC', }, ], }, }, }, + { + request: { + query: MEMBERSHIP_REQUEST, + variables: { + id: 'org1', + skip: 0, + first: 8, + firstName_contains: '', + }, + }, + result: { + data: { + organizations: [], + }, + }, + }, +]; + +export const EMPTY_MOCKS = [ + { + request: { + query: MEMBERSHIP_REQUEST, + variables: { + id: 'org1', + skip: 0, + first: 8, + firstName_contains: '', + }, + }, + result: { + data: { + organizations: [ + { + _id: 'org1', + membershipRequests: [], + }, + ], + }, + }, + }, + { + request: { + query: ORGANIZATION_CONNECTION_LIST, + }, + result: { + data: { + organizationsConnection: [], + }, + }, + }, +]; + +export const MOCKS_WITH_ERROR = [ + { + request: { + query: MEMBERSHIP_REQUEST, + variables: { + first: 0, + skip: 0, + id: '1', + firstName_contains: '', + }, + }, + }, + { + request: { + query: ORGANIZATION_CONNECTION_LIST, + }, + }, ]; diff --git a/src/screens/UserPortal/Chat/Chat.module.css b/src/screens/UserPortal/Chat/Chat.module.css index 40add650f4..52edacdf64 100644 --- a/src/screens/UserPortal/Chat/Chat.module.css +++ b/src/screens/UserPortal/Chat/Chat.module.css @@ -1,5 +1,5 @@ .containerHeight { - height: calc(100vh - 66px); + height: 100vh; } .mainContainer { diff --git a/src/screens/UserPortal/Chat/Chat.test.tsx b/src/screens/UserPortal/Chat/Chat.test.tsx index 6476e9ee40..b090266acf 100644 --- a/src/screens/UserPortal/Chat/Chat.test.tsx +++ b/src/screens/UserPortal/Chat/Chat.test.tsx @@ -117,7 +117,7 @@ describe('Testing People Screen [User Portal]', () => { - + , ); await wait(); @@ -136,7 +136,7 @@ describe('Testing People Screen [User Portal]', () => { - + , ); await wait(); @@ -148,7 +148,7 @@ describe('Testing People Screen [User Portal]', () => { expect(screen.queryAllByText('Noble Mittal')).not.toBe([]); }); - test('Search functionality works as expected', async () => { + test('Search functionality works as expected by pressing enter key', async () => { render( @@ -158,12 +158,36 @@ describe('Testing People Screen [User Portal]', () => { - + , ); await wait(); + userEvent.type(screen.getByTestId('searchInput'), 'j{enter}'); + await wait(); + + expect(getOrganizationIdSpy).toHaveBeenCalled(); + expect(screen.queryByText('John Cena')).toBeInTheDocument(); + expect(screen.queryByText('Noble Mittal')).not.toBeInTheDocument(); + }); + + test('Search functionality works as expected by clicking search Btn', async () => { + render( + + + + + + + + + , + ); + + await wait(); + const searchBtn = screen.getByTestId('searchBtn'); userEvent.type(screen.getByTestId('searchInput'), 'j'); + userEvent.click(searchBtn); await wait(); expect(getOrganizationIdSpy).toHaveBeenCalled(); diff --git a/src/screens/UserPortal/Chat/Chat.tsx b/src/screens/UserPortal/Chat/Chat.tsx index 1ae9d5764d..4757ac9dcc 100644 --- a/src/screens/UserPortal/Chat/Chat.tsx +++ b/src/screens/UserPortal/Chat/Chat.tsx @@ -1,6 +1,5 @@ import React from 'react'; -import OrganizationNavbar from 'components/UserPortal/OrganizationNavbar/OrganizationNavbar'; -import UserSidebar from 'components/UserPortal/UserSidebar/UserSidebar'; +// import OrganizationNavbar from 'components/UserPortal/OrganizationNavbar/OrganizationNavbar'; import { ORGANIZATIONS_MEMBER_CONNECTION_LIST } from 'GraphQl/Queries/Queries'; import { useQuery } from '@apollo/client'; import styles from './Chat.module.css'; @@ -57,17 +56,23 @@ export default function chat(): JSX.Element { }, }); - const handleSearch = ( - event: React.ChangeEvent - ): void => { - const newFilter = event.target.value; - setFilterName(newFilter); + const handleSearch = (value: string): void => { + setFilterName(value); - const filter = { - firstName_contains: newFilter, - }; - - contactRefetch(filter); + contactRefetch({ + firstName_contains: value, + }); + }; + const handleSearchByEnter = (e: any): void => { + if (e.key === 'Enter') { + const { value } = e.target; + handleSearch(value); + } + }; + const handleSearchByBtnClick = (): void => { + const value = + (document.getElementById('searchChats') as HTMLInputElement)?.value || ''; + handleSearch(value); }; React.useEffect(() => { @@ -78,9 +83,8 @@ export default function chat(): JSX.Element { return ( <> - + {/* */}
    -
    diff --git a/src/screens/UserPortal/Donate/Donate.module.css b/src/screens/UserPortal/Donate/Donate.module.css index c137003c0e..4e21cb08d4 100644 --- a/src/screens/UserPortal/Donate/Donate.module.css +++ b/src/screens/UserPortal/Donate/Donate.module.css @@ -1,24 +1,41 @@ .containerHeight { - height: calc(100vh - 66px); + height: 100vh; } .mainContainer { width: 50%; flex-grow: 3; - padding: 20px; + padding: 1rem; max-height: 100%; overflow: auto; display: flex; flex-direction: column; + background-color: #f2f7ff; +} + +.inputContainer { + margin-top: 3rem; + flex: 1; + position: relative; +} +.input { + width: 70%; + position: relative; + box-shadow: 5px 5px 4px 0px #31bb6b1f; } .box { width: auto; /* height: 200px; */ background-color: white; - margin: 20px; + margin-top: 1rem; padding: 20px; - border-radius: 20px; + border: 1px solid #dddddd; + border-radius: 10px; +} + +.heading { + font-size: 1.1rem; } .donationInputContainer { @@ -27,25 +44,45 @@ margin-top: 20px; } +.donateBtn { + padding-inline: 1rem !important; +} + +.dropdown { + min-width: 6rem; +} + +.inputArea { + border: none; + outline: none; + background-color: #f1f3f6; +} + .maxWidth { width: 100%; } .donateActions { - margin-top: 40px; + margin-top: 1rem; width: 100%; display: flex; flex-direction: row-reverse; } .donationsContainer { - margin: 20px; - padding-top: 20px; + padding-top: 4rem; flex-grow: 1; display: flex; flex-direction: column; } +.donationCardsContainer { + display: flex; + flex-wrap: wrap; + gap: 1rem; + --bs-gutter-x: 0; +} + .colorLight { background-color: #f5f5f5; } diff --git a/src/screens/UserPortal/Donate/Donate.test.tsx b/src/screens/UserPortal/Donate/Donate.test.tsx index 3abb433c51..fc30ba7503 100644 --- a/src/screens/UserPortal/Donate/Donate.test.tsx +++ b/src/screens/UserPortal/Donate/Donate.test.tsx @@ -14,7 +14,8 @@ import i18nForTest from 'utils/i18nForTest'; import { StaticMockLink } from 'utils/StaticMockLink'; import Donate from './Donate'; import userEvent from '@testing-library/user-event'; -import * as getOrganizationId from 'utils/getOrganizationId'; +import useLocalStorage from 'utils/useLocalstorage'; +import { DONATE_TO_ORGANIZATION } from 'GraphQl/Mutations/mutations'; const MOCKS = [ { @@ -33,7 +34,7 @@ const MOCKS = [ amount: 1, userId: '6391a15bcb738c181d238952', payPalId: 'payPalId', - __typename: 'Donation', + updatedAt: '2024-04-03T16:43:01.514Z', }, ], }, @@ -50,13 +51,69 @@ const MOCKS = [ data: { organizationsConnection: [ { - __typename: 'Organization', _id: '6401ff65ce8e8406b8f07af3', image: '', name: 'anyOrganization2', description: 'desc', - isPublic: true, - creator: { __typename: 'User', firstName: 'John', lastName: 'Doe' }, + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + userRegistrationRequired: true, + createdAt: '12345678900', + creator: { firstName: 'John', lastName: 'Doe' }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: DONATE_TO_ORGANIZATION, + variables: { + userId: '123', + createDonationOrgId2: '', + payPalId: 'paypalId', + nameOfUser: 'name', + amount: 123, + nameOfOrg: 'anyOrganization2', + }, + }, + result: { + data: { + createDonation: [ + { + _id: '', + amount: 123, + nameOfUser: 'name', + nameOfOrg: 'anyOrganization2', }, ], }, @@ -74,9 +131,12 @@ async function wait(ms = 100): Promise { }); } -describe('Testing Donate Screen [User Portal]', () => { - jest.mock('utils/getOrganizationId'); +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: '' }), +})); +describe('Testing Donate Screen [User Portal]', () => { Object.defineProperty(window, 'matchMedia', { writable: true, value: jest.fn().mockImplementation((query) => ({ @@ -91,11 +151,9 @@ describe('Testing Donate Screen [User Portal]', () => { })), }); - const getOrganizationIdSpy = jest - .spyOn(getOrganizationId, 'default') - .mockImplementation(() => { - return ''; - }); + beforeEach(() => { + jest.clearAllMocks(); + }); test('Screen should be rendered properly', async () => { render( @@ -107,12 +165,13 @@ describe('Testing Donate Screen [User Portal]', () => { - + , ); await wait(); - - expect(getOrganizationIdSpy).toHaveBeenCalled(); + expect(screen.getByPlaceholderText('Search donations')).toBeInTheDocument(); + expect(screen.getByTestId('currency0')).toBeInTheDocument(); + expect(screen.getByPlaceholderText('Amount')).toBeInTheDocument(); }); test('Currency is swtiched to USD', async () => { @@ -125,7 +184,7 @@ describe('Testing Donate Screen [User Portal]', () => { - + , ); await wait(); @@ -133,8 +192,9 @@ describe('Testing Donate Screen [User Portal]', () => { userEvent.click(screen.getByTestId('changeCurrencyBtn')); userEvent.click(screen.getByTestId('currency0')); - await wait(); + + expect(screen.getByTestId('currency0')).toBeInTheDocument(); }); test('Currency is swtiched to INR', async () => { @@ -147,7 +207,7 @@ describe('Testing Donate Screen [User Portal]', () => { - + , ); await wait(); @@ -169,7 +229,7 @@ describe('Testing Donate Screen [User Portal]', () => { - + , ); await wait(); @@ -180,4 +240,44 @@ describe('Testing Donate Screen [User Portal]', () => { await wait(); }); + + test('Checking the existence of Donation Cards', async () => { + render( + + + + + + + + + , + ); + + await wait(); + expect(screen.getAllByTestId('donationCard')[0]).toBeInTheDocument(); + }); + + test('For Donation functionality', async () => { + const { setItem } = useLocalStorage(); + setItem('userId', '123'); + setItem('name', 'name'); + render( + + + + + + + + + , + ); + + await wait(); + + userEvent.type(screen.getByTestId('donationAmount'), '123'); + userEvent.click(screen.getByTestId('donateBtn')); + await wait(); + }); }); diff --git a/src/screens/UserPortal/Donate/Donate.tsx b/src/screens/UserPortal/Donate/Donate.tsx index cbe31f9937..4e39c4e1be 100644 --- a/src/screens/UserPortal/Donate/Donate.tsx +++ b/src/screens/UserPortal/Donate/Donate.tsx @@ -1,27 +1,32 @@ import React from 'react'; -import OrganizationNavbar from 'components/UserPortal/OrganizationNavbar/OrganizationNavbar'; -import OrganizationSidebar from 'components/UserPortal/OrganizationSidebar/OrganizationSidebar'; -import UserSidebar from 'components/UserPortal/UserSidebar/UserSidebar'; +import { useParams } from 'react-router-dom'; import { Button, Dropdown, Form, InputGroup } from 'react-bootstrap'; -import PaginationList from 'components/PaginationList/PaginationList'; +import { toast } from 'react-toastify'; +import { useQuery, useMutation } from '@apollo/client'; +import { Search } from '@mui/icons-material'; +import SendIcon from '@mui/icons-material/Send'; +import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; +import { useTranslation } from 'react-i18next'; + import { ORGANIZATION_DONATION_CONNECTION_LIST, USER_ORGANIZATION_CONNECTION, } from 'GraphQl/Queries/Queries'; -import { useQuery } from '@apollo/client'; +import { DONATE_TO_ORGANIZATION } from 'GraphQl/Mutations/mutations'; import styles from './Donate.module.css'; -import SendIcon from '@mui/icons-material/Send'; -import getOrganizationId from 'utils/getOrganizationId'; -import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; import DonationCard from 'components/UserPortal/DonationCard/DonationCard'; -import { useTranslation } from 'react-i18next'; +import useLocalStorage from 'utils/useLocalstorage'; +import { errorHandler } from 'utils/errorHandler'; +import OrganizationSidebar from 'components/UserPortal/OrganizationSidebar/OrganizationSidebar'; +import PaginationList from 'components/PaginationList/PaginationList'; -interface InterfaceDonationCardProps { +export interface InterfaceDonationCardProps { id: string; name: string; amount: string; userId: string; payPalId: string; + updatedAt: string; } export default function donate(): JSX.Element { @@ -29,7 +34,12 @@ export default function donate(): JSX.Element { keyPrefix: 'donate', }); - const organizationId = getOrganizationId(location.href); + const { getItem } = useLocalStorage(); + const userId = getItem('userId'); + const userName = getItem('name'); + + const { orgId: organizationId } = useParams(); + const [amount, setAmount] = React.useState(''); const [organizationDetails, setOrganizationDetails]: any = React.useState({}); const [donations, setDonations] = React.useState([]); const [selectedCurrency, setSelectedCurrency] = React.useState(0); @@ -38,17 +48,20 @@ export default function donate(): JSX.Element { const currencies = ['USD', 'INR', 'EUR']; - const { data: data2, loading } = useQuery( - ORGANIZATION_DONATION_CONNECTION_LIST, - { - variables: { orgId: organizationId }, - } - ); + const { + data: data2, + loading, + refetch, + } = useQuery(ORGANIZATION_DONATION_CONNECTION_LIST, { + variables: { orgId: organizationId }, + }); const { data } = useQuery(USER_ORGANIZATION_CONNECTION, { variables: { id: organizationId }, }); + const [donate] = useMutation(DONATE_TO_ORGANIZATION); + const navbarProps = { currentPage: 'donate', }; @@ -56,14 +69,14 @@ export default function donate(): JSX.Element { /* istanbul ignore next */ const handleChangePage = ( _event: React.MouseEvent | null, - newPage: number + newPage: number, ): void => { setPage(newPage); }; /* istanbul ignore next */ const handleChangeRowsPerPage = ( - event: React.ChangeEvent + event: React.ChangeEvent, ): void => { const newRowsPerPage = event.target.value; @@ -83,31 +96,62 @@ export default function donate(): JSX.Element { } }, [data2]); + const donateToOrg = (): void => { + try { + donate({ + variables: { + userId, + createDonationOrgId2: organizationId, + payPalId: 'paypalId', + nameOfUser: userName, + amount: Number(amount), + nameOfOrg: organizationDetails.name, + }, + }); + refetch(); + toast.success(t(`success`)); + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + return ( <> -
    - -
    +
    +

    {t(`donations`)}

    +
    +
    + + +
    +
    -

    - {t('donateTo')} {organizationDetails.name} -

    +
    + {t('donateForThe')} {organizationDetails.name} +
    - - {t('amount')} - - + { + setAmount(e.target.value); + }} + />
    -
    @@ -143,9 +202,7 @@ export default function donate(): JSX.Element {
    -
    +
    {loading ? (
    Loading... @@ -156,7 +213,7 @@ export default function donate(): JSX.Element { (rowsPerPage > 0 ? donations.slice( page * rowsPerPage, - page * rowsPerPage + rowsPerPage + page * rowsPerPage + rowsPerPage, ) : /* istanbul ignore next */ donations @@ -167,8 +224,13 @@ export default function donate(): JSX.Element { amount: donation.amount, userId: donation.userId, payPalId: donation.payPalId, + updatedAt: donation.updatedAt, }; - return ; + return ( +
    + +
    + ); }) ) : ( {t('nothingToShow')} diff --git a/src/screens/UserPortal/Events/Events.module.css b/src/screens/UserPortal/Events/Events.module.css index 52a305cc20..db80124201 100644 --- a/src/screens/UserPortal/Events/Events.module.css +++ b/src/screens/UserPortal/Events/Events.module.css @@ -11,17 +11,17 @@ } .maxWidth { - max-width: 300px; + max-width: 800px; } .colorLight { - background-color: #f5f5f5; + background-color: #f1f3f6; } .mainContainer { width: 50%; flex-grow: 3; - padding: 40px; + padding: 20px; max-height: 100%; overflow: auto; } @@ -30,6 +30,14 @@ height: fit-content; min-height: calc(100% - 40px); } +.selectType { + border-radius: 10px; +} +.dropdown__item { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; +} .gap { gap: 20px; @@ -40,7 +48,7 @@ } .containerHeight { - height: calc(100vh - 66px); + height: 100vh; } .colorPrimary { @@ -81,3 +89,76 @@ flex-wrap: wrap; margin-top: 20px; } +.titlemodal { + color: #707070; + font-weight: 600; + font-size: 20px; + margin-bottom: 20px; + padding-bottom: 5px; + border-bottom: 3px solid #31bb6b; + width: 65%; +} + +.datediv { + display: flex; + flex-direction: row; + margin-bottom: 15px; +} + +.datebox { + width: 90%; + border-radius: 7px; + border-color: #e8e5e5; + outline: none; + box-shadow: none; + padding-top: 2px; + padding-bottom: 2px; + padding-right: 5px; + padding-left: 5px; + margin-right: 5px; + margin-left: 5px; +} + +.checkboxdiv > label { + margin-right: 50px; +} +.checkboxdiv > label > input { + margin-left: 10px; +} + +.checkboxdiv { + display: flex; +} +.checkboxdiv > div { + width: 50%; +} + +.dispflex { + display: flex; + align-items: center; +} +.dispflex > input { + border: none; + box-shadow: none; + margin-top: 5px; +} + +.greenregbtn { + margin: 1rem 0 0; + margin-top: 15px; + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + padding: 10px 10px; + border-radius: 5px; + background-color: #31bb6b; + width: 100%; + font-size: 16px; + color: white; + outline: none; + font-weight: 600; + cursor: pointer; + transition: + transform 0.2s, + box-shadow 0.2s; + width: 100%; +} diff --git a/src/screens/UserPortal/Events/Events.test.tsx b/src/screens/UserPortal/Events/Events.test.tsx index 4243efa8ee..6de04ee172 100644 --- a/src/screens/UserPortal/Events/Events.test.tsx +++ b/src/screens/UserPortal/Events/Events.test.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { act, render, screen } from '@testing-library/react'; +import { act, fireEvent, render, screen } from '@testing-library/react'; import { MockedProvider } from '@apollo/react-testing'; import { I18nextProvider } from 'react-i18next'; @@ -11,10 +11,16 @@ import i18nForTest from 'utils/i18nForTest'; import { StaticMockLink } from 'utils/StaticMockLink'; import Events from './Events'; import userEvent from '@testing-library/user-event'; -import * as getOrganizationId from 'utils/getOrganizationId'; import { CREATE_EVENT_MUTATION } from 'GraphQl/Mutations/mutations'; import { toast } from 'react-toastify'; import dayjs from 'dayjs'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { ThemeProvider } from 'react-bootstrap'; +import { createTheme } from '@mui/material'; +import useLocalStorage from 'utils/useLocalstorage'; + +const { setItem, getItem } = useLocalStorage(); jest.mock('react-toastify', () => ({ toast: { @@ -24,6 +30,33 @@ jest.mock('react-toastify', () => ({ }, })); +jest.mock('@mui/x-date-pickers/DatePicker', () => { + return { + DatePicker: jest.requireActual('@mui/x-date-pickers/DesktopDatePicker') + .DesktopDatePicker, + }; +}); + +jest.mock('@mui/x-date-pickers/TimePicker', () => { + return { + TimePicker: jest.requireActual('@mui/x-date-pickers/DesktopTimePicker') + .DesktopTimePicker, + }; +}); + +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: '' }), +})); + +const theme = createTheme({ + palette: { + primary: { + main: '#31bb6b', + }, + }, +}); + const MOCKS = [ { request: { @@ -217,8 +250,6 @@ async function wait(ms = 100): Promise { } describe('Testing Events Screen [User Portal]', () => { - jest.mock('utils/getOrganizationId'); - Object.defineProperty(window, 'matchMedia', { writable: true, value: jest.fn().mockImplementation((query) => ({ @@ -234,67 +265,6 @@ describe('Testing Events Screen [User Portal]', () => { }); test('Screen should be rendered properly', async () => { - const getOrganizationIdSpy = jest - .spyOn(getOrganizationId, 'default') - .mockImplementation(() => { - return ''; - }); - - render( - - - - - - - - - - ); - - await wait(); - - expect(getOrganizationIdSpy).toHaveBeenCalled(); - }); - - test('Events are visible as expected without search query', async () => { - const getOrganizationIdSpy = jest - .spyOn(getOrganizationId, 'default') - .mockImplementation(() => { - return ''; - }); - - render( - - - - - - - - - - ); - - await wait(); - - let mockEventTitle = ''; - if (MOCKS[0].result?.data.eventsByOrganizationConnection) { - mockEventTitle = - MOCKS[0].result?.data.eventsByOrganizationConnection[0].title; - } - - expect(getOrganizationIdSpy).toHaveBeenCalled(); - expect(screen.queryByText(mockEventTitle)).toBeInTheDocument(); - }); - - test('Search works as expected when user types in search input', async () => { - const getOrganizationIdSpy = jest - .spyOn(getOrganizationId, 'default') - .mockImplementation(() => { - return ''; - }); - render( @@ -304,56 +274,34 @@ describe('Testing Events Screen [User Portal]', () => { - + , ); - + setItem('SuperAdmin', true); // testing userRole as Superadmin await wait(); - - expect(getOrganizationIdSpy).toHaveBeenCalled(); - - const randomSearchInput = 'test'; - userEvent.type(screen.getByTestId('searchInput'), randomSearchInput); - + setItem('SuperAdmin', false); + setItem('AdminFor', ['123']); // testing userRole as Admin await wait(); - - let mockEventTitle = ''; - if (MOCKS[0].result?.data.eventsByOrganizationConnection) { - mockEventTitle = - MOCKS[0].result?.data.eventsByOrganizationConnection[0].title; - } - - let mockEventTitleAbsent = ''; - if (MOCKS[0].result?.data.eventsByOrganizationConnection) { - mockEventTitleAbsent = - MOCKS[0].result?.data.eventsByOrganizationConnection[1].title; - } - - expect(screen.queryByText(mockEventTitle)).toBeInTheDocument(); - expect(screen.queryByText(mockEventTitleAbsent)).not.toBeInTheDocument(); }); test('Create event works as expected when event is not an all day event.', async () => { - const getOrganizationIdSpy = jest - .spyOn(getOrganizationId, 'default') - .mockImplementation(() => { - return ''; - }); - render( - - - + + + + + + + - + , ); await wait(); - expect(getOrganizationIdSpy).toHaveBeenCalled(); userEvent.click(screen.getByTestId('createEventModalBtn')); const randomEventTitle = 'testEventTitle'; @@ -363,11 +311,11 @@ describe('Testing Events Screen [User Portal]', () => { userEvent.type(screen.getByTestId('eventTitleInput'), randomEventTitle); userEvent.type( screen.getByTestId('eventDescriptionInput'), - randomEventDescription + randomEventDescription, ); userEvent.type( screen.getByTestId('eventLocationInput'), - randomEventLocation + randomEventLocation, ); userEvent.click(screen.getByTestId('publicEventCheck')); @@ -389,32 +337,28 @@ describe('Testing Events Screen [User Portal]', () => { await wait(); expect(toast.success).toBeCalledWith( - 'Event created and posted successfully.' + 'Event created and posted successfully.', ); }); test('Create event works as expected when event is an all day event.', async () => { - const getOrganizationIdSpy = jest - .spyOn(getOrganizationId, 'default') - .mockImplementation(() => { - return ''; - }); - render( - - - + + + + + + + - + , ); - await wait(); - expect(getOrganizationIdSpy).toHaveBeenCalled(); userEvent.click(screen.getByTestId('createEventModalBtn')); const randomEventTitle = 'testEventTitle'; @@ -424,11 +368,11 @@ describe('Testing Events Screen [User Portal]', () => { userEvent.type(screen.getByTestId('eventTitleInput'), randomEventTitle); userEvent.type( screen.getByTestId('eventDescriptionInput'), - randomEventDescription + randomEventDescription, ); userEvent.type( screen.getByTestId('eventLocationInput'), - randomEventLocation + randomEventLocation, ); userEvent.click(screen.getByTestId('createEventBtn')); @@ -436,38 +380,142 @@ describe('Testing Events Screen [User Portal]', () => { await wait(); expect(toast.success).toBeCalledWith( - 'Event created and posted successfully.' + 'Event created and posted successfully.', ); }); test('Switch to calendar view works as expected.', async () => { - const getOrganizationIdSpy = jest - .spyOn(getOrganizationId, 'default') - .mockImplementation(() => { - return ''; - }); - render( - - - + + + + + + + - + , ); - await wait(); - expect(getOrganizationIdSpy).toHaveBeenCalled(); + // await wait(); - userEvent.click(screen.getByTestId('modeChangeBtn')); - userEvent.click(screen.getByTestId('modeBtn1')); + // userEvent.click(screen.getByTestId('modeChangeBtn')); + // userEvent.click(screen.getByTestId('modeBtn1')); await wait(); const calenderView = 'Calendar View'; expect(screen.queryAllByText(calenderView)).not.toBeNull(); + expect(screen.getByText('Sun')).toBeInTheDocument(); + }); + + test('Testing DatePicker and TimePicker', async () => { + render( + + + + + + + + + + + + + , + ); + + await wait(); + + const startDate = '03/23/2024'; + const endDate = '04/23/2024'; + const startTime = '02:00 PM'; + const endTime = '06:00 PM'; + + userEvent.click(screen.getByTestId('createEventModalBtn')); + + expect(endDate).not.toBeNull(); + const endDateDatePicker = screen.getByLabelText('End Date'); + expect(startDate).not.toBeNull(); + const startDateDatePicker = screen.getByLabelText('Start Date'); + + fireEvent.change(startDateDatePicker, { + target: { value: startDate }, + }); + fireEvent.change(endDateDatePicker, { + target: { value: endDate }, + }); + + await wait(); + + expect(endDateDatePicker).toHaveValue(endDate); + expect(startDateDatePicker).toHaveValue(startDate); + + userEvent.click(screen.getByTestId('allDayEventCheck')); + + expect(endTime).not.toBeNull(); + const endTimePicker = screen.getByLabelText('End Time'); + expect(startTime).not.toBeNull(); + const startTimePicker = screen.getByLabelText('Start Time'); + + fireEvent.change(startTimePicker, { + target: { value: startTime }, + }); + fireEvent.change(endTimePicker, { + target: { value: endTime }, + }); + + await wait(); + expect(endTimePicker).toHaveValue(endTime); + expect(startTimePicker).toHaveValue(startTime); + }); + + test('EndDate null', async () => { + render( + + + + + + + + + + + + + , + ); + + await wait(); + + userEvent.click(screen.getByTestId('createEventModalBtn')); + + const endDateDatePicker = screen.getByLabelText('End Date'); + const startDateDatePicker = screen.getByLabelText('Start Date'); + + fireEvent.change(startDateDatePicker, { + target: { value: null }, + }); + fireEvent.change(endDateDatePicker, { + target: { value: null }, + }); + + userEvent.click(screen.getByTestId('allDayEventCheck')); + + const endTimePicker = screen.getByLabelText('End Time'); + const startTimePicker = screen.getByLabelText('Start Time'); + + fireEvent.change(startTimePicker, { + target: { value: null }, + }); + fireEvent.change(endTimePicker, { + target: { value: null }, + }); }); }); diff --git a/src/screens/UserPortal/Events/Events.tsx b/src/screens/UserPortal/Events/Events.tsx index caf1d72fd2..660ea5e10f 100644 --- a/src/screens/UserPortal/Events/Events.tsx +++ b/src/screens/UserPortal/Events/Events.tsx @@ -1,24 +1,29 @@ +import type { ChangeEvent } from 'react'; import React from 'react'; -import OrganizationNavbar from 'components/UserPortal/OrganizationNavbar/OrganizationNavbar'; -import OrganizationSidebar from 'components/UserPortal/OrganizationSidebar/OrganizationSidebar'; import EventCard from 'components/UserPortal/EventCard/EventCard'; -import UserSidebar from 'components/UserPortal/UserSidebar/UserSidebar'; import { Button, Dropdown, Form, InputGroup } from 'react-bootstrap'; import PaginationList from 'components/PaginationList/PaginationList'; -import { ORGANIZATION_EVENTS_CONNECTION } from 'GraphQl/Queries/Queries'; +import { + ORGANIZATION_EVENTS_CONNECTION, + ORGANIZATIONS_LIST, +} from 'GraphQl/Queries/Queries'; import { useMutation, useQuery } from '@apollo/client'; import { SearchOutlined } from '@mui/icons-material'; import styles from './Events.module.css'; import { useTranslation } from 'react-i18next'; import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; -import getOrganizationId from 'utils/getOrganizationId'; import Modal from 'react-bootstrap/Modal'; -import ReactDatePicker from 'react-datepicker'; -import { CREATE_EVENT_MUTATION } from 'GraphQl/Mutations/mutations'; +import { TimePicker, DatePicker } from '@mui/x-date-pickers'; +import type { Dayjs } from 'dayjs'; import dayjs from 'dayjs'; +import { CREATE_EVENT_MUTATION } from 'GraphQl/Mutations/mutations'; import { toast } from 'react-toastify'; import { errorHandler } from 'utils/errorHandler'; - +import EventCalendar from 'components/EventCalendar/EventCalendar'; +import useLocalStorage from 'utils/useLocalstorage'; +import { useNavigate, useParams } from 'react-router-dom'; +import { ViewType } from 'screens/OrganizationEvents/OrganizationEvents'; +import EventHeader from 'components/EventCalendar/EventHeader'; interface InterfaceEventCardProps { id: string; title: string; @@ -42,30 +47,58 @@ interface InterfaceEventCardProps { }[]; } +interface InterfaceAttendee { + _id: string; + title: string; + description: string; + location: string; + startDate: string; + endDate: string; + isRegisterable: boolean; + isPublic: boolean; + endTime: string; + startTime: string; + recurring: boolean; + allDay: boolean; + attendees: { _id: string }[]; + creator: { + firstName: string; + lastName: string; + _id: string; + }; +} + +const timeToDayJs = (time: string): Dayjs => { + const dateTimeString = dayjs().format('YYYY-MM-DD') + ' ' + time; + return dayjs(dateTimeString, { format: 'YYYY-MM-DD HH:mm:ss' }); +}; + export default function events(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'userEvents', }); + const { getItem } = useLocalStorage(); + const [page, setPage] = React.useState(0); const [rowsPerPage, setRowsPerPage] = React.useState(5); const [events, setEvents] = React.useState([]); - const [filterName, setFilterName] = React.useState(''); const [mode, setMode] = React.useState(0); - const [showCreateEventModal, setShowCreateEventModal] = React.useState(false); + // const [showCreateEventModal, setShowCreateEventModal] = React.useState(false); const [eventTitle, setEventTitle] = React.useState(''); const [eventDescription, setEventDescription] = React.useState(''); const [eventLocation, setEventLocation] = React.useState(''); - const [startDate, setStartDate] = React.useState(new Date()); - const [endDate, setEndDate] = React.useState(new Date()); + const [startDate, setStartDate] = React.useState(new Date()); + const [endDate, setEndDate] = React.useState(new Date()); const [isPublic, setIsPublic] = React.useState(true); const [isRegisterable, setIsRegisterable] = React.useState(true); const [isRecurring, setIsRecurring] = React.useState(false); const [isAllDay, setIsAllDay] = React.useState(true); const [startTime, setStartTime] = React.useState('08:00:00'); const [endTime, setEndTime] = React.useState('10:00:00'); - - const organizationId = getOrganizationId(window.location.href); + const [viewType, setViewType] = React.useState(ViewType.MONTH); + const [createEventModal, setCreateEventmodalisOpen] = React.useState(false); + const { orgId: organizationId } = useParams(); const modes = [t('listView'), t('calendarView')]; @@ -76,9 +109,26 @@ export default function events(): JSX.Element { }, }); + const { data: orgData } = useQuery(ORGANIZATIONS_LIST, { + variables: { id: organizationId }, + }); + const [create] = useMutation(CREATE_EVENT_MUTATION); - const createEvent = async (): Promise => { + const userId = getItem('id') as string; + + const superAdmin = getItem('SuperAdmin'); + const adminFor = getItem('AdminFor'); + const userRole = superAdmin + ? 'SUPERADMIN' + : adminFor?.length > 0 + ? 'ADMIN' + : 'USER'; + + const createEvent = async ( + e: ChangeEvent, + ): Promise => { + e.preventDefault(); try { const { data: createEventData } = await create({ variables: { @@ -109,7 +159,8 @@ export default function events(): JSX.Element { setStartTime('08:00:00'); setEndTime('10:00:00'); } - } catch (error: any) { + setCreateEventmodalisOpen(false); + } catch (error: unknown) { /* istanbul ignore next */ errorHandler(t, error); } @@ -118,64 +169,65 @@ export default function events(): JSX.Element { /* istanbul ignore next */ const handleChangePage = ( _event: React.MouseEvent | null, - newPage: number + newPage: number, ): void => { setPage(newPage); }; - + /* istanbul ignore next */ const toggleCreateEventModal = (): void => - setShowCreateEventModal(!showCreateEventModal); + setCreateEventmodalisOpen(!createEventModal); /* istanbul ignore next */ const handleChangeRowsPerPage = ( - event: React.ChangeEvent + event: React.ChangeEvent, ): void => { const newRowsPerPage = event.target.value; setRowsPerPage(parseInt(newRowsPerPage, 10)); setPage(0); }; - - const handleSearch = ( - event: React.ChangeEvent - ): void => { - const newFilter = event.target.value; - setFilterName(newFilter); - const filter = { - title_contains: newFilter, - }; + /* istanbul ignore next */ + const handleSearch = (value: string): void => { + refetch({ + title_contains: value, + }); setPage(0); - refetch(filter); + }; + /* istanbul ignore next */ + const handleSearchByEnter = ( + e: React.KeyboardEvent, + ): void => { + if (e.key === 'Enter') { + const { value } = e.target as HTMLInputElement; + handleSearch(value); + } + }; + /* istanbul ignore next */ + const handleSearchByBtnClick = (): void => { + const value = + (document.getElementById('searchEvents') as HTMLInputElement)?.value || + ''; + handleSearch(value); }; const handleEventTitleChange = ( - event: React.ChangeEvent + event: React.ChangeEvent, ): void => { setEventTitle(event.target.value); }; const handleEventLocationChange = ( - event: React.ChangeEvent + event: React.ChangeEvent, ): void => { setEventLocation(event.target.value); }; const handleEventDescriptionChange = ( - event: React.ChangeEvent + event: React.ChangeEvent, ): void => { setEventDescription(event.target.value); }; - /* istanbul ignore next */ - const handleStartDateChange = (newDate: any): void => { - setStartDate(newDate); - }; - - /* istanbul ignore next */ - const handleEndDateChange = (newDate: any): void => { - setEndDate(newDate); - }; - /* istanbul ignore next */ React.useEffect(() => { if (data) { @@ -183,302 +235,205 @@ export default function events(): JSX.Element { } }, [data]); - const navbarProps = { - currentPage: 'events', + /* istanbul ignore next */ + const showInviteModal = (): void => { + setCreateEventmodalisOpen(true); + }; + /* istanbul ignore next */ + const handleChangeView = (item: string | null): void => { + /*istanbul ignore next*/ + if (item) { + setViewType(item as ViewType); + } }; return ( <> -
    -
    -
    - - - - - - -
    +

    Events

    + +
    + +
    + + +

    {t('eventDetails')}

    - - - {modes[mode]} - - - {modes.map((value, index) => { - return ( - setMode(index)} - > - {value} - - ); - })} - - -
    -
    -
    -
    - {loading ? ( -
    - Loading... -
    - ) : ( - <> - {events && events.length > 0 ? ( - (rowsPerPage > 0 - ? events.slice( - page * rowsPerPage, - page * rowsPerPage + rowsPerPage - ) - : /* istanbul ignore next */ - events - ).map((event: any) => { - const attendees: any = []; - event.attendees.forEach((attendee: any) => { - const r = { - id: attendee._id, - }; - - attendees.push(r); - }); - - const creator: any = {}; - creator.firstName = event.creator.firstName; - creator.lastName = event.creator.lastName; - creator.id = event.creator._id; - - const cardProps: InterfaceEventCardProps = { - id: event._id, - title: event.title, - description: event.description, - location: event.location, - startDate: event.startDate, - endDate: event.endDate, - isRegisterable: event.isRegisterable, - isPublic: event.isPublic, - endTime: event.endTime, - startTime: event.startTime, - recurring: event.recurring, - allDay: event.allDay, - registrants: attendees, - creator, - }; - - return ; - }) - ) : ( - {t('nothingToShow')} - )} - - )} -
    - - - - - - -
    -
    -
    - - - -
    {t('createEvent')}
    - -
    - - - - {t('eventTitle')} - - - - - - - {t('eventDescription')} - - - - - - - {t('eventLocation')} - - - -
    {t('startDate')}
    - -
    {t('endDate')}
    - -
    -
    - - setIsPublic(!isPublic)} - /> -
    - -
    - - setIsRegisterable(!isRegisterable)} + + +
    + + -
    - -
    - - setIsRecurring(!isRecurring)} + + -
    - -
    - - setIsAllDay(!isAllDay)} + + -
    - - {!isAllDay && ( +
    +
    + { + if (date) { + setStartDate(date?.toDate()); + setEndDate(date?.toDate()); + } + }} + data-testid="eventStartDate" + /> +
    +
    + { + if (date) { + setEndDate(date?.toDate()); + } + }} + minDate={dayjs(startDate)} + data-testid="eventEndDate" + /> +
    +
    - - setStartTime(e.target.value) - } + { + if (time) { + setStartTime(time?.format('HH:mm:ss')); + setEndTime(time?.format('HH:mm:ss')); + } + }} + disabled={isAllDay} />
    - - setEndTime(e.target.value) - } + { + if (time) { + setEndTime(time?.format('HH:mm:ss')); + } + }} + minTime={timeToDayJs(startTime)} + disabled={isAllDay} />
    - )} -
    -
    - - - - -
    +
    +
    + + setIsAllDay(!isAllDay)} + /> +
    +
    + + setIsRecurring(!isRecurring)} + /> +
    +
    +
    +
    + + setIsPublic(!isPublic)} + /> +
    +
    + + setIsRegisterable(!isRegisterable)} + /> +
    +
    + + + + +
    ); diff --git a/src/screens/UserPortal/Home/Home.module.css b/src/screens/UserPortal/Home/Home.module.css deleted file mode 100644 index 48643b3445..0000000000 --- a/src/screens/UserPortal/Home/Home.module.css +++ /dev/null @@ -1,71 +0,0 @@ -.borderNone { - border: none; -} - -.colorWhite { - color: white; -} - -.maxWidth { - max-width: 300px; -} - -.colorLight { - background-color: #f5f5f5; -} - -.mainContainer { - width: 50%; - flex-grow: 3; - padding: 30px; - max-height: 100%; - overflow: auto; -} - -.containerHeight { - height: calc(100vh - 66px); -} - -.link { - text-decoration: none !important; - color: black; -} - -.postInputContainer { - background-color: white; - padding: 10px; - border-radius: 10px; - margin-bottom: 20px; -} - -.postActionContainer { - display: flex; - flex-direction: row; - justify-content: space-between; - gap: 10px; -} - -.postActionBtn { - background-color: white; - border: none; - color: black; -} - -.postActionBtn:hover { - background-color: ghostwhite; - border: none; - color: black; -} - -.postInput { - height: 200px !important; - resize: none; - border: none; - box-shadow: none; - background-color: white; - margin-bottom: 10px; -} - -.imageInput { - background-color: white; -} diff --git a/src/screens/UserPortal/Home/Home.test.tsx b/src/screens/UserPortal/Home/Home.test.tsx deleted file mode 100644 index 105714cfc8..0000000000 --- a/src/screens/UserPortal/Home/Home.test.tsx +++ /dev/null @@ -1,285 +0,0 @@ -import React from 'react'; -import { act, render, screen } from '@testing-library/react'; -import { MockedProvider } from '@apollo/react-testing'; -import { I18nextProvider } from 'react-i18next'; - -import { ORGANIZATION_POST_CONNECTION_LIST } from 'GraphQl/Queries/Queries'; -import { BrowserRouter } from 'react-router-dom'; -import { Provider } from 'react-redux'; -import { store } from 'state/store'; -import i18nForTest from 'utils/i18nForTest'; -import { StaticMockLink } from 'utils/StaticMockLink'; -import Home from './Home'; -import userEvent from '@testing-library/user-event'; -import * as getOrganizationId from 'utils/getOrganizationId'; -import { CREATE_POST_MUTATION } from 'GraphQl/Mutations/mutations'; -import { toast } from 'react-toastify'; -import dayjs from 'dayjs'; - -jest.mock('react-toastify', () => ({ - toast: { - error: jest.fn(), - info: jest.fn(), - success: jest.fn(), - }, -})); - -const MOCKS = [ - { - request: { - query: ORGANIZATION_POST_CONNECTION_LIST, - variables: { - id: '', - }, - }, - result: { - data: { - postsByOrganizationConnection: { - edges: [ - { - _id: '6411e53835d7ba2344a78e21', - title: 'postone', - text: 'THis is the frist post', - imageUrl: null, - videoUrl: null, - creator: { - _id: '640d98d9eb6a743d75341067', - firstName: 'Aditya', - lastName: 'Shelke', - email: 'adidacreator1@gmail.com', - }, - createdAt: dayjs(new Date()).add(1, 'day'), - likeCount: 0, - commentCount: 0, - comments: [], - likedBy: [], - pinned: false, - }, - { - _id: '6411e54835d7ba2344a78e29', - title: 'posttwo', - text: 'THis is the post two', - imageUrl: null, - videoUrl: null, - creator: { - _id: '640d98d9eb6a743d75341067', - firstName: 'Aditya', - lastName: 'Shelke', - email: 'adidacreator1@gmail.com', - }, - createdAt: dayjs(new Date()).add(1, 'day'), - likeCount: 0, - commentCount: 2, - comments: [ - { - _id: '64eb13beca85de60ebe0ed0e', - creator: { - _id: '63d6064458fce20ee25c3bf7', - firstName: 'Noble', - lastName: 'Mittal', - email: 'test@gmail.com', - __typename: 'User', - }, - likeCount: 1, - likedBy: [ - { - _id: 1, - }, - ], - text: 'First comment from Talawa user portal.', - __typename: 'Comment', - }, - { - _id: '64eb483aca85de60ebe0ef99', - creator: { - _id: '63d6064458fce20ee25c3bf7', - firstName: 'Noble', - lastName: 'Mittal', - email: 'test@gmail.com', - createdAt: '2023-02-18T09:22:27.969Z', - - __typename: 'User', - }, - likeCount: 0, - likedBy: [], - text: 'Great View', - __typename: 'Comment', - }, - ], - likedBy: [ - { - _id: '63d6064458fce20ee25c3bf7', - firstName: 'test', - lastName: 'abc', - }, - ], - pinned: false, - }, - ], - }, - }, - }, - }, - { - request: { - query: CREATE_POST_MUTATION, - variables: { - title: '', - text: 'This is a test', - organizationId: '', - file: '', - }, - result: { - data: { - createPost: { - _id: '453', - }, - }, - }, - }, - }, -]; - -const link = new StaticMockLink(MOCKS, true); - -async function wait(ms = 100): Promise { - await act(() => { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); - }); -} - -describe('Testing Home Screen [User Portal]', () => { - jest.mock('utils/getOrganizationId'); - - Object.defineProperty(window, 'matchMedia', { - writable: true, - value: jest.fn().mockImplementation((query) => ({ - matches: false, - media: query, - onchange: null, - addListener: jest.fn(), // Deprecated - removeListener: jest.fn(), // Deprecated - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - dispatchEvent: jest.fn(), - })), - }); - - test('Screen should be rendered properly', async () => { - const getOrganizationIdSpy = jest - .spyOn(getOrganizationId, 'default') - .mockImplementation(() => { - return ''; - }); - - render( - - - - - - - - - - ); - - await wait(); - - expect(getOrganizationIdSpy).toHaveBeenCalled(); - }); - - test('Screen should be rendered properly when user types on the Post Input', async () => { - const getOrganizationIdSpy = jest - .spyOn(getOrganizationId, 'default') - .mockImplementation(() => { - return ''; - }); - - render( - - - - - - - - - - ); - - await wait(); - - expect(getOrganizationIdSpy).toHaveBeenCalled(); - - const randomPostInput = 'This is a test'; - userEvent.type(screen.getByTestId('postInput'), randomPostInput); - - expect(screen.queryByText(randomPostInput)).toBeInTheDocument(); - }); - - test('Error toast should be visible when user tries to create a post with an empty body', async () => { - const getOrganizationIdSpy = jest - .spyOn(getOrganizationId, 'default') - .mockImplementation(() => { - return ''; - }); - - render( - - - - - - - - - - ); - - await wait(); - - expect(getOrganizationIdSpy).toHaveBeenCalled(); - - userEvent.click(screen.getByTestId('postAction')); - - expect(toast.error).toBeCalledWith( - "Can't create a post with an empty body." - ); - }); - - test('Info toast should be visible when user tries to create a post with a valid body', async () => { - const getOrganizationIdSpy = jest - .spyOn(getOrganizationId, 'default') - .mockImplementation(() => { - return ''; - }); - - render( - - - - - - - - - - ); - - await wait(); - - expect(getOrganizationIdSpy).toHaveBeenCalled(); - - const randomPostInput = 'This is a test'; - userEvent.type(screen.getByTestId('postInput'), randomPostInput); - expect(screen.queryByText(randomPostInput)).toBeInTheDocument(); - - userEvent.click(screen.getByTestId('postAction')); - - expect(toast.error).not.toBeCalledWith(); - expect(toast.info).toBeCalledWith('Processing your post. Please wait.'); - }); -}); diff --git a/src/screens/UserPortal/Home/Home.tsx b/src/screens/UserPortal/Home/Home.tsx deleted file mode 100644 index ad02e1b26c..0000000000 --- a/src/screens/UserPortal/Home/Home.tsx +++ /dev/null @@ -1,291 +0,0 @@ -import React from 'react'; -import type { ChangeEvent } from 'react'; -import OrganizationNavbar from 'components/UserPortal/OrganizationNavbar/OrganizationNavbar'; -import styles from './Home.module.css'; -import UserSidebar from 'components/UserPortal/UserSidebar/UserSidebar'; -import OrganizationSidebar from 'components/UserPortal/OrganizationSidebar/OrganizationSidebar'; -import ChevronRightIcon from '@mui/icons-material/ChevronRight'; -import { Button, FloatingLabel, Form } from 'react-bootstrap'; -import { Link } from 'react-router-dom'; -import getOrganizationId from 'utils/getOrganizationId'; -import SendIcon from '@mui/icons-material/Send'; -import PostCard from 'components/UserPortal/PostCard/PostCard'; -import { useMutation, useQuery } from '@apollo/client'; -import { - ADVERTISEMENTS_GET, - ORGANIZATION_POST_CONNECTION_LIST, -} from 'GraphQl/Queries/Queries'; -import { CREATE_POST_MUTATION } from 'GraphQl/Mutations/mutations'; -import { errorHandler } from 'utils/errorHandler'; -import { useTranslation } from 'react-i18next'; -import convertToBase64 from 'utils/convertToBase64'; -import { toast } from 'react-toastify'; -import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; -import PromotedPost from 'components/UserPortal/PromotedPost/PromotedPost'; - -interface InterfacePostCardProps { - id: string; - creator: { - firstName: string; - lastName: string; - email: string; - id: string; - }; - image: string; - video: string; - text: string; - title: string; - likeCount: number; - commentCount: number; - comments: { - creator: { - _id: string; - firstName: string; - lastName: string; - email: string; - }; - likeCount: number; - likedBy: { - id: string; - }[]; - text: string; - }[]; - likedBy: { - firstName: string; - lastName: string; - id: string; - }[]; -} - -export default function home(): JSX.Element { - const { t } = useTranslation('translation', { keyPrefix: 'home' }); - - const organizationId = getOrganizationId(window.location.href); - const [posts, setPosts] = React.useState([]); - const [postContent, setPostContent] = React.useState(''); - const [postImage, setPostImage] = React.useState(''); - const currentOrgId = window.location.href.split('/id=')[1] + ''; - const [adContent, setAdContent] = React.useState([]); - - const navbarProps = { - currentPage: 'home', - }; - const { - data: promotedPostsData, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - refetch: _promotedPostsRefetch, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - loading: promotedPostsLoading, - } = useQuery(ADVERTISEMENTS_GET); - const { - data, - refetch, - loading: loadingPosts, - } = useQuery(ORGANIZATION_POST_CONNECTION_LIST, { - variables: { id: organizationId }, - }); - - const [create] = useMutation(CREATE_POST_MUTATION); - - const handlePost = async (): Promise => { - try { - if (!postContent) { - throw new Error("Can't create a post with an empty body."); - } - toast.info('Processing your post. Please wait.'); - - const { data } = await create({ - variables: { - title: '', - text: postContent, - organizationId: organizationId, - file: postImage, - }, - }); - /* istanbul ignore next */ - if (data) { - toast.dismiss(); - toast.success('Your post is now visible in the feed.'); - refetch(); - setPostContent(''); - setPostImage(''); - } - } catch (error: any) { - /* istanbul ignore next */ - errorHandler(t, error); - } - }; - - const handlePostInput = (e: ChangeEvent): void => { - const content = e.target.value; - - setPostContent(content); - }; - - React.useEffect(() => { - if (data) { - setPosts(data.postsByOrganizationConnection.edges); - } - }, [data]); - - React.useEffect(() => { - if (promotedPostsData) { - setAdContent(promotedPostsData.getAdvertisements); - } - }, [data]); - - return ( - <> - -
    - -
    -
    - - - -
    - => { - const target = e.target as HTMLInputElement; - const file = target.files && target.files[0]; - if (file) { - const image = await convertToBase64(file); - setPostImage(image); - } - } - } - /> - -
    -
    -
    -

    {t('feed')}

    -
    - - {t('pinnedPosts')} - - -
    -
    - {adContent - .filter((ad: any) => ad.orgId == currentOrgId) - .filter((ad: any) => new Date(ad.endDate) > new Date()).length == 0 - ? '' - : adContent - .filter((ad: any) => ad.orgId == currentOrgId) - .filter((ad: any) => new Date(ad.endDate) > new Date()) - .map((post: any) => ( - - ))} - {loadingPosts ? ( -
    - Loading... -
    - ) : ( - <> - {posts.map((post: any) => { - const allLikes: any = []; - post.likedBy.forEach((value: any) => { - const singleLike = { - firstName: value.firstName, - lastName: value.lastName, - id: value._id, - }; - allLikes.push(singleLike); - }); - - const postComments: any = []; - post.comments.forEach((value: any) => { - const commentLikes: any = []; - - value.likedBy.forEach((commentLike: any) => { - const singleLike = { - id: commentLike._id, - }; - commentLikes.push(singleLike); - }); - - const singleCommnet: any = { - id: value._id, - creator: { - firstName: value.creator.firstName, - lastName: value.creator.lastName, - id: value.creator._id, - email: value.creator.email, - }, - likeCount: value.likeCount, - likedBy: commentLikes, - text: value.text, - }; - - postComments.push(singleCommnet); - }); - - const cardProps: InterfacePostCardProps = { - id: post._id, - creator: { - id: post.creator._id, - firstName: post.creator.firstName, - lastName: post.creator.lastName, - email: post.creator.email, - }, - image: post.imageUrl, - video: post.videoUrl, - title: post.title, - text: post.text, - likeCount: post.likeCount, - commentCount: post.commentCount, - comments: postComments, - likedBy: allLikes, - }; - - return ; - })} - - )} -
    - -
    - - ); -} diff --git a/src/screens/UserPortal/Organizations/Organizations.module.css b/src/screens/UserPortal/Organizations/Organizations.module.css index 1f49c0d158..4cd9bbbddc 100644 --- a/src/screens/UserPortal/Organizations/Organizations.module.css +++ b/src/screens/UserPortal/Organizations/Organizations.module.css @@ -6,18 +6,12 @@ color: white; } -.maxWidth { - max-width: 300px; -} - .colorLight { background-color: #f5f5f5; } .mainContainer { - width: 50%; - flex-grow: 3; - padding: 40px; + padding: 20px; max-height: 100%; overflow: auto; } @@ -27,16 +21,23 @@ min-height: calc(100% - 40px); } -.gap { - gap: 20px; -} - .paddingY { padding: 30px 0px; } .containerHeight { - height: calc(100vh - 66px); + height: 100vh; + padding: 1rem 1.5rem 0 calc(300px + 1.5rem); +} + +.expand { + padding-left: 4rem; + animation: moveLeft 0.9s ease-in-out; +} + +.contract { + padding-left: calc(300px + 2rem + 1.5rem); + animation: moveRight 0.5s ease-in-out; } .colorPrimary { @@ -46,3 +47,100 @@ .backgroundWhite { background-color: white; } + +.input { + flex: 1; + position: relative; + margin-right: 10px; +} + +.btnsContainer input { + outline: 1px solid var(--bs-gray-400); +} + +.collapseSidebarButton { + position: fixed; + height: 40px; + bottom: 0; + z-index: 9999; + width: calc(300px + 2rem); + background-color: rgba(245, 245, 245, 0.7); + color: black; + border: none; + border-radius: 0px; +} + +.collapseSidebarButton:hover, +.opendrawer:hover { + opacity: 1; + color: black !important; +} +.opendrawer { + position: fixed; + display: flex; + align-items: center; + justify-content: center; + top: 0; + left: 0; + width: 40px; + height: 100vh; + z-index: 9999; + background-color: rgba(245, 245, 245); + border: none; + border-radius: 0px; + margin-right: 20px; + color: black; +} + +.opendrawer:hover { + transition: background-color 0.5s ease; + background-color: var(--bs-primary); +} +.collapseSidebarButton:hover { + transition: background-color 0.5s ease; + background-color: var(--bs-primary); +} + +@media screen and (max-width: 850px) { + .mainContainer { + width: 100%; + } +} + +@media (max-width: 1120px) { + .collapseSidebarButton { + width: calc(250px + 2rem); + } +} + +@media (max-height: 650px) { + .collapseSidebarButton { + width: 250px; + height: 20px; + } + .opendrawer { + width: 30px; + } +} + +/* For tablets */ +@media (max-width: 820px) { + .containerHeight { + height: 100vh; + padding: 2rem; + } + .opendrawer { + width: 25px; + } + + .contract, + .expand { + animation: none; + } + + .collapseSidebarButton { + width: 100%; + left: 0; + right: 0; + } +} diff --git a/src/screens/UserPortal/Organizations/Organizations.test.tsx b/src/screens/UserPortal/Organizations/Organizations.test.tsx index 6d92831940..87d0997409 100644 --- a/src/screens/UserPortal/Organizations/Organizations.test.tsx +++ b/src/screens/UserPortal/Organizations/Organizations.test.tsx @@ -1,42 +1,87 @@ -import React from 'react'; -import { act, render, screen } from '@testing-library/react'; import { MockedProvider } from '@apollo/react-testing'; +import { act, fireEvent, render, screen } from '@testing-library/react'; import { I18nextProvider } from 'react-i18next'; +import userEvent from '@testing-library/user-event'; import { USER_CREATED_ORGANIZATIONS, USER_JOINED_ORGANIZATIONS, USER_ORGANIZATION_CONNECTION, } from 'GraphQl/Queries/Queries'; -import { BrowserRouter } from 'react-router-dom'; import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; import { store } from 'state/store'; -import i18nForTest from 'utils/i18nForTest'; import { StaticMockLink } from 'utils/StaticMockLink'; +import i18nForTest from 'utils/i18nForTest'; +import useLocalStorage from 'utils/useLocalstorage'; import Organizations from './Organizations'; -import userEvent from '@testing-library/user-event'; +import React from 'react'; +const { getItem } = useLocalStorage(); const MOCKS = [ { request: { query: USER_CREATED_ORGANIZATIONS, variables: { - id: localStorage.getItem('userId'), + id: getItem('userId'), }, }, result: { data: { users: [ { - createdOrganizations: [ - { - __typename: 'Organization', - _id: '6401ff65ce8e8406b8f07af2', - name: 'createdOrganization', - image: '', - description: 'New Desc', - }, - ], + appUserProfile: { + createdOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + image: '', + name: 'anyOrganization1', + description: 'desc', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + createdAt: '1234567890', + userRegistrationRequired: true, + creator: { + __typename: 'User', + firstName: 'John', + lastName: 'Doe', + }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + }, + ], + }, }, ], }, @@ -58,17 +103,87 @@ const MOCKS = [ image: '', name: 'anyOrganization1', description: 'desc', - isPublic: true, + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + createdAt: '1234567890', + userRegistrationRequired: true, creator: { __typename: 'User', firstName: 'John', lastName: 'Doe' }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], }, { __typename: 'Organization', _id: '6401ff65ce8e8406b8f07af3', image: '', name: 'anyOrganization2', + createdAt: '1234567890', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, description: 'desc', - isPublic: true, + userRegistrationRequired: true, creator: { __typename: 'User', firstName: 'John', lastName: 'Doe' }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], }, ], }, @@ -78,22 +193,65 @@ const MOCKS = [ request: { query: USER_JOINED_ORGANIZATIONS, variables: { - id: localStorage.getItem('userId'), + id: getItem('userId'), }, }, result: { data: { users: [ { - joinedOrganizations: [ - { - __typename: 'Organization', - _id: '6401ff65ce8e8406b8f07af2', - name: 'joinedOrganization', - image: '', - description: 'New Desc', - }, - ], + user: { + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + image: '', + name: 'anyOrganization1', + description: 'desc', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + createdAt: '1234567890', + userRegistrationRequired: true, + creator: { + __typename: 'User', + firstName: 'John', + lastName: 'Doe', + }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + }, + ], + }, }, ], }, @@ -115,8 +273,43 @@ const MOCKS = [ image: '', name: 'anyOrganization2', description: 'desc', - isPublic: true, + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + userRegistrationRequired: true, + createdAt: '1234567890', creator: { __typename: 'User', firstName: 'John', lastName: 'Doe' }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + user: { + _id: '4567890fgvhbjn', + }, + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], }, ], }, @@ -134,6 +327,11 @@ async function wait(ms = 100): Promise { }); } +const resizeWindow = (width: number): void => { + window.innerWidth = width; + fireEvent(window, new Event('resize')); +}; + describe('Testing Organizations Screen [User Portal]', () => { test('Screen should be rendered properly', async () => { render( @@ -145,7 +343,7 @@ describe('Testing Organizations Screen [User Portal]', () => { - + , ); await wait(); @@ -161,16 +359,19 @@ describe('Testing Organizations Screen [User Portal]', () => { - + , ); await wait(); - - userEvent.type(screen.getByTestId('searchInput'), '2'); + const searchBtn = screen.getByTestId('searchBtn'); + userEvent.type(screen.getByTestId('searchInput'), '2{enter}'); await wait(); expect(screen.queryByText('anyOrganization2')).toBeInTheDocument(); - expect(screen.queryByText('anyOrganization1')).not.toBeInTheDocument(); + + userEvent.clear(screen.getByTestId('searchInput')); + userEvent.click(searchBtn); + await wait(); }); test('Mode is changed to joined organizations', async () => { @@ -183,7 +384,7 @@ describe('Testing Organizations Screen [User Portal]', () => { - + , ); await wait(); @@ -206,7 +407,7 @@ describe('Testing Organizations Screen [User Portal]', () => { - + , ); await wait(); @@ -218,4 +419,93 @@ describe('Testing Organizations Screen [User Portal]', () => { expect(screen.queryAllByText('createdOrganization')).not.toBe([]); }); + + test('Join Now button render correctly', async () => { + render( + + + + + + + + + , + ); + + await wait(); + + // Assert "Join Now" button + const joinNowButtons = screen.getAllByTestId('joinBtn'); + expect(joinNowButtons.length).toBeGreaterThan(0); + }); + + test('Mode is changed to created organizations', async () => { + render( + + + + + + + + + , + ); + + await wait(); + + userEvent.click(screen.getByTestId('modeChangeBtn')); + await wait(); + userEvent.click(screen.getByTestId('modeBtn2')); + await wait(); + + expect(screen.queryAllByText('createdOrganization')).not.toBe([]); + }); + + test('Testing Sidebar', async () => { + render( + + + + + + + + + , + ); + + await wait(); + + const closeMenubtn = screen.getByTestId('closeMenu'); + expect(closeMenubtn).toBeInTheDocument(); + closeMenubtn.click(); + const openMenuBtn = screen.getByTestId('openMenu'); + expect(openMenuBtn).toBeInTheDocument(); + openMenuBtn.click(); + }); + + test('Testing sidebar when the screen size is less than or equal to 820px', async () => { + resizeWindow(800); + render( + + + + + + + + + , + ); + + await wait(); + expect(screen.getByText('My Organizations')).toBeInTheDocument(); + expect(screen.getByText('Talawa User Portal')).toBeInTheDocument(); + + const settingsBtn = screen.getByTestId('settingsBtn'); + + settingsBtn.click(); + }); }); diff --git a/src/screens/UserPortal/Organizations/Organizations.tsx b/src/screens/UserPortal/Organizations/Organizations.tsx index c0b77f805e..f9fae1f671 100644 --- a/src/screens/UserPortal/Organizations/Organizations.tsx +++ b/src/screens/UserPortal/Organizations/Organizations.tsx @@ -1,31 +1,92 @@ -import React from 'react'; -import UserNavbar from 'components/UserPortal/UserNavbar/UserNavbar'; -import OrganizationCard from 'components/UserPortal/OrganizationCard/OrganizationCard'; -import UserSidebar from 'components/UserPortal/UserSidebar/UserSidebar'; -import { Dropdown, Form, InputGroup } from 'react-bootstrap'; -import PaginationList from 'components/PaginationList/PaginationList'; +import { useQuery } from '@apollo/client'; +import { SearchOutlined } from '@mui/icons-material'; +import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; import { USER_CREATED_ORGANIZATIONS, USER_JOINED_ORGANIZATIONS, USER_ORGANIZATION_CONNECTION, } from 'GraphQl/Queries/Queries'; -import { useQuery } from '@apollo/client'; -import { SearchOutlined } from '@mui/icons-material'; -import styles from './Organizations.module.css'; +import PaginationList from 'components/PaginationList/PaginationList'; +import OrganizationCard from 'components/UserPortal/OrganizationCard/OrganizationCard'; +import UserSidebar from 'components/UserPortal/UserSidebar/UserSidebar'; +import React, { useEffect, useState } from 'react'; +import { Button, Dropdown, Form, InputGroup } from 'react-bootstrap'; import { useTranslation } from 'react-i18next'; -import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; +import useLocalStorage from 'utils/useLocalstorage'; +import styles from './Organizations.module.css'; +import ProfileDropdown from 'components/ProfileDropdown/ProfileDropdown'; + +const { getItem } = useLocalStorage(); interface InterfaceOrganizationCardProps { id: string; name: string; image: string; description: string; + admins: []; + members: []; + address: { + city: string; + countryCode: string; + line1: string; + postalCode: string; + state: string; + }; + membershipRequestStatus: string; + userRegistrationRequired: boolean; + membershipRequests: { + _id: string; + user: { + _id: string; + }; + }[]; +} + +interface InterfaceOrganization { + _id: string; + name: string; + image: string; + description: string; + admins: []; + members: []; + address: { + city: string; + countryCode: string; + line1: string; + postalCode: string; + state: string; + }; + membershipRequestStatus: string; + userRegistrationRequired: boolean; + membershipRequests: { + _id: string; + user: { + _id: string; + }; + }[]; } + export default function organizations(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'userOrganizations', }); + const [hideDrawer, setHideDrawer] = useState(null); + + const handleResize = (): void => { + if (window.innerWidth <= 820) { + setHideDrawer(!hideDrawer); + } + }; + + useEffect(() => { + handleResize(); + window.addEventListener('resize', handleResize); + return () => { + window.removeEventListener('resize', handleResize); + }; + }, []); + const [page, setPage] = React.useState(0); const [rowsPerPage, setRowsPerPage] = React.useState(5); const [organizations, setOrganizations] = React.useState([]); @@ -38,7 +99,7 @@ export default function organizations(): JSX.Element { t('createdOrganizations'), ]; - const userId: string | null = localStorage.getItem('userId'); + const userId: string | null = getItem('userId'); const { data, @@ -48,25 +109,31 @@ export default function organizations(): JSX.Element { variables: { filter: filterName }, }); - const { data: data2 } = useQuery(USER_JOINED_ORGANIZATIONS, { - variables: { id: userId }, - }); + const { data: joinedOrganizationsData } = useQuery( + USER_JOINED_ORGANIZATIONS, + { + variables: { id: userId }, + }, + ); - const { data: data3 } = useQuery(USER_CREATED_ORGANIZATIONS, { - variables: { id: userId }, - }); + const { data: createdOrganizationsData } = useQuery( + USER_CREATED_ORGANIZATIONS, + { + variables: { id: userId }, + }, + ); /* istanbul ignore next */ const handleChangePage = ( _event: React.MouseEvent | null, - newPage: number + newPage: number, ): void => { setPage(newPage); }; /* istanbul ignore next */ const handleChangeRowsPerPage = ( - event: React.ChangeEvent + event: React.ChangeEvent, ): void => { const newRowsPerPage = event.target.value; @@ -74,64 +141,150 @@ export default function organizations(): JSX.Element { setPage(0); }; - const handleSearch = ( - event: React.ChangeEvent - ): void => { - const newFilter = event.target.value; - setFilterName(newFilter); - - const filter = { - filter: newFilter, - }; + const handleSearch = (value: string): void => { + setFilterName(value); - refetch(filter); + refetch({ + filter: value, + }); + }; + const handleSearchByEnter = ( + e: React.KeyboardEvent, + ): void => { + if (e.key === 'Enter') { + const { value } = e.target as HTMLInputElement; + handleSearch(value); + } + }; + const handleSearchByBtnClick = (): void => { + const value = + (document.getElementById('searchUserOrgs') as HTMLInputElement)?.value || + ''; + handleSearch(value); }; /* istanbul ignore next */ React.useEffect(() => { if (data) { - setOrganizations(data.organizationsConnection); + const organizations = data.organizationsConnection.map( + (organization: InterfaceOrganization) => { + let membershipRequestStatus = ''; + if ( + organization.members.find( + (member: { _id: string }) => member._id === userId, + ) + ) + membershipRequestStatus = 'accepted'; + else if ( + organization.membershipRequests.find( + (request: { user: { _id: string } }) => + request.user._id === userId, + ) + ) + membershipRequestStatus = 'pending'; + return { ...organization, membershipRequestStatus }; + }, + ); + setOrganizations(organizations); } }, [data]); /* istanbul ignore next */ React.useEffect(() => { - if (mode == 0) { + if (mode === 0) { if (data) { - setOrganizations(data.organizationsConnection); + const organizations = data.organizationsConnection.map( + (organization: InterfaceOrganization) => { + let membershipRequestStatus = ''; + if ( + organization.members.find( + (member: { _id: string }) => member._id === userId, + ) + ) + membershipRequestStatus = 'accepted'; + else if ( + organization.membershipRequests.find( + (request: { user: { _id: string } }) => + request.user._id === userId, + ) + ) + membershipRequestStatus = 'pending'; + return { ...organization, membershipRequestStatus }; + }, + ); + setOrganizations(organizations); } - } else if (mode == 1) { - if (data2) { - setOrganizations(data2.users[0].joinedOrganizations); + } else if (mode === 1) { + if (joinedOrganizationsData && joinedOrganizationsData.users.length > 0) { + const organizations = + joinedOrganizationsData.users[0]?.user?.joinedOrganizations || []; + setOrganizations(organizations); } - } else if (mode == 2) { - if (data3) { - setOrganizations(data3.users[0].createdOrganizations); + } else if (mode === 2) { + if ( + createdOrganizationsData && + createdOrganizationsData.users.length > 0 + ) { + const organizations = + createdOrganizationsData.users[0]?.appUserProfile + ?.createdOrganizations || []; + setOrganizations(organizations); } } - }, [mode]); - + }, [mode, data, joinedOrganizationsData, createdOrganizationsData, userId]); return ( <> - -
    - -
    + {hideDrawer ? ( + + ) : ( + + )} + +
    +
    +
    + +

    {t('selectOrganization')}

    -
    +
    @@ -178,16 +331,24 @@ export default function organizations(): JSX.Element { (rowsPerPage > 0 ? organizations.slice( page * rowsPerPage, - page * rowsPerPage + rowsPerPage + page * rowsPerPage + rowsPerPage, ) : /* istanbul ignore next */ organizations - ).map((organization: any, index) => { + ).map((organization: InterfaceOrganization, index) => { const cardProps: InterfaceOrganizationCardProps = { name: organization.name, image: organization.image, id: organization._id, description: organization.description, + admins: organization.admins, + members: organization.members, + address: organization.address, + membershipRequestStatus: + organization.membershipRequestStatus, + userRegistrationRequired: + organization.userRegistrationRequired, + membershipRequests: organization.membershipRequests, }; return ; }) diff --git a/src/screens/UserPortal/People/People.module.css b/src/screens/UserPortal/People/People.module.css index f67df3b23f..840be105f7 100644 --- a/src/screens/UserPortal/People/People.module.css +++ b/src/screens/UserPortal/People/People.module.css @@ -1,17 +1,50 @@ .borderNone { border: none; } +.borderBox { + border: 1px solid #dddddd; +} + +.borderRounded5 { + border-radius: 5px; +} + +.borderRounded8 { + border-radius: 8px; +} + +.borderRounded24 { + border-radius: 24px; +} + +.topRadius { + border-top-left-radius: 24px; + border-top-right-radius: 24px; +} + +.bottomRadius { + border-bottom-left-radius: 24px; + border-bottom-right-radius: 24px; +} + +.shadow { + box-shadow: 5px 5px 4px 0px #31bb6b1f; +} .colorWhite { color: white; } +.colorGreen { + color: #31bb6b; +} + .backgroundWhite { background-color: white; } .maxWidth { - max-width: 300px; + max-width: 600px; } .colorLight { @@ -35,14 +68,22 @@ gap: 20px; } -.paddingY { - padding: 30px 0px; -} - .containerHeight { - height: calc(100vh - 66px); + height: 100vh; } .colorPrimary { background: #31bb6b; } + +.greenBorder { + border: 1px solid #31bb6b; +} + +.semiBold { + font-weight: 500; +} + +.placeholderColor::placeholder { + color: #737373; +} diff --git a/src/screens/UserPortal/People/People.test.tsx b/src/screens/UserPortal/People/People.test.tsx index b373a68e98..a233c20015 100644 --- a/src/screens/UserPortal/People/People.test.tsx +++ b/src/screens/UserPortal/People/People.test.tsx @@ -2,7 +2,6 @@ import React from 'react'; import { act, render, screen } from '@testing-library/react'; import { MockedProvider } from '@apollo/react-testing'; import { I18nextProvider } from 'react-i18next'; - import { ORGANIZATIONS_MEMBER_CONNECTION_LIST, ORGANIZATION_ADMINS_LIST, @@ -14,7 +13,6 @@ import i18nForTest from 'utils/i18nForTest'; import { StaticMockLink } from 'utils/StaticMockLink'; import People from './People'; import userEvent from '@testing-library/user-event'; -import * as getOrganizationId from 'utils/getOrganizationId'; const MOCKS = [ { @@ -70,6 +68,7 @@ const MOCKS = [ lastName: 'Admin', image: null, email: 'noble@gmail.com', + createdAt: '2023-03-02T03:22:08.101Z', }, ], }, @@ -114,9 +113,12 @@ async function wait(ms = 100): Promise { }); } -describe('Testing People Screen [User Portal]', () => { - jest.mock('utils/getOrganizationId'); +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: '' }), +})); +describe('Testing People Screen [User Portal]', () => { Object.defineProperty(window, 'matchMedia', { writable: true, value: jest.fn().mockImplementation((query) => ({ @@ -131,12 +133,6 @@ describe('Testing People Screen [User Portal]', () => { })), }); - const getOrganizationIdSpy = jest - .spyOn(getOrganizationId, 'default') - .mockImplementation(() => { - return ''; - }); - test('Screen should be rendered properly', async () => { render( @@ -147,16 +143,15 @@ describe('Testing People Screen [User Portal]', () => { - + , ); await wait(); - expect(getOrganizationIdSpy).toHaveBeenCalled(); expect(screen.queryAllByText('Noble Mittal')).not.toBe([]); }); - test('Search works properly', async () => { + test('Search works properly by pressing enter', async () => { render( @@ -166,15 +161,40 @@ describe('Testing People Screen [User Portal]', () => { - + , ); await wait(); + userEvent.type(screen.getByTestId('searchInput'), 'j{enter}'); + await wait(); + + expect(screen.queryByText('John Cena')).toBeInTheDocument(); + expect(screen.queryByText('Noble Mittal')).not.toBeInTheDocument(); + }); + + test('Search works properly by clicking search Btn', async () => { + render( + + + + + + + + + , + ); + + await wait(); + const searchBtn = screen.getByTestId('searchBtn'); + userEvent.type(screen.getByTestId('searchInput'), ''); + userEvent.click(searchBtn); + await wait(); userEvent.type(screen.getByTestId('searchInput'), 'j'); + userEvent.click(searchBtn); await wait(); - expect(getOrganizationIdSpy).toHaveBeenCalled(); expect(screen.queryByText('John Cena')).toBeInTheDocument(); expect(screen.queryByText('Noble Mittal')).not.toBeInTheDocument(); }); @@ -189,7 +209,7 @@ describe('Testing People Screen [User Portal]', () => { - + , ); await wait(); @@ -199,7 +219,6 @@ describe('Testing People Screen [User Portal]', () => { userEvent.click(screen.getByTestId('modeBtn1')); await wait(); - expect(getOrganizationIdSpy).toHaveBeenCalled(); expect(screen.queryByText('Noble Admin')).toBeInTheDocument(); expect(screen.queryByText('Noble Mittal')).not.toBeInTheDocument(); }); diff --git a/src/screens/UserPortal/People/People.tsx b/src/screens/UserPortal/People/People.tsx index f8b4d7ca3d..f8de35e6e9 100644 --- a/src/screens/UserPortal/People/People.tsx +++ b/src/screens/UserPortal/People/People.tsx @@ -1,8 +1,5 @@ import React from 'react'; -import OrganizationNavbar from 'components/UserPortal/OrganizationNavbar/OrganizationNavbar'; -import OrganizationSidebar from 'components/UserPortal/OrganizationSidebar/OrganizationSidebar'; import PeopleCard from 'components/UserPortal/PeopleCard/PeopleCard'; -import UserSidebar from 'components/UserPortal/UserSidebar/UserSidebar'; import { Dropdown, Form, InputGroup } from 'react-bootstrap'; import PaginationList from 'components/PaginationList/PaginationList'; import { @@ -10,17 +7,28 @@ import { ORGANIZATION_ADMINS_LIST, } from 'GraphQl/Queries/Queries'; import { useQuery } from '@apollo/client'; -import { SearchOutlined } from '@mui/icons-material'; +import { FilterAltOutlined, SearchOutlined } from '@mui/icons-material'; import styles from './People.module.css'; import { useTranslation } from 'react-i18next'; import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; -import getOrganizationId from 'utils/getOrganizationId'; +import { useParams } from 'react-router-dom'; interface InterfaceOrganizationCardProps { id: string; name: string; image: string; email: string; + role: string; + sno: string; +} + +interface InterfaceMember { + firstName: string; + lastName: string; + image: string; + _id: string; + email: string; + userType: string; } export default function people(): JSX.Element { @@ -31,10 +39,9 @@ export default function people(): JSX.Element { const [page, setPage] = React.useState(0); const [rowsPerPage, setRowsPerPage] = React.useState(5); const [members, setMembers] = React.useState([]); - const [filterName, setFilterName] = React.useState(''); const [mode, setMode] = React.useState(0); - const organizationId = getOrganizationId(window.location.href); + const { orgId: organizationId } = useParams(); const modes = ['All Members', 'Admins']; @@ -45,7 +52,7 @@ export default function people(): JSX.Element { orgId: organizationId, firstName_contains: '', }, - } + }, ); const { data: data2 } = useQuery(ORGANIZATION_ADMINS_LIST, { @@ -55,14 +62,14 @@ export default function people(): JSX.Element { /* istanbul ignore next */ const handleChangePage = ( _event: React.MouseEvent | null, - newPage: number + newPage: number, ): void => { setPage(newPage); }; /* istanbul ignore next */ const handleChangeRowsPerPage = ( - event: React.ChangeEvent + event: React.ChangeEvent, ): void => { const newRowsPerPage = event.target.value; @@ -70,23 +77,32 @@ export default function people(): JSX.Element { setPage(0); }; - const handleSearch = ( - event: React.ChangeEvent - ): void => { - const newFilter = event.target.value; - setFilterName(newFilter); - - const filter = { + const handleSearch = (newFilter: string): void => { + refetch({ firstName_contains: newFilter, - }; + }); + }; - refetch(filter); + const handleSearchByEnter = ( + e: React.KeyboardEvent, + ): void => { + if (e.key === 'Enter') { + const { value } = e.currentTarget; + handleSearch(value); + } + }; + + const handleSearchByBtnClick = (): void => { + const inputValue = + (document.getElementById('searchPeople') as HTMLInputElement)?.value || + ''; + handleSearch(inputValue); }; - /* istanbul ignore next */ React.useEffect(() => { if (data) { setMembers(data.organizationsMemberConnection.edges); + console.log(data); } }, [data]); @@ -103,42 +119,40 @@ export default function people(): JSX.Element { } }, [mode]); - const navbarProps = { - currentPage: 'people', - }; - return ( <> -
    -
    +

    People

    - + - {modes[mode]} + + {t('filter').toUpperCase()} {modes.map((value, index) => { @@ -155,11 +169,22 @@ export default function people(): JSX.Element {
    -
    +
    +
    + + S.No + Avatar + + {/* Avatar */} + Name + Email + Role +
    +
    {loading ? (
    @@ -171,11 +196,11 @@ export default function people(): JSX.Element { (rowsPerPage > 0 ? members.slice( page * rowsPerPage, - page * rowsPerPage + rowsPerPage + page * rowsPerPage + rowsPerPage, ) : /* istanbul ignore next */ members - ).map((member: any, index) => { + ).map((member: InterfaceMember, index) => { const name = `${member.firstName} ${member.lastName}`; const cardProps: InterfaceOrganizationCardProps = { @@ -183,6 +208,8 @@ export default function people(): JSX.Element { image: member.image, id: member._id, email: member.email, + role: member.userType, + sno: (index + 1).toString(), }; return ; }) @@ -210,7 +237,7 @@ export default function people(): JSX.Element {
    - + {/* */}
    ); diff --git a/src/screens/UserPortal/Posts/Posts.module.css b/src/screens/UserPortal/Posts/Posts.module.css new file mode 100644 index 0000000000..0cd897266b --- /dev/null +++ b/src/screens/UserPortal/Posts/Posts.module.css @@ -0,0 +1,164 @@ +.borderNone { + border: none; +} + +.colorWhite { + color: white; +} + +.maxWidth { + max-width: 300px; +} + +.colorLight { + background-color: #f5f5f5; +} + +.mainContainer { + width: 50%; + flex-grow: 3; + padding: 30px; + max-height: 100%; + overflow: auto; +} + +.containerHeight { + height: 100vh; +} + +.link { + text-decoration: none !important; + color: black; +} + +.postInputContainer { + background-color: white; + padding: 10px; + border-radius: 10px; + margin-bottom: 20px; +} + +.postActionContainer { + display: flex; + flex-direction: row; + justify-content: space-between; + gap: 10px; +} + +.postActionBtn { + background-color: white; + border: none; + color: black; +} + +.postActionBtn:hover { + background-color: ghostwhite; + border: none; + color: black; +} + +.postInput { + resize: none; + border: none; + outline: none; + box-shadow: none; + background-color: white; + margin-bottom: 10px; +} + +.postInput:focus { + box-shadow: none; +} + +.postContainer { + margin: 1rem auto; + background-color: transparent; + padding: 1rem; + border-radius: 4px; + /* max-width: 40rem; */ + box-shadow: rgba(0, 0, 0, 0.16) 0px 1px 4px; +} + +.userImage { + display: flex; + width: 50px; + height: 50px; + align-items: center; + justify-content: center; + overflow: hidden; + border-radius: 50%; + position: relative; + border: 2px solid #31bb6b; +} + +.userImage img { + position: absolute; + top: 0; + left: 0; + width: 100%; + scale: 1.5; +} + +.startPostBtn { + width: 100%; + border-radius: 25px; + background-color: transparent; + /* border: 1px solid #acacac; */ + box-shadow: rgba(0, 0, 0, 0.16) 0px 1px 4px; + outline: none; + border: none; + color: #000; + font-weight: 900; +} + +.startPostBtn:hover { + background-color: #00000010; + border: 0; + color: #000 !important; +} + +.icons { + width: 25px; +} + +.icons svg { + stroke: #000; +} + +.icons.dark { + cursor: pointer; + border: none; + outline: none; + background-color: transparent; +} + +.icons.dark svg { + stroke: #000; +} + +.iconLabel { + margin: 0; + color: #000; + font-weight: 900; +} + +.uploadLink { + text-align: center; + width: min-content; + padding: 8px 4px; + border-radius: 4px; + cursor: pointer; +} + +.uploadLink:hover { + background-color: #00000010; +} + +.modal { + width: 100dvw; + margin: 0 auto; +} + +.imageInput { + display: none; +} diff --git a/src/screens/UserPortal/Posts/Posts.test.tsx b/src/screens/UserPortal/Posts/Posts.test.tsx new file mode 100644 index 0000000000..b4c1344d2c --- /dev/null +++ b/src/screens/UserPortal/Posts/Posts.test.tsx @@ -0,0 +1,361 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import type { RenderResult } from '@testing-library/react'; +import { act, render, screen, waitFor, within } from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import userEvent from '@testing-library/user-event'; +import { + ADVERTISEMENTS_GET, + ORGANIZATION_POST_LIST, +} from 'GraphQl/Queries/Queries'; +import { Provider } from 'react-redux'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18nForTest from 'utils/i18nForTest'; +import Home from './Posts'; +import useLocalStorage from 'utils/useLocalstorage'; + +const { setItem } = useLocalStorage(); + +jest.mock('react-toastify', () => ({ + toast: { + error: jest.fn(), + info: jest.fn(), + success: jest.fn(), + }, +})); + +const MOCKS = [ + { + request: { + query: ORGANIZATION_POST_LIST, + variables: { + id: 'orgId', + first: 10, + }, + }, + result: { + data: { + organizations: [ + { + posts: { + edges: [ + { + node: { + _id: '6411e53835d7ba2344a78e21', + title: 'post one', + text: 'This is the first post', + imageUrl: null, + videoUrl: null, + createdAt: '2024-03-03T09:26:56.524+00:00', + creator: { + _id: '640d98d9eb6a743d75341067', + firstName: 'Glen', + lastName: 'Dsza', + email: 'glendsza@gmail.com', + }, + likeCount: 0, + commentCount: 0, + comments: [], + pinned: true, + likedBy: [], + }, + cursor: '6411e53835d7ba2344a78e21', + }, + { + node: { + _id: '6411e54835d7ba2344a78e29', + title: 'post two', + text: 'This is the post two', + imageUrl: null, + videoUrl: null, + createdAt: '2024-03-03T09:26:56.524+00:00', + creator: { + _id: '640d98d9eb6a743d75341067', + firstName: 'Glen', + lastName: 'Dsza', + email: 'glendsza@gmail.com', + }, + likeCount: 2, + commentCount: 1, + pinned: false, + likedBy: [ + { + _id: '640d98d9eb6a743d75341067', + firstName: 'Glen', + lastName: 'Dsza', + }, + { + _id: '640d98d9eb6a743d75341068', + firstName: 'Glen2', + lastName: 'Dsza2', + }, + ], + comments: [ + { + _id: '6411e54835d7ba2344a78e29', + creator: { + _id: '640d98d9eb6a743d75341067', + firstName: 'Glen', + lastName: 'Dsza', + email: 'glendsza@gmail.com', + }, + likeCount: 2, + likedBy: [ + { + _id: '640d98d9eb6a743d75341067', + firstName: 'Glen', + lastName: 'Dsza', + }, + { + _id: '640d98d9eb6a743d75341068', + firstName: 'Glen2', + lastName: 'Dsza2', + }, + ], + text: 'This is the post two', + createdAt: '2024-03-03T09:26:56.524+00:00', + }, + ], + }, + cursor: '6411e54835d7ba2344a78e29', + }, + ], + pageInfo: { + startCursor: '6411e53835d7ba2344a78e21', + endCursor: '6411e54835d7ba2344a78e31', + hasNextPage: false, + hasPreviousPage: false, + }, + totalCount: 2, + }, + }, + ], + }, + }, + }, + { + request: { + query: ADVERTISEMENTS_GET, + variables: {}, + }, + result: { + data: { + advertisementsConnection: { + edges: [ + { + node: { + _id: '1234', + name: 'Ad 1', + type: 'Type 1', + organization: { + _id: 'orgId', + }, + mediaUrl: 'Link 1', + endDate: '2024-12-31', + startDate: '2022-01-01', + }, + }, + { + node: { + _id: '2345', + name: 'Ad 2', + type: 'Type 1', + organization: { + _id: 'orgId', + }, + mediaUrl: 'Link 2', + endDate: '2024-09-31', + startDate: '2023-04-01', + }, + }, + { + node: { + _id: '3456', + name: 'name3', + type: 'Type 2', + organization: { + _id: 'orgId', + }, + mediaUrl: 'link3', + startDate: '2023-01-30', + endDate: '2023-12-31', + }, + }, + { + node: { + _id: '4567', + name: 'name4', + type: 'Type 2', + organization: { + _id: 'orgId1', + }, + mediaUrl: 'link4', + startDate: '2023-01-30', + endDate: '2023-12-01', + }, + }, + ], + }, + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); + +afterEach(() => { + localStorage.clear(); +}); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +const renderHomeScreen = (): RenderResult => + render( + + + + + + } /> + + + + + , + ); + +Object.defineProperty(window, 'matchMedia', { + writable: true, + value: jest.fn().mockImplementation((query) => ({ + matches: false, + media: query, + onchange: null, + addListener: jest.fn(), // Deprecated + removeListener: jest.fn(), // Deprecated + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn(), + })), +}); + +describe('Testing Home Screen: User Portal', () => { + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId' }), + })); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + test('Check if HomeScreen renders properly', async () => { + renderHomeScreen(); + + await wait(); + const startPostBtn = await screen.findByTestId('startPostBtn'); + expect(startPostBtn).toBeInTheDocument(); + }); + + test('StartPostModal should render on click of StartPost btn', async () => { + renderHomeScreen(); + + await wait(); + const startPostBtn = await screen.findByTestId('startPostBtn'); + expect(startPostBtn).toBeInTheDocument(); + + userEvent.click(startPostBtn); + const startPostModal = screen.getByTestId('startPostModal'); + expect(startPostModal).toBeInTheDocument(); + }); + + test('StartPostModal should close on clicking the close button', async () => { + renderHomeScreen(); + + await wait(); + const startPostBtn = await screen.findByTestId('startPostBtn'); + expect(startPostBtn).toBeInTheDocument(); + + userEvent.click(startPostBtn); + const startPostModal = screen.getByTestId('startPostModal'); + expect(startPostModal).toBeInTheDocument(); + + userEvent.type(screen.getByTestId('postInput'), 'some content'); + userEvent.upload( + screen.getByTestId('postImageInput'), + new File(['image content'], 'image.png', { type: 'image/png' }), + ); + + // Check that the content and image have been added + expect(screen.getByTestId('postInput')).toHaveValue('some content'); + await screen.findByAltText('Post Image Preview'); + expect(screen.getByAltText('Post Image Preview')).toBeInTheDocument(); + + const closeButton = within(startPostModal).getByRole('button', { + name: /close/i, + }); + userEvent.click(closeButton); + + const closedModalText = screen.queryByText(/somethingOnYourMind/i); + expect(closedModalText).not.toBeInTheDocument(); + + expect(screen.getByTestId('postInput')).toHaveValue(''); + expect(screen.getByTestId('postImageInput')).toHaveValue(''); + }); + + test('Check whether Posts render in PostCard', async () => { + setItem('userId', '640d98d9eb6a743d75341067'); + renderHomeScreen(); + await wait(); + + const postCardContainers = screen.findAllByTestId('postCardContainer'); + expect(postCardContainers).not.toBeNull(); + + expect(screen.queryByText('post one')).toBeInTheDocument(); + expect(screen.queryByText('This is the first post')).toBeInTheDocument(); + + expect(screen.queryByText('post two')).toBeInTheDocument(); + expect(screen.queryByText('This is the post two')).toBeInTheDocument(); + }); +}); + +describe('HomeScreen with invalid orgId', () => { + test('Redirect to /user when organizationId is falsy', async () => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: undefined }), + })); + render( + + + + + + } /> +
    } + /> + + + + + , + ); + + // Wait for the navigation to occur + await waitFor(() => { + const homeEl = screen.getByTestId('homeEl'); + expect(homeEl).toBeInTheDocument(); + }); + }); +}); diff --git a/src/screens/UserPortal/Posts/Posts.tsx b/src/screens/UserPortal/Posts/Posts.tsx new file mode 100644 index 0000000000..22de2a95f3 --- /dev/null +++ b/src/screens/UserPortal/Posts/Posts.tsx @@ -0,0 +1,356 @@ +import { useQuery } from '@apollo/client'; +import ChevronRightIcon from '@mui/icons-material/ChevronRight'; +import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; +import { + ADVERTISEMENTS_GET, + ORGANIZATION_POST_LIST, + USER_DETAILS, +} from 'GraphQl/Queries/Queries'; +import PostCard from 'components/UserPortal/PostCard/PostCard'; +import type { + InterfacePostCard, + InterfaceQueryUserListItem, +} from 'utils/interfaces'; +import PromotedPost from 'components/UserPortal/PromotedPost/PromotedPost'; +import StartPostModal from 'components/UserPortal/StartPostModal/StartPostModal'; +import React, { useEffect, useState } from 'react'; +import { Button, Col, Container, Image, Row } from 'react-bootstrap'; +import { useTranslation } from 'react-i18next'; + +import { Link, Navigate, useParams } from 'react-router-dom'; +import useLocalStorage from 'utils/useLocalstorage'; +import UserDefault from '../../../assets/images/defaultImg.png'; +import { ReactComponent as MediaIcon } from 'assets/svgs/media.svg'; +import { ReactComponent as ArticleIcon } from 'assets/svgs/article.svg'; +import { ReactComponent as EventIcon } from 'assets/svgs/userEvent.svg'; +import styles from './Posts.module.css'; + +interface InterfaceAdContent { + _id: string; + name: string; + type: string; + organization: { + _id: string; + }; + mediaUrl: string; + endDate: string; + startDate: string; + + comments: InterfacePostComments; + likes: InterfacePostLikes; +} + +type AdvertisementsConnection = { + edges: { + node: InterfaceAdContent; + }[]; +}; + +interface InterfaceAdConnection { + advertisementsConnection?: AdvertisementsConnection; +} + +type InterfacePostComments = { + creator: { + _id: string; + firstName: string; + lastName: string; + email: string; + }; + likeCount: number; + likedBy: { + id: string; + }[]; + text: string; +}[]; + +type InterfacePostLikes = { + firstName: string; + lastName: string; + id: string; +}[]; + +type InterfacePostNode = { + commentCount: number; + createdAt: string; + creator: { + email: string; + firstName: string; + lastName: string; + _id: string; + }; + imageUrl: string | null; + likeCount: number; + likedBy: { + _id: string; + firstName: string; + lastName: string; + }[]; + pinned: boolean; + text: string; + title: string; + videoUrl: string | null; + _id: string; + + comments: InterfacePostComments; + likes: InterfacePostLikes; +}; + +export default function home(): JSX.Element { + const { t } = useTranslation('translation', { keyPrefix: 'home' }); + const { getItem } = useLocalStorage(); + const [posts, setPosts] = useState([]); + const [adContent, setAdContent] = useState({}); + const [filteredAd, setFilteredAd] = useState([]); + const [showModal, setShowModal] = useState(false); + const { orgId } = useParams(); + + if (!orgId) { + return ; + } + + const { data: promotedPostsData } = useQuery(ADVERTISEMENTS_GET); + const { + data, + refetch, + loading: loadingPosts, + } = useQuery(ORGANIZATION_POST_LIST, { + variables: { id: orgId, first: 10 }, + }); + const userId: string | null = getItem('userId'); + + const { data: userData } = useQuery(USER_DETAILS, { + variables: { id: userId }, + }); + + const user: InterfaceQueryUserListItem | undefined = userData?.user; + + useEffect(() => { + if (data) { + setPosts(data.organizations[0].posts.edges); + } + }, [data]); + + useEffect(() => { + if (promotedPostsData) { + setAdContent(promotedPostsData); + } + }, [promotedPostsData]); + + useEffect(() => { + setFilteredAd(filterAdContent(adContent, orgId)); + }, [adContent]); + + const filterAdContent = ( + data: { + advertisementsConnection?: { + edges: { + node: InterfaceAdContent; + }[]; + }; + }, + currentOrgId: string, + currentDate: Date = new Date(), + ): InterfaceAdContent[] => { + const { advertisementsConnection } = data; + + if (advertisementsConnection && advertisementsConnection.edges) { + const { edges } = advertisementsConnection; + + return edges + .map((edge) => edge.node) + .filter( + (ad: InterfaceAdContent) => + ad.organization._id === currentOrgId && + new Date(ad.endDate) > currentDate, + ); + } + + return []; + }; + + const handlePostButtonClick = (): void => { + setShowModal(true); + }; + + const handleModalClose = (): void => { + setShowModal(false); + }; + + return ( + <> +
    +
    +

    Posts

    + + + + + + + + + + + +
    +
    + +
    +

    {t('media')}

    +
    + + +
    + {/*
    {eventSvg}
    */} +
    + +
    +

    {t('event')}

    +
    + + +
    +
    + +
    +

    {t('article')}

    +
    + +
    +
    +
    +

    {t('feed')}

    +
    + + {t('pinnedPosts')} + + +
    +
    + + {filteredAd.length > 0 && ( +
    + {filteredAd.map((post: InterfaceAdContent) => ( + + ))} +
    + )} + + {loadingPosts ? ( +
    + Loading... +
    + ) : ( + <> + {posts.map(({ node }: { node: InterfacePostNode }) => { + const { + creator, + _id, + imageUrl, + videoUrl, + title, + text, + likeCount, + commentCount, + likedBy, + comments, + } = node; + + const allLikes: any = []; + + likedBy.forEach((value: any) => { + const singleLike = { + firstName: value.firstName, + lastName: value.lastName, + id: value._id, + }; + allLikes.push(singleLike); + }); + + const postComments: any = []; + + comments.forEach((value: any) => { + const commentLikes: any = []; + value.likedBy.forEach((commentLike: any) => { + const singleLike = { + id: commentLike._id, + }; + commentLikes.push(singleLike); + }); + + const comment = { + id: value._id, + creator: { + firstName: value.creator.firstName, + lastName: value.creator.lastName, + id: value.creator._id, + email: value.creator.email, + }, + likeCount: value.likeCount, + likedBy: commentLikes, + text: value.text, + }; + postComments.push(comment); + }); + + const cardProps: InterfacePostCard = { + id: _id, + creator: { + id: creator._id, + firstName: creator.firstName, + lastName: creator.lastName, + email: creator.email, + }, + image: imageUrl, + video: videoUrl, + title, + text, + likeCount, + commentCount, + comments: postComments, + likedBy: allLikes, + }; + + return ; + })} + + )} +
    + +
    + + ); +} diff --git a/src/screens/UserPortal/Settings/Settings.module.css b/src/screens/UserPortal/Settings/Settings.module.css index c8ca1e6091..71b9c8b94b 100644 --- a/src/screens/UserPortal/Settings/Settings.module.css +++ b/src/screens/UserPortal/Settings/Settings.module.css @@ -1,26 +1,180 @@ .mainContainer { - width: 50%; flex-grow: 3; - padding: 40px; + padding: 25px; max-height: 100%; overflow: auto; } .containerHeight { - height: calc(100vh - 66px); + padding: 1rem 1.5rem 0 calc(300px + 1.5rem); + height: 100vh; } -.content { +.expand { + padding-left: 4rem; + animation: moveLeft 0.9s ease-in-out; +} + +.contract { + padding-left: calc(300px + 2rem + 1.5rem); + animation: moveRight 0.5s ease-in-out; +} + +.cardHeader .cardTitle { + font-size: 1.2rem; + font-weight: 600; +} + +.cardHeader { + padding: 1.25rem 1rem 1rem 1rem; + border-bottom: 1px solid var(--bs-gray-200); + display: flex; + justify-content: space-between; + align-items: center; +} + +.cardBody { + padding: 1.25rem 1rem 1.5rem 1rem; display: flex; flex-direction: column; - max-width: 300px; - gap: 15px; } -.imageInput { - background-color: white; +.cardLabel { + font-weight: bold; + padding-bottom: 1px; + font-size: 14px; + color: #707070; + margin-bottom: 10px; +} + +.cardControl { + margin-bottom: 20px; +} + +.cardButton { + width: fit-content; +} + +.imgContianer { + margin: 0 2rem 0 0; +} + +.imgContianer img { + height: 120px; + width: 120px; + border-radius: 50%; +} + +.profileDetails { + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-evenly; +} + +.collapseSidebarButton { + position: fixed; + height: 40px; + bottom: 0; + z-index: 9999; + width: calc(300px + 2rem); + background-color: rgba(245, 245, 245, 0.7); + color: black; + border: none; + border-radius: 0px; +} + +.collapseSidebarButton:hover, +.opendrawer:hover { + opacity: 1; + color: black !important; +} +.opendrawer { + position: fixed; + display: flex; + align-items: center; + justify-content: center; + top: 0; + left: 0; + width: 40px; + height: 100vh; + z-index: 9999; + background-color: rgba(245, 245, 245); + border: none; + border-radius: 0px; + margin-right: 20px; + color: black; +} + +.opendrawer:hover { + transition: background-color 0.5s ease; + background-color: var(--bs-primary); +} +.collapseSidebarButton:hover { + transition: background-color 0.5s ease; + background-color: var(--bs-primary); +} + +@media (max-width: 1120px) { + .collapseSidebarButton { + width: calc(250px + 2rem); + } +} + +@media (max-height: 650px) { + .collapseSidebarButton { + width: 250px; + height: 20px; + } + .opendrawer { + width: 30px; + } +} + +/* For tablets */ +@media (max-width: 820px) { + .containerHeight { + height: 100vh; + padding: 2rem; + } + + .contract, + .expand { + animation: none; + } + + .opendrawer { + width: 25px; + } + + .collapseSidebarButton { + width: 100%; + left: 0; + right: 0; + } +} + +@media screen and (max-width: 1280px) and (min-width: 992px) { + .imgContianer { + margin: 1rem auto; + } + .profileContainer { + flex-direction: column; + } +} + +@media screen and (max-width: 992px) { + .profileContainer { + align-items: center; + justify-content: center; + } } -.colorLight { - background-color: white; +@media screen and (max-width: 420px) { + .imgContianer { + margin: 1rem auto; + } + .profileContainer { + flex-direction: column; + } } diff --git a/src/screens/UserPortal/Settings/Settings.test.tsx b/src/screens/UserPortal/Settings/Settings.test.tsx index faec179acc..0356bde588 100644 --- a/src/screens/UserPortal/Settings/Settings.test.tsx +++ b/src/screens/UserPortal/Settings/Settings.test.tsx @@ -1,8 +1,7 @@ import React from 'react'; -import { act, render, screen } from '@testing-library/react'; +import { act, fireEvent, render, screen } from '@testing-library/react'; import { MockedProvider } from '@apollo/react-testing'; import { I18nextProvider } from 'react-i18next'; - import { UPDATE_USER_MUTATION } from 'GraphQl/Mutations/mutations'; import { BrowserRouter } from 'react-router-dom'; import { Provider } from 'react-redux'; @@ -11,6 +10,7 @@ import i18nForTest from 'utils/i18nForTest'; import { StaticMockLink } from 'utils/StaticMockLink'; import Settings from './Settings'; import userEvent from '@testing-library/user-event'; +import { CHECK_AUTH } from 'GraphQl/Queries/Queries'; const MOCKS = [ { @@ -19,6 +19,15 @@ const MOCKS = [ variables: { firstName: 'Noble', lastName: 'Mittal', + gender: 'MALE', + phoneNumber: '+174567890', + birthDate: '2024-03-01', + grade: 'GRADE_1', + empStatus: 'UNEMPLOYED', + maritalStatus: 'SINGLE', + address: 'random', + state: 'random', + country: 'IN', }, result: { data: { @@ -31,7 +40,78 @@ const MOCKS = [ }, ]; +const Mocks1 = [ + { + request: { + query: CHECK_AUTH, + }, + result: { + data: { + checkAuth: { + email: 'johndoe@gmail.com', + firstName: 'John', + lastName: 'Doe', + gender: 'MALE', + maritalStatus: 'SINGLE', + educationGrade: 'GRADUATE', + employmentStatus: 'PART_TIME', + birthDate: '2024-03-01', + address: { + state: 'random', + countryCode: 'IN', + line1: 'random', + }, + phone: { + mobile: '+174567890', + }, + image: 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', + _id: '65ba1621b7b00c20e5f1d8d2', + }, + }, + }, + }, +]; + +const Mocks2 = [ + { + request: { + query: CHECK_AUTH, + }, + result: { + data: { + checkAuth: { + email: 'johndoe@gmail.com', + firstName: '', + lastName: '', + gender: '', + maritalStatus: '', + educationGrade: '', + employmentStatus: '', + birthDate: '', + address: { + state: '', + countryCode: '', + line1: '', + }, + phone: { + mobile: '', + }, + image: '', + _id: '65ba1621b7b00c20e5f1d8d2', + }, + }, + }, + }, +]; + const link = new StaticMockLink(MOCKS, true); +const link1 = new StaticMockLink(Mocks1, true); +const link2 = new StaticMockLink(Mocks2, true); + +const resizeWindow = (width: number): void => { + window.innerWidth = width; + fireEvent(window, new Event('resize')); +}; async function wait(ms = 100): Promise { await act(() => { @@ -66,7 +146,7 @@ describe('Testing Settings Screen [User Portal]', () => { - + , ); await wait(); @@ -74,7 +154,7 @@ describe('Testing Settings Screen [User Portal]', () => { expect(screen.queryAllByText('Settings')).not.toBe([]); }); - test('First name input works properly', async () => { + test('input works properly', async () => { render( @@ -84,18 +164,54 @@ describe('Testing Settings Screen [User Portal]', () => { - + , ); await wait(); userEvent.type(screen.getByTestId('inputFirstName'), 'Noble'); await wait(); + userEvent.type(screen.getByTestId('inputLastName'), 'Mittal'); + await wait(); + userEvent.selectOptions(screen.getByTestId('inputGender'), 'Male'); + await wait(); + userEvent.type(screen.getByTestId('inputPhoneNumber'), '1234567890'); + await wait(); + userEvent.selectOptions(screen.getByTestId('inputGrade'), 'Grade 1'); + await wait(); + userEvent.selectOptions(screen.getByTestId('inputEmpStatus'), 'Unemployed'); + await wait(); + userEvent.selectOptions(screen.getByTestId('inputMaritalStatus'), 'Single'); + await wait(); + userEvent.type(screen.getByTestId('inputAddress'), 'random'); + await wait(); + userEvent.type(screen.getByTestId('inputState'), 'random'); + await wait(); + userEvent.selectOptions(screen.getByTestId('inputCountry'), 'IN'); + await wait(); + expect(screen.getByTestId('resetChangesBtn')).toBeInTheDocument(); + await wait(); + fireEvent.change(screen.getByLabelText('Birth Date'), { + target: { value: '2024-03-01' }, + }); + expect(screen.getByLabelText('Birth Date')).toHaveValue('2024-03-01'); + await wait(); + const fileInp = screen.getByTestId('fileInput'); + fileInp.style.display = 'block'; + userEvent.click(screen.getByTestId('uploadImageBtn')); + await wait(); + const imageFile = new File(['(⌐□_□)'], 'profile-image.jpg', { + type: 'image/jpeg', + }); + const files = [imageFile]; + userEvent.upload(fileInp, files); + await wait(); + expect(screen.getAllByAltText('profile picture')[0]).toBeInTheDocument(); }); - test('Last name input works properly', async () => { + test('resetChangesBtn works properly', async () => { render( - + @@ -103,13 +219,99 @@ describe('Testing Settings Screen [User Portal]', () => { - + , ); await wait(); - userEvent.type(screen.getByTestId('inputLastName'), 'Mittal'); + userEvent.click(screen.getByTestId('resetChangesBtn')); + await wait(); + expect(screen.getByTestId('inputFirstName')).toHaveValue('John'); + expect(screen.getByTestId('inputLastName')).toHaveValue('Doe'); + expect(screen.getByTestId('inputGender')).toHaveValue('MALE'); + expect(screen.getByTestId('inputPhoneNumber')).toHaveValue('+174567890'); + expect(screen.getByTestId('inputGrade')).toHaveValue('GRADUATE'); + expect(screen.getByTestId('inputEmpStatus')).toHaveValue('PART_TIME'); + expect(screen.getByTestId('inputMaritalStatus')).toHaveValue('SINGLE'); + expect(screen.getByTestId('inputAddress')).toHaveValue('random'); + expect(screen.getByTestId('inputState')).toHaveValue('random'); + expect(screen.getByTestId('inputCountry')).toHaveValue('IN'); + expect(screen.getByLabelText('Birth Date')).toHaveValue('2024-03-01'); + }); + + test('resetChangesBtn works properly when the details are empty', async () => { + render( + + + + + + + + + , + ); + + await wait(); + + userEvent.click(screen.getByTestId('resetChangesBtn')); + await wait(); + expect(screen.getByTestId('inputFirstName')).toHaveValue(''); + expect(screen.getByTestId('inputLastName')).toHaveValue(''); + expect(screen.getByTestId('inputGender')).toHaveValue(''); + expect(screen.getByTestId('inputPhoneNumber')).toHaveValue(''); + expect(screen.getByTestId('inputGrade')).toHaveValue(''); + expect(screen.getByTestId('inputEmpStatus')).toHaveValue(''); + expect(screen.getByTestId('inputMaritalStatus')).toHaveValue(''); + expect(screen.getByTestId('inputAddress')).toHaveValue(''); + expect(screen.getByTestId('inputState')).toHaveValue(''); + expect(screen.getByTestId('inputCountry')).toHaveValue(''); + expect(screen.getByLabelText('Birth Date')).toHaveValue(''); + }); + + test('sidebar', async () => { + render( + + + + + + + + + , + ); + await wait(); + + const closeMenubtn = screen.getByTestId('closeMenu'); + expect(closeMenubtn).toBeInTheDocument(); + closeMenubtn.click(); + const openMenuBtn = screen.getByTestId('openMenu'); + expect(openMenuBtn).toBeInTheDocument(); + openMenuBtn.click(); + }); + + test('Testing sidebar when the screen size is less than or equal to 820px', async () => { + resizeWindow(800); + render( + + + + + + + + + , + ); + await wait(); + expect(screen.getByText('My Organizations')).toBeInTheDocument(); + expect(screen.getByText('Talawa User Portal')).toBeInTheDocument(); + + const settingsBtn = screen.getByTestId('settingsBtn'); + + settingsBtn.click(); }); test('updateUserDetails Mutation is triggered on button click', async () => { @@ -122,7 +324,7 @@ describe('Testing Settings Screen [User Portal]', () => { - + , ); await wait(); @@ -133,6 +335,32 @@ describe('Testing Settings Screen [User Portal]', () => { userEvent.type(screen.getByTestId('inputLastName'), 'Mittal'); await wait(); + userEvent.selectOptions(screen.getByTestId('inputGender'), 'OTHER'); + await wait(); + + userEvent.type(screen.getByTestId('inputPhoneNumber'), '+174567890'); + await wait(); + + fireEvent.change(screen.getByLabelText('Birth Date'), { + target: { value: '2024-03-01' }, + }); + await wait(); + + userEvent.selectOptions(screen.getByTestId('inputGrade'), 'Graduate'); + await wait(); + + userEvent.selectOptions(screen.getByTestId('inputEmpStatus'), 'Unemployed'); + await wait(); + + userEvent.selectOptions(screen.getByTestId('inputMaritalStatus'), 'Single'); + await wait(); + + userEvent.type(screen.getByTestId('inputAddress'), 'random'); + await wait(); + + userEvent.type(screen.getByTestId('inputState'), 'random'); + await wait(); + userEvent.click(screen.getByTestId('updateUserBtn')); await wait(); }); diff --git a/src/screens/UserPortal/Settings/Settings.tsx b/src/screens/UserPortal/Settings/Settings.tsx index 35afd78790..160137d07d 100644 --- a/src/screens/UserPortal/Settings/Settings.tsx +++ b/src/screens/UserPortal/Settings/Settings.tsx @@ -1,142 +1,594 @@ -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import styles from './Settings.module.css'; -import UserSidebar from 'components/UserPortal/UserSidebar/UserSidebar'; -import UserNavbar from 'components/UserPortal/UserNavbar/UserNavbar'; -import { Button, Form } from 'react-bootstrap'; +import { Button, Card, Col, Form, Row } from 'react-bootstrap'; import convertToBase64 from 'utils/convertToBase64'; import { UPDATE_USER_MUTATION } from 'GraphQl/Mutations/mutations'; import { useMutation, useQuery } from '@apollo/client'; import { errorHandler } from 'utils/errorHandler'; import { toast } from 'react-toastify'; import { CHECK_AUTH } from 'GraphQl/Queries/Queries'; +import useLocalStorage from 'utils/useLocalstorage'; +import { + countryOptions, + educationGradeEnum, + employmentStatusEnum, + genderEnum, + maritalStatusEnum, +} from 'utils/formEnumFields'; +import UserProfile from 'components/UserProfileSettings/UserProfile'; +import DeleteUser from 'components/UserProfileSettings/DeleteUser'; +import OtherSettings from 'components/UserProfileSettings/OtherSettings'; +import UserSidebar from 'components/UserPortal/UserSidebar/UserSidebar'; +import ProfileDropdown from 'components/ProfileDropdown/ProfileDropdown'; export default function settings(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'settings', }); - const { data } = useQuery(CHECK_AUTH); - const [image, setImage] = React.useState(''); - const [updateUserDetails] = useMutation(UPDATE_USER_MUTATION); - const [firstName, setFirstName] = React.useState(''); - const [lastName, setLastName] = React.useState(''); - const [email, setEmail] = React.useState(''); + const [hideDrawer, setHideDrawer] = useState(null); - const handleUpdateUserDetails = async (): Promise => { - let variables: any = { - firstName, - lastName, + const handleResize = (): void => { + if (window.innerWidth <= 820) { + setHideDrawer(!hideDrawer); + } + }; + + useEffect(() => { + handleResize(); + window.addEventListener('resize', handleResize); + return () => { + window.removeEventListener('resize', handleResize); }; + }, []); - /* istanbul ignore next */ - if (image) { - variables = { - ...variables, - file: image, - }; - } + const { setItem } = useLocalStorage(); + + const { data } = useQuery(CHECK_AUTH, { fetchPolicy: 'network-only' }); + const [updateUserDetails] = useMutation(UPDATE_USER_MUTATION); + + const [userDetails, setUserDetails] = React.useState({ + firstName: '', + lastName: '', + gender: '', + email: '', + phoneNumber: '', + birthDate: '', + grade: '', + empStatus: '', + maritalStatus: '', + address: '', + state: '', + country: '', + image: '', + }); + + const originalImageState = React.useRef(''); + const fileInputRef = React.useRef(null); + const handleUpdateUserDetails = async (): Promise => { try { + let updatedUserDetails = { ...userDetails }; + if (updatedUserDetails.image === originalImageState.current) { + updatedUserDetails = { ...updatedUserDetails, image: '' }; + } const { data } = await updateUserDetails({ - variables, + variables: updatedUserDetails, }); - /* istanbul ignore next */ if (data) { - setImage(''); toast.success('Your details have been updated.'); setTimeout(() => { window.location.reload(); }, 500); - const userFullName = `${firstName} ${lastName}`; - localStorage.setItem('name', userFullName); + const userFullName = `${userDetails.firstName} ${userDetails.lastName}`; + setItem('name', userFullName); } } catch (error: any) { errorHandler(t, error); } }; - const handleFirstNameChange = (e: any): void => { - const { value } = e.target; - setFirstName(value); + const handleFieldChange = (fieldName: string, value: string): void => { + setUserDetails((prevState) => ({ + ...prevState, + [fieldName]: value, + })); }; - const handleLastNameChange = (e: any): void => { - const { value } = e.target; - setLastName(value); + const handleImageUpload = (): void => { + if (fileInputRef.current) { + (fileInputRef.current as HTMLInputElement).click(); + } + }; + + const handleResetChanges = (): void => { + /* istanbul ignore next */ + if (data) { + const { + firstName, + lastName, + gender, + phone, + birthDate, + educationGrade, + employmentStatus, + maritalStatus, + address, + } = data.checkAuth; + + setUserDetails({ + ...userDetails, + firstName: firstName || '', + lastName: lastName || '', + gender: gender || '', + phoneNumber: phone?.mobile || '', + birthDate: birthDate || '', + grade: educationGrade || '', + empStatus: employmentStatus || '', + maritalStatus: maritalStatus || '', + address: address?.line1 || '', + state: address?.state || '', + country: address?.countryCode || '', + }); + } }; React.useEffect(() => { /* istanbul ignore next */ if (data) { - setFirstName(data.checkAuth.firstName); - setLastName(data.checkAuth.lastName); - setEmail(data.checkAuth.email); + const { + firstName, + lastName, + gender, + email, + phone, + birthDate, + educationGrade, + employmentStatus, + maritalStatus, + address, + image, + } = data.checkAuth; + + setUserDetails({ + firstName, + lastName, + gender, + email, + phoneNumber: phone?.mobile || '', + birthDate, + grade: educationGrade || '', + empStatus: employmentStatus || '', + maritalStatus: maritalStatus || '', + address: address?.line1 || '', + state: address?.state || '', + country: address?.countryCode || '', + image, + }); + originalImageState.current = image; } }, [data]); return ( <> - -
    - + {hideDrawer ? ( + + ) : ( + + )} + +
    -

    {t('profileSettings')}

    -
    - {t('firstName')} - - {t('lastName')} - - {t('emailAddress')} - - {t('updateImage')} - => { - const target = e.target as HTMLInputElement; - const file = target.files && target.files[0]; - if (file) { - const image = await convertToBase64(file); - setImage(image); - } - } - } - /> - +
    +
    +

    {t('settings')}

    + + + + + + +
    +
    + {t('profileSettings')} +
    +
    + + + + + {t('firstName')} + + + handleFieldChange('firstName', e.target.value) + } + className={`${styles.cardControl}`} + data-testid="inputFirstName" + /> + + + + {t('lastName')} + + + handleFieldChange('lastName', e.target.value) + } + className={`${styles.cardControl}`} + data-testid="inputLastName" + /> + + + + {t('gender')} + + + handleFieldChange('gender', e.target.value) + } + className={`${styles.cardControl}`} + data-testid="inputGender" + > + + {genderEnum.map((g) => ( + + ))} + + + + + + + {t('emailAddress')} + + + + + + {t('phoneNumber')} + + + handleFieldChange('phoneNumber', e.target.value) + } + className={`${styles.cardControl}`} + data-testid="inputPhoneNumber" + /> + + + + {t('displayImage')} + +
    + + , + ): Promise => { + const target = e.target as HTMLInputElement; + const file = target.files && target.files[0]; + if (file) { + const image = await convertToBase64(file); + setUserDetails({ ...userDetails, image }); + } + } + } + style={{ display: 'none' }} + /> +
    + +
    + + + + {t('birthDate')} + + + handleFieldChange('birthDate', e.target.value) + } + className={`${styles.cardControl}`} + /> + + + + {t('grade')} + + + handleFieldChange('grade', e.target.value) + } + className={`${styles.cardControl}`} + data-testid="inputGrade" + > + + {educationGradeEnum.map((grade) => ( + + ))} + + + + + + + {t('empStatus')} + + + handleFieldChange('empStatus', e.target.value) + } + className={`${styles.cardControl}`} + data-testid="inputEmpStatus" + > + + {employmentStatusEnum.map((status) => ( + + ))} + + + + + {t('maritalStatus')} + + + handleFieldChange('maritalStatus', e.target.value) + } + className={`${styles.cardControl}`} + data-testid="inputMaritalStatus" + > + + {maritalStatusEnum.map((status) => ( + + ))} + + + + + + + {t('address')} + + + handleFieldChange('address', e.target.value) + } + className={`${styles.cardControl}`} + data-testid="inputAddress" + /> + + + + {t('state')} + + + handleFieldChange('state', e.target.value) + } + className={`${styles.cardControl}`} + data-testid="inputState" + /> + + + + {t('country')} + + + handleFieldChange('country', e.target.value) + } + className={`${styles.cardControl}`} + data-testid="inputCountry" + > + + {countryOptions.map((country) => ( + + ))} + + + +
    + + +
    +
    +
    + + + + + + + + + + +
    diff --git a/src/screens/UserPortal/Tasks/Tasks.module.css b/src/screens/UserPortal/Tasks/Tasks.module.css deleted file mode 100644 index 1f49c0d158..0000000000 --- a/src/screens/UserPortal/Tasks/Tasks.module.css +++ /dev/null @@ -1,48 +0,0 @@ -.borderNone { - border: none; -} - -.colorWhite { - color: white; -} - -.maxWidth { - max-width: 300px; -} - -.colorLight { - background-color: #f5f5f5; -} - -.mainContainer { - width: 50%; - flex-grow: 3; - padding: 40px; - max-height: 100%; - overflow: auto; -} - -.content { - height: fit-content; - min-height: calc(100% - 40px); -} - -.gap { - gap: 20px; -} - -.paddingY { - padding: 30px 0px; -} - -.containerHeight { - height: calc(100vh - 66px); -} - -.colorPrimary { - background: #31bb6b; -} - -.backgroundWhite { - background-color: white; -} diff --git a/src/screens/UserPortal/Tasks/Tasks.test.tsx b/src/screens/UserPortal/Tasks/Tasks.test.tsx deleted file mode 100644 index 208a1ca4e8..0000000000 --- a/src/screens/UserPortal/Tasks/Tasks.test.tsx +++ /dev/null @@ -1,130 +0,0 @@ -import React from 'react'; -import { act, render, screen } from '@testing-library/react'; -import { MockedProvider } from '@apollo/react-testing'; -import { I18nextProvider } from 'react-i18next'; - -import { UPDATE_USER_MUTATION } from 'GraphQl/Mutations/mutations'; -import { USER_TASKS_LIST } from 'GraphQl/Queries/Queries'; -import { BrowserRouter } from 'react-router-dom'; -import { Provider } from 'react-redux'; -import { store } from 'state/store'; -import i18nForTest from 'utils/i18nForTest'; -import { StaticMockLink } from 'utils/StaticMockLink'; -import Tasks from './Tasks'; - -const MOCKS = [ - { - request: { - query: UPDATE_USER_MUTATION, - variables: { - firstName: 'Noble', - lastName: 'Mittal', - }, - result: { - data: { - updateUserProfile: { - _id: '453', - }, - }, - }, - }, - }, - { - request: { - query: USER_TASKS_LIST, - variables: { - id: localStorage.getItem('userId'), - }, - }, - result: { - data: { - user: { - _id: '63d6064458fce20ee25c3bf7', - assignedTasks: [ - { - _id: '650c440f2b5f121b9ceeaa88', - title: 'Volunteer catering system', - description: 'Lorem ipsum dolor sit amet', - deadline: '2023-09-28T16:25:47.000Z', - volunteers: [ - { - _id: '63d6064458fce20ee25c3bf7', - firstName: 'Noble', - lastName: 'Mittal', - email: 'test@gmail.com', - __typename: 'User', - }, - ], - createdAt: '2023-09-21T13:24:31.217Z', - completed: false, - event: { - _id: '650982592328d374ba2881bc', - title: 'sadas', - organization: { - _id: '6493e4570ee6c913d7199291', - name: 'Test Organization', - image: null, - __typename: 'Organization', - }, - __typename: 'Event', - }, - creator: { - _id: '63d6064458fce20ee25c3bf7', - firstName: 'Noble', - lastName: 'Mittal', - __typename: 'User', - }, - __typename: 'Task', - }, - ], - __typename: 'User', - }, - }, - }, - }, -]; - -const link = new StaticMockLink(MOCKS, true); - -async function wait(ms = 100): Promise { - await act(() => { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); - }); -} - -describe('Testing Tasks Screen [User Portal]', () => { - // Mocks required for media queries for UserNavbar - Object.defineProperty(window, 'matchMedia', { - writable: true, - value: jest.fn().mockImplementation((query) => ({ - matches: false, - media: query, - onchange: null, - addListener: jest.fn(), // Deprecated - removeListener: jest.fn(), // Deprecated - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - dispatchEvent: jest.fn(), - })), - }); - - test('Screen should be rendered properly', async () => { - render( - - - - - - - - - - ); - - await wait(); - - expect(screen.queryAllByText('Your assigned tasks')).not.toBe([]); - }); -}); diff --git a/src/screens/UserPortal/Tasks/Tasks.tsx b/src/screens/UserPortal/Tasks/Tasks.tsx deleted file mode 100644 index af02593b38..0000000000 --- a/src/screens/UserPortal/Tasks/Tasks.tsx +++ /dev/null @@ -1,173 +0,0 @@ -import React from 'react'; -import UserNavbar from 'components/UserPortal/UserNavbar/UserNavbar'; -import TaskCard from 'components/UserPortal/TaskCard/TaskCard'; -import UserSidebar from 'components/UserPortal/UserSidebar/UserSidebar'; -import PaginationList from 'components/PaginationList/PaginationList'; -import { USER_TASKS_LIST } from 'GraphQl/Queries/Queries'; -import { useQuery } from '@apollo/client'; -import styles from './Tasks.module.css'; -import { useTranslation } from 'react-i18next'; -import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; - -interface InterfaceTaskCardProps { - id: string; - title: string; - deadline: string; - description: string; - volunteers: { - id: string; - firstName: string; - lastName: string; - email: string; - }[]; - creator: { - id: string; - firstName: string; - lastName: string; - }; - event: { - id: string; - title: string; - organization: { - id: string; - name: string; - image: string | null; - }; - }; - createdAt: string; - completed: boolean; -} - -export default function tasks(): JSX.Element { - const { t } = useTranslation('translation', { - keyPrefix: 'userTasks', - }); - - const [page, setPage] = React.useState(0); - const [rowsPerPage, setRowsPerPage] = React.useState(5); - const [tasks, setTasks] = React.useState([]); - - const userId: string | null = localStorage.getItem('userId'); - - const { data: tasksData, loading: loadingTasks } = useQuery(USER_TASKS_LIST, { - variables: { id: userId }, - }); - - /* istanbul ignore next */ - const handleChangePage = ( - _event: React.MouseEvent | null, - newPage: number - ): void => { - setPage(newPage); - }; - - /* istanbul ignore next */ - const handleChangeRowsPerPage = ( - event: React.ChangeEvent - ): void => { - const newRowsPerPage = event.target.value; - - setRowsPerPage(parseInt(newRowsPerPage, 10)); - setPage(0); - }; - - /* istanbul ignore next */ - React.useEffect(() => { - if (tasksData) { - setTasks(tasksData.user.assignedTasks); - } - }, [tasksData]); - - return ( - <> - -
    - -
    -

    {t('yourAssignedTasks')}

    -
    -
    - {loadingTasks ? ( -
    - Loading... -
    - ) : ( - <> - {tasks && tasks.length > 0 ? ( - (rowsPerPage > 0 - ? tasks.slice( - page * rowsPerPage, - page * rowsPerPage + rowsPerPage - ) - : /* istanbul ignore next */ - tasks - ).map((task: any, index) => { - const volunteers: any = task.volunteers.map( - (volunteer: any) => { - return { - id: volunteer._id, - firstName: volunteer.firstName, - lastName: volunteer.lastName, - email: volunteer.email, - }; - } - ); - - const cardProps: InterfaceTaskCardProps = { - title: task.title, - id: task._id, - description: task.description, - deadline: task.deadline, - volunteers, - createdAt: task.createdAt, - completed: task.completed, - creator: { - id: task.creator._id, - firstName: task.creator.firstName, - lastName: task.creator.lastName, - }, - event: { - id: task.event._id, - title: task.event.title, - organization: { - id: task.event.organization._id, - name: task.event.organization.name, - image: task.event.organization.image, - }, - }, - }; - - return ; - }) - ) : ( - {t('nothingToShow')} - )} - - )} -
    - - - - - - -
    -
    -
    -
    - - ); -} diff --git a/src/screens/UserPortal/UserLoginPage/UserLoginPage.module.css b/src/screens/UserPortal/UserLoginPage/UserLoginPage.module.css deleted file mode 100644 index 840ceb8a0b..0000000000 --- a/src/screens/UserPortal/UserLoginPage/UserLoginPage.module.css +++ /dev/null @@ -1,48 +0,0 @@ -body::before { - content: none !important; -} - -.leftPane { - align-items: center; - width: 60%; - min-width: 300px; - display: flex; - flex-direction: column; - justify-content: center; -} - -.palisadoesImage { - width: 100%; - height: auto; - max-width: 700px; -} - -.talawaImage { - width: 40%; - height: auto; - margin-left: 50%; - transform: translateX(-50%); -} - -.mainContainer { - display: flex; - flex-direction: row; - flex-wrap: wrap; - gap: 10px; - min-height: 100vh; -} - -.contentContainer { - flex-grow: 1; - display: flex; - flex-direction: column; - justify-content: center; - padding: 20px 50px; - background-color: var(--bs-white); -} - -@media only screen and (max-width: 800px) { - .leftPane { - width: 100%; - } -} diff --git a/src/screens/UserPortal/UserLoginPage/UserLoginPage.tsx b/src/screens/UserPortal/UserLoginPage/UserLoginPage.tsx deleted file mode 100644 index ca4915d691..0000000000 --- a/src/screens/UserPortal/UserLoginPage/UserLoginPage.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import React from 'react'; -import { useTranslation } from 'react-i18next'; - -import PalisadoesImage from 'assets/images/palisadoes_logo.png'; -import TalawaImage from 'assets/images/talawa-logo-200x200.png'; -import ChangeLanguageDropDown from 'components/ChangeLanguageDropdown/ChangeLanguageDropDown'; -import Login from 'components/UserPortal/Login/Login'; -import Register from 'components/UserPortal/Register/Register'; -import styles from './UserLoginPage.module.css'; - -export default function userLoginPage(): JSX.Element { - const { t } = useTranslation('translation', { keyPrefix: 'loginPage' }); - - const [currentMode, setCurrentMode] = React.useState('login'); - const loginRegisterProps = { - setCurrentMode: setCurrentMode, - }; - - return ( -
    -
    - Palisadoes Branding -
    -

    {t('fromPalisadoes')}

    -
    -
    -
    - - Talawa Branding - { - /* istanbul ignore next */ - currentMode === 'login' ? ( - - ) : ( - - ) - } -
    -
    - ); -} diff --git a/src/screens/UserPortal/UserScreen/UserScreen.module.css b/src/screens/UserPortal/UserScreen/UserScreen.module.css new file mode 100644 index 0000000000..f8ad1c5bfd --- /dev/null +++ b/src/screens/UserPortal/UserScreen/UserScreen.module.css @@ -0,0 +1,173 @@ +.pageContainer { + display: flex; + flex-direction: column; + min-height: 100vh; + padding: 1rem 1.5rem 0 calc(300px + 2rem + 1.5rem); +} + +.expand { + padding-left: 4rem; + animation: moveLeft 0.9s ease-in-out; +} +.avatarStyle { + border-radius: 100%; +} +.profileContainer { + border: none; + padding: 2.1rem 0.5rem; + height: 52px; + border-radius: 8px 0px 0px 8px; + display: flex; + align-items: center; + background-color: white !important; + box-shadow: + 0 4px 4px 0 rgba(177, 177, 177, 0.2), + 0 6px 20px 0 rgba(151, 151, 151, 0.19); +} +.profileContainer:focus { + outline: none; + background-color: var(--bs-gray-100); +} +.imageContainer { + width: 56px; +} +.profileContainer .profileText { + flex: 1; + text-align: start; + overflow: hidden; + margin-right: 4px; +} +.angleDown { + margin-left: 4px; +} +.profileContainer .profileText .primaryText { + font-size: 1rem; + font-weight: 600; + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 2; /* number of lines to show */ + -webkit-box-orient: vertical; + word-wrap: break-word; + white-space: normal; +} +.profileContainer .profileText .secondaryText { + font-size: 0.8rem; + font-weight: 400; + color: var(--bs-secondary); + display: block; + text-transform: capitalize; +} + +.contract { + padding-left: calc(300px + 2rem + 1.5rem); + animation: moveRight 0.5s ease-in-out; +} + +.collapseSidebarButton { + position: fixed; + height: 40px; + bottom: 0; + z-index: 9999; + width: calc(300px + 2rem); + background-color: rgba(245, 245, 245, 0.7); + color: black; + border: none; + border-radius: 0px; +} + +.collapseSidebarButton:hover, +.opendrawer:hover { + opacity: 1; + color: black !important; +} +.opendrawer { + position: fixed; + display: flex; + align-items: center; + justify-content: center; + top: 0; + left: 0; + width: 40px; + height: 100vh; + z-index: 9999; + background-color: rgba(245, 245, 245); + border: none; + border-radius: 0px; + margin-right: 20px; + color: black; +} +.profileDropdown { + background-color: transparent !important; +} +.profileDropdown .dropdown-toggle .btn .btn-normal { + display: none !important; + background-color: transparent !important; +} +.dropdownToggle { + background-image: url(/public/images/svg/angleDown.svg); + background-repeat: no-repeat; + background-position: center; + background-color: azure; +} + +.dropdownToggle::after { + border-top: none !important; + border-bottom: none !important; +} + +.opendrawer:hover { + transition: background-color 0.5s ease; + background-color: var(--bs-primary); +} +.collapseSidebarButton:hover { + transition: background-color 0.5s ease; + background-color: var(--bs-primary); +} + +@media (max-width: 1120px) { + .contract { + padding-left: calc(276px + 2rem + 1.5rem); + } + .collapseSidebarButton { + width: calc(250px + 2rem); + } +} + +@media (max-height: 900px) { + .collapseSidebarButton { + width: calc(300px + 1rem); + } +} +@media (max-height: 650px) { + .pageContainer { + padding: 1rem 1.5rem 0 calc(270px); + } + .collapseSidebarButton { + width: 250px; + } + .opendrawer { + width: 30px; + } +} + +/* For tablets */ +@media (max-width: 820px) { + .pageContainer { + padding-left: 2.5rem; + } + + .opendrawer { + width: 25px; + } + + .contract, + .expand { + animation: none; + } + + .collapseSidebarButton { + width: 100%; + left: 0; + right: 0; + } +} diff --git a/src/screens/UserPortal/UserScreen/UserScreen.test.tsx b/src/screens/UserPortal/UserScreen/UserScreen.test.tsx new file mode 100644 index 0000000000..3600e7a991 --- /dev/null +++ b/src/screens/UserPortal/UserScreen/UserScreen.test.tsx @@ -0,0 +1,117 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { fireEvent, render, screen } from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import 'jest-location-mock'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import UserScreen from './UserScreen'; +import { ORGANIZATIONS_LIST } from 'GraphQl/Queries/Queries'; +import { StaticMockLink } from 'utils/StaticMockLink'; + +let mockID: string | undefined = '123'; +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: mockID }), +})); + +const MOCKS = [ + { + request: { + query: ORGANIZATIONS_LIST, + variables: { id: '123' }, + }, + result: { + data: { + organizations: [ + { + _id: '123', + image: null, + creator: { + firstName: 'John', + lastName: 'Doe', + email: 'JohnDoe@example.com', + }, + name: 'Test Organization', + description: 'Testing this organization', + address: { + city: 'Mountain View', + countryCode: 'US', + dependentLocality: 'Some Dependent Locality', + line1: '123 Main Street', + line2: 'Apt 456', + postalCode: '94040', + sortingCode: 'XYZ-789', + state: 'CA', + }, + userRegistrationRequired: true, + visibleInSearch: true, + members: [], + admins: [], + membershipRequests: [], + blockedUsers: [], + }, + ], + }, + }, + }, +]; +const link = new StaticMockLink(MOCKS, true); + +const resizeWindow = (width: number): void => { + window.innerWidth = width; + fireEvent(window, new Event('resize')); +}; + +const clickToggleMenuBtn = (toggleButton: HTMLElement): void => { + fireEvent.click(toggleButton); +}; + +describe('Testing LeftDrawer in OrganizationScreen', () => { + test('Testing LeftDrawer in page functionality', async () => { + render( + + + + + + + + + , + ); + const toggleButton = screen.getByTestId('closeMenu') as HTMLElement; + const icon = toggleButton.querySelector('i'); + + // Resize window to a smaller width + resizeWindow(800); + clickToggleMenuBtn(toggleButton); + expect(icon).toHaveClass('fa fa-angle-double-left'); + // Resize window back to a larger width + + resizeWindow(1000); + clickToggleMenuBtn(toggleButton); + expect(icon).toHaveClass('fa fa-angle-double-right'); + + clickToggleMenuBtn(toggleButton); + expect(icon).toHaveClass('fa fa-angle-double-left'); + }); + + test('should be redirected to / if orgId is undefined', async () => { + mockID = undefined; + render( + + + + + + + + + , + ); + expect(window.location.pathname).toEqual('/'); + }); +}); diff --git a/src/screens/UserPortal/UserScreen/UserScreen.tsx b/src/screens/UserPortal/UserScreen/UserScreen.tsx new file mode 100644 index 0000000000..a1605fa59d --- /dev/null +++ b/src/screens/UserPortal/UserScreen/UserScreen.tsx @@ -0,0 +1,97 @@ +import React, { useEffect, useState } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { Navigate, Outlet, useLocation, useParams } from 'react-router-dom'; +import { updateTargets } from 'state/action-creators'; +import type { RootState } from 'state/reducers'; +import type { TargetsType } from 'state/reducers/routesReducer'; +import styles from './UserScreen.module.css'; +import { Button } from 'react-bootstrap'; +import UserSidebarOrg from 'components/UserPortal/UserSidebarOrg/UserSidebarOrg'; +import ProfileDropdown from 'components/ProfileDropdown/ProfileDropdown'; + +const UserScreen = (): JSX.Element => { + const location = useLocation(); + const [hideDrawer, setHideDrawer] = useState(null); + const { orgId } = useParams(); + + if (!orgId) { + return ; + } + + const appRoutes: { + targets: TargetsType[]; + } = useSelector((state: RootState) => state.userRoutes); + const { targets } = appRoutes; + + console.log(location.pathname.split('/')); + + const dispatch = useDispatch(); + useEffect(() => { + dispatch(updateTargets(orgId)); + }, [orgId]); // Added orgId to the dependency array + + const handleResize = (): void => { + if (window.innerWidth <= 820) { + setHideDrawer(!hideDrawer); + } + }; + + useEffect(() => { + handleResize(); + window.addEventListener('resize', handleResize); + return () => { + window.removeEventListener('resize', handleResize); + }; + }, []); + + return ( + <> + {hideDrawer ? ( + + ) : ( + + )} +
    + +
    +
    +
    + +
    + +
    + + ); +}; + +export default UserScreen; diff --git a/src/screens/Users/Users.test.tsx b/src/screens/Users/Users.test.tsx index 4484518529..59e16a7878 100644 --- a/src/screens/Users/Users.test.tsx +++ b/src/screens/Users/Users.test.tsx @@ -12,10 +12,14 @@ import { store } from 'state/store'; import { StaticMockLink } from 'utils/StaticMockLink'; import i18nForTest from 'utils/i18nForTest'; import Users from './Users'; -import { EMPTY_MOCKS, MOCKS } from './UsersMocks'; +import { EMPTY_MOCKS, MOCKS, MOCKS2 } from './UsersMocks'; +import useLocalStorage from 'utils/useLocalstorage'; + +const { setItem, removeItem } = useLocalStorage(); const link = new StaticMockLink(MOCKS, true); const link2 = new StaticMockLink(EMPTY_MOCKS, true); +const link3 = new StaticMockLink(MOCKS2, true); async function wait(ms = 100): Promise { await act(() => { @@ -25,10 +29,11 @@ async function wait(ms = 100): Promise { }); } beforeEach(() => { - localStorage.setItem('id', '123'); - localStorage.setItem('UserType', 'SUPERADMIN'); - localStorage.setItem('FirstName', 'John'); - localStorage.setItem('LastName', 'Doe'); + setItem('id', '123'); + setItem('SuperAdmin', true); + setItem('FirstName', 'John'); + setItem('AdminFor', [{ name: 'adi', _id: '1234', image: '' }]); + setItem('LastName', 'Doe'); }); afterEach(() => { @@ -46,17 +51,19 @@ describe('Testing Users screen', () => { - + , ); await wait(); - expect(screen.getAllByText(/Users/i)).toBeTruthy(); + expect(screen.getByTestId('testcomp')).toBeInTheDocument(); }); test(`Component should be rendered properly when user is not superAdmin and or userId does not exists in localstorage`, async () => { - localStorage.setItem('UserType', 'ADMIN'); - localStorage.setItem('id', ''); + setItem('AdminFor', ['123']); + removeItem('SuperAdmin'); + await wait(); + setItem('id', ''); render( @@ -66,9 +73,27 @@ describe('Testing Users screen', () => { - + , ); + await wait(); + }); + test(`Component should be rendered properly when userId does not exists in localstorage`, async () => { + removeItem('AdminFor'); + removeItem('SuperAdmin'); + await wait(); + removeItem('id'); + render( + + + + + + + + + , + ); await wait(); }); @@ -82,7 +107,7 @@ describe('Testing Users screen', () => { - + , ); await wait(); @@ -98,13 +123,15 @@ describe('Testing Users screen', () => { - + , ); await wait(); - - const search1 = 'John{backspace}{backspace}{backspace}{backspace}'; + const searchBtn = screen.getByTestId('searchButton'); + const search1 = 'John'; userEvent.type(screen.getByTestId(/searchByName/i), search1); + userEvent.click(searchBtn); + await wait(); const search2 = 'Pete{backspace}{backspace}{backspace}{backspace}'; userEvent.type(screen.getByTestId(/searchByName/i), search2); @@ -118,7 +145,31 @@ describe('Testing Users screen', () => { const search5 = 'Xe'; userEvent.type(screen.getByTestId(/searchByName/i), search5); + userEvent.clear(screen.getByTestId(/searchByName/i)); userEvent.type(screen.getByTestId(/searchByName/i), ''); + userEvent.click(searchBtn); + await wait(); + }); + + test('testing search not found', async () => { + render( + + + + + + + + + , + ); + + await wait(); + + const search = 'hello{enter}'; + await act(() => + userEvent.type(screen.getByTestId(/searchByName/i), search), + ); }); test('Testing User data is not present', async () => { @@ -131,7 +182,7 @@ describe('Testing Users screen', () => { - + , ); await wait(); @@ -149,12 +200,12 @@ describe('Testing Users screen', () => { - + , ); await wait(200); expect(container.textContent).toMatch( - 'Organizations not found, please create an organization through dashboard' + 'Organizations not found, please create an organization through dashboard', ); }); @@ -169,17 +220,17 @@ describe('Testing Users screen', () => { - + , ); await wait(); expect(container.textContent).not.toMatch( - 'Organizations not found, please create an organization through dashboard' + 'Organizations not found, please create an organization through dashboard', ); }); - test('Testing sort Newest and oldest toggle', async () => { + test('Testing sorting functionality', async () => { await act(async () => { render( @@ -191,7 +242,7 @@ describe('Testing Users screen', () => { - + , ); await wait(); @@ -202,15 +253,96 @@ describe('Testing Users screen', () => { const inputText = screen.getByTestId('sortUsers'); fireEvent.click(inputText); - const toggleText = screen.getByTestId('newest'); + const toggleText = screen.getByTestId('oldest'); + fireEvent.click(toggleText); + + expect(searchInput).toBeInTheDocument(); + + fireEvent.click(inputText); + const toggleTite = screen.getByTestId('newest'); + fireEvent.click(toggleTite); + + expect(searchInput).toBeInTheDocument(); + }); + }); + + test('Testing filter functionality', async () => { + await act(async () => { + render( + + + + + + + + + + , + ); + await wait(); + + const searchInput = screen.getByTestId('filter'); + expect(searchInput).toBeInTheDocument(); + + const inputText = screen.getByTestId('filterUsers'); + + fireEvent.click(inputText); + const toggleText = screen.getByTestId('admin'); fireEvent.click(toggleText); expect(searchInput).toBeInTheDocument(); + + fireEvent.click(inputText); + let toggleTite = screen.getByTestId('superAdmin'); + fireEvent.click(toggleTite); + + expect(searchInput).toBeInTheDocument(); + fireEvent.click(inputText); - const toggleTite = screen.getByTestId('oldest'); + toggleTite = screen.getByTestId('user'); fireEvent.click(toggleTite); + + expect(searchInput).toBeInTheDocument(); + + fireEvent.click(inputText); + toggleTite = screen.getByTestId('cancel'); + fireEvent.click(toggleTite); + + await wait(); + expect(searchInput).toBeInTheDocument(); }); }); + + test('check for rerendering', async () => { + const { rerender } = render( + + + + + + + + + + , + ); + + await wait(); + rerender( + + + + + + + + + + , + ); + await wait(); + }); }); diff --git a/src/screens/Users/Users.tsx b/src/screens/Users/Users.tsx index 64a9be1735..1158658532 100644 --- a/src/screens/Users/Users.tsx +++ b/src/screens/Users/Users.tsx @@ -13,41 +13,38 @@ import { ORGANIZATION_CONNECTION_LIST, USER_LIST, } from 'GraphQl/Queries/Queries'; -import SuperAdminScreen from 'components/SuperAdminScreen/SuperAdminScreen'; import TableLoader from 'components/TableLoader/TableLoader'; import UsersTableItem from 'components/UsersTableItem/UsersTableItem'; import InfiniteScroll from 'react-infinite-scroll-component'; -import debounce from 'utils/debounce'; import type { InterfaceQueryUserListItem } from 'utils/interfaces'; import styles from './Users.module.css'; +import useLocalStorage from 'utils/useLocalstorage'; const Users = (): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'users' }); document.title = t('title'); + const { getItem } = useLocalStorage(); + const perPageResult = 12; const [isLoading, setIsLoading] = useState(true); const [hasMore, setHasMore] = useState(true); const [isLoadingMore, setIsLoadingMore] = useState(false); const [searchByName, setSearchByName] = useState(''); const [sortingOption, setSortingOption] = useState('newest'); + const [filteringOption, setFilteringOption] = useState('cancel'); + const superAdmin = getItem('SuperAdmin'); + const adminFor = getItem('AdminFor'); + const userRole = superAdmin + ? 'SUPERADMIN' + : adminFor?.length > 0 + ? 'ADMIN' + : 'USER'; - const userType = localStorage.getItem('UserType'); - const loggedInUserId = localStorage.getItem('id'); + const loggedInUserId = getItem('id'); - const { - data: usersData, - loading: loading, - fetchMore, - refetch: refetchUsers, - }: { - data?: { users: InterfaceQueryUserListItem[] }; - loading: boolean; - fetchMore: any; - refetch: any; - error?: ApolloError; - } = useQuery(USER_LIST, { + const { data, loading, fetchMore, refetch } = useQuery(USER_LIST, { variables: { first: perPageResult, skip: 0, @@ -58,21 +55,22 @@ const Users = (): JSX.Element => { }); const { data: dataOrgs } = useQuery(ORGANIZATION_CONNECTION_LIST); - const [displayedUsers, setDisplayedUsers] = useState(usersData?.users || []); + const [displayedUsers, setDisplayedUsers] = useState(data?.users || []); // Manage loading more state useEffect(() => { - if (!usersData) { + if (!data) { return; } - if (usersData.users.length < perPageResult) { + if (data.users.length < perPageResult) { setHasMore(false); } - if (usersData && usersData.users) { - const newDisplayedUsers = sortUsers(usersData.users, sortingOption); + if (data && data.users) { + let newDisplayedUsers = sortUsers(data.users, sortingOption); + newDisplayedUsers = filterUsers(newDisplayedUsers, filteringOption); setDisplayedUsers(newDisplayedUsers); } - }, [usersData, sortingOption]); + }, [data, sortingOption, filteringOption]); // To clear the search when the component is unmounted useEffect(() => { @@ -94,7 +92,7 @@ const Users = (): JSX.Element => { // Send to orgList page if user is not superadmin useEffect(() => { - if (userType != 'SUPERADMIN') { + if (userRole != 'SUPERADMIN') { window.location.assign('/orglist'); } }, []); @@ -108,23 +106,38 @@ const Users = (): JSX.Element => { } }, [loading]); - const handleSearchByName = (e: any): void => { - const { value } = e.target; + const handleSearch = (value: string): void => { setSearchByName(value); - /* istanbul ignore next */ - if (value.length === 0) { + if (value === '') { resetAndRefetch(); return; } - refetchUsers({ + refetch({ firstName_contains: value, lastName_contains: '', // Later on we can add several search and filter options }); }; + + const handleSearchByEnter = ( + e: React.KeyboardEvent, + ): void => { + if (e.key === 'Enter') { + const { value } = e.currentTarget; + handleSearch(value); + } + }; + + const handleSearchByBtnClick = (): void => { + const inputElement = document.getElementById( + 'searchUsers', + ) as HTMLInputElement; + const inputValue = inputElement?.value || ''; + handleSearch(inputValue); + }; /* istanbul ignore next */ const resetAndRefetch = (): void => { - refetchUsers({ + refetch({ first: perPageResult, skip: 0, firstName_contains: '', @@ -137,8 +150,7 @@ const Users = (): JSX.Element => { setIsLoadingMore(true); fetchMore({ variables: { - skip: usersData?.users.length || 0, - userType: 'ADMIN', + skip: data?.users.length || 0, filter: searchByName, }, updateQuery: ( @@ -147,7 +159,7 @@ const Users = (): JSX.Element => { fetchMoreResult, }: { fetchMoreResult: { users: InterfaceQueryUserListItem[] } | undefined; - } + }, ): { users: InterfaceQueryUserListItem[] } | undefined => { setIsLoadingMore(false); if (!fetchMoreResult) return prev; @@ -160,8 +172,6 @@ const Users = (): JSX.Element => { }, }); }; - const debouncedHandleSearchByName = debounce(handleSearchByName); - // console.log(usersData); const handleSorting = (option: string): void => { setSortingOption(option); @@ -169,164 +179,226 @@ const Users = (): JSX.Element => { const sortUsers = ( allUsers: InterfaceQueryUserListItem[], - sortingOption: string + sortingOption: string, ): InterfaceQueryUserListItem[] => { const sortedUsers = [...allUsers]; if (sortingOption === 'newest') { sortedUsers.sort( (a, b) => - new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime() + new Date(b.user.createdAt).getTime() - + new Date(a.user.createdAt).getTime(), ); - } else if (sortingOption === 'oldest') { + return sortedUsers; + } else { sortedUsers.sort( (a, b) => - new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime() + new Date(a.user.createdAt).getTime() - + new Date(b.user.createdAt).getTime(), ); + return sortedUsers; } + }; - return sortedUsers; + const handleFiltering = (option: string): void => { + setFilteringOption(option); + }; + + const filterUsers = ( + allUsers: InterfaceQueryUserListItem[], + filteringOption: string, + ): InterfaceQueryUserListItem[] => { + const filteredUsers = [...allUsers]; + + if (filteringOption === 'cancel') { + return filteredUsers; + } else if (filteringOption === 'user') { + const output = filteredUsers.filter((user) => { + return user.appUserProfile.adminFor.length === 0; + }); + return output; + } else if (filteringOption === 'admin') { + const output = filteredUsers.filter((user) => { + return ( + user.appUserProfile.isSuperAdmin === false && + user.appUserProfile.adminFor.length !== 0 + ); + }); + return output; + } else { + const output = filteredUsers.filter((user) => { + return user.appUserProfile.isSuperAdmin === true; + }); + return output; + } }; const headerTitles: string[] = [ '#', t('name'), t('email'), - t('roles_userType'), t('joined_organizations'), t('blocked_organizations'), ]; return ( <> - - {/* Buttons Container */} -
    -
    -
    +
    +
    + + -
    + +
    -
    -
    -
    - {isLoading == false && - usersData && - displayedUsers.length === 0 && - searchByName.length > 0 ? ( -
    -

    - {t('noResultsFoundFor')} "{searchByName}" -

    -
    - ) : isLoading == false && usersData && displayedUsers.length === 0 ? ( - // eslint-disable-next-line react/jsx-indent -
    -

    {t('noUserFound')}

    -
    - ) : ( -
    - {isLoading ? ( - - ) : ( - - } - hasMore={hasMore} - className={styles.listBox} - data-testid="users-list" - endMessage={ -
    -
    {t('endOfResults')}
    -
    - } - > - - - - {headerTitles.map((title: string, index: number) => { - return ( - - ); - })} - - - - {usersData && - displayedUsers.map((user, index) => { + + {isLoading == false && + data && + displayedUsers.length === 0 && + searchByName.length > 0 ? ( +
    +

    + {t('noResultsFoundFor')} "{searchByName}" +

    +
    + ) : isLoading == false && data && displayedUsers.length === 0 ? ( +
    +

    {t('noUserFound')}

    +
    + ) : ( +
    + {isLoading ? ( + + ) : ( + + } + hasMore={hasMore} + className={styles.listBox} + data-testid="users-list" + endMessage={ +
    +
    {t('endOfResults')}
    +
    + } + > +
    - {title} -
    + + + {headerTitles.map((title: string, index: number) => { + return ( + + ); + })} + + + + {data && + displayedUsers.map( + (user: InterfaceQueryUserListItem, index: number) => { return ( { } /> ); - })} - -
    + {title} +
    -
    - )} -
    - )} - + }, + )} + + + + )} +
    + )} ); }; diff --git a/src/screens/Users/UsersMocks.ts b/src/screens/Users/UsersMocks.ts index 2ee589fd2f..ff346a1c97 100644 --- a/src/screens/Users/UsersMocks.ts +++ b/src/screens/Users/UsersMocks.ts @@ -13,19 +13,10 @@ export const MOCKS = [ result: { data: { user: { - _id: 'user1', - userType: 'SUPERADMIN', firstName: 'John', lastName: 'Doe', image: '', email: 'John_Does_Palasidoes@gmail.com', - adminFor: [ - { - _id: 1, - name: 'Palisadoes', - image: '', - }, - ], }, }, }, @@ -44,102 +35,391 @@ export const MOCKS = [ data: { users: [ { - _id: 'user1', - firstName: 'John', - lastName: 'Doe', - image: null, - email: 'john@example.com', - userType: 'SUPERADMIN', - adminApproved: true, - adminFor: [ - { - _id: '123', - }, - ], - createdAt: '20/06/2022', - organizationsBlockedBy: [ - { - _id: 'xyz', - name: 'ABC', - image: null, - location: 'Jamaica', - createdAt: '20/06/2022', - creator: { + user: { + _id: 'user1', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + createdAt: '20/06/2022', + registeredEvents: [], + membershipRequests: [], + organizationsBlockedBy: [ + { + _id: 'xyz', + name: 'ABC', + image: null, + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '20/06/2022', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + createdAt: '20/06/2022', + }, + }, + ], + joinedOrganizations: [ + { + _id: 'abc', + name: 'Joined Organization 1', + image: null, + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '20/06/2022', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + createdAt: '20/06/2022', + }, + }, + ], + }, + appUserProfile: { + _id: 'user1', + adminFor: [ + { _id: '123', - firstName: 'John', - lastName: 'Doe', + }, + ], + isSuperAdmin: true, + createdOrganizations: [], + createdEvents: [], + eventAdmin: [], + }, + }, + { + user: { + _id: 'user2', + firstName: 'Jane', + lastName: 'Doe', + image: null, + email: 'john@example.com', + createdAt: '20/06/2022', + registeredEvents: [], + membershipRequests: [], + organizationsBlockedBy: [ + { + _id: '456', + name: 'ABC', image: null, - email: 'john@example.com', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, createdAt: '20/06/2022', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + createdAt: '20/06/2022', + }, }, - }, - ], - joinedOrganizations: [ - { - _id: 'abc', - name: 'Joined Organization 1', - image: null, - location: 'Jamaica', - createdAt: '20/06/2022', - creator: { + ], + joinedOrganizations: [ + { _id: '123', - firstName: 'John', - lastName: 'Doe', + name: 'Palisadoes', image: null, - email: 'john@example.com', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, createdAt: '20/06/2022', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + createdAt: '20/06/2022', + }, }, - }, - ], + ], + }, + appUserProfile: { + _id: 'user2', + adminFor: [ + { + _id: '123', + }, + ], + isSuperAdmin: false, + createdOrganizations: [], + createdEvents: [], + eventAdmin: [], + }, }, + ], + }, + }, + }, + { + request: { + query: ORGANIZATION_CONNECTION_LIST, + }, + result: { + data: { + organizationsConnection: [ { - _id: 'user2', - firstName: 'Jane', - lastName: 'Doe', + _id: 123, image: null, - email: 'john@example.com', - userType: 'SUPERADMIN', - adminApproved: true, - adminFor: [ + creator: { + firstName: 'John', + lastName: 'Doe', + }, + name: 'Palisadoes', + members: [ + { + _id: 'user1', + }, { - _id: '123', + _id: 'user2', }, ], - createdAt: '20/06/2022', - organizationsBlockedBy: [ + admins: [ { - _id: '456', - name: 'ABC', - image: null, - location: 'Jamaica', - createdAt: '20/06/2022', - creator: { + _id: 'user1', + }, + { + _id: 'user2', + }, + ], + createdAt: '09/11/2001', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + }, + ], + }, + }, + }, +]; + +export const MOCKS2 = [ + { + request: { + query: USER_ORGANIZATION_LIST, + variables: { id: 'user1' }, + }, + result: { + data: { + user: { + firstName: 'John', + lastName: 'Doe', + image: '', + email: 'John_Does_Palasidoes@gmail.com', + }, + }, + }, + }, + { + request: { + query: USER_LIST, + variables: { + first: 12, + skip: 0, + firstName_contains: '', + lastName_contains: '', + }, + }, + result: { + data: { + users: [ + { + user: { + _id: 'user1', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + createdAt: '20/06/2022', + registeredEvents: [], + membershipRequests: [], + organizationsBlockedBy: [ + { + _id: 'xyz', + name: 'ABC', + image: null, + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '20/06/2022', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + createdAt: '20/06/2022', + }, + }, + ], + joinedOrganizations: [ + { + _id: 'abc', + name: 'Joined Organization 1', + image: null, + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '20/06/2022', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + createdAt: '20/06/2022', + }, + }, + ], + }, + appUserProfile: { + _id: 'user1', + adminFor: [ + { _id: '123', - firstName: 'John', - lastName: 'Doe', + }, + ], + isSuperAdmin: true, + createdOrganizations: [], + createdEvents: [], + eventAdmin: [], + }, + }, + { + user: { + _id: 'user2', + firstName: 'Jane', + lastName: 'Doe', + image: null, + email: 'john@example.com', + createdAt: '20/06/2022', + registeredEvents: [], + membershipRequests: [], + organizationsBlockedBy: [ + { + _id: '456', + name: 'ABC', image: null, - email: 'john@example.com', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, createdAt: '20/06/2022', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + createdAt: '20/06/2022', + }, }, - }, - ], - joinedOrganizations: [ - { - _id: '123', - name: 'Palisadoes', - image: null, - location: 'Jamaica', - createdAt: '20/06/2022', - creator: { + ], + joinedOrganizations: [ + { _id: '123', - firstName: 'John', - lastName: 'Doe', + name: 'Palisadoes', image: null, - email: 'john@example.com', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, createdAt: '20/06/2022', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + createdAt: '20/06/2022', + }, }, - }, - ], + ], + }, + appUserProfile: { + _id: 'user2', + adminFor: [ + { + _id: '123', + }, + ], + isSuperAdmin: false, + createdOrganizations: [], + createdEvents: [], + eventAdmin: [], + }, }, ], }, @@ -177,7 +457,16 @@ export const MOCKS = [ }, ], createdAt: '09/11/2001', - location: 'Twin Tower', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, }, ], }, diff --git a/src/setup/askForCustomPort/askForCustomPort.test.ts b/src/setup/askForCustomPort/askForCustomPort.test.ts new file mode 100644 index 0000000000..0df6259ba1 --- /dev/null +++ b/src/setup/askForCustomPort/askForCustomPort.test.ts @@ -0,0 +1,24 @@ +import inquirer from 'inquirer'; +import { askForCustomPort } from './askForCustomPort'; + +jest.mock('inquirer'); + +describe('askForCustomPort', () => { + test('should return default port if user provides no input', async () => { + jest + .spyOn(inquirer, 'prompt') + .mockResolvedValueOnce({ customPort: '4321' }); + + const result = await askForCustomPort(); + expect(result).toBe('4321'); + }); + + test('should return user-provided port', async () => { + jest + .spyOn(inquirer, 'prompt') + .mockResolvedValueOnce({ customPort: '8080' }); + + const result = await askForCustomPort(); + expect(result).toBe('8080'); + }); +}); diff --git a/src/setup/askForCustomPort/askForCustomPort.ts b/src/setup/askForCustomPort/askForCustomPort.ts new file mode 100644 index 0000000000..8a923f678f --- /dev/null +++ b/src/setup/askForCustomPort/askForCustomPort.ts @@ -0,0 +1,14 @@ +import inquirer from 'inquirer'; + +export async function askForCustomPort(): Promise { + const { customPort } = await inquirer.prompt([ + { + type: 'input', + name: 'customPort', + message: + 'Enter custom port for development server (leave blank for default 4321):', + default: 4321, + }, + ]); + return customPort; +} diff --git a/src/setup/askForTalawaApiUrl/askForTalawaApiUrl.test.ts b/src/setup/askForTalawaApiUrl/askForTalawaApiUrl.test.ts new file mode 100644 index 0000000000..b1490222b4 --- /dev/null +++ b/src/setup/askForTalawaApiUrl/askForTalawaApiUrl.test.ts @@ -0,0 +1,58 @@ +import inquirer from 'inquirer'; +import { askForTalawaApiUrl } from './askForTalawaApiUrl'; + +jest.mock('inquirer', () => ({ + prompt: jest.fn(), +})); + +describe('askForTalawaApiUrl', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + test('should return the provided endpoint when user enters it', async () => { + const mockPrompt = jest.spyOn(inquirer, 'prompt').mockResolvedValueOnce({ + endpoint: 'http://example.com/graphql/', + }); + + const result = await askForTalawaApiUrl(); + + expect(mockPrompt).toHaveBeenCalledWith([ + { + type: 'input', + name: 'endpoint', + message: 'Enter your talawa-api endpoint:', + default: 'http://localhost:4000/graphql/', + }, + ]); + + expect(result).toBe('http://example.com/graphql/'); + }); + + test('should return the default endpoint when the user does not enter anything', async () => { + const mockPrompt = jest + .spyOn(inquirer, 'prompt') + .mockImplementation(async (questions: any) => { + const answers: Record = {}; + questions.forEach( + (question: { name: string | number; default: any }) => { + answers[question.name] = question.default; + }, + ); + return answers; + }); + + const result = await askForTalawaApiUrl(); + + expect(mockPrompt).toHaveBeenCalledWith([ + { + type: 'input', + name: 'endpoint', + message: 'Enter your talawa-api endpoint:', + default: 'http://localhost:4000/graphql/', + }, + ]); + + expect(result).toBe('http://localhost:4000/graphql/'); + }); +}); diff --git a/src/setup/askForTalawaApiUrl/askForTalawaApiUrl.ts b/src/setup/askForTalawaApiUrl/askForTalawaApiUrl.ts new file mode 100644 index 0000000000..97daa1ac89 --- /dev/null +++ b/src/setup/askForTalawaApiUrl/askForTalawaApiUrl.ts @@ -0,0 +1,13 @@ +import inquirer from 'inquirer'; + +export async function askForTalawaApiUrl(): Promise { + const { endpoint } = await inquirer.prompt([ + { + type: 'input', + name: 'endpoint', + message: 'Enter your talawa-api endpoint:', + default: 'http://localhost:4000/graphql/', + }, + ]); + return endpoint; +} diff --git a/src/setup/checkConnection/checkConnection.test.ts b/src/setup/checkConnection/checkConnection.test.ts new file mode 100644 index 0000000000..c6f5251bdf --- /dev/null +++ b/src/setup/checkConnection/checkConnection.test.ts @@ -0,0 +1,55 @@ +import { checkConnection } from './checkConnection'; + +jest.mock('node-fetch'); + +global.fetch = jest.fn((url) => { + if (url === 'http://example.com/graphql/') { + const responseInit: ResponseInit = { + status: 200, + statusText: 'OK', + headers: new Headers({ 'Content-Type': 'application/json' }), + }; + return Promise.resolve(new Response(JSON.stringify({}), responseInit)); + } else { + const errorResponseInit: ResponseInit = { + status: 500, + statusText: 'Internal Server Error', + headers: new Headers({ 'Content-Type': 'text/plain' }), + }; + return Promise.reject(new Response('Error', errorResponseInit)); + } +}); + +describe('checkConnection', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + test('should return true and log success message if the connection is successful', async () => { + jest.spyOn(console, 'log').mockImplementation((string) => string); + const result = await checkConnection('http://example.com/graphql/'); + + expect(result).toBe(true); + expect(console.log).toHaveBeenCalledWith( + '\nChecking Talawa-API connection....', + ); + expect(console.log).toHaveBeenCalledWith( + '\nConnection to Talawa-API successful! 🎉', + ); + }); + + it('should return false and log error message if the connection fails', async () => { + jest.spyOn(console, 'log').mockImplementation((string) => string); + const result = await checkConnection( + 'http://example_not_working.com/graphql/', + ); + + expect(result).toBe(false); + expect(console.log).toHaveBeenCalledWith( + '\nChecking Talawa-API connection....', + ); + expect(console.log).toHaveBeenCalledWith( + '\nTalawa-API service is unavailable. Is it running? Check your network connectivity too.', + ); + }); +}); diff --git a/src/setup/checkConnection/checkConnection.ts b/src/setup/checkConnection/checkConnection.ts new file mode 100644 index 0000000000..601bea98ca --- /dev/null +++ b/src/setup/checkConnection/checkConnection.ts @@ -0,0 +1,15 @@ +export async function checkConnection(url: string): Promise { + console.log('\nChecking Talawa-API connection....'); + let isConnected = false; + await fetch(url) + .then(() => { + isConnected = true; + console.log('\nConnection to Talawa-API successful! 🎉'); + }) + .catch(() => { + console.log( + '\nTalawa-API service is unavailable. Is it running? Check your network connectivity too.', + ); + }); + return isConnected; +} diff --git a/src/setup/checkEnvFile/checkEnvFile.test.ts b/src/setup/checkEnvFile/checkEnvFile.test.ts new file mode 100644 index 0000000000..a23976db4a --- /dev/null +++ b/src/setup/checkEnvFile/checkEnvFile.test.ts @@ -0,0 +1,47 @@ +import fs from 'fs'; +import { checkEnvFile } from './checkEnvFile'; + +jest.mock('fs'); + +describe('checkEnvFile', () => { + beforeEach(() => { + jest.resetAllMocks(); + }); + + it('should append missing keys to the .env file', () => { + const envContent = 'EXISTING_KEY=existing_value\n'; + const envExampleContent = + 'EXISTING_KEY=existing_value\nNEW_KEY=default_value\n'; + + jest + .spyOn(fs, 'readFileSync') + .mockReturnValueOnce(envContent) + .mockReturnValueOnce(envExampleContent) + .mockReturnValueOnce(envExampleContent); + + jest.spyOn(fs, 'appendFileSync'); + + checkEnvFile(); + + expect(fs.appendFileSync).toHaveBeenCalledWith( + '.env', + 'NEW_KEY=default_value\n', + ); + }); + + it('should not append anything if all keys are present', () => { + const envContent = 'EXISTING_KEY=existing_value\n'; + const envExampleContent = 'EXISTING_KEY=existing_value\n'; + + jest + .spyOn(fs, 'readFileSync') + .mockReturnValueOnce(envContent) + .mockReturnValueOnce(envExampleContent); + + jest.spyOn(fs, 'appendFileSync'); + + checkEnvFile(); + + expect(fs.appendFileSync).not.toHaveBeenCalled(); + }); +}); diff --git a/src/setup/checkEnvFile/checkEnvFile.ts b/src/setup/checkEnvFile/checkEnvFile.ts new file mode 100644 index 0000000000..420a7c1321 --- /dev/null +++ b/src/setup/checkEnvFile/checkEnvFile.ts @@ -0,0 +1,16 @@ +import dotenv from 'dotenv'; +import fs from 'fs'; + +dotenv.config(); + +export function checkEnvFile(): void { + const env = dotenv.parse(fs.readFileSync('.env')); + const envSample = dotenv.parse(fs.readFileSync('.env.example')); + const misplaced = Object.keys(envSample).filter((key) => !(key in env)); + if (misplaced.length > 0) { + const config = dotenv.parse(fs.readFileSync('.env.example')); + misplaced.map((key) => + fs.appendFileSync('.env', `${key}=${config[key]}\n`), + ); + } +} diff --git a/src/setup/validateRecaptcha/validateRecaptcha.test.ts b/src/setup/validateRecaptcha/validateRecaptcha.test.ts new file mode 100644 index 0000000000..c77c9ed62b --- /dev/null +++ b/src/setup/validateRecaptcha/validateRecaptcha.test.ts @@ -0,0 +1,23 @@ +import { validateRecaptcha } from './validateRecaptcha'; + +describe('validateRecaptcha', () => { + it('should return true for a valid Recaptcha string', () => { + const validRecaptcha = 'ss7BEe32HPoDKTPXQevFkVvpvPzGebE2kIRv1ok4'; + expect(validateRecaptcha(validRecaptcha)).toBe(true); + }); + + it('should return false for an invalid Recaptcha string with special characters', () => { + const invalidRecaptcha = 'invalid@recaptcha!'; + expect(validateRecaptcha(invalidRecaptcha)).toBe(false); + }); + + it('should return false for an invalid Recaptcha string with incorrect length', () => { + const invalidRecaptcha = 'shortstring'; + expect(validateRecaptcha(invalidRecaptcha)).toBe(false); + }); + + it('should return false for an invalid Recaptcha string with spaces', () => { + const invalidRecaptcha = 'invalid recaptcha string'; + expect(validateRecaptcha(invalidRecaptcha)).toBe(false); + }); +}); diff --git a/src/setup/validateRecaptcha/validateRecaptcha.ts b/src/setup/validateRecaptcha/validateRecaptcha.ts new file mode 100644 index 0000000000..dcefb860fe --- /dev/null +++ b/src/setup/validateRecaptcha/validateRecaptcha.ts @@ -0,0 +1,4 @@ +export function validateRecaptcha(string: string): boolean { + const pattern = /^[a-zA-Z0-9_-]{40}$/; + return pattern.test(string); +} diff --git a/src/setupTests.ts b/src/setupTests.ts index 0e9f48386b..eac7093309 100644 --- a/src/setupTests.ts +++ b/src/setupTests.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-empty-function */ // jest-dom adds custom jest matchers for asserting on DOM nodes. // allows you to do things like: // expect(element).toHaveTextContent(/react/i) @@ -17,12 +16,10 @@ global.console.warn = function (...args): void { throw new Error(format(...args)); }; Object.defineProperty(HTMLMediaElement.prototype, 'muted', { - set: () => {}, + set: () => ({}), }); import { jestPreviewConfigure } from 'jest-preview'; -import { configure } from 'enzyme'; -import Adapter from '@wojtekmaj/enzyme-adapter-react-17'; // Global CSS here import 'bootstrap/dist/css/bootstrap.css'; @@ -30,8 +27,6 @@ import 'bootstrap/dist/js/bootstrap.min.js'; import 'react-datepicker/dist/react-datepicker.css'; import 'flag-icons/css/flag-icons.min.css'; -configure({ adapter: new Adapter() }); - jestPreviewConfigure({ // Opt-in to automatic mode to preview failed test case automatically. autoPreview: true, diff --git a/src/state/action-creators/index.ts b/src/state/action-creators/index.ts index f0ce7264e1..7fb06971c5 100644 --- a/src/state/action-creators/index.ts +++ b/src/state/action-creators/index.ts @@ -33,3 +33,12 @@ export const updatePluginLinks = (plugins: any) => { }); }; }; + +export const updateTargets = (orgId: string | undefined) => { + return (dispatch: any): void => { + dispatch({ + type: 'UPDATE_TARGETS', + payload: orgId, + }); + }; +}; diff --git a/src/state/reducers/index.ts b/src/state/reducers/index.ts index 3ab9725f7c..ca2b2b28ee 100644 --- a/src/state/reducers/index.ts +++ b/src/state/reducers/index.ts @@ -1,10 +1,12 @@ import { combineReducers } from 'redux'; import routesReducer from './routesReducer'; import pluginReducer from './pluginReducer'; +import userRoutesReducer from './userRoutesReducer'; export const reducers = combineReducers({ appRoutes: routesReducer, plugins: pluginReducer, + userRoutes: userRoutesReducer, }); export type RootState = ReturnType; diff --git a/src/state/reducers/pluginReducer.test.ts b/src/state/reducers/pluginReducer.test.ts index ddef5b9c7f..571345ce2f 100644 --- a/src/state/reducers/pluginReducer.test.ts +++ b/src/state/reducers/pluginReducer.test.ts @@ -7,7 +7,7 @@ describe('Testing Plugin Reducer', () => { reducer(undefined, { type: '', payload: undefined, - }) + }), ).toEqual({ installed: [], addonStore: [], @@ -21,8 +21,8 @@ describe('Testing Plugin Reducer', () => { { type: 'INSTALL_PLUGIN', payload: { name: 'testplug' }, - } - ) + }, + ), ).toEqual({ installed: [{ name: 'testplug' }], addonStore: [], @@ -43,8 +43,8 @@ describe('Testing Plugin Reducer', () => { { type: 'REMOVE_PLUGIN', payload: { id: 3 }, - } - ) + }, + ), ).toEqual({ installed: [{ name: 'testplug3', id: 5 }], addonStore: [], @@ -59,8 +59,8 @@ describe('Testing Plugin Reducer', () => { type: 'UPDATE_INSTALLED', //Here payload is expected to be as array payload: [{ name: 'testplug-updated' }], - } - ) + }, + ), ).toEqual({ installed: [{ name: 'testplug-updated' }], addonStore: [], @@ -75,8 +75,8 @@ describe('Testing Plugin Reducer', () => { type: 'UPDATE_STORE', //Here payload is expected to be as array payload: [{ name: 'sample-addon' }], - } - ) + }, + ), ).toEqual({ installed: [], addonStore: [{ name: 'sample-addon' }], @@ -91,8 +91,8 @@ describe('Testing Plugin Reducer', () => { type: 'UPDATE_EXTRAS', //Here payload is expected to be as array payload: [{ name: 'sample-addon-extra' }], - } - ) + }, + ), ).toEqual({ installed: [], addonStore: [{ name: 'sample-addon-extra' }], diff --git a/src/state/reducers/pluginReducer.ts b/src/state/reducers/pluginReducer.ts index 483b357e16..192c995182 100644 --- a/src/state/reducers/pluginReducer.ts +++ b/src/state/reducers/pluginReducer.ts @@ -2,7 +2,7 @@ import type { InterfaceAction } from 'state/helpers/Action'; const reducer = ( state = INITIAL_STATE, - action: InterfaceAction + action: InterfaceAction, ): typeof INITIAL_STATE => { switch (action.type) { case 'UPDATE_INSTALLED': @@ -17,7 +17,7 @@ const reducer = ( return Object.assign({}, state, { installed: [ ...state.installed.filter( - (plugin: any) => plugin.id !== action.payload.id + (plugin: any) => plugin.id !== action.payload.id, ), ], }); diff --git a/src/state/reducers/routesReducer.test.ts b/src/state/reducers/routesReducer.test.ts index 765920e6f3..36b630094e 100644 --- a/src/state/reducers/routesReducer.test.ts +++ b/src/state/reducers/routesReducer.test.ts @@ -1,5 +1,5 @@ -import reducer from './routesReducer'; import expect from 'expect'; +import reducer from './routesReducer'; describe('Testing Routes reducer', () => { it('should return the initial state', () => { @@ -7,33 +7,37 @@ describe('Testing Routes reducer', () => { reducer(undefined, { type: '', payload: undefined, - }) + }), ).toEqual({ targets: [ - { name: 'Dashboard', url: '/orgdash/id=undefined' }, - { name: 'People', url: '/orgpeople/id=undefined' }, - { name: 'Events', url: '/orgevents/id=undefined' }, - { name: 'Posts', url: '/orgpost/id=undefined' }, + { name: 'My Organizations', url: '/orglist' }, + { name: 'Dashboard', url: '/orgdash/undefined' }, + { name: 'People', url: '/orgpeople/undefined' }, + { name: 'Events', url: '/orgevents/undefined' }, + { name: 'Venues', url: '/orgvenues/undefined' }, + { name: 'Action Items', url: '/orgactionitems/undefined' }, + { name: 'Posts', url: '/orgpost/undefined' }, { name: 'Block/Unblock', - url: '/blockuser/id=undefined', + url: '/blockuser/undefined', }, - { name: 'Advertisement', url: '/orgads/id=undefined' }, + { name: 'Advertisement', url: '/orgads/undefined' }, + { name: 'Funds', url: '/orgfunds/undefined' }, + { name: 'Requests', url: '/requests/undefined' }, { name: 'Plugins', subTargets: [ { icon: 'fa-store', name: 'Plugin Store', - url: '/orgstore/id=undefined', + url: '/orgstore/undefined', }, ], }, - { name: 'Settings', url: '/orgsetting/id=undefined' }, - { name: 'All Organizations', url: '/orglist/id=undefined' }, + { name: 'Settings', url: '/orgsetting/undefined' }, ], - configUrl: 'undefined', components: [ + { name: 'My Organizations', comp_id: 'orglist', component: 'OrgList' }, { name: 'Dashboard', comp_id: 'orgdash', @@ -49,6 +53,16 @@ describe('Testing Routes reducer', () => { comp_id: 'orgevents', component: 'OrganizationEvents', }, + { + name: 'Venues', + comp_id: 'orgvenues', + component: 'OrganizationVenues', + }, + { + name: 'Action Items', + comp_id: 'orgactionitems', + component: 'OrganizationActionItems', + }, { name: 'Posts', comp_id: 'orgpost', component: 'OrgPost' }, { name: 'Block/Unblock', comp_id: 'blockuser', component: 'BlockUser' }, { @@ -56,6 +70,16 @@ describe('Testing Routes reducer', () => { comp_id: 'orgads', component: 'Advertisements', }, + { + name: 'Funds', + comp_id: 'orgfunds', + component: 'OrganizationFunds', + }, + { + name: 'Requests', + comp_id: 'requests', + component: 'Requests', + }, { name: 'Plugins', comp_id: null, @@ -70,7 +94,6 @@ describe('Testing Routes reducer', () => { ], }, { name: 'Settings', comp_id: 'orgsetting', component: 'OrgSettings' }, - { name: 'All Organizations', comp_id: 'orglist', component: 'OrgList' }, { name: '', comp_id: 'member', component: 'MemberDetail' }, ], }); @@ -80,32 +103,35 @@ describe('Testing Routes reducer', () => { expect( reducer(undefined, { type: 'UPDATE_TARGETS', - payload: { test: 'testupdate' }, - }) + payload: 'orgId', + }), ).toEqual({ targets: [ - { name: 'Dashboard', url: '/orgdash/id=undefined' }, - { name: 'People', url: '/orgpeople/id=undefined' }, - { name: 'Events', url: '/orgevents/id=undefined' }, - { name: 'Posts', url: '/orgpost/id=undefined' }, - { name: 'Block/Unblock', url: '/blockuser/id=undefined' }, - { name: 'Advertisement', url: '/orgads/id=undefined' }, + { name: 'My Organizations', url: '/orglist' }, + { name: 'Dashboard', url: '/orgdash/orgId' }, + { name: 'People', url: '/orgpeople/orgId' }, + { name: 'Events', url: '/orgevents/orgId' }, + { name: 'Venues', url: '/orgvenues/orgId' }, + { name: 'Action Items', url: '/orgactionitems/orgId' }, + { name: 'Posts', url: '/orgpost/orgId' }, + { name: 'Block/Unblock', url: '/blockuser/orgId' }, + { name: 'Advertisement', url: '/orgads/orgId' }, + { name: 'Funds', url: '/orgfunds/orgId' }, + { name: 'Requests', url: '/requests/orgId' }, { name: 'Plugins', subTargets: [ { icon: 'fa-store', name: 'Plugin Store', - url: '/orgstore/id=undefined', + url: '/orgstore/orgId', }, ], }, - { name: 'Settings', url: '/orgsetting/id=undefined' }, - { name: 'All Organizations', url: '/orglist/id=undefined' }, - { test: 'testupdate' }, + { name: 'Settings', url: '/orgsetting/orgId' }, ], - configUrl: 'undefined', components: [ + { name: 'My Organizations', comp_id: 'orglist', component: 'OrgList' }, { name: 'Dashboard', comp_id: 'orgdash', @@ -121,6 +147,16 @@ describe('Testing Routes reducer', () => { comp_id: 'orgevents', component: 'OrganizationEvents', }, + { + name: 'Venues', + comp_id: 'orgvenues', + component: 'OrganizationVenues', + }, + { + name: 'Action Items', + comp_id: 'orgactionitems', + component: 'OrganizationActionItems', + }, { name: 'Posts', comp_id: 'orgpost', component: 'OrgPost' }, { name: 'Block/Unblock', comp_id: 'blockuser', component: 'BlockUser' }, { @@ -128,6 +164,12 @@ describe('Testing Routes reducer', () => { comp_id: 'orgads', component: 'Advertisements', }, + { name: 'Funds', comp_id: 'orgfunds', component: 'OrganizationFunds' }, + { + name: 'Requests', + comp_id: 'requests', + component: 'Requests', + }, { name: 'Plugins', comp_id: null, @@ -142,7 +184,6 @@ describe('Testing Routes reducer', () => { ], }, { name: 'Settings', comp_id: 'orgsetting', component: 'OrgSettings' }, - { name: 'All Organizations', comp_id: 'orglist', component: 'OrgList' }, { name: '', comp_id: 'member', component: 'MemberDetail' }, ], }); @@ -153,20 +194,24 @@ describe('Testing Routes reducer', () => { reducer(undefined, { type: 'UPDATE_P_TARGETS', payload: [{ name: 'test-target-plugin', content: 'plugin-new' }], - }) + }), ).toEqual({ targets: [ - { name: 'Dashboard', url: '/orgdash/id=undefined' }, - { name: 'People', url: '/orgpeople/id=undefined' }, - { name: 'Events', url: '/orgevents/id=undefined' }, - { name: 'Posts', url: '/orgpost/id=undefined' }, + { name: 'My Organizations', url: '/orglist' }, + { name: 'Dashboard', url: '/orgdash/undefined' }, + { name: 'People', url: '/orgpeople/undefined' }, + { name: 'Events', url: '/orgevents/undefined' }, + { name: 'Venues', url: '/orgvenues/undefined' }, + { name: 'Action Items', url: '/orgactionitems/undefined' }, + { name: 'Posts', url: '/orgpost/undefined' }, { name: 'Block/Unblock', - url: '/blockuser/id=undefined', + url: '/blockuser/undefined', }, - { name: 'Advertisement', url: '/orgads/id=undefined' }, - { name: 'Settings', url: '/orgsetting/id=undefined' }, - { name: 'All Organizations', url: '/orglist/id=undefined' }, + { name: 'Advertisement', url: '/orgads/undefined' }, + { name: 'Funds', url: '/orgfunds/undefined' }, + { name: 'Requests', url: '/requests/undefined' }, + { name: 'Settings', url: '/orgsetting/undefined' }, { comp_id: null, component: null, @@ -176,13 +221,13 @@ describe('Testing Routes reducer', () => { { icon: 'fa-store', name: 'Plugin Store', - url: '/orgstore/id=undefined', + url: '/orgstore/undefined', }, ], }, ], - configUrl: 'undefined', components: [ + { name: 'My Organizations', comp_id: 'orglist', component: 'OrgList' }, { name: 'Dashboard', comp_id: 'orgdash', @@ -198,7 +243,16 @@ describe('Testing Routes reducer', () => { comp_id: 'orgevents', component: 'OrganizationEvents', }, - + { + name: 'Venues', + comp_id: 'orgvenues', + component: 'OrganizationVenues', + }, + { + name: 'Action Items', + comp_id: 'orgactionitems', + component: 'OrganizationActionItems', + }, { name: 'Posts', comp_id: 'orgpost', component: 'OrgPost' }, { name: 'Block/Unblock', comp_id: 'blockuser', component: 'BlockUser' }, { @@ -206,6 +260,16 @@ describe('Testing Routes reducer', () => { comp_id: 'orgads', component: 'Advertisements', }, + { + name: 'Funds', + comp_id: 'orgfunds', + component: 'OrganizationFunds', + }, + { + name: 'Requests', + comp_id: 'requests', + component: 'Requests', + }, { name: 'Plugins', comp_id: null, @@ -220,9 +284,32 @@ describe('Testing Routes reducer', () => { ], }, { name: 'Settings', comp_id: 'orgsetting', component: 'OrgSettings' }, - { name: 'All Organizations', comp_id: 'orglist', component: 'OrgList' }, { name: '', comp_id: 'member', component: 'MemberDetail' }, ], }); }); }); + +describe('routesReducer', () => { + it('returns state with updated subTargets when UPDATE_P_TARGETS action is dispatched', () => { + const action = { + type: 'UPDATE_P_TARGETS', + payload: [{ name: 'New Plugin', url: '/newplugin' }], + }; + const initialState = { + targets: [{ name: 'Plugins' }], + components: [], + }; + const state = reducer(initialState, action); + const pluginsTarget = state.targets.find( + (target) => target.name === 'Plugins', + ); + // Check if pluginsTarget is defined + if (!pluginsTarget) { + throw new Error('Plugins target not found in state'); + } + expect(pluginsTarget.subTargets).toEqual([ + { name: 'New Plugin', url: '/newplugin' }, + ]); + }); +}); diff --git a/src/state/reducers/routesReducer.ts b/src/state/reducers/routesReducer.ts index 4fafbd1ebb..e223b0754e 100644 --- a/src/state/reducers/routesReducer.ts +++ b/src/state/reducers/routesReducer.ts @@ -1,25 +1,38 @@ import type { InterfaceAction } from 'state/helpers/Action'; -const currentOrg = window.location.href.split('=')[1]; +export type TargetsType = { + name: string; + url?: string; + subTargets?: SubTargetType[]; +}; + +export type SubTargetType = { + name?: string; + url: string; + icon?: string; + comp_id?: string; +}; const reducer = ( state = INITIAL_STATE, - action: InterfaceAction + action: InterfaceAction, ): typeof INITIAL_STATE => { switch (action.type) { case 'UPDATE_TARGETS': { - return Object.assign({}, INITIAL_STATE, { - targets: [...INITIAL_STATE.targets, action.payload], + return Object.assign({}, state, { + targets: [...generateRoutes(components, action.payload)], }); } case 'UPDATE_P_TARGETS': { - const oldTargets: any = INITIAL_STATE.targets.filter( - (target: any) => target.name === 'Plugins' - )[0].subTargets; - return Object.assign({}, INITIAL_STATE, { + const filteredTargets = state.targets.filter( + (target: TargetsType) => target.name === 'Plugins', + ); + + const oldTargets: SubTargetType[] = filteredTargets[0]?.subTargets || []; + return Object.assign({}, state, { targets: [ - ...INITIAL_STATE.targets.filter( - (target: any) => target.name !== 'Plugins' + ...state.targets.filter( + (target: TargetsType) => target.name !== 'Plugins', ), Object.assign( {}, @@ -28,7 +41,7 @@ const reducer = ( comp_id: null, component: null, subTargets: [...action.payload, ...oldTargets], - } + }, ), ], }); @@ -51,24 +64,23 @@ export type ComponentType = { }[]; }; -export type TargetsType = { - name: string; - url?: string; - subTargets?: { - name: any; - url: string; - icon: any; - }[]; -}; - // Note: Routes with names appear on NavBar const components: ComponentType[] = [ + { name: 'My Organizations', comp_id: 'orglist', component: 'OrgList' }, { name: 'Dashboard', comp_id: 'orgdash', component: 'OrganizationDashboard' }, { name: 'People', comp_id: 'orgpeople', component: 'OrganizationPeople' }, { name: 'Events', comp_id: 'orgevents', component: 'OrganizationEvents' }, + { name: 'Venues', comp_id: 'orgvenues', component: 'OrganizationVenues' }, + { + name: 'Action Items', + comp_id: 'orgactionitems', + component: 'OrganizationActionItems', + }, { name: 'Posts', comp_id: 'orgpost', component: 'OrgPost' }, { name: 'Block/Unblock', comp_id: 'blockuser', component: 'BlockUser' }, { name: 'Advertisement', comp_id: 'orgads', component: 'Advertisements' }, + { name: 'Funds', comp_id: 'orgfunds', component: 'OrganizationFunds' }, + { name: 'Requests', comp_id: 'requests', component: 'Requests' }, { name: 'Plugins', comp_id: null, @@ -82,27 +94,37 @@ const components: ComponentType[] = [ }, ], }, - { name: 'Settings', comp_id: 'orgsetting', component: 'OrgSettings' }, - { name: 'All Organizations', comp_id: 'orglist', component: 'OrgList' }, { name: '', comp_id: 'member', component: 'MemberDetail' }, ]; -const generateRoutes = (comps: ComponentType[]): TargetsType[] => { +const generateRoutes = ( + comps: ComponentType[], + currentOrg = undefined, +): TargetsType[] => { return comps .filter((comp) => comp.name && comp.name !== '') .map((comp) => { const entry: TargetsType = comp.comp_id - ? { name: comp.name, url: `/${comp.comp_id}/id=${currentOrg}` } + ? comp.comp_id === 'orglist' + ? { name: comp.name, url: `/${comp.comp_id}` } + : { name: comp.name, url: `/${comp.comp_id}/${currentOrg}` } : { name: comp.name, - subTargets: comp.subTargets?.map((subTarget: any) => { - return { - name: subTarget.name, - url: `/${subTarget.comp_id}/id=${currentOrg}`, - icon: subTarget.icon ? subTarget.icon : null, - }; - }), + subTargets: comp.subTargets?.map( + (subTarget: { + name: string; + comp_id: string; + component: string; + icon?: string; + }) => { + return { + name: subTarget.name, + url: `/${subTarget.comp_id}/${currentOrg}`, + icon: subTarget.icon, + }; + }, + ), }; return entry; }); @@ -110,7 +132,6 @@ const generateRoutes = (comps: ComponentType[]): TargetsType[] => { const INITIAL_STATE = { targets: generateRoutes(components), - configUrl: `${currentOrg}`, components, }; diff --git a/src/state/reducers/userRoutersReducer.test.ts b/src/state/reducers/userRoutersReducer.test.ts new file mode 100644 index 0000000000..f819af8564 --- /dev/null +++ b/src/state/reducers/userRoutersReducer.test.ts @@ -0,0 +1,68 @@ +import expect from 'expect'; +import reducer from './userRoutesReducer'; + +describe('Testing Routes reducer', () => { + it('should return the initial state', () => { + expect( + reducer(undefined, { + type: '', + payload: undefined, + }), + ).toEqual({ + targets: [ + { name: 'My Organizations', url: 'user/organizations' }, + { name: 'Posts', url: 'user/organization/undefined' }, + { name: 'People', url: 'user/people/undefined' }, + { name: 'Events', url: 'user/events/undefined' }, + { name: 'Donate', url: 'user/donate/undefined' }, + ], + components: [ + { + name: 'My Organizations', + comp_id: 'organizations', + component: 'Organizations', + }, + { + name: 'Posts', + comp_id: 'organization', + component: 'Posts', + }, + { name: 'People', comp_id: 'people', component: 'People' }, + { name: 'Events', comp_id: 'events', component: 'Events' }, + { name: 'Donate', comp_id: 'donate', component: 'Donate' }, + ], + }); + }); + + it('should handle UPDATE_TARGETS', () => { + expect( + reducer(undefined, { + type: 'UPDATE_TARGETS', + payload: 'orgId', + }), + ).toEqual({ + targets: [ + { name: 'My Organizations', url: 'user/organizations' }, + { name: 'Posts', url: 'user/organization/orgId' }, + { name: 'People', url: 'user/people/orgId' }, + { name: 'Events', url: 'user/events/orgId' }, + { name: 'Donate', url: 'user/donate/orgId' }, + ], + components: [ + { + name: 'My Organizations', + comp_id: 'organizations', + component: 'Organizations', + }, + { + name: 'Posts', + comp_id: 'organization', + component: 'Posts', + }, + { name: 'People', comp_id: 'people', component: 'People' }, + { name: 'Events', comp_id: 'events', component: 'Events' }, + { name: 'Donate', comp_id: 'donate', component: 'Donate' }, + ], + }); + }); +}); diff --git a/src/state/reducers/userRoutesReducer.ts b/src/state/reducers/userRoutesReducer.ts new file mode 100644 index 0000000000..e85d4c25d9 --- /dev/null +++ b/src/state/reducers/userRoutesReducer.ts @@ -0,0 +1,81 @@ +import type { InterfaceAction } from 'state/helpers/Action'; + +export type TargetsType = { + name: string; + url?: string; + subTargets?: SubTargetType[]; +}; + +export type SubTargetType = { + name?: string; + url: string; + icon?: string; + comp_id?: string; +}; + +const reducer = ( + state = INITIAL_USER_STATE, + action: InterfaceAction, +): typeof INITIAL_USER_STATE => { + switch (action.type) { + case 'UPDATE_TARGETS': { + return Object.assign({}, state, { + targets: [...generateRoutes(components, action.payload)], + }); + } + default: { + return state; + } + } +}; + +export type ComponentType = { + name: string; + comp_id: string | null; + component: string | null; + subTargets?: { + name: string; + comp_id: string; + component: string; + icon?: string; + }[]; +}; + +// Note: Routes with names appear on NavBar +const components: ComponentType[] = [ + { + name: 'My Organizations', + comp_id: 'organizations', + component: 'Organizations', + }, + { + name: 'Posts', + comp_id: 'organization', + component: 'Posts', + }, + { name: 'People', comp_id: 'people', component: 'People' }, + { name: 'Events', comp_id: 'events', component: 'Events' }, + { name: 'Donate', comp_id: 'donate', component: 'Donate' }, +]; + +const generateRoutes = ( + comps: ComponentType[], + currentOrg = undefined, +): TargetsType[] => { + return comps + .filter((comp) => comp.name && comp.name !== '') + .map((comp) => { + const entry: TargetsType = + comp.comp_id === 'organizations' + ? { name: comp.name, url: `user/${comp.comp_id}` } + : { name: comp.name, url: `user/${comp.comp_id}/${currentOrg}` }; + return entry; + }); +}; + +const INITIAL_USER_STATE = { + targets: generateRoutes(components), + components, +}; + +export default reducer; diff --git a/src/state/store.test.tsx b/src/state/store.test.tsx index 81e2831224..eedbbc84f0 100644 --- a/src/state/store.test.tsx +++ b/src/state/store.test.tsx @@ -14,7 +14,6 @@ describe('Testing src/state/store.ts', () => { test('appRoutes schema should contain targets, configUrl and components', () => { expect(state.appRoutes).toMatchObject({ targets: expect.any(Array), - configUrl: expect.any(String), components: expect.any(Array), }); }); diff --git a/src/utils/StaticMockLink.ts b/src/utils/StaticMockLink.ts index 79bbb57bae..31773d3978 100644 --- a/src/utils/StaticMockLink.ts +++ b/src/utils/StaticMockLink.ts @@ -47,7 +47,7 @@ export class StaticMockLink extends ApolloLink { this._normalizeMockedResponse(mockedResponse); const key = requestToKey( normalizedMockedResponse.request, - this.addTypename + this.addTypename, ); let mockedResponses = this._mockedResponsesByKey[key]; if (!mockedResponses) { @@ -70,7 +70,7 @@ export class StaticMockLink extends ApolloLink { return true; } return false; - } + }, ); let configError: Error; @@ -78,8 +78,8 @@ export class StaticMockLink extends ApolloLink { if (!response || typeof responseIndex === 'undefined') { configError = new Error( `No more mocked responses for the query: ${print( - operation.query - )}, variables: ${JSON.stringify(operation.variables)}` + operation.query, + )}, variables: ${JSON.stringify(operation.variables)}`, ); } else { const { newData } = response; @@ -90,41 +90,44 @@ export class StaticMockLink extends ApolloLink { if (!response.result && !response.error) { configError = new Error( - `Mocked response should contain either result or error: ${key}` + `Mocked response should contain either result or error: ${key}`, ); } } return new Observable((observer) => { - const timer = setTimeout(() => { - if (configError) { - try { - // The onError function can return false to indicate that - // configError need not be passed to observer.error. For - // example, the default implementation of onError calls - // observer.error(configError) and then returns false to - // prevent this extra (harmless) observer.error call. - if (this.onError(configError, observer) !== false) { - throw configError; + const timer = setTimeout( + () => { + if (configError) { + try { + // The onError function can return false to indicate that + // configError need not be passed to observer.error. For + // example, the default implementation of onError calls + // observer.error(configError) and then returns false to + // prevent this extra (harmless) observer.error call. + if (this.onError(configError, observer) !== false) { + throw configError; + } + } catch (error) { + observer.error(error); } - } catch (error) { - observer.error(error); - } - } else if (response) { - if (response.error) { - observer.error(response.error); - } else { - if (response.result) { - observer.next( - typeof response.result === 'function' - ? (response.result as ResultFunction)() - : response.result - ); + } else if (response) { + if (response.error) { + observer.error(response.error); + } else { + if (response.result) { + observer.next( + typeof response.result === 'function' + ? (response.result as ResultFunction)() + : response.result, + ); + } + observer.complete(); } - observer.complete(); } - } - }, (response && response.delay) || 0); + }, + (response && response.delay) || 0, + ); return () => { clearTimeout(timer); @@ -133,15 +136,14 @@ export class StaticMockLink extends ApolloLink { } private _normalizeMockedResponse( - mockedResponse: MockedResponse + mockedResponse: MockedResponse, ): MockedResponse { const newMockedResponse = cloneDeep(mockedResponse); const queryWithoutConnection = removeConnectionDirectiveFromDocument( - newMockedResponse.request.query + newMockedResponse.request.query, ); invariant(queryWithoutConnection, 'query is required'); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - newMockedResponse.request.query = queryWithoutConnection!; + newMockedResponse.request.query = queryWithoutConnection; const query = removeClientSetsFromDocument(newMockedResponse.request.query); if (query) { newMockedResponse.request.query = query; diff --git a/src/utils/currency.ts b/src/utils/currency.ts new file mode 100644 index 0000000000..d096177dc5 --- /dev/null +++ b/src/utils/currency.ts @@ -0,0 +1,330 @@ +export const currencyOptions = [ + { value: 'AED', label: 'AED' }, // United Arab Emirates Dirham + { value: 'AFN', label: 'AFN' }, // Afghan Afghani + { value: 'ALL', label: 'ALL' }, // Albanian Lek + { value: 'AMD', label: 'AMD' }, // Armenian Dram + { value: 'ANG', label: 'ANG' }, // Netherlands Antillean Guilder + { value: 'AOA', label: 'AOA' }, // Angolan Kwanza + { value: 'ARS', label: 'ARS' }, // Argentine Peso + { value: 'AUD', label: 'AUD' }, // Australian Dollar + { value: 'AWG', label: 'AWG' }, // Aruban Florin + { value: 'AZN', label: 'AZN' }, // Azerbaijani Manat + { value: 'BAM', label: 'BAM' }, // Bosnia-Herzegovina Convertible Mark + { value: 'BBD', label: 'BBD' }, // Barbadian Dollar + { value: 'BDT', label: 'BDT' }, // Bangladeshi Taka + { value: 'BGN', label: 'BGN' }, // Bulgarian Lev + { value: 'BHD', label: 'BHD' }, // Bahraini Dinar + { value: 'BIF', label: 'BIF' }, // Burundian Franc + { value: 'BMD', label: 'BMD' }, // Bermudian Dollar + { value: 'BND', label: 'BND' }, // Brunei Dollar + { value: 'BOB', label: 'BOB' }, // Bolivian Boliviano + { value: 'BRL', label: 'BRL' }, // Brazilian Real + { value: 'BSD', label: 'BSD' }, // Bahamian Dollar + { value: 'BTN', label: 'BTN' }, // Bhutanese Ngultrum + { value: 'BWP', label: 'BWP' }, // Botswanan Pula + { value: 'BYN', label: 'BYN' }, // Belarusian Ruble + { value: 'BZD', label: 'BZD' }, // Belize Dollar + { value: 'CAD', label: 'CAD' }, // Canadian Dollar + { value: 'CDF', label: 'CDF' }, // Congolese Franc + { value: 'CHF', label: 'CHF' }, // Swiss Franc + { value: 'CLP', label: 'CLP' }, // Chilean Peso + { value: 'CNY', label: 'CNY' }, // Chinese Yuan + { value: 'COP', label: 'COP' }, // Colombian Peso + { value: 'CRC', label: 'CRC' }, // Costa Rican Colón + { value: 'CUP', label: 'CUP' }, // Cuban Peso + { value: 'CVE', label: 'CVE' }, // Cape Verdean Escudo + { value: 'CZK', label: 'CZK' }, // Czech Koruna + { value: 'DJF', label: 'DJF' }, // Djiboutian Franc + { value: 'DKK', label: 'DKK' }, // Danish Krone + { value: 'DOP', label: 'DOP' }, // Dominican Peso + { value: 'DZD', label: 'DZD' }, // Algerian Dinar + { value: 'EGP', label: 'EGP' }, // Egyptian Pound + { value: 'ERN', label: 'ERN' }, // Eritrean Nakfa + { value: 'ETB', label: 'ETB' }, // Ethiopian Birr + { value: 'EUR', label: 'EUR' }, // Euro + { value: 'FJD', label: 'FJD' }, // Fijian Dollar + { value: 'FKP', label: 'FKP' }, // Falkland Islands Pound + { value: 'FOK', label: 'FOK' }, // Faroese Krona + { value: 'FRO', label: 'FRO' }, // Fijian Dollar + { value: 'GBP', label: 'GBP' }, // British Pound Sterling + { value: 'GEL', label: 'GEL' }, // Georgian Lari + { value: 'GGP', label: 'GGP' }, // Guernsey Pound + { value: 'GHS', label: 'GHS' }, // Ghanaian Cedi + { value: 'GIP', label: 'GIP' }, // Gibraltar Pound + { value: 'GMD', label: 'GMD' }, // Gambian Dalasi + { value: 'GNF', label: 'GNF' }, // Guinean Franc + { value: 'GTQ', label: 'GTQ' }, // Guatemalan Quetzal + { value: 'GYD', label: 'GYD' }, // Guyanaese Dollar + { value: 'HKD', label: 'HKD' }, // Hong Kong Dollar + { value: 'HNL', label: 'HNL' }, // Honduran Lempira + { value: 'HRK', label: 'HRK' }, // Croatian Kuna + { value: 'HTG', label: 'HTG' }, // Haitian Gourde + { value: 'HUF', label: 'HUF' }, // Hungarian Forint + { value: 'IDR', label: 'IDR' }, // Indonesian Rupiah + { value: 'ILS', label: 'ILS' }, // Israeli New Shekel + { value: 'IMP', label: 'IMP' }, // Manx pound + { value: 'INR', label: 'INR' }, // Indian Rupee + { value: 'IQD', label: 'IQD' }, // Iraqi Dinar + { value: 'IRR', label: 'IRR' }, // Iranian Rial + { value: 'ISK', label: 'ISK' }, // Icelandic Króna + { value: 'JEP', label: 'JEP' }, // Jersey Pound + { value: 'JMD', label: 'JMD' }, // Jamaican Dollar + { value: 'JOD', label: 'JOD' }, // Jordanian Dinar + { value: 'JPY', label: 'JPY' }, // Japanese Yen + { value: 'KES', label: 'KES' }, // Kenyan Shilling + { value: 'KGS', label: 'KGS' }, // Kyrgystani Som + { value: 'KHR', label: 'KHR' }, // Cambodian Riel + { value: 'KID', label: 'KID' }, // Kiribati dollar + { value: 'KMF', label: 'KMF' }, // Comorian Franc + { value: 'KRW', label: 'KRW' }, // South Korean Won + { value: 'KWD', label: 'KWD' }, // Kuwaiti Dinar + { value: 'KYD', label: 'KYD' }, // Cayman Islands Dollar + { value: 'KZT', label: 'KZT' }, // Kazakhstani Tenge + { value: 'LAK', label: 'LAK' }, // Laotian Kip + { value: 'LBP', label: 'LBP' }, // Lebanese Pound + { value: 'LKR', label: 'LKR' }, // Sri Lankan Rupee + { value: 'LRD', label: 'LRD' }, // Liberian Dollar + { value: 'LSL', label: 'LSL' }, // Lesotho Loti + { value: 'LYD', label: 'LYD' }, // Libyan Dinar + { value: 'MAD', label: 'MAD' }, // Moroccan Dirham + { value: 'MDL', label: 'MDL' }, // Moldovan Leu + { value: 'MGA', label: 'MGA' }, // Malagasy Ariary + { value: 'MKD', label: 'MKD' }, // Macedonian Denar + { value: 'MMK', label: 'MMK' }, // Myanma Kyat + { value: 'MNT', label: 'MNT' }, // Mongolian Tugrik + { value: 'MOP', label: 'MOP' }, // Macanese Pataca + { value: 'MRU', label: 'MRU' }, // Mauritanian Ouguiya + { value: 'MUR', label: 'MUR' }, // Mauritian Rupee + { value: 'MVR', label: 'MVR' }, // Maldivian Rufiyaa + { value: 'MWK', label: 'MWK' }, // Malawian Kwacha + { value: 'MXN', label: 'MXN' }, // Mexican Peso + { value: 'MYR', label: 'MYR' }, // Malaysian Ringgit + { value: 'MZN', label: 'MZN' }, // Mozambican Metical + { value: 'NAD', label: 'NAD' }, // Namibian Dollar + { value: 'NGN', label: 'NGN' }, // Nigerian Naira + { value: 'NIO', label: 'NIO' }, // Nicaraguan Córdoba + { value: 'NOK', label: 'NOK' }, // Norwegian Krone + { value: 'NPR', label: 'NPR' }, // Nepalese Rupee + { value: 'NZD', label: 'NZD' }, // New Zealand Dollar + { value: 'OMR', label: 'OMR' }, // Omani Rial + { value: 'PAB', label: 'PAB' }, // Panamanian Balboa + { value: 'PEN', label: 'PEN' }, // Peruvian Nuevo Sol + { value: 'PGK', label: 'PGK' }, // Papua New Guinean Kina + { value: 'PHP', label: 'PHP' }, // Philippine Peso + { value: 'PKR', label: 'PKR' }, // Pakistani Rupee + { value: 'PLN', label: 'PLN' }, // Polish Zloty + { value: 'PYG', label: 'PYG' }, // Paraguayan Guarani + { value: 'QAR', label: 'QAR' }, // Qatari Rial + { value: 'RON', label: 'RON' }, // Romanian Leu + { value: 'RSD', label: 'RSD' }, // Serbian Dinar + { value: 'RUB', label: 'RUB' }, // Russian Ruble + { value: 'RWF', label: 'RWF' }, // Rwandan Franc + { value: 'SAR', label: 'SAR' }, // Saudi Riyal + { value: 'SBD', label: 'SBD' }, // Solomon Islands Dollar + { value: 'SCR', label: 'SCR' }, // Seychellois Rupee + { value: 'SDG', label: 'SDG' }, // Sudanese Pound + { value: 'SEK', label: 'SEK' }, // Swedish Krona + { value: 'SGD', label: 'SGD' }, // Singapore Dollar + { value: 'SHP', label: 'SHP' }, // Saint Helena Pound + { value: 'SLL', label: 'SLL' }, // Sierra Leonean Leone + { value: 'SOS', label: 'SOS' }, // Somali Shilling + { value: 'SPL', label: 'SPL' }, // Seborgan Luigino + { value: 'SRD', label: 'SRD' }, // Surinamese Dollar + { value: 'STN', label: 'STN' }, // São Tomé and Príncipe Dobra + { value: 'SVC', label: 'SVC' }, // Salvadoran Colón + { value: 'SYP', label: 'SYP' }, // Syrian Pound + { value: 'SZL', label: 'SZL' }, // Swazi Lilangeni + { value: 'THB', label: 'THB' }, // Thai Baht + { value: 'TJS', label: 'TJS' }, // Tajikistani Somoni + { value: 'TMT', label: 'TMT' }, // Turkmenistani Manat + { value: 'TND', label: 'TND' }, // Tunisian Dinar + { value: 'TOP', label: 'TOP' }, // Tongan Pa'anga + { value: 'TRY', label: 'TRY' }, // Turkish Lira + { value: 'TTD', label: 'TTD' }, // Trinidad and Tobago Dollar + { value: 'TVD', label: 'TVD' }, // Tuvaluan Dollar + { value: 'TWD', label: 'TWD' }, // New Taiwan Dollar + { value: 'TZS', label: 'TZS' }, // Tanzanian Shilling + { value: 'UAH', label: 'UAH' }, // Ukrainian Hryvnia + { value: 'UGX', label: 'UGX' }, // Ugandan Shilling + { value: 'USD', label: 'USD' }, // United States Dollar + { value: 'UYU', label: 'UYU' }, // Uruguayan Peso + { value: 'UZS', label: 'UZS' }, // Uzbekistan Som + { value: 'VEF', label: 'VEF' }, // Venezuelan Bolívar + { value: 'VND', label: 'VND' }, // Vietnamese Dong + { value: 'VUV', label: 'VUV' }, // Vanuatu Vatu + { value: 'WST', label: 'WST' }, // Samoan Tala + { value: 'XAF', label: 'XAF' }, // CFA Franc BEAC + { value: 'XCD', label: 'XCD' }, // East Caribbean Dollar + { value: 'XDR', label: 'XDR' }, // Special Drawing Rights + { value: 'XOF', label: 'XOF' }, // CFA Franc BCEAO + { value: 'XPF', label: 'XPF' }, // CFP Franc + { value: 'YER', label: 'YER' }, // Yemeni Rial + { value: 'ZAR', label: 'ZAR' }, // South African Rand + { value: 'ZMW', label: 'ZMW' }, // Zambian Kwacha + { value: 'ZWD', label: 'ZWD' }, // Zimbabwean Dollar +]; +export const currencySymbols = { + AED: 'د.إ', // United Arab Emirates Dirham + AFN: '؋', // Afghan Afghani + ALL: 'L', // Albanian Lek + AMD: '֏', // Armenian Dram + ANG: 'ƒ', // Netherlands Antillean Guilder + AOA: 'Kz', // Angolan Kwanza + ARS: '$', // Argentine Peso + AUD: '$', // Australian Dollar + AWG: 'ƒ', // Aruban Florin + AZN: '₼', // Azerbaijani Manat + BAM: 'КМ', // Bosnia-Herzegovina Convertible Mark + BBD: '$', // Barbadian Dollar + BDT: '৳', // Bangladeshi Taka + BGN: 'лв', // Bulgarian Lev + BHD: '.د.ب', // Bahraini Dinar + BIF: 'FBu', // Burundian Franc + BMD: '$', // Bermudian Dollar + BND: '$', // Brunei Dollar + BOB: 'Bs.', // Bolivian Boliviano + BRL: 'R$', // Brazilian Real + BSD: '$', // Bahamian Dollar + BTN: 'Nu.', // Bhutanese Ngultrum + BWP: 'P', // Botswanan Pula + BYN: 'Br', // Belarusian Ruble + BZD: 'BZ$', // Belize Dollar + CAD: '$', // Canadian Dollar + CDF: 'FC', // Congolese Franc + CHF: 'CHF', // Swiss Franc + CLP: '$', // Chilean Peso + CNY: '¥', // Chinese Yuan + COP: '$', // Colombian Peso + CRC: '₡', // Costa Rican Colón + CUP: '₱', // Cuban Peso + CVE: '$', // Cape Verdean Escudo + CZK: 'Kč', // Czech Koruna + DJF: 'Fdj', // Djiboutian Franc + DKK: 'kr', // Danish Krone + DOP: 'RD$', // Dominican Peso + DZD: 'د.ج', // Algerian Dinar + EGP: 'ج.م', // Egyptian Pound + ERN: 'Nfk', // Eritrean Nakfa + ETB: 'ብር', // Ethiopian Birr + EUR: '€', // Euro + FJD: 'FJ$', // Fijian Dollar + FKP: '£', // Falkland Islands Pound + FOK: 'kr', // Faroese Krona + FRO: 'kr', // Fijian Dollar + GBP: '£', // British Pound Sterling + GEL: '₾', // Georgian Lari + GGP: '£', // Guernsey Pound + GHS: '₵', // Ghanaian Cedi + GIP: '£', // Gibraltar Pound + GMD: 'D', // Gambian Dalasi + GNF: 'FG', // Guinean Franc + GTQ: 'Q', // Guatemalan Quetzal + GYD: '$', // Guyanaese Dollar + HKD: '$', // Hong Kong Dollar + HNL: 'L', // Honduran Lempira + HRK: 'kn', // Croatian Kuna + HTG: 'G', // Haitian Gourde + HUF: 'Ft', // Hungarian Forint + IDR: 'Rp', // Indonesian Rupiah + ILS: '₪', // Israeli New Shekel + IMP: '£', // Manx pound + INR: '₹', // Indian Rupee + IQD: 'د.ع', // Iraqi Dinar + IRR: '﷼', // Iranian Rial + ISK: 'kr', // Icelandic Króna + JEP: '£', // Jersey Pound + JMD: 'J$', // Jamaican Dollar + JOD: 'د.ا', // Jordanian Dinar + JPY: '¥', // Japanese Yen + KES: 'KSh', // Kenyan Shilling + KGS: 'с', // Kyrgystani Som + KHR: '៛', // Cambodian Riel + KID: '$', // Kiribati dollar + KMF: 'CF', // Comorian Franc + KRW: '₩', // South Korean Won + KWD: 'د.ك', // Kuwaiti Dinar + KYD: '$', // Cayman Islands Dollar + KZT: '₸', // Kazakhstani Tenge + LAK: '₭', // Laotian Kip + LBP: 'ل.ل', // Lebanese Pound + LKR: 'රු', // Sri Lankan Rupee + LRD: '$', // Liberian Dollar + LSL: 'L', // Lesotho Loti + LYD: 'ل.د', // Libyan Dinar + MAD: 'د.م.', // Moroccan Dirham + MDL: 'L', // Moldovan Leu + MGA: 'Ar', // Malagasy Ariary + MKD: 'ден', // Macedonian Denar + MMK: 'K', // Myanma Kyat + MNT: '₮', // Mongolian Tugrik + MOP: 'MOP$', // Macanese Pataca + MRU: 'UM', // Mauritanian Ouguiya + MUR: '₨', // Mauritian Rupee + MVR: 'ރ.', // Maldivian Rufiyaa + MWK: 'MK', // Malawian Kwacha + MXN: '$', // Mexican Peso + MYR: 'RM', // Malaysian Ringgit + MZN: 'MT', // Mozambican Metical + NAD: '$', // Namibian Dollar + NGN: '₦', // Nigerian Naira + NIO: 'C$', // Nicaraguan Córdoba + NOK: 'kr', // Norwegian Krone + NPR: '₨', // Nepalese Rupee + NZD: '$', // New Zealand Dollar + OMR: 'ر.ع.', // Omani Rial + PAB: 'B/.', // Panamanian Balboa + PEN: 'S/', // Peruvian Nuevo Sol + PGK: 'K', // Papua New Guinean Kina + PHP: '₱', // Philippine Peso + PKR: '₨', // Pakistani Rupee + PLN: 'zł', // Polish Zloty + PYG: '₲', // Paraguayan Guarani + QAR: 'ر.ق', // Qatari Rial + RON: 'lei', // Romanian Leu + RSD: 'дин', // Serbian Dinar + RUB: '₽', // Russian Ruble + RWF: 'RF', // Rwandan Franc + SAR: 'ر.س', // Saudi Riyal + SBD: '$', // Solomon Islands Dollar + SCR: 'SR', // Seychellois Rupee + SDG: 'ج.س.', // Sudanese Pound + SEK: 'kr', // Swedish Krona + SGD: '$', // Singapore Dollar + SHP: '£', // Saint Helena Pound + SLL: 'Le', // Sierra Leonean Leone + SOS: 'Sh', // Somali Shilling + SPL: 'L', // Seborgan Luigino + SRD: '$', // Surinamese Dollar + STN: 'Db', // São Tomé and Príncipe Dobra + SVC: '₡', // Salvadoran Colón + SYP: '£S', // Syrian Pound + SZL: 'E', // Swazi Lilangeni + THB: '฿', // Thai Baht + TJS: 'ЅМ', // Tajikistani Somoni + TMT: 'T', // Turkmenistani Manat + TND: 'د.ت', // Tunisian Dinar + TOP: 'T$', // Tongan Pa'anga + TRY: '₺', // Turkish Lira + TTD: 'TT$', // Trinidad and Tobago Dollar + TVD: '$', // Tuvaluan Dollar + TWD: 'NT$', // New Taiwan Dollar + TZS: 'TSh', // Tanzanian Shilling + UAH: '₴', // Ukrainian Hryvnia + UGX: 'USh', // Ugandan Shilling + USD: '$', // United States Dollar + UYU: '$U', // Uruguayan Peso + UZS: 'UZS', // Uzbekistan Som + VEF: 'Bs.', // Venezuelan Bolívar + VND: '₫', // Vietnamese Dong + VUV: 'VT', // Vanuatu Vatu + WST: 'WS$', // Samoan Tala + XAF: 'FCFA', // CFA Franc BEAC + XCD: 'EC$', // East Caribbean Dollar + XDR: 'SDR', // Special Drawing Rights + XOF: 'CFA', // CFA Franc BCEAO + XPF: 'CFP', // CFP Franc + YER: '﷼', // Yemeni Rial + ZAR: 'R', // South African Rand + ZMW: 'ZK', // Zambian Kwacha + ZWD: 'Z$', // Zimbabwean Dollar +}; diff --git a/src/utils/debounce.ts b/src/utils/debounce.ts deleted file mode 100644 index 8388364ad2..0000000000 --- a/src/utils/debounce.ts +++ /dev/null @@ -1,9 +0,0 @@ -const debounce = (fn: any, ms = 600): any => { - let timeoutId: ReturnType; - return function (this: any, ...args: any[]): any { - clearTimeout(timeoutId); - timeoutId = setTimeout(() => fn.apply(this, args), ms); - }; -}; - -export default debounce; diff --git a/src/utils/errorHandler.tsx b/src/utils/errorHandler.tsx index 4ec1fb4ccb..508284db5a 100644 --- a/src/utils/errorHandler.tsx +++ b/src/utils/errorHandler.tsx @@ -7,7 +7,7 @@ import { toast } from 'react-toastify'; */ export const errorHandler = ( t: TFunction<'translation', string>, - error: any + error: any, ): void => { if (error?.message === 'Failed to fetch') { toast.error(t('talawaApiUnavailable')); diff --git a/src/utils/fieldTypes.ts b/src/utils/fieldTypes.ts new file mode 100644 index 0000000000..b17fb9833a --- /dev/null +++ b/src/utils/fieldTypes.ts @@ -0,0 +1,3 @@ +const availableFieldTypes = ['String', 'Boolean', 'Date', 'Number']; + +export default availableFieldTypes; diff --git a/src/utils/formEnumFields.ts b/src/utils/formEnumFields.ts new file mode 100644 index 0000000000..928537aaab --- /dev/null +++ b/src/utils/formEnumFields.ts @@ -0,0 +1,352 @@ +const countryOptions = [ + { value: 'af', label: 'Afghanistan' }, + { value: 'al', label: 'Albania' }, + { value: 'dz', label: 'Algeria' }, + { value: 'ad', label: 'Andorra' }, + { value: 'ao', label: 'Angola' }, + { value: 'ai', label: 'Anguilla' }, + { value: 'ag', label: 'Antigua and Barbuda' }, + { value: 'ar', label: 'Argentina' }, + { value: 'am', label: 'Armenia' }, + { value: 'aw', label: 'Aruba' }, + { value: 'au', label: 'Australia' }, + { value: 'at', label: 'Austria' }, + { value: 'az', label: 'Azerbaijan' }, + { value: 'bs', label: 'Bahamas' }, + { value: 'bh', label: 'Bahrain' }, + { value: 'bd', label: 'Bangladesh' }, + { value: 'bb', label: 'Barbados' }, + { value: 'by', label: 'Belarus' }, + { value: 'be', label: 'Belgium' }, + { value: 'bz', label: 'Belize' }, + { value: 'bj', label: 'Benin' }, + { value: 'bm', label: 'Bermuda' }, + { value: 'bt', label: 'Bhutan' }, + { value: 'bo', label: 'Bolivia' }, + { value: 'ba', label: 'Bosnia and Herzegovina' }, + { value: 'bw', label: 'Botswana' }, + { value: 'br', label: 'Brazil' }, + { value: 'bn', label: 'Brunei' }, + { value: 'bg', label: 'Bulgaria' }, + { value: 'bf', label: 'Burkina Faso' }, + { value: 'bi', label: 'Burundi' }, + { value: 'cv', label: 'Cabo Verde' }, + { value: 'kh', label: 'Cambodia' }, + { value: 'cm', label: 'Cameroon' }, + { value: 'ca', label: 'Canada' }, + { value: 'ky', label: 'Cayman Islands' }, + { value: 'cf', label: 'Central African Republic' }, + { value: 'td', label: 'Chad' }, + { value: 'cl', label: 'Chile' }, + { value: 'cn', label: 'China' }, + { value: 'co', label: 'Colombia' }, + { value: 'km', label: 'Comoros' }, + { value: 'cg', label: 'Congo' }, + { value: 'cr', label: 'Costa Rica' }, + { value: 'hr', label: 'Croatia' }, + { value: 'cu', label: 'Cuba' }, + { value: 'cy', label: 'Cyprus' }, + { value: 'cz', label: 'Czechia' }, + { value: 'dk', label: 'Denmark' }, + { value: 'dj', label: 'Djibouti' }, + { value: 'dm', label: 'Dominica' }, + { value: 'do', label: 'Dominican Republic' }, + { value: 'ec', label: 'Ecuador' }, + { value: 'eg', label: 'Egypt' }, + { value: 'sv', label: 'El Salvador' }, + { value: 'gq', label: 'Equatorial Guinea' }, + { value: 'er', label: 'Eritrea' }, + { value: 'ee', label: 'Estonia' }, + { value: 'et', label: 'Ethiopia' }, + { value: 'fj', label: 'Fiji' }, + { value: 'fi', label: 'Finland' }, + { value: 'fr', label: 'France' }, + { value: 'ga', label: 'Gabon' }, + { value: 'gm', label: 'Gambia' }, + { value: 'ge', label: 'Georgia' }, + { value: 'de', label: 'Germany' }, + { value: 'gh', label: 'Ghana' }, + { value: 'gi', label: 'Gibraltar' }, + { value: 'gr', label: 'Greece' }, + { value: 'gl', label: 'Greenland' }, + { value: 'gd', label: 'Grenada' }, + { value: 'gt', label: 'Guatemala' }, + { value: 'gn', label: 'Guinea' }, + { value: 'gw', label: 'Guinea-Bissau' }, + { value: 'gy', label: 'Guyana' }, + { value: 'ht', label: 'Haiti' }, + { value: 'hn', label: 'Honduras' }, + { value: 'hu', label: 'Hungary' }, + { value: 'is', label: 'Iceland' }, + { value: 'in', label: 'India' }, + { value: 'id', label: 'Indonesia' }, + { value: 'ir', label: 'Iran' }, + { value: 'iq', label: 'Iraq' }, + { value: 'ie', label: 'Ireland' }, + { value: 'il', label: 'Israel' }, + { value: 'it', label: 'Italy' }, + { value: 'jm', label: 'Jamaica' }, + { value: 'jp', label: 'Japan' }, + { value: 'jo', label: 'Jordan' }, + { value: 'kz', label: 'Kazakhstan' }, + { value: 'ke', label: 'Kenya' }, + { value: 'ki', label: 'Kiribati' }, + { value: 'kw', label: 'Kuwait' }, + { value: 'kg', label: 'Kyrgyzstan' }, + { value: 'la', label: 'Laos' }, + { value: 'lv', label: 'Latvia' }, + { value: 'lb', label: 'Lebanon' }, + { value: 'ls', label: 'Lesotho' }, + { value: 'lr', label: 'Liberia' }, + { value: 'ly', label: 'Libya' }, + { value: 'li', label: 'Liechtenstein' }, + { value: 'lt', label: 'Lithuania' }, + { value: 'lu', label: 'Luxembourg' }, + { value: 'mk', label: 'North Macedonia' }, + { value: 'mg', label: 'Madagascar' }, + { value: 'mw', label: 'Malawi' }, + { value: 'my', label: 'Malaysia' }, + { value: 'mv', label: 'Maldives' }, + { value: 'ml', label: 'Mali' }, + { value: 'mt', label: 'Malta' }, + { value: 'mh', label: 'Marshall Islands' }, + { value: 'mr', label: 'Mauritania' }, + { value: 'mu', label: 'Mauritius' }, + { value: 'mx', label: 'Mexico' }, + { value: 'fm', label: 'Micronesia' }, + { value: 'md', label: 'Moldova' }, + { value: 'mc', label: 'Monaco' }, + { value: 'mn', label: 'Mongolia' }, + { value: 'me', label: 'Montenegro' }, + { value: 'ma', label: 'Morocco' }, + { value: 'mz', label: 'Mozambique' }, + { value: 'mm', label: 'Myanmar' }, + { value: 'na', label: 'Namibia' }, + { value: 'nr', label: 'Nauru' }, + { value: 'np', label: 'Nepal' }, + { value: 'nl', label: 'Netherlands' }, + { value: 'nz', label: 'New Zealand' }, + { value: 'ni', label: 'Nicaragua' }, + { value: 'ne', label: 'Niger' }, + { value: 'ng', label: 'Nigeria' }, + { value: 'kp', label: 'North Korea' }, + { value: 'no', label: 'Norway' }, + { value: 'om', label: 'Oman' }, + { value: 'pk', label: 'Pakistan' }, + { value: 'pw', label: 'Palau' }, + { value: 'pa', label: 'Panama' }, + { value: 'pg', label: 'Papua New Guinea' }, + { value: 'py', label: 'Paraguay' }, + { value: 'pe', label: 'Peru' }, + { value: 'ph', label: 'Philippines' }, + { value: 'pl', label: 'Poland' }, + { value: 'pt', label: 'Portugal' }, + { value: 'qa', label: 'Qatar' }, + { value: 'ro', label: 'Romania' }, + { value: 'ru', label: 'Russia' }, + { value: 'rw', label: 'Rwanda' }, + { value: 'lc', label: 'Saint Lucia' }, + { value: 'vc', label: 'Saint Vincent and the Grenadines' }, + { value: 'ws', label: 'Samoa' }, + { value: 'sm', label: 'San Marino' }, + { value: 'st', label: 'Sao Tome and Principe' }, + { value: 'sa', label: 'Saudi Arabia' }, + { value: 'sn', label: 'Senegal' }, + { value: 'rs', label: 'Serbia' }, + { value: 'sc', label: 'Seychelles' }, + { value: 'sl', label: 'Sierra Leone' }, + { value: 'sg', label: 'Singapore' }, + { value: 'sk', label: 'Slovakia' }, + { value: 'si', label: 'Slovenia' }, + { value: 'sb', label: 'Solomon Islands' }, + { value: 'so', label: 'Somalia' }, + { value: 'za', label: 'South Africa' }, + { value: 'kr', label: 'South Korea' }, + { value: 'ss', label: 'South Sudan' }, + { value: 'es', label: 'Spain' }, + { value: 'lk', label: 'Sri Lanka' }, + { value: 'sd', label: 'Sudan' }, + { value: 'sr', label: 'Suriname' }, + { value: 'sz', label: 'Eswatini' }, + { value: 'se', label: 'Sweden' }, + { value: 'ch', label: 'Switzerland' }, + { value: 'sy', label: 'Syria' }, + { value: 'tw', label: 'Taiwan' }, + { value: 'tj', label: 'Tajikistan' }, + { value: 'tz', label: 'Tanzania' }, + { value: 'th', label: 'Thailand' }, + { value: 'tl', label: 'Timor-Leste' }, + { value: 'tg', label: 'Togo' }, + { value: 'to', label: 'Tonga' }, + { value: 'tt', label: 'Trinidad and Tobago' }, + { value: 'tn', label: 'Tunisia' }, + { value: 'tr', label: 'Turkey' }, + { value: 'tm', label: 'Turkmenistan' }, + { value: 'tv', label: 'Tuvalu' }, + { value: 'ug', label: 'Uganda' }, + { value: 'ua', label: 'Ukraine' }, + { value: 'ae', label: 'United Arab Emirates' }, + { value: 'gb', label: 'United Kingdom' }, + { value: 'us', label: 'United States' }, + { value: 'uy', label: 'Uruguay' }, + { value: 'uz', label: 'Uzbekistan' }, + { value: 'vu', label: 'Vanuatu' }, + { value: 'va', label: 'Vatican City' }, + { value: 've', label: 'Venezuela' }, + { value: 'vn', label: 'Vietnam' }, + { value: 'ye', label: 'Yemen' }, + { value: 'zm', label: 'Zambia' }, + { value: 'zw', label: 'Zimbabwe' }, +]; + +const educationGradeEnum = [ + { + value: 'NO_GRADE', + label: 'noGrade', + }, + { + value: 'PRE_KG', + label: 'preKg', + }, + { + value: 'KG', + label: 'kg', + }, + { + value: 'GRADE_1', + label: 'grade1', + }, + { + value: 'GRADE_2', + label: 'grade2', + }, + { + value: 'GRADE_3', + label: 'grade3', + }, + { + value: 'GRADE_4', + label: 'grade4', + }, + { + value: 'GRADE_5', + label: 'grade5', + }, + { + value: 'GRADE_6', + label: 'grade6', + }, + { + value: 'GRADE_7', + label: 'grade7', + }, + { + value: 'GRADE_8', + label: 'grade8', + }, + { + value: 'GRADE_9', + label: 'grade9', + }, + { + value: 'GRADE_10', + label: 'grade10', + }, + { + value: 'GRADE_11', + label: 'grade11', + }, + { + value: 'GRADE_12', + label: 'grade12', + }, + { + value: 'GRADUATE', + label: 'graduate', + }, +]; + +const maritalStatusEnum = [ + { + value: 'SINGLE', + label: 'single', + }, + { + value: 'ENGAGED', + label: 'engaged', + }, + { + value: 'MARRIED', + label: 'married', + }, + { + value: 'DIVORCED', + label: 'divorced', + }, + { + value: 'WIDOWED', + label: 'widowed', + }, + { + value: 'SEPARATED', + label: 'separated', + }, +]; + +const genderEnum = [ + { + value: 'MALE', + label: 'male', + }, + { + value: 'FEMALE', + label: 'female', + }, + { + value: 'OTHER', + label: 'other', + }, +]; + +const employmentStatusEnum = [ + { + value: 'FULL_TIME', + label: 'fullTime', + }, + { + value: 'PART_TIME', + label: 'partTime', + }, + { + value: 'UNEMPLOYED', + label: 'unemployed', + }, +]; + +const userRoleEnum = [ + { + value: 'USER', + label: 'User', + }, + { + value: 'ADMIN', + label: 'Admin', + }, + { + value: 'SUPERADMIN', + label: 'Super Admin', + }, + { + value: 'NON_USER', + label: 'Non-User', + }, +]; + +export { + countryOptions, + educationGradeEnum, + maritalStatusEnum, + genderEnum, + employmentStatusEnum, + userRoleEnum, +}; diff --git a/src/utils/getOrganizationId.ts b/src/utils/getOrganizationId.ts index cee92613ab..0a7c283e39 100644 --- a/src/utils/getOrganizationId.ts +++ b/src/utils/getOrganizationId.ts @@ -1,8 +1,8 @@ /* istanbul ignore next */ const getOrganizationId = (url: string): string => { - const id = url.split('=')[1]; + const id = url?.split('=')[1]; - return id.split('#')[0]; + return id?.split('#')[0]; }; export default getOrganizationId; diff --git a/src/utils/getRefreshToken.test.ts b/src/utils/getRefreshToken.test.ts index 12d8448b76..58de898a66 100644 --- a/src/utils/getRefreshToken.test.ts +++ b/src/utils/getRefreshToken.test.ts @@ -1,3 +1,4 @@ +// SKIP_LOCALSTORAGE_CHECK import { refreshToken } from './getRefreshToken'; jest.mock('@apollo/client', () => { @@ -15,7 +16,7 @@ jest.mock('@apollo/client', () => { refreshToken: 'newRefreshToken', }, }, - }) + }), ), })), }; @@ -28,6 +29,7 @@ describe('refreshToken', () => { global.window.location = { ...location, reload: jest.fn() }; // Mock localStorage.setItem() and localStorage.clear() + Storage.prototype.setItem = jest.fn(); Storage.prototype.clear = jest.fn(); @@ -39,12 +41,12 @@ describe('refreshToken', () => { const result = await refreshToken(); expect(localStorage.setItem).toHaveBeenCalledWith( - 'token', - 'newAccessToken' + 'Talawa-admin_token', + JSON.stringify('newAccessToken'), ); expect(localStorage.setItem).toHaveBeenCalledWith( - 'refreshToken', - 'newRefreshToken' + 'Talawa-admin_refreshToken', + JSON.stringify('newRefreshToken'), ); expect(result).toBe(true); expect(window.location.reload).toHaveBeenCalled(); diff --git a/src/utils/getRefreshToken.ts b/src/utils/getRefreshToken.ts index f3145c4b48..5d6f8aa2ce 100644 --- a/src/utils/getRefreshToken.ts +++ b/src/utils/getRefreshToken.ts @@ -1,6 +1,7 @@ import { ApolloClient, InMemoryCache, HttpLink } from '@apollo/client'; import { BACKEND_URL } from 'Constant/constant'; import { REFRESH_TOKEN_MUTATION } from 'GraphQl/Mutations/mutations'; +import useLocalStorage from './useLocalstorage'; export async function refreshToken(): Promise { const client = new ApolloClient({ @@ -10,7 +11,9 @@ export async function refreshToken(): Promise { cache: new InMemoryCache(), }); - const refreshToken = localStorage.getItem('refreshToken'); + const { getItem, setItem } = useLocalStorage(); + + const refreshToken = getItem('refreshToken'); /* istanbul ignore next */ try { const { data } = await client.mutate({ @@ -20,8 +23,9 @@ export async function refreshToken(): Promise { }, }); - localStorage.setItem('token', data.refreshToken.accessToken); - localStorage.setItem('refreshToken', data.refreshToken.refreshToken); + setItem('token', data.refreshToken.accessToken); + setItem('refreshToken', data.refreshToken.refreshToken); + window.location.reload(); return true; } catch (error) { diff --git a/src/utils/interfaces.ts b/src/utils/interfaces.ts index e90711028f..77256976a7 100644 --- a/src/utils/interfaces.ts +++ b/src/utils/interfaces.ts @@ -4,15 +4,75 @@ export interface InterfaceUserType { lastName: string; image: string | null; email: string; - userType: string; - adminFor: { - _id: string; - name: string; - image: string | null; - }[]; }; } +export interface InterfaceActionItemCategoryInfo { + _id: string; + name: string; + isDisabled: boolean; +} + +export interface InterfaceActionItemCategoryList { + actionItemCategoriesByOrganization: InterfaceActionItemCategoryInfo[]; +} + +export interface InterfaceActionItemInfo { + _id: string; + assignee: { + _id: string; + firstName: string; + lastName: string; + }; + assigner: { + _id: string; + firstName: string; + lastName: string; + }; + actionItemCategory: { + _id: string; + name: string; + }; + preCompletionNotes: string; + postCompletionNotes: string; + assignmentDate: Date; + dueDate: Date; + completionDate: Date; + isCompleted: boolean; + event: { + _id: string; + title: string; + }; + creator: { + _id: string; + firstName: string; + lastName: string; + }; +} + +export interface InterfaceActionItemList { + actionItemsByOrganization: InterfaceActionItemInfo[]; +} + +export interface InterfaceMembersList { + organizations: { + _id: string; + members: InterfaceMemberInfo[]; + }[]; +} + +export interface InterfaceMemberInfo { + _id: string; + firstName: string; + lastName: string; + email: string; + image: string; + createdAt: string; + organizationsBlockedBy: { + _id: string; + }[]; +} + export interface InterfaceOrgConnectionInfoType { _id: string; image: string | null; @@ -29,7 +89,7 @@ export interface InterfaceOrgConnectionInfoType { _id: string; }[]; createdAt: string; - location: string; + address: InterfaceAddress; } export interface InterfaceOrgConnectionType { organizationsConnection: InterfaceOrgConnectionInfoType[]; @@ -45,8 +105,8 @@ export interface InterfaceQueryOrganizationsListObject { }; name: string; description: string; - location: string; - isPublic: boolean; + address: InterfaceAddress; + userRegistrationRequired: boolean; visibleInSearch: boolean; members: { _id: string; @@ -59,6 +119,7 @@ export interface InterfaceQueryOrganizationsListObject { firstName: string; lastName: string; email: string; + createdAt: string; }[]; membershipRequests: { _id: string; @@ -75,19 +136,143 @@ export interface InterfaceQueryOrganizationsListObject { email: string; }[]; } - +export interface InterfacePostForm { + posttitle: string; + postinfo: string; + postphoto: string | null; + postvideo: string | null; + pinned: boolean; +} export interface InterfaceQueryOrganizationPostListItem { + posts: { + edges: { + node: { + _id: string; + title: string; + text: string; + imageUrl: string | null; + videoUrl: string | null; + creator: { + _id: string; + firstName: string; + lastName: string; + email: string; + }; + createdAt: string; + likeCount: number; + commentCount: number; + pinned: boolean; + + likedBy: { _id: string }[]; + comments: { + _id: string; + text: string; + creator: { _id: string }; + createdAt: string; + likeCount: number; + likedBy: { _id: string }[]; + }[]; + }; + cursor: string; + }[]; + pageInfo: { + startCursor: string; + endCursor: string; + hasNextPage: boolean; + hasPreviousPage: boolean; + }; + totalCount: number; + }; +} + +export interface InterfaceQueryOrganizationAdvertisementListItem { + advertisements: { + edges: { + node: { + _id: string; + name: string; + mediaUrl: string; + endDate: string; + startDate: string; + type: 'BANNER' | 'MENU' | 'POPUP'; + }; + cursor: string; + }[]; + pageInfo: { + startCursor: string; + endCursor: string; + hasNextPage: boolean; + hasPreviousPage: boolean; + }; + totalCount: number; + }; +} +export interface InterfaceQueryOrganizationFunds { + fundsByOrganization: { + _id: string; + name: string; + refrenceNumber: string; + taxDeductible: boolean; + isArchived: boolean; + isDefault: boolean; + createdAt: string; + organizationId: string; + creator: { _id: string; firstName: string; lastName: string }; + }[]; +} +export interface InterfaceQueryOrganizationFundCampaigns { + campaigns: { + _id: string; + name: string; + fundingGoal: number; + startDate: Date; + endDate: Date; + createdAt: string; + currency: string; + }[]; +} +export interface InterfaceQueryFundCampaignsPledges { + startDate: Date; + endDate: Date; + pledges: { + _id: string; + amount: number; + currency: string; + endDate: string; + startDate: string; + users: { + _id: string; + firstName: string; + }[]; + }[]; +} +export interface InterfaceFundInfo { _id: string; - title: string; - text: string; - imageUrl: null; - videoUrl: null; + name: string; + refrenceNumber: string; + taxDeductible: boolean; + isArchived: boolean; + isDefault: boolean; createdAt: string; - creator: { +} +export interface InterfaceCampaignInfo { + _id: string; + name: string; + fundingGoal: number; + startDate: Date; + endDate: Date; + createdAt: string; + currency: string; +} +export interface InterfacePledgeInfo { + _id: string; + amount: number; + currency: string; + endDate: string; + startDate: string; + users: { _id: string; firstName: string; - lastName: string; - email: string; }[]; } export interface InterfaceQueryOrganizationEventListItem { @@ -116,52 +301,137 @@ export interface InterfaceQueryBlockPageMemberListItem { } export interface InterfaceQueryUserListItem { - _id: string; - firstName: string; - lastName: string; - image: string | null; - email: string; - userType: string; - adminFor: { _id: string }[]; - adminApproved: boolean; - organizationsBlockedBy: { + user: { _id: string; - name: string; - location: string; + firstName: string; + lastName: string; image: string | null; - createdAt: string; - creator: { + email: string; + organizationsBlockedBy: { _id: string; - firstName: string; - lastName: string; - email: string; + name: string; image: string | null; - }; - }[]; - joinedOrganizations: { - _id: string; - name: string; - location: string; - image: string | null; + address: InterfaceAddress; + creator: { + _id: string; + firstName: string; + lastName: string; + email: string; + image: string | null; + }; + createdAt: string; + }[]; + joinedOrganizations: { + _id: string; + name: string; + address: InterfaceAddress; + image: string | null; + createdAt: string; + creator: { + _id: string; + firstName: string; + lastName: string; + email: string; + image: string | null; + }; + }[]; createdAt: string; + registeredEvents: { _id: string }[]; + membershipRequests: { _id: string }[]; + }; + appUserProfile: { + _id: string; + adminFor: { _id: string }[]; + isSuperAdmin: boolean; + createdOrganizations: { _id: string }[]; + createdEvents: { _id: string }[]; + eventAdmin: { _id: string }[]; + }; +} + +export interface InterfaceQueryVenueListItem { + _id: string; + name: string; + description: string | null; + image: string | null; + capacity: string; +} + +export interface InterfaceAddress { + city: string; + countryCode: string; + dependentLocality: string; + line1: string; + line2: string; + postalCode: string; + sortingCode: string; + state: string; +} +export interface InterfaceCreateFund { + fundName: string; + fundRef: string; +} + +export interface InterfacePostCard { + id: string; + creator: { + firstName: string; + lastName: string; + email: string; + id: string; + }; + image: string | null; + video: string | null; + text: string; + title: string; + likeCount: number; + commentCount: number; + comments: { + id: string; creator: { _id: string; firstName: string; lastName: string; email: string; - image: string | null; }; + likeCount: number; + likedBy: { + id: string; + }[]; + text: string; }[]; - createdAt: string; + likedBy: { + firstName: string; + lastName: string; + id: string; + }[]; +} +export interface InterfaceCreateCampaign { + campaignName: string; + campaignCurrency: string; + campaignGoal: number; + campaignStartDate: Date; + campaignEndDate: Date; } -export interface InterfaceQueryRequestListItem { - _id: string; - firstName: string; - lastName: string; - image: string; - email: string; - userType: string; - adminApproved: boolean; - createdAt: string; +export interface InterfaceCreatePledge { + pledgeAmount: number; + pledgeCurrency: string; + pledgeStartDate: Date; + pledgeEndDate: Date; +} + +export interface InterfaceQueryMembershipRequestsListItem { + organizations: { + _id: string; + membershipRequests: { + _id: string; + user: { + _id: string; + firstName: string; + lastName: string; + email: string; + }; + }[]; + }[]; } diff --git a/src/utils/linkValid.test.tsx b/src/utils/linkValid.test.tsx new file mode 100644 index 0000000000..0cf8a9785b --- /dev/null +++ b/src/utils/linkValid.test.tsx @@ -0,0 +1,15 @@ +import { isValidLink } from './linkValidator'; + +describe('Testing link validator', () => { + it('returns true for a valid link', () => { + const validLink = 'https://www.example.com'; + const result = isValidLink(validLink); + expect(result).toBe(true); + }); + + it('returns false for an invalid link', () => { + const invalidLink = 'not a valid link'; + const result = isValidLink(invalidLink); + expect(result).toBe(false); + }); +}); diff --git a/src/utils/linkValidator.ts b/src/utils/linkValidator.ts new file mode 100644 index 0000000000..fac4766a3b --- /dev/null +++ b/src/utils/linkValidator.ts @@ -0,0 +1,8 @@ +export const isValidLink = (link: string): boolean => { + try { + new URL(link); + return true; + } catch (error) { + return false; + } +}; diff --git a/src/utils/recurrenceUtils/index.ts b/src/utils/recurrenceUtils/index.ts new file mode 100644 index 0000000000..9b376fc83d --- /dev/null +++ b/src/utils/recurrenceUtils/index.ts @@ -0,0 +1,3 @@ +export * from './recurrenceTypes'; +export * from './recurrenceConstants'; +export * from './recurrenceUtilityFunctions'; diff --git a/src/utils/recurrenceUtils/recurrenceConstants.ts b/src/utils/recurrenceUtils/recurrenceConstants.ts new file mode 100644 index 0000000000..0b2dd68b4f --- /dev/null +++ b/src/utils/recurrenceUtils/recurrenceConstants.ts @@ -0,0 +1,87 @@ +/* + Recurrence constants +*/ + +import { + Frequency, + RecurrenceEndOption, + RecurringEventMutationType, + WeekDays, +} from './recurrenceTypes'; + +// recurrence frequency mapping +export const frequencies = { + [Frequency.DAILY]: 'Day', + [Frequency.WEEKLY]: 'Week', + [Frequency.MONTHLY]: 'Month', + [Frequency.YEARLY]: 'Year', +}; + +// recurrence days options to select from in the UI +export const daysOptions = ['S', 'M', 'T', 'W', 'T', 'F', 'S']; + +// recurrence days array +export const Days = [ + WeekDays.SUNDAY, + WeekDays.MONDAY, + WeekDays.TUESDAY, + WeekDays.WEDNESDAY, + WeekDays.THURSDAY, + WeekDays.FRIDAY, + WeekDays.SATURDAY, +]; + +// constants for recurrence end options +export const endsNever = RecurrenceEndOption.never; +export const endsOn = RecurrenceEndOption.on; +export const endsAfter = RecurrenceEndOption.after; + +// recurrence end options array +export const recurrenceEndOptions = [endsNever, endsOn, endsAfter]; + +// different types of updations / deletions on recurring events +export const thisInstance = RecurringEventMutationType.thisInstance; +export const thisAndFollowingInstances = + RecurringEventMutationType.thisAndFollowingInstances; +export const allInstances = RecurringEventMutationType.allInstances; + +export const recurringEventMutationOptions = [ + thisInstance, + thisAndFollowingInstances, + allInstances, +]; + +// array of week days containing 'MO' to 'FR +export const mondayToFriday = Days.filter( + (day) => day !== WeekDays.SATURDAY && day !== WeekDays.SUNDAY, +); + +// names of week days +export const dayNames = { + [WeekDays.SUNDAY]: 'Sunday', + [WeekDays.MONDAY]: 'Monday', + [WeekDays.TUESDAY]: 'Tuesday', + [WeekDays.WEDNESDAY]: 'Wednesday', + [WeekDays.THURSDAY]: 'Thursday', + [WeekDays.FRIDAY]: 'Friday', + [WeekDays.SATURDAY]: 'Saturday', +}; + +// names of months +export const monthNames = [ + 'January', + 'February', + 'March', + 'April', + 'May', + 'June', + 'July', + 'August', + 'September', + 'October', + 'November', + 'December', +]; + +// week day's occurences in month +export const weekDayOccurences = ['First', 'Second', 'Third', 'Fourth', 'Last']; diff --git a/src/utils/recurrenceUtils/recurrenceTypes.ts b/src/utils/recurrenceUtils/recurrenceTypes.ts new file mode 100644 index 0000000000..684c98ad87 --- /dev/null +++ b/src/utils/recurrenceUtils/recurrenceTypes.ts @@ -0,0 +1,59 @@ +/* + Recurrence types +*/ + +// interface for the recurrenceRuleStateData that would be sent to the backend +export interface InterfaceRecurrenceRuleState { + recurrenceStartDate: Date; + recurrenceEndDate: Date | null; + frequency: Frequency; + weekDays: WeekDays[]; + interval: number; + count: number | undefined; + weekDayOccurenceInMonth: number | undefined; +} + +// interface for the RecurrenceRule document that would be fetched from the backend +export interface InterfaceRecurrenceRule { + recurrenceStartDate: string; + recurrenceEndDate: string | null; + frequency: Frequency; + weekDays: WeekDays[]; + interval: number; + count: number | null; + weekDayOccurenceInMonth: number | null; +} + +// recurrence frequency +export enum Frequency { + DAILY = 'DAILY', + WEEKLY = 'WEEKLY', + MONTHLY = 'MONTHLY', + YEARLY = 'YEARLY', +} + +// recurrence week days +export enum WeekDays { + SUNDAY = 'SUNDAY', + MONDAY = 'MONDAY', + TUESDAY = 'TUESDAY', + WEDNESDAY = 'WEDNESDAY', + THURSDAY = 'THURSDAY', + FRIDAY = 'FRIDAY', + SATURDAY = 'SATURDAY', +} + +// recurrence end options +// i.e. whether it 'never' ends, ends 'on' a certain date, or 'after' a certain number of occurences +export enum RecurrenceEndOption { + never = 'never', + on = 'on', + after = 'after', +} + +// update / delete options of recurring events +export enum RecurringEventMutationType { + thisInstance = 'thisInstance', + thisAndFollowingInstances = 'thisAndFollowingInstances', + allInstances = 'allInstances', +} diff --git a/src/utils/recurrenceUtils/recurrenceUtilityFunctions.ts b/src/utils/recurrenceUtils/recurrenceUtilityFunctions.ts new file mode 100644 index 0000000000..d316174042 --- /dev/null +++ b/src/utils/recurrenceUtils/recurrenceUtilityFunctions.ts @@ -0,0 +1,252 @@ +/* + Recurrence utility functions +*/ + +import dayjs from 'dayjs'; +import { + Days, + dayNames, + mondayToFriday, + monthNames, + weekDayOccurences, +} from './recurrenceConstants'; +import { Frequency } from './recurrenceTypes'; +import type { + WeekDays, + InterfaceRecurrenceRuleState, + InterfaceRecurrenceRule, +} from './recurrenceTypes'; + +// function that generates the recurrence rule text to display +// e.g. - 'Weekly on Sunday, until Feburary 23, 2029' +export const getRecurrenceRuleText = ( + recurrenceRuleState: InterfaceRecurrenceRuleState, +): string => { + let recurrenceRuleText = ''; + const { + recurrenceStartDate, + recurrenceEndDate, + frequency, + weekDays, + interval, + count, + weekDayOccurenceInMonth, + } = recurrenceRuleState; + + switch (frequency) { + case Frequency.DAILY: + if (interval && interval > 1) { + recurrenceRuleText = `Every ${interval} days`; + } else { + recurrenceRuleText = 'Daily'; + } + break; + + case Frequency.WEEKLY: + if (isMondayToFriday(weekDays)) { + if (interval && interval > 1) { + recurrenceRuleText = `Every ${interval} weeks, `; + } + recurrenceRuleText += 'Monday to Friday'; + break; + } + if (interval && interval > 1) { + recurrenceRuleText = `Every ${interval} weeks on `; + } else { + recurrenceRuleText = 'Weekly on '; + } + recurrenceRuleText += getWeekDaysString(weekDays); + break; + + case Frequency.MONTHLY: + if (interval && interval > 1) { + recurrenceRuleText = `Every ${interval} months on `; + } else { + recurrenceRuleText = 'Monthly on '; + } + + if (weekDayOccurenceInMonth) { + const getOccurence = + weekDayOccurenceInMonth !== -1 ? weekDayOccurenceInMonth - 1 : 4; + recurrenceRuleText += `${weekDayOccurences[getOccurence]} ${dayNames[Days[recurrenceStartDate.getDay()]]}`; + } else { + recurrenceRuleText += `Day ${recurrenceStartDate.getDate()}`; + } + break; + + case Frequency.YEARLY: + if (interval && interval > 1) { + recurrenceRuleText = `Every ${interval} years on `; + } else { + recurrenceRuleText = 'Annually on '; + } + recurrenceRuleText += `${monthNames[recurrenceStartDate.getMonth()]} ${recurrenceStartDate.getDate()}`; + break; + } + + if (recurrenceEndDate) { + const options = { year: 'numeric', month: 'long', day: 'numeric' }; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + recurrenceRuleText += `, until ${recurrenceEndDate.toLocaleDateString('en-US', options)}`; + } + + if (count) { + recurrenceRuleText += `, ${count} ${count > 1 ? 'times' : 'time'}`; + } + + return recurrenceRuleText; +}; + +// function that generates a string of selected week days for the recurrence rule text +// e.g. - for an array ['MONDAY', 'TUESDAY', 'FRIDAY'], it would output: 'Monday, Tuesday & Friday' +const getWeekDaysString = (weekDays: WeekDays[]): string => { + const fullDayNames = weekDays.map((day) => dayNames[day]); + + let weekDaysString = fullDayNames.join(', '); + + const lastCommaIndex = weekDaysString.lastIndexOf(','); + if (lastCommaIndex !== -1) { + weekDaysString = + weekDaysString.substring(0, lastCommaIndex) + + ' &' + + weekDaysString.substring(lastCommaIndex + 1); + } + + return weekDaysString; +}; + +// function that checks if the array contains all days from Monday to Friday +const isMondayToFriday = (weekDays: WeekDays[]): boolean => { + return mondayToFriday.every((day) => weekDays.includes(day)); +}; + +// function that returns the occurence of the weekday in a month, +// i.e. First Monday, Second Monday, Last Monday, etc. +export const getWeekDayOccurenceInMonth = (date: Date): number => { + const dayOfMonth = date.getDate(); + + // Calculate the current occurrence + const occurrence = Math.ceil(dayOfMonth / 7); + + return occurrence; +}; + +// function that checks whether it's the last occurence of the weekday in that month +export const isLastOccurenceOfWeekDay = (date: Date): boolean => { + const currentDay = date.getDay(); + + const lastOccurenceInMonth = new Date( + date.getFullYear(), + date.getMonth() + 1, + 0, + ); + + // set the lastOccurenceInMonth to that day's last occurence + while (lastOccurenceInMonth.getDay() !== currentDay) { + lastOccurenceInMonth.setDate(lastOccurenceInMonth.getDate() - 1); + } + + return date.getDate() === lastOccurenceInMonth.getDate(); +}; + +// function that evaluates whether the startDate or endDate of a recurring event instance have changed +export const haveInstanceDatesChanged = ( + instanceOriginalStartDate: string, + instanceOriginalEndDate: string, + instanceNewStartDate: string, + instanceNewEndDate: string, +): boolean => { + return ( + instanceOriginalStartDate !== instanceNewStartDate || + instanceOriginalEndDate !== instanceNewEndDate + ); +}; + +// function that checks whether the recurrence rule has changed +export const hasRecurrenceRuleChanged = ( + originalRecurrencerule: InterfaceRecurrenceRule | null, + recurrenceRuleState: InterfaceRecurrenceRuleState, +): boolean => { + if (!originalRecurrencerule) { + return false; + } + + const newRecurrenceRule = getRecurrenceRule(recurrenceRuleState); + + const recurrenceProperties = Object.keys( + newRecurrenceRule, + ) as (keyof InterfaceRecurrenceRule)[]; + + for (const recurrenceProperty of recurrenceProperties) { + if (recurrenceProperty === 'weekDays') { + if ( + weekDaysHaveChanged( + originalRecurrencerule.weekDays, + newRecurrenceRule.weekDays, + ) + ) { + return true; + } + } else if ( + originalRecurrencerule[recurrenceProperty] !== + newRecurrenceRule[recurrenceProperty] + ) { + return true; + } + } + + return false; +}; + +// function that returns the recurrence rule object based on the current recurrence rule state +const getRecurrenceRule = ( + recurrenceRuleState: InterfaceRecurrenceRuleState, +): InterfaceRecurrenceRule => { + const { + recurrenceStartDate, + recurrenceEndDate, + frequency, + weekDays, + interval, + count, + weekDayOccurenceInMonth, + } = recurrenceRuleState; + + const originalRecurrencerule = { + recurrenceStartDate: dayjs(recurrenceStartDate).format('YYYY-MM-DD'), + recurrenceEndDate: recurrenceEndDate + ? dayjs(recurrenceEndDate).format('YYYY-MM-DD') + : null, + frequency, + weekDays: weekDays?.length ? weekDays : [], + interval, + count: count ?? null, + weekDayOccurenceInMonth: weekDayOccurenceInMonth ?? null, + }; + + return originalRecurrencerule; +}; + +// function to check whether recurrence weekDays have been changed +const weekDaysHaveChanged = ( + originalWeekDays: WeekDays[], + currentWeekDays: WeekDays[], +): boolean => { + if (originalWeekDays.length !== currentWeekDays.length) { + return true; + } + + // Sort both arrays + const sortedOriginalWeekDays = [...originalWeekDays].sort(); + const sortedCurrentWeekDays = [...currentWeekDays].sort(); + + // Compare arrays + for (let i = 0; i < sortedOriginalWeekDays.length; i++) { + if (sortedOriginalWeekDays[i] !== sortedCurrentWeekDays[i]) { + return true; + } + } + + return false; +}; diff --git a/src/utils/useLocalstorage.test.ts b/src/utils/useLocalstorage.test.ts new file mode 100644 index 0000000000..7483da4da2 --- /dev/null +++ b/src/utils/useLocalstorage.test.ts @@ -0,0 +1,137 @@ +import { + getStorageKey, + getItem, + setItem, + removeItem, + useLocalStorage, +} from './useLocalstorage'; + +describe('Storage Helper Functions', () => { + beforeEach(() => { + localStorage.clear(); + }); + + it('generates correct storage key', () => { + const key = 'testKey'; + const prefix = 'TestPrefix'; + const storageKey = getStorageKey(prefix, key); + expect(storageKey).toBe('TestPrefix_testKey'); + }); + + it('gets item from local storage', () => { + const key = 'testKey'; + const prefix = 'TestPrefix'; + const value = 'data'; + localStorage.setItem('TestPrefix_testKey', JSON.stringify(value)); + + const retrievedValue = getItem(prefix, key); + + expect(retrievedValue).toEqual(value); + }); + + it('returns null when getting a non-existent item', () => { + const key = 'nonExistentKey'; + const prefix = 'TestPrefix'; + + const retrievedValue = getItem(prefix, key); + + expect(retrievedValue).toBeNull(); + }); + + it('sets item in local storage', () => { + const key = 'testKey'; + const prefix = 'TestPrefix'; + const value = { some: 'data' }; + + setItem(prefix, key, value); + + const storedData = localStorage.getItem('TestPrefix_testKey'); + const parsedData = storedData ? JSON.parse(storedData) : null; + + expect(parsedData).toEqual(value); + }); + + it('removes item from local storage', () => { + const key = 'testKey'; + const prefix = 'TestPrefix'; + const value = 'data'; + localStorage.setItem('TestPrefix_testKey', value); + + removeItem(prefix, key); + + const retrievedValue = localStorage.getItem('TestPrefix_testKey'); + expect(retrievedValue).toBeNull(); + }); + + it('uses default prefix for useLocalStorage', () => { + const storageHelper = useLocalStorage(); + const key = 'testKey'; + const value = { some: 'data' }; + + storageHelper.setItem(key, value); + + const storedData = localStorage.getItem('Talawa-admin_testKey'); + const parsedData = storedData ? JSON.parse(storedData) : null; + + expect(parsedData).toEqual(value); + }); + + it('uses provided prefix for useLocalStorage', () => { + const customPrefix = 'CustomPrefix'; + const storageHelper = useLocalStorage(customPrefix); + const key = 'testKey'; + const value = { some: 'data' }; + + storageHelper.setItem(key, value); + + const storedData = localStorage.getItem('CustomPrefix_testKey'); + const parsedData = storedData ? JSON.parse(storedData) : null; + + expect(parsedData).toEqual(value); + }); + + it('calls getStorageKey with the correct parameters', () => { + const customPrefix = 'CustomPrefix'; + const storageHelper = useLocalStorage(customPrefix); + const key = 'testKey'; + + const spyGetStorageKey = jest.spyOn(storageHelper, 'getStorageKey'); + storageHelper.getStorageKey(key); + + expect(spyGetStorageKey).toHaveBeenCalledWith(key); + }); + + it('calls getItem with the correct parameters', () => { + const customPrefix = 'CustomPrefix'; + const storageHelper = useLocalStorage(customPrefix); + const key = 'testKey'; + + const spyGetItem = jest.spyOn(storageHelper, 'getItem'); + storageHelper.getItem(key); + + expect(spyGetItem).toHaveBeenCalledWith(key); + }); + + it('calls setItem with the correct parameters', () => { + const customPrefix = 'CustomPrefix'; + const storageHelper = useLocalStorage(customPrefix); + const key = 'testKey'; + const value = 'data'; + + const spySetItem = jest.spyOn(storageHelper, 'setItem'); + storageHelper.setItem(key, value); + + expect(spySetItem).toHaveBeenCalledWith(key, value); + }); + + it('calls removeItem with the correct parameters', () => { + const customPrefix = 'CustomPrefix'; + const storageHelper = useLocalStorage(customPrefix); + const key = 'testKey'; + + const spyRemoveItem = jest.spyOn(storageHelper, 'removeItem'); + storageHelper.removeItem(key); + + expect(spyRemoveItem).toHaveBeenCalledWith(key); + }); +}); diff --git a/src/utils/useLocalstorage.ts b/src/utils/useLocalstorage.ts new file mode 100644 index 0000000000..9650381085 --- /dev/null +++ b/src/utils/useLocalstorage.ts @@ -0,0 +1,72 @@ +/** + * Helper interface for managing localStorage operations. + */ +interface InterfaceStorageHelper { + getItem: (key: string) => any; + setItem: (key: string, value: any) => void; + removeItem: (key: string) => void; + getStorageKey: (key: string) => string; +} + +const PREFIX = 'Talawa-admin'; + +/** + * Generates the prefixed key for storage. + * @param prefix - Prefix to be added to the key, common for all keys. + * @param key - The unique name identifying the value. + * @returns - Prefixed key. + */ +export const getStorageKey = (prefix: string, key: string): string => { + return `${prefix}_${key}`; +}; + +/** + * Retrieves the stored value for the given key from local storage. + * @param prefix - Prefix to be added to the key, common for all keys. + * @param key - The unique name identifying the value. + * @returns - The stored value for the given key from local storage. + */ +export const getItem = (prefix: string, key: string): any => { + const prefixedKey = getStorageKey(prefix, key); + const storedData = localStorage.getItem(prefixedKey); + return storedData ? JSON.parse(storedData) : null; +}; + +/** + * Sets the value for the given key in local storage. + * @param prefix - Prefix to be added to the key, common for all keys. + * @param key - The unique name identifying the value. + * @param value - The value for the key. + */ +export const setItem = (prefix: string, key: string, value: any): void => { + const prefixedKey = getStorageKey(prefix, key); + localStorage.setItem(prefixedKey, JSON.stringify(value)); +}; + +/** + * Removes the value associated with the given key from local storage. + * @param prefix - Prefix to be added to the key, common for all keys. + * @param key - The unique name identifying the value. + */ +export const removeItem = (prefix: string, key: string): void => { + const prefixedKey = getStorageKey(prefix, key); + localStorage.removeItem(prefixedKey); +}; + +/** + * Custom hook for simplified localStorage operations. + * @param prefix - Prefix to be added to the key, common for all keys. Default is 'Talawa-admin'. + * @returns - Functions to getItem, setItem, removeItem, and getStorageKey. + */ +export const useLocalStorage = ( + prefix: string = PREFIX, +): InterfaceStorageHelper => { + return { + getItem: (key: string) => getItem(prefix, key), + setItem: (key: string, value: any) => setItem(prefix, key, value), + removeItem: (key: string) => removeItem(prefix, key), + getStorageKey: (key: string) => getStorageKey(prefix, key), + }; +}; + +export default useLocalStorage; diff --git a/talawa-admin-docs/Dockerfile b/talawa-admin-docs/Dockerfile new file mode 100644 index 0000000000..e69de29bb2 diff --git a/talawa-admin-docs/README.md b/talawa-admin-docs/README.md index fb964eb868..82dc89754c 100644 --- a/talawa-admin-docs/README.md +++ b/talawa-admin-docs/README.md @@ -3,6 +3,8 @@ talawa-admin / [Modules](modules.md) # Talawa Admin 💬 Join the community on Slack. The link can be found in the `Talawa` [README.md](https://github.com/PalisadoesFoundation/talawa) file. +![talawa-logo-lite-200x200](https://github.com/PalisadoesFoundation/talawa-admin/assets/16875803/26291ec5-d3c1-4135-8bc7-80885dff613d) + [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) [![GitHub stars](https://img.shields.io/github/stars/PalisadoesFoundation/talawa-admin.svg?style=social&label=Star&maxAge=2592000)](https://github.com/PalisadoesFoundation/talawa-admin) [![GitHub forks](https://img.shields.io/github/forks/PalisadoesFoundation/talawa-admin.svg?style=social&label=Fork&maxAge=2592000)](https://github.com/PalisadoesFoundation/talawa-admin) @@ -20,6 +22,16 @@ Core features include: `talawa` is based on the original `quito` code created by the [Palisadoes Foundation][pfd] as part of its annual Calico Challenge program. Calico provides paid summer internships for Jamaican university students to work on selected open source projects. They are mentored by software professionals and receive stipends based on the completion of predefined milestones. Calico was started in 2015. Visit [The Palisadoes Foundation's website](http://www.palisadoes.org/) for more details on its origin and activities. +# Table of Contents + +\ -- [Prerequisites for Developers](#prerequisites-for-developers) -- [Installation](#installation) +- [Talawa-Admin Installation](#talawa-admin-installation) +- [Table of Contents](#table-of-contents) +- [Installation Steps Summary](#installation-steps-summary) +- [Prerequisites](#prerequisites) + - [Install git](#install-git) - [Setting up this repository](#setting-up-this-repository) - - [Setting up npm](#setting-up-npm) - - [Setting up Typescript](#setting-up-typescript) - - [Installing required packages/dependencies](#installing-required-packagesdependencies) + - [Install node.js](#install-nodejs) + - [Install TypeScript](#install-typescript) + - [Install Required Packages](#install-required-packages) - [Configuration](#configuration) - [Creating .env file](#creating-env-file) - [Setting up PORT in .env file](#setting-up-port-in-env-file) - - [Setting up REACT_APP_TALAWA_URL in .env file](#setting-up-react_app_talawa_url-in-env-file) - - [Setting up REACT_APP_RECAPTCHA_SITE_KEY in .env file](#setting-up-react_app_recaptcha_site_key-in-env-file) + - [Setting up REACT\_APP\_TALAWA\_URL in .env file](#setting-up-react_app_talawa_url-in-env-file) + - [Setting up REACT\_APP\_RECAPTCHA\_SITE\_KEY in .env file](#setting-up-react_app_recaptcha_site_key-in-env-file) - [Setting up Compiletime and Runtime logs](#setting-up-compiletime-and-runtime-logs) - [Post Configuration Steps](#post-configuration-steps) - [Running Talawa-Admin](#running-talawa-admin) @@ -33,66 +36,114 @@ This document provides instructions on how to set up and start a running instanc -# Prerequisites for Developers -We recommend that you to follow these steps before beginning development work on Talawa-Admin: +# Installation Steps Summary -1. You need to have `nodejs` installed in your machine. We recommend using Node version greater than 20.0.0. You can install it either through [nvm](https://github.com/nvm-sh/nvm) (Node Version Manager) or by visiting the official [Nodejs](https://nodejs.org/download/release/v16.20.2/) website. -1. [Talawa-API](https://github.com/PalisadoesFoundation/talawa-api): (**This is mandatory**) The API system that the mobile app uses for accessing data. Setup your own **_local instance_** -1. [Talawa](https://github.com/PalisadoesFoundation/talawa): (Optional) The mobile app that people will use to access Talawa's features. This may be useful if you need to verify administrative features you have added or modified. +Installation is not difficult, but there are many steps. This is a brief explanation of what needs to be done: -The INSTALLATION.md files in both repositories show you how. The Talawa-API INSTALLATION.md will also show you the Organization URL to use access Talawa Admin. +1. Install `git` +2. Download the code from GitHub using `git` +3. Install `node.js` (Node), the runtime environment the application will need to work. +4. Configure the Node Package Manager (`npm`) to automatically use the correct version of Node for our application. +5. Use `npm` to install TypeScript, the language the application is written in. +6. Install other supporting software such as the database. +7. Configure the application +8. Start the application -# Installation +These steps are explained in more detail in the sections that follow. -You will need to have copies of your code on your local system. Here's how to do that. +# Prerequisites -## Setting up this repository - -First you need a local copy of `talawa-admin`. Run the following command in the directory of choice on your local system. - -1. Navigate to the folder where you want to setup the repository. Here, I will set it up in a folder called `talawa`. -2. Navigate to the folder and open a terminal in this folder (you can right-click and choose appropiate option based onn your OS). Next, we'll fork and clone the `talawa-admin` repository. -3. Navigate to [https://github.com/PalisadoesFoundation/talawa-admin/](hhttps://github.com/PalisadoesFoundation/talawa-admin/) and click on the `fork` button. It is placed on the right corner opposite the repository name `PalisadoesFoundation/talawa-admin`. -4. You should now see `talawa-admin` under your repositories. It will be marked as forked from `PalisadoesFoundation/talawa-admin` -5. Clone the repository to your local computer (replacing the values in `{{}}`): - -``` -$ git clone https://github.com/{{YOUR GITHUB USERNAME}}/talawa-admin.git -``` +In this section we'll explain how to set up all the prerequisite software packages to get you up and running. -This will setup the repository and the code files locally for you. For more detailed instructions on contributing code, and managing the versions of this repository with Git, checkout [CONTRIBUTING.md here](./CONTRIBUTING.md) +## Install git -**NOTE:** `All the commands we're going to execute in the following instructions will assume you are in the root directory of the cloned talawa-admin project. If you fail to do so, the commands will not work.` +The easiest way to get the latest copies of our code is to install the `git` package on your computer. -## Setting up npm +Follow the setup guide for `git` on official [git docs](https://git-scm.com/downloads). Basic `git` knowledge is required for open source contribution so make sure you're comfortable with it. [Here's](https://youtu.be/apGV9Kg7ics) a good tutorial to get started with `git` and `github`. -Best way to install and manage `node.js` is making use of node version managers. Two most popular node version managers right now are [fnm](https://github.com/Schniz/fnm) and [nvm](https://github.com/nvm-sh/nvm). We'd recommend `fnm` because it's written in `rust` and is much faster than `nvm`. Install whichever one you want and follow their guide to set up `node.js` on your system. - -_**NOTE**_ - -1. The repository has a `.node-version` file to help ensure you use the supported version of `node.js`. Do not edit this file. -1. We strongly recommend that you configure your node version manager of choice to automatically read `.node-version` files - -## Setting up Typescript +## Setting up this repository -As `talawa-admin` and `talawa-api` repositories are written using [Typescript](https://www.typescriptlang.org/), you will need to install typescript on your machine. -We recommend to install `Typescript` globally on your machine by running the following command in the terminal: +First you need a local copy of `talawa-admin`. Run the following command in the directory of choice on your local system. -``` +1. On your computer, navigate to the folder where you want to setup the repository. +2. Open a `cmd` (Windows) or `terminal` (Linux or MacOS) session in this folder. + 1. An easy way to do this is to right-click and choose appropriate option based on your OS. +3. **For Our Open Source Contributor Software Developers:** + 1. Next, we'll fork and clone the `talawa-admin` repository. + 1. In your web browser, navigate to [https://github.com/PalisadoesFoundation/talawa-admin/](https://github.com/PalisadoesFoundation/talawa-admin/) and click on the `fork` button. It is placed on the right corner opposite the repository name `PalisadoesFoundation/talawa-admin`. + + ![Image with fork](public/markdown/images/install1.png) + + 2. You should now see `talawa-admin` under your repositories. It will be marked as forked from `PalisadoesFoundation/talawa-admin` + + ![Image of user's clone](public/markdown/images/install2.png) + + 3. Clone the repository to your local computer (replacing the values in `{{}}`): + ```bash + $ git clone https://github.com/{{YOUR GITHUB USERNAME}}/talawa-admin.git + cd talawa-admin + git checkout develop + ``` + - **Note:** Make sure to check out the `develop` branch + 4. You now have a local copy of the code files. For more detailed instructions on contributing code, and managing the versions of this repository with `git`, checkout our [CONTRIBUTING.md](./CONTRIBUTING.md) file. +4. **Talawa Administrators:** + 1. Clone the repository to your local computer using this command: + + ```bash + $ git clone https://github.com/PalisadoesFoundation/talawa-admin.git + ``` + +## Install node.js + +Best way to install and manage `node.js` is making use of node version managers. We recommend using `fnm`, which will be described in more detail later. + +Follow these steps to install the `node.js` packages in Windows, Linux and MacOS. + +1. For Windows: + 1. first install `node.js` from their website at https://nodejs.org + 1. When installing, don't click the option to install the `necessary tools`. These are not needed in our case. + 2. then install [fnm](https://github.com/Schniz/fnm). Please read all the steps in this section first. + 1. All the commands listed on this page will need to be run in a Windows terminal session in the `talawa-admin` directory. + 2. Install `fnm` using the `winget` option listed on the page. + 3. Setup `fnm` to automatically set the version of `node.js` to the version required for the repository using these steps: + 1. First, refer to the `fnm` web page's section on `Shell Setup` recommendations. + 2. Open a `Windows PowerShell` terminal window + 3. Run the recommended `Windows PowerShell` command to open `notepad`. + 4. Paste the recommended string into `notepad` + 5. Save the document. + 6. Exit `notepad` + 7. Exit PowerShell + 8. This will ensure that you are always using the correct version of `node.js` +2. For Linux and MacOS, use the terminal window. + 1. install `node.js` + 2. then install `fnm` + 1. Refer to the installation page's section on the `Shell Setup` recommendations. + 2. Run the respective recommended commands to setup your node environment + 3. This will ensure that you are always using the correct version of `node.js` + +## Install TypeScript + +TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. It adds optional types, classes, and modules to JavaScript, and supports tools for large-scale JavaScript applications. + +To install TypeScript, you can use the `npm` command which comes with `node.js`: + +```bash npm install -g typescript ``` -For more details please refer to the installation guidelines provided in the [official docs](https://www.typescriptlang.org/download). +This command installs TypeScript globally on your system so that it can be accessed from any project. -## Installing required packages/dependencies +## Install Required Packages -Run the following command to install the packages and dependencies required by `talawa-admin`: +Run the following command to install the packages and dependencies required by the app: ``` npm install ``` +The prerequisites are now installed. The next step will be to get the app up and running. + # Configuration It's important to configure Talawa-Admin. Here's how to do it. diff --git a/package-lock.json b/package-lock.json index d3e0d5e85d..bfbbf48e43 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", "@mui/icons-material": "^5.8.3", - "@mui/material": "^5.14.1", + "@mui/material": "^5.15.15", "@mui/private-theming": "^5.15.12", "@mui/system": "^5.14.12", "@mui/x-charts": "^6.0.0-alpha.13", @@ -65,8 +65,8 @@ "@testing-library/user-event": "^12.1.10", "@types/inquirer": "^9.0.7", "@types/jest": "^26.0.24", - "@types/js-cookie": "^3.0.2", - "@types/node": "^12.20.55", + "@types/js-cookie": "^3.0.6", + "@types/node": "^20.12.7", "@types/node-fetch": "^2.6.10", "@types/react": "^17.0.14", "@types/react-bootstrap": "^0.32.32", @@ -78,7 +78,7 @@ "@typescript-eslint/eslint-plugin": "^5.9.0", "@typescript-eslint/parser": "^5.9.0", "cross-env": "^7.0.3", - "eslint-config-prettier": "^8.10.0", + "eslint-config-prettier": "^9.1.0", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^25.3.4", "eslint-plugin-prettier": "^5.1.3", @@ -88,7 +88,7 @@ "identity-obj-proxy": "^3.0.0", "jest": "^27.4.5", "jest-localstorage-mock": "^2.4.19", - "jest-location-mock": "^1.0.9", + "jest-location-mock": "^2.0.0", "jest-preview": "^0.3.1", "lint-staged": "^15.2.2", "postcss-modules": "^6.0.0", @@ -3285,28 +3285,28 @@ } }, "node_modules/@floating-ui/core": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.5.0.tgz", - "integrity": "sha512-kK1h4m36DQ0UHGj5Ah4db7R0rHemTqqO0QLvUqi1/mUUp3LuAWbWxdxSIf/XsnH9VS6rRVPLJCncjRzUvyCLXg==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.1.tgz", + "integrity": "sha512-42UH54oPZHPdRHdw6BgoBD6cg/eVTmVrFcgeRDM3jbO7uxSoipVcmcIGFcA5jmOHO5apcyvBhkSKES3fQJnu7A==", "dependencies": { - "@floating-ui/utils": "^0.1.3" + "@floating-ui/utils": "^0.2.0" } }, "node_modules/@floating-ui/dom": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.3.tgz", - "integrity": "sha512-ClAbQnEqJAKCJOEbbLo5IUlZHkNszqhuxS4fHAVxRPXPya6Ysf2G8KypnYcOTpx6I8xcgF9bbHb6g/2KpbV8qA==", + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.4.tgz", + "integrity": "sha512-0G8R+zOvQsAG1pg2Q99P21jiqxqGBW1iRe/iXHsBRBxnpXKFI8QwbB4x5KmYLggNO5m34IQgOIu9SCRfR/WWiQ==", "dependencies": { - "@floating-ui/core": "^1.4.2", - "@floating-ui/utils": "^0.1.3" + "@floating-ui/core": "^1.0.0", + "@floating-ui/utils": "^0.2.0" } }, "node_modules/@floating-ui/react-dom": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.2.tgz", - "integrity": "sha512-5qhlDvjaLmAst/rKb3VdlCinwTF4EYMiVxuuc/HVUjs46W0zgtbMmAZ1UTsDrRTxRmUEzl92mOtWbeeXL26lSQ==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.9.tgz", + "integrity": "sha512-q0umO0+LQK4+p6aGyvzASqKbKOJcAHJ7ycE9CuUvfx3s9zTHWmGJTPOIlM/hmSBfUfg/XfY5YhLBLR/LHwShQQ==", "dependencies": { - "@floating-ui/dom": "^1.5.1" + "@floating-ui/dom": "^1.0.0" }, "peerDependencies": { "react": ">=16.8.0", @@ -3314,9 +3314,9 @@ } }, "node_modules/@floating-ui/utils": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.6.tgz", - "integrity": "sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==" + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.2.tgz", + "integrity": "sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw==" }, "node_modules/@gar/promisify": { "version": "1.1.3", @@ -3855,16 +3855,16 @@ } }, "node_modules/@mui/base": { - "version": "5.0.0-beta.17", - "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.17.tgz", - "integrity": "sha512-xNbk7iOXrglNdIxFBN0k3ySsPIFLWCnFxqsAYl7CIcDkD9low4kJ7IUuy6ctwx/HAy2fenrT3KXHr1sGjAMgpQ==", + "version": "5.0.0-beta.40", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.40.tgz", + "integrity": "sha512-I/lGHztkCzvwlXpjD2+SNmvNQvB4227xBXhISPjEaJUXGImOQ9f3D2Yj/T3KasSI/h0MLWy74X0J6clhPmsRbQ==", "dependencies": { - "@babel/runtime": "^7.22.15", - "@floating-ui/react-dom": "^2.0.2", - "@mui/types": "^7.2.4", - "@mui/utils": "^5.14.11", + "@babel/runtime": "^7.23.9", + "@floating-ui/react-dom": "^2.0.8", + "@mui/types": "^7.2.14", + "@mui/utils": "^5.15.14", "@popperjs/core": "^2.11.8", - "clsx": "^2.0.0", + "clsx": "^2.1.0", "prop-types": "^15.8.1" }, "engines": { @@ -3872,7 +3872,7 @@ }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0", @@ -3886,20 +3886,20 @@ } }, "node_modules/@mui/base/node_modules/clsx": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", - "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", "engines": { "node": ">=6" } }, "node_modules/@mui/core-downloads-tracker": { - "version": "5.14.11", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.14.11.tgz", - "integrity": "sha512-uY8FLQURhXe3f3O4dS5OSGML9KDm9+IE226cBu78jarVIzdQGPlXwGIlSI9VJR8MvZDA6C0+6XfWDhWCHruC5Q==", + "version": "5.15.15", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.15.tgz", + "integrity": "sha512-aXnw29OWQ6I5A47iuWEI6qSSUfH6G/aCsW9KmW3LiFqr7uXZBK4Ks+z8G+qeIub8k0T5CMqlT2q0L+ZJTMrqpg==", "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" } }, "node_modules/@mui/icons-material": { @@ -3928,19 +3928,19 @@ } }, "node_modules/@mui/material": { - "version": "5.14.11", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.14.11.tgz", - "integrity": "sha512-DnSdJzcR7lwG12JA5L2t8JF+RDzMygu5rCNW+logWb/KW2/TRzwLyVWO+CorHTBjBRd38DBxnwOCDiYkDd+N3A==", + "version": "5.15.15", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.15.tgz", + "integrity": "sha512-3zvWayJ+E1kzoIsvwyEvkTUKVKt1AjchFFns+JtluHCuvxgKcLSRJTADw37k0doaRtVAsyh8bz9Afqzv+KYrIA==", "dependencies": { - "@babel/runtime": "^7.22.15", - "@mui/base": "5.0.0-beta.17", - "@mui/core-downloads-tracker": "^5.14.11", - "@mui/system": "^5.14.11", - "@mui/types": "^7.2.4", - "@mui/utils": "^5.14.11", - "@types/react-transition-group": "^4.4.6", - "clsx": "^2.0.0", - "csstype": "^3.1.2", + "@babel/runtime": "^7.23.9", + "@mui/base": "5.0.0-beta.40", + "@mui/core-downloads-tracker": "^5.15.15", + "@mui/system": "^5.15.15", + "@mui/types": "^7.2.14", + "@mui/utils": "^5.15.14", + "@types/react-transition-group": "^4.4.10", + "clsx": "^2.1.0", + "csstype": "^3.1.3", "prop-types": "^15.8.1", "react-is": "^18.2.0", "react-transition-group": "^4.4.5" @@ -3950,7 +3950,7 @@ }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { "@emotion/react": "^11.5.0", @@ -3972,9 +3972,9 @@ } }, "node_modules/@mui/material/node_modules/clsx": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", - "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", "engines": { "node": ">=6" } @@ -4006,13 +4006,13 @@ } }, "node_modules/@mui/styled-engine": { - "version": "5.14.15", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.14.15.tgz", - "integrity": "sha512-mbOjRf867BysNpexe5Z/P8s3bWzDPNowmKhi7gtNDP/LPEeqAfiDSuC4WPTXmtvse1dCl30Nl755OLUYuoi7Mw==", + "version": "5.15.14", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.15.14.tgz", + "integrity": "sha512-RILkuVD8gY6PvjZjqnWhz8fu68dVkqhM5+jYWfB5yhlSQKg+2rHkmEwm75XIeAqI3qwOndK6zELK5H6Zxn4NHw==", "dependencies": { - "@babel/runtime": "^7.23.2", + "@babel/runtime": "^7.23.9", "@emotion/cache": "^11.11.0", - "csstype": "^3.1.2", + "csstype": "^3.1.3", "prop-types": "^15.8.1" }, "engines": { @@ -4020,7 +4020,7 @@ }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { "@emotion/react": "^11.4.1", @@ -4037,17 +4037,17 @@ } }, "node_modules/@mui/system": { - "version": "5.14.15", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.14.15.tgz", - "integrity": "sha512-zr0Gdk1RgKiEk+tCMB900LaOpEC8NaGvxtkmMdL/CXgkqQZSVZOt2PQsxJWaw7kE4YVkIe4VukFVc43qcq9u3w==", - "dependencies": { - "@babel/runtime": "^7.23.2", - "@mui/private-theming": "^5.14.15", - "@mui/styled-engine": "^5.14.15", - "@mui/types": "^7.2.7", - "@mui/utils": "^5.14.15", - "clsx": "^2.0.0", - "csstype": "^3.1.2", + "version": "5.15.15", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.15.tgz", + "integrity": "sha512-aulox6N1dnu5PABsfxVGOZffDVmlxPOVgj56HrUnJE8MCSh8lOvvkd47cebIVQQYAjpwieXQXiDPj5pwM40jTQ==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/private-theming": "^5.15.14", + "@mui/styled-engine": "^5.15.14", + "@mui/types": "^7.2.14", + "@mui/utils": "^5.15.14", + "clsx": "^2.1.0", + "csstype": "^3.1.3", "prop-types": "^15.8.1" }, "engines": { @@ -4055,7 +4055,7 @@ }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { "@emotion/react": "^11.5.0", @@ -4076,17 +4076,17 @@ } }, "node_modules/@mui/system/node_modules/clsx": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", - "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", "engines": { "node": ">=6" } }, "node_modules/@mui/types": { - "version": "7.2.7", - "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.7.tgz", - "integrity": "sha512-sofpWmcBqOlTzRbr1cLQuUDKaUYVZTw8ENQrtL39TECRNENEzwgnNPh6WMfqMZlMvf1Aj9DLg74XPjnLr0izUQ==", + "version": "7.2.14", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.14.tgz", + "integrity": "sha512-MZsBZ4q4HfzBsywtXgM1Ksj6HDThtiwmOKUXH1pKYISI9gAVXCNHNpo7TlGoGrBaYWZTdNoirIN7JsQcQUjmQQ==", "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0" }, @@ -5494,9 +5494,9 @@ } }, "node_modules/@types/js-cookie": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.3.tgz", - "integrity": "sha512-Xe7IImK09HP1sv2M/aI+48a20VX+TdRJucfq4vfRVy6nWN8PYPOEnlMRSgxJAgYQIXJVL8dZ4/ilAM7dWNaOww==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.6.tgz", + "integrity": "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==", "dev": true }, "node_modules/@types/json-schema": { @@ -5522,9 +5522,12 @@ "peer": true }, "node_modules/@types/node": { - "version": "12.20.55", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", - "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==" + "version": "20.12.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", + "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/@types/node-fetch": { "version": "2.6.11", @@ -5669,9 +5672,9 @@ } }, "node_modules/@types/react-transition-group": { - "version": "4.4.6", - "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.6.tgz", - "integrity": "sha512-VnCdSxfcm08KjsJVQcfBmhEQAPnLB8G08hAxn39azX1qYBQ/5RVQuoHuKIcfKOdncuaUvEpFKFzEvbtIMsfVew==", + "version": "4.4.10", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz", + "integrity": "sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==", "dependencies": { "@types/react": "*" } @@ -8825,9 +8828,9 @@ "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" }, "node_modules/csstype": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", - "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "node_modules/customize-cra": { "version": "1.0.0", @@ -9957,9 +9960,9 @@ } }, "node_modules/eslint-config-prettier": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz", - "integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, "bin": { "eslint-config-prettier": "bin/cli.js" @@ -14257,18 +14260,36 @@ } }, "node_modules/jest-location-mock": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/jest-location-mock/-/jest-location-mock-1.0.10.tgz", - "integrity": "sha512-g5u0rDOaj1I/lWuPOOP6xfpY+O958IcOanwPKnHdfWm0l4Y2sdVmwXMPY9fT5s8D9nX44Zl/Ypmk6B88mDoqZQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jest-location-mock/-/jest-location-mock-2.0.0.tgz", + "integrity": "sha512-loakfclgY/y65/2i4s0fcdlZY3hRPfwNnmzRsGFQYQryiaow2DEIGTLXIPI8cAO1Is36xsVLVkIzgvhQ+FXHdw==", "dev": true, "dependencies": { "@jedmao/location": "^3.0.0", - "jest-diff": "^27.0.1" + "jest-diff": "^29.6.4" }, "engines": { - "node": ">=10.0.0" + "node": "^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-location-mock/node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-location-mock/node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, "node_modules/jest-location-mock/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -14286,41 +14307,50 @@ } }, "node_modules/jest-location-mock/node_modules/diff-sequences": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", - "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-location-mock/node_modules/jest-diff": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", - "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "diff-sequences": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-location-mock/node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-location-mock/node_modules/pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "dependencies": { - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" + "react-is": "^18.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-location-mock/node_modules/pretty-format/node_modules/ansi-styles": { @@ -14335,12 +14365,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jest-location-mock/node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - }, "node_modules/jest-matcher-utils": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", @@ -23371,6 +23395,11 @@ "react": ">=15.0.0" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", diff --git a/package.json b/package.json index 10ddc16b1f..1d211a790c 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", "@mui/icons-material": "^5.8.3", - "@mui/material": "^5.14.1", + "@mui/material": "^5.15.15", "@mui/private-theming": "^5.15.12", "@mui/system": "^5.14.12", "@mui/x-charts": "^6.0.0-alpha.13", @@ -97,8 +97,8 @@ "@testing-library/user-event": "^12.1.10", "@types/inquirer": "^9.0.7", "@types/jest": "^26.0.24", - "@types/js-cookie": "^3.0.2", - "@types/node": "^12.20.55", + "@types/js-cookie": "^3.0.6", + "@types/node": "^20.12.7", "@types/node-fetch": "^2.6.10", "@types/react": "^17.0.14", "@types/react-bootstrap": "^0.32.32", @@ -110,7 +110,7 @@ "@typescript-eslint/eslint-plugin": "^5.9.0", "@typescript-eslint/parser": "^5.9.0", "cross-env": "^7.0.3", - "eslint-config-prettier": "^8.10.0", + "eslint-config-prettier": "^9.1.0", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^25.3.4", "eslint-plugin-prettier": "^5.1.3", @@ -120,7 +120,7 @@ "identity-obj-proxy": "^3.0.0", "jest": "^27.4.5", "jest-localstorage-mock": "^2.4.19", - "jest-location-mock": "^1.0.9", + "jest-location-mock": "^2.0.0", "jest-preview": "^0.3.1", "lint-staged": "^15.2.2", "postcss-modules": "^6.0.0", diff --git a/public/locales/en.json b/public/locales/en.json index 4dce655d45..b1e75a64aa 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -37,7 +37,42 @@ "lowercase_check": "Atleast one lowercase letter", "uppercase_check": "Atleast one uppercase letter", "numeric_value_check": "Atleaset one numeric value", - "special_char_check": "Atleast one special character" + "special_char_check": "Atleast one special character", + "loading": "Loading...", + "selectOrg": "Select an organization", + "afterRegister": "Successfully registered. Please wait for admin to approve your request." + }, + "userLoginPage": { + "title": "Talawa Admin", + "fromPalisadoes": "An open source application by Palisadoes Foundation volunteers", + "talawa_portal": "Talawa Admin Portal", + "login": "Login", + "register": "Register", + "firstName": "First Name", + "lastName": "Last Name", + "email": "Email", + "password": "Password", + "atleast_8_char_long": "Atleast 8 Character long", + "Password_and_Confirm_password_mismatches.": "Password and Confirm password mismatches.", + "confirmPassword": "Confirm Password", + "forgotPassword": "Forgot Password ?", + "enterEmail": "Enter Email", + "enterPassword": "Enter Password", + "doNotOwnAnAccount": "Do not own an account?", + "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too.", + "captchaError": "Captcha Error!", + "Please_check_the_captcha": "Please, check the captcha.", + "Something_went_wrong": "Something went wrong, Please try after sometime.", + "passwordMismatches": "Password and Confirm password mismatches.", + "fillCorrectly": "Fill all the Details Correctly.", + "notAuthorised": "Sorry! you are not Authorised!", + "notFound": "User not found!", + "successfullyRegistered": "Successfully Registered. Please wait until you will be approved.", + "userLogin": "User Login", + "afterRegister": "Successfully registered. Please wait for admin to approve your request.", + "OR": "OR", + "loading": "Loading...", + "selectOrg": "Select an organization" }, "latestEvents": { "eventCardTitle": "Upcoming Events", diff --git a/public/locales/fr.json b/public/locales/fr.json index 4a851b8e8d..ef9eed6c96 100644 --- a/public/locales/fr.json +++ b/public/locales/fr.json @@ -37,7 +37,40 @@ "lowercase_check": "Au moins une lettre minuscule", "uppercase_check": "Au moins une lettre majuscule", "special_char_check": "Au moins un caractère spécial", - "numeric_value_check": "Au moins une valeur numérique" + "numeric_value_check": "Au moins une valeur numérique", + "afterRegister": "Inscription réussie. Veuillez attendre l'approbation de l'administrateur pour votre demande." + }, + "userLoginPage": { + "title": "Administration Talawa", + "fromPalisadoes": "Une application open source par des bénévoles de la Fondation Palisadoes", + "talawa_portal": "Portail d'administration Talawa", + "login": "Connexion", + "register": "S'inscrire", + "firstName": "Prénom", + "lastName": "Nom de famille", + "email": "E-mail", + "password": "Mot de passe", + "atleast_8_char_long": "Au moins 8 caractères de long", + "Password_and_Confirm_password_mismatches.": "Les mots de passe ne correspondent pas.", + "confirmPassword": "Confirmez le mot de passe", + "forgotPassword": "Mot de passe oublié ?", + "enterEmail": "Entrez l'e-mail", + "enterPassword": "Entrez le mot de passe", + "doNotOwnAnAccount": "Vous n'avez pas de compte ?", + "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau.", + "captchaError": "Erreur de captcha !", + "Please_check_the_captcha": "Veuillez vérifier le captcha.", + "Something_went_wrong": "Quelque chose s'est mal passé, veuillez réessayer ultérieurement.", + "passwordMismatches": "Les mots de passe ne correspondent pas.", + "fillCorrectly": "Remplissez correctement tous les détails.", + "notAuthorised": "Désolé ! Vous n'êtes pas autorisé !", + "notFound": "Utilisateur non trouvé !", + "successfullyRegistered": "Inscription réussie. Veuillez attendre que votre demande soit approuvée.", + "userLogin": "Connexion utilisateur", + "afterRegister": "Inscription réussie. Veuillez attendre l'approbation de l'administrateur.", + "OR": "OU", + "loading": "Chargement...", + "selectOrg": "Sélectionnez une organisation" }, "latestEvents": { "eventCardTitle": "Événements à venir", diff --git a/public/locales/hi.json b/public/locales/hi.json index eddc354c5c..a029df8bd7 100644 --- a/public/locales/hi.json +++ b/public/locales/hi.json @@ -37,7 +37,42 @@ "lowercase_check": "कम से कम एक छोटा अक्षर", "uppercase_check": "कम से कम एक बड़ा अक्षर", "numeric_value_check": "कम से कम एक संख्यात्मक मान", - "special_char_check": "कम से कम एक विशेष पात्र" + "special_char_check": "कम से कम एक विशेष पात्र", + "loading": "लोड हो रहा है...", + "selectOrg": "कोई संगठन चुनें", + "afterRegister": "सफलतापूर्वक पंजीकृत हो गया। कृपया व्यवस्थापक की मंजूरी का इंतजार करें।" + }, + "userLoginPage": { + "title": "तलवा व्यवस्थापक", + "fromPalisadoes": "पलिसाडो के स्वयंसेवकों द्वारा एक खुला स्रोत अनुप्रयोग", + "talawa_portal": "तलावा प्रशासन पोर्टल", + "login": "लॉग इन करें", + "register": "पंजीकरण करवाना", + "firstName": "पहला नाम", + "lastName": "उपनाम", + "email": "ईमेल", + "password": "पासवर्ड", + "atleast_8_char_long": "कम से कम 8 कैरेक्टर लंबा", + "Password_and_Confirm_password_mismatches.": "पासवर्ड और पुष्टि पासवर्ड बेमेल।", + "confirmPassword": "पासवर्ड की पुष्टि कीजिये", + "forgotPassword": "पासवर्ड भूल गए ?", + "enterEmail": "ईमेल दर्ज करें", + "enterPassword": "पास वर्ड दर्ज करें", + "doNotOwnAnAccount": "क्या आपके पास खाता नहीं है?", + "talawaApiUnavailable": "तलावा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रही है? अपनी नेटवर्क कनेक्टिविटी की भी जाँच करें।", + "captchaError": "कैप्चा त्रुटि!", + "Please_check_the_captcha": "कृपया, कैप्चा जांचें।", + "Something_went_wrong": "कुछ गलत हुआ, कृपया कुछ समय बाद प्रयास करें।", + "passwordMismatches": "पासवर्ड और पुष्टि पासवर्ड मेल नहीं खाते।", + "fillCorrectly": "सभी विवरण सही ढंग से भरें।", + "notAuthorised": "क्षमा करें! आप अधिकृत नहीं हैं!", + "notFound": "उपयोगकर्ता नहीं मिला!", + "successfullyRegistered": "सफलतापूर्वक पंजीकृत। कृपया स्वीकृत होने तक प्रतीक्षा करें।", + "afterRegister": "पंजीकरण सफलतापूर्वक हो गया है। कृपया आपके अनुरोध को स्वीकार करने के लिए व्यवस्थापक की प्रतीक्षा करें।", + "userLogin": "उपयोगकर्ता लॉगिन", + "OR": "या", + "loading": "लोड हो रहा है...", + "selectOrg": "कोई संगठन चुनें" }, "latestEvents": { "eventCardTitle": "आगामी घटनाएँ", diff --git a/public/locales/sp.json b/public/locales/sp.json index 4b25f43e6c..c084402939 100644 --- a/public/locales/sp.json +++ b/public/locales/sp.json @@ -37,7 +37,42 @@ "lowercase_check": "Al menos una letra mayuscula", "uppercase_check": "Al menos una letra minúscula", "numeric_value_check": "Al menos un valor numérico", - "special_char_check": "Al menos un carácter especial" + "special_char_check": "Al menos un carácter especial", + "loading": "Cargando...", + "selectOrg": "Seleccione una organización", + "afterRegister": "Registro exitoso. Por favor, espere a que el administrador apruebe su solicitud." + }, + "userLoginPage": { + "title": "Administrador Talawa", + "fromPalisadoes": "Una aplicación de código abierto de los voluntarios de la Fundación palisados", + "talawa_portal": "Portal De Administración Talawa", + "login": "Acceso", + "register": "Registro", + "firstName": "Primer nombre", + "lastName": "Apellido", + "email": "Correo electrónico", + "password": "Clave", + "atleast_8_char_long": "Al menos 8 caracteres de largo", + "Password_and_Confirm_password_mismatches.": "Contraseña y Confirmar contraseña no coinciden.", + "confirmPassword": "Confirmar contraseña", + "forgotPassword": "Has olvidado tu contraseña ?", + "enterEmail": "ingrese correo electrónico", + "enterPassword": "introducir la contraseña", + "doNotOwnAnAccount": "¿No tienes una cuenta?", + "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está funcionando? Verifica también la conectividad de tu red.", + "captchaError": "¡Error de captcha!", + "Please_check_the_captcha": "Por favor, revisa el captcha.", + "Something_went_wrong": "Algo salió mal. Inténtalo después de un tiempo", + "passwordMismatches": "Contraseña y Confirmar contraseña no coinciden.", + "fillCorrectly": "Complete todos los detalles correctamente.", + "notAuthorised": "¡Lo siento! ¡No estás autorizado!", + "notFound": "¡Usuario no encontrado!", + "successfullyRegistered": "Registrado con éxito. Espere hasta que sea aprobado", + "userLogin": "Inicio de sesión de usuario", + "afterRegister": "Registrado exitosamente. Espere a que el administrador apruebe su solicitud.", + "OR": "O", + "loading": "Cargando...", + "selectOrg": "Seleccione una organización" }, "latestEvents": { "eventCardTitle": "Próximos Eventos", diff --git a/public/locales/zh.json b/public/locales/zh.json index 0d5f717b00..d105c830bd 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -37,7 +37,42 @@ "lowercase_check": "至少一個小寫字母", "uppercase_check": "至少有一個大寫字母", "numeric_value_check": "至少一個數值", - "special_char_check": "至少一個特殊字符" + "special_char_check": "至少一個特殊字符", + "loading": "载入中...", + "selectOrg": "选择一个组织", + "afterRegister": "注册成功。请等待管理员批准您的请求" + }, + "userLoginPage": { + "title": "塔拉瓦管理員", + "fromPalisadoes": "柵欄 基金会志愿者的开源应用程序", + "talawa_portal": "塔拉瓦管理門戶", + "login": "登錄", + "register": "登記", + "firstName": "名", + "lastName": "姓", + "email": "電子郵件", + "password": "密碼", + "atleast_8_char_long": "至少 8 個字符長", + "Password_and_Confirm_password_mismatches.": "密碼和確認密碼不匹配。", + "confirmPassword": "確認密碼", + "forgotPassword": "忘記密碼 ?", + "enterEmail": "输入电子邮件", + "enterPassword": "输入密码", + "doNotOwnAnAccount": "沒有帳戶嗎?", + "talawaApiUnavailable": "服務不可用。它正在運行嗎?還要檢查您的網絡連接。", + "captchaError": "驗證碼錯誤!", + "Please_check_the_captcha": "請檢查驗證碼。", + "Something_went_wrong": "出了點問題,請稍後再試。", + "passwordMismatches": "密碼和確認密碼不匹配。", + "fillCorrectly": "正確填寫所有細節。", + "notAuthorised": "抱歉!你沒有被授權!", + "notFound": "找不到用戶!", + "successfullyRegistered": "註冊成功,請等待審核通過。", + "userLogin": "用户登录", + "afterRegister": "註冊成功。 請等待管理員批准您的請求。", + "OR": "或者", + "loading": "载入中...", + "selectOrg": "选择一个组织" }, "latestEvents": { "eventCardTitle": "即将举行的活动", diff --git a/public/markdown/images/install1.png b/public/markdown/images/install1.png new file mode 100644 index 0000000000000000000000000000000000000000..632cb4f7a506190163e2c5b58a5cd4734584ee56 GIT binary patch literal 38688 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�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

    $Z+!OFDab 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 { const propsOrg: InterfaceLeftDrawerProps = { ...props, }; -const propsUsers: InterfaceLeftDrawerProps = { - ...props, - hideDrawer: null, -}; const MOCKS = [ { @@ -73,6 +69,10 @@ describe('Testing Left Drawer component for SUPERADMIN', () => { setItem('SuperAdmin', true); setItem('FirstName', 'John'); setItem('LastName', 'Doe'); + setItem('UserImage', ''); + setItem('SuperAdmin', true); + setItem('FirstName', 'John'); + setItem('LastName', 'Doe'); render( @@ -86,6 +86,7 @@ describe('Testing Left Drawer component for SUPERADMIN', () => { expect(screen.getByText('My Organizations')).toBeInTheDocument(); expect(screen.getByText('Users')).toBeInTheDocument(); expect(screen.getByText('Community Profile')).toBeInTheDocument(); + expect(screen.getByText('Community Profile')).toBeInTheDocument(); expect(screen.getByText('Talawa Admin Portal')).toBeInTheDocument(); const orgsBtn = screen.getByTestId(/orgsBtn/i); @@ -97,6 +98,7 @@ describe('Testing Left Drawer component for SUPERADMIN', () => { orgsBtn.className.includes('text-white btn btn-success'), ).toBeTruthy(); expect(rolesBtn.className.includes('text-secondary btn')).toBeTruthy(); + expect(rolesBtn.className.includes('text-secondary btn')).toBeTruthy(); expect( communityProfileBtn.className.includes('text-secondary btn'), ).toBeTruthy(); @@ -108,11 +110,16 @@ describe('Testing Left Drawer component for SUPERADMIN', () => { }); test('Testing Drawer when hideDrawer is null', () => { + const tempProps: InterfaceLeftDrawerProps = { + ...props, + hideDrawer: false, + }; + render( - + , @@ -123,24 +130,18 @@ describe('Testing Left Drawer component for SUPERADMIN', () => { ...props, hideDrawer: false, }; - render( - - - - - - - , - ); }); - test('Testing Drawer when the screen size is less than or equal to 820px', () => { + const tempProps: InterfaceLeftDrawerProps = { + ...props, + hideDrawer: false, + }; resizeWindow(800); render( - + , @@ -155,35 +156,36 @@ describe('Testing Left Drawer component for SUPERADMIN', () => { orgsBtn.className.includes('text-white btn btn-success'), ).toBeTruthy(); }); -}); - -describe('Testing Left Drawer component for ADMIN', () => { - test('Components should be rendered properly', () => { - render( - - - - - - - , - ); - - expect(screen.getByText('My Organizations')).toBeInTheDocument(); - expect(screen.getByText('Talawa Admin Portal')).toBeInTheDocument(); - - expect(screen.getAllByText(/admin/i)).toHaveLength(1); - - const orgsBtn = screen.getByTestId(/orgsBtn/i); - orgsBtn.click(); - expect( - orgsBtn.className.includes('text-white btn btn-success'), - ).toBeTruthy(); - - // These screens arent meant for admins so they should not be present - expect(screen.queryByTestId(/rolesBtn/i)).toBeNull(); - userEvent.click(orgsBtn); - expect(global.window.location.pathname).toContain('/orglist'); + describe('Testing Left Drawer component for ADMIN', () => { + test('Components should be rendered properly', () => { + render( + + + + + + + , + ); + + expect(screen.getByText('My Organizations')).toBeInTheDocument(); + expect(screen.getByText('Talawa Admin Portal')).toBeInTheDocument(); + + expect(screen.getAllByText(/admin/i)).toHaveLength(1); + expect(screen.getAllByText(/admin/i)).toHaveLength(1); + + const orgsBtn = screen.getByTestId(/orgsBtn/i); + orgsBtn.click(); + expect( + orgsBtn.className.includes('text-white btn btn-success'), + ).toBeTruthy(); + + // These screens arent meant for admins so they should not be present + expect(screen.queryByTestId(/rolesBtn/i)).toBeNull(); + + userEvent.click(orgsBtn); + expect(global.window.location.pathname).toContain('/orglist'); + }); }); }); diff --git a/src/components/LeftDrawerOrg/LeftDrawerOrg.module.css b/src/components/LeftDrawerOrg/LeftDrawerOrg.module.css index b300eb7e89..54560e7969 100644 --- a/src/components/LeftDrawerOrg/LeftDrawerOrg.module.css +++ b/src/components/LeftDrawerOrg/LeftDrawerOrg.module.css @@ -61,7 +61,6 @@ .leftDrawer .optionList { height: 100%; - overflow-y: auto; } .leftDrawer .optionList button { diff --git a/src/components/OrganizationScreen/OrganizationScreen.module.css b/src/components/OrganizationScreen/OrganizationScreen.module.css index 7570b14ced..9b8190a3ad 100644 --- a/src/components/OrganizationScreen/OrganizationScreen.module.css +++ b/src/components/OrganizationScreen/OrganizationScreen.module.css @@ -134,6 +134,9 @@ } @media (max-height: 900px) { + .pageContainer { + padding: 1rem 1.5rem 0 calc(300px + 2rem); + } .collapseSidebarButton { height: 30px; width: calc(300px + 1rem); diff --git a/src/screens/LoginPage/LoginPage.module.css b/src/screens/LoginPage/LoginPage.module.css index dba42696d7..e7ce0eca7e 100644 --- a/src/screens/LoginPage/LoginPage.module.css +++ b/src/screens/LoginPage/LoginPage.module.css @@ -14,6 +14,10 @@ height: 100vh; } +.selectOrgText input { + outline: none !important; +} + .row .left_portion .inner .palisadoes_logo { width: 600px; height: auto; diff --git a/src/screens/LoginPage/LoginPage.test.tsx b/src/screens/LoginPage/LoginPage.test.tsx index bac7b264db..a61f8adb2e 100644 --- a/src/screens/LoginPage/LoginPage.test.tsx +++ b/src/screens/LoginPage/LoginPage.test.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { MockedProvider } from '@apollo/react-testing'; -import { act, render, screen, fireEvent } from '@testing-library/react'; +import { act, render, screen, fireEvent, within } from '@testing-library/react'; import { Provider } from 'react-redux'; import { BrowserRouter } from 'react-router-dom'; import userEvent from '@testing-library/user-event'; @@ -13,13 +13,13 @@ import { LOGIN_MUTATION, RECAPTCHA_MUTATION, SIGNUP_MUTATION, - UPDATE_COMMUNITY, } from 'GraphQl/Mutations/mutations'; import { store } from 'state/store'; import i18nForTest from 'utils/i18nForTest'; import { BACKEND_URL } from 'Constant/constant'; import useLocalStorage from 'utils/useLocalstorage'; -import { GET_COMMUNITY_DATA } from 'GraphQl/Queries/Queries'; +import { GET_COMMUNITY_DATA, ORGANIZATION_LIST } from 'GraphQl/Queries/Queries'; +import { debug } from 'jest-preview'; const MOCKS = [ { @@ -92,6 +92,7 @@ const MOCKS = [ }, }, ]; + const MOCKS2 = [ { request: { @@ -121,9 +122,83 @@ const MOCKS2 = [ }, }, ]; +const MOCKS3 = [ + { + request: { + query: ORGANIZATION_LIST, + }, + result: { + data: { + organizations: [ + { + _id: '6437904485008f171cf29924', + image: null, + creator: { + firstName: 'Wilt', + lastName: 'Shepherd', + }, + name: 'Unity Foundation', + members: [ + { + _id: '64378abd85008f171cf2990d', + }, + ], + admins: [ + { + _id: '64378abd85008f171cf2990d', + }, + ], + createdAt: '2023-04-13T05:16:52.827Z', + address: { + city: 'Bronx', + countryCode: 'US', + dependentLocality: 'Some Dependent Locality', + line1: '123 Random Street', + line2: 'Apartment 456', + postalCode: '10451', + sortingCode: 'ABC-123', + state: 'NYC', + }, + }, + { + _id: 'db1d5caad2ade57ab811e681', + image: null, + creator: { + firstName: 'Sonya', + lastName: 'Jones', + }, + name: 'Mills Group', + members: [ + { + _id: '661b8410bd25a325da05e67c', + }, + ], + admins: [ + { + _id: '661b8410bd25a325da05e67c', + }, + ], + createdAt: '2024-04-14T07:21:52.940Z', + address: { + city: 'Lake Martineside', + countryCode: 'SL', + dependentLocality: 'Apt. 544', + line1: '5112 Dare Centers', + line2: 'Suite 163', + postalCode: '10452', + sortingCode: '46565-3458', + state: 'New Hampshire', + }, + }, + ], + }, + }, + }, +]; const link = new StaticMockLink(MOCKS, true); const link2 = new StaticMockLink(MOCKS2, true); +const link3 = new StaticMockLink(MOCKS3, true); async function wait(ms = 100): Promise { await act(() => { @@ -852,6 +927,33 @@ describe('Testing redirect if already logged in', () => { expect(mockNavigate).toHaveBeenCalledWith('/orglist'); }); }); +test('Render the Select Organization list and change the option', async () => { + render( + + + + + + + + + , + ); + + await wait(); + userEvent.click(screen.getByTestId(/goToRegisterPortion/i)); + await wait(); + const autocomplete = screen.getByTestId('selectOrg'); + const input = within(autocomplete).getByRole('combobox'); + autocomplete.focus(); + // the value here can be any string you want, so you may also consider to + // wrapper it as a function and pass in inputValue as parameter + fireEvent.change(input, { target: { value: 'a' } }); + fireEvent.keyDown(autocomplete, { key: 'ArrowDown' }); + fireEvent.keyDown(autocomplete, { key: 'Enter' }); + + debug(); +}); describe('Talawa-API server fetch check', () => { beforeEach(() => { diff --git a/src/screens/LoginPage/LoginPage.tsx b/src/screens/LoginPage/LoginPage.tsx index 4508684778..834232fb8a 100644 --- a/src/screens/LoginPage/LoginPage.tsx +++ b/src/screens/LoginPage/LoginPage.tsx @@ -22,7 +22,7 @@ import { RECAPTCHA_MUTATION, SIGNUP_MUTATION, } from 'GraphQl/Mutations/mutations'; -import { GET_COMMUNITY_DATA } from 'GraphQl/Queries/Queries'; +import { GET_COMMUNITY_DATA, ORGANIZATION_LIST } from 'GraphQl/Queries/Queries'; import { ReactComponent as PalisadoesLogo } from 'assets/svgs/palisadoes.svg'; import { ReactComponent as TalawaLogo } from 'assets/svgs/talawa.svg'; import ChangeLanguageDropDown from 'components/ChangeLanguageDropdown/ChangeLanguageDropDown'; @@ -32,6 +32,8 @@ import { errorHandler } from 'utils/errorHandler'; import useLocalStorage from 'utils/useLocalstorage'; import { socialMediaLinks } from '../../constants'; import styles from './LoginPage.module.css'; +import type { InterfaceQueryOrganizationListObject } from 'utils/interfaces'; +import { Autocomplete, TextField } from '@mui/material'; const loginPage = (): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'loginPage' }); @@ -59,6 +61,7 @@ const loginPage = (): JSX.Element => { signEmail: '', signPassword: '', cPassword: '', + signOrg: '', }); const [formState, setFormState] = useState({ email: '', @@ -73,6 +76,7 @@ const loginPage = (): JSX.Element => { numericValue: true, specialChar: true, }); + const [organizations, setOrganizations] = useState([]); const passwordValidationRegExp = { lowercaseCharRegExp: new RegExp('[a-z]'), @@ -115,6 +119,26 @@ const loginPage = (): JSX.Element => { const [signup, { loading: signinLoading }] = useMutation(SIGNUP_MUTATION); const [recaptcha, { loading: recaptchaLoading }] = useMutation(RECAPTCHA_MUTATION); + const { data: orgData } = useQuery(ORGANIZATION_LIST); + + useEffect(() => { + if (orgData) { + const options = orgData.organizations.map( + (org: InterfaceQueryOrganizationListObject) => { + const tempObj: { label: string; id: string } | null = {} as { + label: string; + id: string; + }; + tempObj['label'] = + `${org.name}(${org.address.city},${org.address.state},${org.address.countryCode})`; + tempObj['id'] = org._id; + return tempObj; + }, + ); + setOrganizations(options); + } + }, [orgData]); + useEffect(() => { async function loadResource(): Promise { try { @@ -156,8 +180,14 @@ const loginPage = (): JSX.Element => { const signupLink = async (e: ChangeEvent): Promise => { e.preventDefault(); - const { signfirstName, signlastName, signEmail, signPassword, cPassword } = - signformState; + const { + signfirstName, + signlastName, + signEmail, + signPassword, + cPassword, + signOrg, + } = signformState; const isVerified = await verifyRecaptcha(recaptchaToken); /* istanbul ignore next */ @@ -196,6 +226,7 @@ const loginPage = (): JSX.Element => { lastName: signlastName, email: signEmail, password: signPassword, + orgId: signOrg, }, }); @@ -211,6 +242,7 @@ const loginPage = (): JSX.Element => { signEmail: '', signPassword: '', cPassword: '', + signOrg: '', }); } } catch (error) { @@ -761,6 +793,32 @@ const loginPage = (): JSX.Element => {

    )}
    +
    + {t('selectOrg')} +
    + { + setSignFormState({ + ...signformState, + signOrg: value?.id ?? '', + }); + }} + options={organizations} + renderInput={(params) => ( + + )} + /> +
    +
    {REACT_APP_USE_RECAPTCHA === 'yes' ? (
    Date: Sun, 5 May 2024 13:25:51 -0700 Subject: [PATCH 16/34] Bump follow-redirects from 1.15.5 to 1.15.6 (#1960) Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.5 to 1.15.6. - [Release notes](https://github.com/follow-redirects/follow-redirects/releases) - [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.5...v1.15.6) --- updated-dependencies: - dependency-name: follow-redirects dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index bfbbf48e43..8cebd04140 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11240,9 +11240,9 @@ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" }, "node_modules/follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", From 9b5d158d5ea3d2c6aba07e6b38b000182a77909e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 5 May 2024 13:26:16 -0700 Subject: [PATCH 17/34] Bump tar from 6.1.15 to 6.2.1 (#1959) Bumps [tar](https://github.com/isaacs/node-tar) from 6.1.15 to 6.2.1. - [Release notes](https://github.com/isaacs/node-tar/releases) - [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md) - [Commits](https://github.com/isaacs/node-tar/compare/v6.1.15...v6.2.1) --- updated-dependencies: - dependency-name: tar dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8cebd04140..6b55365b80 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22645,9 +22645,9 @@ } }, "node_modules/tar": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", - "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "optional": true, "peer": true, "dependencies": { From 389ac01d2f7635a0b5f6e7cc4a62d5b45d0939b4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 5 May 2024 13:26:42 -0700 Subject: [PATCH 18/34] Bump tj-actions/changed-files from 40 to 41 in /.github/workflows (#1961) Bumps [tj-actions/changed-files](https://github.com/tj-actions/changed-files) from 40 to 41. - [Release notes](https://github.com/tj-actions/changed-files/releases) - [Changelog](https://github.com/tj-actions/changed-files/blob/main/HISTORY.md) - [Commits](https://github.com/tj-actions/changed-files/compare/v40...v41) --- updated-dependencies: - dependency-name: tj-actions/changed-files dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/pull-request.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index f08efc3b89..558c1f5509 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -42,7 +42,7 @@ jobs: - name: Get changed TypeScript files id: changed-files - uses: tj-actions/changed-files@v40 + uses: tj-actions/changed-files@v41 - name: Check formatting if: steps.changed-files.outputs.only_changed != 'true' @@ -85,7 +85,7 @@ jobs: - name: Get Changed Unauthorized files id: changed-unauth-files - uses: tj-actions/changed-files@v40 + uses: tj-actions/changed-files@v41 with: files: | .github/** @@ -124,7 +124,7 @@ jobs: - name: Get changed files id: changed-files - uses: tj-actions/changed-files@v40 + uses: tj-actions/changed-files@v41 - name: Echo number of changed files env: @@ -177,7 +177,7 @@ jobs: - name: Get changed TypeScript files id: changed-files - uses: tj-actions/changed-files@v40 + uses: tj-actions/changed-files@v41 - name: Run tests if: steps.changed-files.outputs.only_changed != 'true' From d3d681f416c544b51a506bd9e243f7ac5c2b7a50 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 5 May 2024 13:27:05 -0700 Subject: [PATCH 19/34] Bump express from 4.18.2 to 4.19.2 (#1962) Bumps [express](https://github.com/expressjs/express) from 4.18.2 to 4.19.2. - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/master/History.md) - [Commits](https://github.com/expressjs/express/compare/4.18.2...4.19.2) --- updated-dependencies: - dependency-name: express dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6b55365b80..e2f34bb77a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7185,12 +7185,12 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "dependencies": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", @@ -7198,7 +7198,7 @@ "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.11.0", - "raw-body": "2.5.1", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" }, @@ -8299,9 +8299,9 @@ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" }, "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "engines": { "node": ">= 0.6" } @@ -10812,16 +10812,16 @@ } }, "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -19641,9 +19641,9 @@ } }, "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", From 7091c761d14048fa8e50b28bb3167e97cda46841 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 5 May 2024 13:27:27 -0700 Subject: [PATCH 20/34] Bump ejs from 3.1.9 to 3.1.10 (#1963) Bumps [ejs](https://github.com/mde/ejs) from 3.1.9 to 3.1.10. - [Release notes](https://github.com/mde/ejs/releases) - [Commits](https://github.com/mde/ejs/compare/v3.1.9...v3.1.10) --- updated-dependencies: - dependency-name: ejs dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index e2f34bb77a..808f6a2ba4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9514,9 +9514,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/ejs": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz", - "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", "dependencies": { "jake": "^10.8.5" }, From bf9852d96dfcc3e52d42f96f3cbcfc2350703af8 Mon Sep 17 00:00:00 2001 From: Pranshu Gupta Date: Sun, 19 May 2024 20:00:08 +0530 Subject: [PATCH 21/34] coderabbit yaml file (#1991) --- .coderabbit.yaml | 17 +++++++++++++++++ .github/workflows/pull-request.yml | 3 +++ INSTALLATION.md | 7 ++----- 3 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 .coderabbit.yaml diff --git a/.coderabbit.yaml b/.coderabbit.yaml new file mode 100644 index 0000000000..124f0a7db0 --- /dev/null +++ b/.coderabbit.yaml @@ -0,0 +1,17 @@ +# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json +language: "en-US" +early_access: false +reviews: + profile: "chill" + request_changes_workflow: true + high_level_summary: true + poem: true + review_status: true + collapse_walkthrough: false + auto_review: + enabled: true + drafts: false + base_branches: + - develop +chat: + auto_reply: true diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 558c1f5509..99d9355292 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -98,12 +98,15 @@ jobs: .gitignore .eslintrc.json .eslintignore + .prettierrc + .prettierignore vite.config.ts docker-compose.yaml Dockerfile CODEOWNERS LICENSE setup.ts + .coderabbit.yaml - name: List all changed unauthorized files if: steps.changed-unauth-files.outputs.any_changed == 'true' || steps.changed-unauth-files.outputs.any_deleted == 'true' diff --git a/INSTALLATION.md b/INSTALLATION.md index 98de170d6d..05ede15d0c 100644 --- a/INSTALLATION.md +++ b/INSTALLATION.md @@ -6,8 +6,6 @@ This document provides instructions on how to set up and start a running instanc -- [Talawa-Admin Installation](#talawa-admin-installation) -- [Table of Contents](#table-of-contents) - [Installation Steps Summary](#installation-steps-summary) - [Prerequisites](#prerequisites) - [Install git](#install-git) @@ -18,8 +16,8 @@ This document provides instructions on how to set up and start a running instanc - [Configuration](#configuration) - [Creating .env file](#creating-env-file) - [Setting up PORT in .env file](#setting-up-port-in-env-file) - - [Setting up REACT\_APP\_TALAWA\_URL in .env file](#setting-up-react_app_talawa_url-in-env-file) - - [Setting up REACT\_APP\_RECAPTCHA\_SITE\_KEY in .env file](#setting-up-react_app_recaptcha_site_key-in-env-file) + - [Setting up REACT_APP_TALAWA_URL in .env file](#setting-up-react_app_talawa_url-in-env-file) + - [Setting up REACT_APP_RECAPTCHA_SITE_KEY in .env file](#setting-up-react_app_recaptcha_site_key-in-env-file) - [Setting up Compiletime and Runtime logs](#setting-up-compiletime-and-runtime-logs) - [Post Configuration Steps](#post-configuration-steps) - [Running Talawa-Admin](#running-talawa-admin) @@ -36,7 +34,6 @@ This document provides instructions on how to set up and start a running instanc - # Installation Steps Summary Installation is not difficult, but there are many steps. This is a brief explanation of what needs to be done: From f661cc9a1ce4715c1523fbf90b342ea2a4987ba0 Mon Sep 17 00:00:00 2001 From: Peter Harrison <16875803+palisadoes@users.noreply.github.com> Date: Sun, 2 Jun 2024 09:08:03 -0700 Subject: [PATCH 22/34] Updating the main branch to the latest develop code (#2020) * Deleted all files in the main branch in anticipation of merging develop into main cleanly * Merge develop into main --------- Co-authored-by: Peter Harrison --- .coderabbit.yaml | 2 +- .dockerignore | 8 - .github/workflows/compare_translations.py | 56 +- .github/workflows/pull-request.yml | 8 +- package-lock.json | 641 ++++----- package.json | 24 +- public/locales/en/common.json | 65 + public/locales/en/errors.json | 9 + .../locales/{en.json => en/translation.json} | 348 +---- public/locales/fr.json | 1133 ---------------- public/locales/fr/common.json | 65 + public/locales/fr/errors.json | 9 + public/locales/fr/translation.json | 892 +++++++++++++ public/locales/hi.json | 1140 ----------------- public/locales/hi/common.json | 65 + public/locales/hi/errors.json | 9 + public/locales/hi/translation.json | 892 +++++++++++++ public/locales/sp/common.json | 65 + public/locales/sp/errors.json | 9 + .../locales/{sp.json => sp/translation.json} | 0 public/locales/zh.json | 1138 ---------------- public/locales/zh/common.json | 65 + public/locales/zh/errors.json | 9 + public/locales/zh/translation.json | 892 +++++++++++++ src/App.tsx | 7 +- src/GraphQl/Mutations/mutations.ts | 4 +- .../ActionItems/ActionItemsContainer.tsx | 2 + .../ActionItems/ActionItemsModalBody.tsx | 5 +- .../core/AddOnRegister/AddOnRegister.tsx | 5 +- .../Advertisements/Advertisements.test.tsx | 39 +- .../Advertisements/Advertisements.tsx | 7 +- .../AdvertisementEntry/AdvertisementEntry.tsx | 23 +- .../AdvertisementRegister.test.tsx | 55 +- .../AdvertisementRegister.tsx | 21 +- .../CollapsibleDropdown.test.tsx | 16 +- .../CollapsibleDropdown.tsx | 6 +- src/components/DeleteOrg/DeleteOrg.tsx | 3 +- .../EventCalendar/EventCalendar.test.tsx | 3 +- .../EventCalendar/YearlyEventCalender.tsx | 2 +- .../EventDashboardScreen.tsx | 4 +- .../EventListCard/EventListCard.test.tsx | 50 +- .../EventListCard/EventListCard.tsx | 2 + .../EventListCard/EventListCardModals.tsx | 31 +- .../EventActionItems.module.css | 4 +- .../EventActionItems/EventActionItems.tsx | 5 +- src/components/LeftDrawer/LeftDrawer.tsx | 9 +- .../LeftDrawerOrg/LeftDrawerOrg.tsx | 12 +- .../LoginPortalToggle/LoginPortalToggle.tsx | 6 +- .../MemberRequestCard/MemberRequestCard.tsx | 7 +- .../OrgActionItemCategories.test.tsx | 38 +- .../OrgActionItemCategories.tsx | 11 +- .../OrgAdminListCard.test.tsx | 7 +- .../OrgAdminListCard/OrgAdminListCard.tsx | 5 +- src/components/OrgListCard/OrgListCard.tsx | 5 +- .../OrgPeopleListCard/OrgPeopleListCard.tsx | 5 +- .../OrgPostCard/OrgPostCard.test.tsx | 6 + src/components/OrgPostCard/OrgPostCard.tsx | 68 +- .../OrgProfileFieldSettings.tsx | 7 +- src/components/OrgUpdate/OrgUpdate.tsx | 17 +- .../CustomRecurrenceModal.tsx | 6 +- .../RecurrenceOptions.test.tsx | 26 +- .../RecurrenceOptions/RecurrenceOptions.tsx | 3 + .../UserPasswordUpdate/UserPasswordUpdate.tsx | 11 +- .../CommentCard/CommentCard.module.css | 12 +- .../UserPortal/CommentCard/CommentCard.tsx | 6 +- .../UserPortal/EventCard/EventCard.tsx | 7 +- .../UserPortal/Login/Login.test.tsx | 26 +- src/components/UserPortal/Login/Login.tsx | 19 +- .../OrganizationCard/OrganizationCard.tsx | 18 +- .../OrganizationNavbar/OrganizationNavbar.tsx | 11 +- .../OrganizationSidebar.tsx | 107 +- .../UserPortal/PostCard/PostCard.module.css | 145 ++- .../UserPortal/PostCard/PostCard.test.tsx | 290 ++++- .../UserPortal/PostCard/PostCard.tsx | 380 ++++-- .../UserPortal/Register/Register.tsx | 23 +- .../StartPostModal/StartPostModal.test.tsx | 70 +- .../StartPostModal/StartPostModal.tsx | 66 +- .../UserPortal/UserNavbar/UserNavbar.tsx | 5 +- .../UserPortal/UserSidebar/UserSidebar.tsx | 7 +- .../UserSidebarOrg/UserSidebarOrg.tsx | 3 +- .../UserProfileSettings/UserProfile.tsx | 3 +- .../UsersTableItem/UserTableItem.test.tsx | 256 +++- .../UsersTableItem/UserTableItemMocks.ts | 48 +- .../UsersTableItem/UsersTableItem.tsx | 81 +- src/components/Venues/VenueCard.tsx | 8 +- src/components/Venues/VenueModal.tsx | 3 +- src/screens/BlockUser/BlockUser.tsx | 19 +- .../ForgotPassword/ForgotPassword.test.tsx | 12 +- src/screens/ForgotPassword/ForgotPassword.tsx | 26 +- .../FundCampaignPledge.test.tsx | 37 +- .../FundCampaignPledge/FundCampaignPledge.tsx | 291 ++--- .../FundCampaignPledge/PledgeCreateModal.tsx | 6 +- .../FundCampaignPledge/PledgeDeleteModal.tsx | 6 +- .../FundCampaignPledge/PledgeEditModal.tsx | 6 +- src/screens/LoginPage/LoginPage.tsx | 55 +- src/screens/MemberDetail/MemberDetail.tsx | 25 +- src/screens/OrgList/OrgList.test.tsx | 2 +- src/screens/OrgList/OrgList.tsx | 52 +- src/screens/OrgList/OrgListMocks.ts | 16 +- src/screens/OrgList/OrganizationModal.tsx | 14 +- src/screens/OrgPost/OrgPost.tsx | 13 +- .../ActionItemDeleteModal.tsx | 6 +- .../OrganizationActionItems.test.tsx | 48 +- .../OrganizationActionItems.tsx | 3 +- .../OrganizationDashboard.tsx | 29 +- .../OrganizationEvents.test.tsx | 46 +- .../OrganizationEvents/OrganizationEvents.tsx | 16 +- .../CampaignDeleteModal.tsx | 6 +- .../OrganizationFundCampagins.tsx | 8 +- .../OrganizationFunds/OrganizationFunds.tsx | 3 +- .../OrganizationPeople.module.css | 4 +- .../OrganizationPeople/OrganizationPeople.tsx | 9 +- .../OrganizationVenues/OrganizationVenues.tsx | 5 +- .../PageNotFound/PageNotFound.test.tsx | 2 +- src/screens/PageNotFound/PageNotFound.tsx | 8 +- src/screens/Requests/Requests.test.tsx | 2 +- src/screens/Requests/Requests.tsx | 9 +- src/screens/UserPortal/Chat/Chat.tsx | 41 +- src/screens/UserPortal/Events/Events.tsx | 138 +- .../Organizations/Organizations.tsx | 2 +- src/screens/UserPortal/People/People.tsx | 5 +- src/screens/UserPortal/Posts/Posts.module.css | 57 +- src/screens/UserPortal/Posts/Posts.test.tsx | 31 +- src/screens/UserPortal/Posts/Posts.tsx | 321 ++--- src/screens/UserPortal/Settings/Settings.tsx | 17 +- src/screens/Users/Users.tsx | 19 +- src/state/reducers/routesReducer.test.ts | 12 +- src/state/reducers/routesReducer.ts | 2 +- src/utils/errorHandler.test.tsx | 11 +- src/utils/errorHandler.tsx | 20 +- src/utils/i18n.ts | 4 +- src/utils/i18nForTest.ts | 8 +- src/utils/interfaces.ts | 2 + 133 files changed, 5708 insertions(+), 5447 deletions(-) delete mode 100644 .dockerignore create mode 100644 public/locales/en/common.json create mode 100644 public/locales/en/errors.json rename public/locales/{en.json => en/translation.json} (73%) delete mode 100644 public/locales/fr.json create mode 100644 public/locales/fr/common.json create mode 100644 public/locales/fr/errors.json create mode 100644 public/locales/fr/translation.json delete mode 100644 public/locales/hi.json create mode 100644 public/locales/hi/common.json create mode 100644 public/locales/hi/errors.json create mode 100644 public/locales/hi/translation.json create mode 100644 public/locales/sp/common.json create mode 100644 public/locales/sp/errors.json rename public/locales/{sp.json => sp/translation.json} (100%) delete mode 100644 public/locales/zh.json create mode 100644 public/locales/zh/common.json create mode 100644 public/locales/zh/errors.json create mode 100644 public/locales/zh/translation.json diff --git a/.coderabbit.yaml b/.coderabbit.yaml index 124f0a7db0..46e2d25b8c 100644 --- a/.coderabbit.yaml +++ b/.coderabbit.yaml @@ -14,4 +14,4 @@ reviews: base_branches: - develop chat: - auto_reply: true + auto_reply: true \ No newline at end of file diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index 06d9a3ecb2..0000000000 --- a/.dockerignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -videos -images -.env -.git -.gitignore -.github -.dockerignore \ No newline at end of file diff --git a/.github/workflows/compare_translations.py b/.github/workflows/compare_translations.py index f6f22e843c..fd4f772605 100644 --- a/.github/workflows/compare_translations.py +++ b/.github/workflows/compare_translations.py @@ -98,9 +98,15 @@ def load_translation(filepath): Returns: translation: Loaded translation """ - with open(filepath, "r", encoding="utf-8") as file: - translation = json.load(file) - return translation + try: + with open(filepath, "r", encoding="utf-8") as file: + content = file.read() + if not content.strip(): + raise ValueError(f"File {filepath} is empty.") + translation = json.loads(content) + return translation + except json.JSONDecodeError as e: + raise ValueError(f"Error decoding JSON from file {filepath}: {e}") def check_translations(directory): @@ -112,26 +118,36 @@ def check_translations(directory): Returns: None """ - default_file = "en.json" - default_translation = load_translation(os.path.join(directory, default_file)) - translations = os.listdir(directory) - translations.remove(default_file) # Exclude default translation + default_language_dir = os.path.join(directory, "en") + default_files = ["common.json", "errors.json", "translation.json"] + default_translations = {} + for file in default_files: + file_path = os.path.join(default_language_dir, file) + default_translations[file] = load_translation(file_path) + + languages = os.listdir(directory) + languages.remove("en") # Exclude default language directory + error_found = False - for translation_file in translations: - other_file = os.path.join(directory, translation_file) - other_translation = load_translation(other_file) + for language in languages: + language_dir = os.path.join(directory, language) + for file in default_files: + default_translation = default_translations[file] + other_file_path = os.path.join(language_dir, file) + other_translation = load_translation(other_file_path) + + # Compare translations and get detailed error messages + errors = compare_translations( + default_translation, other_translation, f"en/{file}", f"{language}/{file}" + ) + if errors: + error_found = True + print(f"File {language}/{file} has missing translations for:") + for error in errors: + print(f" - {error}") - # Compare translations and get detailed error messages - errors = compare_translations( - default_translation, other_translation, default_file, translation_file - ) - if errors: - error_found = True - print(f"File {translation_file} has missing translations for:") - for error in errors: - print(f" - {error}") if error_found: sys.exit(1) # Exit with an error status code @@ -154,7 +170,7 @@ def main(): "--directory", type=str, nargs="?", - default=os.path.join(os.getcwd(), "public/locales"), + default=os.path.join(os.getcwd(), "locales"), help="Directory containing translation files(relative to the root directory).", ) args = parser.parse_args() diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 99d9355292..1ec7380c6c 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -42,7 +42,7 @@ jobs: - name: Get changed TypeScript files id: changed-files - uses: tj-actions/changed-files@v41 + uses: tj-actions/changed-files@v40 - name: Check formatting if: steps.changed-files.outputs.only_changed != 'true' @@ -85,7 +85,7 @@ jobs: - name: Get Changed Unauthorized files id: changed-unauth-files - uses: tj-actions/changed-files@v41 + uses: tj-actions/changed-files@v40 with: files: | .github/** @@ -127,7 +127,7 @@ jobs: - name: Get changed files id: changed-files - uses: tj-actions/changed-files@v41 + uses: tj-actions/changed-files@v40 - name: Echo number of changed files env: @@ -180,7 +180,7 @@ jobs: - name: Get changed TypeScript files id: changed-files - uses: tj-actions/changed-files@v41 + uses: tj-actions/changed-files@v40 - name: Run tests if: steps.changed-files.outputs.only_changed != 'true' diff --git a/package-lock.json b/package-lock.json index 808f6a2ba4..e60d88abe1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,25 +11,25 @@ "@apollo/client": "^3.4.0-beta.19", "@apollo/link-error": "^2.0.0-beta.3", "@apollo/react-testing": "^4.0.0", - "@dicebear/collection": "^7.0.4", - "@dicebear/core": "^7.0.4", + "@dicebear/collection": "^8.0.1", + "@dicebear/core": "^8.0.1", "@emotion/react": "^11.11.1", - "@emotion/styled": "^11.11.0", + "@emotion/styled": "^11.11.5", "@mui/icons-material": "^5.8.3", "@mui/material": "^5.15.15", "@mui/private-theming": "^5.15.12", "@mui/system": "^5.14.12", - "@mui/x-charts": "^6.0.0-alpha.13", - "@mui/x-data-grid": "^6.8.0", + "@mui/x-charts": "^7.4.0", + "@mui/x-data-grid": "^6.20.0", "@mui/x-date-pickers": "^6.6.0", "@pdfme/generator": "^1.2.6", "bootstrap": "^5.3.0", "customize-cra": "^1.0.0", - "dayjs": "^1.10.7", + "dayjs": "^1.11.11", "flag-icons": "^6.6.6", - "graphql": "^15.5.1", + "graphql": "^16.8.1", "graphql-tag": "^2.12.6", - "graphql-ws": "^5.14.0", + "graphql-ws": "^5.16.0", "history": "^5.3.0", "i18next": "^21.8.14", "i18next-browser-languagedetector": "^6.1.4", @@ -45,7 +45,7 @@ "react-dom": "^17.0.2", "react-google-recaptcha": "^2.1.0", "react-i18next": "^11.18.1", - "react-icons": "^4.12.0", + "react-icons": "^5.2.1", "react-infinite-scroll-component": "^6.1.0", "react-redux": "^7.2.5", "react-router-dom": "^6.22.2", @@ -53,8 +53,8 @@ "react-toastify": "^9.0.3", "redux": "^4.1.1", "redux-thunk": "^2.3.0", - "sanitize-html": "^2.12.1", - "typedoc-plugin-markdown": "^3.17.1", + "sanitize-html": "^2.13.0", + "typedoc-plugin-markdown": "^4.0.2", "typescript": "^4.3.5", "web-vitals": "^1.0.1" }, @@ -66,7 +66,7 @@ "@types/inquirer": "^9.0.7", "@types/jest": "^26.0.24", "@types/js-cookie": "^3.0.6", - "@types/node": "^20.12.7", + "@types/node": "^20.12.12", "@types/node-fetch": "^2.6.10", "@types/react": "^17.0.14", "@types/react-bootstrap": "^0.32.32", @@ -2634,149 +2634,149 @@ } }, "node_modules/@dicebear/adventurer": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/adventurer/-/adventurer-7.0.4.tgz", - "integrity": "sha512-1ya9lD0S8YHaW+1+bky9HCnLWve/gjiFtZ1wjEM26nBxrFBCmvgiqPn/+L/Uf0ercHIyXMRElHylWmLxtWztfQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/adventurer/-/adventurer-8.0.1.tgz", + "integrity": "sha512-dlEycOH+yETbNo3EtswFJCnG02OEgpyPpOFmSgUuRhcRKsqbMlcsiYV4wKeRvq6VvudJXp8UiHwWszLjCHTvKA==", "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@dicebear/core": "^7.0.0" + "@dicebear/core": "^8.0.0" } }, "node_modules/@dicebear/adventurer-neutral": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/adventurer-neutral/-/adventurer-neutral-7.0.4.tgz", - "integrity": "sha512-meAMZFLzvqf58p8Qno4vKRmwss2XdKn5osG5/xPkiXVUVhtNEtVoKSIG0KK9ukjC18UOHo6mjZab7xUclz6o4Q==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/adventurer-neutral/-/adventurer-neutral-8.0.1.tgz", + "integrity": "sha512-NgSz01T/K6MJn93Lk8rKPGKTx6cJe4/lNKMKjRM+4mez8S56WNdGDGUn/QY5GL3P1p01QAOMFF3hygJk3WAr3g==", "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@dicebear/core": "^7.0.0" + "@dicebear/core": "^8.0.0" } }, "node_modules/@dicebear/avataaars": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/avataaars/-/avataaars-7.0.4.tgz", - "integrity": "sha512-mkQDtGYfj4rVguuPednpKj2RQWyV1pew3GqcKfjz77HBfhHeXDDwlMqWPQkaKyYkI0V9q3LtApGECyxYiisDvA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/avataaars/-/avataaars-8.0.1.tgz", + "integrity": "sha512-TYXqP9mq3yHOdLlJr8saXnvxj14eY2YAmoVVbT15Rp5+kPzGDyfblNsM838sP5K6JyCNeojZsGE/sPJKk/G+mA==", "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@dicebear/core": "^7.0.0" + "@dicebear/core": "^8.0.0" } }, "node_modules/@dicebear/avataaars-neutral": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/avataaars-neutral/-/avataaars-neutral-7.0.4.tgz", - "integrity": "sha512-EpbeiY23G4fuL2DnZ7fjnSn8WZvdALgg/N3pQpn8yPDdulgaV4vRDOit94pvp/DjW0Zz7mPPkSEN//0zijcXvA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/avataaars-neutral/-/avataaars-neutral-8.0.1.tgz", + "integrity": "sha512-vMV1Htaqpnz+qAVyn2tJWbRQIa6mpO/bu7dD0dumuIb45+LIpNwdUuCvkIQw2qf5ODhn1WAfYX3HEJaxRZc4lA==", "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@dicebear/core": "^7.0.0" + "@dicebear/core": "^8.0.0" } }, "node_modules/@dicebear/big-ears": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/big-ears/-/big-ears-7.0.4.tgz", - "integrity": "sha512-yOvIVFOB8Wv9ulSp6vIyEHiIHkishnLEuKIPAcgGScxjlbtcAo9OmeUsgSmM03wYsV62jInaiA4hAHRPfLYzfQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/big-ears/-/big-ears-8.0.1.tgz", + "integrity": "sha512-lnPRFbXsHv2EXJR2OLqJdoUIrSVUpf1z4GkCOfAi01sYNYVpfnzg3kNF77QUhkXUhaONF7d4Wz8rUduBHRtjaA==", "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@dicebear/core": "^7.0.0" + "@dicebear/core": "^8.0.0" } }, "node_modules/@dicebear/big-ears-neutral": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/big-ears-neutral/-/big-ears-neutral-7.0.4.tgz", - "integrity": "sha512-kxydevCihleTG5TnIh604i/zi+1MMvPuFuecattcUoa3NIPx4zi08j2zb7gwTUX54l49ENG1ZSO058S9c03yrA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/big-ears-neutral/-/big-ears-neutral-8.0.1.tgz", + "integrity": "sha512-2FPvNpLI/ald3P8iWhX7SR986B8/DQlvrTNK/v+V0HRJvG1t6/7f9qfUL7OLf6plL7EgSUmKfMKacdiR5skZkA==", "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@dicebear/core": "^7.0.0" + "@dicebear/core": "^8.0.0" } }, "node_modules/@dicebear/big-smile": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/big-smile/-/big-smile-7.0.4.tgz", - "integrity": "sha512-vHuedMXdK5RGhXDSCY+U9vDyfby20m3eteYSgEwLKmi3ZJBLXw2xAuAb8cGMPmK7zsyj4eH50r93hKcaTaOTag==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/big-smile/-/big-smile-8.0.1.tgz", + "integrity": "sha512-uh7FP0RgX8Qtr5zpeKUSNq028IQ3srF5LHJfQGjf4wA8R+ln/Sq0gPRJk6qMCCvPFV42b7A6f7rO7mHGnQ+qDA==", "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@dicebear/core": "^7.0.0" + "@dicebear/core": "^8.0.0" } }, "node_modules/@dicebear/bottts": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/bottts/-/bottts-7.0.4.tgz", - "integrity": "sha512-Nni2Y5rL6+CJ8/Cij1lCvV/YhI+i3cy//nWQQGqmGTqlCGZdOziDGCWuf7Ufmv8081sbKWj++QOP+ueAX8E7ZA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/bottts/-/bottts-8.0.1.tgz", + "integrity": "sha512-WmaGZnKAT90EP/pzfUox22RshCk3GLB/p+6SsjD0ZIBNjcMXhaJroSoGVcHmPgQVzZBDIdW9C0qDKhkCNVVizg==", "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@dicebear/core": "^7.0.0" + "@dicebear/core": "^8.0.0" } }, "node_modules/@dicebear/bottts-neutral": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/bottts-neutral/-/bottts-neutral-7.0.4.tgz", - "integrity": "sha512-C9McuZSdrMypTAOSsNJMgsbb2wylHbrvkPyksyouSgeIRrr3vdJFAsa+N1UfApNj4YdsznmoBIMl2XAGktTBAg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/bottts-neutral/-/bottts-neutral-8.0.1.tgz", + "integrity": "sha512-krbD3U+UvzlY+kfQDpg9Hql1xJmmu3y9ensiU+XZXiuNw/ZavgGqpJtzpbYeF3J5GsggQlbBh/ZAK9AIKz7S3Q==", "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@dicebear/core": "^7.0.0" + "@dicebear/core": "^8.0.0" } }, "node_modules/@dicebear/collection": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/collection/-/collection-7.0.4.tgz", - "integrity": "sha512-5jXmitM/DGwmorp9hGh5coEhrMLsygEYNJiOf6eH0loVeXjI0/X3TEmQabtXzwp/nVhBGYyvuBmPIg50fnUhxQ==", - "dependencies": { - "@dicebear/adventurer": "7.0.4", - "@dicebear/adventurer-neutral": "7.0.4", - "@dicebear/avataaars": "7.0.4", - "@dicebear/avataaars-neutral": "7.0.4", - "@dicebear/big-ears": "7.0.4", - "@dicebear/big-ears-neutral": "7.0.4", - "@dicebear/big-smile": "7.0.4", - "@dicebear/bottts": "7.0.4", - "@dicebear/bottts-neutral": "7.0.4", - "@dicebear/croodles": "7.0.4", - "@dicebear/croodles-neutral": "7.0.4", - "@dicebear/fun-emoji": "7.0.4", - "@dicebear/icons": "7.0.4", - "@dicebear/identicon": "7.0.4", - "@dicebear/initials": "7.0.4", - "@dicebear/lorelei": "7.0.4", - "@dicebear/lorelei-neutral": "7.0.4", - "@dicebear/micah": "7.0.4", - "@dicebear/miniavs": "7.0.4", - "@dicebear/notionists": "7.0.4", - "@dicebear/notionists-neutral": "7.0.4", - "@dicebear/open-peeps": "7.0.4", - "@dicebear/personas": "7.0.4", - "@dicebear/pixel-art": "7.0.4", - "@dicebear/pixel-art-neutral": "7.0.4", - "@dicebear/rings": "7.0.4", - "@dicebear/shapes": "7.0.4", - "@dicebear/thumbs": "7.0.4" + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/collection/-/collection-8.0.1.tgz", + "integrity": "sha512-RlWvOOXTxqP1llNzWhrnm6wCMKFAku/Ty0YJNv+4LYA1YIDpyLNN2PwxxCuj7hU244qUwQcVPQPPPr0XQ+rA/g==", + "dependencies": { + "@dicebear/adventurer": "8.0.1", + "@dicebear/adventurer-neutral": "8.0.1", + "@dicebear/avataaars": "8.0.1", + "@dicebear/avataaars-neutral": "8.0.1", + "@dicebear/big-ears": "8.0.1", + "@dicebear/big-ears-neutral": "8.0.1", + "@dicebear/big-smile": "8.0.1", + "@dicebear/bottts": "8.0.1", + "@dicebear/bottts-neutral": "8.0.1", + "@dicebear/croodles": "8.0.1", + "@dicebear/croodles-neutral": "8.0.1", + "@dicebear/fun-emoji": "8.0.1", + "@dicebear/icons": "8.0.1", + "@dicebear/identicon": "8.0.1", + "@dicebear/initials": "8.0.1", + "@dicebear/lorelei": "8.0.1", + "@dicebear/lorelei-neutral": "8.0.1", + "@dicebear/micah": "8.0.1", + "@dicebear/miniavs": "8.0.1", + "@dicebear/notionists": "8.0.1", + "@dicebear/notionists-neutral": "8.0.1", + "@dicebear/open-peeps": "8.0.1", + "@dicebear/personas": "8.0.1", + "@dicebear/pixel-art": "8.0.1", + "@dicebear/pixel-art-neutral": "8.0.1", + "@dicebear/rings": "8.0.1", + "@dicebear/shapes": "8.0.1", + "@dicebear/thumbs": "8.0.1" }, "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@dicebear/core": "^7.0.0" + "@dicebear/core": "^8.0.0" } }, "node_modules/@dicebear/converter": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/converter/-/converter-7.0.4.tgz", - "integrity": "sha512-oiA2Oc5izWf6ipPtHYCi2c9W565VzyryObtSL6xB36V9MHRD8wvH5mYr9AvbViDGEOOeNE3EtIELQIMdNtB7Rg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/converter/-/converter-8.0.1.tgz", + "integrity": "sha512-65L04fN4V07WcUnwQuDYDH+zrP8WA6/UeIuqqH/Pv7VWoJtIk9qHlaA+XGpPr4qgRtkmY7uXVkrED/RMlqvUDA==", "dependencies": { "@types/json-schema": "^7.0.11", "tmp-promise": "^3.0.3" @@ -2802,11 +2802,11 @@ } }, "node_modules/@dicebear/core": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/core/-/core-7.0.4.tgz", - "integrity": "sha512-Xi8Au8K4pWj61jKMKqlhqmg83DvMAG6PfDuDbp7F75ZNvrGGh0BkJt9keSHe4WpHs+BbXDXSMOivSS10QB20fA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/core/-/core-8.0.1.tgz", + "integrity": "sha512-HWqvQRpVjkboQXinCOjU3poZIMd5p+32wPvc9N5fYiXe3KQLhJNw5T5XiRttDUm3XpoTvhQ4DVTPDsXT8CqrTg==", "dependencies": { - "@dicebear/converter": "7.0.4", + "@dicebear/converter": "8.0.1", "@types/json-schema": "^7.0.11" }, "engines": { @@ -2814,212 +2814,212 @@ } }, "node_modules/@dicebear/croodles": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/croodles/-/croodles-7.0.4.tgz", - "integrity": "sha512-PMe7W2IE8R9yqEXuccfEaTF0D+1VXrCXnShw52D5C23qPDTxL1XxZKXcOoeXYi5o1jeIVagZjHiX8XaQK18ftQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/croodles/-/croodles-8.0.1.tgz", + "integrity": "sha512-4si6gm61hEI8uDk+7OhSX+0qSPfotYx1dbdBphgGgiP9KTOgipnXzNtz8YnGzNf+V89nV4twHa6Bl6Wna4kFYA==", "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@dicebear/core": "^7.0.0" + "@dicebear/core": "^8.0.0" } }, "node_modules/@dicebear/croodles-neutral": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/croodles-neutral/-/croodles-neutral-7.0.4.tgz", - "integrity": "sha512-b7v1WPEDKWzJAcCMo8OQMMgRTI0c2Ae3dCLBbFXtkhJ6oqzuFUbWwcrUWsp0segBXlPAM3lZrH1gy1GJBHrSuQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/croodles-neutral/-/croodles-neutral-8.0.1.tgz", + "integrity": "sha512-DlR1wxzacRc3GhkMRg4MJ4CBfci/Z96SUl3YpvhHQ4ZtPldaQmdxs3jzOlnG1cuNRkqmiB1D66EXj5146V5WMA==", "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@dicebear/core": "^7.0.0" + "@dicebear/core": "^8.0.0" } }, "node_modules/@dicebear/fun-emoji": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/fun-emoji/-/fun-emoji-7.0.4.tgz", - "integrity": "sha512-rlaID1EQW8pj/TmM805+dA6XVLge2hkiVaQkoM+4Df/RGj/GPbDeBgu8dRKLwORPNY5ug3zfFgERStZcSyYmqQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/fun-emoji/-/fun-emoji-8.0.1.tgz", + "integrity": "sha512-s2zXyZ7Rp3E2OHxAghhKIYmTtQ64D1VU+/p0VNaIQTPnyfxgpdrKlBMAlp4fXHyirhtAWCHSWgXcU9UFvlmr+w==", "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@dicebear/core": "^7.0.0" + "@dicebear/core": "^8.0.0" } }, "node_modules/@dicebear/icons": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/icons/-/icons-7.0.4.tgz", - "integrity": "sha512-wkWjjkDD43lmYKgCBDdUc54y6llCsCOSPND2RnKi6noOGpThsN6aTE6nN2Hwf0ORxWPEzBFRmgoat+frWd9a4A==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/icons/-/icons-8.0.1.tgz", + "integrity": "sha512-uInO34VW1etgMsbarXIeYULTk+dlj0L9vW7nUinWqwwEbimgXT4iqzNSjQyogmQ3wmaahI1zNwrGUkfkQojouw==", "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@dicebear/core": "^7.0.0" + "@dicebear/core": "^8.0.0" } }, "node_modules/@dicebear/identicon": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/identicon/-/identicon-7.0.4.tgz", - "integrity": "sha512-Q68lP7dqqt0fMx9SONPJSi94aieNveTyrCgv/kuU3F9upeQyesmdAeQ+e2QOojOOMrEuM+ujFuPInvwwkaZF7w==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/identicon/-/identicon-8.0.1.tgz", + "integrity": "sha512-mIHBuUlTs1RNZg+9k4NIjYXYjZBh08ksK/7Pmb+5twsoIPuAPjZ+FbQsfc27Wga/IuJfgf9mYBq6Sxc8/LQxjg==", "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@dicebear/core": "^7.0.0" + "@dicebear/core": "^8.0.0" } }, "node_modules/@dicebear/initials": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/initials/-/initials-7.0.4.tgz", - "integrity": "sha512-cNkuG/3cPbF4UScmLk+2nYF2LaB9N1k3Pw1gmd3PST+oUsdlkNIM6e4Wym/0fgDLGPWyxbiGsbhe371ACWJVNQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/initials/-/initials-8.0.1.tgz", + "integrity": "sha512-ctO1f92XAms72qkhiKI/vvS/E6mco1RiTEACPJGv6hDPfdjR1vxpkzFpo3jm3RohfwOPCN5fH2l3BSinnlbzzw==", "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@dicebear/core": "^7.0.0" + "@dicebear/core": "^8.0.0" } }, "node_modules/@dicebear/lorelei": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/lorelei/-/lorelei-7.0.4.tgz", - "integrity": "sha512-pFDNHns7lke3M+TGPHFizjsjBMM/70okdH4Y+WKg9WHe+Y0dV54OgXf9/I6A10ipdVTCtM4i2xfNkSW+QP/spQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/lorelei/-/lorelei-8.0.1.tgz", + "integrity": "sha512-AY9XDeV7pIojDziiT/9flPWvH/5dswlVvezHQljmLa1H6EIQAIRWj9INeDaS2u2hRTFQKVeYQ1kuP3Omb+t26A==", "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@dicebear/core": "^7.0.0" + "@dicebear/core": "^8.0.0" } }, "node_modules/@dicebear/lorelei-neutral": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/lorelei-neutral/-/lorelei-neutral-7.0.4.tgz", - "integrity": "sha512-QtyKGJhExocZse662b1W5LGh0ykFh4AFf827f5FkXiOGmAgghsm1m/0bFuF9giwqFJ7W3eZu5oTSn97+s3z17A==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/lorelei-neutral/-/lorelei-neutral-8.0.1.tgz", + "integrity": "sha512-vC5M7jg6UByJyFjBitLB3xKr435FdH8BHD8oVzf9A2MXi/ovQ0bEak9MnxVcrxUufJx7bsgS/XCRYNLUwaQKyw==", "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@dicebear/core": "^7.0.0" + "@dicebear/core": "^8.0.0" } }, "node_modules/@dicebear/micah": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/micah/-/micah-7.0.4.tgz", - "integrity": "sha512-c6U9iqsEsuPqHxiZuM5O7xqJIv98rIMergdi6O8jlINXacNLzF9DUHLAkxMiFeiqDDqQ34wUQq+M6qt9xBq0eQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/micah/-/micah-8.0.1.tgz", + "integrity": "sha512-B7+YCX62CqnjLlJNY6+NXy+HJlyGMzCbrnE38bGdmnH7PZ1IrEnmJny41AcopKziE02h65kdwCZFXy/v7piT4g==", "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@dicebear/core": "^7.0.0" + "@dicebear/core": "^8.0.0" } }, "node_modules/@dicebear/miniavs": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/miniavs/-/miniavs-7.0.4.tgz", - "integrity": "sha512-p1sWveGT3gvtnwplhDakB6wEu5jT/EHbRzsTMOT3Lz9nqkF08sJCe7KCRsji1EVGyX4nOjA+dQcHK9yUAdqQAg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/miniavs/-/miniavs-8.0.1.tgz", + "integrity": "sha512-mzNAa2cIvsyeRuSnWoQ6l23yiw4BhmzrwdmfJZuDLloh/UNJjyiiCItYSTBmhtxcJrWX8YQTd/2hPdXjsdceTA==", "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@dicebear/core": "^7.0.0" + "@dicebear/core": "^8.0.0" } }, "node_modules/@dicebear/notionists": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/notionists/-/notionists-7.0.4.tgz", - "integrity": "sha512-twmpHy2S6FkTiPzNd0wXuWhBv0XgkCPIuzJiUeyTadVEjlijOvPeAr9kuGuhDMO7MTHnuQoFRw1sctQmj+xbXA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/notionists/-/notionists-8.0.1.tgz", + "integrity": "sha512-wOZPSj7lKIJkxiJHysGUVehPmaisWV9dUNhs4jDApiit3u6cbspDEOXvlAn/68cpGP8LfjsdyCp8yhZ9Wvk15Q==", "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@dicebear/core": "^7.0.0" + "@dicebear/core": "^8.0.0" } }, "node_modules/@dicebear/notionists-neutral": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/notionists-neutral/-/notionists-neutral-7.0.4.tgz", - "integrity": "sha512-tk06h7uj1IR42g/RhhLVv1rbxy+rNROhXSto5ADX0/Ovk+HaR8yQGQyO3Tt/rXpGuf5+5JK0sVAiRgGaMFSxig==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/notionists-neutral/-/notionists-neutral-8.0.1.tgz", + "integrity": "sha512-j70iiLZPpLw9JfyziRC8jUaVnbz2NPTZFMd+O08ba3FcTsG0H5+bYimTWL+6fxZ/psN1S3NS/onVvgPkvBWTjg==", "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@dicebear/core": "^7.0.0" + "@dicebear/core": "^8.0.0" } }, "node_modules/@dicebear/open-peeps": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/open-peeps/-/open-peeps-7.0.4.tgz", - "integrity": "sha512-c4oMnOvzLiMXoj+oBKILzF0DRWRd3I/ykBC7zhr3904R/dp6PXQnMDiMFIjCYeifCl8W30ggTzvNEX7nwbxJaQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/open-peeps/-/open-peeps-8.0.1.tgz", + "integrity": "sha512-NQbXmnPjyz3YZOAIEzQY6OFXg3sCIIDZgQZjl3qzTqsmUtZVMRnX8Sk53ig1SIM1kxIAyJ908wplwIYV16zxsw==", "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@dicebear/core": "^7.0.0" + "@dicebear/core": "^8.0.0" } }, "node_modules/@dicebear/personas": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/personas/-/personas-7.0.4.tgz", - "integrity": "sha512-gbWqNakXeWSKjW4s4zw4dSmuHOGF9+tgwzjwilrQvZMODOESYUCKPql/3KFJLVG9Rr00BH83QGZEn6vYiBLbVg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/personas/-/personas-8.0.1.tgz", + "integrity": "sha512-qxivUbnx4xvE1PvqCg6pBQadVDJVjXaXnxtIUxIRJyDeYIJUxkeBr2A5JOIiNLdypqXoYwhURy5r3NCmesaAWg==", "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@dicebear/core": "^7.0.0" + "@dicebear/core": "^8.0.0" } }, "node_modules/@dicebear/pixel-art": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/pixel-art/-/pixel-art-7.0.4.tgz", - "integrity": "sha512-H0OZ7JyLyiBYOa9NJI6yr1x/XjXl4P17U8lvRuQhCYHntdgDvuIwv1/kulq4vLBGRK1afXBTm/NPWi0Optyg/Q==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/pixel-art/-/pixel-art-8.0.1.tgz", + "integrity": "sha512-WMRKdxP8/PL2UGiLAP7CdgTNaIRpFyLdr+u6RyXAUmWiI25ltnZQjctzCfUrO/Nxywc6L6lBkApZtTaP+X+UHg==", "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@dicebear/core": "^7.0.0" + "@dicebear/core": "^8.0.0" } }, "node_modules/@dicebear/pixel-art-neutral": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/pixel-art-neutral/-/pixel-art-neutral-7.0.4.tgz", - "integrity": "sha512-4hzHw7I4f4bj4C7L2xQ28oA7XS1uonwGE7jTCqjRzg3YkzjTthxf7kEE/WWiP0Lk1onPhSdB8kqDejPGvNUXLQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/pixel-art-neutral/-/pixel-art-neutral-8.0.1.tgz", + "integrity": "sha512-jrbwMNjLk8hlOm+hMTT43z2DqXEFtv6/8hhms7VZE9FjcB1GrQy8j6tSClTq/ktkZlWofEGfvD8BrG5HsbKvaw==", "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@dicebear/core": "^7.0.0" + "@dicebear/core": "^8.0.0" } }, "node_modules/@dicebear/rings": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/rings/-/rings-7.0.4.tgz", - "integrity": "sha512-LJzSWronkeWefFLwaOWg3tr0jSOuW2hien4Uv+nG2alYSkJ6hGH4zLtGo/SRQdNWQg4j/6838fWJDdoryWQM2w==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/rings/-/rings-8.0.1.tgz", + "integrity": "sha512-RcSXPJDdDiyAscUhJMI6pgOgk4or0nzjKndur44U6I+6s0qS3c74zfT//whLUnDnSO2ZTaUGAjQ5gGJtzp5fqQ==", "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@dicebear/core": "^7.0.0" + "@dicebear/core": "^8.0.0" } }, "node_modules/@dicebear/shapes": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/shapes/-/shapes-7.0.4.tgz", - "integrity": "sha512-C1OhdAGwCmEK9JDjK9wERBxaZIOp2x4yWVsra/VCfba+fJSKmmorhbYIw33vE5ZV3/PseztnDB3sWOMMl/jCdw==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/shapes/-/shapes-8.0.1.tgz", + "integrity": "sha512-Duhe3bcKmcYt7GcUsNP4/OIbcHzgb4L7rfuMpUgqjXKATLYq1Wizsw9/y9wrwII8h7wIMxG6RDSndNbd7ISTtA==", "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@dicebear/core": "^7.0.0" + "@dicebear/core": "^8.0.0" } }, "node_modules/@dicebear/thumbs": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@dicebear/thumbs/-/thumbs-7.0.4.tgz", - "integrity": "sha512-mAOWbaNtWKLIHGtTZxHVei1UFWz/l0h4aP8h97UE71av2QTM7CEw2RpF8Q19MxxoDlHi+oZ7Jvjblzi5k96LtA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/thumbs/-/thumbs-8.0.1.tgz", + "integrity": "sha512-cK3UeVVWtiGbStpYeKJrCw3Wy+LGNS5sFja2O3ogc/qpjiL7WFX7kYJXOE2neqOUxVItDxg7dfGatxFrsgUTYA==", "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@dicebear/core": "^7.0.0" + "@dicebear/core": "^8.0.0" } }, "node_modules/@emotion/babel-plugin": { @@ -3058,9 +3058,9 @@ "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" }, "node_modules/@emotion/is-prop-valid": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", - "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz", + "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==", "dependencies": { "@emotion/memoize": "^0.8.1" } @@ -3094,9 +3094,9 @@ } }, "node_modules/@emotion/serialize": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.2.tgz", - "integrity": "sha512-zR6a/fkFP4EAcCMQtLOhIgpprZOwNmCldtpaISpvz348+DP4Mz8ZoKaGGCQpbzepNIUWbq4w6hNZkwDyKoS+HA==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.4.tgz", + "integrity": "sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==", "dependencies": { "@emotion/hash": "^0.9.1", "@emotion/memoize": "^0.8.1", @@ -3111,14 +3111,14 @@ "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" }, "node_modules/@emotion/styled": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.0.tgz", - "integrity": "sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==", + "version": "11.11.5", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.5.tgz", + "integrity": "sha512-/ZjjnaNKvuMPxcIiUkf/9SHoG4Q196DRl1w82hQ3WCsjo1IUR8uaGWrC6a87CrYAW0Kb/pK7hk8BnLgLRi9KoQ==", "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.11.0", - "@emotion/is-prop-valid": "^1.2.1", - "@emotion/serialize": "^1.1.2", + "@emotion/is-prop-valid": "^1.2.2", + "@emotion/serialize": "^1.1.4", "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", "@emotion/utils": "^1.2.1" }, @@ -4124,14 +4124,20 @@ } }, "node_modules/@mui/x-charts": { - "version": "6.0.0-alpha.13", - "resolved": "https://registry.npmjs.org/@mui/x-charts/-/x-charts-6.0.0-alpha.13.tgz", - "integrity": "sha512-/FfH55kkhbP3IRbQczvcysp78iTMllqHC4RUDz4wskQVMVCep32slv77aTfgP+XWtMx9lEHPGse238OKwUKLEA==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@mui/x-charts/-/x-charts-7.4.0.tgz", + "integrity": "sha512-W6A0ZJmfXLeAtuml0Yi7gvjxS6aW/2h6uO9PQNuE/rpV0iIEMU5bVfcJZGMVlh0WY+43FEicI1/8n6FzMcfZdg==", "dependencies": { - "@babel/runtime": "^7.22.15", - "@mui/base": "^5.0.0-beta.14", - "clsx": "^2.0.0", + "@babel/runtime": "^7.24.0", + "@mui/base": "^5.0.0-beta.40", + "@mui/system": "^5.15.14", + "@mui/utils": "^5.15.14", + "@react-spring/rafz": "^9.7.3", + "@react-spring/web": "^9.7.3", + "clsx": "^2.1.1", "d3-color": "^3.1.0", + "d3-delaunay": "^6.0.4", + "d3-interpolate": "^3.0.1", "d3-scale": "^4.0.2", "d3-shape": "^3.2.0", "prop-types": "^15.8.1" @@ -4142,8 +4148,7 @@ "peerDependencies": { "@emotion/react": "^11.9.0", "@emotion/styled": "^11.8.1", - "@mui/material": "^5.4.1", - "@mui/system": "^5.4.1", + "@mui/material": "^5.15.14", "react": "^17.0.0 || ^18.0.0", "react-dom": "^17.0.0 || ^18.0.0" }, @@ -4157,21 +4162,21 @@ } }, "node_modules/@mui/x-charts/node_modules/clsx": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", - "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", "engines": { "node": ">=6" } }, "node_modules/@mui/x-data-grid": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-6.10.0.tgz", - "integrity": "sha512-x9h+Z4B2vu+ZKKwClBVs30Y9eZYdhqyV3toHH2E0zat7FIZxwiVfk6qz4Q98V1fV0Fe1nczPj9i0siUmduMEXg==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-6.20.0.tgz", + "integrity": "sha512-N9a4eJRmWgP5zT2AZ41BnBgCSQJiw4dc5Q2U9zQ5aOhOs+8Jb218tX79MIAfwt1s4rbTZmgAdsBUn9Xs93Kmrw==", "dependencies": { - "@babel/runtime": "^7.22.5", - "@mui/utils": "^5.13.6", - "clsx": "^1.2.1", + "@babel/runtime": "^7.23.2", + "@mui/utils": "^5.14.16", + "clsx": "^2.0.0", "prop-types": "^15.8.1", "reselect": "^4.1.8" }, @@ -4189,6 +4194,14 @@ "react-dom": "^17.0.0 || ^18.0.0" } }, + "node_modules/@mui/x-data-grid/node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" + } + }, "node_modules/@mui/x-date-pickers": { "version": "6.10.0", "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-6.10.0.tgz", @@ -4527,6 +4540,71 @@ "tslib": "^2.4.0" } }, + "node_modules/@react-spring/animated": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.3.tgz", + "integrity": "sha512-5CWeNJt9pNgyvuSzQH+uy2pvTg8Y4/OisoscZIR8/ZNLIOI+CatFBhGZpDGTF/OzdNFsAoGk3wiUYTwoJ0YIvw==", + "dependencies": { + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-spring/core": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.7.3.tgz", + "integrity": "sha512-IqFdPVf3ZOC1Cx7+M0cXf4odNLxDC+n7IN3MDcVCTIOSBfqEcBebSv+vlY5AhM0zw05PDbjKrNmBpzv/AqpjnQ==", + "dependencies": { + "@react-spring/animated": "~9.7.3", + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-spring/donate" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-spring/rafz": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.7.3.tgz", + "integrity": "sha512-9vzW1zJPcC4nS3aCV+GgcsK/WLaB520Iyvm55ARHfM5AuyBqycjvh1wbmWmgCyJuX4VPoWigzemq1CaaeRSHhQ==" + }, + "node_modules/@react-spring/shared": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.7.3.tgz", + "integrity": "sha512-NEopD+9S5xYyQ0pGtioacLhL2luflh6HACSSDUZOwLHoxA5eku1UPuqcJqjwSD6luKjjLfiLOspxo43FUHKKSA==", + "dependencies": { + "@react-spring/types": "~9.7.3" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-spring/types": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.7.3.tgz", + "integrity": "sha512-Kpx/fQ/ZFX31OtlqVEFfgaD1ACzul4NksrvIgYfIFq9JpDHFwQkMVZ10tbo0FU/grje4rcL4EIrjekl3kYwgWw==" + }, + "node_modules/@react-spring/web": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.7.3.tgz", + "integrity": "sha512-BXt6BpS9aJL/QdVqEIX9YoUy8CE6TJrU0mNCqSoxdXlIeNcEBWOfIyE6B14ENNsyQKS3wOWkiJfco0tCr/9tUg==", + "dependencies": { + "@react-spring/animated": "~9.7.3", + "@react-spring/core": "~9.7.3", + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/@remix-run/router": { "version": "1.15.2", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.2.tgz", @@ -5522,9 +5600,9 @@ "peer": true }, "node_modules/@types/node": { - "version": "20.12.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", - "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", + "version": "20.12.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz", + "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==", "dependencies": { "undici-types": "~5.26.4" } @@ -7185,12 +7263,12 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "dependencies": { "bytes": "3.1.2", - "content-type": "~1.0.5", + "content-type": "~1.0.4", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", @@ -7198,7 +7276,7 @@ "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.11.0", - "raw-body": "2.5.2", + "raw-body": "2.5.1", "type-is": "~1.6.18", "unpipe": "1.0.0" }, @@ -8299,9 +8377,9 @@ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" }, "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", "engines": { "node": ">= 0.6" } @@ -8859,6 +8937,17 @@ "node": ">=12" } }, + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/d3-format": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", @@ -9029,9 +9118,9 @@ } }, "node_modules/dayjs": { - "version": "1.11.9", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.9.tgz", - "integrity": "sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==" + "version": "1.11.11", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz", + "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==" }, "node_modules/debug": { "version": "4.3.4", @@ -9206,6 +9295,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delaunator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", + "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", + "dependencies": { + "robust-predicates": "^3.0.2" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -9514,9 +9611,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/ejs": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", - "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz", + "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==", "dependencies": { "jake": "^10.8.5" }, @@ -10812,16 +10909,16 @@ } }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.1", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.5.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -11240,9 +11337,9 @@ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" }, "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", "funding": [ { "type": "individual", @@ -11958,11 +12055,11 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" }, "node_modules/graphql": { - "version": "15.8.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.8.0.tgz", - "integrity": "sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw==", + "version": "16.8.1", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.8.1.tgz", + "integrity": "sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==", "engines": { - "node": ">= 10.x" + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" } }, "node_modules/graphql-tag": { @@ -11980,9 +12077,9 @@ } }, "node_modules/graphql-ws": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.14.0.tgz", - "integrity": "sha512-itrUTQZP/TgswR4GSSYuwWUzrE/w5GhbwM2GX3ic2U7aw33jgEsayfIlvaj7/GcIvZgNMzsPTrE5hqPuFUiE5g==", + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.16.0.tgz", + "integrity": "sha512-Ju2RCU2dQMgSKtArPbEtsK5gNLnsQyTNIo/T7cZNp96niC1x0KdJNZV0TIoilceBPQwfb5itrGl8pkFeOUMl4A==", "engines": { "node": ">=10" }, @@ -12054,34 +12151,6 @@ "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" }, - "node_modules/handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/handlebars/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -19641,9 +19710,9 @@ } }, "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -19968,9 +20037,9 @@ } }, "node_modules/react-icons": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.12.0.tgz", - "integrity": "sha512-IBaDuHiShdZqmfc/TwHu6+d6k2ltNCf3AszxNmjJc1KUfXdEeRJOKyNvLmAHaarhzGmTSVygNdyu8/opXv2gaw==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.2.1.tgz", + "integrity": "sha512-zdbW5GstTzXaVKvGSyTaBalt7HSfuK5ovrzlpyiWHAFXndXTdd/1hdDHI4xBM1Mn7YriT6aqESucFl9kEXzrdw==", "peerDependencies": { "react": "*" } @@ -21053,6 +21122,11 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/robust-predicates": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" + }, "node_modules/rollup": { "version": "2.79.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", @@ -21199,9 +21273,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/sanitize-html": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.12.1.tgz", - "integrity": "sha512-Plh+JAn0UVDpBRP/xEjsk+xDCoOvMBwQUf/K+/cBAVuTbtX8bj2VB7S1sL1dssVpykqp0/KPSesHrqXtokVBpA==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.13.0.tgz", + "integrity": "sha512-Xff91Z+4Mz5QiNSLdLWwjgBDm5b1RU6xBT0+12rapjiaR7SwfRdjw8f+6Rir2MXKLrDicRFHdb51hGOAxmsUIA==", "dependencies": { "deepmerge": "^4.2.2", "escape-string-regexp": "^4.0.0", @@ -22645,9 +22719,9 @@ } }, "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", + "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", "optional": true, "peer": true, "dependencies": { @@ -22911,14 +22985,11 @@ } }, "node_modules/tmp-promise/node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dependencies": { - "rimraf": "^3.0.0" - }, + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", "engines": { - "node": ">=8.17.0" + "node": ">=14.14" } }, "node_modules/tmpl": { @@ -23309,14 +23380,11 @@ } }, "node_modules/typedoc-plugin-markdown": { - "version": "3.17.1", - "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-3.17.1.tgz", - "integrity": "sha512-QzdU3fj0Kzw2XSdoL15ExLASt2WPqD7FbLeaqwT70+XjKyTshBnUlQA5nNREO1C2P8Uen0CDjsBLMsCQ+zd0lw==", - "dependencies": { - "handlebars": "^4.7.7" - }, + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.0.2.tgz", + "integrity": "sha512-4MV3M+0lsmIaXuDBzeqLYemZqwTQDWQow+o8zdT9hC7KFu06GaFo2uUEbkjE6pgZA9hnkOTtzRVd0R9YJWcH8A==", "peerDependencies": { - "typedoc": ">=0.24.0" + "typedoc": "0.25.x" } }, "node_modules/typedoc/node_modules/brace-expansion": { @@ -23355,18 +23423,6 @@ "node": ">=4.2.0" } }, - "node_modules/uglify-js": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", - "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -24202,11 +24258,6 @@ "node": ">=8" } }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" - }, "node_modules/workbox-background-sync": { "version": "6.6.0", "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-6.6.0.tgz", diff --git a/package.json b/package.json index 1d211a790c..57e60288ce 100644 --- a/package.json +++ b/package.json @@ -8,25 +8,25 @@ "@apollo/client": "^3.4.0-beta.19", "@apollo/link-error": "^2.0.0-beta.3", "@apollo/react-testing": "^4.0.0", - "@dicebear/collection": "^7.0.4", - "@dicebear/core": "^7.0.4", + "@dicebear/collection": "^8.0.1", + "@dicebear/core": "^8.0.1", "@emotion/react": "^11.11.1", - "@emotion/styled": "^11.11.0", + "@emotion/styled": "^11.11.5", "@mui/icons-material": "^5.8.3", "@mui/material": "^5.15.15", "@mui/private-theming": "^5.15.12", "@mui/system": "^5.14.12", - "@mui/x-charts": "^6.0.0-alpha.13", - "@mui/x-data-grid": "^6.8.0", + "@mui/x-charts": "^7.4.0", + "@mui/x-data-grid": "^6.20.0", "@mui/x-date-pickers": "^6.6.0", "@pdfme/generator": "^1.2.6", "bootstrap": "^5.3.0", "customize-cra": "^1.0.0", - "dayjs": "^1.10.7", + "dayjs": "^1.11.11", "flag-icons": "^6.6.6", - "graphql": "^15.5.1", + "graphql": "^16.8.1", "graphql-tag": "^2.12.6", - "graphql-ws": "^5.14.0", + "graphql-ws": "^5.16.0", "history": "^5.3.0", "i18next": "^21.8.14", "i18next-browser-languagedetector": "^6.1.4", @@ -42,7 +42,7 @@ "react-dom": "^17.0.2", "react-google-recaptcha": "^2.1.0", "react-i18next": "^11.18.1", - "react-icons": "^4.12.0", + "react-icons": "^5.2.1", "react-infinite-scroll-component": "^6.1.0", "react-redux": "^7.2.5", "react-router-dom": "^6.22.2", @@ -50,8 +50,8 @@ "react-toastify": "^9.0.3", "redux": "^4.1.1", "redux-thunk": "^2.3.0", - "sanitize-html": "^2.12.1", - "typedoc-plugin-markdown": "^3.17.1", + "sanitize-html": "^2.13.0", + "typedoc-plugin-markdown": "^4.0.2", "typescript": "^4.3.5", "web-vitals": "^1.0.1" }, @@ -98,7 +98,7 @@ "@types/inquirer": "^9.0.7", "@types/jest": "^26.0.24", "@types/js-cookie": "^3.0.6", - "@types/node": "^20.12.7", + "@types/node": "^20.12.12", "@types/node-fetch": "^2.6.10", "@types/react": "^17.0.14", "@types/react-bootstrap": "^0.32.32", diff --git a/public/locales/en/common.json b/public/locales/en/common.json new file mode 100644 index 0000000000..54e46bdba6 --- /dev/null +++ b/public/locales/en/common.json @@ -0,0 +1,65 @@ +{ + "firstName": "First Name", + "lastName": "Last Name", + "searchByName": "Search By Name", + "loading": "Loading...", + "endOfResults": "End of results", + "noResultsFoundFor": "No results found for ", + "edit": "Edit", + "admins": "Admins", + "admin": "ADMIN", + "user": "USER", + "superAdmin": "SUPERADMIN", + "members": "Members", + "logout": "Logout", + "login": "Login", + "register": "Register", + "menu": "Menu", + "settings": "Settings", + "users": "Users", + "requests": "Requests", + "OR": "OR", + "cancel": "Cancel", + "close": "Close", + "create": "Create", + "delete": "Delete", + "done": "Done", + "yes": "Yes", + "no": "No", + "filter": "Filter", + "search": "Search", + "description": "Description", + "saveChanges": "Save Changes", + "displayImage": "Display Image", + "enterEmail": "Enter Email", + "emailAddress": "Email Address", + "email": "Email", + "name": "Name", + "enterPassword": "Enter Password", + "password": "Password", + "confirmPassword": "Confirm Password", + "forgotPassword": "Forgot Password ?", + "talawaAdminPortal": "Talawa Admin Portal", + "address": "Address", + "location": "Location", + "enterLocation": "Enter Location", + "joined": "Joined", + "startDate": "Start Date", + "endDate": "End Date", + "startTime": "Start Time", + "endTime": "End Time", + "My Organizations": "My Organizations", + "Dashboard": "Dashboard", + "People": "People", + "Events": "Events", + "Venues": "Venues", + "Action Items": "Action Items", + "Posts": "Posts", + "Block/Unblock": "Block/Unblock", + "Advertisement": "Advertisement", + "Funds": "Funds", + "Membership Requests": "Membership Requests", + "Plugins": "Plugins", + "Plugin Store": "Plugin Store", + "Settings": "Settings" +} diff --git a/public/locales/en/errors.json b/public/locales/en/errors.json new file mode 100644 index 0000000000..90b2acca9f --- /dev/null +++ b/public/locales/en/errors.json @@ -0,0 +1,9 @@ +{ + "talawaApiUnavailable": "Talawa-API service is unavailable!. Is it running? Check your network connectivity too.", + "notFound": "Not found", + "unknownError": "An unknown error occurred. Please try again later. {{msg}}", + "notAuthorised": "Sorry! you are not Authorised!", + "errorSendingMail": "Error sending mail", + "emailNotRegistered": "Email not registered", + "notFoundMsg": "Oops! The Page you requested was not found!" +} diff --git a/public/locales/en.json b/public/locales/en/translation.json similarity index 73% rename from public/locales/en.json rename to public/locales/en/translation.json index b1e75a64aa..6e58a2ea2a 100644 --- a/public/locales/en.json +++ b/public/locales/en/translation.json @@ -2,14 +2,7 @@ "loginPage": { "title": "Talawa Admin", "fromPalisadoes": "An open source application by Palisadoes Foundation volunteers", - "talawa_portal": "Talawa Admin Portal", - "login": "Login", "userLogin": "User Login", - "register": "Register", - "firstName": "First Name", - "lastName": "Last Name", - "email": "Email", - "password": "Password", "atleast_8_char_long": "Atleast 8 Character long", "atleast_6_char_long": "Atleast 6 Character long", "firstName_invalid": "First name should contain only lower and upper case letters", @@ -17,61 +10,34 @@ "password_invalid": "Password should contain atleast one lowercase letter, one uppercase letter, one numeric value and one special character", "email_invalid": "Email should have atleast 8 characters", "Password_and_Confirm_password_mismatches.": "Password and Confirm password mismatches.", - "confirmPassword": "Confirm Password", - "forgotPassword": "Forgot Password ?", - "enterEmail": "Enter Email", - "enterPassword": "Enter Password", "doNotOwnAnAccount": "Do not own an account?", - "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too.", "captchaError": "Captcha Error!", "Please_check_the_captcha": "Please, check the captcha.", "Something_went_wrong": "Something went wrong, Please try after sometime.", "passwordMismatches": "Password and Confirm password mismatches.", "fillCorrectly": "Fill all the Details Correctly.", - "notAuthorised": "Sorry! you are not Authorised!", - "notFound": "User not found!", "successfullyRegistered": "Successfully Registered. Please wait until you will be approved.", - "OR": "OR", - "admin": "ADMIN", - "user": "USER", "lowercase_check": "Atleast one lowercase letter", "uppercase_check": "Atleast one uppercase letter", "numeric_value_check": "Atleaset one numeric value", "special_char_check": "Atleast one special character", - "loading": "Loading...", "selectOrg": "Select an organization", "afterRegister": "Successfully registered. Please wait for admin to approve your request." }, "userLoginPage": { "title": "Talawa Admin", "fromPalisadoes": "An open source application by Palisadoes Foundation volunteers", - "talawa_portal": "Talawa Admin Portal", - "login": "Login", - "register": "Register", - "firstName": "First Name", - "lastName": "Last Name", - "email": "Email", - "password": "Password", "atleast_8_char_long": "Atleast 8 Character long", "Password_and_Confirm_password_mismatches.": "Password and Confirm password mismatches.", - "confirmPassword": "Confirm Password", - "forgotPassword": "Forgot Password ?", - "enterEmail": "Enter Email", - "enterPassword": "Enter Password", "doNotOwnAnAccount": "Do not own an account?", - "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too.", "captchaError": "Captcha Error!", "Please_check_the_captcha": "Please, check the captcha.", "Something_went_wrong": "Something went wrong, Please try after sometime.", "passwordMismatches": "Password and Confirm password mismatches.", "fillCorrectly": "Fill all the Details Correctly.", - "notAuthorised": "Sorry! you are not Authorised!", - "notFound": "User not found!", "successfullyRegistered": "Successfully Registered. Please wait until you will be approved.", "userLogin": "User Login", "afterRegister": "Successfully registered. Please wait for admin to approve your request.", - "OR": "OR", - "loading": "Loading...", "selectOrg": "Select an organization" }, "latestEvents": { @@ -85,25 +51,14 @@ "noPostsCreated": "No Posts Created" }, "listNavbar": { - "talawa_portal": "Talawa Admin Portal", - "roles": "Roles", - "requests": "Requests", - "logout": "Logout" + "roles": "Roles" }, "leftDrawer": { - "talawaAdminPortal": "Talawa Admin Portal", - "menu": "Menu", "my organizations": "My Organizations", - "users": "Users", - "requests": "Requests", - "communityProfile": "Community Profile", - "logout": "Logout" + "requests": "Membership Requests", + "communityProfile": "Community Profile" }, "leftDrawerOrg": { - "talawaAdminPortal": "Talawa Admin Portal", - "menu": "Menu", - "logout": "Logout", - "talawa_portal": "Talawa Admin Portal", "Dashboard": "Dashboard", "People": "People", "Events": "Events", @@ -116,27 +71,19 @@ "allOrganizations": "All Organizations", "yourOrganization": "Your Organization", "notification": "Notification", - "settings": "Settings", "language": "Language", "notifications": "Notifications", "spamsThe": "spams the", "group": "group", - "noNotifications": "No Notifications", - "close": "Close" + "noNotifications": "No Notifications" }, "orgList": { "title": "Talawa Organizations", "you": "You", - "name": "Name", "designation": "Designation", - "email": "Email", - "searchByName": "Search By Name", "my organizations": "My Organizations", "createOrganization": "Create Organization", "createSampleOrganization": "Create Sample Organization", - "description": "Description", - "location": "Location", - "address": "Address", "city": "City", "countryCode": "Country Code", "dependentLocality": "Dependent Locality", @@ -147,28 +94,20 @@ "state": "State / Province", "userRegistrationRequired": "User Registration Required", "visibleInSearch": "Visible In Search", - "displayImage": "Display Image", "enterName": "Enter Name", "sort": "Sort", "Latest": "Latest", "Earliest": "Earliest", - "filter": "Filter", - "cancel": "Cancel", "noOrgErrorTitle": "Organizations Not Found", "sampleOrgDuplicate": "Only one sample organization allowed", "noOrgErrorDescription": "Please create an organization through dashboard", - "endOfResults": "End of results", "manageFeatures": "Manage Features", "manageFeaturesInfo": "Creation Successful ! Please select features that you want to enale for this organization from the plugin store.", "goToStore": "Go to Plugin Store", "enableEverything": "Enable Everything", - "noResultsFoundFor": "No results found for", - "OR": "OR", "sampleOrgSuccess": "Sample Organization Successfully Created" }, "orgListCard": { - "admins": "Admins", - "members": "Members", "manage": "Manage", "sampleOrganization": "Sample Organization" }, @@ -177,17 +116,13 @@ "all": "All" }, "requests": { - "title": "Requests", + "title": "Membership Requests", "sl_no": "Sl. No.", - "name": "Name", - "email": "Email", "accept": "Accept", "reject": "Reject", - "searchRequests": "Search requests", - "endOfResults": "End of results", + "searchRequests": "Search membership requests", "noOrgError": "Organizations not found, please create an organization through dashboard", - "noResultsFoundFor": "No results found for ", - "noRequestsFound": "No Request Found", + "noRequestsFound": "No Membership Requests Found", "acceptedSuccessfully": "Request accepted successfully", "rejectedSuccessfully": "Request rejected successfully", "noOrgErrorTitle": "Organizations Not Found", @@ -195,36 +130,22 @@ }, "users": { "title": "Talawa Roles", - "searchByName": "Search By Name", - "users": "Users", - "name": "Name", - "email": "Email", "joined_organizations": "Joined Organizations", "blocked_organizations": "Blocked Organizations", "orgJoinedBy": "Organizations Joined By", "orgThatBlocked": "Organizations That Blocked", - "endOfResults": "End of results", "hasNotJoinedAnyOrg": "has not joined any organization", "isNotBlockedByAnyOrg": "is not blocked by any organization", "searchByOrgName": "Search By Organization Name", "view": "View", - "admin": "ADMIN", - "superAdmin": "SUPERADMIN", - "user": "USER", "enterName": "Enter Name", "loadingUsers": "Loading Users...", "noUserFound": "No User Found", "sort": "Sort", "Newest": "Newest First", "Oldest": "Oldest First", - "filter": "Filter", "noOrgError": "Organizations not found, please create an organization through dashboard", "roleUpdated": "Role Updated.", - "noResultsFoundFor": "No results found for ", - "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too.", - "cancel": "Cancel", - "admins": "Admins", - "members": "Members", "joinNow": "Join Now", "visit": "Visit", "withdraw": "Widthdraw" @@ -243,33 +164,25 @@ }, "dashboard": { "title": "Dashboard", - "location": "Location", "about": "About", "deleteThisOrganization": "Delete This Organization", "statistics": "Statistics", - "members": "Members", - "admins": "Admins", "posts": "Posts", "events": "Events", "blockedUsers": "Blocked Users", - "requests": "Requests", "viewAll": "View All", "upcomingEvents": "Upcoming Events", "noUpcomingEvents": "No Upcoming Events", "latestPosts": "Latest Posts", "noPostsPresent": "No Posts Present", "membershipRequests": "Membership requests", - "noMembershipRequests": "No Membership requests present", - "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too." + "noMembershipRequests": "No Membership requests present" }, "organizationPeople": { "title": "Talawa Members", "filterByName": "Filter by Name", "filterByLocation": "Filter by Location", "filterByEvent": "Filter by Event", - "members": "Members", - "admins": "Admins", - "users": "Users", "searchName": "Enter Name", "searchevent": "Enter Event", "searchFullName": "Enter Full Name", @@ -279,46 +192,27 @@ "addMembers": "Add Members", "existingUser": "Existing User", "newUser": "New User", - "firstName": "First Name", "enterFirstName": "Enter your first name", - "lastName": "Last Name", "enterLastName": "Enter your last name", - "emailAddress": "Email Address", - "enterEmail": "Enter your email address", - "password": "Password", - "enterPassword": "Enter your password", - "confirmPassword": "Confirm Password", - "enterConfirmPassword": "Enter your password to confirm", + "enterConfirmPassword": "Enter Password to confirm", "organization": "Organization", - "create": "Create", - "cancel": "Cancel", "invalidDetailsMessage": "Please enter valid details." }, "userListCard": { - "joined": "Joined", "addAdmin": "Add Admin", - "addedAsAdmin": "User is added as admin.", - "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too." + "addedAsAdmin": "User is added as admin." }, "orgAdminListCard": { - "joined": "Joined", "remove": "Remove", "removeAdmin": "Remove Admin", "removeAdminMsg": "Do you want to remove this admin?", - "no": "No", - "yes": "Yes", - "adminRemoved": "The admin is removed.", - "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too." + "adminRemoved": "The admin is removed." }, "orgPeopleListCard": { - "joined": "Joined", "remove": "Remove", "removeMember": "Remove Member", "removeMemberMsg": "Do you want to remove this member?", - "no": "No", - "yes": "Yes", - "memberRemoved": "The Member is removed", - "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too." + "memberRemoved": "The Member is removed" }, "organizationEvents": { "title": "Events", @@ -328,12 +222,6 @@ "addEvent": "Add Event", "eventDetails": "Event Details", "eventTitle": "Title", - "description": "Description", - "location": "Location", - "startDate": "Start Date", - "endDate": "End Date", - "startTime": "Start Time", - "endTime": "End Time", "allDay": "All Day", "recurringEvent": "Recurring Event", "isPublic": "Is Public", @@ -342,11 +230,9 @@ "enterFilter": "Enter Filter", "enterTitle": "Enter Title", "enterDescrip": "Enter Description", - "eventLocation": "Enter Location", "searchEventName": "Search Event Name", "eventType": "Event Type", "eventCreated": "Congratulations! The Event is created.", - "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too.", "customRecurrence": "Custom Recurrence", "repeatsEvery": "Repeats Every", "repeatsOn": "Repeats On", @@ -354,8 +240,7 @@ "never": "Never", "on": "On", "after": "After", - "occurences": "occurences", - "done": "Done" + "occurences": "occurences" }, "organizationActionItems": { "actionItemCategory": "Action Item Category", @@ -366,10 +251,8 @@ "assignmentDate": "Assignment Date", "active": "Active", "clearFilters": "Clear Filters", - "close": "Close", "completed": "Completed", "completionDate": "Completion Date", - "createActionItem": "Create", "deleteActionItem": "Delete Action Item", "deleteActionItemMsg": "Do you want to remove this action item?", "details": "Details", @@ -378,7 +261,6 @@ "editActionItem": "Edit Action Item", "isCompleted": "Completed", "latest": "Latest", - "no": "No", "noActionItems": "No Action Items", "options": "Options", "preCompletionNotes": "Pre Completion Notes", @@ -392,34 +274,22 @@ "successfulCreation": "Action Item created successfully", "successfulUpdation": "Action Item updated successfully", "successfulDeletion": "Action Item deleted successfully", - "title": "Action Items", - "yes": "Yes" + "title": "Action Items" }, "eventListCard": { - "location": "Event Location", "deleteEvent": "Delete Event", "deleteEventMsg": "Do you want to remove this event?", - "no": "No", - "yes": "Yes", "editEvent": "Edit Event", "eventTitle": "Title", - "description": "Description", - "startDate": "Start Date", - "endDate": "End Date", - "registerEvent": "Register", "alreadyRegistered": "Already registered", - "startTime": "Start Time", - "endTime": "End Time", "allDay": "All Day", "recurringEvent": "Recurring Event", "isPublic": "Is Public", "isRegistrable": "Is Registrable", - "close": "Close", "updatePost": "Update Post", "eventDetails": "Event Details", "eventDeleted": "Event deleted successfully.", "eventUpdated": "Event updated successfully.", - "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too.", "thisInstance": "This Instance", "thisAndFollowingInstances": "This & Following Instances", "allInstances": "All Instances", @@ -430,8 +300,7 @@ "never": "Never", "on": "On", "after": "After", - "occurences": "occurences", - "done": "Done" + "occurences": "occurences" }, "funds": { "title": "Funds", @@ -450,11 +319,8 @@ "fundCreate": "Create Fund", "fundUpdate": "Update Fund", "fundDelete": "Delete Fund", - "no": "No", - "yes": "Yes", "manageFund": "Manage Fund", "searchFullName": "Search By Name", - "filter": "Filter", "noFundsFound": "No Funds Found", "createdBy": "Created By", "createdOn": "Created On", @@ -471,8 +337,6 @@ "fundCampaign": { "title": "Fundraising Campaigns", "campaignName": "Campaign Name", - "startDate": "Start Date", - "endDate": "End Date", "campaignOptions": "Options", "fundingGoal": "Funding Goal", "addCampaign": "Add Campaign", @@ -485,18 +349,13 @@ "updateCampaign": "Update Fund Campaign", "manageCampaign": "Manage Fund Campaign", "deleteCampaign": "Delete Fund Campaign", - "no": "No", - "yes": "Yes", "currency": "Currency", "selectCurrency": "Select Currency", - "filter": "Filter", "searchFullName": "Search By Name" }, "pledges": { "title": "Fund Campaign Pledges", "volunteers": "Volunteers", - "startDate": "Start Date", - "endDate": "End Date", "pledgeAmount": "Pledge Amount", "pledgeOptions": "Options", "pledgeCreated": "Pledge created successfully", @@ -511,8 +370,6 @@ "amount": "Amount", "editPledge": "Edit Pledge", "deletePledgeMsg": "Are you sure you want to delete this pledge?", - "no": "No", - "yes": "Yes", "noPledges": "No Pledges Found" }, "orgPost": { @@ -533,7 +390,6 @@ "postDes": "What do you to talk about?", "Title": "Title", "Text": "Text", - "cancel": "Cancel", "searchBy": "Search By", "Oldest": "Oldest First", "Latest": "Latest First", @@ -552,7 +408,6 @@ "organization not found!": "Organization Not Found!" }, "userNotFound": { - "user": "User", "not found!": "Not Found!", "roles": "Roles", "user not found!": "User Not Found!", @@ -564,11 +419,8 @@ "author": "Author", "imageURL": "Image URL", "videoURL": "Video URL", - "edit": "Edit Post", "deletePost": "Delete Post", "deletePostMsg": "Do you want to remove this post?", - "no": "No", - "yes": "Yes", "editPost": "Edit Post", "postTitle": "Title", "postTitle1": "Edit title of the post", @@ -576,33 +428,26 @@ "information": "Information", "image": "Image", "video": "Video", - "close": "Close", "updatePost": "Update Post", "postDeleted": "Post deleted successfully.", "postUpdated": "Post Updated successfully.", "tag": " Your browser does not support the video tag", - "pin": "Pin Post", - "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too." + "pin": "Pin Post" }, "blockUnblockUser": { "title": "Block/Unblock User", "pageName": "Block/Unblock", - "searchByName": "Search By Name", "listOfUsers": "List of Users who spammed", - "name": "Name", - "email": "Email", "block_unblock": "Block/Unblock", "unblock": "UnBlock", "block": "Block", "orgName": "Enter Name", "blockedSuccessfully": "User blocked successfully", "Un-BlockedSuccessfully": "User Un-Blocked successfully", - "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too.", "allMembers": "All Members", "blockedUsers": "Blocked Users", "searchByFirstName": "Search By First Name", "searchByLastName": "Search By Last Name", - "noResultsFoundFor": "No results found for", "noSpammerFound": "No spammer found" }, "eventManagement": { @@ -615,7 +460,6 @@ }, "forgotPassword": { "title": "Talawa Forgot Password", - "forgotPassword": "Forgot Password", "registeredEmail": "Registered Email", "getOtp": "Get OTP", "enterOtp": "Enter OTP", @@ -624,9 +468,7 @@ "changePassword": "Change Password", "backToLogin": "Back to Login", "userOtp": "e.g. 12345", - "password": "Password", "emailNotRegistered": "Email is not registered.", - "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too.", "errorSendingMail": "Error in sending mail.", "passwordMismatches": "Password and Confirm password mismatches.", "passwordChanges": "Password changes successfully.", @@ -661,12 +503,10 @@ }, "orgSettings": { "title": "Settings", - "pageName": "Settings", "general": "General", "actionItemCategories": "Action Item Categories", "updateOrganization": "Update Organization", "seeRequest": "See Request", - "settings": "Settings", "noData": "No data", "otherSettings": "Other Settings", "changeLanguage": "Change Language", @@ -676,46 +516,28 @@ "deleteOrganization": "Delete Organization", "deleteSampleOrganization": "Delete Sample Organization", "deleteMsg": "Do you want to delete this organization?", - "cancel": "Cancel", "confirmDelete": "Confirm Delete", "longDelOrgMsg": "By clicking on Delete Organization button the organization will be permanently deleted along with its events, tags and all related data.", "successfullyDeletedSampleOrganization": "Successfully deleted sample Organization" }, "userUpdate": { - "firstName": "First Name", - "lastName": "Last Name", - "email": "Email", - "password": "Password", "appLanguageCode": "Default Language", - "userType": "User Type", - "admin": "Admin", - "superAdmin": "Superadmin", - "displayImage": "Display Image", - "saveChanges": "Save Changes", - "cancel": "Cancel" + "userType": "User Type" }, "userPasswordUpdate": { "previousPassword": "Previous Password", "newPassword": "New Password", - "confirmNewPassword": "Confirm New Password", - "saveChanges": "Save Changes", - "cancel": "Cancel" + "confirmNewPassword": "Confirm New Password" }, "orgDelete": { "deleteOrg": "Delete Org" }, "membershipRequest": { - "joined": "Joined", "accept": "Accept", "reject": "Reject", - "memberAdded": "it is accepted", - "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too." + "memberAdded": "it is accepted" }, "orgUpdate": { - "name": "Name", - "description": "Description", - "location": "Location", - "address": "Address", "city": "City", "countryCode": "Country Code", "line1": "Line 1", @@ -724,13 +546,10 @@ "dependentLocality": "Dependent Locality", "sortingCode": "Sorting code", "state": "State / Province", - "displayImage": "Display Image", "userRegistrationRequired": "User Registration Required", "isVisibleInSearch": "Visible in Search", - "saveChanges": "Save Changes", "enterNameOrganization": "Enter Organization Name", - "successfulUpdated": "Organization updated successfully", - "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too." + "successfulUpdated": "Organization updated successfully" }, "addOnRegister": { "addNew": "Add New", @@ -738,8 +557,6 @@ "pluginName": "Plugin Name", "creatorName": "Creator Name", "pluginDesc": "Plugin Description", - "close": "Close", - "register": "Register", "pName": "Ex: Donations", "cName": "Ex: john Doe", "pDesc": "This Plugin enables UI for" @@ -753,8 +570,7 @@ "install": "Installed", "available": "Available", "pMessage": "Plugin does not exists", - "filter": "Filters", - "search": "Search" + "filter": "Filters" }, "addOnEntry": { "enable": "Enabled", @@ -770,7 +586,6 @@ "organizations": "Organizations", "events": "Events", "role": "Role", - "email": "Email", "createdOn": "Created on", "main": "Main", "firstName": "First name", @@ -781,9 +596,7 @@ "educationGrade": "Educational Grade", "employmentStatus": "Employment Status", "maritalStatus": "Marital Status", - "displayImage": "Display Image", "phone": "Phone", - "address": "Address", "countryCode": "Country Code", "state": "State", "city": "City", @@ -792,54 +605,31 @@ "actionsHeading": "Actions", "personalDetailsHeading": "Profile Details", "appLanguageCode": "Choose Language", - "delete": "Delete User", - "saveChanges": "Save Changes", + "deleteUser": "Delete User", "pluginCreationAllowed": "Plugin creation allowed", - "joined": "Joined", "created": "Created", "adminForOrganizations": "Admin for organizations", "membershipRequests": "Membership requests", "adminForEvents": "Admin for events", "addedAsAdmin": "User is added as admin.", - "talawaApiUnavailable": "Talawa-API service is unavailable. Kindly check your network connection and wait for a while.", - "password": "Password", - "userType": "User Type", - "admin": "Admin", - "superAdmin": "Superadmin", - "cancel": "Cancel" + "userType": "User Type" }, "userLogin": { "login": "Login", - "forgotPassword": "Forgot Password?", "loginIntoYourAccount": "Login into your account", - "emailAddress": "Email Address", - "enterEmail": "Enter your email address", - "password": "Password", - "enterPassword": "Enter your password", - "register": "Register", "invalidDetailsMessage": "Please enter a valid email and password.", "notAuthorised": "Sorry! you are not Authorised!", - "invalidCredentials": "Entered credentials are incorrect. Please enter valid credentials.", - "talawaApiUnavailable": "Talawa-API service is unavailable. Kindly check your network connection and wait for a while." + "invalidCredentials": "Entered credentials are incorrect. Please enter valid credentials." }, "userRegister": { - "register": "Register", - "firstName": "First Name", "enterFirstName": "Enter your first name", - "lastName": "Last Name", "enterLastName": "Enter your last name", - "emailAddress": "Email Address", - "enterEmail": "Enter your email address", - "password": "Password", - "enterPassword": "Enter your password", - "confirmPassword": "Confirm Password", - "enterConfirmPassword": "Enter your password to confirm", + "enterConfirmPassword": "Enter Password to confirm", "alreadyhaveAnAccount": "Already have an account?", "login": "Login", "afterRegister": "Successfully registered. Please wait for admin to approve your request.", "passwordNotMatch": "Password doesn't match. Confirm Password and try again.", - "invalidDetailsMessage": "Please enter valid details.", - "talawaApiUnavailable": "Talawa-API service is unavailable. Kindly check your network connection and wait for a while." + "invalidDetailsMessage": "Please enter valid details." }, "userNavbar": { "talawa": "Talawa", @@ -848,39 +638,28 @@ "events": "Events", "chat": "Chat", "donate": "Donate", - "settings": "Settings", - "language": "Language", - "logout": "Logout", - "close": "Close" + "language": "Language" }, "userOrganizations": { "allOrganizations": "All Organizations", "joinedOrganizations": "Joined Organizations", "createdOrganizations": "Created Organizations", "selectOrganization": "Select an organization", - "search": "Search users", + "searchUsers": "Search users", "nothingToShow": "Nothing to show here.", - "organizations": "Organizations", - "searchByName": "Search By Name", - "filter": "Filter" + "organizations": "Organizations" }, "userSidebarOrg": { "yourOrganizations": "Your Organizations", "noOrganizations": "You haven't joined any organization yet.", "viewAll": "View all", "talawaUserPortal": "Talawa User Portal", - "menu": "Menu", "my organizations": "My Organizations", - "users": "Users", - "requests": "Requests", - "communityProfile": "Community Profile", - "logout": "Logout", - "settings": "Settings" + "communityProfile": "Community Profile" }, "organizationSidebar": { "viewAll": "View all", "events": "Events", - "members": "Members", "noEvents": "No Events to show", "noMembers": "No Members to show" }, @@ -889,8 +668,15 @@ "comments": "Comments" }, "home": { + "posts": "Posts", + "post": "Post", + "title": "Title", + "textArea": "Something on your mind?", "feed": "Feed", - "pinnedPosts": "View Pinned Posts", + "loading": "Loading", + "pinnedPosts": "Pinned Posts", + "yourFeed": "Your Feed", + "nothingToShowHere": "Nothing to show here", "somethingOnYourMind": "Something on your mind?", "addPost": "Add Post", "startPost": "Start a post", @@ -899,24 +685,17 @@ "article": "Article" }, "settings": { - "settings": "Settings", "profileSettings": "Profile Settings", - "firstName": "First Name", - "lastName": "Last Name", "gender": "Gender", - "emailAddress": "Email Address", "phoneNumber": "Phone Number", - "displayImage": "Display Image", "chooseFile": "Choose File", "birthDate": "Birth Date", "grade": "Educational Grade", "empStatus": "Employment Status", "maritalStatus": "Marital Status", - "address": "Address", "state": "City/State", "country": "Country", "resetChanges": "Reset Changes", - "saveChanges": "Save Changes", "profileDetails": "Profile Details", "deleteUserMessage": "By clicking on Delete User button your user will be permanently deleted along with its events, tags and all related data.", "copyLink": "Copy Profile Link", @@ -957,8 +736,7 @@ "fullTime": "Full Time", "partTime": "Part Time", "selectCountry": "Select a country", - "enterState": "Enter City or State", - "joined": "Joined" + "enterState": "Enter City or State" }, "donate": { "donations": "Donations", @@ -972,13 +750,8 @@ }, "userEvents": { "nothingToShow": "Nothing to show here.", - "search": "Search", "createEvent": "Create Event", "recurring": "Recurring Event", - "startTime": "Start Time", - "endTime": "End Time", - "cancel": "Cancel", - "create": "Create", "listView": "List View", "calendarView": "Calendar View", "allDay": "All Day", @@ -986,31 +759,23 @@ "eventDetails": "Event Details", "eventTitle": "Title", "enterTitle": "Enter Title", - "eventDescription": "Description", "enterDescription": "Enter Description", - "eventLocation": "Location", - "enterLocation": "Enter Location", - "startDate": "Start Date", - "endDate": "End Date", "publicEvent": "Is Public", "registerable": "Is Registerable", "monthlyCalendarView": "Monthly Calendar", "yearlyCalendarView": "Yearly Calender" }, "userEventCard": { - "location": "Location", "starts": "Starts", "ends": "Ends", "creator": "Creator", - "alreadyRegistered": "Already registered", - "register": "Register" + "alreadyRegistered": "Already registered" }, "advertisement": { "title": "Advertisements", "activeAds": "Active Campaigns", "archievedAds": "Completed Campaigns", "pMessage": "Ads not present for this campaign.", - "delete": "Delete", "validLink": "Link is valid", "invalidLink": "Link is invalid", "Rname": "Enter name of Advertisement", @@ -1022,21 +787,14 @@ "addNew": "Create new advertisement", "EXname": "Ex. Cookie Shop", "EXlink": "Ex. http://yourwebsite.com/photo", - "register": "Create Advertisement", - "close": "Close ", + "createAdvertisement": "Create Advertisement", "deleteAdvertisement": "Delete Advertisement", "deleteAdvertisementMsg": "Do you want to remove this advertisement?", - "no": "No", - "yes": "Yes", "view": "View", - "edit": "Edit", - "editAdvertisement": "Edit Advertisement", - "saveChanges": "Save Changes", - "endOfResults": "End of results" + "editAdvertisement": "Edit Advertisement" }, "userChat": { "chat": "Chat", - "search": "Search", "contacts": "Contacts" }, "userChatRoom": { @@ -1049,14 +807,11 @@ "customFieldName": "Field Name", "enterCustomFieldName": "Enter Field name", "customFieldType": "Field Type", - "saveChanges": "Save Changes", "Remove Custom Field": "Remove Custom Field", "fieldSuccessMessage": "Field added successfully", "fieldRemovalSuccess": "Field removed successfully" }, "orgActionItemCategories": { - "createButton": "Create", - "editButton": "Edit", "enableButton": "Enable", "disableButton": "Disable", "updateActionItemCategory": "Update", @@ -1075,7 +830,6 @@ "venueDetails": "Venue Details", "venueName": "Name of the Venue", "enterVenueName": "Enter Venue Name", - "description": "Description of the Venue", "enterVenueDesc": "Enter Venue Description", "capacity": "Capacity", "enterVenueCapacity": "Enter Venue Capacity", @@ -1089,14 +843,10 @@ "highestCapacity": "Highest Capacity", "lowestCapacity": "Lowest Capacity", "noVenues": "No Venues Found!", - "edit": "Edit", "view": "View", - "delete": "Delete", "venueTitleError": "Venue title cannot be empty!", "venueCapacityError": "Capacity must be a positive number!", - "searchBy": "Search By", - "name": "Name", - "desc": "Description" + "searchBy": "Search By" }, "addMember": { "title": "Add Member", @@ -1104,22 +854,12 @@ "existingUser": "Existing User", "newUser": "New User", "searchFullName": "Search by Full Name", - "firstName": "First Name", "enterFirstName": "Enter First Name", - "lastName": "Last Name", "enterLastName": "Enter Last Name", - "emailAddress": "Email Address", - "enterEmail": "Enter Email", - "password": "Password", - "enterPassword": "Enter Password", - "confirmPassword": "Confirm Password", "enterConfirmPassword": "Enter Confirm Password", "organization": "Organization", - "cancel": "Cancel", - "create": "Create", "invalidDetailsMessage": "Please provide all required details.", "passwordNotMatch": "Passwords do not match.", - "user": "User", "addMember": "Add Member" }, "eventActionItems": { @@ -1136,8 +876,6 @@ "editActionItem": "Edit Action Item", "deleteActionItem": "Delete Action Item", "deleteActionItemMsg": "Do you want to remove this action item?", - "yes": "Yes", - "no": "No", "successfulDeletion": "Action Item deleted successfully", "successfulCreation": "Action Item created successfully", "successfulUpdation": "Action Item updated successfully", diff --git a/public/locales/fr.json b/public/locales/fr.json deleted file mode 100644 index ef9eed6c96..0000000000 --- a/public/locales/fr.json +++ /dev/null @@ -1,1133 +0,0 @@ -{ - "loginPage": { - "title": "Administrateur Talawa", - "talawa_portal": "Portail D'Administrateur Talawa", - "fromPalisadoes": "Une application open source par les volontaires de la Fondation Palissades", - "login": "Connexion", - "userLogin": "Utilisateur en ligne", - "register": "S'inscrire", - "firstName": "Prénom", - "lastName": "Nom de famille", - "email": "E-mail", - "password": "Mot de passe", - "atleast_8_char_long": "Au moins 8 caractères", - "atleast_6_char_long": "Au moins 6 caractères", - "firstName_invalid": "Le prénom ne doit contenir que des lettres minuscules et majuscules", - "lastName_invalid": "Le nom de famille ne doit contenir que des lettres minuscules et majuscules", - "password_invalid": "Le mot de passe doit contenir au moins une lettre minuscule, une lettre majuscule, une valeur numérique et un caractère spécial", - "email_invalid": "L'e-mail doit contenir au moins 8 caractères", - "Password_and_Confirm_password_mismatches.": "Le mot de passe et la confirmation du mot de passe ne correspondent pas.", - "confirmPassword": "Confirmez le mot de passe", - "forgotPassword": "Mot de passe oublié ?", - "enterEmail": "entrez l'e-mail", - "enterPassword": "Entrer le mot de passe", - "doNotOwnAnAccount": "Vous n'avez pas de compte ?", - "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau.", - "captchaError": "Erreur de captcha !", - "Please_check_the_captcha": "Veuillez vérifier le captcha.", - "Something_went_wrong": "Quelque chose s'est mal passé, veuillez réessayer plus tard.", - "passwordMismatches": "Le mot de passe et la confirmation du mot de passe ne correspondent pas.", - "fillCorrectly": "Remplissez tous les détails correctement.", - "notAuthorised": "Désolé ! vous n'êtes pas autorisé !", - "notFound": "Utilisateur introuvable !", - "successfullyRegistered": "Enregistré avec succès. Veuillez patienter jusqu'à ce que vous soyez approuvé.", - "OR": "OU", - "admin": "ADMIN", - "user": "UTILISATEUR", - "lowercase_check": "Au moins une lettre minuscule", - "uppercase_check": "Au moins une lettre majuscule", - "special_char_check": "Au moins un caractère spécial", - "numeric_value_check": "Au moins une valeur numérique", - "afterRegister": "Inscription réussie. Veuillez attendre l'approbation de l'administrateur pour votre demande." - }, - "userLoginPage": { - "title": "Administration Talawa", - "fromPalisadoes": "Une application open source par des bénévoles de la Fondation Palisadoes", - "talawa_portal": "Portail d'administration Talawa", - "login": "Connexion", - "register": "S'inscrire", - "firstName": "Prénom", - "lastName": "Nom de famille", - "email": "E-mail", - "password": "Mot de passe", - "atleast_8_char_long": "Au moins 8 caractères de long", - "Password_and_Confirm_password_mismatches.": "Les mots de passe ne correspondent pas.", - "confirmPassword": "Confirmez le mot de passe", - "forgotPassword": "Mot de passe oublié ?", - "enterEmail": "Entrez l'e-mail", - "enterPassword": "Entrez le mot de passe", - "doNotOwnAnAccount": "Vous n'avez pas de compte ?", - "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau.", - "captchaError": "Erreur de captcha !", - "Please_check_the_captcha": "Veuillez vérifier le captcha.", - "Something_went_wrong": "Quelque chose s'est mal passé, veuillez réessayer ultérieurement.", - "passwordMismatches": "Les mots de passe ne correspondent pas.", - "fillCorrectly": "Remplissez correctement tous les détails.", - "notAuthorised": "Désolé ! Vous n'êtes pas autorisé !", - "notFound": "Utilisateur non trouvé !", - "successfullyRegistered": "Inscription réussie. Veuillez attendre que votre demande soit approuvée.", - "userLogin": "Connexion utilisateur", - "afterRegister": "Inscription réussie. Veuillez attendre l'approbation de l'administrateur.", - "OR": "OU", - "loading": "Chargement...", - "selectOrg": "Sélectionnez une organisation" - }, - "latestEvents": { - "eventCardTitle": "Événements à venir", - "eventCardSeeAll": "Voir Tout", - "noEvents": "Aucun événement à venir" - }, - "latestPosts": { - "latestPostsTitle": "Dernières Publications", - "seeAllLink": "Voir Tout", - "noPostsCreated": "Aucune Publication Créée" - }, - "listNavbar": { - "talawa_portal": "Portail D'Administrateur Talawa", - "roles": "Les rôles", - "requests": "Demandes", - "logout": "Se déconnecter" - }, - "leftDrawer": { - "talawaAdminPortal": "Portail d'administration Talawa", - "menu": "Menu", - "my organizations": "Mes Organisations", - "users": "Utilisateurs", - "requests": "Demandes", - "communityProfile": "Profil de la communauté", - "logout": "Déconnexion" - }, - "leftDrawerOrg": { - "talawaAdminPortal": "Portail d'administration Talawa", - "menu": "Menu", - "talawa_portal": "Portail D'Administrateur Talawa", - "Dashboard": "Tableau de bord", - "People": "Personnes", - "Events": "Événements", - "Contributions": "Contributions", - "Posts": "Des postes", - "Block/Unblock": "Bloquer/Débloquer", - "Plugins": "Plugins", - "Plugin Store": "Magasin de plugins", - "allOrganizations": "Toutes les organisations", - "yourOrganization": "Votre organisation", - "notification": "Notification", - "settings": "Réglages", - "language": "Langue", - "logout": "Se déconnecter", - "notifications": "Notifications", - "spamsThe": "spam le", - "group": "groupe", - "noNotifications": "Aucune notification", - "close": "Proche" - }, - "orgList": { - "title": "Organisations Talawa", - "you": "Tu", - "name": "Nom", - "designation": "La désignation", - "email": "E-mail", - "searchByName": "Rechercher par nom", - "my organizations": "Mes Organisations", - "createOrganization": "Créer une organisation", - "createSampleOrganization": "Créer une organisation d'exemple", - "description": "La description", - "location": "Emplacement", - "address": "Adresse", - "city": "Ville", - "countryCode": "Code Pays", - "line1": "Ligne 1", - "line2": "Ligne 2", - "postalCode": "Code Postal", - "dependentLocality": "Localité Dépendante", - "sortingCode": "Code de Tri", - "state": "État / Province", - "userRegistrationRequired": "enregistrement requis", - "visibleInSearch": "Visible dans la recherche", - "displayImage": "Afficher l'image", - "enterName": "Entrez le nom", - "sort": "Trier", - "Earliest": "Le plus tôt", - "Latest": "Dernière", - "filter": "Filtre", - "cancel": "Annuler", - "endOfResults": "Fin des résultats", - "noOrgErrorTitle": "Organisations non trouvées", - "sampleOrgDuplicate": "Seule une organisation d'exemple est autorisée.", - "noOrgErrorDescription": "Veuillez créer une organisation via le tableau de bord", - "noResultsFoundFor": "Aucun résultat trouvé pour ", - "OR": "OU", - "sampleOrgSuccess": "Organisation d'exemple créée avec succès" - }, - "orgListCard": { - "admins": "Administrateurs", - "members": "Membres", - "manage": "Faire en sorte", - "sampleOrganization": "Organisation d'exemple" - }, - "paginationList": { - "rowsPerPage": "lignes par page", - "all": "Tout" - }, - "requests": { - "title": "Demandes", - "sl_no": "Num.", - "name": "Nom", - "email": "Email", - "accept": "Accepter", - "reject": "Rejeter", - "searchRequests": "Rechercher des demandes", - "endOfResults": "Fin des résultats", - "noOrgError": "Organisations introuvables, veuillez créer une organisation via le tableau de bord", - "noResultsFoundFor": "Aucun résultat trouvé pour ", - "noRequestsFound": "Aucune demande trouvée", - "acceptedSuccessfully": "Demande acceptée avec succès", - "rejectedSuccessfully": "Demande rejetée avec succès", - "noOrgErrorTitle": "Organisations non trouvées", - "noOrgErrorDescription": "Veuillez créer une organisation via le tableau de bord" - }, - "users": { - "title": "Rôles Talawa", - "searchByName": "Recherche par nom", - "users": "Utilisateurs", - "name": "Nom", - "email": "E-mail", - "joined_organizations": "Organisations rejointes", - "blocked_organizations": "Organisations bloquées", - "endOfResults": "Fin des résultats", - "orgJoinedBy": "Organisation rejointe par", - "orgThatBlocked": "Organisation bloquée par", - "hasNotJoinedAnyOrg": "n'a rejoint aucune organisation", - "isNotBlockedByAnyOrg": "n'est bloqué par aucune organisation", - "searchByOrgName": "Rechercher par nom d'organisation", - "view": "Vue", - "admin": "ADMIN", - "superAdmin": "SUPERADMIN", - "user": "UTILISATEUR", - "enterName": "Entrez le nom", - "loadingUsers": "Chargement des utilisateurs...", - "noUserFound": "Aucun utilisateur trouvé", - "sort": "Trier", - "Oldest": "Les plus anciennes d'abord", - "Newest": "Les plus récentes d'abord", - "filter": "Filtre", - "roleUpdated": "Rôle mis à jour.", - "noResultsFoundFor": "Aucun résultat trouvé pour ", - "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau.", - "cancel": "Annuler", - "admins": "Administrateurs", - "members": "Membres", - "joinNow": "Adhérer maintenant", - "visit": "visite", - "withdraw": "Retirer", - "orgJoined": "Organisation rejointe avec succès", - "MembershipRequestSent": "Demande d'adhésion envoyée avec succès", - "AlreadyJoined": "Vous êtes déjà membre de cette organisation.", - "errorOccured": "Une erreur s'est produite. Veuillez réessayer plus tard." - }, - "communityProfile": { - "title": "Profil de la communauté", - "editProfile": "Editer le profil", - "communityProfileInfo": "Ces détails apparaîtront sur l'écran de connexion/inscription pour vous et les membres de votre communauté.", - "communityName": "Nom de la communauté", - "wesiteLink": "Lien de site Web", - "logo": "Logo", - "social": "Liens vers les réseaux sociaux", - "url": "Entrer l'URL", - "profileChangedMsg": "Les détails du profil ont été mis à jour avec succès.", - "resetData": "Réinitialisez avec succès les détails du profil." - }, - "dashboard": { - "title": "Tableau de bord", - "location": "Emplacement", - "about": "À propos de", - "deleteThisOrganization": "Supprimer cette organisation", - "statistics": "Statistiques", - "members": "Membres", - "admins": "Administrateurs", - "posts": "Des postes", - "events": "Événements", - "blockedUsers": "Utilisateurs bloqués", - "requests": "Demandes", - "viewAll": "Voir tout", - "upcomingEvents": "Événements à venir", - "noUpcomingEvents": "Aucun événement à venir", - "latestPosts": "Derniers messages", - "noPostsPresent": "Aucune publication présente", - "membershipRequests": "Demandes d'adhésion", - "noMembershipRequests": "Aucune demande d'adhésion", - "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau." - }, - "organizationPeople": { - "title": "Membres Talawa", - "filterByName": "Filtrer par nom", - "filterByLocation": "Filtrer par lieu", - "filterByEvent": "Filtrer par événement", - "members": "Membres", - "admins": "Administrateurs", - "users": "Utilisateurs", - "searchName": "Entrez le nom", - "searchevent": "Entrez l'événement", - "searchFirstName": "Entrez votre prénom", - "searchLastName": "Entrer le nom de famille", - "people": "Personnes", - "sort": "Trier par rôle", - "actions": "Actions", - "existingUser": "utilisateur existant", - "newUser": "Nouvel Utilisateur", - "firstName": "Prénom", - "enterFirstName": "Entrez votre prénom", - "lastName": "Nom de famille", - "enterLastName": "Entrez votre nom de famille", - "emailAddress": "Email Address", - "enterEmail": "Entrez votre adresse email", - "password": "Mot de passe", - "enterPassword": "Tapez votre mot de passe", - "confirmPassword": "Confirmez le mot de passe", - "enterConfirmPassword": "Entrez votre mot de passe pour confirmer", - "organization": "Organization", - "create": "Créer", - "cancel": "Annuler", - "invalidDetailsMessage": "Veuillez entrer des détails valides." - }, - "userListCard": { - "joined": "Inscrit", - "addAdmin": "Ajouter un administrateur", - "addedAsAdmin": "L'utilisateur est ajouté en tant qu'administrateur.", - "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau." - }, - "orgAdminListCard": { - "joined": "Inscrit", - "remove": "Retirer", - "removeAdmin": "Supprimer l'administrateur", - "removeAdminMsg": "Voulez-vous supprimer cet administrateur ?", - "no": "Non", - "yes": "Oui", - "adminRemoved": "L'administrateur est supprimé.", - "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau." - }, - "orgPeopleListCard": { - "joined": "Inscrit", - "remove": "Retirer", - "removeMember": "Supprimer le membre", - "removeMemberMsg": "Voulez-vous supprimer ce membre ?", - "no": "Non", - "yes": "Oui", - "memberRemoved": "Le membre est supprimé", - "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau." - }, - "organizationEvents": { - "title": "Événements", - "filterByTitle": "Filtrer par titre", - "filterByLocation": "Filtrer par l'emplacement", - "filterByDescription": "Filtrer par Description", - "events": "Événements", - "addEvent": "Ajouter un évènement", - "eventDetails": "Détails de l'évènement", - "eventTitle": "Titre", - "description": "La description", - "location": "Emplacement", - "startDate": "Date de début", - "endDate": "Date de fin", - "startTime": "Heure de début", - "endTime": "Heure de fin", - "allDay": "Toute la journée", - "recurringEvent": "Événement récurrent", - "isPublic": "Est publique", - "isRegistrable": "Est enregistrable", - "createEvent": "Créer un évènement", - "enterFilter": "Entrez le filtre", - "enterTitle": "Entrez le titre", - "enterDescrip": "Entrez la description", - "eventLocation": "Entrez l'emplacement", - "eventCreated": "Toutes nos félicitations! L'événement est créé.", - "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau.", - "searchEventName": "Rechercher le nom de l'événement", - "eventType": "Type d'événement", - "customRecurrence": "Récurrence personnalisée", - "repeatsEvery": "Se répète tous les", - "repeatsOn": "Se répète sur", - "ends": "Finit", - "never": "Jamais", - "on": "Sur", - "after": "Après", - "occurences": "Occurrences", - "done": "Fait" - }, - "organizationActionItems": { - "actionItemCategory": "Catégorie de l'élément d'action", - "actionItemActive": "Mesure de suivi active", - "actionItemCompleted": "Mesure de suivi terminée", - "actionItemDetails": "Détails de l'élément d'action", - "actionItemStatus": "État de l’action", - "assignee": "Attributaire", - "assigner": "Assignateur", - "assignmentDate": "Date d'attribution", - "active": "Actif", - "clearFilters": "Effacer les filtres", - "close": "Fermer", - "completed": "Terminé", - "completionDate": "Date d'achèvement", - "createActionItem": "Créer", - "deleteActionItem": "Supprimer l'élément d'action", - "deleteActionItemMsg": "Voulez-vous supprimer cet élément d'action?", - "details": "Détails", - "dueDate": "Date d'échéance", - "earliest": "Le plus tôt", - "editActionItem": "Modifier l'élément d'action", - "eventActionItems": "Mesures à prendre pour l’événement", - "isCompleted": "Terminé", - "latest": "Le plus récent", - "makeActive": "Rendre actif", - "markCompletion": "Marquer l'achèvement", - "no": "Non", - "noActionItems": "Pas d'éléments d'action", - "options": "Options", - "preCompletionNotes": "Notes avant achèvement", - "postCompletionNotes": "Notes après achèvement", - "selectActionItemCategory": "Sélectionnez une catégorie d'élément d'action", - "selectAssignee": "Sélectionnez un attributaire", - "status": "Statut", - "successfulCreation": "Élément d'action créé avec succès", - "successfulUpdation": "Élément d'action mis à jour avec succès", - "successfulDeletion": "Élément d'action supprimé avec succès", - "title": "Éléments d'action", - "yes": "Oui" - }, - "eventListCard": { - "location": "Lieu de l'événement", - "deleteEvent": "Supprimer l'événement", - "deleteEventMsg": "Voulez-vous supprimer cet événement ?", - "no": "Non", - "yes": "Oui", - "editEvent": "Modifier l'événement", - "eventTitle": "Titre", - "description": "La description", - "startDate": "Date de début", - "endDate": "Date de fin", - "registerEvent": "Registre", - "alreadyRegistered": "Déjà enregistré", - "startTime": "Heure de début", - "endTime": "Heure de fin", - "allDay": "Toute la journée", - "recurringEvent": "Événement récurrent", - "isPublic": "Est publique", - "isRegistrable": "Est enregistrable", - "close": "Proche", - "updatePost": "Mettre à jour le message", - "eventDetails": "Détails de l'évènement", - "eventDeleted": "Événement supprimé avec succès.", - "eventUpdated": "Événement mis à jour avec succès.", - "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau.", - "thisInstance": "Cette Instance", - "thisAndFollowingInstances": "Cette et les Instances Suivantes", - "allInstances": "Toutes les Instances", - "customRecurrence": "Récurrence personnalisée", - "repeatsEvery": "Se répète tous les", - "repeatsOn": "Se répète sur", - "ends": "Finit", - "never": "Jamais", - "on": "Sur", - "after": "Après", - "occurences": "Occurrences", - "done": "Fait" - }, - "funds": { - "title": "Fonds", - "createFund": "Créer un fonds", - "fundName": "Nom du fonds", - "fundId": "Identifiant du fonds", - "fundOptions": "Options de fonds", - "noFunds": "Pas de fonds", - "fundDetails": "Détails du fonds", - "taxDeductible": "Déductible d'impôt", - "enterfundName": "Entrez le nom du fonds", - "enterfundId": "Entrez l'identifiant du fonds", - "default": "Défaut", - "archived": "Archivé", - "nonArchive": "Non archivé", - "fundCreate": "Créer un fonds", - "fundUpdate": "Mettre à jour le fonds", - "fundDelete": "Supprimer le fonds", - "no": "Non", - "yes": "Oui", - "manageFund": "Gérer le fonds", - "searchFullName": "Rechercher par nom", - "filter": "Filtre", - "noFundsFound": "Aucun fonds trouvé", - "createdBy": "Créé par", - "createdOn": "Créé le", - "status": "Statut", - "archiveFund": "Archiver le fonds", - "archiveFundMsg": "Voulez-vous archiver ce fonds ?", - "fundCreated": "Fonds créé avec succès", - "fundUpdated": "Fonds mis à jour avec succès", - "fundDeleted": "Fonds supprimé avec succès", - "fundArchived": "Fonds archivé avec succès", - "fundUnarchived": "Fonds désarchivé avec succès", - "deleteFundMsg": "Voulez-vous supprimer ce fonds ?" - }, - "fundCampaign": { - "title": "Campagne de fonds", - "campaignName": "Nom de la campagne", - "startDate": "Date de début", - "endDate": "Date de fin", - "campaignOptions": " Options de campagne", - "fundingGoal": "Objectif de financement", - "addCampaign": "Ajouter une campagne", - "createdCampaign": "Campagne créée avec succès", - "updatedCampaign": "Campagne mise à jour avec succès", - "deletedCampaign": "Campagne supprimée avec succès", - "deleteCampaignMsg": "Voulez-vous supprimer cette campagne?", - "noCampaigns": "Pas de campagnes", - "createCampaign": "Créer une campagne de fonds", - "updateCampaign": "Mettre à jour la campagne de fonds", - "manageCampaign": "Gérer la campagne de fonds", - "deleteCampaign": "Supprimer la campagne de fonds", - "no": "Non", - "yes": "Oui", - "currency": "Devise", - "selectCurrency": "Sélectionnez la devise", - "filter": "Filtre", - "searchFullName": "Rechercher par nom" - }, - "pledges": { - "title": "Engagements de campagne de financement", - "volunteers": "Bénévoles", - "startDate": "Date de début", - "endDate": "Date de fin", - "pledgeAmount": "Montant de l'engagement", - "pledgeOptions": "Options", - "pledgeCreated": "Engagement créé avec succès", - "pledgeUpdated": "Engagement mis à jour avec succès", - "pledgeDeleted": "Engagement supprimé avec succès", - "addPledge": "Ajouter un engagement", - "createPledge": "Créer un engagement", - "currency": "Devise", - "selectCurrency": "Sélectionner une devise", - "updatePledge": "Mettre à jour l'engagement", - "deletePledge": "Supprimer l'engagement", - "amount": "Montant", - "editPledge": "Modifier l'engagement", - "deletePledgeMsg": "Êtes-vous sûr de vouloir supprimer cet engagement?", - "no": "Non", - "yes": "Oui", - "noPledges": "Aucun engagement trouvé" - }, - "orgPost": { - "title": "Talawa Publications", - "searchPost": "Rechercher une publication", - "posts": "Publications", - "createPost": "Créer une publication", - "postDetails": "Détails de la publication", - "postTitle1": "Écrire le titre de la publication", - "postTitle": "Titre", - "addMedia": "Télécharger une photo ou une vidéo", - "information": "Informations", - "information1": "Écrire les informations de la publication", - "addPost": "Ajouter une publication", - "searchTitle": "Rechercher par titre", - "searchText": "Rechercher par texte", - "ptitle": "Titre de la publication", - "postDes": "De quoi voulez-vous parler?", - "Title": "Titre", - "Text": "Texte", - "cancel": "Annuler", - "searchBy": "Rechercher par", - "Oldest": "Les plus anciennes d'abord", - "Latest": "Les plus récentes d'abord", - "sortPost": "Trier les publications", - "tag": "Votre navigateur ne prend pas en charge la balise vidéo", - "postCreatedSuccess": "Félicitations ! Vous avez publié quelque chose.", - "pinPost": "Épingler le message", - "Next": "Suivant ", - "Previous": "Précédent" - }, - "postNotFound": { - "post": "Poste", - "not found!": "Pas Trouvé!", - "organization": "Organization", - "post not found!": "Poste Pas Trouvé!", - "organization not found!": "Organization Pas Trouvé!" - }, - "userNotFound": { - "user": "utilisateur", - "not found!": "pas trouvé!", - "roles": "les rôles", - "user not found!": "utilisateur non trouvé!", - "member not found!": "Membre introuvable!", - "admin not found!": "Administrateur introuvable!", - "roles not found!": "utilisateur non trouvé!" - }, - "orgPostCard": { - "author": "Auteur", - "imageURL": "URL de l'image", - "videoURL": "URL de la vidéo", - "edit": "Modifier la publication", - "deletePost": "Supprimer la publication", - "deletePostMsg": "Voulez-vous supprimer cette publication ?", - "no": "Non", - "yes": "Oui", - "editPost": "Modifier la publication", - "postTitle": "Titre", - "postTitle1": "Modifier le titre du message", - "information1": "Modifier les informations du message", - "information": "Informations", - "image": "Image", - "video": "Vidéo", - "close": "Fermer", - "pin": "Épingler la publication", - "updatePost": "Mettre à jour la publication", - "postDeleted": "Publication supprimée avec succès.", - "postUpdated": "Publication mise à jour avec succès.", - "tag": "Votre navigateur ne prend pas en charge la balise vidéo", - "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau." - }, - "blockUnblockUser": { - "title": "Talawa Bloquer/Débloquer l'utilisateur", - "pageName": "Bloquer/Débloquer'", - "searchByName": "Recherche par nom", - "listOfUsers": "Liste des utilisateurs qui ont spammé", - "name": "Nom", - "email": "E-mail", - "block_unblock": "Bloquer/Débloquer", - "unblock": "Débloquer", - "block": "Bloquer", - "orgName": "Entrez le nom", - "blockedSuccessfully": "Utilisateur bloqué avec succès", - "Un-BlockedSuccessfully": "Utilisateur débloqué avec succès", - "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau.", - "allMembers": "Tous les membres", - "blockedUsers": "Utilisateurs bloqués", - "searchByFirstName": "Rechercher par prénom", - "searchByLastName": "Rechercher par nom de famille", - "noResultsFoundFor": "Aucun résultat trouvé pour ", - "noSpammerFound": "Aucun spammeur trouvé" - }, - "eventManagement": { - "title": "Gestion des événements", - "dashboard": "Tableau de bord", - "registrants": "Participants inscrits", - "eventActions": "Actions d'événement", - "eventStats": "Statistiques de l'événement", - "to": "À" - }, - "forgotPassword": { - "title": "Mot de passe oublié Talawa", - "forgotPassword": "Mot de passe oublié", - "registeredEmail": "Email enregistré", - "getOtp": "Obtenir OTP", - "enterOtp": "Entrez OTP", - "enterNewPassword": "Entrez un nouveau mot de passe", - "cofirmNewPassword": "Confirmer le nouveau mot de passe", - "changePassword": "Changer le mot de passe", - "backToLogin": "Retour à la connexion", - "userOtp": "par exemple. 12345", - "password": "Mot de passe", - "emailNotRegistered": "L'e-mail n'est pas enregistré.", - "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau.", - "errorSendingMail": "Erreur lors de l'envoi du courrier.", - "passwordMismatches": "Le mot de passe et la confirmation du mot de passe ne correspondent pas.", - "passwordChanges": "Mot de passe modifié avec succès.", - "OTPsent": "OTP est envoyé à votre adresse e-mail enregistrée." - }, - "pageNotFound": { - "title": "404 introuvable", - "talawaAdmin": "Administrateur Talawa", - "talawaUser": "Utilisateur Talawa", - "404": "404", - "notFoundMsg": "Oups ! La page demandée est introuvable !", - "backToHome": "De retour à la maison" - }, - "orgContribution": { - "title": "Cotisations Talawa", - "filterByName": "Filtrer par nom", - "filterByTransId": "Filtrer par Trans. ID", - "recentStats": "Statistiques récentes", - "contribution": "Contribution", - "orgname": "Entrez le nom", - "searchtransaction": "Saisir l'identifiant de la transaction" - }, - "contriStats": { - "recentContribution": "Contribution récente", - "highestContribution": "Contribution la plus élevée", - "totalContribution": "Contribution totale" - }, - "orgContriCards": { - "date": "Date", - "transactionId": "Identifiant de transaction", - "amount": "Montant" - }, - "orgSettings": { - "title": "Paramètre Talawa", - "pageName": "Paramètres", - "general": "Général", - "actionItemCategories": "Catégories d’éléments d’action", - "updateYourDetails": "Mettre à jour vos informations", - "updateYourPassword": "Mettez à jour votre mot de passe", - "updateOrganization": "Mettre à jour l'organisation", - "seeRequest": "Voir demande", - "settings": "Réglages", - "noData": "Pas de données", - "otherSettings": "Autres paramètres", - "changeLanguage": "Changer la langue", - "manageCustomFields": "Gérer les Champs Personnalisés" - }, - "deleteOrg": { - "deleteOrganization": "Supprimer l'organisation", - "deleteSampleOrganization": "Supprimer l'organisation d'exemple", - "deleteMsg": "Voulez-vous supprimer cette organisation ?", - "cancel": "Annuler", - "confirmDelete": "Confirmer la suppression", - "longDelOrgMsg": "En cliquant sur le bouton Supprimer l'organisation, l'organisation sera définitivement supprimée ainsi que ses événements, balises et toutes les données associées.", - "successfullyDeletedSampleOrganization": "Exemple d'organisation supprimé avec succès" - }, - "userUpdate": { - "firstName": "Prénom", - "lastName": "Nom de famille", - "email": "E-mail", - "password": "Mot de passe", - "appLanguageCode": "Langue par défaut", - "userType": "Type d'utilisateur", - "admin": "Administrateur", - "superAdmin": "Super administrateur", - "displayImage": "Afficher l'image", - "saveChanges": "Sauvegarder les modifications", - "cancel": "Annuler" - }, - "userPasswordUpdate": { - "previousPassword": "mot de passe précédent", - "newPassword": "Nouveau mot de passe", - "confirmNewPassword": "Confirmer le nouveau mot de passe", - "saveChanges": "Sauvegarder les modifications", - "cancel": "Annuler" - }, - "orgDelete": { - "deleteOrg": "Supprimer l'organisation" - }, - "membershipRequest": { - "joined": "Inscrit", - "accept": "Accepter", - "reject": "Rejeter", - "memberAdded": "c'est accepté", - "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau." - }, - "orgUpdate": { - "name": "Nom", - "description": "La description", - "location": "emplacement", - "address": "Adresse", - "city": "Ville", - "countryCode": "Code Pays", - "line1": "Ligne 1", - "line2": "Ligne 2", - "postalCode": "Code Postal", - "dependentLocality": "Localité Dépendante", - "sortingCode": "Code de Tri", - "state": "État / Province", - "displayImage": "Afficher l'image", - "userRegistrationRequired": "enregistrement requis", - "isVisibleInSearch": "Visible dans la recherche", - "saveChanges": "Sauvegarder les modifications", - "enterNameOrganization": "Entrez le nom de l'organisation", - "successfulUpdated": "Mise à jour réussie", - "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau." - }, - "addOnRegister": { - "addNew": "Ajouter nouveau", - "addPlugin": "Ajouter un plug-in", - "pluginName": "Nom du plug-in", - "creatorName": "Creator Name", - "pluginDesc": "Description du plug-in", - "close": "Fermer", - "register": "Enregistrer", - "pName": "Ex : Dons", - "cName": "Ex: Jean Doe", - "pDesc": "Ce plugin active l'interface utilisateur pour" - }, - "addOnStore": { - "title": "Add-On Store", - "searchName": "Ex:Des dons ", - "enable": "Activé", - "disable": "Désactivé", - "pHeading": "Plugins", - "install": "Installée", - "available": "Disponible", - "pMessage": "Le plugin n'existe pas", - "filter": "Filtres", - "search": "recherche" - }, - "addOnEntry": { - "enable": "Activé", - "install": "Installer", - "uninstall": "désinstaller" - }, - "memberDetail": { - "title": "Détails de l'utilisateur", - "addAdmin": "Ajouter un administrateur", - "alreadyIsAdmin": "Le membre est déjà un administrateur", - "organizations": "Organisations", - "events": "Événements", - "role": "Rôle", - "email": "Email", - "createdOn": "Créé le", - "main": "Principal", - "firstName": "Prénom", - "lastName": "Nom de famille", - "language": "Langue", - "gender": "Genre", - "birthDate": "Date de naissance", - "educationGrade": "Niveau d'éducation", - "employmentStatus": "Statut d'emploi", - "maritalStatus": "État civil", - "displayImage": "Image de profil", - "phone": "Téléphone", - "address": "Adresse", - "countryCode": "Code pays", - "state": "État", - "city": "Ville", - "personalInfoHeading": "Informations personnelles", - "contactInfoHeading": "Coordonnées", - "actionsHeading": "Actions", - "personalDetailsHeading": "Détails du profil", - "appLanguageCode": "Choisir la langue", - "delete": "Supprimer l'utilisateur", - "saveChanges": "Enregistrer les modifications", - "pluginCreationAllowed": "Autorisation de création de plugin", - "joined": "Rejoint", - "created": "Créé", - "adminForOrganizations": "Administrateur pour les organisations", - "membershipRequests": "Demandes d'adhésion", - "adminForEvents": "Administrateur pour les événements", - "addedAsAdmin": "L'utilisateur est ajouté en tant qu'administrateur.", - "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Veuillez vérifier votre connexion réseau et attendre un moment." - }, - "userLogin": { - "login": "Connexion", - "forgotPassword": "Mot de passe oublié?", - "loginIntoYourAccount": "Connectez-vous à votre compte", - "emailAddress": "Email Address", - "enterEmail": "Entrez votre adresse email", - "password": "Mot de passe", - "enterPassword": "Tapez votre mot de passe", - "register": "Enregistrer", - "invalidDetailsMessage": "Veuillez saisir un e-mail et un mot de passe valides.", - "notAuthorised": "Désolé! vous n'êtes pas autorisé !", - "invalidCredentials": "Les informations d'identification saisies sont incorrectes. Veuillez entrer des informations d'identification valides.", - "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Veuillez vérifier votre connexion réseau et attendre un moment." - }, - "userRegister": { - "register": "Enregistrer", - "firstName": "Prénom", - "enterFirstName": "Entrez votre prénom", - "lastName": "Nom de famille", - "enterLastName": "Entrez votre nom de famille", - "emailAddress": "Email Address", - "enterEmail": "Entrez votre adresse email", - "password": "Mot de passe", - "enterPassword": "Tapez votre mot de passe", - "confirmPassword": "Confirmez le mot de passe", - "enterConfirmPassword": "Entrez votre mot de passe pour confirmer", - "alreadyhaveAnAccount": "Vous avez déjà un compte?", - "login": "Connexion", - "afterRegister": "Enregistré avec succès. Veuillez attendre que l'administrateur approuve votre demande.", - "passwordNotMatch": "Le mot de passe ne correspond pas. Confirmez le mot de passe et réessayez.", - "invalidDetailsMessage": "Veuillez entrer des détails valides.", - "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Veuillez vérifier votre connexion réseau et attendre un moment." - }, - "userNavbar": { - "talawa": "Talawa", - "home": "Maison", - "people": "Personnes", - "events": "Événements", - "chat": "Discuter", - "donate": "Donner", - "settings": "Paramètres", - "language": "Langue", - "logout": "Se déconnecter", - "close": "Fermer" - }, - "userOrganizations": { - "allOrganizations": "Toutes les organisations", - "joinedOrganizations": "Organisations jointes", - "createdOrganizations": "Organisations créées", - "search": "Rechercher des utilisateurs", - "nothingToShow": "Rien à montrer ici.", - "selectOrganization": "Sélectionnez une organisation", - "filter": "Filtre", - "organizations": "Organizations", - "searchByName": "Recherche par nom" - }, - "userSidebarOrg": { - "yourOrganizations": "Vos organisations", - "noOrganizations": "Vous n'avez encore rejoint aucune organisation.", - "viewAll": "Voir tout", - "talawaUserPortal": "Talawa portail utilisateur", - "menu": "Menu", - "my organizations": "Mes Organisations", - "users": "Utilisateurs", - "requests": "Demandes", - "communityProfile": "Profil de la communauté", - "logout": "Se déconnecter", - "settings": "Paramètres" - }, - "organizationSidebar": { - "viewAll": "Voir tout", - "events": "Événements", - "members": "Membres", - "noEvents": "Aucun événement à afficher", - "noMembers": "Aucun membre à afficher" - }, - "postCard": { - "likes": "Aime", - "comments": "commentaires" - }, - "home": { - "feed": "Alimentation", - "pinnedPosts": "Afficher les publications épinglées", - "somethingOnYourMind": "Quelque chose dans votre esprit?", - "addPost": "Ajouter une publication", - "startPost": "Commencer une publication", - "media": "Médias", - "event": "Événement", - "article": "Article" - }, - "settings": { - "settings": "Paramètres", - "profileSettings": "Paramètres de profil", - "firstName": "Prénom", - "lastName": "Nom de famille", - "gender": "Genre", - "emailAddress": "Adresse e-mail", - "phoneNumber": "Numéro de téléphone", - "displayImage": "Image de profil", - "chooseFile": "Choisir un fichier", - "birthDate": "Date de naissance", - "grade": "Niveau scolaire", - "empStatus": "Situation professionnelle", - "maritalStatus": "État civil", - "address": "Adresse", - "state": "Ville/État", - "country": "Pays", - "resetChanges": "Réinitialiser les modifications", - "saveChanges": "Enregistrer les modifications", - "profileDetails": "Détails du profil", - "deleteUserMessage": "En cliquant sur le bouton Supprimer l'utilisateur, votre utilisateur sera supprimé définitivement ainsi que ses événements, tags et toutes les données associées.", - "copyLink": "Copier le lien du profil", - "deleteUser": "Supprimer l'utilisateur", - "otherSettings": "Autres paramètres", - "changeLanguage": "Changer la langue", - "sgender": "Sélectionner le genre", - "gradePlaceholder": "Entrer la note", - "sEmpStatus": "Sélectionner le statut d'emploi", - "male": "Homme", - "female": "Femme", - "other": "Autre", - "employed": "Employé(e)", - "unemployed": "Sans emploi", - "sMaritalStatus": "Sélectionner l'état civil", - "single": "Célibataire", - "married": "Marié(e)", - "divorced": "Divorcé(e)", - "widowed": "Veuf(ve)", - "engaged": "Fiancé(e)", - "seperated": "Séparé(e)", - "grade1": "CP (Cours Préparatoire)", - "grade2": "CE1 (Cours Élémentaire 1ère année)", - "grade3": "CE2 (Cours Élémentaire 2ème année)", - "grade4": "CM1 (Cours Moyen 1ère année)", - "grade5": "CM2 (Cours Moyen 2ème année)", - "grade6": "6ème", - "grade7": "5ème", - "grade8": "4ème", - "grade9": "3ème", - "grade10": "Seconde", - "grade11": "Première", - "grade12": "Terminale", - "graduate": "Diplômé(e)", - "kg": "Maternelle", - "preKg": "Toute Petite Section", - "noGrade": "Pas de niveau", - "fullTime": "Temps plein", - "partTime": "Temps partiel", - "enterState": "Entrer la ville ou l'état", - "selectCountry": "Sélectionner un pays", - "joined": "Rejoint" - }, - "donate": { - "donations": "Des dons", - "searchDonations": "Rechercher des dons", - "donateForThe": "Faites un don pour le", - "amount": "Montante", - "yourPreviousDonations": "Vos dons précédents", - "donate": "Donner", - "nothingToShow": "Rien à montrer ici.", - "success": "Don réussi" - }, - "userEvents": { - "nothingToShow": "Rien à montrer ici.", - "search": "Recherche", - "createEvent": "Créer un évènement", - "recurring": "Récurrente", - "startTime": "Heure de début", - "endTime": "Heure de fin", - "cancel": "Annuler", - "create": "Créer", - "listView": "Vue en liste", - "calendarView": "Vue du calendrier", - "allDay": "Toute la journée", - "eventCreated": "Événement créé et publié avec succès.", - "eventDetails": "Détails de l'événement", - "eventTitle": "Titre", - "enterTitle": "Entrez le titre", - "eventDescription": "Description", - "enterDescription": "Entrez la description", - "eventLocation": "Emplacement", - "enterLocation": "Entrez l'emplacement", - "startDate": "Date de début", - "endDate": "Date de fin", - "publicEvent": "Est public", - "registerable": "Est enregistrable", - "monthlyCalendarView": "Calendrier mensuel", - "yearlyCalendarView": "Calendrier annuel" - }, - "userEventCard": { - "location": "Emplacement", - "starts": "Départs", - "ends": "Prend fin", - "creator": "Créatrice", - "alreadyRegistered": "Déjà enregistré", - "register": "Registre" - }, - "advertisement": { - "title": "Publicités", - "pHeading": "Gérer les publicités", - "activeAds": "Campagnes actives", - "archievedAds": "Campagnes terminées", - "pMessage": "Aucune publicité n'est présente pour cette campagne.", - "delete": "Supprimer", - "validLink": "Le lien est valide", - "invalidLink": "Le lien n'est pas valide", - "close": "Fermer", - "deleteAdvertisement": "Supprimer l'annonce", - "deleteAdvertisementMsg": "Voulez-vous supprimer cette annonce ?", - "no": "Non", - "yes": "Oui", - "Rmedia": "Fournir du contenu multimédia à afficher", - "view": "Voir", - "edit": "Éditer", - "editAdvertisement": "Éditer l'annonce", - "saveChanges": "Enregistrer les modifications", - "endOfResults": "Fin des résultats" - }, - "userChat": { - "chat": "Chat", - "search": "Recherche", - "contacts": "Contacts" - }, - "userChatRoom": { - "selectContact": "Sélectionnez un contact pour démarrer la conversation", - "sendMessage": "Envoyer le message" - }, - "orgProfileField": { - "loading": "Chargement...", - "noCustomField": "Aucun champ personnalisé disponible", - "customFieldName": "Nom du champ", - "enterCustomFieldName": "Entrez le nom du champ", - "customFieldType": "Type de champ", - "saveChanges": "Enregistrer les modifications", - "Supprimer le champ personnalisé": "Supprimer le champ personnalisé", - "fieldSuccessMessage": "Champ ajouté avec succès", - "fieldRemovalSuccess": "Champ supprimé avec succès" - }, - "orgActionItemCategories": { - "createButton": "Créez", - "editButton": "Éditez", - "enableButton": "Activez", - "disableButton": "Désactivez", - "updateActionItemCategory": "Mettre à jour", - "actionItemCategoryName": "Nom", - "actionItemCategoryDetails": "Détails de la catégorie d’élément d’action", - "enterName": "Entrez le nom", - "successfulCreation": "Catégorie d’élément d’action créée avec succès", - "successfulUpdation": "La catégorie d’élément d’action a été mise à jour avec succès", - "sameNameConflict": "Veuillez modifier le nom pour effectuer une mise à jour", - "categoryEnabled": "Catégorie d’action activée", - "categoryDisabled": "Catégorie d’action désactivée" - }, - "organizationVenues": { - "title": "Lieux", - "addVenue": "Ajouter un lieu", - "venueDetails": "Détails du lieu", - "venueName": "Nom du lieu", - "enterVenueName": "Entrez le nom du lieu", - "description": "Description du lieu", - "enterVenueDesc": "Entrez la description du lieu", - "capacity": "Capacité", - "enterVenueCapacity": "Entrez la capacité du lieu", - "image": "Image du lieu", - "uploadVenueImage": "Télécharger l'image du lieu", - "createVenue": "Créer un lieu", - "venueAdded": "Lieu ajouté avec succès", - "editVenue": "Mettre à jour le lieu", - "venueUpdated": "Détails du lieu mis à jour avec succès", - "sort": "Trier", - "highestCapacity": "Capacité la plus élevée", - "lowestCapacity": "Capacité la plus faible", - "noVenues": "Aucun lieu trouvé!", - "edit": "Modifier", - "view": "Voir", - "delete": "Supprimer", - "venueTitleError": "Le titre du lieu ne peut pas être vide!", - "venueCapacityError": "La capacité doit être un nombre positif!", - "searchBy": "Rechercher par", - "name": "Nom", - "desc": "Description" - }, - "addMember": { - "title": "Ajouter un membre", - "addMembers": "Ajouter des membres", - "existingUser": "Utilisateur existant", - "newUser": "Nouvel utilisateur", - "searchFullName": "Rechercher par nom complet", - "firstName": "Prénom", - "enterFirstName": "Entrez le prénom", - "lastName": "Nom de famille", - "enterLastName": "Entrez le nom de famille", - "emailAddress": "Adresse e-mail", - "enterEmail": "Entrez l'e-mail", - "password": "Mot de passe", - "enterPassword": "Entrez le mot de passe", - "confirmPassword": "Confirmer le mot de passe", - "enterConfirmPassword": "Confirmez le mot de passe", - "organization": "Organisation", - "cancel": "Annuler", - "create": "Créer", - "invalidDetailsMessage": "Veuillez fournir tous les détails requis.", - "passwordNotMatch": "Les mots de passe ne correspondent pas.", - "user": "Utilisateur", - "addMember": "Ajouter un membre" - }, - "eventActionItems": { - "title": "Éléments d'action", - "createActionItem": "Créer des éléments d'action", - "actionItemCategory": "Catégorie d'éléments d'action", - "selectActionItemCategory": "Sélectionnez une catégorie d'élément d'action", - "selectAssignee": "Sélectionner un cessionnaire", - "preCompletionNotes": "Notes de pré-achèvement", - "postCompletionNotes": "Notes post-achèvement", - "actionItemDetails": "Détails de l'élément d'action", - "dueDate": "Date d'échéance", - "completetionDate": "Date d'achèvement", - "editActionItem": "Modifier l'élément d'action", - "deleteActionItem": "Supprimer l'élément d'action", - "deleteActionItemMsg": "Voulez-vous supprimer cette action ?", - "yes": "Oui", - "no": "non", - "successfulDeletion": "Élément d'action supprimé avec succès", - "successfulCreation": "Élément d'action créé avec succès", - "successfulUpdation": "Élément d'action mis à jour avec succès", - "notes": "Remarques", - "save": "Enregistrer" - } -} diff --git a/public/locales/fr/common.json b/public/locales/fr/common.json new file mode 100644 index 0000000000..bce0b3bcea --- /dev/null +++ b/public/locales/fr/common.json @@ -0,0 +1,65 @@ +{ + "firstName": "Prénom", + "lastName": "Nom de famille", + "searchByName": "Rechercher par nom", + "loading": "Chargement...", + "endOfResults": "Fin des résultats", + "noResultsFoundFor": "Aucun résultat trouvé pour ", + "edit": "Modifier", + "admins": "Administrateurs", + "admin": "ADMINISTRATEUR", + "user": "UTILISATEUR", + "superAdmin": "SUPERADMIN", + "members": "Membres", + "logout": "Se déconnecter", + "login": "Se connecter", + "register": "Registre", + "menu": "Menu", + "settings": "Paramètres", + "users": "Utilisateurs", + "requests": "Demandes", + "OR": "OU", + "cancel": "Annuler", + "close": "Fermer", + "create": "Créer", + "delete": "Supprimer", + "done": "Fait", + "yes": "Oui", + "no": "Non", + "filter": "Filtre", + "search": "Recherche", + "description": "Description", + "saveChanges": "Sauvegarder les modifications", + "displayImage": "Afficher l'image", + "enterEmail": "Entrez l'e-mail", + "emailAddress": "Adresse e-mail", + "email": "E-mail", + "name": "Nom", + "enterPassword": "Entrer le mot de passe", + "password": "Mot de passe", + "confirmPassword": "Confirmez le mot de passe", + "forgotPassword": "Mot de passe oublié ?", + "talawaAdminPortal": "Portail d'administration Talawa", + "address": "Adresse", + "location": "Emplacement", + "enterLocation": "Entrez l'emplacement", + "joined": "Rejoint", + "startDate": "Date de début", + "endDate": "Date de fin", + "startTime": "Heure de début", + "endTime": "Heure de fin", + "My Organizations": "Mes Organisations", + "Dashboard": "Tableau de Bord", + "People": "Personnes", + "Events": "Événements", + "Venues": "Lieux", + "Action Items": "Éléments d'Action", + "Posts": "Publications", + "Block/Unblock": "Bloquer/Débloquer", + "Advertisement": "Publicité", + "Funds": "Fonds", + "Membership Requests": "Demandes d'Adhésion", + "Plugins": "Plugins", + "Plugin Store": "Magasin de Plugins", + "Settings": "Paramètres" +} diff --git a/public/locales/fr/errors.json b/public/locales/fr/errors.json new file mode 100644 index 0000000000..5788340a97 --- /dev/null +++ b/public/locales/fr/errors.json @@ -0,0 +1,9 @@ +{ + "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible !. ", + "notFound": "Pas trouvé", + "unknownError": "Une erreur inconnue est survenue. {{msg}}", + "notAuthorised": "Désolé! ", + "errorSendingMail": "Erreur lors de l'envoi du courrier", + "emailNotRegistered": "Email non enregistré", + "notFoundMsg": "Oops! " +} diff --git a/public/locales/fr/translation.json b/public/locales/fr/translation.json new file mode 100644 index 0000000000..e9168770ce --- /dev/null +++ b/public/locales/fr/translation.json @@ -0,0 +1,892 @@ +{ + "loginPage": { + "title": "Administrateur Talawa", + "fromPalisadoes": "Une application open source réalisée par les bénévoles de la Fondation Palisadoes", + "userLogin": "Utilisateur en ligne", + "atleast_8_char_long": "Au moins 8 caractères", + "atleast_6_char_long": "Au moins 6 caractères", + "firstName_invalid": "Le prénom ne doit contenir que des lettres minuscules et majuscules", + "lastName_invalid": "Le nom de famille ne doit contenir que des lettres minuscules et majuscules", + "password_invalid": "Le mot de passe doit contenir au moins une lettre minuscule, une lettre majuscule, une valeur numérique et un caractère spécial", + "email_invalid": "L'e-mail doit contenir au moins 8 caractères", + "Password_and_Confirm_password_mismatches.": "Mot de passe et Confirmer les incompatibilités de mot de passe.", + "doNotOwnAnAccount": "Vous ne possédez pas de compte ?", + "captchaError": "Erreur CAPTCHA!", + "Please_check_the_captcha": "S'il vous plaît, vérifiez le captcha.", + "Something_went_wrong": "Quelque chose s'est mal passé. Veuillez réessayer plus tard.", + "passwordMismatches": "Mot de passe et Confirmer les incompatibilités de mot de passe.", + "fillCorrectly": "Remplissez correctement tous les détails.", + "successfullyRegistered": "Enregistré avec succès. ", + "lowercase_check": "Au moins une lettre minuscule", + "uppercase_check": "Au moins une lettre majuscule", + "numeric_value_check": "Au moins une valeur numérique", + "special_char_check": "Au moins un caractère spécial", + "selectOrg": "Sélectionnez une organisation", + "afterRegister": "Enregistré avec succès. " + }, + "userLoginPage": { + "title": "Administrateur Talawa", + "fromPalisadoes": "Une application open source réalisée par les bénévoles de la Fondation Palisadoes", + "atleast_8_char_long": "Au moins 8 caractères", + "Password_and_Confirm_password_mismatches.": "Mot de passe et Confirmer les incompatibilités de mot de passe.", + "doNotOwnAnAccount": "Vous ne possédez pas de compte ?", + "captchaError": "Erreur CAPTCHA!", + "Please_check_the_captcha": "S'il vous plaît, vérifiez le captcha.", + "Something_went_wrong": "Quelque chose s'est mal passé. Veuillez réessayer plus tard.", + "passwordMismatches": "Mot de passe et Confirmer les incompatibilités de mot de passe.", + "fillCorrectly": "Remplissez correctement tous les détails.", + "successfullyRegistered": "Enregistré avec succès. ", + "userLogin": "Utilisateur en ligne", + "afterRegister": "Enregistré avec succès. ", + "selectOrg": "Sélectionnez une organisation" + }, + "latestEvents": { + "eventCardTitle": "évènements à venir", + "eventCardSeeAll": "Voir tout", + "noEvents": "Aucun événement à venir" + }, + "latestPosts": { + "latestPostsTitle": "Derniers messages", + "seeAllLink": "Voir tout", + "noPostsCreated": "Aucun message créé" + }, + "listNavbar": { + "roles": "Les rôles" + }, + "leftDrawer": { + "my organizations": "Mes organisations", + "requests": "Demandes d'adhésion", + "communityProfile": "Profil de la communauté" + }, + "leftDrawerOrg": { + "Dashboard": "Tableau de bord", + "People": "Personnes", + "Events": "Événements", + "Contributions": "Contributions", + "Posts": "Des postes", + "Block/Unblock": "Bloquer/Débloquer", + "Plugins": "Plugins", + "Plugin Store": "Magasin de plugins", + "Advertisement": "Annonces", + "allOrganizations": "Toutes les organisations", + "yourOrganization": "Ton organisation", + "notification": "Notification", + "language": "Langue", + "notifications": "Notifications", + "spamsThe": "spamme le", + "group": "groupe", + "noNotifications": "Aucune notification" + }, + "orgList": { + "title": "Organisations Talawa", + "you": "Toi", + "designation": "Désignation", + "my organizations": "Mes organisations", + "createOrganization": "Créer une organisation", + "createSampleOrganization": "Créer un exemple d'organisation", + "city": "Ville", + "countryCode": "Code postal", + "dependentLocality": "Localité dépendante", + "line1": "Ligne 1", + "line2": "Ligne 2", + "postalCode": "Code Postal", + "sortingCode": "Code de tri", + "state": "État/Province", + "userRegistrationRequired": "Inscription de l'utilisateur requise", + "visibleInSearch": "Visible dans la recherche", + "enterName": "Entrez le nom", + "sort": "Trier", + "Latest": "Dernier", + "Earliest": "Le plus tôt", + "noOrgErrorTitle": "Organisations introuvables", + "sampleOrgDuplicate": "Un seul échantillon d’organisation autorisé", + "noOrgErrorDescription": "Veuillez créer une organisation via le tableau de bord", + "manageFeatures": "Gérer les fonctionnalités", + "manageFeaturesInfo": "Création réussie ! ", + "goToStore": "Accédez à la boutique de plugins", + "enableEverything": "Activer tout", + "sampleOrgSuccess": "Exemple d'organisation créée avec succès" + }, + "orgListCard": { + "manage": "Gérer", + "sampleOrganization": "Exemple d'organisation" + }, + "paginationList": { + "rowsPerPage": "lignes par page", + "all": "Tous" + }, + "requests": { + "title": "Demandes d'adhésion", + "sl_no": "Sl. ", + "accept": "Accepter", + "reject": "Rejeter", + "searchRequests": "Rechercher des demandes d'adhésion", + "noOrgError": "Organisations introuvables, veuillez créer une organisation via le tableau de bord", + "noRequestsFound": "Aucune demande d'adhésion trouvée", + "acceptedSuccessfully": "Demande acceptée avec succès", + "rejectedSuccessfully": "Demande rejetée avec succès", + "noOrgErrorTitle": "Organisations introuvables", + "noOrgErrorDescription": "Veuillez créer une organisation via le tableau de bord" + }, + "users": { + "title": "Rôles Talawa", + "joined_organizations": "Organisations rejointes", + "blocked_organizations": "Organisations bloquées", + "orgJoinedBy": "Organisations rejointes par", + "orgThatBlocked": "Organisations qui ont bloqué", + "hasNotJoinedAnyOrg": "n'a rejoint aucune organisation", + "isNotBlockedByAnyOrg": "n'est bloqué par aucune organisation", + "searchByOrgName": "Rechercher par nom d'organisation", + "view": "Voir", + "enterName": "Entrez le nom", + "loadingUsers": "Chargement des utilisateurs...", + "noUserFound": "Aucun utilisateur trouvé", + "sort": "Trier", + "Newest": "Le plus récent d'abord", + "Oldest": "Le plus âgé en premier", + "noOrgError": "Organisations introuvables, veuillez créer une organisation via le tableau de bord", + "roleUpdated": "Rôle mis à jour.", + "joinNow": "Adhérer maintenant", + "visit": "Visite", + "withdraw": "Largeur de tirage" + }, + "communityProfile": { + "title": "Profil de la communauté", + "editProfile": "Editer le profil", + "communityProfileInfo": "Ces détails apparaîtront sur l'écran de connexion/inscription pour vous et les membres de votre communauté.", + "communityName": "Nom de la communauté", + "wesiteLink": "Lien de site Web", + "logo": "Logo", + "social": "Liens vers les réseaux sociaux", + "url": "Entrer l'URL", + "profileChangedMsg": "Les détails du profil ont été mis à jour avec succès.", + "resetData": "Réinitialisez avec succès les détails du profil." + }, + "dashboard": { + "title": "Tableau de bord", + "about": "À propos", + "deleteThisOrganization": "Supprimer cette organisation", + "statistics": "Statistiques", + "posts": "Des postes", + "events": "Événements", + "blockedUsers": "Utilisateurs bloqués", + "viewAll": "Voir tout", + "upcomingEvents": "évènements à venir", + "noUpcomingEvents": "Aucun événement à venir", + "latestPosts": "Derniers messages", + "noPostsPresent": "Aucun message présent", + "membershipRequests": "Demandes d'adhésion", + "noMembershipRequests": "Aucune demande d'adhésion présente" + }, + "organizationPeople": { + "title": "Membres Talawa", + "filterByName": "Filtrer par nom", + "filterByLocation": "Filtrer par emplacement", + "filterByEvent": "Filtrer par événement", + "searchName": "Entrez le nom", + "searchevent": "Entrer l'événement", + "searchFullName": "Entrez le nom complet", + "people": "Personnes", + "sort": "Recherche par rôle", + "actions": "Actions", + "addMembers": "Ajouter des membres", + "existingUser": "Utilisateur existant", + "newUser": "Nouvel utilisateur", + "enterFirstName": "Entrez votre prénom", + "enterLastName": "Entrez votre nom de famille", + "enterConfirmPassword": "Entrez votre mot de passe pour confirmer", + "organization": "Organisation", + "invalidDetailsMessage": "Veuillez saisir des informations valides." + }, + "userListCard": { + "addAdmin": "Ajouter un administrateur", + "addedAsAdmin": "L'utilisateur est ajouté en tant qu'administrateur." + }, + "orgAdminListCard": { + "remove": "Retirer", + "removeAdmin": "Supprimer l'administrateur", + "removeAdminMsg": "Voulez-vous supprimer cet administrateur ?", + "adminRemoved": "L'administrateur est supprimé." + }, + "orgPeopleListCard": { + "remove": "Retirer", + "removeMember": "Supprimer un membre", + "removeMemberMsg": "Voulez-vous supprimer ce membre ?", + "memberRemoved": "Le membre est supprimé" + }, + "organizationEvents": { + "title": "Événements", + "filterByTitle": "Filtrer par titre", + "filterByLocation": "Filtrer par emplacement", + "filterByDescription": "Filtrer par description", + "addEvent": "Ajouter un évènement", + "eventDetails": "Détails de l'évènement", + "eventTitle": "Titre", + "startTime": "Heure de début", + "endTime": "Heure de fin", + "allDay": "Toute la journée", + "recurringEvent": "Événement récurrent", + "isPublic": "est public", + "isRegistrable": "Est enregistrable", + "createEvent": "Créer un évènement", + "enterFilter": "Entrer le filtre", + "enterTitle": "Entrez le titre", + "enterDescrip": "Entrez la description", + "eventLocation": "Entrez l'emplacement", + "searchEventName": "Rechercher le nom de l'événement", + "eventType": "Type d'événement", + "eventCreated": "Toutes nos félicitations! ", + "customRecurrence": "Récurrence personnalisée", + "repeatsEvery": "Se répète tous les", + "repeatsOn": "Répétition activée", + "ends": "Prend fin", + "never": "Jamais", + "on": "Sur", + "after": "Après", + "occurences": "événements" + }, + "organizationActionItems": { + "actionItemCategory": "Catégorie d'élément d'action", + "actionItemDetails": "Détails de l'action", + "actionItemCompleted": "Élément d'action terminé", + "assignee": "Cessionnaire", + "assigner": "Assigner", + "assignmentDate": "Date d'affectation", + "active": "Actif", + "clearFilters": "Effacer les filtres", + "completed": "Complété", + "completionDate": "Date d'achèvement", + "deleteActionItem": "Supprimer l'élément d'action", + "deleteActionItemMsg": "Voulez-vous supprimer cette action ?", + "details": "Détails", + "dueDate": "Date d'échéance", + "earliest": "Le plus tôt", + "editActionItem": "Modifier l'élément d'action", + "isCompleted": "Complété", + "latest": "Dernier", + "noActionItems": "Aucune action", + "options": "Possibilités", + "preCompletionNotes": "Notes préalables à l'achèvement", + "actionItemActive": "Actif", + "markCompletion": "Marquer l'achèvement", + "actionItemStatus": "Statut de l'action", + "postCompletionNotes": "Notes post-achèvement", + "selectActionItemCategory": "Sélectionnez une catégorie d'élément d'action", + "selectAssignee": "Sélectionnez un responsable", + "status": "Statut", + "successfulCreation": "Élément d'action créé avec succès", + "successfulUpdation": "Élément d'action mis à jour avec succès", + "successfulDeletion": "Élément d'action supprimé avec succès", + "title": "Éléments d'action" + }, + "eventListCard": { + "deleteEvent": "Supprimer l'événement", + "deleteEventMsg": "Voulez-vous supprimer cet événement ?", + "editEvent": "Modifier l'événement", + "eventTitle": "Titre", + "alreadyRegistered": "Déjà enregistré", + "startTime": "Heure de début", + "endTime": "Heure de fin", + "allDay": "Toute la journée", + "recurringEvent": "Événement récurrent", + "isPublic": "est public", + "isRegistrable": "Est enregistrable", + "updatePost": "Mettre à jour le message", + "eventDetails": "Détails de l'évènement", + "eventDeleted": "Événement supprimé avec succès.", + "eventUpdated": "Événement mis à jour avec succès.", + "thisInstance": "Cette instance", + "thisAndFollowingInstances": "Instances présentes et suivantes", + "allInstances": "Toutes les instances", + "customRecurrence": "Récurrence personnalisée", + "repeatsEvery": "Se répète tous les", + "repeatsOn": "Répétition activée", + "ends": "Prend fin", + "never": "Jamais", + "on": "Sur", + "after": "Après", + "occurences": "événements" + }, + "funds": { + "title": "Fonds", + "createFund": "Créer un fonds", + "fundName": "Nom du fonds", + "fundId": "ID du fonds", + "fundOptions": "Options", + "noFunds": "Aucun fonds trouvé", + "fundDetails": "Détails du fonds", + "taxDeductible": "Déductible d'impôts", + "enterfundName": "Entrez le nom du fonds", + "enterfundId": "Entrez l'ID du fonds", + "default": "Fonds de défaut", + "archived": "Archivé", + "nonArchive": "Non archivé", + "fundCreate": "Créer un fonds", + "fundUpdate": "Mettre à jour le fonds", + "fundDelete": "Supprimer le fonds", + "manageFund": "Gérer le fonds", + "searchFullName": "Rechercher par nom", + "noFundsFound": "Aucun fonds trouvé", + "createdBy": "Créé par", + "createdOn": "Créé sur", + "status": "Statut", + "archiveFund": "Fonds d'archives", + "archiveFundMsg": "Lors de l'archivage, ce fonds le supprimera de la liste des fonds. Cette action peut être annulée.", + "fundCreated": "Fonds créé avec succès", + "fundUpdated": "Fonds mis à jour avec succès", + "fundDeleted": "Fonds supprimé avec succès", + "fundArchived": "Fonds archivé avec succès", + "fundUnarchived": "Fonds désarchivé avec succès", + "deleteFundMsg": "Voulez-vous supprimer ce fonds ?" + }, + "fundCampaign": { + "title": "Campagnes de collecte de fonds", + "campaignName": "Nom de la campagne", + "campaignOptions": "Possibilités", + "fundingGoal": "Objectif de financement", + "addCampaign": "Ajouter une campagne", + "createdCampaign": "Campagne créée avec succès", + "updatedCampaign": "Campagne mise à jour avec succès", + "deletedCampaign": "Campagne supprimée avec succès", + "deleteCampaignMsg": "Êtes-vous sûr de vouloir supprimer cette campagne ?", + "noCampaigns": "Aucune campagne trouvée", + "createCampaign": "Créer une campagne de financement", + "updateCampaign": "Mettre à jour la campagne de financement", + "manageCampaign": "Gérer la campagne de financement", + "deleteCampaign": "Supprimer la campagne de financement", + "currency": "Devise", + "selectCurrency": "Sélectionnez la devise", + "searchFullName": "Rechercher par nom" + }, + "pledges": { + "title": "Engagements de campagne de financement", + "volunteers": "Bénévoles", + "pledgeAmount": "Montant de la promesse de don", + "pledgeOptions": "Possibilités", + "pledgeCreated": "Engagement créé avec succès", + "pledgeUpdated": "Engagement mis à jour avec succès", + "pledgeDeleted": "Engagement supprimé avec succès", + "addPledge": "Ajouter un engagement", + "createPledge": "Créer un engagement", + "currency": "Devise", + "selectCurrency": "Sélectionnez la devise", + "updatePledge": "Engagement de mise à jour", + "deletePledge": "Supprimer l'engagement", + "amount": "Montant", + "editPledge": "Modifier l'engagement", + "deletePledgeMsg": "Etes-vous sûr de vouloir supprimer cet engagement ?", + "noPledges": "Aucun engagement trouvé" + }, + "orgPost": { + "title": "Des postes", + "searchPost": "Rechercher un article", + "posts": "Des postes", + "createPost": "Créer un message", + "postDetails": "Détails du message", + "postTitle1": "Écrivez le titre du message", + "postTitle": "Titre", + "addMedia": "Télécharger des médias", + "information": "Information", + "information1": "Écrire les informations du message", + "addPost": "Ajouter un message", + "searchTitle": "Recherche par titre", + "searchText": "Recherche par texte", + "ptitle": "Titre de l'article", + "postDes": "De quoi veux-tu parler ?", + "Title": "Titre", + "Text": "Texte", + "searchBy": "Recherché par", + "Oldest": "Le plus âgé en premier", + "Latest": "Dernier premier", + "sortPost": "Trier le message", + "tag": " Votre navigateur ne prend pas en charge la balise vidéo", + "postCreatedSuccess": "Toutes nos félicitations! ", + "pinPost": "Épingler le message", + "Next": "Page suivante", + "Previous": "Page précédente" + }, + "postNotFound": { + "post": "Poste", + "not found!": "Pas trouvé!", + "organization": "Organisation", + "post not found!": "Message introuvable !", + "organization not found!": "Organisation introuvable !" + }, + "userNotFound": { + "not found!": "Pas trouvé!", + "roles": "Les rôles", + "user not found!": "Utilisateur non trouvé!", + "member not found!": "Membre introuvable!", + "admin not found!": "Administrateur introuvable !", + "roles not found!": "Rôles introuvables !" + }, + "orgPostCard": { + "author": "Auteur", + "imageURL": "URL de l'image", + "videoURL": "URL de la vidéo", + "deletePost": "Supprimer le message", + "deletePostMsg": "Voulez-vous supprimer ce message?", + "editPost": "Modifier le message", + "postTitle": "Titre", + "postTitle1": "Modifier le titre du message", + "information1": "Modifier les informations du message", + "information": "Information", + "image": "Image", + "video": "Vidéo", + "updatePost": "Mettre à jour le message", + "postDeleted": "Message supprimé avec succès.", + "postUpdated": "Post mis à jour avec succès.", + "tag": " Votre navigateur ne prend pas en charge la balise vidéo", + "pin": "Épingler le message" + }, + "blockUnblockUser": { + "title": "Bloquer/débloquer un utilisateur", + "pageName": "Bloquer/Débloquer", + "listOfUsers": "Liste des utilisateurs qui ont spammé", + "block_unblock": "Bloquer/Débloquer", + "unblock": "Débloquer", + "block": "Bloc", + "orgName": "Entrez le nom", + "blockedSuccessfully": "Utilisateur bloqué avec succès", + "Un-BlockedSuccessfully": "Utilisateur débloqué avec succès", + "allMembers": "Tous les membres", + "blockedUsers": "Utilisateurs bloqués", + "searchByFirstName": "Recherche par prénom", + "searchByLastName": "Rechercher par nom de famille", + "noSpammerFound": "Aucun spammeur trouvé" + }, + "eventManagement": { + "title": "Gestion d'événements", + "dashboard": "Tableau de bord", + "registrants": "Inscrits", + "eventActions": "Actions d'événement", + "eventStats": "Statistiques des événements", + "to": "À" + }, + "forgotPassword": { + "title": "Talawa Mot de passe oublié", + "registeredEmail": "Email enregistré", + "getOtp": "Obtenir OTP", + "enterOtp": "Entrez OTP", + "enterNewPassword": "Entrez un nouveau mot de passe", + "cofirmNewPassword": "Confirmer le nouveau mot de passe", + "changePassword": "Changer le mot de passe", + "backToLogin": "Retour connexion", + "userOtp": "par exemple. ", + "emailNotRegistered": "L'e-mail n'est pas enregistré.", + "errorSendingMail": "Erreur lors de l'envoi du courrier.", + "passwordMismatches": "Mot de passe et Confirmer les incompatibilités de mot de passe.", + "passwordChanges": "Le mot de passe a été modifié avec succès.", + "OTPsent": "OTP est envoyé à votre adresse e-mail enregistrée." + }, + "pageNotFound": { + "404": "404", + "title": "404 introuvable", + "talawaAdmin": "Administrateur Talawa", + "talawaUser": "Utilisateur Talawa", + "notFoundMsg": "Oops! ", + "backToHome": "De retour à la maison" + }, + "orgContribution": { + "title": "Contributions de Talawa", + "filterByName": "Filtrer par nom", + "filterByTransId": "Filtrer par Trans. ", + "recentStats": "Statistiques récentes", + "contribution": "Contribution", + "orgname": "Entrez le nom", + "searchtransaction": "Entrez l'ID de la transaction" + }, + "contriStats": { + "recentContribution": "Contribution récente", + "highestContribution": "Contribution la plus élevée", + "totalContribution": "Contribution totale" + }, + "orgContriCards": { + "date": "Date", + "transactionId": "identifiant de transaction", + "amount": "Montant" + }, + "orgSettings": { + "title": "Paramètres", + "general": "Général", + "actionItemCategories": "Catégories d'éléments d'action", + "updateOrganization": "Mettre à jour l'organisation", + "seeRequest": "Voir la demande", + "noData": "Pas de données", + "otherSettings": "Autres réglages", + "changeLanguage": "Changer de langue", + "manageCustomFields": "Gérer les champs personnalisés" + }, + "deleteOrg": { + "deleteOrganization": "Supprimer l'organisation", + "deleteSampleOrganization": "Supprimer un exemple d'organisation", + "deleteMsg": "Voulez-vous supprimer cette organisation ?", + "confirmDelete": "Confirmation de la suppression", + "longDelOrgMsg": "En cliquant sur le bouton Supprimer l'organisation, l'organisation sera définitivement supprimée ainsi que ses événements, balises et toutes les données associées.", + "successfullyDeletedSampleOrganization": "Exemple d'organisation supprimé avec succès" + }, + "userUpdate": { + "appLanguageCode": "Langage par défaut", + "userType": "Type d'utilisateur" + }, + "userPasswordUpdate": { + "previousPassword": "Mot de passe précédent", + "newPassword": "nouveau mot de passe", + "confirmNewPassword": "Confirmer le nouveau mot de passe" + }, + "orgDelete": { + "deleteOrg": "Supprimer l'organisation" + }, + "membershipRequest": { + "accept": "Accepter", + "reject": "Rejeter", + "memberAdded": "c'est accepté" + }, + "orgUpdate": { + "city": "Ville", + "countryCode": "Code postal", + "line1": "Ligne 1", + "line2": "Ligne 2", + "postalCode": "Code Postal", + "dependentLocality": "Localité dépendante", + "sortingCode": "Code de tri", + "state": "État/Province", + "userRegistrationRequired": "Inscription de l'utilisateur requise", + "isVisibleInSearch": "Visible dans la recherche", + "enterNameOrganization": "Entrez le nom de l'organisation", + "successfulUpdated": "Organisation mise à jour avec succès" + }, + "addOnRegister": { + "addNew": "Ajouter un nouveau", + "addPlugin": "Ajouter un plugin", + "pluginName": "Nom du plugin", + "creatorName": "Nom du créateur", + "pluginDesc": "Description du plugin", + "pName": "Ex : Dons", + "cName": "Ex : John Doe", + "pDesc": "Ce plugin active l'interface utilisateur pour" + }, + "addOnStore": { + "title": "Ajouter sur la boutique", + "searchName": "Ex : Dons", + "enable": "Activé", + "disable": "Désactivé", + "pHeading": "Plugins", + "install": "installée", + "available": "Disponible", + "pMessage": "Le plugin n'existe pas" + }, + "addOnEntry": { + "enable": "Activé", + "install": "Installer", + "uninstall": "Désinstaller", + "uninstallMsg": "Cette fonctionnalité est désormais supprimée de votre organisation", + "installMsg": "Cette fonctionnalité est désormais activée dans votre organisation" + }, + "memberDetail": { + "title": "Détails de l'utilisateur", + "addAdmin": "Ajouter un administrateur", + "alreadyIsAdmin": "Le membre est déjà un administrateur", + "organizations": "Organisations", + "events": "Événements", + "role": "Rôle", + "createdOn": "Créé sur", + "main": "Principal", + "firstName": "Prénom", + "lastName": "Nom de famille", + "language": "Langue", + "gender": "Genre", + "birthDate": "Date de naissance", + "educationGrade": "Niveau d'éducation", + "employmentStatus": "Statut d'emploi", + "maritalStatus": "État civil", + "phone": "Téléphone", + "countryCode": "Code postal", + "state": "État", + "city": "Ville", + "personalInfoHeading": "Informations personnelles", + "contactInfoHeading": "Coordonnées", + "actionsHeading": "Actions", + "personalDetailsHeading": "Détails du profil", + "appLanguageCode": "Choisissez la langue", + "deleteUser": "Supprimer l'utilisateur", + "pluginCreationAllowed": "Création de plugin autorisée", + "created": "Créé", + "adminForOrganizations": "Administrateur pour les organisations", + "membershipRequests": "Demandes d'adhésion", + "adminForEvents": "Administrateur pour les événements", + "addedAsAdmin": "L'utilisateur est ajouté en tant qu'administrateur.", + "userType": "Type d'utilisateur" + }, + "userLogin": { + "login": "Se connecter", + "loginIntoYourAccount": "Connectez-vous à votre compte", + "invalidDetailsMessage": "Veuillez entrer un email et un mot de passe valides.", + "notAuthorised": "Désolé! ", + "invalidCredentials": "Les informations d'identification saisies sont incorrectes. " + }, + "userRegister": { + "enterFirstName": "Entrez votre prénom", + "enterLastName": "Entrez votre nom de famille", + "enterConfirmPassword": "Entrez votre mot de passe pour confirmer", + "alreadyhaveAnAccount": "Vous avez déjà un compte?", + "login": "Se connecter", + "afterRegister": "Enregistré avec succès. ", + "passwordNotMatch": "Le mot de passe ne correspond pas. ", + "invalidDetailsMessage": "Veuillez saisir des informations valides." + }, + "userNavbar": { + "talawa": "Talawa", + "home": "Maison", + "people": "Personnes", + "events": "Événements", + "chat": "Chat", + "donate": "Faire un don", + "language": "Langue" + }, + "userOrganizations": { + "allOrganizations": "Toutes les organisations", + "joinedOrganizations": "Organisations rejointes", + "createdOrganizations": "Organisations créées", + "selectOrganization": "Sélectionnez une organisation", + "searchUsers": "Rechercher des utilisateurs", + "nothingToShow": "Rien à montrer ici.", + "organizations": "Organisations" + }, + "userSidebarOrg": { + "yourOrganizations": "Vos organisations", + "noOrganizations": "Vous n'avez encore rejoint aucune organisation.", + "viewAll": "Voir tout", + "talawaUserPortal": "Portail utilisateur Talawa", + "my organizations": "Mes organisations", + "communityProfile": "Profil de la communauté" + }, + "organizationSidebar": { + "viewAll": "Voir tout", + "events": "Événements", + "noEvents": "Aucun événement à afficher", + "noMembers": "Aucun membre à afficher" + }, + "postCard": { + "likes": "Aime", + "comments": "commentaires" + }, + "home": { + "posts": "Des postes", + "post": "Poste", + "title": "Titre", + "textArea": "Quelque chose vous préoccupe ?", + "feed": "Alimentation", + "loading": "Chargement", + "pinnedPosts": "Messages épinglés", + "yourFeed": "Votre flux", + "nothingToShowHere": "Rien à montrer ici", + "somethingOnYourMind": "Quelque chose vous préoccupe ?", + "addPost": "Ajouter un message", + "startPost": "Démarrer un message", + "media": "Médias", + "event": "Événement", + "article": "Article" + }, + "settings": { + "profileSettings": "Paramètres de profil", + "gender": "Genre", + "phoneNumber": "Numéro de téléphone", + "chooseFile": "Choisir le fichier", + "birthDate": "Date de naissance", + "grade": "Niveau d'éducation", + "empStatus": "Statut d'emploi", + "maritalStatus": "État civil", + "state": "Ville/État", + "country": "Pays", + "resetChanges": "Réinitialiser les modifications", + "profileDetails": "Détails du profil", + "deleteUserMessage": "En cliquant sur le bouton Supprimer l'utilisateur, votre utilisateur sera définitivement supprimé ainsi que ses événements, balises et toutes les données associées.", + "copyLink": "Copier le lien du profil", + "deleteUser": "Supprimer l'utilisateur", + "otherSettings": "Autres réglages", + "changeLanguage": "Changer de langue", + "sgender": "Sélectionnez le sexe", + "gradePlaceholder": "Entrez la note", + "sEmpStatus": "Sélectionnez le statut d'emploi", + "female": "Femelle", + "male": "Mâle", + "employed": "Employé", + "other": "Autre", + "sMaritalStatus": "Sélectionnez l'état civil", + "unemployed": "Sans emploi", + "married": "Marié", + "single": "Célibataire", + "widowed": "Veuf", + "divorced": "Divorcé", + "engaged": "Engagé", + "seperated": "Séparé", + "grade1": "1re année", + "grade2": "2e année", + "grade3": "3e année", + "grade4": "Niveau 4", + "grade5": "Niveau 5", + "grade6": "6ème année", + "grade7": "7e année", + "grade8": "8e année", + "grade9": "9e année", + "grade10": "10 e année", + "grade11": "11e année", + "grade12": "12 e année", + "graduate": "Diplômé", + "kg": "KG", + "preKg": "Pré-KG", + "noGrade": "Aucune note", + "fullTime": "À temps plein", + "partTime": "À temps partiel", + "selectCountry": "Choisissez un pays", + "enterState": "Entrez la ville ou l'état" + }, + "donate": { + "donations": "Des dons", + "searchDonations": "Rechercher des dons", + "donateForThe": "Faites un don pour le", + "amount": "Montant", + "yourPreviousDonations": "Vos dons précédents", + "donate": "Faire un don", + "nothingToShow": "Rien à montrer ici.", + "success": "Don réussi" + }, + "userEvents": { + "nothingToShow": "Rien à montrer ici.", + "createEvent": "Créer un évènement", + "recurring": "Événement récurrent", + "startTime": "Heure de début", + "endTime": "Heure de fin", + "listView": "Vue en liste", + "calendarView": "Vue du calendrier", + "allDay": "Toute la journée", + "eventCreated": "Événement créé et publié avec succès.", + "eventDetails": "Détails de l'évènement", + "eventTitle": "Titre", + "enterTitle": "Entrez le titre", + "enterDescription": "Entrez la description", + "enterLocation": "Entrez l'emplacement", + "publicEvent": "est public", + "registerable": "Est enregistrable", + "monthlyCalendarView": "Calendrier mensuel", + "yearlyCalendarView": "Calendrier annuel" + }, + "userEventCard": { + "starts": "Départs", + "ends": "Prend fin", + "creator": "Créateur", + "alreadyRegistered": "Déjà enregistré" + }, + "advertisement": { + "title": "Annonces", + "activeAds": "Campagnes actives", + "archievedAds": "Campagnes terminées", + "pMessage": "Annonces non présentes pour cette campagne.", + "validLink": "Le lien est valide", + "invalidLink": "Le lien n'est pas valide", + "Rname": "Entrez le nom de l'annonce", + "Rtype": "Sélectionnez le type de publicité", + "Rmedia": "Fournir du contenu multimédia à afficher", + "RstartDate": "Sélectionnez la date de début", + "RendDate": "Sélectionnez la date de fin", + "RClose": "Ferme la fenêtre", + "addNew": "Créer une nouvelle annonce", + "EXname": "Ex. ", + "EXlink": "Ex. ", + "createAdvertisement": "Créer une publicité", + "deleteAdvertisement": "Supprimer la publicité", + "deleteAdvertisementMsg": "Voulez-vous supprimer cette publicité ?", + "view": "Voir", + "editAdvertisement": "Modifier l'annonce" + }, + "userChat": { + "chat": "Chat", + "contacts": "Contacts" + }, + "userChatRoom": { + "selectContact": "Sélectionnez un contact pour démarrer la conversation", + "sendMessage": "Envoyer le message" + }, + "orgProfileField": { + "loading": "Chargement...", + "noCustomField": "Aucun champ personnalisé disponible", + "customFieldName": "Nom de domaine", + "enterCustomFieldName": "Entrez le nom du champ", + "customFieldType": "Type de champ", + "Remove Custom Field": "Supprimer le champ personnalisé", + "fieldSuccessMessage": "Champ ajouté avec succès", + "fieldRemovalSuccess": "Champ supprimé avec succès" + }, + "orgActionItemCategories": { + "enableButton": "Activer", + "disableButton": "Désactiver", + "updateActionItemCategory": "Mise à jour", + "actionItemCategoryName": "Nom", + "actionItemCategoryDetails": "Détails de la catégorie d'élément d'action", + "enterName": "Entrez le nom", + "successfulCreation": "Catégorie d'élément d'action créée avec succès", + "successfulUpdation": "Catégorie d'élément d'action mise à jour avec succès", + "sameNameConflict": "Veuillez changer le nom pour effectuer une mise à jour", + "categoryEnabled": "Catégorie d'élément d'action activée", + "categoryDisabled": "Catégorie d'élément d'action désactivée" + }, + "organizationVenues": { + "title": "Lieux", + "addVenue": "Ajouter un lieu", + "venueDetails": "Détails du lieu", + "venueName": "Nom du lieu", + "enterVenueName": "Entrez le nom du lieu", + "enterVenueDesc": "Entrez la description du lieu", + "capacity": "Capacité", + "enterVenueCapacity": "Entrez la capacité du site", + "image": "Image du lieu", + "uploadVenueImage": "Télécharger l'image du lieu", + "createVenue": "Créer un lieu", + "venueAdded": "Lieu ajouté avec succès", + "editVenue": "Mettre à jour le lieu", + "venueUpdated": "Les détails du lieu ont été mis à jour avec succès", + "sort": "Trier", + "highestCapacity": "Capacité la plus élevée", + "lowestCapacity": "Capacité la plus basse", + "noVenues": "Aucun lieu trouvé !", + "view": "Voir", + "venueTitleError": "Le titre du lieu ne peut pas être vide !", + "venueCapacityError": "La capacité doit être un nombre positif !", + "searchBy": "Recherché par" + }, + "addMember": { + "title": "Ajouter un membre", + "addMembers": "Ajouter des membres", + "existingUser": "Utilisateur existant", + "newUser": "Nouvel utilisateur", + "searchFullName": "Rechercher par nom complet", + "enterFirstName": "Entrez votre prénom", + "enterLastName": "Entrer le nom de famille", + "enterConfirmPassword": "Entrez Confirmer le mot de passe", + "organization": "Organisation", + "invalidDetailsMessage": "Veuillez fournir tous les détails requis.", + "passwordNotMatch": "Les mots de passe ne correspondent pas.", + "addMember": "Ajouter un membre" + }, + "eventActionItems": { + "title": "Éléments d'action", + "createActionItem": "Créer des éléments d'action", + "actionItemCategory": "Catégorie d'élément d'action", + "selectActionItemCategory": "Sélectionnez une catégorie d'élément d'action", + "selectAssignee": "Sélectionnez un responsable", + "preCompletionNotes": "Notes préalables à l'achèvement", + "postCompletionNotes": "Notes post-achèvement", + "actionItemDetails": "Détails de l'action", + "dueDate": "Date d'échéance", + "completionDate": "Date d'achèvement", + "editActionItem": "Modifier l'élément d'action", + "deleteActionItem": "Supprimer l'élément d'action", + "deleteActionItemMsg": "Voulez-vous supprimer cette action ?", + "successfulDeletion": "Élément d'action supprimé avec succès", + "successfulCreation": "Élément d'action créé avec succès", + "successfulUpdation": "Élément d'action mis à jour avec succès", + "notes": "Remarques", + "save": "Sauvegarder" + } +} diff --git a/public/locales/hi.json b/public/locales/hi.json deleted file mode 100644 index a029df8bd7..0000000000 --- a/public/locales/hi.json +++ /dev/null @@ -1,1140 +0,0 @@ -{ - "loginPage": { - "title": "तलवा व्यवस्थापक", - "fromPalisadoes": "पलिसाडो के स्वयंसेवकों द्वारा एक खुला स्रोत अनुप्रयोग", - "talawa_portal": "तलावा प्रशासन पोर्टल", - "login": "लॉग इन करें", - "userLogin": "उपयोगकर्ता लॉगिन", - "register": "पंजीकरण करवाना", - "firstName": "पहला नाम", - "lastName": "उपनाम", - "email": "ईमेल", - "password": "पासवर्ड", - "atleast_8_char_long": "कम से कम 8 कैरेक्टर लंबा", - "atleast_6_char_long": "कम से कम 6 अक्षर लंबा", - "firstName_invalid": "प्रथम नाम में केवल छोटे और बड़े अक्षर होने चाहिए", - "lastName_invalid": "अंतिम नाम में केवल छोटे और बड़े अक्षर होने चाहिए", - "password_invalid": "पासवर्ड में कम से कम एक लोअरकेस अक्षर, एक अपरकेस अक्षर, एक संख्यात्मक मान और एक विशेष अक्षर होना चाहिए", - "email_invalid": "ईमेल में कम से कम 8 अक्षर होने चाहिए", - "Password_and_Confirm_password_mismatches.": "पासवर्ड और पुष्टि पासवर्ड बेमेल।", - "confirmPassword": "पासवर्ड की पुष्टि कीजिये", - "forgotPassword": "पासवर्ड भूल गए ?", - "enterEmail": "ईमेल दर्ज करें", - "enterPassword": "पास वर्ड दर्ज करें", - "doNotOwnAnAccount": "क्या आपके पास खाता नहीं है?", - "talawaApiUnavailable": "तलावा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रही है? अपनी नेटवर्क कनेक्टिविटी की भी जाँच करें।", - "captchaError": "कैप्चा त्रुटि!", - "Please_check_the_captcha": "कृपया, कैप्चा जांचें।", - "Something_went_wrong": "कुछ गलत हुआ, कृपया कुछ समय बाद प्रयास करें।", - "passwordMismatches": "पासवर्ड और पुष्टि पासवर्ड मेल नहीं खाते।", - "fillCorrectly": "सभी विवरण सही ढंग से भरें।", - "notAuthorised": "क्षमा करें! आप अधिकृत नहीं हैं!", - "notFound": "उपयोगकर्ता नहीं मिला!", - "successfullyRegistered": "सफलतापूर्वक पंजीकृत। कृपया स्वीकृत होने तक प्रतीक्षा करें।", - "OR": "या", - "admin": "व्यवस्थापक", - "user": "उपयोगकर्ता", - "lowercase_check": "कम से कम एक छोटा अक्षर", - "uppercase_check": "कम से कम एक बड़ा अक्षर", - "numeric_value_check": "कम से कम एक संख्यात्मक मान", - "special_char_check": "कम से कम एक विशेष पात्र", - "loading": "लोड हो रहा है...", - "selectOrg": "कोई संगठन चुनें", - "afterRegister": "सफलतापूर्वक पंजीकृत हो गया। कृपया व्यवस्थापक की मंजूरी का इंतजार करें।" - }, - "userLoginPage": { - "title": "तलवा व्यवस्थापक", - "fromPalisadoes": "पलिसाडो के स्वयंसेवकों द्वारा एक खुला स्रोत अनुप्रयोग", - "talawa_portal": "तलावा प्रशासन पोर्टल", - "login": "लॉग इन करें", - "register": "पंजीकरण करवाना", - "firstName": "पहला नाम", - "lastName": "उपनाम", - "email": "ईमेल", - "password": "पासवर्ड", - "atleast_8_char_long": "कम से कम 8 कैरेक्टर लंबा", - "Password_and_Confirm_password_mismatches.": "पासवर्ड और पुष्टि पासवर्ड बेमेल।", - "confirmPassword": "पासवर्ड की पुष्टि कीजिये", - "forgotPassword": "पासवर्ड भूल गए ?", - "enterEmail": "ईमेल दर्ज करें", - "enterPassword": "पास वर्ड दर्ज करें", - "doNotOwnAnAccount": "क्या आपके पास खाता नहीं है?", - "talawaApiUnavailable": "तलावा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रही है? अपनी नेटवर्क कनेक्टिविटी की भी जाँच करें।", - "captchaError": "कैप्चा त्रुटि!", - "Please_check_the_captcha": "कृपया, कैप्चा जांचें।", - "Something_went_wrong": "कुछ गलत हुआ, कृपया कुछ समय बाद प्रयास करें।", - "passwordMismatches": "पासवर्ड और पुष्टि पासवर्ड मेल नहीं खाते।", - "fillCorrectly": "सभी विवरण सही ढंग से भरें।", - "notAuthorised": "क्षमा करें! आप अधिकृत नहीं हैं!", - "notFound": "उपयोगकर्ता नहीं मिला!", - "successfullyRegistered": "सफलतापूर्वक पंजीकृत। कृपया स्वीकृत होने तक प्रतीक्षा करें।", - "afterRegister": "पंजीकरण सफलतापूर्वक हो गया है। कृपया आपके अनुरोध को स्वीकार करने के लिए व्यवस्थापक की प्रतीक्षा करें।", - "userLogin": "उपयोगकर्ता लॉगिन", - "OR": "या", - "loading": "लोड हो रहा है...", - "selectOrg": "कोई संगठन चुनें" - }, - "latestEvents": { - "eventCardTitle": "आगामी घटनाएँ", - "eventCardSeeAll": "सभी देखें", - "noEvents": "कोई आगामी घटनाएँ नहीं" - }, - "latestPosts": { - "latestPostsTitle": "नवीनतम पोस्ट", - "seeAllLink": "सभी देखें", - "noPostsCreated": "कोई पोस्ट नहीं बनाई गई" - }, - "listNavbar": { - "talawa_portal": "तलावा प्रशासन पोर्टल", - "roles": "भूमिकाएँ", - "requests": "अनुरोध", - "logout": "लॉग आउट" - }, - "leftDrawer": { - "talawaAdminPortal": "तलावा व्यवस्थापक पोर्टल", - "menu": "मेन्यू", - "my organizations": "मेरे संगठन", - "users": "उपयोगकर्ता", - "requests": "अनुरोध", - "communityProfile": "सामुदायिक प्रोफ़ाइल", - "logout": "लॉग आउट" - }, - "leftDrawerOrg": { - "talawaAdminPortal": "तलावा व्यवस्थापक पोर्टल", - "menu": "मेन्यू", - "talawa_portal": "तलावा प्रशासन पोर्टल", - "Dashboard": "डैशबोर्ड", - "People": "लोग", - "Events": "आयोजन", - "Contributions": "योगदान", - "Posts": "पोस्ट", - "Block/Unblock": "ब्लॉक/अनब्लॉक करें", - "Plugins": "प्लगइन्स", - "Plugin Store": "प्लगइन स्टोर", - "allOrganizations": "सभी संगठन", - "yourOrganization": "आपका संगठन", - "notification": "अधिसूचना", - "settings": "समायोजन", - "language": "भाषा", - "logout": "लॉग आउट", - "notifications": "सूचनाएं", - "spamsThe": "स्पैम द", - "group": "समूह", - "noNotifications": "कोई सूचनाएं नहीं", - "close": "बंद करना" - }, - "orgList": { - "title": "तलवा संगठन", - "you": "आप", - "name": "नाम", - "designation": "पद", - "email": "ईमेल", - "searchByName": "नाम से खोजें", - "my organizations": "मेरे संगठन", - "createOrganization": "संगठन बनाएं", - "createSampleOrganization": " सैंपल संगठन बनाएं", - "description": "विवरण", - "location": "स्थान", - "address": "पता", - "city": "शहर", - "countryCode": "देश कोड", - "line1": "लाइन 1", - "line2": "लाइन 2", - "postalCode": "पोस्टल कोड", - "dependentLocality": "आश्रित स्थान", - "sortingCode": "क्रमबद्ध कोड", - "state": "राज्य / प्रांत", - "userRegistrationRequired": "उपयोगकर्ता पंजीकरण आवश्यक", - "visibleInSearch": "खोज में दृश्यमान", - "displayImage": "प्रदर्शन छवि", - "enterName": "नाम दर्ज करें", - "sort": "छांटें", - "Earliest": "सबसे पुराना", - "Latest": "सबसे नवीनतम", - "filter": "फ़िल्टर", - "cancel": "रद्द करना", - "endOfResults": "परिणामों का अंत", - "noOrgErrorTitle": "संगठन नहीं मिला", - "sampleOrgDuplicate": "केवल एक नमूना संगठन को अनुमति दी गई", - "noOrgErrorDescription": "कृपया डैशबोर्ड के माध्यम से एक संगठन बनाएं", - "noResultsFoundFor": "के लिए कोई परिणाम नहीं मिला ", - "OR": "या", - "sampleOrgSuccess": "सैंपल संगठन सफलतापूर्वक बनाया गया" - }, - "orgListCard": { - "admins": "व्यवस्थापक", - "members": "सदस्य", - "manage": "प्रबंधित करना", - "sampleOrganization": "सैंपल संगठन" - }, - "paginationList": { - "rowsPerPage": "प्रति पृष्ठ पंक्तियाँ", - "all": "सभी" - }, - "requests": { - "title": "अनुरोध", - "sl_no": "क्रमांक", - "name": "नाम", - "email": "ईमेल", - "accept": "स्वीकार करें", - "reject": "अस्वीकार करें", - "searchRequests": "अनुरोध खोजें", - "endOfResults": "परिणामों का समाप्ति", - "noOrgError": "संगठन नहीं मिला, कृपया डैशबोर्ड के माध्यम से एक संगठन बनाएं", - "noResultsFoundFor": "के लिए कोई परिणाम नहीं मिला ", - "noRequestsFound": "कोई अनुरोध नहीं मिला", - "acceptedSuccessfully": "अनुरोध सफलतापूर्वक स्वीकार किया गया", - "rejectedSuccessfully": "अनुरोध सफलतापूर्वक अस्वीकार किया गया", - "noOrgErrorTitle": "संगठन नहीं मिला", - "noOrgErrorDescription": "कृपया डैशबोर्ड के माध्यम से एक संगठन बनाएं" - }, - "users": { - "title": "तलावा भूमिकाएं", - "searchByName": "नाम से खोजें", - "users": "उपयोगकर्ता", - "name": "नाम", - "email": "ईमेल", - "joined_organizations": "संगठनों में शामिल हुए", - "blocked_organizations": "अवरोधित संगठन", - "endOfResults": "परिणामों का अंत", - "orgJoinedBy": "द्वारा शामिल हुए संगठन", - "orgThatBlocked": "जिन संगठनों ने अवरोधित किया", - "hasNotJoinedAnyOrg": "किसी भी संगठन में शामिल नहीं है", - "isNotBlockedByAnyOrg": "किसी भी संगठन द्वारा अवरोधित नहीं है", - "searchByOrgName": "संगठन के नाम से खोजें", - "view": "देखें", - "admin": "व्यवस्थापक", - "superAdmin": "सुपरएडमिन", - "user": "उपयोगकर्ता", - "enterName": "नाम दर्ज करें", - "loadingUsers": "उपयोगकर्ता लोड हो रहा है ...", - "noUserFound": "कोई उपयोगकर्ता नहीं मिला।", - "sort": "छांटें", - "Oldest": "सबसे पुराना पहले", - "Newest": "सबसे नवीनतम पहले", - "filter": "फ़िल्टर", - "roleUpdated": "भूमिका अपडेट की गई।", - "noResultsFoundFor": "के लिए कोई परिणाम नहीं मिला ", - "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।", - "cancel": "रद्द करें", - "admins": "व्यवस्थापक", - "members": "सदस्य", - "joinNow": "अब शामिल हों", - "visit": "दर्शन", - "withdraw": "अनुरोध वापस लें", - "orgJoined": "संगठन सफलतापूर्वक जुड़ा गया", - "MembershipRequestSent": "सदस्यता अनुरोध सफलतापूर्वक भेजा गया", - "AlreadyJoined": "आप इस संगठन के पहले से ही सदस्य हैं।", - "errorOccured": "कुछ गड़बड़ हो गई है। कृपया बाद में पुन: प्रयास करें।" - }, - "communityProfile": { - "title": "सामुदायिक प्रोफ़ाइल", - "editProfile": "प्रोफ़ाइल संपादित करें", - "communityProfileInfo": "ये विवरण आपके और आपके समुदाय के सदस्यों के लिए लॉगिन/साइनअप स्क्रीन पर दिखाई देंगे", - "communityName": "समुदाय का नाम", - "wesiteLink": "वेबसाइट की लिंक", - "logo": "प्रतीक चिन्ह", - "social": "सोशल मीडिया लिंक", - "url": "यू आर एल दर्ज करो", - "profileChangedMsg": "प्रोफ़ाइल विवरण सफलतापूर्वक अपडेट किया गया।", - "resetData": "प्रोफ़ाइल विवरण सफलतापूर्वक रीसेट किया गया।" - }, - "dashboard": { - "title": "डैशबोर्ड", - "location": "स्थान", - "about": "के बारे में", - "deleteThisOrganization": "इस संगठन को हटाएं", - "statistics": "सांख्यिकी", - "members": "सदस्य", - "admins": "व्यवस्थापक", - "posts": "पोस्ट", - "events": "आयोजन", - "blockedUsers": "रोके गए उपयोगकर्ता", - "requests": "अनुरोध", - "viewAll": "सभी देखें", - "upcomingEvents": "आगामी घटनाएँ", - "noUpcomingEvents": "कोई आगामी घटनाएँ नहीं", - "latestPosts": "नवीनतम पोस्ट", - "noPostsPresent": "कोई पोस्ट नहीं है", - "membershipRequests": "सदस्यता अनुरोध", - "noMembershipRequests": "कोई सदस्यता अनुरोध नहीं", - "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।" - }, - "organizationPeople": { - "title": "तलावा सदस्य", - "filterByName": "नाम से फ़िल्टर करें", - "filterByLocation": "स्थान के अनुसार फ़िल्टर करें", - "filterByEvent": "इवेंट द्वारा फ़िल्टर करें", - "members": "सदस्य", - "admins": "व्यवस्थापक", - "users": "उपयोगकर्ता", - "searchName": "नाम दर्ज करें", - "searchevent": "घटना दर्ज करें", - "searchFirstName": "प्रथम नाम दर्ज करें", - "searchLastName": "अंतिम नाम दर्ज करो", - "people": "लोग", - "sort": "भूमिका के आधार पर खोजें", - "actions": "क्रियाएँ", - "existingUser": "मौजूदा उपयोगकर्ता", - "newUser": "नए उपयोगकर्ता", - "firstName": "पहला नाम", - "enterFirstName": "अपना पहला नाम दर्ज करें", - "lastName": "अंतिम नाम", - "enterLastName": "अपना अंतिम नाम दर्ज करें", - "emailAddress": "ईमेल एड्रेस", - "enterEmail": "अपना ईमेल पता दर्ज करें", - "password": "पासवर्ड", - "enterPassword": "अपना पासवर्ड डालें", - "confirmPassword": "पासवर्ड की पुष्टि कीजिये", - "enterConfirmPassword": "पुष्टि करने के लिए अपना पासवर्ड दर्ज करें", - "organization": "संगठन", - "create": "बनाएं", - "cancel": "रद्द करना", - "invalidDetailsMessage": "कृपया मान्य विवरण दर्ज करें।" - }, - "userListCard": { - "joined": "में शामिल हो गए", - "addAdmin": "व्यवस्थापक जोड़ें", - "addedAsAdmin": "उपयोगकर्ता को व्यवस्थापक के रूप में जोड़ा गया है।", - "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।" - }, - "orgAdminListCard": { - "joined": "में शामिल हो गए", - "remove": "हटाना", - "removeAdmin": "व्यवस्थापक हटाएं", - "removeAdminMsg": "क्या आप इस व्यवस्थापक को हटाना चाहते हैं?", - "no": "नहीं", - "yes": "हाँ", - "adminRemoved": "व्यवस्थापक को हटा दिया गया है।", - "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।" - }, - "orgPeopleListCard": { - "joined": "में शामिल हो गए", - "remove": "हटाना", - "removeMember": "सदस्य निकालें", - "removeMemberMsg": "क्या आप इस सदस्य को हटाना चाहते हैं?", - "no": "नहीं", - "yes": "हाँ", - "memberRemoved": "सदस्य को हटा दिया गया है", - "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।" - }, - "organizationEvents": { - "title": "आयोजन", - "filterByTitle": "शीर्षक द्वारा फ़िल्टर करें", - "filterByLocation": "स्थान के अनुसार फ़िल्टर करें", - "filterByDescription": "विवरण द्वारा फ़िल्टर करें", - "events": "आयोजन", - "addEvent": "कार्यक्रम जोड़ें", - "eventDetails": "घटना की जानकारी", - "eventTitle": "शीर्षक", - "description": "विवरण", - "location": "स्थान", - "startDate": "आरंभ करने की तिथि", - "endDate": "अंतिम तिथि", - "startTime": "समय शुरू", - "endTime": "अंत समय", - "allDay": "पूरे दिन", - "recurringEvent": "पुनरावर्ती ईवेंट", - "isPublic": "सार्वजनिक है", - "isRegistrable": "पंजीकरण योग्य है", - "createEvent": "कार्यक्रम बनाएँ", - "enterFilter": "फ़िल्टर दर्ज करें", - "enterTitle": "शीर्षक दर्ज करें", - "enterDescrip": "विवरण दर्ज करें", - "eventLocation": "स्थान दर्ज करें", - "eventCreated": "बधाई हो! इवेंट बनाया गया है।", - "searchEventName": "ईवेंट नाम खोजें", - "eventType": "ईवेंट प्रकार", - "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।", - "customRecurrence": "कस्टम पुनरावृत्ति", - "repeatsEvery": "दोहराता है हर", - "repeatsOn": "को दोहराएगा", - "ends": "समाप्त होता", - "never": "कभी नहीं", - "on": "पर", - "after": "के बाद", - "occurences": "'घटित होता है", - "done": "समाज-सम्मत" - }, - "organizationActionItems": { - "actionItemCategory": "कार्य आइटम श्रेणी", - "actionItemActive": "क्रिया आइटम सक्रिय", - "actionItemCompleted": "क्रिया आइटम पूर्ण हुआ", - "actionItemDetails": "कार्य आइटम विवरण", - "actionItemStatus": "कार्रवाई आइटम स्थिति", - "assignee": "सौंपने वाला", - "assigner": "निर्धारक", - "assignmentDate": "सौंपने की तारीख", - "active": "सक्रिय", - "clearFilters": "फ़िल्टर हटाएं", - "close": "बंद करें", - "completed": "पूरा हुआ", - "completionDate": "समापन तिथि", - "createActionItem": "बनाएं", - "deleteActionItem": "कार्य आइटम हटाएं", - "deleteActionItemMsg": "क्या आप इस कार्य आइटम को हटाना चाहते हैं?", - "details": "विवरण", - "dueDate": "नियत तारीख", - "earliest": "सबसे पहले", - "editActionItem": "कार्य आइटम संपादित करें", - "eventActionItems": "इवेंट एक्शन आइटम", - "isCompleted": "पूरा हुआ", - "latest": "नवीनतम", - "makeActive": "सक्रिय करें", - "markCompletion": "मार्क पूर्णता", - "no": "नहीं", - "noActionItems": "कोई कार्य आइटम नहीं", - "options": "विकल्प", - "preCompletionNotes": "समापन से पहले के नोट्स", - "postCompletionNotes": "समापन के बाद के नोट्स", - "searchByName": "नाम से खोजें", - "selectActionItemCategory": "कार्य आइटम श्रेणी का चयन करें", - "selectAssignee": "सौंपने वाला चुनें", - "status": "स्थिति", - "successfulCreation": "कार्य आइटम सफलतापूर्वक बनाया गया", - "successfulUpdation": "कार्य आइटम सफलतापूर्वक अपडेट किया गया", - "successfulDeletion": "कार्य आइटम सफलतापूर्वक हटाया गया", - "title": "कार्य आइटम", - "yes": "हाँ" - }, - "eventListCard": { - "location": "आयोजन स्थान", - "deleteEvent": "घटना हटाएं", - "deleteEventMsg": "क्या आप इस इवेंट को हटाना चाहते हैं?", - "no": "नहीं", - "yes": "हाँ", - "editEvent": "घटना संपादित करें", - "eventTitle": "शीर्षक", - "description": "विवरण", - "startDate": "आरंभ करने की तिथि", - "endDate": "अंतिम तिथि", - "registerEvent": "रजिस्टर करें", - "alreadyRegistered": "पहले से ही पंजीकृत", - "startTime": "समय शुरू", - "endTime": "अंत समय", - "allDay": "पूरे दिन", - "recurringEvent": "पुनरावर्ती ईवेंट", - "isPublic": "सार्वजनिक है", - "isRegistrable": "पंजीकरण योग्य है", - "close": "बंद करना", - "updatePost": "अपडेट पोस्ट", - "eventDetails": "घटना की जानकारी", - "eventDeleted": "इवेंट सफलतापूर्वक मिटाया गया.", - "eventUpdated": "इवेंट सफलतापूर्वक अपडेट किया गया।", - "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।", - "thisInstance": "यह अवसर", - "thisAndFollowingInstances": "यह और निम्नलिखित अवसर", - "allInstances": "सभी अवसर", - "customRecurrence": "कस्टम पुनरावृत्ति", - "repeatsEvery": "दोहराता है हर", - "repeatsOn": "को दोहराएगा", - "ends": "समाप्त होता", - "never": "कभी नहीं", - "on": "पर", - "after": "के बाद", - "occurences": "'घटित होता है", - "done": "समाज-सम्मत" - }, - "funds": { - "title": "फंड्स", - "createFund": "फंड बनाएँ", - "fundName": "फंड का नाम", - "fundId": "फंड आईडी", - "fundOptions": "फंड विकल्प", - "noFunds": "कोई फंड नहीं", - "fundDetails": "फंड विवरण", - "taxDeductible": "कर कटौती", - "enterfundName": " फंड का नाम दर्ज करें", - "enterfundId": " फंड आईडी दर्ज करें", - "default": "डिफ़ॉल्ट", - "archived": "संग्रहीत", - "nonArchive": "गैर संग्रहीत", - "fundCreate": "फंड बनाएँ", - "fundUpdate": "फंड अपडेट करें", - "fundDelete": "फंड हटाएं", - "no": "नहीं", - "yes": "हाँ", - "manageFund": "कोष प्रबंधित करें", - "searchFullName": "नाम से खोजें", - "filter": "फ़िल्टर", - "noFundsFound": "कोई धनराशि नहीं मिली", - "createdBy": "द्वारा बनाया गया", - "createdOn": "बनाया गया", - "status": "स्थिति", - "archiveFund": "फंड संग्रहीत करें", - "archiveFundMsg": "क्या आप इस फंड को संग्रहीत करना चाहते हैं?", - "fundCreated": "फंड सफलतापूर्वक बनाया गया", - "fundUpdated": "फंड सफलतापूर्वक अपडेट किया गया", - "fundDeleted": "फंड सफलतापूर्वक हटाया गया", - "fundArchived": "फंड सफलतापूर्वक संग्रहीत किया गया", - "fundUnarchived": "फंड सफलतापूर्वक गैर संग्रहीत किया गया", - "deleteFundMsg": "क्या आप इस फंड को हटाना चाहते हैं?" - }, - - "fundCampaign": { - "title": "तलवा फंड अभियान", - "campaignName": "अभियान का नाम", - "startDate": "प्रारंभ तिथि", - "endDate": "समाप्ति तिथि", - "campaignOptions": "अभियान विकल्प", - "fundingGoal": "वित्तीय लक्ष्य", - "addCampaign": "अभियान जोड़ें", - "createdCampaign": "अभियान सफलतापूर्वक बनाया गया", - "updatedCampaign": "अभियान सफलतापूर्वक अपडेट किया गया", - "deletedCampaign": "अभियान सफलतापूर्वक हटाया गया", - "deleteCampaignMsg": "क्या आप इस अभियान को हटाना चाहते हैं?", - "noCampaigns": "कोई अभियान नहीं", - "createCampaign": "अभियान बनाएँ", - "updateCampaign": "अभियान अपडेट करें", - "manageCampaign": "अभियान प्रबंधित करें", - "deleteCampaign": "अभियान हटाएं", - "no": "नहीं", - "yes": "हाँ", - "currency": "मुद्रा", - "selectCurrency": "मुद्रा चुनें", - "filter": "फ़िल्टर", - "searchFullName": "नाम से खोजें" - }, - "pledges": { - "title": "फंडकैम्पेन प्रतिज्ञाएं", - "volunteers": "स्वयंसेवक", - "startDate": "प्रारंभ तिथि", - "endDate": "समाप्ति तिथि", - "pledgeAmount": "प्रतिज्ञा राशि", - "pledgeOptions": "विकल्प", - "pledgeCreated": "प्रतिज्ञा सफलतापूर्वक बनाई गई", - "pledgeUpdated": "प्रतिज्ञा सफलतापूर्वक अपडेट की गई", - "pledgeDeleted": "प्रतिज्ञा सफलतापूर्वक हटा दी गई", - "addPledge": "प्रतिज्ञा जोड़ें", - "createPledge": "प्रतिज्ञा बनाएं", - "currency": "मुद्रा", - "selectCurrency": "मुद्रा चुनें", - "updatePledge": "प्रतिज्ञा अपडेट करें", - "deletePledge": "प्रतिज्ञा हटाएं", - "amount": "राशि", - "editPledge": "प्रतिज्ञा संपादित करें", - "deletePledgeMsg": "क्या आप वाकई इस प्रतिज्ञा को हटाना चाहते हैं?", - "no": "नहीं", - "yes": "हाँ", - "noPledges": "कोई प्रतिज्ञा नहीं मिली" - }, - - "orgPost": { - "title": "तलवा पोस्ट्स", - "searchPost": "पोस्ट खोजें", - "posts": "पोस्ट्स", - "createPost": "पोस्ट बनाएँ", - "postDetails": "पोस्ट विवरण", - "postTitle1": "पोस्ट का शीर्षक लिखें", - "postTitle": "शीर्षक", - "addMedia": "फ़ोटो या वीडियो अपलोड करें", - "information": "जानकारी", - "information1": "पोस्ट की जानकारी लिखें", - "addPost": "पोस्ट जोड़ें", - "searchTitle": "शीर्षक से खोजें", - "searchText": "टेक्स्ट से खोजें", - "ptitle": "पोस्ट का शीर्षक", - "postDes": "आप किस बारे में बात करना चाहते हैं?", - "Title": "शीर्षक", - "Text": "टेक्स्ट", - "cancel": "रद्द करें", - "searchBy": "इसके द्वारा खोजें", - "Oldest": "सबसे पुराना पहले", - "Latest": "सबसे नवीनतम पहले", - "sortPost": "पोस्ट को क्रमित करें", - "tag": "आपका ब्राउज़र वीडियो टैग का समर्थन नहीं करता", - "postCreatedSuccess": "बधाई हो! आपने कुछ पोस्ट किया है।", - "pinPost": "पोस्ट को पिन करें", - "Next": "अगला पृष्ठ", - "Previous": "पिछला पृष्ठ" - }, - "postNotFound": { - "post": "पोस्ट", - "not found!": "नहीं मिला!", - "organization": "संगठन", - "post not found!": "पोस्ट नहीं मिला!", - "organization not found!": "संगठन नहीं मिला!" - }, - "userNotFound": { - "user": "उपयोगकर्ता", - "not found!": "नहीं मिला!", - "roles": "भूमिका", - "user not found!": "उपयोगकर्ता नहीं मिले!", - "member not found!": "सदस्य अनुपस्थित!", - "admin not found!": "व्यवस्थापक नहीं मिला!", - "roles not found!": "भूमिकाएँ नहीं मिलीं!" - }, - "orgPostCard": { - "author": "लेखक", - "imageURL": "छवि URL", - "videoURL": "वीडियो URL", - "edit": "पोस्ट संपादित करें", - "deletePost": "पोस्ट हटाएं", - "deletePostMsg": "क्या आप इस पोस्ट को हटाना चाहते हैं?", - "no": "नहीं", - "yes": "हाँ", - "editPost": "पोस्ट संपादित करें", - "postTitle": "शीर्षक", - "postTitle1": "पोस्ट का शीर्षक संपादित करें", - "information1": "पोस्ट की जानकारी संपादित करें", - "information": "जानकारी", - "image": "छवि", - "video": "वीडियो", - "close": "बंद करें", - "updatePost": "पोस्ट अपडेट करें", - "postDeleted": "पोस्ट सफलतापूर्वक हटा दी गई है।", - "pin": "पोस्ट पिन करें", - "postUpdated": "पोस्ट सफलतापूर्वक अपडेट की गई है।", - "tag": "आपका ब्राउज़र वीडियो टैग का समर्थन नहीं करता", - "talawaApiUnavailable": "Talawa-API सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जाँचें।" - }, - "blockUnblockUser": { - "title": "तलावा ब्लॉक/अनब्लॉक यूजर", - "pageName": "ब्लॉक/अनब्लॉक", - "searchByName": "नाम से खोजें", - "listOfUsers": "स्पैम करने वाले उपयोगकर्ताओं की सूची", - "name": "नाम", - "email": "ईमेल", - "block_unblock": "ब्लॉक/अनब्लॉक करें", - "unblock": "अनब्लॉक करें", - "block": "अवरोध पैदा करना", - "orgName": "नाम दर्ज करें", - "blockedSuccessfully": "उपयोगकर्ता को सफलतापूर्वक अवरोधित किया गया", - "Un-BlockedSuccessfully": "उपयोगकर्ता अन-ब्लॉक किया गया सफलतापूर्वक", - "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।", - "allMembers": "सभी सदस्य", - "blockedUsers": "रोके गए उपयोगकर्ता", - "searchByFirstName": "पहले नाम से खोजें", - "searchByLastName": "उपनाम से खोजें", - "noResultsFoundFor": "के लिए कोई परिणाम नहीं मिला ", - "noSpammerFound": "कोई स्पैमर नहीं मिला" - }, - "eventManagement": { - "title": "इवेंट मैनेजमेंट", - "dashboard": "डैशबोर्ड", - "registrants": "पंजीकृत श्रेष्ठीकरण", - "eventActions": "इवेंट कार्रवाई", - "eventStats": "इवेंट स्टैटिस्टिक्स", - "to": "से" - }, - "forgotPassword": { - "title": "तलवा पासवर्ड भूल गए", - "forgotPassword": "पासवर्ड भूल गए", - "registeredEmail": "पंजीकृत ईमेल", - "getOtp": "ओटीपी प्राप्त करें", - "enterOtp": "ओटीपी दर्ज करें", - "enterNewPassword": "नया पासवर्ड दर्ज करें", - "cofirmNewPassword": "नए पासवर्ड की पुष्टि करें", - "changePassword": "पासवर्ड बदलें", - "backToLogin": "लॉगिन पर वापस जाएं", - "userOtp": "उदाहरण के लिए 12345", - "password": "पासवर्ड", - "emailNotRegistered": "ईमेल पंजीकृत नहीं है।", - "talawaApiUnavailable": "तलावा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रही है? अपनी नेटवर्क कनेक्टिविटी की भी जाँच करें।", - "errorSendingMail": "मेल भेजने में त्रुटि।", - "passwordMismatches": "पासवर्ड और पुष्टि पासवर्ड मेल नहीं खाते।", - "passwordChanges": "पासवर्ड सफलतापूर्वक बदल गया है।", - "OTPsent": "OTP आपके पंजीकृत ईमेल पर भेजा गया है।" - }, - "pageNotFound": { - "title": "404 नहीं मिला", - "talawaAdmin": "तलावा एडमिन", - "talawaUser": "तलावा उपयोगकर्ता", - "404": "404", - "notFoundMsg": "ओह! आपके द्वारा अनुरोधित पृष्ठ नहीं मिला!", - "backToHome": "घर वापिस जा रहा हूँ" - }, - "orgContribution": { - "title": "तलवा योगदान", - "filterByName": "नाम से फ़िल्टर करें", - "filterByTransId": "ट्रांस आईडी द्वारा फ़िल्टर करें", - "recentStats": "हाल के आँकड़े", - "contribution": "योगदान", - "orgname": "नाम दर्ज करें", - "searchtransaction": "लेन-देन आईडी दर्ज करें" - }, - "contriStats": { - "recentContribution": "हाल ही में योगदान", - "highestContribution": "उच्चतम योगदान", - "totalContribution": "कुल योगदान" - }, - "orgContriCards": { - "date": "दिनांक", - "transactionId": "लेनदेन आईडी", - "amount": "राशि" - }, - "orgSettings": { - "title": "तलावा सेटिंग", - "pageName": "सेटिंग्स", - "general": "सामान्य", - "actionItemCategories": "कार्रवाई आइटम श्रेणियाँ", - "updateYourDetails": "अपना विवरण अपडेट करें", - "updateYourPassword": "अपना पासवर्ड अपडेट करें", - "updateOrganization": "अद्यतन संगठन", - "seeRequest": "अनुरोध देखें", - "settings": "समायोजन", - "noData": "कोई डेटा नहीं", - "otherSettings": "अन्य सेटिंग्स", - "changeLanguage": "भाषा बदलें", - "manageCustomFields": "कस्टम फ़ील्ड प्रबंधन करें" - }, - "deleteOrg": { - "deleteOrganization": "संगठन हटाएं", - "deleteSampleOrganization": "सैंपल संगठन को हटाएं", - "deleteMsg": "क्या आप इस संगठन को हटाना चाहते हैं?", - "cancel": "रद्द करना", - "confirmDelete": "हटाने की पुष्टि करें", - "longDelOrgMsg": "संगठन को हमेशा के लिए हटा देने के लिए संगठन हटाने के बटन पर क्लिक करके, उसके इवेंट्स, टैग्स और सभी संबंधित डेटा सहित सभी जानकारी हटा दी जाएगी।", - "successfullyDeletedSampleOrganization": "नमूना संगठन सफलतापूर्वक हटा दिया गया" - }, - "userUpdate": { - "firstName": "पहला नाम", - "lastName": "उपनाम", - "email": "ईमेल", - "password": "पासवर्ड", - "appLanguageCode": "डिफ़ॉल्ट भाषा", - "userType": "उपयोगकर्ता का प्रकार", - "admin": "व्यवस्थापक", - "superAdmin": "सुपरएडमिन", - "displayImage": "प्रदर्शन छवि", - "saveChanges": "परिवर्तनों को सुरक्षित करें", - "cancel": "रद्द करना" - }, - "userPasswordUpdate": { - "previousPassword": "पिछला पासवर्ड", - "newPassword": "नया पासवर्ड", - "confirmNewPassword": "नए पासवर्ड की पुष्टि करें", - "saveChanges": "परिवर्तनों को सुरक्षित करें", - "cancel": "रद्द करना" - }, - "orgDelete": { - "deleteOrg": "संगठन हटाएं" - }, - "membershipRequest": { - "joined": "में शामिल हो गए", - "accept": "स्वीकार करना", - "reject": "अस्वीकार", - "memberAdded": "यह स्वीकार किया जाता है", - "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।" - }, - "orgUpdate": { - "name": "नाम", - "description": "विवरण", - "location": "जगह", - "address": "पता", - "city": "शहर", - "countryCode": "देश कोड", - "line1": "लाइन 1", - "line2": "लाइन 2", - "postalCode": "पोस्टल कोड", - "dependentLocality": "आश्रित स्थान", - "sortingCode": "क्रमबद्ध कोड", - "state": "राज्य / प्रांत", - "displayImage": "प्रदर्शन छवि", - "userRegistrationRequired": "उपयोगकर्ता पंजीकरण आवश्यक", - "isVisibleInSearch": "खोज में दिखाए जा सकते हैं", - "saveChanges": "परिवर्तनों को सुरक्षित करें", - "cancel": "रद्द करना", - "enterNameOrganization": "संगठन का नाम दर्ज करें", - "successfulUpdated": "सफल अपडेट किया गया", - "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।" - }, - "addOnRegister": { - "addNew": "नया जोड़ो", - "addPlugin": "प्लगइन जोड़ें", - "pluginName": "प्लगइन का नाम", - "creatorName": "निर्माता का नाम", - "pluginDesc": "प्लगइन विवरण", - "close": "बंद करना", - "register": "पंजीकरण करवाना", - "pName": "जैसे: दान", - "cName": "जैसे: जॉन डो", - "pDesc": "यह प्लगइन यूआई को सक्षम बनाता है" - }, - "addOnStore": { - "title": "प्लगइन स्टोर", - "searchName": "जैसे: दान", - "enable": "सक्रिय", - "disable": "अक्षम", - "pHeading": "प्लग-इन", - "install": "स्थापित", - "available": "उपलब्ध", - "pMessage": "प्लगइन मौजूद नहीं है", - "filter": "फिल्टर", - "search": "खोज" - }, - "addOnEntry": { - "enable": "सक्रिय", - "install": "स्थापित करना", - "uninstall": "स्थापना रद्द करें" - }, - "memberDetail": { - "title": "उपयोगकर्ता विवरण", - "addAdmin": "व्यवस्थापक जोड़ें", - "alreadyIsAdmin": "सदस्य पहले से ही एक व्यवस्थापक है", - "organizations": "संगठन", - "events": "घटनाएं", - "role": "भूमिका", - "email": "ईमेल", - "createdOn": "पर बनाया गया", - "main": "मुख्य", - "firstName": "पहला नाम", - "lastName": "अंतिम नाम", - "language": "भाषा", - "gender": "लिंग", - "birthDate": "जन्म तिथि", - "educationGrade": "शैक्षिक ग्रेड", - "employmentStatus": "रोजगार की स्थिति", - "maritalStatus": "वैवाहिक स्थिति", - "displayImage": "प्रदर्शन छवि", - "phone": "फोन", - "address": "पता", - "countryCode": "देश कोड", - "state": "राज्य", - "city": "शहर", - "personalInfoHeading": "व्यक्तिगत जानकारी", - "contactInfoHeading": "संपर्क जानकारी", - "actionsHeading": "कार्रवाई", - "personalDetailsHeading": "प्रोफ़ाइल विवरण", - "appLanguageCode": "भाषा चुनें", - "delete": "उपयोगकर्ता को हटाएं", - "saveChanges": "परिवर्तन सहेजें", - "pluginCreationAllowed": "प्लगइन निर्माण अनुमति दी गई", - "joined": "शामिल हुए", - "created": "बनाया गया", - "adminForOrganizations": "संगठनों के लिए व्यवस्थापक", - "membershipRequests": "सदस्यता अनुरोध", - "adminForEvents": "घटनाओं के लिए व्यवस्थापक", - "addedAsAdmin": "उपयोगकर्ता को व्यवस्थापक के रूप में जोड़ा गया है।", - "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। कृपया अपना नेटवर्क कनेक्शन जांचें और कुछ देर प्रतीक्षा करें।" - }, - "userLogin": { - "login": "लॉगिन", - "forgotPassword": "पासवर्ड भूल गए ?", - "loginIntoYourAccount": "अपने खाते में प्रवेश करें", - "emailAddress": "ईमेल एड्रेस", - "enterEmail": "अपना ईमेल पता दर्ज करें", - "password": "पासवर्ड", - "enterPassword": "अपना पासवर्ड डालें", - "register": "रजिस्टर करें", - "invalidDetailsMessage": "कृपया एक वैध ईमेल और पासवर्ड दर्ज करें।", - "notAuthorised": "क्षमा मांगना! आप अधिकृत नहीं हैं!", - "invalidCredentials": "दर्ज क्रेडेंशियल्स गलत हैं। कृपया मान्य क्रेडेंशियल दर्ज करें।", - "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। कृपया अपना नेटवर्क कनेक्शन जांचें और कुछ देर प्रतीक्षा करें।" - }, - "userRegister": { - "register": "रजिस्टर करें", - "firstName": "पहला नाम", - "enterFirstName": "अपना पहला नाम दर्ज करें", - "lastName": "अंतिम नाम", - "enterLastName": "अपना अंतिम नाम दर्ज करें", - "emailAddress": "ईमेल एड्रेस", - "enterEmail": "अपना ईमेल पता दर्ज करें", - "password": "पासवर्ड", - "enterPassword": "अपना पासवर्ड डालें", - "confirmPassword": "पासवर्ड की पुष्टि कीजिये", - "enterConfirmPassword": "पुष्टि करने के लिए अपना पासवर्ड दर्ज करें", - "alreadyhaveAnAccount": "क्या आपके पास पहले से एक खाता मौजूद है?", - "login": "लॉगिन", - "afterRegister": "पंजीकरण सफलतापूर्वक हो गया है। कृपया आपके अनुरोध को स्वीकार करने के लिए व्यवस्थापक की प्रतीक्षा करें।", - "passwordNotMatch": "पासवर्ड मेल नहीं खाता. पासवर्ड की पुष्टि करें और पुनः प्रयास करें।", - "invalidDetailsMessage": "कृपया मान्य विवरण दर्ज करें।", - "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। कृपया अपना नेटवर्क कनेक्शन जांचें और कुछ देर प्रतीक्षा करें।" - }, - "userNavbar": { - "talawa": "तलावा", - "home": "घर", - "people": "लोग", - "events": "आयोजन", - "chat": "बातचीत", - "donate": "दान देना", - "settings": "समायोजन", - "language": "भाषा", - "logout": "लॉग आउट", - "close": "बंद करना" - }, - "userOrganizations": { - "allOrganizations": "सभी संगठन", - "joinedOrganizations": "संगठन शामिल हुए", - "createdOrganizations": "संगठन बनाये गये", - "search": "खोज करें", - "nothingToShow": "यहां दिखाने के लिए कुछ भी नहीं है.", - "selectOrganization": "संगठन का चयन करें", - "filter": "फिल्टर", - "organizations": "संगठन", - "searchByName": "नाम से खोजें" - }, - "userSidebarOrg": { - "yourOrganizations": "आपके संगठन", - "noOrganizations": "आप अभी तक किसी संगठन में शामिल नहीं हुए हैं.", - "viewAll": "सभी को देखें", - "talawaUserPortal": "तलावा उपयोगकर्ता पोर्टल", - "menu": "मेन्यू", - "my organizations": "मेरे संगठन", - "users": "उपयोगकर्ता", - "requests": "अनुरोध", - "communityProfile": "सामुदायिक प्रोफ़ाइल", - "logout": "लॉग आउट", - "settings": "समायोजन" - }, - "organizationSidebar": { - "viewAll": "सभी को देखें", - "events": "आयोजन", - "members": "सदस्य", - "noEvents": "दिखाने के लिए कोई ईवेंट नहीं", - "noMembers": "दिखाने के लिए कोई सदस्य नहीं" - }, - "postCard": { - "likes": "पसंद", - "comments": "टिप्पणियाँ" - }, - "home": { - "feed": "फ़ीड", - "pinnedPosts": "पिन किए गए पोस्ट देखें", - "somethingOnYourMind": "आपके मन में कुछ है?", - "addPost": "पोस्ट जोड़ें", - "startPost": "एक पोस्ट शुरू करें", - "media": "मीडिया", - "event": "घटना", - "article": "लेख" - }, - "settings": { - "settings": "सेटिंग्स", - "profileSettings": "पार्श्वचित्र समायोजन", - "firstName": "पहला नाम", - "lastName": "उपनाम", - "gender": "लिंग", - "emailAddress": "ईमेल पता", - "phoneNumber": "फोन नंबर", - "displayImage": "प्रदर्शन छवि", - "chooseFile": "फ़ाइल चुनें", - "birthDate": "जन्म तिथि", - "grade": "शैक्षिक ग्रेड", - "empStatus": "रोजगार की स्थिति", - "maritalStatus": "वैवाहिक स्थिति", - "address": "पता", - "state": "शहर / राज्य", - "country": "देश", - "resetChanges": "परिवर्तन रीसेट करें", - "saveChanges": "परिवर्तन सहेजें", - "profileDetails": "प्रोफ़ाइल विवरण", - "deleteUserMessage": "उपयोगकर्ता हटाएं बटन पर क्लिक करने से, आपका उपयोगकर्ता, उसकी घटनाओं, टैग्स और सभी संबंधित डेटा के साथ स्थायी रूप से हटा दिया जाएगा।", - "copyLink": "प्रोफ़ाइल लिंक कॉपी करें", - "deleteUser": "उपयोगकर्ता हटाएं", - "otherSettings": "अन्य सेटिंग्स", - "changeLanguage": "भाषा बदलें", - "sgender": "लिंग चुनें", - "gradePlaceholder": "ग्रेड दर्ज करें", - "sEmpStatus": "रोजगार की स्थिति चुनें", - "male": "पुरुष", - "female": "महिला", - "other": "अन्य", - "employed": "नियोजित", - "unemployed": "बेरोजगार", - "sMaritalStatus": "वैवाहिक स्थिति चुनें", - "single": "अविवाहित", - "married": "विवाहित", - "divorced": "तलाकशुदा", - "widowed": "विधवा", - "engaged": "सगाईशुदा", - "seperated": "अलग", - "grade1": "कक्षा 1", - "grade2": "कक्षा 2", - "grade3": "कक्षा 3", - "grade4": "कक्षा 4", - "grade5": "कक्षा 5", - "grade6": "कक्षा 6", - "grade7": "कक्षा 7", - "grade8": "कक्षा 8", - "grade9": "कक्षा 9", - "grade10": "कक्षा 10", - "grade11": "कक्षा 11", - "grade12": "कक्षा 12 ", - "graduate": "स्नातक", - "kg": "केजी", - "preKg": "प्री-केजी", - "noGrade": "कोई ग्रेड नहीं", - "fullTime": "पूर्णकालिक", - "partTime": "अंशकालिक", - "enterState": "शहर या राज्य दर्ज करें", - "selectCountry": "देश चुनें", - "joined": "शामिल हुआ" - }, - "donate": { - "donations": "दान", - "searchDonations": "दान खोजें", - "donateForThe": "के लिए दान करें", - "donateTo": "दान दें", - "amount": "मात्रा", - "yourPreviousDonations": "आपका पिछला दान", - "donate": "दान", - "nothingToShow": "यहां दिखाने के लिए कुछ भी नहीं है.", - "success": "दान सफल" - }, - "userEvents": { - "nothingToShow": "यहां दिखाने के लिए कुछ भी नहीं है.", - "search": "खोज", - "createEvent": "कार्यक्रम बनाएँ", - "recurring": "पुनरावर्ती", - "startTime": "समय शुरू", - "endTime": "अंत समय", - "cancel": "रद्द करना", - "create": "बनाएं", - "listView": "लिस्ट व्यू", - "calendarView": "कैलेंडर दृश्य", - "allDay": "पूरे दिन", - "eventCreated": "इवेंट सफलतापूर्वक बनाया और पोस्ट किया गया।", - "eventDetails": "घटना विवरण", - "eventTitle": "शीर्षक", - "enterTitle": "शीर्षक दर्ज करें", - "eventDescription": "विवरण", - "enterDescription": "विवरण दर्ज करें", - "eventLocation": "स्थान", - "enterLocation": "स्थान दर्ज करें", - "startDate": "प्रारंभ तिथि", - "endDate": "अंतिम तिथि", - "publicEvent": "सार्वजनिक है", - "registerable": "पंजीकृत करने योग्य है", - "monthlyCalendarView": "मासिक कैलेंडर", - "yearlyCalendarView": "वार्षिक कैलेंडर" - }, - "userEventCard": { - "location": "जगह", - "starts": "प्रारंभ होगा", - "ends": "समाप्त होगा", - "creator": "निर्माता", - "alreadyRegistered": "पहले से ही पंजीकृत", - "register": "पंजीकरण करवाना" - }, - "advertisement": { - "title": "विज्ञापन", - "pHeading": "विज्ञापन प्रबंधन", - "activeAds": "सक्रिय अभियान", - "archievedAds": "संपन्न अभियान", - "pMessage": "इस अभियान के लिए कोई विज्ञापन नहीं हैं।", - "delete": "हटाएँ", - "validLink": "लिंक मान्य है", - "invalidLink": "लिंक अमान्य है", - "close": "बंद करें", - "deleteAdvertisement": "विज्ञापन हटाएं", - "deleteAdvertisementMsg": "क्या आप इस विज्ञापन को हटाना चाहते हैं?", - "no": "नहीं", - "yes": "हाँ", - "Rmedia": "प्रदर्शित करने के लिए मीडिया सामग्री प्रदान करें", - "view": "देखें", - "edit": "संपादित करें", - "editAdvertisement": "विज्ञापन संपादित करें", - "saveChanges": "परिवर्तन सहेजें", - "endOfResults": "परिणामों का अंत" - }, - "userChat": { - "chat": "बात", - "search": "खोज", - "contacts": "संपर्क" - }, - "userChatRoom": { - "selectContact": "बातचीत शुरू करने के लिए एक संपर्क चुनें", - "sendMessage": "मेसेज भेजें" - }, - "orgProfileField": { - "loading": "लोड हो रहा है...", - "noCustomField": "कोई कस्टम फ़ील्ड उपलब्ध नहीं है", - "customFieldName": "फ़ील्ड का नाम", - "enterCustomFieldName": "फ़ील्ड का नाम दर्ज करें", - "customFieldType": "फ़ील्ड का प्रकार", - "saveChanges": "परिवर्तन सहेजें", - "Remove Custom Field": "कस्टम फ़ील्ड हटाएँ", - "fieldSuccessMessage": "फ़ील्ड सफलतापूर्वक जोड़ा गया", - "fieldRemovalSuccess": "फ़ील्ड सफलतापूर्वक हटा दिया गया" - }, - "orgActionItemCategories": { - "createButton": "बनाएं", - "editButton": "संपादित करें", - "enableButton": "सक्षम करें", - "disableButton": "अक्षम करें", - "updateActionItemCategory": "अद्यतन करें", - "actionItemCategoryName": "नाम", - "actionItemCategoryDetails": "कार्रवाई आइटम श्रेणी विवरण", - "enterName": "नाम दर्ज करें", - "successfulCreation": "कार्रवाई आइटम श्रेणी सफलतापूर्वक बनाई गई", - "successfulUpdation": "क्रिया आइटम श्रेणी सफलतापूर्वक अद्यतन की गई", - "sameNameConflict": "अपडेट करने के लिए कृपया नाम बदलें", - "categoryEnabled": "कार्रवाई आइटम श्रेणी सक्षम", - "categoryDisabled": "क्रिया आइटम श्रेणी अक्षम की गई" - }, - "organizationVenues": { - "title": "स्थलों", - "addVenue": "स्थल जोड़ें", - "venueDetails": "स्थल विवरण", - "venueName": "स्थल का नाम", - "enterVenueName": "स्थल का नाम दर्ज करें", - "description": "स्थल विवरण", - "enterVenueDesc": "स्थल विवरण दर्ज करें", - "capacity": "क्षमता", - "enterVenueCapacity": "स्थल क्षमता दर्ज करें", - "image": "स्थल इमेज", - "uploadVenueImage": "स्थल इमेज अपलोड करें", - "createVenue": "स्थल बनाएं", - "venueAdded": "स्थल सफलतापूर्वक जोड़ा गया", - "editVenue": "स्थल अपडेट करें", - "venueUpdated": "स्थल विवरण सफलतापूर्वक अपडेट किए गए", - "sort": "क्रमबद्ध करें", - "highestCapacity": "सबसे उच्च क्षमता", - "lowestCapacity": "सबसे कम क्षमता", - "noVenues": "कोई स्थल नहीं मिला!", - "edit": "संपादित करें", - "view": "देखें", - "delete": "हटाएं", - "venueTitleError": "स्थल शीर्षक खाली नहीं हो सकता!", - "venueCapacityError": "क्षमता एक धनात्मक संख्या होनी चाहिए!", - "searchBy": "से खोजें", - "name": "नाम", - "desc": "विवरण" - }, - "addMember": { - "title": "सदस्य जोड़ें", - "addMembers": "सदस्य जोड़ें", - "existingUser": "मौजूदा उपयोगकर्ता", - "newUser": "नया उपयोगकर्ता", - "searchFullName": "पूरा नाम से खोजें", - "firstName": "प्रथम नाम", - "enterFirstName": "प्रथम नाम दर्ज करें", - "lastName": "अंतिम नाम", - "enterLastName": "अंतिम नाम दर्ज करें", - "emailAddress": "ईमेल पता", - "enterEmail": "ईमेल दर्ज करें", - "password": "पासवर्ड", - "enterPassword": "पासवर्ड दर्ज करें", - "confirmPassword": "पासवर्ड की पुष्टि करें", - "enterConfirmPassword": "पासवर्ड की पुष्टि करें", - "organization": "संगठन", - "cancel": "रद्द करें", - "create": "सृजन करें", - "invalidDetailsMessage": "कृपया सभी आवश्यक विवरण प्रदान करें।", - "passwordNotMatch": "पासवर्ड मेल नहीं खाते।", - "user": "उपयोगकर्ता", - "addMember": "सदस्य जोड़ें" - }, - "eventActionItems": { - "title": "कार्रवाई आइटम", - "createActionItem": "क्रिया आइटम बनाएँ", - "actionItemCategory": "एक्शन आइटम श्रेणी", - "selectActionItemCategory": "एक क्रिया आइटम श्रेणी चुनें", - "selectAssignee": "एक असाइनी का चयन करें", - "preCompletionNotes": "पूर्व समापन नोट्स", - "postCompletionNotes": "पोस्टकंप्लीशननोट्स", - "actionItemDetails": "एक्शन आइटम विवरण", - "dueDate": "नियत तिथि", - "completionDate": "समापन तिथि", - "editActionItem": "एक्शन आइटम संपादित करें", - "deleteActionItem": "क्रिया आइटम हटाएं", - "deleteActionItemMsg": "क्या आप इस क्रिया आइटम को हटाना चाहते हैं?", - "yes": "हां", - "no": "नहीं", - "successfulDeletion": "कार्रवाई आइटम सफलतापूर्वक हटा दिया गया", - "successfulCreation": "क्रिया आइटम सफलतापूर्वक बनाया गया", - "successfulUpdation": "कार्रवाई आइटम सफलतापूर्वक अद्यतन किया गया", - "notes": "नोट्स", - "save": "सहेजें" - } -} diff --git a/public/locales/hi/common.json b/public/locales/hi/common.json new file mode 100644 index 0000000000..1a6ed161e7 --- /dev/null +++ b/public/locales/hi/common.json @@ -0,0 +1,65 @@ +{ + "firstName": "पहला नाम", + "lastName": "उपनाम", + "searchByName": "नाम से खोजें", + "loading": "लोड हो रहा है...", + "endOfResults": "परिणाम का अंत", + "noResultsFoundFor": "का कोई परिणाम नहीं मिला ", + "edit": "संपादन करना", + "admins": "व्यवस्थापक", + "admin": "व्यवस्थापक", + "user": "उपयोगकर्ता", + "superAdmin": "सुपरएडमिन", + "members": "सदस्यों", + "logout": "लॉग आउट", + "login": "लॉग इन करें", + "register": "पंजीकरण करवाना", + "menu": "मेन्यू", + "settings": "समायोजन", + "users": "उपयोगकर्ताओं", + "requests": "अनुरोध", + "OR": "या", + "cancel": "रद्द करना", + "close": "बंद करना", + "create": "बनाएं", + "delete": "मिटाना", + "done": "हो गया", + "yes": "हाँ", + "no": "नहीं", + "filter": "फ़िल्टर", + "search": "खोज", + "description": "विवरण", + "saveChanges": "परिवर्तनों को सुरक्षित करें", + "displayImage": "प्रदर्शन छवि", + "enterEmail": "ईमेल दर्ज करें", + "emailAddress": "मेल पता", + "email": "ईमेल", + "name": "नाम", + "enterPassword": "पास वर्ड दर्ज करें", + "password": "पासवर्ड", + "confirmPassword": "पासवर्ड की पुष्टि कीजिये", + "forgotPassword": "पासवर्ड भूल गए ?", + "talawaAdminPortal": "तलावा एडमिन पोर्टल", + "address": "पता", + "location": "जगह", + "enterLocation": "स्थान दर्ज करें", + "joined": "में शामिल हो गए", + "startDate": "आरंभ करने की तिथि", + "endDate": "अंतिम तिथि", + "startTime": "समय शुरू", + "endTime": "अंत समय", + "My Organizations": "मेरे संगठन", + "Dashboard": "डैशबोर्ड", + "People": "लोग", + "Events": "कार्यक्रम", + "Venues": "स्थल", + "Action Items": "कार्य आइटम", + "Posts": "पोस्ट", + "Block/Unblock": "ब्लॉक/अनब्लॉक", + "Advertisement": "विज्ञापन", + "Funds": "निधि", + "Membership Requests": "सदस्यता अनुरोध", + "Plugins": "प्लगइन्स", + "Plugin Store": "प्लगइन स्टोर", + "Settings": "सेटिंग्स" +} diff --git a/public/locales/hi/errors.json b/public/locales/hi/errors.json new file mode 100644 index 0000000000..5e08ee8e9e --- /dev/null +++ b/public/locales/hi/errors.json @@ -0,0 +1,9 @@ +{ + "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है! ", + "notFound": "नहीं मिला", + "unknownError": "एक अज्ञात त्रुटि हुई। {{msg}}", + "notAuthorised": "क्षमा मांगना! ", + "errorSendingMail": "मेल भेजने में त्रुटि", + "emailNotRegistered": "ईमेल पंजीकृत नहीं है", + "notFoundMsg": "उफ़! " +} diff --git a/public/locales/hi/translation.json b/public/locales/hi/translation.json new file mode 100644 index 0000000000..41a8741eca --- /dev/null +++ b/public/locales/hi/translation.json @@ -0,0 +1,892 @@ +{ + "loginPage": { + "title": "तलावा प्रशासन", + "fromPalisadoes": "पैलिसाडोज़ फाउंडेशन के स्वयंसेवकों द्वारा एक खुला स्रोत एप्लिकेशन", + "userLogin": "उपयोगकर्ता लॉगिन", + "atleast_8_char_long": "कम से कम 8 अक्षर लंबा", + "atleast_6_char_long": "कम से कम 6 अक्षर लंबा", + "firstName_invalid": "प्रथम नाम में केवल छोटे और बड़े अक्षर होने चाहिए", + "lastName_invalid": "अंतिम नाम में केवल छोटे और बड़े अक्षर होने चाहिए", + "password_invalid": "पासवर्ड में कम से कम एक लोअरकेस अक्षर, एक अपरकेस अक्षर, एक संख्यात्मक मान और एक विशेष अक्षर होना चाहिए", + "email_invalid": "ईमेल में कम से कम 8 अक्षर होने चाहिए", + "Password_and_Confirm_password_mismatches.": "पासवर्ड और पासवर्ड बेमेल होने की पुष्टि करें।", + "doNotOwnAnAccount": "क्या आपके पास कोई खाता नहीं है?", + "captchaError": "कैप्चा त्रुटि!", + "Please_check_the_captcha": "कृपया, कैप्चा जांचें।", + "Something_went_wrong": "कुछ ग़लत हो गया, कृपया कुछ देर बाद प्रयास करें।", + "passwordMismatches": "पासवर्ड और पासवर्ड बेमेल होने की पुष्टि करें।", + "fillCorrectly": "सभी विवरण सही-सही भरें।", + "successfullyRegistered": "पंजीकरण सफलतापूर्वक हो गया है। ", + "lowercase_check": "कम से कम एक छोटा अक्षर", + "uppercase_check": "कम से कम एक बड़ा अक्षर", + "numeric_value_check": "कम से कम एक संख्यात्मक मान निर्धारित करें", + "special_char_check": "कम से कम एक विशेष पात्र", + "selectOrg": "एक संगठन चुनें", + "afterRegister": "पंजीकरण सफलतापूर्वक हो गया है। " + }, + "userLoginPage": { + "title": "तलावा प्रशासन", + "fromPalisadoes": "पैलिसाडोज़ फाउंडेशन के स्वयंसेवकों द्वारा एक खुला स्रोत एप्लिकेशन", + "atleast_8_char_long": "कम से कम 8 अक्षर लंबा", + "Password_and_Confirm_password_mismatches.": "पासवर्ड और पासवर्ड बेमेल होने की पुष्टि करें।", + "doNotOwnAnAccount": "क्या आपके पास कोई खाता नहीं है?", + "captchaError": "कैप्चा त्रुटि!", + "Please_check_the_captcha": "कृपया, कैप्चा जांचें।", + "Something_went_wrong": "कुछ ग़लत हो गया, कृपया कुछ देर बाद प्रयास करें।", + "passwordMismatches": "पासवर्ड और पासवर्ड बेमेल होने की पुष्टि करें।", + "fillCorrectly": "सभी विवरण सही-सही भरें।", + "successfullyRegistered": "पंजीकरण सफलतापूर्वक हो गया है। ", + "userLogin": "उपयोगकर्ता लॉगिन", + "afterRegister": "पंजीकरण सफलतापूर्वक हो गया है। ", + "selectOrg": "एक संगठन चुनें" + }, + "latestEvents": { + "eventCardTitle": "आगामी कार्यक्रम", + "eventCardSeeAll": "सभी देखें", + "noEvents": "कोई आगामी ईवेंट नहीं" + }, + "latestPosts": { + "latestPostsTitle": "नवीनतम पोस्ट", + "seeAllLink": "सभी देखें", + "noPostsCreated": "कोई पोस्ट नहीं बनाई गई" + }, + "listNavbar": { + "roles": "भूमिकाएँ" + }, + "leftDrawer": { + "my organizations": "मेरे संगठन", + "requests": "सदस्यता अनुरोध", + "communityProfile": "सामुदायिक प्रोफ़ाइल" + }, + "leftDrawerOrg": { + "Dashboard": "डैशबोर्ड", + "People": "लोग", + "Events": "आयोजन", + "Contributions": "योगदान", + "Posts": "पदों", + "Block/Unblock": "ब्लॉक/अनब्लॉक करें", + "Plugins": "प्लग-इन", + "Plugin Store": "प्लगइन स्टोर", + "Advertisement": "विज्ञापनों", + "allOrganizations": "सभी संगठन", + "yourOrganization": "आपकी संगठन", + "notification": "अधिसूचना", + "language": "भाषा", + "notifications": "सूचनाएं", + "spamsThe": "स्पैम करता है", + "group": "समूह", + "noNotifications": "कोई सूचनाएं नहीं" + }, + "orgList": { + "title": "तलावा संगठन", + "you": "आप", + "designation": "पद का नाम", + "my organizations": "मेरे संगठन", + "createOrganization": "संगठन बनाएं", + "createSampleOrganization": "नमूना संगठन बनाएं", + "city": "शहर", + "countryCode": "कंट्री कोड", + "dependentLocality": "आश्रित इलाका", + "line1": "लाइन 1", + "line2": "लाइन 2", + "postalCode": "डाक कोड", + "sortingCode": "कोड क्रमबद्ध करना", + "state": "राज्य/प्रान्त", + "userRegistrationRequired": "उपयोगकर्ता पंजीकरण आवश्यक", + "visibleInSearch": "खोज में दृश्यमान", + "enterName": "नाम दर्ज करें", + "sort": "क्रम से लगाना", + "Latest": "नवीनतम", + "Earliest": "जल्द से जल्द", + "noOrgErrorTitle": "संगठन नहीं मिले", + "sampleOrgDuplicate": "केवल एक नमूना संगठन को अनुमति दी गई", + "noOrgErrorDescription": "कृपया डैशबोर्ड के माध्यम से एक संगठन बनाएं", + "manageFeatures": "सुविधाओं को प्रबंधित करें", + "manageFeaturesInfo": "सृजन सफल! ", + "goToStore": "प्लगइन स्टोर पर जाएँ", + "enableEverything": "सब कुछ सक्षम करें", + "sampleOrgSuccess": "नमूना संगठन सफलतापूर्वक बनाया गया" + }, + "orgListCard": { + "manage": "प्रबंधित करना", + "sampleOrganization": "नमूना संगठन" + }, + "paginationList": { + "rowsPerPage": "प्रति पृष्ठ पंक्तियाँ", + "all": "सभी" + }, + "requests": { + "title": "सदस्यता अनुरोध", + "sl_no": "क्र.सं. ", + "accept": "स्वीकार करना", + "reject": "अस्वीकार करना", + "searchRequests": "सदस्यता अनुरोध खोजें", + "noOrgError": "संगठन नहीं मिला, कृपया डैशबोर्ड के माध्यम से एक संगठन बनाएं", + "noRequestsFound": "कोई सदस्यता अनुरोध नहीं मिला", + "acceptedSuccessfully": "अनुरोध सफलतापूर्वक स्वीकार किया गया", + "rejectedSuccessfully": "अनुरोध सफलतापूर्वक अस्वीकार कर दिया गया", + "noOrgErrorTitle": "संगठन नहीं मिले", + "noOrgErrorDescription": "कृपया डैशबोर्ड के माध्यम से एक संगठन बनाएं" + }, + "users": { + "title": "तलावा भूमिकाएँ", + "joined_organizations": "संगठनों से जुड़े", + "blocked_organizations": "अवरुद्ध संगठन", + "orgJoinedBy": "संगठनों से जुड़े", + "orgThatBlocked": "वे संगठन जिन्होंने अवरुद्ध किया", + "hasNotJoinedAnyOrg": "किसी भी संगठन में शामिल नहीं हुआ है", + "isNotBlockedByAnyOrg": "किसी भी संगठन द्वारा अवरुद्ध नहीं किया गया है", + "searchByOrgName": "संगठन के नाम से खोजें", + "view": "देखना", + "enterName": "नाम दर्ज करें", + "loadingUsers": "उपयोगकर्ता लोड हो रहे हैं...", + "noUserFound": "कोई उपयोगकर्ता नहीं मिला", + "sort": "क्रम से लगाना", + "Newest": "नवीनतम पहले", + "Oldest": "सबसे पुराना पहले", + "noOrgError": "संगठन नहीं मिला, कृपया डैशबोर्ड के माध्यम से एक संगठन बनाएं", + "roleUpdated": "भूमिका अद्यतन की गई.", + "joinNow": "अब शामिल हों", + "visit": "मिलने जाना", + "withdraw": "चौड़ाई निकालना" + }, + "communityProfile": { + "title": "सामुदायिक प्रोफ़ाइल", + "editProfile": "प्रोफ़ाइल संपादित करें", + "communityProfileInfo": "ये विवरण आपके और आपके समुदाय के सदस्यों के लिए लॉगिन/साइनअप स्क्रीन पर दिखाई देंगे", + "communityName": "समुदाय का नाम", + "wesiteLink": "वेबसाइट की लिंक", + "logo": "प्रतीक चिन्ह", + "social": "सोशल मीडिया लिंक", + "url": "यू आर एल दर्ज करो", + "profileChangedMsg": "प्रोफ़ाइल विवरण सफलतापूर्वक अपडेट किया गया.", + "resetData": "प्रोफ़ाइल विवरण सफलतापूर्वक रीसेट करें।" + }, + "dashboard": { + "title": "डैशबोर्ड", + "about": "के बारे में", + "deleteThisOrganization": "इस संगठन को हटाएँ", + "statistics": "आंकड़े", + "posts": "पदों", + "events": "आयोजन", + "blockedUsers": "रोके गए उपयोगकर्ता", + "viewAll": "सभी को देखें", + "upcomingEvents": "आगामी कार्यक्रम", + "noUpcomingEvents": "कोई आगामी ईवेंट नहीं", + "latestPosts": "नवीनतम पोस्ट", + "noPostsPresent": "कोई पोस्ट मौजूद नहीं", + "membershipRequests": "सदस्यता अनुरोध", + "noMembershipRequests": "कोई सदस्यता अनुरोध मौजूद नहीं है" + }, + "organizationPeople": { + "title": "तलवा सदस्य", + "filterByName": "नाम से फ़िल्टर करें", + "filterByLocation": "स्थान के अनुसार फ़िल्टर करें", + "filterByEvent": "इवेंट के अनुसार फ़िल्टर करें", + "searchName": "नाम दर्ज करें", + "searchevent": "इवेंट दर्ज करें", + "searchFullName": "पूरा नाम दर्ज करें", + "people": "लोग", + "sort": "भूमिका के आधार पर खोजें", + "actions": "कार्रवाई", + "addMembers": "सदस्य जोड़ें", + "existingUser": "मौजूदा उपयोगकर्ता", + "newUser": "नए उपयोगकर्ता", + "enterFirstName": "अपना पहला नाम दर्ज करें", + "enterLastName": "अपना अंतिम नाम दर्ज करें", + "enterConfirmPassword": "पुष्टि करने के लिए अपना पासवर्ड दर्ज करें", + "organization": "संगठन", + "invalidDetailsMessage": "कृपया वैध विवरण दर्ज करें." + }, + "userListCard": { + "addAdmin": "व्यवस्थापक जोड़ें", + "addedAsAdmin": "उपयोगकर्ता को व्यवस्थापक के रूप में जोड़ा गया है." + }, + "orgAdminListCard": { + "remove": "निकालना", + "removeAdmin": "व्यवस्थापक हटाएँ", + "removeAdminMsg": "क्या आप इस व्यवस्थापक को हटाना चाहते हैं?", + "adminRemoved": "व्यवस्थापक को हटा दिया गया है." + }, + "orgPeopleListCard": { + "remove": "निकालना", + "removeMember": "सदस्य हटाएँ", + "removeMemberMsg": "क्या आप इस सदस्य को हटाना चाहते हैं?", + "memberRemoved": "सदस्य को हटा दिया गया है" + }, + "organizationEvents": { + "title": "आयोजन", + "filterByTitle": "शीर्षक के अनुसार फ़िल्टर करें", + "filterByLocation": "स्थान के अनुसार फ़िल्टर करें", + "filterByDescription": "विवरण के अनुसार फ़िल्टर करें", + "addEvent": "कार्यक्रम जोड़ें", + "eventDetails": "घटना की जानकारी", + "eventTitle": "शीर्षक", + "startTime": "समय शुरू", + "endTime": "अंत समय", + "allDay": "पूरे दिन", + "recurringEvent": "पुनरावर्ती ईवेंट", + "isPublic": "सार्वजनिक है", + "isRegistrable": "पंजीकरण योग्य है", + "createEvent": "कार्यक्रम बनाएँ", + "enterFilter": "फ़िल्टर दर्ज करें", + "enterTitle": "शीर्षक दर्ज करें", + "enterDescrip": "विवरण दर्ज करें", + "eventLocation": "स्थान दर्ज करें", + "searchEventName": "ईवेंट का नाम खोजें", + "eventType": "घटना प्रकार", + "eventCreated": "बधाई हो! ", + "customRecurrence": "कस्टम पुनरावृत्ति", + "repeatsEvery": "प्रत्येक को दोहराता है", + "repeatsOn": "पर दोहराता है", + "ends": "समाप्त होता है", + "never": "कभी नहीं", + "on": "पर", + "after": "बाद", + "occurences": "घटनाओं" + }, + "organizationActionItems": { + "actionItemCategory": "कार्य आइटम श्रेणी", + "actionItemDetails": "कार्रवाई मद विवरण", + "actionItemCompleted": "कार्य आइटम पूर्ण हुआ", + "assignee": "संपत्ति-भागी", + "assigner": "असाइनर", + "assignmentDate": "असाइनमेंट दिनांक", + "active": "सक्रिय", + "clearFilters": "फ़िल्टर साफ़ करें", + "completed": "पुरा होना।", + "completionDate": "पूरा करने की तिथि", + "deleteActionItem": "क्रिया आइटम हटाएँ", + "deleteActionItemMsg": "क्या आप इस क्रिया आइटम को हटाना चाहते हैं?", + "details": "विवरण", + "dueDate": "नियत तारीख", + "earliest": "जल्द से जल्द", + "editActionItem": "क्रिया आइटम संपादित करें", + "isCompleted": "पुरा होना।", + "latest": "नवीनतम", + "noActionItems": "कोई एक्शन आइटम नहीं", + "options": "विकल्प", + "preCompletionNotes": "समापन पूर्व नोट्स", + "actionItemActive": "सक्रिय", + "markCompletion": "पूर्णता चिह्नित करें", + "actionItemStatus": "कार्रवाई मद स्थिति", + "postCompletionNotes": "समापन के बाद के नोट्स", + "selectActionItemCategory": "एक क्रिया आइटम श्रेणी का चयन करें", + "selectAssignee": "एक समनुदेशिती का चयन करें", + "status": "स्थिति", + "successfulCreation": "कार्रवाई आइटम सफलतापूर्वक बनाया गया", + "successfulUpdation": "कार्रवाई आइटम सफलतापूर्वक अपडेट किया गया", + "successfulDeletion": "कार्रवाई आइटम सफलतापूर्वक हटा दिया गया", + "title": "एक्शन आइटम्स" + }, + "eventListCard": { + "deleteEvent": "ईवेंट हटाएँ", + "deleteEventMsg": "क्या आप इस ईवेंट को हटाना चाहते हैं?", + "editEvent": "इवेंट संपादित करें", + "eventTitle": "शीर्षक", + "alreadyRegistered": "पहले से ही पंजीकृत", + "startTime": "समय शुरू", + "endTime": "अंत समय", + "allDay": "पूरे दिन", + "recurringEvent": "पुनरावर्ती ईवेंट", + "isPublic": "सार्वजनिक है", + "isRegistrable": "पंजीकरण योग्य है", + "updatePost": "पोस्ट अपडेट करें", + "eventDetails": "घटना की जानकारी", + "eventDeleted": "ईवेंट सफलतापूर्वक हटा दिया गया.", + "eventUpdated": "इवेंट सफलतापूर्वक अपडेट किया गया.", + "thisInstance": "यह उदाहरण", + "thisAndFollowingInstances": "यह और निम्नलिखित उदाहरण", + "allInstances": "सभी उदाहरण", + "customRecurrence": "कस्टम पुनरावृत्ति", + "repeatsEvery": "प्रत्येक को दोहराता है", + "repeatsOn": "पर दोहराता है", + "ends": "समाप्त होता है", + "never": "कभी नहीं", + "on": "पर", + "after": "बाद", + "occurences": "घटनाओं" + }, + "funds": { + "title": "फंड", + "createFund": "फंड बनाएं", + "fundName": "फंड का नाम", + "fundId": "फंड आईडी", + "fundOptions": "Opitons", + "noFunds": "कोई फंड नहीं मिला", + "fundDetails": "फंड विवरण", + "taxDeductible": "कर छूट", + "enterfundName": "फंड का नाम दर्ज करें", + "enterfundId": "फंड आईडी दर्ज करें", + "default": "डिफ़ॉल्ट फंड", + "archived": "संग्रहीत", + "nonArchive": "गैर-अभिलेखित", + "fundCreate": "फंड बनाएं", + "fundUpdate": "अद्यतन निधि", + "fundDelete": "फ़ंड हटाएँ", + "manageFund": "फंड का प्रबंधन करें", + "searchFullName": "नाम से खोजें", + "noFundsFound": "कोई फंड नहीं मिला", + "createdBy": "के द्वारा बनाई गई", + "createdOn": "पर बनाया", + "status": "स्थिति", + "archiveFund": "पुरालेख कोष", + "archiveFundMsg": "इस फंड को संग्रहित करने पर इसे फंड सूची से हटा दिया जाएगा। इस कार्रवाई को पूर्ववत किया जा सकता है", + "fundCreated": "फंड सफलतापूर्वक बनाया गया", + "fundUpdated": "फंड सफलतापूर्वक अपडेट किया गया", + "fundDeleted": "फंड सफलतापूर्वक हटा दिया गया", + "fundArchived": "निधि सफलतापूर्वक संग्रहित की गई", + "fundUnarchived": "फंड सफलतापूर्वक संग्रहित किया गया", + "deleteFundMsg": "क्या आप इस फंड को हटाना चाहते हैं?" + }, + "fundCampaign": { + "title": "धन उगाही अभियान", + "campaignName": "अभियान का नाम", + "campaignOptions": "विकल्प", + "fundingGoal": "वित्त पोषण लक्ष्य", + "addCampaign": "अभियान जोड़ें", + "createdCampaign": "अभियान सफलतापूर्वक बनाया गया", + "updatedCampaign": "अभियान सफलतापूर्वक अपडेट किया गया", + "deletedCampaign": "अभियान सफलतापूर्वक हटा दिया गया", + "deleteCampaignMsg": "क्या आप वाकई इस अभियान को हटाना चाहते हैं?", + "noCampaigns": "कोई अभियान नहीं मिला", + "createCampaign": "फंड अभियान बनाएं", + "updateCampaign": "अद्यतन निधि अभियान", + "manageCampaign": "फंड अभियान प्रबंधित करें", + "deleteCampaign": "फ़ंड अभियान हटाएँ", + "currency": "मुद्रा", + "selectCurrency": "मुद्रा चुनें", + "searchFullName": "नाम से खोजें" + }, + "pledges": { + "title": "निधि अभियान प्रतिज्ञाएँ", + "volunteers": "स्वयंसेवकों", + "pledgeAmount": "प्रतिज्ञा राशि", + "pledgeOptions": "विकल्प", + "pledgeCreated": "प्रतिज्ञा सफलतापूर्वक बनाई गई", + "pledgeUpdated": "प्रतिज्ञा सफलतापूर्वक अद्यतन की गई", + "pledgeDeleted": "प्रतिज्ञा सफलतापूर्वक हटा दी गई", + "addPledge": "प्रतिज्ञा जोड़ें", + "createPledge": "प्रतिज्ञा बनाएँ", + "currency": "मुद्रा", + "selectCurrency": "मुद्रा चुनें", + "updatePledge": "प्रतिज्ञा अद्यतन करें", + "deletePledge": "प्रतिज्ञा हटाएँ", + "amount": "मात्रा", + "editPledge": "प्रतिज्ञा संपादित करें", + "deletePledgeMsg": "क्या आप वाकई इस प्रतिज्ञा को हटाना चाहते हैं?", + "noPledges": "कोई प्रतिज्ञा नहीं मिली" + }, + "orgPost": { + "title": "पदों", + "searchPost": "पोस्ट खोजें", + "posts": "पदों", + "createPost": "पोस्ट बनाएं", + "postDetails": "पोस्ट विवरण", + "postTitle1": "पोस्ट का शीर्षक लिखें", + "postTitle": "शीर्षक", + "addMedia": "मीडिया अपलोड करें", + "information": "जानकारी", + "information1": "पोस्ट की जानकारी लिखें", + "addPost": "पोस्ट जोड़ें", + "searchTitle": "शीर्षक से खोजें", + "searchText": "पाठ द्वारा खोजें", + "ptitle": "शीर्षक पोस्ट करें", + "postDes": "तुम्हें किस बारे में बात करनी है?", + "Title": "शीर्षक", + "Text": "मूलपाठ", + "searchBy": "खोज से", + "Oldest": "सबसे पुराना पहले", + "Latest": "नवीनतम प्रथम", + "sortPost": "पोस्ट क्रमबद्ध करें", + "tag": " आपका ब्राउज़र में वीडियो टैग समर्थित नहीं है", + "postCreatedSuccess": "बधाई हो! ", + "pinPost": "पिन पद", + "Next": "अगला पृष्ठ", + "Previous": "पिछला पृष्ठ" + }, + "postNotFound": { + "post": "डाक", + "not found!": "नहीं मिला!", + "organization": "संगठन", + "post not found!": "पोस्ट नहीं मिली!", + "organization not found!": "संगठन नहीं मिला!" + }, + "userNotFound": { + "not found!": "नहीं मिला!", + "roles": "भूमिकाएँ", + "user not found!": "उपयोगकर्ता नहीं मिला!", + "member not found!": "सदस्य अनुपस्थित!", + "admin not found!": "व्यवस्थापक नहीं मिला!", + "roles not found!": "भूमिकाएँ नहीं मिलीं!" + }, + "orgPostCard": { + "author": "लेखक", + "imageURL": "छवि यूआरएल", + "videoURL": "वीडियो यूआरएल", + "deletePost": "पोस्ट को हटाएं", + "deletePostMsg": "क्या आप इस पोस्ट को हटाना चाहते हैं?", + "editPost": "संपादित पोस्ट", + "postTitle": "शीर्षक", + "postTitle1": "पोस्ट का शीर्षक संपादित करें", + "information1": "पोस्ट की जानकारी संपादित करें", + "information": "जानकारी", + "image": "छवि", + "video": "वीडियो", + "updatePost": "पोस्ट अपडेट करें", + "postDeleted": "पोस्ट सफलतापूर्वक हटा दी गई.", + "postUpdated": "पोस्ट सफलतापूर्वक अपडेट किया गया.", + "tag": " आपका ब्राउज़र में वीडियो टैग समर्थित नहीं है", + "pin": "पिन पद" + }, + "blockUnblockUser": { + "title": "उपयोगकर्ता को ब्लॉक/अनब्लॉक करें", + "pageName": "ब्लॉक/अनब्लॉक करें", + "listOfUsers": "स्पैम भेजने वाले उपयोगकर्ताओं की सूची", + "block_unblock": "ब्लॉक/अनब्लॉक करें", + "unblock": "अनवरोधित", + "block": "अवरोध पैदा करना", + "orgName": "नाम दर्ज करें", + "blockedSuccessfully": "उपयोगकर्ता को सफलतापूर्वक अवरोधित किया गया", + "Un-BlockedSuccessfully": "उपयोगकर्ता को सफलतापूर्वक अन-अवरुद्ध किया गया", + "allMembers": "सभी सदस्य", + "blockedUsers": "रोके गए उपयोगकर्ता", + "searchByFirstName": "प्रथम नाम से खोजें", + "searchByLastName": "अंतिम नाम से खोजें", + "noSpammerFound": "कोई स्पैमर नहीं मिला" + }, + "eventManagement": { + "title": "इवेंट मैनेजमेंट", + "dashboard": "डैशबोर्ड", + "registrants": "कुलसचिव", + "eventActions": "घटना क्रियाएँ", + "eventStats": "घटना सांख्यिकी", + "to": "को" + }, + "forgotPassword": { + "title": "तलावा पासवर्ड भूल गए", + "registeredEmail": "पंजीकृत ईमेल", + "getOtp": "ओटीपी प्राप्त करें", + "enterOtp": "ओटीपी दर्ज करें", + "enterNewPassword": "नया पासवर्ड दर्ज करें", + "cofirmNewPassword": "नए पासवर्ड की पुष्टि करें", + "changePassword": "पासवर्ड बदलें", + "backToLogin": "लॉगिन पर वापस जाएं", + "userOtp": "जैसे ", + "emailNotRegistered": "ईमेल पंजीकृत नहीं है.", + "errorSendingMail": "मेल भेजने में त्रुटि.", + "passwordMismatches": "पासवर्ड और पासवर्ड बेमेल होने की पुष्टि करें।", + "passwordChanges": "पासवर्ड सफलतापूर्वक बदल गया.", + "OTPsent": "ओटीपी आपके पंजीकृत ईमेल पर भेजा जाता है।" + }, + "pageNotFound": { + "404": "404", + "title": "404 नहीं मिला", + "talawaAdmin": "तलावा प्रशासन", + "talawaUser": "तलावा उपयोगकर्ता", + "notFoundMsg": "उफ़! ", + "backToHome": "घर वापिस जा रहा हूँ" + }, + "orgContribution": { + "title": "तलावा योगदान", + "filterByName": "नाम से फ़िल्टर करें", + "filterByTransId": "ट्रांस द्वारा फ़िल्टर करें। ", + "recentStats": "हाल के आँकड़े", + "contribution": "योगदान", + "orgname": "नाम दर्ज करें", + "searchtransaction": "लेनदेन आईडी दर्ज करें" + }, + "contriStats": { + "recentContribution": "हालिया योगदान", + "highestContribution": "सर्वोच्च योगदान", + "totalContribution": "कुल योगदान" + }, + "orgContriCards": { + "date": "तारीख", + "transactionId": "लेन-देन आईडी", + "amount": "मात्रा" + }, + "orgSettings": { + "title": "समायोजन", + "general": "सामान्य", + "actionItemCategories": "कार्रवाई आइटम श्रेणियाँ", + "updateOrganization": "संगठन अद्यतन करें", + "seeRequest": "अनुरोध देखें", + "noData": "कोई डेटा नहीं", + "otherSettings": "अन्य सेटिंग", + "changeLanguage": "भाषा बदलें", + "manageCustomFields": "कस्टम फ़ील्ड प्रबंधित करें" + }, + "deleteOrg": { + "deleteOrganization": "संगठन हटाएँ", + "deleteSampleOrganization": "नमूना संगठन हटाएँ", + "deleteMsg": "क्या आप इस संगठन को हटाना चाहते हैं?", + "confirmDelete": "हटाने की पुष्टि करें", + "longDelOrgMsg": "संगठन हटाएं बटन पर क्लिक करने से संगठन अपने ईवेंट, टैग और सभी संबंधित डेटा के साथ स्थायी रूप से हटा दिया जाएगा।", + "successfullyDeletedSampleOrganization": "नमूना संगठन सफलतापूर्वक हटा दिया गया" + }, + "userUpdate": { + "appLanguageCode": "डिफ़ॉल्ट भाषा", + "userType": "उपयोगकर्ता का प्रकार" + }, + "userPasswordUpdate": { + "previousPassword": "पिछला पासवर्ड", + "newPassword": "नया पासवर्ड", + "confirmNewPassword": "नए पासवर्ड की पुष्टि करें" + }, + "orgDelete": { + "deleteOrg": "संगठन हटाएं" + }, + "membershipRequest": { + "accept": "स्वीकार करना", + "reject": "अस्वीकार करना", + "memberAdded": "यह स्वीकृत है" + }, + "orgUpdate": { + "city": "शहर", + "countryCode": "कंट्री कोड", + "line1": "लाइन 1", + "line2": "लाइन 2", + "postalCode": "डाक कोड", + "dependentLocality": "आश्रित इलाका", + "sortingCode": "कोड क्रमबद्ध करना", + "state": "राज्य/प्रान्त", + "userRegistrationRequired": "उपयोगकर्ता पंजीकरण आवश्यक", + "isVisibleInSearch": "खोज में दृश्यमान", + "enterNameOrganization": "संगठन का नाम दर्ज करें", + "successfulUpdated": "संगठन सफलतापूर्वक अद्यतन किया गया" + }, + "addOnRegister": { + "addNew": "नया जोड़ो", + "addPlugin": "प्लगइन जोड़ें", + "pluginName": "प्लगइन नाम", + "creatorName": "निर्माता का नाम", + "pluginDesc": "प्लगइन विवरण", + "pName": "उदाहरणार्थ: दान", + "cName": "उदाहरण: जॉन डो", + "pDesc": "यह प्लगइन यूआई को सक्षम बनाता है" + }, + "addOnStore": { + "title": "स्टोर पर जोड़ें", + "searchName": "उदाहरणार्थ: दान", + "enable": "सक्रिय", + "disable": "अक्षम", + "pHeading": "प्लग-इन", + "install": "स्थापित", + "available": "उपलब्ध", + "pMessage": "प्लगइन मौजूद नहीं है" + }, + "addOnEntry": { + "enable": "सक्रिय", + "install": "स्थापित करना", + "uninstall": "स्थापना रद्द करें", + "uninstallMsg": "यह सुविधा अब आपके संगठन से हटा दी गई है", + "installMsg": "यह सुविधा अब आपके संगठन में सक्षम है" + }, + "memberDetail": { + "title": "उपयोगकर्ता विवरण", + "addAdmin": "व्यवस्थापक जोड़ें", + "alreadyIsAdmin": "सदस्य पहले से ही एक व्यवस्थापक है", + "organizations": "संगठनों", + "events": "आयोजन", + "role": "भूमिका", + "createdOn": "पर बनाया", + "main": "मुख्य", + "firstName": "पहला नाम", + "lastName": "उपनाम", + "language": "भाषा", + "gender": "लिंग", + "birthDate": "जन्म तिथि", + "educationGrade": "शैक्षिक ग्रेड", + "employmentStatus": "रोज़गार की स्थिति", + "maritalStatus": "वैवाहिक स्थिति", + "phone": "फ़ोन", + "countryCode": "कंट्री कोड", + "state": "राज्य", + "city": "शहर", + "personalInfoHeading": "व्यक्तिगत जानकारी", + "contactInfoHeading": "संपर्क जानकारी", + "actionsHeading": "कार्रवाई", + "personalDetailsHeading": "प्रोफ़ाइल विवरण", + "appLanguageCode": "भाषा चुनें", + "deleteUser": "उपभोक्ता मिटायें", + "pluginCreationAllowed": "प्लगइन निर्माण की अनुमति दी गई", + "created": "बनाया था", + "adminForOrganizations": "संगठनों के लिए व्यवस्थापक", + "membershipRequests": "सदस्यता अनुरोध", + "adminForEvents": "घटनाओं के लिए व्यवस्थापक", + "addedAsAdmin": "उपयोगकर्ता को व्यवस्थापक के रूप में जोड़ा गया है.", + "userType": "उपयोगकर्ता का प्रकार" + }, + "userLogin": { + "login": "लॉग इन करें", + "loginIntoYourAccount": "अपने खाते में लॉगिन करें", + "invalidDetailsMessage": "कृपया एक वैध ईमेल और पासवर्ड दर्ज करें।", + "notAuthorised": "क्षमा मांगना! ", + "invalidCredentials": "दर्ज किए गए क्रेडेंशियल ग़लत हैं. " + }, + "userRegister": { + "enterFirstName": "अपना पहला नाम दर्ज करें", + "enterLastName": "अपना अंतिम नाम दर्ज करें", + "enterConfirmPassword": "पुष्टि करने के लिए अपना पासवर्ड दर्ज करें", + "alreadyhaveAnAccount": "क्या आपके पास पहले से एक खाता मौजूद है?", + "login": "लॉग इन करें", + "afterRegister": "पंजीकरण सफलतापूर्वक हो गया है। ", + "passwordNotMatch": "पासवर्ड मेल नहीं खाता. ", + "invalidDetailsMessage": "कृपया वैध विवरण दर्ज करें." + }, + "userNavbar": { + "talawa": "तलावा", + "home": "घर", + "people": "लोग", + "events": "आयोजन", + "chat": "बात करना", + "donate": "दान करें", + "language": "भाषा" + }, + "userOrganizations": { + "allOrganizations": "सभी संगठन", + "joinedOrganizations": "संगठनों से जुड़े", + "createdOrganizations": "संगठन बनाये", + "selectOrganization": "एक संगठन चुनें", + "searchUsers": "उपयोगकर्ता खोजें", + "nothingToShow": "यहां दिखाने के लिए कुछ भी नहीं है.", + "organizations": "संगठनों" + }, + "userSidebarOrg": { + "yourOrganizations": "आपके संगठन", + "noOrganizations": "आप अभी तक किसी संगठन में शामिल नहीं हुए हैं.", + "viewAll": "सभी को देखें", + "talawaUserPortal": "तलावा उपयोगकर्ता पोर्टल", + "my organizations": "मेरे संगठन", + "communityProfile": "सामुदायिक प्रोफ़ाइल" + }, + "organizationSidebar": { + "viewAll": "सभी को देखें", + "events": "आयोजन", + "noEvents": "दिखाने के लिए कोई ईवेंट नहीं", + "noMembers": "दिखाने के लिए कोई सदस्य नहीं" + }, + "postCard": { + "likes": "पसंद है", + "comments": "टिप्पणियाँ" + }, + "home": { + "posts": "पदों", + "post": "डाक", + "title": "शीर्षक", + "textArea": "आपके मन में कुछ है?", + "feed": "खिलाना", + "loading": "लोड हो रहा है", + "pinnedPosts": "चिपके पत्र", + "yourFeed": "आपका फ़ीड", + "nothingToShowHere": "यहां दिखाने के लिए कुछ भी नहीं है", + "somethingOnYourMind": "आपके मन में कुछ है?", + "addPost": "पोस्ट जोड़ें", + "startPost": "एक पोस्ट प्रारंभ करें", + "media": "मिडिया", + "event": "आयोजन", + "article": "लेख" + }, + "settings": { + "profileSettings": "पार्श्वचित्र समायोजन", + "gender": "लिंग", + "phoneNumber": "फ़ोन नंबर", + "chooseFile": "फाइलें चुनें", + "birthDate": "जन्म तिथि", + "grade": "शैक्षिक ग्रेड", + "empStatus": "रोज़गार की स्थिति", + "maritalStatus": "वैवाहिक स्थिति", + "state": "शहरी स्थान", + "country": "देश", + "resetChanges": "परिवर्तन रीसेट करें", + "profileDetails": "प्रोफ़ाइल विवरण", + "deleteUserMessage": "डिलीट यूजर बटन पर क्लिक करने से आपका यूजर अपने इवेंट, टैग और सभी संबंधित डेटा के साथ स्थायी रूप से हटा दिया जाएगा।", + "copyLink": "प्रोफ़ाइल लिंक कॉपी करें", + "deleteUser": "उपभोक्ता मिटायें", + "otherSettings": "अन्य सेटिंग", + "changeLanguage": "भाषा बदलें", + "sgender": "लिंग चुनें", + "gradePlaceholder": "ग्रेड दर्ज करें", + "sEmpStatus": "रोजगार की स्थिति चुनें", + "female": "महिला", + "male": "पुरुष", + "employed": "कार्यरत", + "other": "अन्य", + "sMaritalStatus": "वैवाहिक स्थिति चुनें", + "unemployed": "बेरोज़गार", + "married": "विवाहित", + "single": "अकेला", + "widowed": "विधवा", + "divorced": "तलाकशुदा", + "engaged": "काम में लगा हुआ", + "seperated": "विभाजित", + "grade1": "ग्रेड 1", + "grade2": "ग्रेड 2", + "grade3": "ग्रेड 3", + "grade4": "ग्रेड 4", + "grade5": "ग्रेड 5", + "grade6": "वर्ग 6", + "grade7": "श्रेणी 7", + "grade8": "कक्षा 8", + "grade9": "श्रेणी 9", + "grade10": "ग्रेड 10", + "grade11": "ग्रेड 11", + "grade12": "कक्षा 12", + "graduate": "स्नातक", + "kg": "किलोग्राम", + "preKg": "पूर्व केजी", + "noGrade": "कोई ग्रेड नहीं", + "fullTime": "पूरा समय", + "partTime": "पार्ट टाईम", + "selectCountry": "कोई देश चुनें", + "enterState": "शहर या राज्य दर्ज करें" + }, + "donate": { + "donations": "दान", + "searchDonations": "दान खोजें", + "donateForThe": "के लिए दान करें", + "amount": "मात्रा", + "yourPreviousDonations": "आपका पिछला दान", + "donate": "दान करें", + "nothingToShow": "यहां दिखाने के लिए कुछ भी नहीं है.", + "success": "दान सफल" + }, + "userEvents": { + "nothingToShow": "यहां दिखाने के लिए कुछ भी नहीं है.", + "createEvent": "कार्यक्रम बनाएँ", + "recurring": "पुनरावर्ती ईवेंट", + "startTime": "समय शुरू", + "endTime": "अंत समय", + "listView": "लिस्ट व्यू", + "calendarView": "कैलेंडर दृश्य", + "allDay": "पूरे दिन", + "eventCreated": "ईवेंट सफलतापूर्वक बनाया और पोस्ट किया गया.", + "eventDetails": "घटना की जानकारी", + "eventTitle": "शीर्षक", + "enterTitle": "शीर्षक दर्ज करें", + "enterDescription": "विवरण दर्ज करें", + "enterLocation": "स्थान दर्ज करें", + "publicEvent": "सार्वजनिक है", + "registerable": "पंजीकरण योग्य है", + "monthlyCalendarView": "मासिक कैलेंडर", + "yearlyCalendarView": "वार्षिक कैलेंडर" + }, + "userEventCard": { + "starts": "प्रारंभ होगा", + "ends": "समाप्त होता है", + "creator": "निर्माता", + "alreadyRegistered": "पहले से ही पंजीकृत" + }, + "advertisement": { + "title": "विज्ञापनों", + "activeAds": "सक्रिय अभियान", + "archievedAds": "पूर्ण अभियान", + "pMessage": "इस अभियान के लिए विज्ञापन मौजूद नहीं हैं.", + "validLink": "लिंक मान्य है", + "invalidLink": "लिंक अमान्य है", + "Rname": "विज्ञापन का नाम दर्ज करें", + "Rtype": "विज्ञापन का प्रकार चुनें", + "Rmedia": "प्रदर्शित करने के लिए मीडिया सामग्री प्रदान करें", + "RstartDate": "आरंभ तिथि चुनें", + "RendDate": "अंतिम तिथि चुनें", + "RClose": "खिड़की बंद करो", + "addNew": "नया विज्ञापन बनाएं", + "EXname": "पूर्व। ", + "EXlink": "पूर्व। ", + "createAdvertisement": "विज्ञापन बनाएं", + "deleteAdvertisement": "विज्ञापन हटाएँ", + "deleteAdvertisementMsg": "क्या आप यह विज्ञापन हटाना चाहते हैं?", + "view": "देखना", + "editAdvertisement": "विज्ञापन संपादित करें" + }, + "userChat": { + "chat": "बात करना", + "contacts": "संपर्क" + }, + "userChatRoom": { + "selectContact": "बातचीत शुरू करने के लिए एक संपर्क चुनें", + "sendMessage": "मेसेज भेजें" + }, + "orgProfileField": { + "loading": "लोड हो रहा है...", + "noCustomField": "कोई कस्टम फ़ील्ड उपलब्ध नहीं है", + "customFieldName": "कार्यक्षेत्र नाम", + "enterCustomFieldName": "फ़ील्ड नाम दर्ज करें", + "customFieldType": "क्षेत्र प्रकार", + "Remove Custom Field": "कस्टम फ़ील्ड हटाएँ", + "fieldSuccessMessage": "फ़ील्ड सफलतापूर्वक जोड़ा गया", + "fieldRemovalSuccess": "फ़ील्ड सफलतापूर्वक हटा दी गई" + }, + "orgActionItemCategories": { + "enableButton": "सक्षम", + "disableButton": "अक्षम करना", + "updateActionItemCategory": "अद्यतन", + "actionItemCategoryName": "नाम", + "actionItemCategoryDetails": "कार्य आइटम श्रेणी विवरण", + "enterName": "नाम दर्ज करें", + "successfulCreation": "कार्रवाई आइटम श्रेणी सफलतापूर्वक बनाई गई", + "successfulUpdation": "कार्रवाई आइटम श्रेणी सफलतापूर्वक अपडेट की गई", + "sameNameConflict": "अपडेट करने के लिए कृपया नाम बदलें", + "categoryEnabled": "कार्य आइटम श्रेणी सक्षम", + "categoryDisabled": "कार्रवाई आइटम श्रेणी अक्षम" + }, + "organizationVenues": { + "title": "स्थानों", + "addVenue": "स्थान जोड़ें", + "venueDetails": "स्थल विवरण", + "venueName": "आयोजन स्थल का नाम", + "enterVenueName": "स्थान का नाम दर्ज करें", + "enterVenueDesc": "स्थान विवरण दर्ज करें", + "capacity": "क्षमता", + "enterVenueCapacity": "स्थान क्षमता दर्ज करें", + "image": "स्थल छवि", + "uploadVenueImage": "स्थल छवि अपलोड करें", + "createVenue": "स्थान बनाएँ", + "venueAdded": "स्थान सफलतापूर्वक जोड़ा गया", + "editVenue": "स्थान अद्यतन करें", + "venueUpdated": "स्थान विवरण सफलतापूर्वक अपडेट किया गया", + "sort": "क्रम से लगाना", + "highestCapacity": "उच्चतम क्षमता", + "lowestCapacity": "सबसे कम क्षमता", + "noVenues": "कोई स्थान नहीं मिला!", + "view": "देखना", + "venueTitleError": "स्थान का शीर्षक खाली नहीं हो सकता!", + "venueCapacityError": "क्षमता एक धनात्मक संख्या होनी चाहिए!", + "searchBy": "खोज से" + }, + "addMember": { + "title": "सदस्य जोड़ें", + "addMembers": "सदस्य जोड़ें", + "existingUser": "मौजूदा उपयोगकर्ता", + "newUser": "नए उपयोगकर्ता", + "searchFullName": "पूरे नाम से खोजें", + "enterFirstName": "प्रथम नाम दर्ज करें", + "enterLastName": "अंतिम नाम दर्ज करो", + "enterConfirmPassword": "पासवर्ड की पुष्टि करें दर्ज करें", + "organization": "संगठन", + "invalidDetailsMessage": "कृपया सभी आवश्यक विवरण प्रदान करें।", + "passwordNotMatch": "सांकेतिक शब्द मेल नहीं खाते।", + "addMember": "सदस्य जोड़ें" + }, + "eventActionItems": { + "title": "एक्शन आइटम्स", + "createActionItem": "एक्शन आइटम बनाएं", + "actionItemCategory": "कार्य आइटम श्रेणी", + "selectActionItemCategory": "एक क्रिया आइटम श्रेणी का चयन करें", + "selectAssignee": "एक समनुदेशिती का चयन करें", + "preCompletionNotes": "समापन पूर्व नोट्स", + "postCompletionNotes": "समापन के बाद के नोट्स", + "actionItemDetails": "कार्रवाई मद विवरण", + "dueDate": "नियत तारीख", + "completionDate": "पूरा करने की तिथि", + "editActionItem": "क्रिया आइटम संपादित करें", + "deleteActionItem": "क्रिया आइटम हटाएँ", + "deleteActionItemMsg": "क्या आप इस क्रिया आइटम को हटाना चाहते हैं?", + "successfulDeletion": "कार्रवाई आइटम सफलतापूर्वक हटा दिया गया", + "successfulCreation": "कार्रवाई आइटम सफलतापूर्वक बनाया गया", + "successfulUpdation": "कार्रवाई आइटम सफलतापूर्वक अपडेट किया गया", + "notes": "टिप्पणियाँ", + "save": "बचाना" + } +} diff --git a/public/locales/sp/common.json b/public/locales/sp/common.json new file mode 100644 index 0000000000..dfd1a960bd --- /dev/null +++ b/public/locales/sp/common.json @@ -0,0 +1,65 @@ +{ + "firstName": "First Name", + "lastName": "Last Name", + "searchByName": "Search By Name", + "loading": "Loading...", + "endOfResults": "End of results", + "noResultsFoundFor": "No results found for ", + "edit": "Edit", + "admins": "Admins", + "admin": "ADMIN", + "user": "USER", + "superAdmin": "SUPERADMIN", + "members": "Members", + "logout": "Logout", + "login": "Login", + "register": "Register", + "menu": "Menu", + "settings": "Settings", + "users": "Users", + "requests": "Requests", + "OR": "OR", + "cancel": "Cancel", + "close": "Close", + "create": "Create", + "delete": "Delete", + "done": "Done", + "yes": "Yes", + "no": "No", + "filter": "Filter", + "search": "Search", + "description": "Description", + "saveChanges": "Save Changes", + "displayImage": "Display Image", + "enterEmail": "Enter Email", + "emailAddress": "Email Address", + "email": "Email", + "name": "Name", + "enterPassword": "Enter Password", + "password": "Password", + "confirmPassword": "Confirm Password", + "forgotPassword": "Forgot Password ?", + "talawaAdminPortal": "Talawa Admin Portal", + "address": "Address", + "location": "Location", + "enterLocation": "Enter Location", + "joined": "Joined", + "startDate": "Start Date", + "endDate": "End Date", + "startTime": "Start Time", + "endTime": "End Time", + "My Organizations": "Mis Organizaciones", + "Dashboard": "Tablero", + "People": "Gente", + "Events": "Eventos", + "Venues": "Lugares", + "Action Items": "Elementos de Acción", + "Posts": "Publicaciones", + "Block/Unblock": "Bloquear/Desbloquear", + "Advertisement": "Publicidad", + "Funds": "Fondos", + "Membership Requests": "Solicitudes de Membresía", + "Plugins": "Complementos", + "Plugin Store": "Tienda de Complementos", + "Settings": "Configuraciones" +} diff --git a/public/locales/sp/errors.json b/public/locales/sp/errors.json new file mode 100644 index 0000000000..90b2acca9f --- /dev/null +++ b/public/locales/sp/errors.json @@ -0,0 +1,9 @@ +{ + "talawaApiUnavailable": "Talawa-API service is unavailable!. Is it running? Check your network connectivity too.", + "notFound": "Not found", + "unknownError": "An unknown error occurred. Please try again later. {{msg}}", + "notAuthorised": "Sorry! you are not Authorised!", + "errorSendingMail": "Error sending mail", + "emailNotRegistered": "Email not registered", + "notFoundMsg": "Oops! The Page you requested was not found!" +} diff --git a/public/locales/sp.json b/public/locales/sp/translation.json similarity index 100% rename from public/locales/sp.json rename to public/locales/sp/translation.json diff --git a/public/locales/zh.json b/public/locales/zh.json deleted file mode 100644 index d105c830bd..0000000000 --- a/public/locales/zh.json +++ /dev/null @@ -1,1138 +0,0 @@ -{ - "loginPage": { - "title": "塔拉瓦管理員", - "fromPalisadoes": "柵欄 基金会志愿者的开源应用程序", - "talawa_portal": "塔拉瓦管理門戶", - "login": "登錄", - "userLogin": "用户登录", - "register": "登記", - "firstName": "名", - "lastName": "姓", - "email": "電子郵件", - "password": "密碼", - "atleast_8_char_long": "至少 8 個字符長", - "atleast_6_char_long": "至少 6 個字元長", - "firstName_invalid": "名字只能包含小寫和大寫字母", - "lastName_invalid": "姓氏只能包含小寫和大寫字母", - "password_invalid": "密碼應至少包含1個小寫字母、1個大寫字母、1個數字和1個特殊字符", - "email_invalid": "電子郵件應至少包含 8 個字符", - "Password_and_Confirm_password_mismatches.": "密碼和確認密碼不匹配。", - "confirmPassword": "確認密碼", - "forgotPassword": "忘記密碼 ?", - "enterEmail": "输入电子邮件", - "enterPassword": "输入密码", - "doNotOwnAnAccount": "沒有帳戶嗎?", - "talawaApiUnavailable": "服務不可用。它正在運行嗎?還要檢查您的網絡連接。", - "captchaError": "驗證碼錯誤!", - "Please_check_the_captcha": "請檢查驗證碼。", - "Something_went_wrong": "出了點問題,請稍後再試。", - "passwordMismatches": "密碼和確認密碼不匹配。", - "fillCorrectly": "正確填寫所有細節。", - "notAuthorised": "抱歉!你沒有被授權!", - "notFound": "找不到用戶!", - "successfullyRegistered": "註冊成功,請等待審核通過。", - "OR": "或者", - "admin": "行政", - "user": "用戶", - "lowercase_check": "至少一個小寫字母", - "uppercase_check": "至少有一個大寫字母", - "numeric_value_check": "至少一個數值", - "special_char_check": "至少一個特殊字符", - "loading": "载入中...", - "selectOrg": "选择一个组织", - "afterRegister": "注册成功。请等待管理员批准您的请求" - }, - "userLoginPage": { - "title": "塔拉瓦管理員", - "fromPalisadoes": "柵欄 基金会志愿者的开源应用程序", - "talawa_portal": "塔拉瓦管理門戶", - "login": "登錄", - "register": "登記", - "firstName": "名", - "lastName": "姓", - "email": "電子郵件", - "password": "密碼", - "atleast_8_char_long": "至少 8 個字符長", - "Password_and_Confirm_password_mismatches.": "密碼和確認密碼不匹配。", - "confirmPassword": "確認密碼", - "forgotPassword": "忘記密碼 ?", - "enterEmail": "输入电子邮件", - "enterPassword": "输入密码", - "doNotOwnAnAccount": "沒有帳戶嗎?", - "talawaApiUnavailable": "服務不可用。它正在運行嗎?還要檢查您的網絡連接。", - "captchaError": "驗證碼錯誤!", - "Please_check_the_captcha": "請檢查驗證碼。", - "Something_went_wrong": "出了點問題,請稍後再試。", - "passwordMismatches": "密碼和確認密碼不匹配。", - "fillCorrectly": "正確填寫所有細節。", - "notAuthorised": "抱歉!你沒有被授權!", - "notFound": "找不到用戶!", - "successfullyRegistered": "註冊成功,請等待審核通過。", - "userLogin": "用户登录", - "afterRegister": "註冊成功。 請等待管理員批准您的請求。", - "OR": "或者", - "loading": "载入中...", - "selectOrg": "选择一个组织" - }, - "latestEvents": { - "eventCardTitle": "即将举行的活动", - "eventCardSeeAll": "查看全部", - "noEvents": "暂无即将举行的活动" - }, - "latestPosts": { - "latestPostsTitle": "最新文章", - "seeAllLink": "查看全部", - "noPostsCreated": "暂无文章" - }, - "listNavbar": { - "talawa_portal": "塔拉瓦管理門戶", - "roles": "角色", - "requests": "要求", - "logout": "登出" - }, - "leftDrawer": { - "talawaAdminPortal": "塔拉瓦管理门户", - "menu": "菜单", - "my organizations": "我的组织", - "users": "用户", - "requests": "请求", - "communityProfile": "社区简介", - "logout": "退出登录" - }, - "leftDrawerOrg": { - "talawaAdminPortal": "塔拉瓦管理门户", - "menu": "菜单", - "talawa_portal": "塔拉瓦管理門戶", - "Dashboard": "儀表板", - "People": "人們", - "Events": "事件", - "Contributions": "貢獻", - "Posts": "帖子", - "Block/Unblock": "阻止/解除阻止", - "Plugins": "插件", - "Plugin Store": "插件商店", - "allOrganizations": "所有组织", - "yourOrganization": "您的组织", - "notification": "通知", - "settings": "設置", - "language": "語", - "logout": "登出", - "notifications": "通知", - "spamsThe": "垃圾郵件", - "group": "團體", - "noNotifications": "沒有通知", - "close": "關" - }, - "funds": { - "title": "资金", - "createFund": "创建基金", - "fundName": "基金名称", - "fundId": "基金ID", - "fundOptions": "选项", - "noFunds": "未找到基金", - "fundDetails": "基金详情", - "taxDeductible": "允许税收扣除", - "enterfundName": " 输入基金名称", - "enterfundId": "输入基金ID", - "default": "默认基金", - "archived": "已归档", - "nonArchive": "未归档", - "fundCreate": "创建基金", - "fundUpdate": "更新基金", - "fundDelete": "删除基金", - "no": "否", - "yes": "是", - "manageFund": "管理基金", - "searchFullName": "按姓名搜索", - "filter": "筛选", - "noFundsFound": "找不到资金", - "createdBy": "创建人", - "createdOn": "创建日期", - "status": "状态", - "archiveFund": "归档基金", - "archiveFundMsg": "您是否要归档此基金?", - "fundCreated": "基金创建成功", - "fundUpdated": "基金更新成功", - "fundDeleted": "基金删除成功", - "fundArchived": "基金已归档", - "fundUnarchived": "基金未归档", - "deleteFundMsg": "您是否要删除此基金?" - }, - "fundCampaign": { - "title": "筹款活动", - "campaignName": "活动名称", - "startDate": "开始日期", - "endDate": "结束日期", - "campaignOptions": "活动选项", - "fundingGoal": "筹款目标", - "addCampaign": "添加活动", - "createdCampaign": "活动创建成功", - "updatedCampaign": "活动更新成功", - "deletedCampaign": "活动删除成功", - "deleteCampaignMsg": "您确定要删除此活动吗", - "noCampaigns": "未找到活动", - "createCampaign": "创建筹款活动", - "updateCampaign": "更新筹款活动", - "manageCampaign": "管理筹款活动", - "deleteCampaign": "删除筹款活动", - "no": "没有", - "yes": "是", - "currency": "货币", - "selectCurrency": "选择货币", - "filter": "筛选", - "searchFullName": "按姓名搜索" - }, - "pledges": { - "title": "资金筹款承诺", - "volunteers": "志愿者", - "startDate": "开始日期", - "endDate": "结束日期", - "pledgeAmount": "承诺金额", - "pledgeOptions": "选项", - "pledgeCreated": "承诺成功创建", - "pledgeUpdated": "承诺成功更新", - "pledgeDeleted": "承诺成功删除", - "addPledge": "添加承诺", - "createPledge": "创建承诺", - "currency": "货币", - "selectCurrency": "选择货币", - "updatePledge": "更新承诺", - "deletePledge": "删除承诺", - "amount": "数量", - "editPledge": "编辑承诺", - "deletePledgeMsg": "您确定要删除此承诺吗?", - "no": "否", - "yes": "是", - "noPledges": "未找到承诺" - }, - "orgList": { - "title": "塔拉瓦組織", - "you": "你", - "name": "姓名", - "designation": "指定", - "email": "電子郵件", - "searchByName": "按名稱搜索", - "my organizations": "我的组织", - "createOrganization": "創建組織", - "createSampleOrganization": "创建示范组织", - "description": "描述", - "location": "地點", - "address": "地址", - "city": "城市", - "countryCode": "国家代码", - "line1": "地址行 1", - "line2": "地址行 2", - "postalCode": "邮政编码", - "dependentLocality": "从属地区", - "sortingCode": "排序代码", - "state": "省 / 直辖市", - "isPubluserRegistrationRequiredic": "需要用户注册", - "visibleInSearch": "在搜索中可見", - "displayImage": "顯示圖像", - "enterName": "输入名字", - "sort": "排序", - "Earliest": "最早的", - "Latest": "最新的", - "filter": "過濾", - "cancel": "取消", - "endOfResults": "結果結束", - "noOrgErrorTitle": "找不到组织", - "sampleOrgDuplicate": "只允许一个样本组织", - "noOrgErrorDescription": "请通过仪表板创建一个组织", - "noResultsFoundFor": "未找到结果 ", - "OR": "或者", - "sampleOrgSuccess": "示例组织成功创建" - }, - "orgListCard": { - "admins": "管理員", - "members": "成員", - "manage": "管理", - "sampleOrganization": "示例组织" - }, - "paginationList": { - "rowsPerPage": "每頁行數", - "all": "全部" - }, - "requests": { - "title": "请求", - "sl_no": "序号", - "name": "姓名", - "email": "电子邮件", - "accept": "接受", - "reject": "拒绝", - "searchRequests": "搜索请求", - "endOfResults": "结果结束", - "noOrgError": "找不到组织,请通过仪表板创建组织", - "noResultsFoundFor": "未找到结果 ", - "noRequestsFound": "未找到请求", - "acceptedSuccessfully": "请求成功接受", - "rejectedSuccessfully": "请求成功拒绝", - "noOrgErrorTitle": "找不到组织", - "noOrgErrorDescription": "请通过仪表板创建一个组织" - }, - "users": { - "title": "塔拉瓦角色", - "searchByName": "按名稱搜索", - "users": "用户", - "name": "姓名", - "email": "電子郵件", - "joined_organizations": "加入的組織", - "blocked_organizations": "阻止的組織", - "endOfResults": "結果結束", - "orgJoinedBy": "加入組織", - "orgThatBlocked": "阻止組織", - "hasNotJoinedAnyOrg": "尚未加入任何組織", - "isNotBlockedByAnyOrg": "沒有被任何組織阻止", - "searchByOrgName": "按組織名稱搜索", - "view": "視圖", - "admin": "行政", - "superAdmin": "超級管理員", - "user": "用戶", - "enterName": "输入名字", - "loadingUsers": "正在加載用戶...", - "noUserFound": "找不到用戶。", - "sort": "排序", - "Oldest": "最旧的优先", - "Newest": "最新的优先", - "filter": "過濾", - "roleUpdated": "角色已更新。", - "noResultsFoundFor": "未找到结果 ", - "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。", - "cancel": "取消", - "admins": "管理員", - "members": "成員", - "joinNow": "现在加入", - "visit": "加入访问", - "withdraw": "提取", - "orgJoined": "成功加入组织", - "MembershipRequestSent": "会员申请已成功发送", - "AlreadyJoined": "您已经是该组织的成员。", - "errorOccured": "发生错误,请稍后重试。" - }, - "communityProfile": { - "title": "社区简介", - "editProfile": "编辑个人资料", - "communityProfileInfo": "这些详细信息将显示在您和您的社区成员的登录/注册屏幕上", - "communityName": "社区名字", - "wesiteLink": "网站链接", - "logo": "标识", - "social": "社交媒体链接", - "url": "输入网址", - "profileChangedMsg": "已成功更新个人资料详细信息。", - "resetData": "成功重置个人资料详细信息。" - }, - "dashboard": { - "title": "儀表板", - "location": "地點", - "about": "關於", - "deleteThisOrganization": "刪除此組織", - "statistics": "統計數據", - "members": "成員", - "admins": "管理員", - "posts": "帖子", - "events": "事件", - "blockedUsers": "被阻止的用戶", - "requests": "请求", - "viewAll": "查看全部", - "upcomingEvents": "即将举办的活动", - "noUpcomingEvents": "没有即将举办的活动", - "latestPosts": "最新帖子", - "noPostsPresent": "没有帖子", - "membershipRequests": "会员申请", - "noMembershipRequests": "没有会员申请", - "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。" - }, - "organizationPeople": { - "title": "塔拉瓦成員", - "filterByName": "按名稱過濾", - "filterByLocation": "按位置過濾", - "filterByEvent": "按事件過濾", - "members": "成員", - "admins": "管理員", - "users": "用戶", - "searchName": "輸入名字", - "searchevent": "輸入事件", - "searchFirstName": "输入名字", - "searchLastName": "输入姓氏", - "people": "人", - "sort": "按角色搜索", - "actions": "操作", - "existingUser": "现有用户", - "newUser": "新用户", - "firstName": "名", - "enterFirstName": "輸入您的名字", - "lastName": "姓", - "enterLastName": "輸入您的姓氏", - "emailAddress": "電子郵件地址", - "enterEmail": "輸入你的電子郵箱地址", - "password": "密碼", - "enterPassword": "輸入您的密碼", - "confirmPassword": "確認密碼", - "enterConfirmPassword": "輸入您的密碼以確認", - "organization": "組織", - "create": "創造", - "cancel": "取消", - "invalidDetailsMessage": "請輸入有效的詳細信息。" - }, - "userListCard": { - "joined": "加入", - "addAdmin": "添加管理員", - "addedAsAdmin": "用戶被添加為管理員。", - "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。" - }, - "orgAdminListCard": { - "joined": "加入", - "remove": "消除", - "removeAdmin": "刪除管理員", - "removeAdminMsg": "您要刪除此管理員嗎?", - "no": "不", - "yes": "是的", - "adminRemoved": "管理員被刪除。", - "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。" - }, - "orgPeopleListCard": { - "joined": "加入", - "remove": "消除", - "removeMember": "刪除成員", - "removeMemberMsg": "您要刪除此成員嗎?", - "no": "不", - "yes": "是的", - "memberRemoved": "該會員已被刪除", - "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。" - }, - "organizationEvents": { - "title": "活动", - "filterByTitle": "按標題過濾", - "filterByLocation": "按位置過濾", - "filterByDescription": "按描述過濾", - "events": "事件", - "addEvent": "添加事件", - "eventDetails": "活動詳情", - "eventTitle": "標題", - "description": "描述", - "location": "地點", - "startDate": "開始日期", - "endDate": "結束日期", - "startTime": "開始時間", - "endTime": "時間結束", - "allDay": "一整天", - "recurringEvent": "重複事件", - "isPublic": "是公開的", - "isRegistrable": "可註冊", - "createEvent": "創建事件", - "enterFilter": "輸入過濾器", - "enterTitle": "輸入標題", - "enterDescrip": "輸入說明", - "eventLocation": "輸入位置", - "eventCreated": "恭喜!事件已創建。", - "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。", - "searchEventName": "搜索活动名称", - "eventType": "活动类型", - "customRecurrence": "自定义重复", - "repeatsEvery": "重复每", - "repeatsOn": "重复于", - "ends": "结束", - "never": "永不", - "on": "于", - "after": "之后", - "occurences": "次数", - "done": "完成" - }, - "organizationActionItems": { - "actionItemCategory": "行动项目类别", - "actionItemActive": "活动措施项", - "actionItemCompleted": "已完成操作项", - "actionItemDetails": "行动项目详情", - "actionItemStatus": "措施项状态", - "assignee": "受让人", - "assigner": "分配者", - "assignmentDate": "分配日期", - "active": "活跃", - "clearFilters": "清除筛选器", - "close": "关闭", - "completed": "已完成", - "completionDate": "完成日期", - "createActionItem": "创建", - "deleteActionItem": "删除行动项目", - "deleteActionItemMsg": "您是否要删除此行动项目?", - "details": "详情", - "dueDate": "到期日", - "earliest": "最早", - "editActionItem": "编辑行动项目", - "eventActionItems": "事件操作项", - "isCompleted": "已完成", - "latest": "最新", - "makeActive": "激活", - "markCompletion": "标记完成", - "no": "否", - "noActionItems": "无行动项目", - "options": "选项", - "preCompletionNotes": "完成前的笔记", - "postCompletionNotes": "完成后的笔记", - "searchByName": "按名称搜索", - "selectActionItemCategory": "选择行动项目类别", - "selectAssignee": "选择受让人", - "status": "状态", - "successfulCreation": "行动项目创建成功", - "successfulUpdation": "行动项目更新成功", - "successfulDeletion": "行动项目删除成功", - "title": "行动项目", - "yes": "是" - }, - "eventListCard": { - "location": "活動地點", - "deleteEvent": "刪除事件", - "deleteEventMsg": "您要刪除此活動嗎?", - "no": "不", - "yes": "是的", - "editEvent": "編輯事件", - "eventTitle": "標題", - "description": "描述", - "startDate": "开始日期", - "endDate": "结束日期", - "registerEvent": "登記", - "alreadyRegistered": "已經註冊", - "startTime": "開始時間", - "endTime": "時間結束", - "allDay": "一整天", - "recurringEvent": "重複事件", - "isPublic": "是公開的", - "isRegistrable": "可註冊", - "close": "關", - "updatePost": "更新帖子", - "eventDetails": "活動詳情", - "eventDeleted": "活动删除成功。", - "eventUpdated": "活動更新成功。", - "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。", - "thisInstance": "此实例", - "thisAndFollowingInstances": "此及其后续实例", - "allInstances": "所有实例", - "customRecurrence": "自定义重复", - "repeatsEvery": "重复每", - "repeatsOn": "重复于", - "ends": "结束", - "never": "永不", - "on": "于", - "after": "之后", - "occurences": "次数", - "done": "完成" - }, - "orgPost": { - "title": "塔拉瓦帖子", - "searchPost": "搜索帖子", - "posts": "帖子", - "createPost": "创建帖子", - "postDetails": "帖子详情", - "postTitle1": "填写帖子标题", - "postTitle": "标题", - "addMedia": "上传照片或视频", - "information": "信息", - "information1": "填写帖子信息", - "addPost": "添加帖子", - "searchTitle": "按标题搜索", - "searchText": "按文本搜索", - "ptitle": "帖子标题", - "postDes": "您想讨论什么?", - "Title": "标题", - "Text": "文本", - "cancel": "取消", - "searchBy": "按方式搜索", - "Oldest": "最旧的优先", - "Latest": "最新的优先", - "sortPost": "排序帖子", - "tag": "您的浏览器不支持视频标签", - "postCreatedSuccess": "恭喜!您已经发布了一些内容。", - "pinPost": "针柱", - "Next": "下一页", - "Previous": "上一页" - }, - "postNotFound": { - "post": "郵政", - "not found!": "未找到!", - "organization": "組織", - "post not found!": "郵政 未找到!", - "organization not found!": "組織 未找到!" - }, - "userNotFound": { - "user": "用户", - "not found!": "未找到!", - "roles": "角色", - "user not found!": "找不到用户!", - "member not found!": "找不到会员!", - "admin not found!": "找不到管理员!", - "roles not found!": "找不到角色!" - }, - "orgPostCard": { - "author": "作者", - "imageURL": "图像链接", - "videoURL": "视频链接", - "edit": "编辑帖子", - "deletePost": "删除帖子", - "deletePostMsg": "您确定要删除此帖子吗?", - "no": "否", - "yes": "是", - "editPost": "编辑帖子", - "postTitle": "标题", - "postTitle1": "編輯貼文標題", - "information1": "編輯貼文訊息", - "information": "信息", - "image": "图片", - "video": "视频", - "close": "关闭", - "pin": "置顶帖子", - "updatePost": "更新帖子", - "postDeleted": "帖子成功删除。", - "postUpdated": "帖子成功更新。", - "tag": "您的浏览器不支持视频标签", - "talawaApiUnavailable": "Talawa-API 服务不可用。是否正在运行?还请检查您的网络连接。" - }, - "blockUnblockUser": { - "title": "塔拉瓦封鎖/解除封鎖用戶", - "pageName": "封锁/解封", - "searchByName": "按名稱搜索", - "listOfUsers": "發送垃圾郵件的用戶列表", - "name": "姓名", - "email": "電子郵件", - "block_unblock": "阻止/解除阻止", - "unblock": "解除封鎖", - "block": "堵塞", - "orgName": "輸入名字", - "blockedSuccessfully": "用戶被成功阻止", - "Un-BlockedSuccessfully": "用戶解封成功", - "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。", - "allMembers": "所有成员", - "blockedUsers": "被阻止的用户", - "searchByFirstName": "按名字搜索", - "searchByLastName": "按姓氏搜索", - "noResultsFoundFor": "未找到结果 ", - "noSpammerFound": "未发现垃圾邮件发送者" - }, - "eventManagement": { - "title": "事件管理", - "dashboard": "仪表板", - "registrants": "注册参与者", - "eventActions": "事件操作", - "eventStats": "事件统计", - "to": "到" - }, - "forgotPassword": { - "title": "塔拉瓦忘記密碼", - "forgotPassword": "忘記密碼", - "registeredEmail": "註冊的電子郵件", - "getOtp": "獲取一次性密碼", - "enterOtp": "輸入一次性密碼", - "enterNewPassword": "輸入新密碼", - "cofirmNewPassword": "確認新密碼", - "changePassword": "更改密碼", - "backToLogin": "回到登錄", - "userOtp": "舉個例子。 12345", - "password": "密碼", - "emailNotRegistered": "電子郵件未註冊。", - "talawaApiUnavailable": "服務不可用。它正在運行嗎?還要檢查您的網絡連接。", - "errorSendingMail": "發送郵件時出錯。", - "passwordMismatches": "密碼和確認密碼不匹配。", - "passwordChanges": "密碼修改成功。", - "OTPsent": "已發送到您的註冊郵箱。" - }, - "pageNotFound": { - "title": "404 未找到", - "talawaAdmin": "塔拉瓦管理員", - "talawaUser": "塔拉瓦用戶", - "404": "404", - "notFoundMsg": "糟糕!找不到您請求的頁面!", - "backToHome": "回到家" - }, - "orgContribution": { - "title": "塔拉瓦貢獻", - "filterByName": "按名稱過濾", - "filterByTransId": "按 Trans.ID 過濾", - "recentStats": "最近的統計", - "contribution": "貢獻", - "orgname": "輸入名字", - "searchtransaction": "輸入交易編號" - }, - "contriStats": { - "recentContribution": "最近的貢獻", - "highestContribution": "最高貢獻", - "totalContribution": "總貢獻" - }, - "orgContriCards": { - "date": "日期", - "transactionId": "交易 ID", - "amount": "數量" - }, - "orgSettings": { - "title": "塔拉瓦設置", - "pageName": "设置", - "general": "一般", - "actionItemCategories": "措施项类别", - "updateYourDetails": "更新您的詳細信息", - "updateYourPassword": "更新您的密碼", - "updateOrganization": "更新組織", - "seeRequest": "查看請求", - "settings": "設置", - "noData": "沒有數據", - "otherSettings": "其他设置", - "changeLanguage": "更改语言", - "manageCustomFields": "管理自定义字段" - }, - "deleteOrg": { - "deleteOrganization": "删除组织", - "deleteSampleOrganization": "删除示范组织", - "deleteMsg": "您是否要删除此组织?", - "cancel": "取消", - "confirmDelete": "确认删除", - "longDelOrgMsg": "点击删除组织按钮,组织将被永久删除,包括其事件、标签和所有相关数据。", - "successfullyDeletedSampleOrganization": "已成功刪除樣本組織" - }, - "userUpdate": { - "firstName": "名", - "lastName": "姓", - "email": "電子郵件", - "password": "密碼", - "appLanguageCode": "默认语言", - "userType": "用戶類型", - "admin": "行政", - "superAdmin": "超級管理員", - "displayImage": "顯示圖像", - "saveChanges": "保存更改", - "cancel": "取消" - }, - "userPasswordUpdate": { - "previousPassword": "以前的密碼", - "newPassword": "新密碼", - "confirmNewPassword": "確認新密碼", - "saveChanges": "保存更改", - "cancel": "取消" - }, - "orgDelete": { - "deleteOrg": "刪除組織" - }, - "membershipRequest": { - "joined": "加入", - "accept": "接受", - "reject": "拒絕", - "memberAdded": "它被接受", - "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。" - }, - "orgUpdate": { - "name": "姓名", - "description": "描述", - "location": "地點", - "address": "地址", - "city": "城市", - "countryCode": "国家代码", - "line1": "地址行 1", - "line2": "地址行 2", - "postalCode": "邮政编码", - "dependentLocality": "从属地区", - "sortingCode": "排序代码", - "state": "省 / 直辖市", - "displayImage": "顯示圖像", - "userRegistrationRequired": "需要用户注册", - "isVisibleInSearch": "在搜索中可见", - "saveChanges": "保存更改", - "cancel": "取消", - "enterNameOrganization": "輸入組織名稱", - "successfulUpdated": "更新成功", - "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。" - }, - "addOnRegister": { - "addNew": "添新", - "addPlugin": "添加插件", - "pluginName": "插件名称", - "creatorName": "创建者姓名", - "pluginDesc": "插件说明", - "close": "关闭", - "register": "登记", - "pName": "例如:捐赠", - "cName": "例如:约翰·多伊", - "pDesc": "此插件启用 UI" - }, - "addOnStore": { - "title": "插件商店", - "searchName": "例如:捐赠", - "enable": "启用", - "disable": "残疾人", - "pHeading": "插件", - "install": "已安装", - "available": "可用的", - "pMessage": "插件不存在”", - "filter": "过滤器", - "search": "搜索" - }, - "addOnEntry": { - "enable": "启用", - "install": "安装", - "uninstall": "卸载" - }, - "memberDetail": { - "title": "用户详细信息", - "addAdmin": "添加管理员", - "alreadyIsAdmin": "会员已经是管理员", - "organizations": "组织", - "events": "事件", - "role": "角色", - "email": "电子邮件", - "createdOn": "创建于", - "main": "主要的", - "firstName": "名字", - "lastName": "姓氏", - "language": "语言", - "gender": "性别", - "birthDate": "出生日期", - "educationGrade": "教育程度", - "employmentStatus": "就业状况", - "maritalStatus": "婚姻状况", - "displayImage": "显示图片", - "phone": "电话", - "address": "地址", - "countryCode": "国家代码", - "state": "州/省", - "city": "城市", - "personalInfoHeading": "个人信息", - "contactInfoHeading": "联系信息", - "actionsHeading": "操作", - "personalDetailsHeading": "个人详情", - "appLanguageCode": "选择语言", - "delete": "删除用户", - "saveChanges": "保存更改", - "pluginCreationAllowed": "允许创建插件", - "joined": "加入", - "created": "创建", - "adminForOrganizations": "组织管理员", - "membershipRequests": "会员申请", - "adminForEvents": "事件管理员", - "addedAsAdmin": "用戶被添加為管理員。", - "talawaApiUnavailable": "Talawa-API 服務不可用。 請檢查您的網絡連接並稍等片刻。" - }, - "userLogin": { - "login": "登錄", - "forgotPassword": "忘記密碼 ?", - "loginIntoYourAccount": "登錄您的賬戶", - "emailAddress": "電子郵件地址", - "enterEmail": "輸入你的電子郵箱地址", - "password": "密碼", - "enterPassword": "輸入您的密碼", - "register": "登記", - "invalidDetailsMessage": "請輸入有效的電子郵件和密碼", - "notAuthorised": "對不起! 你沒有被授權!", - "invalidCredentials": "輸入的憑據不正確。 請輸入有效憑據。", - "talawaApiUnavailable": "Talawa-API 服務不可用。 請檢查您的網絡連接並稍等片刻。" - }, - "userRegister": { - "register": "登記", - "firstName": "名", - "enterFirstName": "輸入您的名字", - "lastName": "姓", - "enterLastName": "輸入您的姓氏", - "emailAddress": "電子郵件地址", - "enterEmail": "輸入你的電子郵箱地址", - "password": "密碼", - "enterPassword": "輸入您的密碼", - "confirmPassword": "確認密碼", - "enterConfirmPassword": "輸入您的密碼以確認", - "alreadyhaveAnAccount": "已有帳戶?", - "login": "登錄", - "afterRegister": "註冊成功。 請等待管理員批准您的請求。", - "passwordNotMatch": "密碼不匹配。 確認密碼並重試。", - "invalidDetailsMessage": "請輸入有效的詳細信息。", - "talawaApiUnavailable": "Talawa-API 服務不可用。 請檢查您的網絡連接並稍等片刻。" - }, - "userNavbar": { - "talawa": "塔拉瓦", - "home": "家", - "people": "人們", - "events": "活動", - "chat": "聊天", - "donate": "捐", - "settings": "設置", - "language": "語言", - "logout": "登出", - "close": "關閉" - }, - "userOrganizations": { - "allOrganizations": "所有組織", - "joinedOrganizations": "加入組織", - "createdOrganizations": "創建的組織", - "search": "搜索用户", - "nothingToShow": "這裡沒有什麼可展示的。", - "selectOrganization": "選擇組織", - "filter": "過濾", - "organizations": "组织", - "searchByName": "按名稱搜索" - }, - "userSidebarOrg": { - "yourOrganizations": "您的組織", - "noOrganizations": "您還沒有加入任何組織。", - "viewAll": "查看全部", - "talawaUserPortal": "用户门户", - "menu": "菜单", - "my organizations": "我的组织", - "users": "用户", - "requests": "请求", - "communityProfile": "社区简介", - "logout": "登出", - "settings": "設置" - }, - "organizationSidebar": { - "viewAll": "查看全部", - "events": "事件", - "members": "成员", - "noEvents": "沒有可顯示的活動", - "noMembers": "沒有可顯示的會員" - }, - "postCard": { - "likes": "喜歡", - "comments": "評論" - }, - "home": { - "feed": "餵養", - "pinnedPosts": "查看固定帖子", - "somethingOnYourMind": "你有什麼心事嗎?", - "addPost": "添加帖子", - "startPost": "开始一篇帖子", - "media": "媒体", - "event": "活动", - "article": "文章" - }, - "settings": { - "settings": "设置", - "profileSettings": "配置文件设置", - "firstName": "名", - "lastName": "姓", - "gender": "性别", - "emailAddress": "电子邮件地址", - "phoneNumber": "电话号码", - "displayImage": "个人资料图片", - "chooseFile": "选择文件", - "birthDate": "出生日期", - "grade": "教育程度", - "empStatus": "就业状况", - "maritalStatus": "婚姻状况", - "address": "地址", - "state": "城市/州", - "country": "国家", - "resetChanges": "重置更改", - "saveChanges": "保存更改", - "profileDetails": "个人资料详细信息", - "deleteUserMessage": "点击“删除用户”按钮后,您的用户将 永久删除,其事件、标签以及所有相关数据也将被删除。", - "copyLink": "复制个人资料链接", - "deleteUser": "删除用户", - "otherSettings": "其他设置", - "changeLanguage": "更改语言", - "sgender": "选择性别", - "gradePlaceholder": "输入成绩", - "sEmpStatus": "选择就业状态", - "male": "男性", - "female": "女性", - "other": "其他", - "employed": "已 employed", - "unemployed": "失业", - "sMaritalStatus": "选择婚姻状况", - "single": "单身", - "married": "已婚", - "divorced": "离婚", - "widowed": "鰥寡", - "engaged": "已订婚", - "seperated": "分居", - "grade1": "一年级", - "grade2": "二年级", - "grade3": "三年级", - "grade4": "四年级", - "grade5": "五年级", - "grade6": "六年级", - "grade7": "七年级", - "grade8": "八年级", - "grade9": "九年级", - "grade10": "十年级", - "grade11": "十一年级", - "grade12": "十二年级", - "graduate": "毕业生", - "kg": "幼儿园", - "preKg": "学前班", - "noGrade": "无等级", - "fullTime": "全职", - "partTime": "兼职", - "enterState": "输入城市或州", - "selectCountry": "选择国家/地区", - "joined": "加入" - }, - "donate": { - "donations": "捐款", - "searchDonations": "搜索捐款", - "donateForThe": "为", - "donateTo": "捐贈給", - "amount": "數量", - "yourPreviousDonations": "您之前的捐款", - "donate": "捐", - "nothingToShow": "這裡沒有什麼可顯示的。", - "success": "捐赠成功" - }, - "userEvents": { - "nothingToShow": "這裡沒有什麼可顯示的。", - "search": "搜索", - "createEvent": "創建事件", - "recurring": "再次發生的", - "startTime": "開始時間", - "endTime": "時間結束", - "cancel": "取消", - "create": "創造", - "listView": "列表顯示", - "calendarView": "日曆視圖", - "allDay": "整天", - "eventCreated": "活动创建并发布成功。", - "eventDetails": "活动详情", - "eventTitle": "标题", - "enterTitle": "输入标题", - "eventDescription": "描述", - "enterDescription": "输入描述", - "eventLocation": "地点", - "enterLocation": "输入位置", - "startDate": "开始日期", - "endDate": "结束日期", - "publicEvent": "公开", - "registerable": "可注册", - "monthlyCalendarView": "月历", - "yearlyCalendarView": "年度日历" - }, - "userEventCard": { - "location": "地點", - "starts": "開始", - "ends": "結束", - "creator": "創作者", - "alreadyRegistered": "已經註冊", - "register": "登記" - }, - "advertisement": { - "title": "广告", - "pHeading": "管理广告", - "activeAds": "活动广告", - "archievedAds": "已完成的广告活动", - "pMessage": "此广告活动没有相关广告。", - "delete": "删除", - "validLink": "链接有效", - "invalidLink": "链接无效", - "close": "关闭", - "deleteAdvertisement": "删除广告", - "deleteAdvertisementMsg": "您是否要删除此广告?", - "no": "不", - "yes": "是", - "Rmedia": "提供要显示的媒体内容", - "view": "查看", - "edit": "编辑", - "editAdvertisement": "编辑广告", - "saveChanges": "保存更改", - "endOfResults": "結果結束" - }, - "userChat": { - "chat": "聊天", - "search": "搜尋", - "contacts": "聯絡方式" - }, - "userChatRoom": { - "selectContact": "選擇聯絡人開始對話", - "sendMessage": "傳訊息" - }, - "orgProfileField": { - "loading": "正在加载...", - "noCustomField": "没有可用的自定义字段", - "customFieldName": "字段名称", - "enterCustomFieldName": "输入字段名称", - "customFieldType": "字段类型", - "saveChanges": "保存更改", - "删除自定义字段": "删除自定义字段", - "fieldSuccessMessage": "字段添加成功", - "fieldRemovalSuccess": "字段删除成功" - }, - "orgActionItemCategories": { - "createButton": "创建", - "editButton": "编辑", - "enableButton": "启用", - "disableButton": "禁用", - "updateActionItemCategory": "更新", - "actionItemCategoryName": "名称", - "actionItemCategoryDetails": "措施项类别详细信息", - "enterName": "输入名称", - "successfulCreation": "已成功创建措施项类别", - "successfulUpdation": "措施项类别已成功更新", - "sameNameConflict": "请更改名称以进行更新", - "categoryEnabled": "已启用措施项类别", - "categoryDisabled": "措施项类别已禁用" - }, - "organizationVenues": { - "title": "场地", - "addVenue": "添加场地", - "venueDetails": "场地详情", - "venueName": "场地名称", - "enterVenueName": "输入场地名称", - "description": "场地描述", - "enterVenueDesc": "输入场地描述", - "capacity": "容量", - "enterVenueCapacity": "输入场地容量", - "image": "场地图像", - "uploadVenueImage": "上传场地图像", - "createVenue": "创建场地", - "venueAdded": "场地添加成功", - "editVenue": "更新场地", - "venueUpdated": "场地详情更新成功", - "sort": "排序", - "highestCapacity": "最高容量", - "lowestCapacity": "最低容量", - "noVenues": "没有找到场地!", - "edit": "编辑", - "view": "查看", - "delete": "删除", - "venueTitleError": "场地标题不能为空!", - "venueCapacityError": "容量必须为正数!", - "searchBy": "搜索方式", - "name": "名称", - "desc": "描述" - }, - "addMember": { - "title": "添加成员", - "addMembers": "添加成员", - "existingUser": "现有用户", - "newUser": "新用户", - "searchFullName": "按全名搜索", - "firstName": "名字", - "enterFirstName": "输入名字", - "lastName": "姓氏", - "enterLastName": "输入姓氏", - "emailAddress": "电子邮件地址", - "enterEmail": "输入电子邮件", - "password": "密码", - "enterPassword": "输入密码", - "confirmPassword": "确认密码", - "enterConfirmPassword": "输入确认密码", - "organization": "组织", - "cancel": "取消", - "create": "创建", - "invalidDetailsMessage": "请提供所有必需的细节。", - "passwordNotMatch": "密码不匹配。", - "user": "用户", - "addMember": "添加成员" - }, - "eventActionItems": { - "title": "行动项目", - "createActionItem": "创建操作项", - "actionItemCategory": "操作项类别", - "selectActionItemCategory": "选择操作项类别", - "selectAssignee": "选择受让人", - "preCompletionNotes": "预完成注释", - "postCompletionNotes": "完成后注释", - "actionItemDetails": "操作项详细信息", - "dueDate": "截止日期", - "completionDate": "完成日期", - "editActionItem": "编辑操作项", - "deleteActionItem": "删除操作项", - "deleteActionItemMsg": "您要删除此操作项吗?", - "yes": "是的", - "不": "不", - "successfulDeletion": "操作项删除成功", - "successfulCreation": "操作项创建成功", - "successfulUpdation": "操作项更新成功", - "notes": "注释", - "save": "保存" - } -} diff --git a/public/locales/zh/common.json b/public/locales/zh/common.json new file mode 100644 index 0000000000..5d6fc97310 --- /dev/null +++ b/public/locales/zh/common.json @@ -0,0 +1,65 @@ +{ + "firstName": "名", + "lastName": "姓", + "searchByName": "按名称搜索", + "loading": "加载中...", + "endOfResults": "结果结束", + "noResultsFoundFor": "没有找到结果 ", + "edit": "编辑", + "admins": "管理员", + "admin": "行政", + "user": "用户", + "superAdmin": "超级管理员", + "members": "会员", + "logout": "登出", + "login": "登录", + "register": "登记", + "menu": "菜单", + "settings": "设置", + "users": "用户", + "requests": "要求", + "OR": "或者", + "cancel": "取消", + "close": "关闭", + "create": "创造", + "delete": "删除", + "done": "完毕", + "yes": "是的", + "no": "不", + "filter": "筛选", + "search": "搜索", + "description": "描述", + "saveChanges": "保存更改", + "displayImage": "显示图像", + "enterEmail": "输入电子邮件", + "emailAddress": "电子邮件地址", + "email": "电子邮件", + "name": "姓名", + "enterPassword": "输入密码", + "password": "密码", + "confirmPassword": "确认密码", + "forgotPassword": "忘记密码 ?", + "talawaAdminPortal": "塔拉瓦管理门户", + "address": "地址", + "location": "地点", + "enterLocation": "输入位置", + "joined": "已加入", + "startDate": "开始日期", + "endDate": "结束日期", + "startTime": "开始时间", + "endTime": "时间结束", + "My Organizations": "我的组织", + "Dashboard": "仪表板", + "People": "人们", + "Events": "事件", + "Venues": "场地", + "Action Items": "行动项目", + "Posts": "帖子", + "Block/Unblock": "封锁/解除封锁", + "Advertisement": "广告", + "Funds": "资金", + "Membership Requests": "会员请求", + "Plugins": "插件", + "Plugin Store": "插件商店", + "Settings": "设置" +} diff --git a/public/locales/zh/errors.json b/public/locales/zh/errors.json new file mode 100644 index 0000000000..7ddfe06ab4 --- /dev/null +++ b/public/locales/zh/errors.json @@ -0,0 +1,9 @@ +{ + "talawaApiUnavailable": "Talawa-API 服务不可用!", + "notFound": "未找到", + "unknownError": "出现未知错误。 {{msg}}", + "notAuthorised": "对不起!", + "errorSendingMail": "发送邮件时出错", + "emailNotRegistered": "邮箱未注册", + "notFoundMsg": "哎呀!" +} diff --git a/public/locales/zh/translation.json b/public/locales/zh/translation.json new file mode 100644 index 0000000000..13e581a0a3 --- /dev/null +++ b/public/locales/zh/translation.json @@ -0,0 +1,892 @@ +{ + "loginPage": { + "title": "塔拉瓦管理员", + "fromPalisadoes": "Palisadoes 基金会志愿者开发的开源应用程序", + "userLogin": "用户登录", + "atleast_8_char_long": "至少 8 个字符长", + "atleast_6_char_long": "至少 6 个字符长", + "firstName_invalid": "名字只能包含小写和大写字母", + "lastName_invalid": "姓氏只能包含小写和大写字母", + "password_invalid": "密码应至少包含1个小写字母、1个大写字母、1个数字和1个特殊字符", + "email_invalid": "电子邮件应至少包含 8 个字符", + "Password_and_Confirm_password_mismatches.": "密码和确认密码不匹配。", + "doNotOwnAnAccount": "没有帐户?", + "captchaError": "验证码错误!", + "Please_check_the_captcha": "请检查验证码。", + "Something_went_wrong": "出了点问题,请稍后再试。", + "passwordMismatches": "密码和确认密码不匹配。", + "fillCorrectly": "正确填写所有详细信息。", + "successfullyRegistered": "注册成功。", + "lowercase_check": "至少一个小写字母", + "uppercase_check": "至少有一个大写字母", + "numeric_value_check": "至少设定一个数值", + "special_char_check": "至少一个特殊字符", + "selectOrg": "选择一个组织", + "afterRegister": "注册成功。" + }, + "userLoginPage": { + "title": "塔拉瓦管理员", + "fromPalisadoes": "Palisadoes 基金会志愿者开发的开源应用程序", + "atleast_8_char_long": "至少 8 个字符长", + "Password_and_Confirm_password_mismatches.": "密码和确认密码不匹配。", + "doNotOwnAnAccount": "没有帐户?", + "captchaError": "验证码错误!", + "Please_check_the_captcha": "请检查验证码。", + "Something_went_wrong": "出了点问题,请稍后再试。", + "passwordMismatches": "密码和确认密码不匹配。", + "fillCorrectly": "正确填写所有详细信息。", + "successfullyRegistered": "注册成功。", + "userLogin": "用户登录", + "afterRegister": "注册成功。", + "selectOrg": "选择一个组织" + }, + "latestEvents": { + "eventCardTitle": "即将举行的活动", + "eventCardSeeAll": "查看全部", + "noEvents": "没有即将举行的活动" + }, + "latestPosts": { + "latestPostsTitle": "最新帖子", + "seeAllLink": "查看全部", + "noPostsCreated": "没有创建帖子" + }, + "listNavbar": { + "roles": "角色" + }, + "leftDrawer": { + "my organizations": "我的组织", + "requests": "会员申请", + "communityProfile": "社区简介" + }, + "leftDrawerOrg": { + "Dashboard": "仪表板", + "People": "人们", + "Events": "活动", + "Contributions": "贡献", + "Posts": "帖子", + "Block/Unblock": "阻止/解除阻止", + "Plugins": "插件", + "Plugin Store": "插件商店", + "Advertisement": "广告", + "allOrganizations": "所有组织", + "yourOrganization": "您的组织", + "notification": "通知", + "language": "语言", + "notifications": "通知", + "spamsThe": "垃圾邮件", + "group": "团体", + "noNotifications": "无通知" + }, + "orgList": { + "title": "塔拉瓦组织", + "you": "你", + "designation": "指定", + "my organizations": "我的组织", + "createOrganization": "创建组织", + "createSampleOrganization": "创建样本组织", + "city": "城市", + "countryCode": "国家代码", + "dependentLocality": "附属地点", + "line1": "1号线", + "line2": "2号线", + "postalCode": "邮政编码", + "sortingCode": "排序代码", + "state": "州/省", + "userRegistrationRequired": "需要用户注册", + "visibleInSearch": "在搜索中可见", + "enterName": "输入名字", + "sort": "种类", + "Latest": "最新的", + "Earliest": "最早", + "noOrgErrorTitle": "未找到组织", + "sampleOrgDuplicate": "只允许一个样本组织", + "noOrgErrorDescription": "请通过仪表板创建组织", + "manageFeatures": "管理功能", + "manageFeaturesInfo": "创建成功!", + "goToStore": "前往插件商店", + "enableEverything": "启用一切", + "sampleOrgSuccess": "样本组织已成功创建" + }, + "orgListCard": { + "manage": "管理", + "sampleOrganization": "组织样本" + }, + "paginationList": { + "rowsPerPage": "每页行数", + "all": "全部" + }, + "requests": { + "title": "会员申请", + "sl_no": "SL。", + "accept": "接受", + "reject": "拒绝", + "searchRequests": "搜索会员请求", + "noOrgError": "未找到组织,请通过仪表板创建组织", + "noRequestsFound": "未找到会员申请", + "acceptedSuccessfully": "请求已成功接受", + "rejectedSuccessfully": "请求被成功拒绝", + "noOrgErrorTitle": "未找到组织", + "noOrgErrorDescription": "请通过仪表板创建组织" + }, + "users": { + "title": "塔拉瓦角色", + "joined_organizations": "加入组织", + "blocked_organizations": "被阻止的组织", + "orgJoinedBy": "加入组织", + "orgThatBlocked": "阻止的组织", + "hasNotJoinedAnyOrg": "没有加入任何组织", + "isNotBlockedByAnyOrg": "没有被任何组织封锁", + "searchByOrgName": "按组织名称搜索", + "view": "看法", + "enterName": "输入名字", + "loadingUsers": "正在加载用户...", + "noUserFound": "未找到用户", + "sort": "种类", + "Newest": "新的先来", + "Oldest": "最旧的在前", + "noOrgError": "未找到组织,请通过仪表板创建组织", + "roleUpdated": "角色已更新。", + "joinNow": "立即加入", + "visit": "访问", + "withdraw": "拉幅" + }, + "communityProfile": { + "title": "社区简介", + "editProfile": "编辑个人资料", + "communityProfileInfo": "这些详细信息将显示在您和您的社区成员的登录/注册屏幕上", + "communityName": "社区名字", + "wesiteLink": "网站链接", + "logo": "标识", + "social": "社交媒体链接", + "url": "输入网址", + "profileChangedMsg": "已成功更新个人资料详细信息。", + "resetData": "成功重置个人资料详细信息。" + }, + "dashboard": { + "title": "仪表板", + "about": "关于", + "deleteThisOrganization": "删除该组织", + "statistics": "统计数据", + "posts": "帖子", + "events": "活动", + "blockedUsers": "被阻止的用户", + "viewAll": "查看全部", + "upcomingEvents": "即将举行的活动", + "noUpcomingEvents": "没有即将举行的活动", + "latestPosts": "最新帖子", + "noPostsPresent": "没有帖子", + "membershipRequests": "会员请求", + "noMembershipRequests": "没有会员请求" + }, + "organizationPeople": { + "title": "塔拉瓦会员", + "filterByName": "按名称过滤", + "filterByLocation": "按地点过滤", + "filterByEvent": "按事件过滤", + "searchName": "输入名字", + "searchevent": "输入事件", + "searchFullName": "输入全名", + "people": "人们", + "sort": "按角色搜索", + "actions": "行动", + "addMembers": "添加会员", + "existingUser": "现有用户", + "newUser": "新用户", + "enterFirstName": "输入您的名字", + "enterLastName": "输入您的姓氏", + "enterConfirmPassword": "输入您的密码进行确认", + "organization": "组织", + "invalidDetailsMessage": "请输入有效的详细信息。" + }, + "userListCard": { + "addAdmin": "添加管理员", + "addedAsAdmin": "用户被添加为管理员。" + }, + "orgAdminListCard": { + "remove": "消除", + "removeAdmin": "删除管理员", + "removeAdminMsg": "您想删除该管理员吗?", + "adminRemoved": "管理员被删除。" + }, + "orgPeopleListCard": { + "remove": "消除", + "removeMember": "删除会员", + "removeMemberMsg": "您想删除该成员吗?", + "memberRemoved": "该会员已被删除" + }, + "organizationEvents": { + "title": "活动", + "filterByTitle": "按标题过滤", + "filterByLocation": "按地点过滤", + "filterByDescription": "按描述过滤", + "addEvent": "添加事件", + "eventDetails": "活动详情", + "eventTitle": "标题", + "startTime": "开始时间", + "endTime": "时间结束", + "allDay": "一整天", + "recurringEvent": "重复事件", + "isPublic": "是公开的", + "isRegistrable": "可注册", + "createEvent": "创建事件", + "enterFilter": "输入过滤器", + "enterTitle": "输入标题", + "enterDescrip": "输入描述", + "eventLocation": "输入位置", + "searchEventName": "搜索活动名称", + "eventType": "事件类型", + "eventCreated": "恭喜!", + "customRecurrence": "自定义重复", + "repeatsEvery": "重复每个", + "repeatsOn": "重复开启", + "ends": "结束", + "never": "绝不", + "on": "在", + "after": "后", + "occurences": "事件" + }, + "organizationActionItems": { + "actionItemCategory": "行动项目类别", + "actionItemDetails": "行动项目详情", + "actionItemCompleted": "行动项目已完成", + "assignee": "受让人", + "assigner": "转让人", + "assignmentDate": "分配日期", + "active": "积极的", + "clearFilters": "清除过滤器", + "completed": "完全的", + "completionDate": "完成日期", + "deleteActionItem": "删除操作项", + "deleteActionItemMsg": "您想删除此操作项吗?", + "details": "细节", + "dueDate": "到期日", + "earliest": "最早", + "editActionItem": "编辑操作项", + "isCompleted": "完全的", + "latest": "最新的", + "noActionItems": "无行动项目", + "options": "选项", + "preCompletionNotes": "预完成注释", + "actionItemActive": "积极的", + "markCompletion": "标记完成", + "actionItemStatus": "行动项目状态", + "postCompletionNotes": "完成后注释", + "selectActionItemCategory": "选择操作项类别", + "selectAssignee": "选择受托人", + "status": "地位", + "successfulCreation": "操作项创建成功", + "successfulUpdation": "操作项已成功更新", + "successfulDeletion": "操作项已成功删除", + "title": "行动项目" + }, + "eventListCard": { + "deleteEvent": "删除事件", + "deleteEventMsg": "您想删除此事件吗?", + "editEvent": "编辑事件", + "eventTitle": "标题", + "alreadyRegistered": "已经注册", + "startTime": "开始时间", + "endTime": "时间结束", + "allDay": "一整天", + "recurringEvent": "重复事件", + "isPublic": "是公开的", + "isRegistrable": "可注册", + "updatePost": "更新帖子", + "eventDetails": "活动详情", + "eventDeleted": "活动删除成功。", + "eventUpdated": "活动更新成功。", + "thisInstance": "本实例", + "thisAndFollowingInstances": "本实例及后续实例", + "allInstances": "所有实例", + "customRecurrence": "自定义重复", + "repeatsEvery": "重复每个", + "repeatsOn": "重复开启", + "ends": "结束", + "never": "绝不", + "on": "在", + "after": "后", + "occurences": "事件" + }, + "funds": { + "title": "资金", + "createFund": "创建基金", + "fundName": "基金名称", + "fundId": "基金编号", + "fundOptions": "奥皮通斯", + "noFunds": "未找到资金", + "fundDetails": "基金详情", + "taxDeductible": "免税额", + "enterfundName": "输入基金名称", + "enterfundId": "输入基金ID", + "default": "违约基金", + "archived": "已归档", + "nonArchive": "非存档", + "fundCreate": "创建基金", + "fundUpdate": "更新基金", + "fundDelete": "删除基金", + "manageFund": "管理基金", + "searchFullName": "按名称搜索", + "noFundsFound": "未找到资金", + "createdBy": "由...制作", + "createdOn": "创建于", + "status": "地位", + "archiveFund": "档案基金", + "archiveFundMsg": "存档后,该基金将从基金列表中删除。此操作可以撤消", + "fundCreated": "基金创建成功", + "fundUpdated": "基金更新成功", + "fundDeleted": "资金删除成功", + "fundArchived": "资金归档成功", + "fundUnarchived": "基金已成功解档", + "deleteFundMsg": "您想删除该基金吗?" + }, + "fundCampaign": { + "title": "筹款活动", + "campaignName": "活动名称", + "campaignOptions": "选项", + "fundingGoal": "资助目标", + "addCampaign": "添加活动", + "createdCampaign": "活动创建成功", + "updatedCampaign": "活动更新成功", + "deletedCampaign": "营销活动删除成功", + "deleteCampaignMsg": "您确定要删除此广告活动吗?", + "noCampaigns": "未找到活动", + "createCampaign": "创建基金活动", + "updateCampaign": "更新基金活动", + "manageCampaign": "管理基金活动", + "deleteCampaign": "删除基金活动", + "currency": "货币", + "selectCurrency": "选择货币", + "searchFullName": "按名称搜索" + }, + "pledges": { + "title": "基金活动承诺", + "volunteers": "志愿者", + "pledgeAmount": "质押金额", + "pledgeOptions": "选项", + "pledgeCreated": "质押创建成功", + "pledgeUpdated": "承诺更新成功", + "pledgeDeleted": "承诺删除成功", + "addPledge": "添加承诺", + "createPledge": "创建承诺", + "currency": "货币", + "selectCurrency": "选择货币", + "updatePledge": "更新承诺", + "deletePledge": "删除承诺", + "amount": "数量", + "editPledge": "编辑承诺", + "deletePledgeMsg": "您确定要删除此承诺吗?", + "noPledges": "未找到承诺" + }, + "orgPost": { + "title": "帖子", + "searchPost": "搜索帖子", + "posts": "帖子", + "createPost": "创建帖子", + "postDetails": "帖子详情", + "postTitle1": "写下帖子的标题", + "postTitle": "标题", + "addMedia": "上传媒体", + "information": "信息", + "information1": "填写帖子信息", + "addPost": "添加帖子", + "searchTitle": "按标题搜索", + "searchText": "按文本搜索", + "ptitle": "帖子标题", + "postDes": "你要聊什么?", + "Title": "标题", + "Text": "文本", + "searchBy": "搜索依据", + "Oldest": "最旧的在前", + "Latest": "最新第一", + "sortPost": "排序帖子", + "tag": " 您的浏览器不支持video标签", + "postCreatedSuccess": "恭喜!", + "pinPost": "针柱", + "Next": "下一页", + "Previous": "上一页" + }, + "postNotFound": { + "post": "邮政", + "not found!": "未找到!", + "organization": "组织", + "post not found!": "帖子未找到!", + "organization not found!": "未找到组织!" + }, + "userNotFound": { + "not found!": "未找到!", + "roles": "角色", + "user not found!": "未找到用户!", + "member not found!": "未找到会员!", + "admin not found!": "找不到管理员!", + "roles not found!": "未找到角色!" + }, + "orgPostCard": { + "author": "作者", + "imageURL": "图片网址", + "videoURL": "视频网址", + "deletePost": "删除帖子", + "deletePostMsg": "您想删除此帖子吗?", + "editPost": "编辑帖子", + "postTitle": "标题", + "postTitle1": "编辑帖子标题", + "information1": "编辑帖子信息", + "information": "信息", + "image": "图像", + "video": "视频", + "updatePost": "更新帖子", + "postDeleted": "帖子删除成功。", + "postUpdated": "帖子更新成功。", + "tag": " 您的浏览器不支持video标签", + "pin": "针柱" + }, + "blockUnblockUser": { + "title": "阻止/取消阻止用户", + "pageName": "阻止/解除阻止", + "listOfUsers": "发送垃圾邮件的用户列表", + "block_unblock": "阻止/解除阻止", + "unblock": "解锁", + "block": "堵塞", + "orgName": "输入名字", + "blockedSuccessfully": "用户被成功屏蔽", + "Un-BlockedSuccessfully": "用户解封成功", + "allMembers": "所有会员", + "blockedUsers": "被阻止的用户", + "searchByFirstName": "按名字搜索", + "searchByLastName": "按姓氏搜索", + "noSpammerFound": "未发现垃圾邮件发送者" + }, + "eventManagement": { + "title": "事件管理", + "dashboard": "仪表板", + "registrants": "注册者", + "eventActions": "事件动作", + "eventStats": "事件统计", + "to": "到" + }, + "forgotPassword": { + "title": "塔拉瓦 忘记密码", + "registeredEmail": "注册的电子邮件", + "getOtp": "获取一次性密码", + "enterOtp": "输入一次性密码", + "enterNewPassword": "输入新密码", + "cofirmNewPassword": "确认新密码", + "changePassword": "更改密码", + "backToLogin": "回到登入", + "userOtp": "例如", + "emailNotRegistered": "电子邮件未注册。", + "errorSendingMail": "发送邮件时出错。", + "passwordMismatches": "密码和确认密码不匹配。", + "passwordChanges": "密码修改成功。", + "OTPsent": "OTP 已发送至您的注册邮箱。" + }, + "pageNotFound": { + "404": "404", + "title": "404 未找到", + "talawaAdmin": "塔拉瓦管理员", + "talawaUser": "塔拉瓦用户", + "notFoundMsg": "哎呀!", + "backToHome": "返回首页" + }, + "orgContribution": { + "title": "塔拉瓦 贡献", + "filterByName": "按名称过滤", + "filterByTransId": "按反式过滤。 ", + "recentStats": "最近的统计数据", + "contribution": "贡献", + "orgname": "输入名字", + "searchtransaction": "输入交易ID" + }, + "contriStats": { + "recentContribution": "最近的贡献", + "highestContribution": "最高贡献", + "totalContribution": "总贡献" + }, + "orgContriCards": { + "date": "日期", + "transactionId": "交易ID", + "amount": "数量" + }, + "orgSettings": { + "title": "设置", + "general": "一般的", + "actionItemCategories": "行动项目类别", + "updateOrganization": "更新组织", + "seeRequest": "查看请求", + "noData": "没有数据", + "otherSettings": "其他设置", + "changeLanguage": "改变语言", + "manageCustomFields": "管理自定义字段" + }, + "deleteOrg": { + "deleteOrganization": "删除组织", + "deleteSampleOrganization": "删除样本组织", + "deleteMsg": "您想删除该组织吗?", + "confirmDelete": "确认删除", + "longDelOrgMsg": "通过单击“删除组织”按钮,该组织及其事件、标签和所有相关数据将被永久删除。", + "successfullyDeletedSampleOrganization": "已成功删除样本组织" + }, + "userUpdate": { + "appLanguageCode": "默认语言", + "userType": "用户类型" + }, + "userPasswordUpdate": { + "previousPassword": "旧密码", + "newPassword": "新密码", + "confirmNewPassword": "确认新密码" + }, + "orgDelete": { + "deleteOrg": "删除组织" + }, + "membershipRequest": { + "accept": "接受", + "reject": "拒绝", + "memberAdded": "它被接受" + }, + "orgUpdate": { + "city": "城市", + "countryCode": "国家代码", + "line1": "1号线", + "line2": "2号线", + "postalCode": "邮政编码", + "dependentLocality": "附属地点", + "sortingCode": "排序代码", + "state": "州/省", + "userRegistrationRequired": "需要用户注册", + "isVisibleInSearch": "在搜索中可见", + "enterNameOrganization": "输入组织名称", + "successfulUpdated": "组织更新成功" + }, + "addOnRegister": { + "addNew": "添新", + "addPlugin": "添加插件", + "pluginName": "插件名称", + "creatorName": "创建者姓名", + "pluginDesc": "插件说明", + "pName": "例如:捐款", + "cName": "例如:约翰·多伊", + "pDesc": "该插件启用 UI" + }, + "addOnStore": { + "title": "添加商店", + "searchName": "例如:捐款", + "enable": "启用", + "disable": "残疾人", + "pHeading": "插件", + "install": "已安装", + "available": "可用的", + "pMessage": "插件不存在" + }, + "addOnEntry": { + "enable": "启用", + "install": "安装", + "uninstall": "卸载", + "uninstallMsg": "此功能现已从您的组织中删除", + "installMsg": "您的组织现已启用此功能" + }, + "memberDetail": { + "title": "用户详细信息", + "addAdmin": "添加管理员", + "alreadyIsAdmin": "会员已经是管理员", + "organizations": "组织机构", + "events": "活动", + "role": "角色", + "createdOn": "创建于", + "main": "主要的", + "firstName": "名", + "lastName": "姓", + "language": "语言", + "gender": "性别", + "birthDate": "出生日期", + "educationGrade": "教育等级", + "employmentStatus": "就业状况", + "maritalStatus": "婚姻状况", + "phone": "电话", + "countryCode": "国家代码", + "state": "状态", + "city": "城市", + "personalInfoHeading": "个人信息", + "contactInfoHeading": "联系信息", + "actionsHeading": "行动", + "personalDetailsHeading": "个人资料详情", + "appLanguageCode": "选择语言", + "deleteUser": "删除用户", + "pluginCreationAllowed": "允许创建插件", + "created": "已创建", + "adminForOrganizations": "组织管理员", + "membershipRequests": "会员请求", + "adminForEvents": "活动管理员", + "addedAsAdmin": "用户被添加为管理员。", + "userType": "用户类型" + }, + "userLogin": { + "login": "登录", + "loginIntoYourAccount": "登录您的帐户", + "invalidDetailsMessage": "请输入有效的电子邮件和密码。", + "notAuthorised": "对不起!", + "invalidCredentials": "输入的凭据不正确。" + }, + "userRegister": { + "enterFirstName": "输入您的名字", + "enterLastName": "输入您的姓氏", + "enterConfirmPassword": "输入您的密码进行确认", + "alreadyhaveAnAccount": "已经有帐户?", + "login": "登录", + "afterRegister": "注册成功。", + "passwordNotMatch": "密码不匹配。", + "invalidDetailsMessage": "请输入有效的详细信息。" + }, + "userNavbar": { + "talawa": "塔拉瓦", + "home": "家", + "people": "人们", + "events": "活动", + "chat": "聊天", + "donate": "捐", + "language": "语言" + }, + "userOrganizations": { + "allOrganizations": "所有组织", + "joinedOrganizations": "加入组织", + "createdOrganizations": "创建组织", + "selectOrganization": "选择一个组织", + "searchUsers": "搜索用户", + "nothingToShow": "这里没有什么可显示的。", + "organizations": "组织机构" + }, + "userSidebarOrg": { + "yourOrganizations": "您的组织", + "noOrganizations": "您还没有加入任何组织。", + "viewAll": "查看全部", + "talawaUserPortal": "塔拉瓦用户门户", + "my organizations": "我的组织", + "communityProfile": "社区简介" + }, + "organizationSidebar": { + "viewAll": "查看全部", + "events": "活动", + "noEvents": "没有可显示的活动", + "noMembers": "没有可显示的会员" + }, + "postCard": { + "likes": "喜欢", + "comments": "评论" + }, + "home": { + "posts": "帖子", + "post": "邮政", + "title": "标题", + "textArea": "你有什么心事吗?", + "feed": "喂养", + "loading": "加载中", + "pinnedPosts": "已标记的帖子", + "yourFeed": "您的动态", + "nothingToShowHere": "这里没有可显示的内容", + "somethingOnYourMind": "你有什么心事吗?", + "addPost": "添加帖子", + "startPost": "开始发帖", + "media": "媒体", + "event": "事件", + "article": "文章" + }, + "settings": { + "profileSettings": "配置文件设置", + "gender": "性别", + "phoneNumber": "电话号码", + "chooseFile": "选择文件", + "birthDate": "出生日期", + "grade": "教育等级", + "empStatus": "就业状况", + "maritalStatus": "婚姻状况", + "state": "市,州", + "country": "国家", + "resetChanges": "重置更改", + "profileDetails": "个人资料详情", + "deleteUserMessage": "通过单击“删除用户”按钮,您的用户及其事件、标签和所有相关数据将被永久删除。", + "copyLink": "复制个人资料链接", + "deleteUser": "删除用户", + "otherSettings": "其他设置", + "changeLanguage": "改变语言", + "sgender": "选择性别", + "gradePlaceholder": "输入年级", + "sEmpStatus": "选择就业状况", + "female": "女性", + "male": "男性", + "employed": "就业", + "other": "其他", + "sMaritalStatus": "选择婚姻状况", + "unemployed": "失业", + "married": "已婚", + "single": "单身的", + "widowed": "寡", + "divorced": "离婚", + "engaged": "已订婚的", + "seperated": "分离的", + "grade1": "1级", + "grade2": "二年级", + "grade3": "三年级", + "grade4": "四年级", + "grade5": "五年级", + "grade6": "6年级", + "grade7": "7年级", + "grade8": "8级", + "grade9": "9年级", + "grade10": "10年级", + "grade11": "11年级", + "grade12": "12年级", + "graduate": "毕业", + "kg": "公斤", + "preKg": "预幼稚园", + "noGrade": "无等级", + "fullTime": "全职", + "partTime": "兼职", + "selectCountry": "选择一个国家", + "enterState": "输入城市或州" + }, + "donate": { + "donations": "捐款", + "searchDonations": "搜索捐款", + "donateForThe": "为", + "amount": "数量", + "yourPreviousDonations": "您之前的捐款", + "donate": "捐", + "nothingToShow": "这里没有什么可显示的。", + "success": "捐赠成功" + }, + "userEvents": { + "nothingToShow": "这里没有什么可显示的。", + "createEvent": "创建事件", + "recurring": "重复事件", + "startTime": "开始时间", + "endTime": "时间结束", + "listView": "列表显示", + "calendarView": "日历视图", + "allDay": "一整天", + "eventCreated": "活动已成功创建并发布。", + "eventDetails": "活动详情", + "eventTitle": "标题", + "enterTitle": "输入标题", + "enterDescription": "输入描述", + "enterLocation": "输入位置", + "publicEvent": "是公开的", + "registerable": "可注册", + "monthlyCalendarView": "月历", + "yearlyCalendarView": "年历" + }, + "userEventCard": { + "starts": "开始", + "ends": "结束", + "creator": "创作者", + "alreadyRegistered": "已经注册" + }, + "advertisement": { + "title": "广告", + "activeAds": "活跃活动", + "archievedAds": "已完成的活动", + "pMessage": "此活动中不存在广告。", + "validLink": "链接有效", + "invalidLink": "链接无效", + "Rname": "输入广告名称", + "Rtype": "选择广告类型", + "Rmedia": "提供要显示的媒体内容", + "RstartDate": "选择开始日期", + "RendDate": "选择结束日期", + "RClose": "关上窗户", + "addNew": "制作新广告", + "EXname": "前任。", + "EXlink": "前任。 ", + "createAdvertisement": "创建广告", + "deleteAdvertisement": "删除广告", + "deleteAdvertisementMsg": "您想删除该广告吗?", + "view": "看法", + "editAdvertisement": "编辑广告" + }, + "userChat": { + "chat": "聊天", + "contacts": "联系方式" + }, + "userChatRoom": { + "selectContact": "选择联系人开始对话", + "sendMessage": "发信息" + }, + "orgProfileField": { + "loading": "加载中...", + "noCustomField": "没有可用的自定义字段", + "customFieldName": "字段名称", + "enterCustomFieldName": "输入字段名称", + "customFieldType": "字段类型", + "Remove Custom Field": "删除自定义字段", + "fieldSuccessMessage": "字段添加成功", + "fieldRemovalSuccess": "字段删除成功" + }, + "orgActionItemCategories": { + "enableButton": "使能够", + "disableButton": "禁用", + "updateActionItemCategory": "更新", + "actionItemCategoryName": "姓名", + "actionItemCategoryDetails": "行动项目类别详细信息", + "enterName": "输入名字", + "successfulCreation": "操作项类别创建成功", + "successfulUpdation": "行动项目类别已成功更新", + "sameNameConflict": "请更改名称以进行更新", + "categoryEnabled": "已启用操作项类别", + "categoryDisabled": "操作项类别已禁用" + }, + "organizationVenues": { + "title": "场地", + "addVenue": "添加场地", + "venueDetails": "场地详情", + "venueName": "场地名称", + "enterVenueName": "输入场地名称", + "enterVenueDesc": "输入场地描述", + "capacity": "容量", + "enterVenueCapacity": "输入场地容量", + "image": "场地图片", + "uploadVenueImage": "上传场地图片", + "createVenue": "创建场地", + "venueAdded": "场地添加成功", + "editVenue": "更新地点", + "venueUpdated": "场地详情更新成功", + "sort": "种类", + "highestCapacity": "最高容量", + "lowestCapacity": "最低容量", + "noVenues": "未找到场地!", + "view": "看法", + "venueTitleError": "场地名称不能为空!", + "venueCapacityError": "容量必须是正数!", + "searchBy": "搜索依据" + }, + "addMember": { + "title": "添加会员", + "addMembers": "添加会员", + "existingUser": "现有用户", + "newUser": "新用户", + "searchFullName": "按全名搜索", + "enterFirstName": "输入名字", + "enterLastName": "输入姓氏", + "enterConfirmPassword": "输入确认密码", + "organization": "组织", + "invalidDetailsMessage": "请提供所有必需的详细信息。", + "passwordNotMatch": "密码不匹配。", + "addMember": "添加会员" + }, + "eventActionItems": { + "title": "行动项目", + "createActionItem": "创建行动项目", + "actionItemCategory": "行动项目类别", + "selectActionItemCategory": "选择操作项类别", + "selectAssignee": "选择受托人", + "preCompletionNotes": "预完成注释", + "postCompletionNotes": "完成后注释", + "actionItemDetails": "行动项目详情", + "dueDate": "到期日", + "completionDate": "完成日期", + "editActionItem": "编辑操作项", + "deleteActionItem": "删除操作项", + "deleteActionItemMsg": "您想删除此操作项吗?", + "successfulDeletion": "操作项已成功删除", + "successfulCreation": "操作项创建成功", + "successfulUpdation": "操作项已成功更新", + "notes": "笔记", + "save": "节省" + } +} diff --git a/src/App.tsx b/src/App.tsx index 24d52cf65c..1d8787e7eb 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -127,7 +127,10 @@ function app(): JSX.Element { } /> } /> } /> - + } + /> } @@ -164,7 +167,7 @@ function app(): JSX.Element { } /> }> } /> diff --git a/src/GraphQl/Mutations/mutations.ts b/src/GraphQl/Mutations/mutations.ts index c5d0ea1c1a..2ed67be88d 100644 --- a/src/GraphQl/Mutations/mutations.ts +++ b/src/GraphQl/Mutations/mutations.ts @@ -346,7 +346,9 @@ export const REMOVE_MEMBER_MUTATION = gql` export const ADD_ADMIN_MUTATION = gql` mutation CreateAdmin($orgid: ID!, $userid: ID!) { createAdmin(data: { organizationId: $orgid, userId: $userid }) { - _id + user { + _id + } } } `; diff --git a/src/components/ActionItems/ActionItemsContainer.tsx b/src/components/ActionItems/ActionItemsContainer.tsx index 733591d9b2..0cb799c212 100644 --- a/src/components/ActionItems/ActionItemsContainer.tsx +++ b/src/components/ActionItems/ActionItemsContainer.tsx @@ -42,6 +42,7 @@ function actionItemsContainer({ const { t } = useTranslation('translation', { keyPrefix: 'organizationActionItems', }); + const { t: tCommon } = useTranslation('common'); const [actionItemPreviewModalIsOpen, setActionItemPreviewModalIsOpen] = useState(false); @@ -453,6 +454,7 @@ function actionItemsContainer({ deleteActionItemHandler={deleteActionItemHandler} toggleDeleteModal={toggleDeleteModal} t={t} + tCommon={tCommon} /> ); diff --git a/src/components/ActionItems/ActionItemsModalBody.tsx b/src/components/ActionItems/ActionItemsModalBody.tsx index 59de3b1681..1aeb536b8b 100644 --- a/src/components/ActionItems/ActionItemsModalBody.tsx +++ b/src/components/ActionItems/ActionItemsModalBody.tsx @@ -33,6 +33,7 @@ export const ActionItemsModalBody = ({ const { t } = useTranslation('translation', { keyPrefix: 'organizationActionItems', }); + const { t: tCommon } = useTranslation('common'); const [dueDate, setDueDate] = useState(new Date()); const [actionItemCreateModalIsOpen, setActionItemCreateModalIsOpen] = @@ -80,7 +81,7 @@ export const ActionItemsModalBody = ({ data: InterfaceActionItemList | undefined; loading: boolean; error?: Error | undefined; - refetch: any; + refetch: () => void; } = useQuery(ACTION_ITEM_LIST, { variables: { organizationId, @@ -188,7 +189,7 @@ export const ActionItemsModalBody = ({ data-testid="createEventActionItemBtn" onClick={showCreateModal} > - {t('createActionItem')} + {tCommon('create')}
    diff --git a/src/components/AddOn/core/AddOnRegister/AddOnRegister.tsx b/src/components/AddOn/core/AddOnRegister/AddOnRegister.tsx index f808d223e8..9f88775265 100644 --- a/src/components/AddOn/core/AddOnRegister/AddOnRegister.tsx +++ b/src/components/AddOn/core/AddOnRegister/AddOnRegister.tsx @@ -18,6 +18,7 @@ interface InterfaceFormStateTypes { function addOnRegister(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'addOnRegister' }); + const { t: tCommon } = useTranslation('common'); const { orgId: currentUrl } = useParams(); const navigate = useNavigate(); @@ -134,14 +135,14 @@ function addOnRegister(): JSX.Element { onClick={handleClose} data-testid="addonclose" > - {t('close')} + {tCommon('close')} diff --git a/src/components/Advertisements/Advertisements.test.tsx b/src/components/Advertisements/Advertisements.test.tsx index 0eb638f6b1..fcb8889dad 100644 --- a/src/components/Advertisements/Advertisements.test.tsx +++ b/src/components/Advertisements/Advertisements.test.tsx @@ -1,38 +1,32 @@ import React from 'react'; -import 'jest-location-mock'; -import { - act, - fireEvent, - render, - screen, - waitFor, -} from '@testing-library/react'; -import { MockedProvider } from '@apollo/client/testing'; import { ApolloClient, - ApolloProvider, - InMemoryCache, ApolloLink, + ApolloProvider, HttpLink, + InMemoryCache, } from '@apollo/client'; +import { MockedProvider } from '@apollo/client/testing'; +import { act, fireEvent, render, screen } from '@testing-library/react'; +import 'jest-location-mock'; import type { DocumentNode, NormalizedCacheObject } from '@apollo/client'; -import { BrowserRouter } from 'react-router-dom'; -import Advertisement from './Advertisements'; -import { Provider } from 'react-redux'; -import { store } from 'state/store'; +import userEvent from '@testing-library/user-event'; import { BACKEND_URL } from 'Constant/constant'; -import i18nForTest from 'utils/i18nForTest'; -import { I18nextProvider } from 'react-i18next'; +import { ADD_ADVERTISEMENT_MUTATION } from 'GraphQl/Mutations/mutations'; import { ORGANIZATIONS_LIST, ORGANIZATION_ADVERTISEMENT_LIST, PLUGIN_GET, } from 'GraphQl/Queries/Queries'; -import userEvent from '@testing-library/user-event'; -import { ADD_ADVERTISEMENT_MUTATION } from 'GraphQl/Mutations/mutations'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; import { ToastContainer } from 'react-toastify'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; import useLocalStorage from 'utils/useLocalstorage'; +import Advertisement from './Advertisements'; const { getItem } = useLocalStorage(); @@ -387,7 +381,7 @@ describe('Testing Advertisement Component', () => { await wait(); - userEvent.click(screen.getByText('Create new advertisement')); + userEvent.click(screen.getByText('Create Advertisement')); userEvent.type( screen.getByLabelText('Enter name of Advertisement'), 'Cookie Shop', @@ -509,8 +503,9 @@ describe('Testing Advertisement Component', () => { const moreiconbtn = await screen.findAllByTestId('moreiconbtn'); fireEvent.click(moreiconbtn[1]); - expect(await screen.findByTestId('deletebtn')); - fireEvent.click(await screen.findByTestId('deletebtn')); + const deleteBtn = await screen.findByTestId('deletebtn'); + expect(deleteBtn).toBeInTheDocument(); + fireEvent.click(deleteBtn); }); test('infinite scroll', async () => { diff --git a/src/components/Advertisements/Advertisements.tsx b/src/components/Advertisements/Advertisements.tsx index 95b95fb936..0b880700d9 100644 --- a/src/components/Advertisements/Advertisements.tsx +++ b/src/components/Advertisements/Advertisements.tsx @@ -13,6 +13,7 @@ import InfiniteScroll from 'react-infinite-scroll-component'; export default function advertisements(): JSX.Element { const { orgId: currentOrgId } = useParams(); const { t } = useTranslation('translation', { keyPrefix: 'advertisement' }); + const { t: tCommon } = useTranslation('common'); document.title = t('title'); const [after, setAfter] = useState(null); @@ -32,7 +33,7 @@ export default function advertisements(): JSX.Element { data?: { organizations: InterfaceQueryOrganizationAdvertisementListItem[]; }; - refetch: any; + refetch: () => void; } = useQuery(ORGANIZATION_ADVERTISEMENT_LIST, { variables: { id: currentOrgId, @@ -114,7 +115,7 @@ export default function advertisements(): JSX.Element { (ad: Ad) => new Date(ad.endDate) > new Date(), ).length !== 0 && (
    -
    {t('endOfResults')}
    +
    {tCommon('endOfResults')}
    ) } @@ -189,7 +190,7 @@ export default function advertisements(): JSX.Element { (ad: Ad) => new Date(ad.endDate) < new Date(), ).length !== 0 && (
    -
    {t('endOfResults')}
    +
    {tCommon('endOfResults')}
    ) } diff --git a/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.tsx b/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.tsx index c6faa21de8..cbc933a894 100644 --- a/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.tsx +++ b/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.tsx @@ -10,14 +10,6 @@ import AdvertisementRegister from '../AdvertisementRegister/AdvertisementRegiste import MoreVertIcon from '@mui/icons-material/MoreVert'; import { toast } from 'react-toastify'; -type Ad = { - _id: string; - name: string; - type: 'BANNER' | 'MENU' | 'POPUP'; - mediaUrl: string; - endDate: string; // Assuming it's a string in the format 'yyyy-MM-dd' - startDate: string; // Assuming it's a string in the format 'yyyy-MM-dd' -}; interface InterfaceAddOnEntryProps { id: string; name: string; @@ -26,7 +18,7 @@ interface InterfaceAddOnEntryProps { organizationId: string; startDate: Date; endDate: Date; - setAfter: any; + setAfter: React.Dispatch>; } function advertisementEntry({ id, @@ -39,6 +31,7 @@ function advertisementEntry({ setAfter, }: InterfaceAddOnEntryProps): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'advertisement' }); + const { t: tCommon } = useTranslation('common'); const [buttonLoading, setButtonLoading] = useState(false); const [dropdown, setDropdown] = useState(false); const [showDeleteModal, setShowDeleteModal] = useState(false); @@ -64,8 +57,10 @@ function advertisementEntry({ toast.error('Advertisement Deleted'); setButtonLoading(false); setAfter(null); - } catch (error: any) { - toast.error(error.message); + } catch (error: unknown) { + if (error instanceof Error) { + toast.error(error.message); + } setButtonLoading(false); } }; @@ -102,7 +97,7 @@ function advertisementEntry({ />
  • - {t('delete')} + {tCommon('delete')}
)} @@ -164,7 +159,7 @@ function advertisementEntry({ diff --git a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.test.tsx b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.test.tsx index 00a8f94ac8..a38823a97c 100644 --- a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.test.tsx +++ b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.test.tsx @@ -1,11 +1,5 @@ import React from 'react'; -import { - render, - fireEvent, - waitFor, - screen, - act, -} from '@testing-library/react'; +import { render, fireEvent, waitFor, screen } from '@testing-library/react'; import { ApolloClient, @@ -131,11 +125,15 @@ const client: ApolloClient = new ApolloClient({ link: ApolloLink.from([httpLink]), }); -const translations = JSON.parse( - JSON.stringify( - i18n.getDataByLanguage('en')?.translation?.advertisement ?? null, +const translations = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.advertisement ?? {}, + ), ), -); + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), @@ -163,7 +161,7 @@ describe('Testing Advertisement Register Component', () => { , ); await waitFor(() => { - expect(getByText(translations.addNew)).toBeInTheDocument(); + expect(getByText(translations.createAdvertisement)).toBeInTheDocument(); }); }); @@ -189,10 +187,10 @@ describe('Testing Advertisement Register Component', () => { , ); - expect(getByText(translations.addNew)).toBeInTheDocument(); + expect(getByText(translations.createAdvertisement)).toBeInTheDocument(); - fireEvent.click(getByText(translations.addNew)); - expect(queryByText(translations.RClose)).toBeInTheDocument(); + fireEvent.click(getByText(translations.createAdvertisement)); + expect(queryByText(translations.addNew)).toBeInTheDocument(); fireEvent.change(getByLabelText(translations.Rname), { target: { value: 'Ad1' }, @@ -237,7 +235,7 @@ describe('Testing Advertisement Register Component', () => { test('update advertisement', async () => { const setTimeoutSpy = jest.spyOn(global, 'setTimeout'); - const { getByText, queryByText, getByLabelText } = render( + const { getByText, getByLabelText } = render( @@ -323,10 +321,10 @@ describe('Testing Advertisement Register Component', () => { , ); - expect(getByText(translations.addNew)).toBeInTheDocument(); + expect(getByText(translations.createAdvertisement)).toBeInTheDocument(); - fireEvent.click(getByText(translations.addNew)); - expect(queryByText(translations.RClose)).toBeInTheDocument(); + fireEvent.click(getByText(translations.createAdvertisement)); + expect(queryByText(translations.addNew)).toBeInTheDocument(); await waitFor(() => { fireEvent.click(getByText(translations.register)); @@ -359,10 +357,10 @@ describe('Testing Advertisement Register Component', () => { , ); - expect(getByText(translations.addNew)).toBeInTheDocument(); + expect(getByText(translations.createAdvertisement)).toBeInTheDocument(); - fireEvent.click(getByText(translations.addNew)); - expect(queryByText(translations.RClose)).toBeInTheDocument(); + fireEvent.click(getByText(translations.createAdvertisement)); + expect(queryByText(translations.addNew)).toBeInTheDocument(); fireEvent.change(getByLabelText(translations.Rname), { target: { value: 'Ad1' }, @@ -453,11 +451,12 @@ describe('Testing Advertisement Register Component', () => { , ); + fireEvent.click(getByText(translations.createAdvertisement)); + await waitFor(() => { + expect(queryByText(translations.addNew)).toBeInTheDocument(); + }); + fireEvent.click(getByText(translations.close)); await waitFor(() => { - fireEvent.click(getByText(translations.addNew)); - expect(queryByText(translations.RClose)).toBeInTheDocument(); - - fireEvent.click(getByText(translations.RClose)); expect(queryByText(translations.close)).not.toBeInTheDocument(); }); }); @@ -548,8 +547,8 @@ describe('Testing Advertisement Register Component', () => { , ); - fireEvent.click(screen.getByText(translations.addNew)); - await screen.findByText(translations.RClose); + fireEvent.click(screen.getByText(translations.createAdvertisement)); + await screen.findByText(translations.addNew); const mediaFile = new File(['video content'], 'test.mp4', { type: 'video/mp4', diff --git a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.tsx b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.tsx index 8261c304f2..78bfec9ead 100644 --- a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.tsx +++ b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.tsx @@ -24,7 +24,7 @@ interface InterfaceAddOnRegisterProps { advertisementMediaEdit?: string; endDateEdit?: Date; startDateEdit?: Date; - setAfter: any; + setAfter: React.Dispatch>; } interface InterfaceFormStateTypes { name: string; @@ -46,6 +46,7 @@ function advertisementRegister({ setAfter, }: InterfaceAddOnRegisterProps): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'advertisement' }); + const { t: tCommon } = useTranslation('common'); const { orgId: currentOrg } = useParams(); @@ -198,8 +199,10 @@ function advertisementRegister({ handleClose(); setAfter(null); } - } catch (error: any) { - toast.error(error.message); + } catch (error: unknown) { + if (error instanceof Error) { + toast.error(error.message); + } } }; return ( @@ -213,18 +216,18 @@ function advertisementRegister({ data-testid="createAdvertisement" > - {t('addNew')} + {t('createAdvertisement')} ) : (
- {t('edit')} + {tCommon('edit')}
)} {formStatus === 'register' ? ( - {t('RClose')} + {t('addNew')} ) : ( {t('editAdvertisement')} )} @@ -366,7 +369,7 @@ function advertisementRegister({ onClick={handleClose} data-testid="addonclose" > - {t('close')} + {tCommon('close')} {formStatus === 'register' ? ( ) : ( )} diff --git a/src/components/CollapsibleDropdown/CollapsibleDropdown.test.tsx b/src/components/CollapsibleDropdown/CollapsibleDropdown.test.tsx index f7c94b223b..cfb1001e6b 100644 --- a/src/components/CollapsibleDropdown/CollapsibleDropdown.test.tsx +++ b/src/components/CollapsibleDropdown/CollapsibleDropdown.test.tsx @@ -4,6 +4,10 @@ import { BrowserRouter } from 'react-router-dom'; import CollapsibleDropdown from './CollapsibleDropdown'; import type { InterfaceCollapsibleDropdown } from './CollapsibleDropdown'; +import { store } from 'state/store'; +import { Provider } from 'react-redux'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), @@ -41,7 +45,11 @@ describe('Testing CollapsibleDropdown component', () => { test('Component should be rendered properly', () => { render( - + + + + + , ); expect(screen.getByText('DropDown Category')).toBeInTheDocument(); @@ -52,7 +60,11 @@ describe('Testing CollapsibleDropdown component', () => { test('Dropdown should be rendered and functioning correctly', () => { render( - + + + + + , ); const parentDropdownBtn = screen.getByTestId('collapsible-dropdown'); diff --git a/src/components/CollapsibleDropdown/CollapsibleDropdown.tsx b/src/components/CollapsibleDropdown/CollapsibleDropdown.tsx index 03f08b044f..4b85a1911b 100644 --- a/src/components/CollapsibleDropdown/CollapsibleDropdown.tsx +++ b/src/components/CollapsibleDropdown/CollapsibleDropdown.tsx @@ -4,6 +4,7 @@ import type { TargetsType } from 'state/reducers/routesReducer'; import styles from './CollapsibleDropdown.module.css'; import IconComponent from 'components/IconComponent/IconComponent'; import { NavLink, useLocation, useNavigate } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; export interface InterfaceCollapsibleDropdown { showDropdown: boolean; @@ -16,6 +17,7 @@ const collapsibleDropdown = ({ showDropdown, setShowDropdown, }: InterfaceCollapsibleDropdown): JSX.Element => { + const { t: tCommon } = useTranslation('common'); const { name, subTargets } = target; const navigate = useNavigate(); const location = useLocation(); @@ -42,7 +44,7 @@ const collapsibleDropdown = ({ fill={showDropdown ? 'var(--bs-white)' : 'var(--bs-secondary)'} /> - {name} + {tCommon(name)} - {name} + {tCommon(name || '')}
- {t('cancel')} + {tCommon('cancel')}
} + /> + Event Dashboard (User)} + /> @@ -125,7 +136,7 @@ describe('Testing Event List Card', () => { test('Should navigate to "/" if orgId is not defined', async () => { render( - + { }); }); - test('Should navigate to event dashboard when clicked', async () => { + test('Should navigate to event dashboard when clicked (For Admin)', async () => { renderEventListCard(props[1]); userEvent.click(screen.getByTestId('card')); @@ -300,6 +311,25 @@ describe('Testing Event List Card', () => { await waitFor(() => { expect(screen.queryByTestId('card')).not.toBeInTheDocument(); + expect(screen.queryByText('Event Dashboard (Admin)')).toBeInTheDocument(); + }); + }); + + test('Should navigate to event dashboard when clicked (For User)', async () => { + setItem('userId', '123'); + renderEventListCard(props[2]); + + userEvent.click(screen.getByTestId('card')); + + await waitFor(() => { + expect(screen.getByTestId('showEventDashboardBtn')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('showEventDashboardBtn')); + + await waitFor(() => { + expect(screen.queryByTestId('card')).not.toBeInTheDocument(); + expect(screen.queryByText('Event Dashboard (User)')).toBeInTheDocument(); }); }); @@ -853,7 +883,7 @@ describe('Testing Event List Card', () => { - + ); diff --git a/src/components/EventListCard/EventListCardModals.tsx b/src/components/EventListCard/EventListCardModals.tsx index 7fdc85647a..51612f45e5 100644 --- a/src/components/EventListCard/EventListCardModals.tsx +++ b/src/components/EventListCard/EventListCardModals.tsx @@ -47,6 +47,7 @@ interface InterfaceEventListCardModalProps { eventModalIsOpen: boolean; hideViewModal: () => void; t: (key: string) => string; + tCommon: (key: string) => string; } function EventListCardModals({ @@ -54,6 +55,7 @@ function EventListCardModals({ eventModalIsOpen, hideViewModal, t, + tCommon, }: InterfaceEventListCardModalProps): JSX.Element { const { refetchEvents } = eventListCardProps; @@ -322,7 +324,7 @@ function EventListCardModals({ (registrant) => registrant._id === userId, ); const [registerEventMutation] = useMutation(REGISTER_EVENT); - const [isRegistered, setIsRegistered] = React.useState(isInitiallyRegistered); + const [isRegistered, setIsRegistered] = useState(isInitiallyRegistered); const registerEventHandler = async (): Promise => { if (!isRegistered) { @@ -352,7 +354,9 @@ function EventListCardModals({ }; const openEventDashboard = (): void => { - navigate(`/event/${orgId}/${eventListCardProps.id}`); + const userPath = eventListCardProps.userRole === Role.USER ? 'user/' : ''; + console.log(`/${userPath}event/${orgId}/${eventListCardProps.id}`); + navigate(`/${userPath}event/${orgId}/${eventListCardProps.id}`); }; const popover = ( @@ -404,7 +408,7 @@ function EventListCardModals({ eventListCardProps.userRole === Role.USER } /> -

{t('description')}

+

{tCommon('description')}

-

{t('location')}

+

{tCommon('location')}

{ @@ -480,7 +484,7 @@ function EventListCardModals({
{ @@ -496,7 +500,7 @@ function EventListCardModals({
)} @@ -671,7 +676,7 @@ function EventListCardModals({ onClick={registerEventHandler} data-testid="registerEventBtn" > - {t('registerEvent')} + {tCommon('register')} ))} @@ -725,7 +730,7 @@ function EventListCardModals({ onClick={toggleRecurringEventUpdateModal} data-testid="eventUpdateOptionsModalCloseBtn" > - {t('no')} + {tCommon('no')} @@ -791,7 +796,7 @@ function EventListCardModals({ onClick={toggleDeleteModal} data-testid="eventDeleteModalCloseBtn" > - {t('no')} + {tCommon('no')} diff --git a/src/components/EventManagement/EventActionItems/EventActionItems.module.css b/src/components/EventManagement/EventActionItems/EventActionItems.module.css index a73fd82113..1253dd7a2f 100644 --- a/src/components/EventManagement/EventActionItems/EventActionItems.module.css +++ b/src/components/EventManagement/EventActionItems/EventActionItems.module.css @@ -42,9 +42,9 @@ position: relative; } -input { +/* input { outline: 1px solid var(--bs-gray-400); -} +} */ .btnsContainer .input button { width: 52px; diff --git a/src/components/EventManagement/EventActionItems/EventActionItems.tsx b/src/components/EventManagement/EventActionItems/EventActionItems.tsx index d23cfd3bee..26273c213d 100644 --- a/src/components/EventManagement/EventActionItems/EventActionItems.tsx +++ b/src/components/EventManagement/EventActionItems/EventActionItems.tsx @@ -33,6 +33,7 @@ function eventActionItems(props: { eventId: string }): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'eventActionItems', }); + const { t: tCommon } = useTranslation('common'); const [actionItemCreateModalIsOpen, setActionItemCreateModalIsOpen] = useState(false); @@ -533,7 +534,7 @@ function eventActionItems(props: { eventId: string }): JSX.Element { onClick={toggleDeleteModal} data-testid="actionItemDeleteModalCloseBtn" > - {t('no')} + {tCommon('no')} diff --git a/src/components/LeftDrawer/LeftDrawer.tsx b/src/components/LeftDrawer/LeftDrawer.tsx index 94d4974d0f..dc501d6185 100644 --- a/src/components/LeftDrawer/LeftDrawer.tsx +++ b/src/components/LeftDrawer/LeftDrawer.tsx @@ -19,6 +19,7 @@ const leftDrawer = ({ setHideDrawer, }: InterfaceLeftDrawerProps): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'leftDrawer' }); + const { t: tCommon } = useTranslation('common'); const { getItem } = useLocalStorage(); const superAdmin = getItem('SuperAdmin'); @@ -42,8 +43,10 @@ const leftDrawer = ({ data-testid="leftDrawerContainer" > -

{t('talawaAdminPortal')}

-
{t('menu')}
+

{tCommon('talawaAdminPortal')}

+
+ {tCommon('menu')} +
{({ isActive }) => ( @@ -87,7 +90,7 @@ const leftDrawer = ({ }`} />
- {t('users')} + {tCommon('users')} )} diff --git a/src/components/LeftDrawerOrg/LeftDrawerOrg.tsx b/src/components/LeftDrawerOrg/LeftDrawerOrg.tsx index 115b2cf7bc..6cc501db45 100644 --- a/src/components/LeftDrawerOrg/LeftDrawerOrg.tsx +++ b/src/components/LeftDrawerOrg/LeftDrawerOrg.tsx @@ -27,7 +27,7 @@ const leftDrawerOrg = ({ hideDrawer, setHideDrawer, }: InterfaceLeftDrawerProps): JSX.Element => { - const { t } = useTranslation('translation', { keyPrefix: 'leftDrawerOrg' }); + const { t: tCommon } = useTranslation('common'); const [showDropdown, setShowDropdown] = React.useState(false); const [organization, setOrganization] = @@ -76,7 +76,9 @@ const leftDrawerOrg = ({ {/* Branding Section */}
- {t('talawaAdminPortal')} + + {tCommon('talawaAdminPortal')} +
{/* Organization Section */} @@ -126,7 +128,7 @@ const leftDrawerOrg = ({ {/* Options List */}
- {t('menu')} + {tCommon('menu')}
{targets.map(({ name, url }, index) => { return url ? ( @@ -141,7 +143,7 @@ const leftDrawerOrg = ({ >
- {name} + {tCommon(name)} )} diff --git a/src/components/LoginPortalToggle/LoginPortalToggle.tsx b/src/components/LoginPortalToggle/LoginPortalToggle.tsx index 359cfd577a..c1feb9f4da 100644 --- a/src/components/LoginPortalToggle/LoginPortalToggle.tsx +++ b/src/components/LoginPortalToggle/LoginPortalToggle.tsx @@ -12,7 +12,7 @@ interface InterfaceLoginPortalToggleProps { function loginPortalToggle({ onToggle, }: InterfaceLoginPortalToggleProps): JSX.Element { - const { t } = useTranslation('translation', { keyPrefix: 'loginPage' }); + const { t: tCommon } = useTranslation('common'); const [activeRole, setActiveRole] = useState<'admin' | 'user'>('admin'); const handleNavLinkClick = (role: 'admin' | 'user'): void => { @@ -28,7 +28,7 @@ function loginPortalToggle({ to="/" onClick={() => handleNavLinkClick('admin')} > - {t('admin')} + {tCommon('admin')} @@ -37,7 +37,7 @@ function loginPortalToggle({ to="/" onClick={() => handleNavLinkClick('user')} > - {t('user')} + {tCommon('user')} diff --git a/src/components/MemberRequestCard/MemberRequestCard.tsx b/src/components/MemberRequestCard/MemberRequestCard.tsx index 1ce1f1924c..462e78d2ee 100644 --- a/src/components/MemberRequestCard/MemberRequestCard.tsx +++ b/src/components/MemberRequestCard/MemberRequestCard.tsx @@ -32,6 +32,7 @@ function memberRequestCard( const { t } = useTranslation('translation', { keyPrefix: 'membershipRequest', }); + const { t: tCommon } = useTranslation('common'); const addMember = async (): Promise => { try { @@ -47,7 +48,7 @@ function memberRequestCard( setTimeout(() => { window.location.reload(); }, 2000); - } catch (error: any) { + } catch (error: unknown) { /* istanbul ignore next */ errorHandler(t, error); } @@ -65,7 +66,7 @@ function memberRequestCard( /* istanbul ignore next */ window.location.reload(); - } catch (error: any) { + } catch (error: unknown) { /* istanbul ignore next */ errorHandler(t, error); } @@ -99,7 +100,7 @@ function memberRequestCard(

- {t('joined')}: {props.joinDate} + {tCommon('joined')}: {props.joinDate}

@@ -210,7 +211,7 @@ const OrgActionItemCategories = (): any => { className="me-2" data-testid="actionItemCategoryUpdateModalOpenBtn" > - {t('editButton')} + {tCommon('edit')} diff --git a/src/components/OrgAdminListCard/OrgAdminListCard.test.tsx b/src/components/OrgAdminListCard/OrgAdminListCard.test.tsx index cb2492d306..282dedb330 100644 --- a/src/components/OrgAdminListCard/OrgAdminListCard.test.tsx +++ b/src/components/OrgAdminListCard/OrgAdminListCard.test.tsx @@ -57,7 +57,12 @@ const renderOrgAdminListCard = (props: { , ); }; - +jest.mock('i18next-browser-languagedetector', () => ({ + init: jest.fn(), + type: 'languageDetector', + detect: jest.fn(() => 'en'), + cacheUserLanguage: jest.fn(), +})); describe('Testing Organization Admin List Card', () => { global.alert = jest.fn(); diff --git a/src/components/OrgAdminListCard/OrgAdminListCard.tsx b/src/components/OrgAdminListCard/OrgAdminListCard.tsx index 6d60af9338..9afb47000d 100644 --- a/src/components/OrgAdminListCard/OrgAdminListCard.tsx +++ b/src/components/OrgAdminListCard/OrgAdminListCard.tsx @@ -23,6 +23,7 @@ function orgAdminListCard(props: InterfaceOrgPeopleListCardProps): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'orgAdminListCard', }); + const { t: tCommon } = useTranslation('common'); const removeAdmin = async (): Promise => { try { @@ -55,14 +56,14 @@ function orgAdminListCard(props: InterfaceOrgPeopleListCardProps): JSX.Element { {t('removeAdminMsg')} diff --git a/src/components/OrgListCard/OrgListCard.tsx b/src/components/OrgListCard/OrgListCard.tsx index ef1e5efeba..bdba9107b0 100644 --- a/src/components/OrgListCard/OrgListCard.tsx +++ b/src/components/OrgListCard/OrgListCard.tsx @@ -50,6 +50,7 @@ function orgListCard(props: InterfaceOrgListCardProps): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'orgListCard', }); + const { t: tCommon } = useTranslation('common'); return ( <> @@ -83,8 +84,8 @@ function orgListCard(props: InterfaceOrgListCardProps): JSX.Element {
)}
- {t('admins')}: {admins.length}      {' '} - {t('members')}: {members.length} + {tCommon('admins')}: {admins.length}     +   {tCommon('members')}: {members.length}
diff --git a/src/components/OrgPeopleListCard/OrgPeopleListCard.tsx b/src/components/OrgPeopleListCard/OrgPeopleListCard.tsx index 7e696e62db..781443847b 100644 --- a/src/components/OrgPeopleListCard/OrgPeopleListCard.tsx +++ b/src/components/OrgPeopleListCard/OrgPeopleListCard.tsx @@ -25,6 +25,7 @@ function orgPeopleListCard( const { t } = useTranslation('translation', { keyPrefix: 'orgPeopleListCard', }); + const { t: tCommon } = useTranslation('common'); const removeMember = async (): Promise => { try { @@ -59,7 +60,7 @@ function orgPeopleListCard( {t('removeMemberMsg')} diff --git a/src/components/OrgPostCard/OrgPostCard.test.tsx b/src/components/OrgPostCard/OrgPostCard.test.tsx index b89fc6cd99..863ed2822b 100644 --- a/src/components/OrgPostCard/OrgPostCard.test.tsx +++ b/src/components/OrgPostCard/OrgPostCard.test.tsx @@ -78,6 +78,12 @@ jest.mock('react-toastify', () => ({ error: jest.fn(), }, })); +jest.mock('i18next-browser-languagedetector', () => ({ + init: jest.fn(), + type: 'languageDetector', + detect: jest.fn(() => 'en'), + cacheUserLanguage: jest.fn(), +})); const link = new StaticMockLink(MOCKS, true); async function wait(ms = 100): Promise { await act(() => { diff --git a/src/components/OrgPostCard/OrgPostCard.tsx b/src/components/OrgPostCard/OrgPostCard.tsx index 17fa9fb94a..be71622c7c 100644 --- a/src/components/OrgPostCard/OrgPostCard.tsx +++ b/src/components/OrgPostCard/OrgPostCard.tsx @@ -1,7 +1,5 @@ import { useMutation } from '@apollo/client'; -import CloseIcon from '@mui/icons-material/Close'; -import MoreVertIcon from '@mui/icons-material/MoreVert'; -import PushPinIcon from '@mui/icons-material/PushPin'; +import { Close, MoreVert, PushPin } from '@mui/icons-material'; import { DELETE_POST_MUTATION, TOGGLE_PINNED_POST, @@ -10,17 +8,13 @@ import { import AboutImg from 'assets/images/defaultImg.png'; import type { ChangeEvent } from 'react'; import React, { useEffect, useRef, useState } from 'react'; -import { Form } from 'react-bootstrap'; -import Button from 'react-bootstrap/Button'; -import Card from 'react-bootstrap/Card'; -import Modal from 'react-bootstrap/Modal'; +import { Form, Button, Card, Modal } from 'react-bootstrap'; import { useTranslation } from 'react-i18next'; import { toast } from 'react-toastify'; import convertToBase64 from 'utils/convertToBase64'; import { errorHandler } from 'utils/errorHandler'; import type { InterfacePostForm } from 'utils/interfaces'; import styles from './OrgPostCard.module.css'; - interface InterfaceOrgPostCardProps { key: string; id: string; @@ -31,7 +25,6 @@ interface InterfaceOrgPostCardProps { postVideo: string | null; pinned: boolean; } - export default function orgPostCard( props: InterfaceOrgPostCardProps, ): JSX.Element { @@ -42,7 +35,6 @@ export default function orgPostCard( postvideo: '', pinned: false, }); - // console.log('postformState', postformState); const [postPhotoUpdated, setPostPhotoUpdated] = useState(false); const [postVideoUpdated, setPostVideoUpdated] = useState(false); const [togglePost, setPostToggle] = useState('Read more'); @@ -70,7 +62,6 @@ export default function orgPostCard( } } catch (error: unknown) { if (error instanceof Error) { - console.log(error.message); /* istanbul ignore next */ errorHandler(t, error); } @@ -89,12 +80,10 @@ export default function orgPostCard( setShowEditModal((prev) => !prev); }; const toggleShowDeleteModal = (): void => setShowDeleteModal((prev) => !prev); - const handleVideoPlay = (): void => { setPlaying(true); videoRef.current?.play(); }; - const handleVideoPause = (): void => { setPlaying(false); videoRef.current?.pause(); @@ -102,7 +91,6 @@ export default function orgPostCard( const handleCardClick = (): void => { setModalVisible(true); }; - const handleMoreOptionsClick = (): void => { setMenuVisible(true); }; @@ -119,7 +107,6 @@ export default function orgPostCard( fileInput.value = ''; } }; - const clearVideoInput = (): void => { setPostFormState({ ...postformState, @@ -140,7 +127,6 @@ export default function orgPostCard( setPostToggle('Read more'); } } - function handleEditModal(): void { setModalVisible(false); setMenuVisible(false); @@ -151,15 +137,12 @@ export default function orgPostCard( postvideo: props.postVideo, }); } - function handleDeleteModal(): void { setModalVisible(false); setMenuVisible(false); setShowDeleteModal(true); } - useEffect(() => { - // console.log(props.postPhoto); setPostFormState({ posttitle: props.postTitle, postinfo: props.postInfo, @@ -168,14 +151,12 @@ export default function orgPostCard( pinned: props.pinned, }); }, []); - const { t } = useTranslation('translation', { keyPrefix: 'orgPostCard', }); - + const { t: tCommon } = useTranslation('common'); const [deletePostMutation] = useMutation(DELETE_POST_MUTATION); const [updatePostMutation] = useMutation(UPDATE_POST_MUTATION); - const deletePost = async (): Promise => { try { const { data } = await deletePostMutation({ @@ -183,7 +164,6 @@ export default function orgPostCard( id: props.id, }, }); - if (data) { toast.success(t('postDeleted')); toggleShowDeleteModal(); @@ -191,7 +171,7 @@ export default function orgPostCard( window.location.reload(); }); } - } catch (error: any) { + } catch (error: unknown) { errorHandler(t, error); } }; @@ -204,12 +184,10 @@ export default function orgPostCard( [name]: value, })); }; - const updatePostHandler = async ( e: ChangeEvent, ): Promise => { e.preventDefault(); - try { const { data } = await updatePostMutation({ variables: { @@ -224,18 +202,18 @@ export default function orgPostCard( }), }, }); - if (data) { toast.success(t('postUpdated')); setTimeout(() => { window.location.reload(); }, 2000); } - } catch (error: any) { - toast.error(error.message); + } catch (error: unknown) { + if (error instanceof Error) { + toast.error(error.message); + } } }; - return ( <>
@@ -263,7 +241,7 @@ export default function orgPostCard( {props.pinned && ( - {props.pinned && ( - + )} {props.postTitle} @@ -316,7 +290,7 @@ export default function orgPostCard( /> {props.pinned && ( -
)} -

{t('author')}: {props.postAuthor} @@ -395,19 +368,18 @@ export default function orgPostCard( onClick={handleMoreOptionsClick} data-testid="moreiconbtn" > - +

)} - {menuVisible && (
@@ -418,7 +390,7 @@ export default function orgPostCard( onClick={handleEditModal} data-testid="editPostModalBtn" > - {t('edit')} + {tCommon('edit')}
  • setMenuVisible(false)} data-testid="closebtn" > - {t('close')} + {tCommon('close')}
  • )}
    - - {/* Delete Modal */}
    {t('deletePost')}
    @@ -460,7 +430,7 @@ export default function orgPostCard( {t('deletePostMsg')}
    - - {/* Edit Modal */} - {t('close')} + {tCommon('close')}
    diff --git a/src/components/OrgUpdate/OrgUpdate.tsx b/src/components/OrgUpdate/OrgUpdate.tsx index b19ba4af92..e2820f3b49 100644 --- a/src/components/OrgUpdate/OrgUpdate.tsx +++ b/src/components/OrgUpdate/OrgUpdate.tsx @@ -66,6 +66,7 @@ function orgUpdate(props: InterfaceOrgUpdateProps): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'orgUpdate', }); + const { t: tCommon } = useTranslation('common'); const { data, @@ -130,7 +131,7 @@ function orgUpdate(props: InterfaceOrgUpdateProps): JSX.Element { refetch({ id: orgId }); toast.success(t('successfulUpdated')); } - } catch (error: any) { + } catch (error: unknown) { errorHandler(t, error); } }; @@ -156,7 +157,7 @@ function orgUpdate(props: InterfaceOrgUpdateProps): JSX.Element { <>
    - {t('name')} + {tCommon('name')} - {t('description')} + {tCommon('description')} - {t('address')} + {tCommon('address')} - {t('displayImage')}: + {tCommon('displayImage')}: - {t('saveChanges')} + {tCommon('saveChanges')}
    diff --git a/src/components/RecurrenceOptions/CustomRecurrenceModal.tsx b/src/components/RecurrenceOptions/CustomRecurrenceModal.tsx index 890caaabdb..c1aecaa854 100644 --- a/src/components/RecurrenceOptions/CustomRecurrenceModal.tsx +++ b/src/components/RecurrenceOptions/CustomRecurrenceModal.tsx @@ -35,6 +35,7 @@ interface InterfaceCustomRecurrenceModalProps { state: React.SetStateAction, ) => void; t: (key: string) => string; + tCommon: (key: string) => string; } const CustomRecurrenceModal: React.FC = ({ @@ -45,6 +46,7 @@ const CustomRecurrenceModal: React.FC = ({ hideCustomRecurrenceModal, setCustomRecurrenceModalIsOpen, t, + tCommon, }) => { const { recurrenceStartDate, @@ -335,7 +337,7 @@ const CustomRecurrenceModal: React.FC = ({ {option === endsOn && (
    = ({ data-testid="customRecurrenceSubmitBtn" onClick={handleCustomRecurrenceSubmit} > - {t('done')} + {tCommon('done')}
    diff --git a/src/components/RecurrenceOptions/RecurrenceOptions.test.tsx b/src/components/RecurrenceOptions/RecurrenceOptions.test.tsx index 5e32a6ec8b..510f7a04aa 100644 --- a/src/components/RecurrenceOptions/RecurrenceOptions.test.tsx +++ b/src/components/RecurrenceOptions/RecurrenceOptions.test.tsx @@ -14,7 +14,7 @@ import { I18nextProvider } from 'react-i18next'; import OrganizationEvents from '../../screens/OrganizationEvents/OrganizationEvents'; import { store } from 'state/store'; -import i18nForTest from 'utils/i18nForTest'; +import i18n from 'utils/i18nForTest'; import userEvent from '@testing-library/user-event'; import { StaticMockLink } from 'utils/StaticMockLink'; import { toast } from 'react-toastify'; @@ -42,11 +42,15 @@ async function wait(ms = 100): Promise { }); } -const translations = JSON.parse( - JSON.stringify( - i18nForTest.getDataByLanguage('en')?.translation.organizationEvents, +const translations = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.organizationEvents ?? {}, + ), ), -); + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; jest.mock('@mui/x-date-pickers/DateTimePicker', () => { return { @@ -82,7 +86,7 @@ describe('Testing the creaction of recurring events through recurrence options', - + @@ -120,7 +124,7 @@ describe('Testing the creaction of recurring events through recurrence options', - + @@ -164,7 +168,7 @@ describe('Testing the creaction of recurring events through recurrence options', - + @@ -224,7 +228,7 @@ describe('Testing the creaction of recurring events through recurrence options', - + @@ -348,7 +352,7 @@ describe('Testing the creaction of recurring events through recurrence options', - + @@ -466,7 +470,7 @@ describe('Testing the creaction of recurring events through recurrence options', - + diff --git a/src/components/RecurrenceOptions/RecurrenceOptions.tsx b/src/components/RecurrenceOptions/RecurrenceOptions.tsx index cf93410dab..f3a4e61226 100644 --- a/src/components/RecurrenceOptions/RecurrenceOptions.tsx +++ b/src/components/RecurrenceOptions/RecurrenceOptions.tsx @@ -19,6 +19,7 @@ interface InterfaceRecurrenceOptionsProps { ) => void; popover: JSX.Element; t: (key: string) => string; + tCommon: (key: string) => string; } const RecurrenceOptions: React.FC = ({ @@ -27,6 +28,7 @@ const RecurrenceOptions: React.FC = ({ setRecurrenceRuleState, popover, t, + tCommon, }) => { const [customRecurrenceModalIsOpen, setCustomRecurrenceModalIsOpen] = useState(false); @@ -220,6 +222,7 @@ const RecurrenceOptions: React.FC = ({ hideCustomRecurrenceModal={hideCustomRecurrenceModal} setCustomRecurrenceModalIsOpen={setCustomRecurrenceModalIsOpen} t={t} + tCommon={tCommon} /> ); diff --git a/src/components/UserPasswordUpdate/UserPasswordUpdate.tsx b/src/components/UserPasswordUpdate/UserPasswordUpdate.tsx index cbb771be0e..78fea1df53 100644 --- a/src/components/UserPasswordUpdate/UserPasswordUpdate.tsx +++ b/src/components/UserPasswordUpdate/UserPasswordUpdate.tsx @@ -17,6 +17,7 @@ const UserUpdate: React.FC< const { t } = useTranslation('translation', { keyPrefix: 'userPasswordUpdate', }); + const { t: tCommon } = useTranslation('common'); const [formState, setFormState] = React.useState({ previousPassword: '', newPassword: '', @@ -55,9 +56,11 @@ const UserUpdate: React.FC< window.location.reload(); }, 2000); } - } catch (error: any) { + } catch (error: unknown) { /* istanbul ignore next */ - toast.error(error.toString()); + if (error instanceof Error) { + toast.error(error.toString()); + } } }; @@ -135,7 +138,7 @@ const UserUpdate: React.FC< value="savechanges" onClick={loginLink} > - {t('saveChanges')} + {tCommon('saveChanges')} diff --git a/src/components/UserPortal/CommentCard/CommentCard.module.css b/src/components/UserPortal/CommentCard/CommentCard.module.css index 1124f6369d..b765d60bbd 100644 --- a/src/components/UserPortal/CommentCard/CommentCard.module.css +++ b/src/components/UserPortal/CommentCard/CommentCard.module.css @@ -1,13 +1,11 @@ .mainContainer { - width: 100%; - display: flex; - flex-direction: row; - padding: 10px; + width: auto; + overflow: hidden; background-color: white; + margin-top: 1rem; + padding: 0.5rem; + border: 1px solid #dddddd; border-radius: 10px; - box-shadow: 2px 2px 8px 0px #c8c8c8; - overflow: hidden; - margin-top: 10px; } .personDetails { diff --git a/src/components/UserPortal/CommentCard/CommentCard.tsx b/src/components/UserPortal/CommentCard/CommentCard.tsx index 955f136cb5..57cc6a1cf4 100644 --- a/src/components/UserPortal/CommentCard/CommentCard.tsx +++ b/src/components/UserPortal/CommentCard/CommentCard.tsx @@ -8,6 +8,7 @@ import { toast } from 'react-toastify'; import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; import ThumbUpOffAltIcon from '@mui/icons-material/ThumbUpOffAlt'; import useLocalStorage from 'utils/useLocalstorage'; +import AccountCircleIcon from '@mui/icons-material/AccountCircle'; interface InterfaceCommentCardProps { id: string; @@ -80,7 +81,10 @@ function commentCard(props: InterfaceCommentCardProps): JSX.Element { return (
    - {creatorName} +
    + + {creatorName} +
    {props.text}
    ) : ( )}
    diff --git a/src/components/UserPortal/Login/Login.test.tsx b/src/components/UserPortal/Login/Login.test.tsx index a59d9d9063..9248c5e9ec 100644 --- a/src/components/UserPortal/Login/Login.test.tsx +++ b/src/components/UserPortal/Login/Login.test.tsx @@ -195,10 +195,7 @@ describe('Testing Login Component [User Portal]', () => { await wait(); - userEvent.type( - screen.getByPlaceholderText(/Enter your email address/i), - formData.email, - ); + userEvent.type(screen.getByPlaceholderText(/Enter Email/i), formData.email); userEvent.click(screen.getByTestId('loginBtn')); expect(toast.error).toBeCalledWith( @@ -226,13 +223,10 @@ describe('Testing Login Component [User Portal]', () => { await wait(); - userEvent.type( - screen.getByPlaceholderText(/Enter your email address/i), - formData.email, - ); + userEvent.type(screen.getByPlaceholderText(/Enter Email/i), formData.email); userEvent.type( - screen.getByPlaceholderText(/Enter your password/i), + screen.getByPlaceholderText(/Enter Password/i), formData.password, ); @@ -263,13 +257,10 @@ describe('Testing Login Component [User Portal]', () => { await wait(); - userEvent.type( - screen.getByPlaceholderText(/Enter your email address/i), - formData.email, - ); + userEvent.type(screen.getByPlaceholderText(/Enter Email/i), formData.email); userEvent.type( - screen.getByPlaceholderText(/Enter your password/i), + screen.getByPlaceholderText(/Enter Password/i), formData.password, ); @@ -299,13 +290,10 @@ describe('Testing Login Component [User Portal]', () => { await wait(); - userEvent.type( - screen.getByPlaceholderText(/Enter your email address/i), - formData.email, - ); + userEvent.type(screen.getByPlaceholderText(/Enter Email/i), formData.email); userEvent.type( - screen.getByPlaceholderText(/Enter your password/i), + screen.getByPlaceholderText(/Enter Password/i), formData.password, ); diff --git a/src/components/UserPortal/Login/Login.tsx b/src/components/UserPortal/Login/Login.tsx index 9fd40c3615..517170263e 100644 --- a/src/components/UserPortal/Login/Login.tsx +++ b/src/components/UserPortal/Login/Login.tsx @@ -19,6 +19,7 @@ interface InterfaceLoginProps { export default function login(props: InterfaceLoginProps): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'userLogin' }); + const { t: tCommon } = useTranslation('common'); const navigate = useNavigate(); @@ -52,7 +53,7 @@ export default function login(props: InterfaceLoginProps): JSX.Element { setItem('token', data.login.accessToken); setItem('userId', data.login.user._id); navigate('/user/organizations'); - } catch (error: any) { + } catch (error: unknown) { errorHandler(t, error); } } @@ -80,13 +81,13 @@ export default function login(props: InterfaceLoginProps): JSX.Element { return ( <> -

    {t('login')}

    +

    {tCommon('login')}

    -
    {t('emailAddress')}
    +
    {tCommon('emailAddress')}
    -
    {t('password')}
    +
    {tCommon('password')}
    - {t('forgotPassword')} + {tCommon('forgotPassword')}
    @@ -127,7 +128,7 @@ export default function login(props: InterfaceLoginProps): JSX.Element { onClick={handleLogin} data-testid="loginBtn" > - {t('login')} + {tCommon('login')}
    ); diff --git a/src/components/UserPortal/OrganizationCard/OrganizationCard.tsx b/src/components/UserPortal/OrganizationCard/OrganizationCard.tsx index 1d83eeac15..fdb2d040d9 100644 --- a/src/components/UserPortal/OrganizationCard/OrganizationCard.tsx +++ b/src/components/UserPortal/OrganizationCard/OrganizationCard.tsx @@ -54,6 +54,7 @@ function organizationCard(props: InterfaceOrganizationCardProps): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'users', }); + const { t: tCommon } = useTranslation('common'); const navigate = useNavigate(); @@ -94,12 +95,14 @@ function organizationCard(props: InterfaceOrganizationCardProps): JSX.Element { toast.success(t('orgJoined')); } refetch(); - } catch (error: any) { + } catch (error: unknown) { /* istanbul ignore next */ - if (error.message === 'User is already a member') { - toast.error(t('AlreadyJoined')); - } else { - toast.error(t('errorOccured')); + if (error instanceof Error) { + if (error.message === 'User is already a member') { + toast.error(t('AlreadyJoined')); + } else { + toast.error(t('errorOccured')); + } } } } @@ -150,8 +153,9 @@ function organizationCard(props: InterfaceOrganizationCardProps): JSX.Element {
    )}
    - {t('admins')}: {props.admins?.length}     -   {t('members')}: {props.members?.length} + {tCommon('admins')}: {props.admins?.length}   +     {tCommon('members')}:{' '} + {props.members?.length}
    diff --git a/src/components/UserPortal/OrganizationNavbar/OrganizationNavbar.tsx b/src/components/UserPortal/OrganizationNavbar/OrganizationNavbar.tsx index 7ecde0f275..90cd75a83c 100644 --- a/src/components/UserPortal/OrganizationNavbar/OrganizationNavbar.tsx +++ b/src/components/UserPortal/OrganizationNavbar/OrganizationNavbar.tsx @@ -30,10 +30,13 @@ function organizationNavbar(props: InterfaceNavbarProps): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'userNavbar', }); + const { t: tCommon } = useTranslation('common'); const navigate = useNavigate(); - const [organizationDetails, setOrganizationDetails]: any = React.useState({}); + const [organizationDetails, setOrganizationDetails] = React.useState<{ + name: string; + }>({ name: '' }); // const dropDirection: DropDirection = screen.width > 767 ? 'start' : 'down'; const dropDirection: DropDirection = 'start'; @@ -59,7 +62,7 @@ function organizationNavbar(props: InterfaceNavbarProps): JSX.Element { const userName = getItem('name'); React.useEffect(() => { if (data) { - setOrganizationDetails(data.organizationsConnection[0]); + setOrganizationDetails({ name: data.organizationsConnection[0].name }); } }, [data]); @@ -222,14 +225,14 @@ function organizationNavbar(props: InterfaceNavbarProps): JSX.Element { - {t('settings')} + {tCommon('settings')} - {t('logout')} + {tCommon('logout')} diff --git a/src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.tsx b/src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.tsx index 17365dcddf..6e5aa42d70 100644 --- a/src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.tsx +++ b/src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.tsx @@ -13,15 +13,20 @@ import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; import CalendarMonthIcon from '@mui/icons-material/CalendarMonth'; import dayjs from 'dayjs'; import { useTranslation } from 'react-i18next'; +import type { + InterfaceQueryOrganizationEventListItem, + InterfaceMemberInfo, +} from 'utils/interfaces'; export default function organizationSidebar(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'organizationSidebar', }); + const { t: tCommon } = useTranslation('common'); const { orgId: organizationId } = useParams(); - const [members, setMembers]: any = React.useState([]); - const [events, setEvents]: any = React.useState([]); + const [members, setMembers] = React.useState([]); + const [events, setEvents] = React.useState([]); const eventsLink = `/user/events/id=${organizationId}`; const peopleLink = `/user/people/id=${organizationId}`; @@ -64,7 +69,7 @@ export default function organizationSidebar(): JSX.Element { return (
    - {t('members')} + {tCommon('members')}
    {memberLoading ? (
    @@ -73,26 +78,31 @@ export default function organizationSidebar(): JSX.Element { ) : ( {members.length ? ( - members.map((member: any, index: React.Key | null | undefined) => { - const memberName = `${member.firstName} ${member.lastName}`; - return ( - -
    - -
    {memberName}
    -
    -
    - ); - }) + members.map( + ( + member: InterfaceMemberInfo, + index: React.Key | null | undefined, + ) => { + const memberName = `${member.firstName} ${member.lastName}`; + return ( + +
    + +
    {memberName}
    +
    +
    + ); + }, + ) ) : (
    {t('noMembers')}
    )} @@ -115,31 +125,36 @@ export default function organizationSidebar(): JSX.Element { ) : ( {events.length ? ( - events.map((event: any, index: React.Key | null | undefined) => { - return ( - -
    -
    -
    {event.title}
    -
    - + events.map( + ( + event: InterfaceQueryOrganizationEventListItem, + index: React.Key | null | undefined, + ) => { + return ( + +
    +
    +
    {event.title}
    +
    + +
    +
    +
    + Starts{' '} + {dayjs(event.startDate).format("D MMMM 'YY")} +
    +
    + Ends {dayjs(event.endDate).format("D MMMM 'YY")}
    -
    - Starts{' '} - {dayjs(event.startDate).format("D MMMM 'YY")} -
    -
    - Ends {dayjs(event.endDate).format("D MMMM 'YY")} -
    -
    - - ); - }) + + ); + }, + ) ) : (
    {t('noEvents')}
    )} diff --git a/src/components/UserPortal/PostCard/PostCard.module.css b/src/components/UserPortal/PostCard/PostCard.module.css index 56158473f9..857c4d0799 100644 --- a/src/components/UserPortal/PostCard/PostCard.module.css +++ b/src/components/UserPortal/PostCard/PostCard.module.css @@ -1,31 +1,131 @@ -.cardActions { +.cardStyles { + height: 28rem; + max-height: 30rem; + width: 20rem; + background-color: white; + padding: 0; + border: none !important; + outline: none !important; +} + +.cardHeader { display: flex; + width: 100%; + padding-inline: 0; + padding-block: 0; flex-direction: row; + gap: 0.5rem; align-items: center; - gap: 1px; + background-color: white; + border-bottom: 1px solid #dddddd; } -.cardActionBtn { - background-color: rgba(0, 0, 0, 0); +.creator { + display: flex; + width: 100%; + padding-inline: 1rem; + padding-block: 0; + flex-direction: row; + gap: 0.5rem; + align-items: center; +} +.creator p { + margin-bottom: 0; + font-weight: 500; +} +.creator svg { + width: 2rem; + height: 2rem; +} + +.customToggle { + padding: 0; + background: none; border: none; + margin-right: 1rem; + --bs-btn-active-bg: none; +} +.customToggle svg { color: black; } -.cardActionBtn:hover { - background-color: ghostwhite; +.customToggle::after { + content: none; +} +.customToggle:hover, +.customToggle:focus, +.customToggle:active { + background: none; border: none; - color: black !important; +} +.customToggle svg { + color: black; +} + +.cardBody div { + padding: 0.5rem; } .imageContainer { max-width: 100%; } -.cardHeader { +.cardTitle { + --max-lines: 1; + display: -webkit-box; + overflow: hidden; + -webkit-box-orient: vertical; + -webkit-line-clamp: var(--max-lines); + + font-size: 1.3rem !important; + font-weight: 600; +} + +.date { + font-weight: 600; +} + +.cardText { + --max-lines: 2; + display: -webkit-box; + overflow: hidden; + -webkit-box-orient: vertical; + -webkit-line-clamp: var(--max-lines); + + padding-top: 0; + font-weight: 300; + margin-top: 0.7rem !important; + text-align: justify; +} + +.viewBtn { + display: flex; + justify-content: flex-end; + margin: 0.5rem; +} +.viewBtn Button { + padding-inline: 1rem; +} + +.cardActions { display: flex; flex-direction: row; - gap: 10px; align-items: center; + gap: 1px; + justify-content: flex-end; +} + +.cardActionBtn { + background-color: rgba(0, 0, 0, 0); + padding: 0; + border: none; + color: black; +} + +.cardActionBtn:hover { + background-color: ghostwhite; + border: none; + color: black !important; } .creatorNameModal { @@ -40,7 +140,7 @@ display: flex; flex-direction: row; align-items: center; - gap: 1px; + gap: 1rem; margin: 5px 0px; } @@ -53,3 +153,28 @@ color: white; cursor: pointer; } + +.commentContainer { + overflow: auto; + max-height: 18rem; + padding-bottom: 1rem; +} + +.modalFooter { + background-color: white; + position: absolute; + width: calc(100% - 1rem); + padding-block: 0.5rem; + display: flex; + flex-direction: column; + border-top: 1px solid #dddddd; + bottom: 0; + right: 0.5rem; + margin-left: 1rem; +} + +.inputArea { + border: none; + outline: none; + background-color: #f1f3f6; +} diff --git a/src/components/UserPortal/PostCard/PostCard.test.tsx b/src/components/UserPortal/PostCard/PostCard.test.tsx index aa170f63a8..1ba0459b6d 100644 --- a/src/components/UserPortal/PostCard/PostCard.test.tsx +++ b/src/components/UserPortal/PostCard/PostCard.test.tsx @@ -7,6 +7,7 @@ import { BrowserRouter } from 'react-router-dom'; import { store } from 'state/store'; import i18nForTest from 'utils/i18nForTest'; import { StaticMockLink } from 'utils/StaticMockLink'; +import { toast } from 'react-toastify'; import PostCard from './PostCard'; import userEvent from '@testing-library/user-event'; @@ -16,11 +17,21 @@ import { UNLIKE_POST, LIKE_COMMENT, UNLIKE_COMMENT, + DELETE_POST_MUTATION, + UPDATE_POST_MUTATION, } from 'GraphQl/Mutations/mutations'; import useLocalStorage from 'utils/useLocalstorage'; const { setItem, getItem } = useLocalStorage(); +jest.mock('react-toastify', () => ({ + toast: { + error: jest.fn(), + info: jest.fn(), + success: jest.fn(), + }, +})); + const MOCKS = [ { request: { @@ -109,6 +120,37 @@ const MOCKS = [ }, }, }, + { + request: { + query: UPDATE_POST_MUTATION, + variables: { + id: 'postId', + text: 'Edited Post', + }, + }, + result: { + data: { + updatePost: { + _id: '', + }, + }, + }, + }, + { + request: { + query: DELETE_POST_MUTATION, + variables: { + id: 'postId', + }, + }, + result: { + data: { + removePost: { + _id: '', + }, + }, + }, + }, ]; async function wait(ms = 100): Promise { @@ -124,13 +166,15 @@ const link = new StaticMockLink(MOCKS, true); describe('Testing PostCard Component [User Portal]', () => { test('Component should be rendered properly', async () => { const cardProps = { - id: '', + id: 'postId', + userImage: 'image.png', creator: { firstName: 'test', lastName: 'user', email: 'test@user.com', id: '1', }, + postedAt: '', image: '', video: '', text: 'This is post test text', @@ -152,6 +196,20 @@ describe('Testing PostCard Component [User Portal]', () => { text: 'First comment from Talawa user portal.', __typename: 'Comment', }, + { + id: '64eb13beca85de60ebe0ed0b', + creator: { + _id: '63d6064458fce20ee25c3bf8', + firstName: 'Priyanshu', + lastName: 'Bartwal', + email: 'test1@gmail.com', + __typename: 'User', + }, + likeCount: 0, + likedBy: [], + text: 'First comment from Talawa user portal.', + __typename: 'Comment', + }, ], likedBy: [ { @@ -160,6 +218,101 @@ describe('Testing PostCard Component [User Portal]', () => { id: '2', }, ], + fetchPosts: jest.fn(), + }; + + render( + + + + + + + + + , + ); + + await wait(); + }); + + test('Dropdown component should be rendered properly', async () => { + setItem('userId', '2'); + + const cardProps = { + id: '', + userImage: 'image.png', + creator: { + firstName: 'test', + lastName: 'user', + email: 'test@user.com', + id: '1', + }, + postedAt: '', + image: '', + video: '', + text: 'This is post test text', + title: 'This is post test title', + likeCount: 1, + commentCount: 0, + comments: [], + likedBy: [ + { + firstName: 'test', + lastName: 'user', + id: '2', + }, + ], + fetchPosts: jest.fn(), + }; + + render( + + + + + + + + + , + ); + await wait(); + + userEvent.click(screen.getByTestId('dropdown')); + await wait(); + expect(screen.getByText('Edit')).toBeInTheDocument(); + expect(screen.getByText('Delete')).toBeInTheDocument(); + }); + + test('Edit post should work properly', async () => { + setItem('userId', '2'); + + const cardProps = { + id: 'postId', + userImage: 'image.png', + creator: { + firstName: 'test', + lastName: 'user', + email: 'test@user.com', + id: '1', + }, + postedAt: '', + image: '', + video: '', + text: 'test Post', + title: 'This is post test title', + likeCount: 1, + commentCount: 0, + comments: [], + likedBy: [ + { + firstName: 'test', + lastName: 'user', + id: '2', + }, + ], + fetchPosts: jest.fn(), }; render( @@ -173,8 +326,69 @@ describe('Testing PostCard Component [User Portal]', () => { , ); + await wait(); + userEvent.click(screen.getByTestId('dropdown')); + userEvent.click(screen.getByTestId('editPost')); await wait(); + + expect(screen.getByTestId('editPostModalTitle')).toBeInTheDocument(); + userEvent.clear(screen.getByTestId('postInput')); + userEvent.type(screen.getByTestId('postInput'), 'Edited Post'); + userEvent.click(screen.getByTestId('editPostBtn')); + await wait(); + + expect(toast.success).toBeCalledWith('Successfully edited the Post.'); + }); + + test('Delete post should work properly', async () => { + setItem('userId', '2'); + + const cardProps = { + id: 'postId', + userImage: 'image.png', + creator: { + firstName: 'test', + lastName: 'user', + email: 'test@user.com', + id: '1', + }, + postedAt: '', + image: '', + video: '', + text: 'test Post', + title: 'This is post test title', + likeCount: 1, + commentCount: 0, + comments: [], + likedBy: [ + { + firstName: 'test', + lastName: 'user', + id: '2', + }, + ], + fetchPosts: jest.fn(), + }; + + render( + + + + + + + + + , + ); + await wait(); + + userEvent.click(screen.getByTestId('dropdown')); + userEvent.click(screen.getByTestId('deletePost')); + await wait(); + + expect(toast.success).toBeCalledWith('Successfully deleted the Post.'); }); test('Component should be rendered properly if user has liked the post', async () => { @@ -183,12 +397,14 @@ describe('Testing PostCard Component [User Portal]', () => { const cardProps = { id: '', + userImage: 'image.png', creator: { firstName: 'test', lastName: 'user', email: 'test@user.com', id: '1', }, + postedAt: '', image: '', video: '', text: 'This is post test text', @@ -203,6 +419,7 @@ describe('Testing PostCard Component [User Portal]', () => { id: '2', }, ], + fetchPosts: jest.fn(), }; render( @@ -230,12 +447,14 @@ describe('Testing PostCard Component [User Portal]', () => { const cardProps = { id: '', + userImage: 'image.png', creator: { firstName: 'test', lastName: 'user', email: 'test@user.com', id: '1', }, + postedAt: '', image: '', video: '', text: 'This is post test text', @@ -250,6 +469,7 @@ describe('Testing PostCard Component [User Portal]', () => { id: '2', }, ], + fetchPosts: jest.fn(), }; render( @@ -266,6 +486,7 @@ describe('Testing PostCard Component [User Portal]', () => { await wait(); + userEvent.click(screen.getByTestId('viewPostBtn')); userEvent.click(screen.getByTestId('likePostBtn')); if (beforeUserId) { @@ -279,12 +500,14 @@ describe('Testing PostCard Component [User Portal]', () => { const cardProps = { id: '', + userImage: 'image.png', creator: { firstName: 'test', lastName: 'user', email: 'test@user.com', id: '1', }, + postedAt: '', image: '', video: '', text: 'This is post test text', @@ -299,6 +522,7 @@ describe('Testing PostCard Component [User Portal]', () => { id: '1', }, ], + fetchPosts: jest.fn(), }; render( @@ -315,6 +539,7 @@ describe('Testing PostCard Component [User Portal]', () => { await wait(); + userEvent.click(screen.getByTestId('viewPostBtn')); userEvent.click(screen.getByTestId('likePostBtn')); if (beforeUserId) { @@ -325,12 +550,14 @@ describe('Testing PostCard Component [User Portal]', () => { test('Component should be rendered properly if post image is defined', async () => { const cardProps = { id: '', + userImage: 'image.png', creator: { firstName: 'test', lastName: 'user', email: 'test@user.com', id: '1', }, + postedAt: '', image: 'testImage', video: '', text: 'This is post test text', @@ -345,6 +572,7 @@ describe('Testing PostCard Component [User Portal]', () => { id: '1', }, ], + fetchPosts: jest.fn(), }; render( @@ -365,12 +593,14 @@ describe('Testing PostCard Component [User Portal]', () => { test('Comment is created successfully after create comment button is clicked.', async () => { const cardProps = { id: '1', + userImage: 'image.png', creator: { firstName: 'test', lastName: 'user', email: 'test@user.com', id: '1', }, + postedAt: '', image: 'testImage', video: '', text: 'This is post test text', @@ -385,6 +615,7 @@ describe('Testing PostCard Component [User Portal]', () => { id: '1', }, ], + fetchPosts: jest.fn(), }; render( @@ -401,7 +632,7 @@ describe('Testing PostCard Component [User Portal]', () => { const randomComment = 'testComment'; - userEvent.click(screen.getByTestId('showCommentsBtn')); + userEvent.click(screen.getByTestId('viewPostBtn')); userEvent.type(screen.getByTestId('commentInput'), randomComment); userEvent.click(screen.getByTestId('createCommentBtn')); @@ -424,6 +655,7 @@ describe('Testing PostCard Component [User Portal]', () => { title: 'This is post test title', likeCount: 1, commentCount: 1, + postedAt: '', comments: [ { id: '1', @@ -442,6 +674,23 @@ describe('Testing PostCard Component [User Portal]', () => { ], text: 'testComment', }, + { + id: '2', + creator: { + _id: '1', + id: '1', + firstName: 'test', + lastName: 'user', + email: 'test@user.com', + }, + likeCount: 1, + likedBy: [ + { + id: '2', + }, + ], + text: 'testComment', + }, ], likedBy: [ { @@ -450,6 +699,7 @@ describe('Testing PostCard Component [User Portal]', () => { id: '1', }, ], + fetchPosts: jest.fn(), }; const beforeUserId = getItem('userId'); setItem('userId', '2'); @@ -466,11 +716,9 @@ describe('Testing PostCard Component [User Portal]', () => { , ); - const showCommentsButton = screen.getByTestId('showCommentsBtn'); + userEvent.click(screen.getByTestId('viewPostBtn')); - userEvent.click(showCommentsButton); - - userEvent.click(screen.getByTestId('likeCommentBtn')); + userEvent.click(screen.getAllByTestId('likeCommentBtn')[0]); await wait(); @@ -494,6 +742,7 @@ describe('Testing PostCard Component [User Portal]', () => { title: 'This is post test title', likeCount: 1, commentCount: 1, + postedAt: '', comments: [ { id: '1', @@ -512,6 +761,23 @@ describe('Testing PostCard Component [User Portal]', () => { ], text: 'testComment', }, + { + id: '2', + creator: { + _id: '1', + id: '1', + firstName: 'test', + lastName: 'user', + email: 'test@user.com', + }, + likeCount: 1, + likedBy: [ + { + id: '2', + }, + ], + text: 'testComment', + }, ], likedBy: [ { @@ -520,6 +786,7 @@ describe('Testing PostCard Component [User Portal]', () => { id: '1', }, ], + fetchPosts: jest.fn(), }; const beforeUserId = getItem('userId'); setItem('userId', '1'); @@ -536,11 +803,9 @@ describe('Testing PostCard Component [User Portal]', () => { , ); - const showCommentsButton = screen.getByTestId('showCommentsBtn'); - - userEvent.click(showCommentsButton); + userEvent.click(screen.getByTestId('viewPostBtn')); - userEvent.click(screen.getByTestId('likeCommentBtn')); + userEvent.click(screen.getAllByTestId('likeCommentBtn')[0]); await wait(); @@ -551,12 +816,14 @@ describe('Testing PostCard Component [User Portal]', () => { test('Comment modal pops when show comments button is clicked.', async () => { const cardProps = { id: '', + userImage: 'image.png', creator: { firstName: 'test', lastName: 'user', email: 'test@user.com', id: '1', }, + postedAt: '', image: 'testImage', video: '', text: 'This is post test text', @@ -571,6 +838,7 @@ describe('Testing PostCard Component [User Portal]', () => { id: '1', }, ], + fetchPosts: jest.fn(), }; render( @@ -587,7 +855,7 @@ describe('Testing PostCard Component [User Portal]', () => { await wait(); - userEvent.click(screen.getByTestId('showCommentsBtn')); + userEvent.click(screen.getByTestId('viewPostBtn')); expect(screen.findAllByText('Comments')).not.toBeNull(); }); }); diff --git a/src/components/UserPortal/PostCard/PostCard.tsx b/src/components/UserPortal/PostCard/PostCard.tsx index 2574505a81..d1b84412fb 100644 --- a/src/components/UserPortal/PostCard/PostCard.tsx +++ b/src/components/UserPortal/PostCard/PostCard.tsx @@ -1,24 +1,40 @@ import React from 'react'; -import { Button, Card, Form, InputGroup, Modal } from 'react-bootstrap'; +import { useMutation } from '@apollo/client'; +import { toast } from 'react-toastify'; +import { useTranslation } from 'react-i18next'; +import { + Col, + Button, + Card, + Dropdown, + Form, + InputGroup, + Modal, + ModalFooter, +} from 'react-bootstrap'; +import AccountCircleIcon from '@mui/icons-material/AccountCircle'; +import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; +import ThumbUpOffAltIcon from '@mui/icons-material/ThumbUpOffAlt'; +import SendIcon from '@mui/icons-material/Send'; +import MoreVertIcon from '@mui/icons-material/MoreVert'; import ThumbUpIcon from '@mui/icons-material/ThumbUp'; import CommentIcon from '@mui/icons-material/Comment'; -import AccountCircleIcon from '@mui/icons-material/AccountCircle'; -import styles from './PostCard.module.css'; -import { useMutation } from '@apollo/client'; +import DeleteOutlineOutlinedIcon from '@mui/icons-material/DeleteOutlineOutlined'; +import EditOutlinedIcon from '@mui/icons-material/EditOutlined'; + +import type { InterfacePostCard } from 'utils/interfaces'; import { CREATE_COMMENT_POST, + DELETE_POST_MUTATION, LIKE_POST, UNLIKE_POST, + UPDATE_POST_MUTATION, } from 'GraphQl/Mutations/mutations'; -import { toast } from 'react-toastify'; -import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; -import ThumbUpOffAltIcon from '@mui/icons-material/ThumbUpOffAlt'; -import { useTranslation } from 'react-i18next'; -import SendIcon from '@mui/icons-material/Send'; -import { errorHandler } from 'utils/errorHandler'; import CommentCard from '../CommentCard/CommentCard'; +import { errorHandler } from 'utils/errorHandler'; import useLocalStorage from 'utils/useLocalstorage'; -import type { InterfacePostCard } from 'utils/interfaces'; +import styles from './PostCard.module.css'; +import UserDefault from '../../../assets/images/defaultImg.png'; interface InterfaceCommentCardProps { id: string; @@ -41,6 +57,7 @@ export default function postCard(props: InterfacePostCard): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'postCard', }); + const { t: tCommon } = useTranslation('common'); const { getItem } = useLocalStorage(); @@ -51,8 +68,10 @@ export default function postCard(props: InterfacePostCard): JSX.Element { const [likes, setLikes] = React.useState(props.likeCount); const [isLikedByUser, setIsLikedByUser] = React.useState(likedByUser); - const [showComments, setShowComments] = React.useState(false); const [commentInput, setCommentInput] = React.useState(''); + const [viewPost, setViewPost] = React.useState(false); + const [showEditPost, setShowEditPost] = React.useState(false); + const [postContent, setPostContent] = React.useState(props.text); const postCreator = `${props.creator.firstName} ${props.creator.lastName}`; @@ -60,8 +79,14 @@ export default function postCard(props: InterfacePostCard): JSX.Element { const [unLikePost, { loading: unlikeLoading }] = useMutation(UNLIKE_POST); const [create, { loading: commentLoading }] = useMutation(CREATE_COMMENT_POST); + const [editPost] = useMutation(UPDATE_POST_MUTATION); + const [deletePost] = useMutation(DELETE_POST_MUTATION); - const toggleCommentsModal = (): void => setShowComments(!showComments); + const toggleViewPost = (): void => setViewPost(!viewPost); + const toggleEditPost = (): void => setShowEditPost(!showEditPost); + const handlePostInput = (e: React.ChangeEvent): void => { + setPostContent(e.target.value); + }; const handleToggleLike = async (): Promise => { if (isLikedByUser) { @@ -76,7 +101,7 @@ export default function postCard(props: InterfacePostCard): JSX.Element { setLikes((likes) => likes - 1); setIsLikedByUser(false); } - } catch (error: any) { + } catch (error: unknown) { /* istanbul ignore next */ toast.error(error); } @@ -92,7 +117,7 @@ export default function postCard(props: InterfacePostCard): JSX.Element { setLikes((likes) => likes + 1); setIsLikedByUser(true); } - } catch (error: any) { + } catch (error: unknown) { /* istanbul ignore next */ toast.error(error); } @@ -172,131 +197,254 @@ export default function postCard(props: InterfacePostCard): JSX.Element { setComments([...comments, newComment]); } - } catch (error: any) { + } catch (error: unknown) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + + const handleEditPost = (): void => { + try { + editPost({ + variables: { + id: props.id, + text: postContent, + }, + }); + + props.fetchPosts(); + toggleEditPost(); + toast.success('Successfully edited the Post.'); + } catch (error: unknown) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + const handleDeletePost = (): void => { + try { + deletePost({ + variables: { + id: props.id, + }, + }); + + props.fetchPosts(); + toast.success('Successfully deleted the Post.'); + } catch (error: unknown) { /* istanbul ignore next */ errorHandler(t, error); } }; return ( -
    - - -
    - - {postCreator} + + + +
    + +

    {postCreator}

    + + + + + + + + {tCommon('edit')} + + + + {tCommon('delete')} + + {/* Pin Post + Report + Share */} + +
    - - {props.title} - {props.text} + + + + {props.title} + + + Posted On: {props.postedAt} + + + {props.text} + {props.image && ( )} - +
    - {likes} - {` ${t('likes')}`} - - {numComments} - {` ${t('comments')}`}
    - - -
    - - {postCreator} + + +
    + postImg
    - {props.image && ( - - )} -
    {props.text}
    -
    - - {likes} - {` ${t('likes')}`} +
    +
    +
    +
    + + {likes} + {` ${t('likes')}`} +
    +
    + + {numComments} + {` ${t('comments')}`} +
    +
    + + + + {commentLoading ? ( + + ) : ( + + )} + + +
    -

    Comments

    - {numComments ? ( - comments.map((comment: any, index: any) => { - const cardProps: InterfaceCommentCardProps = { - id: comment.id, - creator: { - id: comment.creator.id, - firstName: comment.creator.firstName, - lastName: comment.creator.lastName, - email: comment.creator.email, - }, - likeCount: comment.likeCount, - likedBy: comment.likedBy, - text: comment.text, - handleLikeComment: handleLikeComment, - handleDislikeComment: handleDislikeComment, - }; - - return ; - }) - ) : ( - <>No comments to show. - )} -
    - - - - {commentLoading ? ( - - ) : ( - - )} - -
    -
    + + +

    + Edit Post +

    +
    + + + + + + +
    + ); } diff --git a/src/components/UserPortal/Register/Register.tsx b/src/components/UserPortal/Register/Register.tsx index f67674b4f8..a9a4a52d85 100644 --- a/src/components/UserPortal/Register/Register.tsx +++ b/src/components/UserPortal/Register/Register.tsx @@ -20,6 +20,7 @@ export default function register(props: InterfaceRegisterProps): JSX.Element { const { setCurrentMode } = props; const { t } = useTranslation('translation', { keyPrefix: 'userRegister' }); + const { t: tCommon } = useTranslation('common'); const handleModeChangeToLogin = (): void => { setCurrentMode('login'); @@ -70,7 +71,7 @@ export default function register(props: InterfaceRegisterProps): JSX.Element { password: '', confirmPassword: '', }); - } catch (error: any) { + } catch (error: unknown) { /* istanbul ignore next */ errorHandler(t, error); } @@ -116,9 +117,9 @@ export default function register(props: InterfaceRegisterProps): JSX.Element { return ( <> -

    {t('register')}

    +

    {tCommon('register')}

    -
    {t('firstName')}
    +
    {tCommon('firstName')}
    -
    {t('lastName')}
    +
    {tCommon('lastName')}
    -
    {t('emailAddress')}
    +
    {tCommon('emailAddress')}
    -
    {t('password')}
    +
    {tCommon('password')}
    -
    {t('confirmPassword')}
    +
    {tCommon('confirmPassword')}
    - {t('register')} + {tCommon('register')}
    @@ -213,7 +214,7 @@ export default function register(props: InterfaceRegisterProps): JSX.Element { className={styles.loginText} data-testid="setLoginBtn" > - {t('login')} + {tCommon('login')}
    diff --git a/src/components/UserPortal/StartPostModal/StartPostModal.test.tsx b/src/components/UserPortal/StartPostModal/StartPostModal.test.tsx index 65faca9fa1..5a2e815af4 100644 --- a/src/components/UserPortal/StartPostModal/StartPostModal.test.tsx +++ b/src/components/UserPortal/StartPostModal/StartPostModal.test.tsx @@ -26,9 +26,10 @@ const MOCKS = [ request: { query: CREATE_POST_MUTATION, variables: { - title: 'Dummy Post', + title: '', text: 'This is dummy text', organizationId: '123', + file: '', }, result: { data: { @@ -94,6 +95,7 @@ const renderStartPostModal = ( }, }, organizationId: '123', + img: '', }; return render( @@ -121,22 +123,6 @@ describe('Testing StartPostModal Component: User Portal', () => { expect(modal).toBeInTheDocument(); }); - test('triggers file input when the upload icon is clicked', async () => { - const clickSpy = jest.spyOn(HTMLInputElement.prototype, 'click'); - renderStartPostModal(true, null); - - await wait(); - const postImageInput = screen.getByTestId('postImageInput'); - expect(postImageInput).toHaveAttribute('type', 'file'); - expect(postImageInput).toHaveStyle({ display: 'inline-block' }); - - const iconButton = screen.getByTestId('addMediaBtn'); - fireEvent.click(iconButton); - - expect(clickSpy).toHaveBeenCalled(); - clickSpy.mockRestore(); - }); - test('On invalid post submission with empty body Error toast should be shown', async () => { const toastSpy = jest.spyOn(toast, 'error'); renderStartPostModal(true, null); @@ -150,7 +136,7 @@ describe('Testing StartPostModal Component: User Portal', () => { renderStartPostModal(true, null); await wait(); - const randomPostInput = 'test post input'; + const randomPostInput = 'This is dummy text'; userEvent.type(screen.getByTestId('postInput'), randomPostInput); expect(screen.queryByText(randomPostInput)).toBeInTheDocument(); @@ -158,6 +144,10 @@ describe('Testing StartPostModal Component: User Portal', () => { expect(toast.error).not.toBeCalledWith(); expect(toast.info).toBeCalledWith('Processing your post. Please wait.'); + // await wait(); + // expect(toast.success).toBeCalledWith( + // 'Your post is now visible in the feed.', + // ); }); test('If user image is null then default image should be shown', async () => { @@ -178,48 +168,4 @@ describe('Testing StartPostModal Component: User Portal', () => { const userImage = screen.getByTestId('userImage'); expect(userImage).toHaveAttribute('src', 'image.png'); }); - - test('should update post image state when a file is selected', async () => { - renderStartPostModal(true, null); - await wait(); - - const file = new File(['(⌐□_□)'], 'chad.png', { type: 'image/png' }); - const input = screen.getByTestId('postImageInput') as HTMLInputElement; - await act(async () => { - fireEvent.change(input, { target: { files: [file] } }); - }); - - expect(input.files?.[0]).toEqual(file); - const previewImage = await screen.findByAltText('Post Image Preview'); - expect(previewImage).toBeInTheDocument(); - }); - - test('should not update post image state when no file is selected', async () => { - renderStartPostModal(true, null); - await wait(); - - const input = screen.getByTestId('postImageInput') as HTMLInputElement; - await act(async () => { - fireEvent.change(input, { target: { files: null } }); - }); - - const previewImage = screen.queryByAltText('Post Image Preview'); - expect(previewImage).not.toBeInTheDocument(); - }); - - test('triggers file input when fileInputRef exists', async () => { - const clickSpy = jest.spyOn(HTMLInputElement.prototype, 'click'); - const refMock = { current: { click: clickSpy } }; - - renderStartPostModal(true, null); - await wait(); - - jest.spyOn(React, 'useRef').mockReturnValueOnce(refMock); - - const iconButton = screen.getByTestId('addMediaBtn'); - fireEvent.click(iconButton); - - expect(clickSpy).toHaveBeenCalled(); - clickSpy.mockRestore(); - }); }); diff --git a/src/components/UserPortal/StartPostModal/StartPostModal.tsx b/src/components/UserPortal/StartPostModal/StartPostModal.tsx index 20fe4aae2d..036bcd904e 100644 --- a/src/components/UserPortal/StartPostModal/StartPostModal.tsx +++ b/src/components/UserPortal/StartPostModal/StartPostModal.tsx @@ -1,4 +1,4 @@ -import React, { useRef, useState } from 'react'; +import React, { useState } from 'react'; import type { ChangeEvent } from 'react'; import { Button, Form, Image, Modal } from 'react-bootstrap'; import { toast } from 'react-toastify'; @@ -6,7 +6,6 @@ import { useMutation } from '@apollo/client'; import { useTranslation } from 'react-i18next'; import { errorHandler } from 'utils/errorHandler'; -import convertToBase64 from 'utils/convertToBase64'; import UserDefault from '../../../assets/images/defaultImg.png'; import styles from './StartPostModal.module.css'; import { CREATE_POST_MUTATION } from 'GraphQl/Mutations/mutations'; @@ -18,6 +17,7 @@ interface InterfaceStartPostModalProps { fetchPosts: () => void; userData: InterfaceQueryUserListItem | undefined; organizationId: string; + img: string | null; } const startPostModal = ({ @@ -26,11 +26,10 @@ const startPostModal = ({ fetchPosts, userData, organizationId, + img, }: InterfaceStartPostModalProps): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'home' }); const [postContent, setPostContent] = useState(''); - const [postImage, setPostImage] = useState(''); - const fileInputRef = useRef(null); const [createPost] = useMutation(CREATE_POST_MUTATION); @@ -40,15 +39,9 @@ const startPostModal = ({ const handleHide = (): void => { setPostContent(''); - setPostImage(''); onHide(); }; - const uploadMedia = (e: React.MouseEvent): void => { - e.preventDefault(); - fileInputRef.current?.click(); - }; - const handlePost = async (): Promise => { try { if (!postContent) { @@ -61,7 +54,7 @@ const startPostModal = ({ title: '', text: postContent, organizationId: organizationId, - file: postImage, + file: img, }, }); /* istanbul ignore next */ @@ -121,58 +114,17 @@ const startPostModal = ({ placeholder={t('somethingOnYourMind')} value={postContent} /> - , - ): Promise => { - const file = e.target.files && e.target.files[0]; - if (file) { - const image = await convertToBase64(file); - setPostImage(image); - } else { - toast.info('Error uploading image. Please try again.'); - } - }} - /> - {postImage && ( + {img && (
    - Post Image Preview + Post Image Preview
    )} -
    - -
    )} diff --git a/src/components/UserPortal/UserSidebarOrg/UserSidebarOrg.tsx b/src/components/UserPortal/UserSidebarOrg/UserSidebarOrg.tsx index 03fbbd9c4f..7d78d3765e 100644 --- a/src/components/UserPortal/UserSidebarOrg/UserSidebarOrg.tsx +++ b/src/components/UserPortal/UserSidebarOrg/UserSidebarOrg.tsx @@ -28,6 +28,7 @@ const UserSidebarOrg = ({ setHideDrawer, }: InterfaceUserSidebarOrgProps): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'userSidebarOrg' }); + const { t: tCommon } = useTranslation('common'); const [showDropdown, setShowDropdown] = React.useState(false); const [organization, setOrganization] = @@ -126,7 +127,7 @@ const UserSidebarOrg = ({ {/* Options List */}
    - {t('menu')} + {tCommon('menu')}
    {targets.map(({ name, url }, index) => { return url ? ( diff --git a/src/components/UserProfileSettings/UserProfile.tsx b/src/components/UserProfileSettings/UserProfile.tsx index 4c77d4ccef..77e1542c82 100644 --- a/src/components/UserProfileSettings/UserProfile.tsx +++ b/src/components/UserProfileSettings/UserProfile.tsx @@ -21,6 +21,7 @@ const UserProfile: React.FC = ({ const { t } = useTranslation('translation', { keyPrefix: 'settings', }); + const { t: tCommon } = useTranslation('common'); return ( <> @@ -48,7 +49,7 @@ const UserProfile: React.FC = ({ - {t('joined')} 1st May, 2021 + {tCommon('joined')} 1st May, 2021
    diff --git a/src/components/UsersTableItem/UserTableItem.test.tsx b/src/components/UsersTableItem/UserTableItem.test.tsx index e89288ff28..bfa0a31c86 100644 --- a/src/components/UsersTableItem/UserTableItem.test.tsx +++ b/src/components/UsersTableItem/UserTableItem.test.tsx @@ -6,11 +6,18 @@ import { toast } from 'react-toastify'; import { StaticMockLink } from 'utils/StaticMockLink'; import i18nForTest from 'utils/i18nForTest'; import type { InterfaceQueryUserListItem } from 'utils/interfaces'; -import { MOCKS } from './UserTableItemMocks'; +import { MOCKS, MOCKS2, MOCKS_UPDATE } from './UserTableItemMocks'; import UsersTableItem from './UsersTableItem'; import { BrowserRouter } from 'react-router-dom'; const link = new StaticMockLink(MOCKS, true); +const link2 = new StaticMockLink(MOCKS2, true); +const link3 = new StaticMockLink(MOCKS_UPDATE, true); import useLocalStorage from 'utils/useLocalstorage'; +import { + REMOVE_ADMIN_MUTATION, + REMOVE_MEMBER_MUTATION, +} from 'GraphQl/Mutations/mutations'; +import userEvent from '@testing-library/user-event'; const { setItem } = useLocalStorage(); @@ -1084,4 +1091,251 @@ describe('Testing User Table Item', () => { fireEvent.click(confirmRemoveBtn); }); + + test('handles errors in removeUser mutation', async () => { + const props: { + user: InterfaceQueryUserListItem; + index: number; + loggedInUserId: string; + resetAndRefetch: () => void; + } = { + user: { + user: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', + email: '', + createdAt: '2022-09-29T15:39:36.355Z', + organizationsBlockedBy: [ + { + _id: 'xyz', + name: 'Blocked Organization 1', + image: + 'https://api.dicebear.com/5.x/initials/svg?seed=Blocked%20Organization%201', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '2023-08-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: + 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', + email: '', + }, + }, + ], + joinedOrganizations: [ + { + _id: 'abc', + name: 'Joined Organization 1', + image: null, + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '2023-08-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: '', + }, + }, + ], + registeredEvents: [], + membershipRequests: [], + }, + appUserProfile: { + _id: '123', + isSuperAdmin: true, + createdOrganizations: [], + createdEvents: [], + eventAdmin: [], + adminFor: [ + { + _id: 'abc', + }, + { + _id: 'xyz', + }, + ], + }, + }, + index: 0, + loggedInUserId: '123', + resetAndRefetch: resetAndRefetchMock, + }; + + const mocks = [ + { + request: { + query: REMOVE_MEMBER_MUTATION, + variables: { + userId: '123', + orgId: 'xyz', + }, + }, + result: { + errors: [ + { + message: 'User does not exist', + }, + ], + }, + }, + ]; + + render( + + + + + + + , + ); + + await wait(); + const showBlockedByOrgsBtn = screen.getByTestId( + `showBlockedByOrgsBtn${123}`, + ); + expect(showBlockedByOrgsBtn).toBeInTheDocument(); + fireEvent.click(showBlockedByOrgsBtn); + expect(screen.getByTestId('modal-blocked-org-123')).toBeInTheDocument(); + }); + + test('change role button should function properly', async () => { + const props: { + user: InterfaceQueryUserListItem; + index: number; + loggedInUserId: string; + resetAndRefetch: () => void; + } = { + user: { + user: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', + email: '', + createdAt: '2022-09-29T15:39:36.355Z', + organizationsBlockedBy: [ + { + _id: 'xyz', + name: 'Blocked Organization 1', + image: + 'https://api.dicebear.com/5.x/initials/svg?seed=Blocked%20Organization%201', + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '2023-08-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: + 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', + email: '', + }, + }, + ], + joinedOrganizations: [ + { + _id: 'abc', + name: 'Joined Organization 1', + image: null, + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '2023-08-29T15:39:36.355Z', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: '', + }, + }, + ], + registeredEvents: [], + + membershipRequests: [], + }, + appUserProfile: { + _id: '123', + isSuperAdmin: false, + createdOrganizations: [], + createdEvents: [], + eventAdmin: [], + adminFor: [ + { + _id: 'abc', + }, + { + _id: 'xyz', + }, + ], + }, + }, + index: 0, + loggedInUserId: '123', + resetAndRefetch: resetAndRefetchMock, + }; + + render( + + + + + + + , + ); + + await wait(); + const showJoinedOrgs = screen.getByTestId(`showJoinedOrgsBtn${123}`); + expect(showJoinedOrgs).toBeInTheDocument(); + fireEvent.click(showJoinedOrgs); + const changeRoleBtn = screen.getByTestId( + `changeRoleInOrg${'abc'}`, + ) as HTMLSelectElement; + expect(changeRoleBtn).toBeInTheDocument(); + userEvent.selectOptions(changeRoleBtn, 'ADMIN'); + await wait(); + userEvent.selectOptions(changeRoleBtn, 'USER'); + await wait(); + expect(changeRoleBtn.value).toBe(`USER?abc`); + await wait(); + }); }); diff --git a/src/components/UsersTableItem/UserTableItemMocks.ts b/src/components/UsersTableItem/UserTableItemMocks.ts index 02c430f959..3162487f33 100644 --- a/src/components/UsersTableItem/UserTableItemMocks.ts +++ b/src/components/UsersTableItem/UserTableItemMocks.ts @@ -3,7 +3,7 @@ import { UPDATE_USER_ROLE_IN_ORG_MUTATION, } from 'GraphQl/Mutations/mutations'; -export const MOCKS = [ +const MOCKS = [ { request: { query: REMOVE_MEMBER_MUTATION, @@ -20,6 +20,39 @@ export const MOCKS = [ }, }, }, + { + request: { + query: UPDATE_USER_ROLE_IN_ORG_MUTATION, + variables: { + userId: '123', + organizationId: 'abc', + role: 'USER', + }, + }, + result: { + data: { + updateUserRoleInOrganization: { + _id: '123', + }, + }, + }, + }, +]; + +const MOCKS2 = [ + { + request: { + query: REMOVE_MEMBER_MUTATION, + variables: { + userid: '123', + orgid: 'abc', + }, + }, + error: new Error('Failed to remove member'), + }, +]; + +const MOCKS_UPDATE = [ { request: { query: UPDATE_USER_ROLE_IN_ORG_MUTATION, @@ -29,6 +62,17 @@ export const MOCKS = [ role: 'ADMIN', }, }, + error: new Error('Failed to update user role in organization'), + }, + { + request: { + query: UPDATE_USER_ROLE_IN_ORG_MUTATION, + variables: { + userId: '123', + organizationId: 'abc', + role: 'USER', + }, + }, result: { data: { updateUserRoleInOrganization: { @@ -38,3 +82,5 @@ export const MOCKS = [ }, }, ]; + +export { MOCKS, MOCKS2, MOCKS_UPDATE }; diff --git a/src/components/UsersTableItem/UsersTableItem.tsx b/src/components/UsersTableItem/UsersTableItem.tsx index 507a85316d..b7c7670239 100644 --- a/src/components/UsersTableItem/UsersTableItem.tsx +++ b/src/components/UsersTableItem/UsersTableItem.tsx @@ -4,6 +4,7 @@ import { REMOVE_MEMBER_MUTATION, UPDATE_USER_ROLE_IN_ORG_MUTATION, } from 'GraphQl/Mutations/mutations'; +import Avatar from 'components/Avatar/Avatar'; import dayjs from 'dayjs'; import React, { useState } from 'react'; import { Button, Form, Modal, Row, Table } from 'react-bootstrap'; @@ -13,19 +14,16 @@ import { toast } from 'react-toastify'; import { errorHandler } from 'utils/errorHandler'; import type { InterfaceQueryUserListItem } from 'utils/interfaces'; import styles from './UsersTableItem.module.css'; -import Avatar from 'components/Avatar/Avatar'; - type Props = { user: InterfaceQueryUserListItem; index: number; loggedInUserId: string; resetAndRefetch: () => void; }; - const UsersTableItem = (props: Props): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'users' }); + const { t: tCommon } = useTranslation('common'); const { user, index, resetAndRefetch } = props; - const [showJoinedOrganizations, setShowJoinedOrganizations] = useState(false); const [showBlockedOrganizations, setShowBlockedOrganizations] = useState(false); @@ -49,7 +47,6 @@ const UsersTableItem = (props: Props): JSX.Element => { const [removeUser] = useMutation(REMOVE_MEMBER_MUTATION); const [updateUserInOrgType] = useMutation(UPDATE_USER_ROLE_IN_ORG_MUTATION); const navigate = useNavigate(); - const confirmRemoveUser = async (): Promise => { try { const { data } = await removeUser({ @@ -58,23 +55,19 @@ const UsersTableItem = (props: Props): JSX.Element => { orgid: removeUserProps.orgId, }, }); - if (data) { toast.success('Removed User from Organization successfully'); resetAndRefetch(); } - } catch (error: any) { - /* istanbul ignore next */ + } catch (error: unknown) { errorHandler(t, error); } }; - - /* istanbul ignore next */ - const changeRoleInOrg = async (e: any): Promise => { + const changeRoleInOrg = async ( + e: React.ChangeEvent, + ): Promise => { const { value } = e.target; - const inputData = value.split('?'); - try { const { data } = await updateUserInOrgType({ variables: { @@ -87,16 +80,12 @@ const UsersTableItem = (props: Props): JSX.Element => { toast.success(t('roleUpdated')); resetAndRefetch(); } - } catch (error: any) { - /* istanbul ignore next */ + } catch (error: unknown) { errorHandler(t, error); } }; - function goToOrg(_id: string): void { const url = '/orgdash/' + _id; - - // Dont change the below two lines window.location.replace(url); navigate(url); } @@ -125,15 +114,19 @@ const UsersTableItem = (props: Props): JSX.Element => { setOrgsBlockedBy(filteredOrgs); } }; - const handleSearchJoinedOrgs = (e: any): void => { + const handleSearchJoinedOrgs = ( + e: React.KeyboardEvent, + ): void => { if (e.key === 'Enter') { - const { value } = e.target; + const { value } = e.currentTarget; searchJoinedOrgs(value); } }; - const handleSearcgByOrgsBlockedBy = (e: any): void => { + const handleSearchByOrgsBlockedBy = ( + e: React.KeyboardEvent, + ): void => { if (e.key === 'Enter') { - const { value } = e.target; + const { value } = e.currentTarget; searchOrgsBlockedBy(value); } }; @@ -143,15 +136,12 @@ const UsersTableItem = (props: Props): JSX.Element => { ?.value || ''; searchJoinedOrgs(inputValue); }; - const handleSearchButtonClickOrgsBlockedBy = (): void => { const inputValue = (document.getElementById('orgname-blocked-by') as HTMLInputElement) ?.value || ''; searchOrgsBlockedBy(inputValue); }; - - /* istanbul ignore next */ function onHideRemoveUserModal(): void { setShowRemoveUserModal(false); if (removeUserProps.setShowOnCancel == 'JOINED') { @@ -160,12 +150,9 @@ const UsersTableItem = (props: Props): JSX.Element => { setShowBlockedOrganizations(true); } } - const isSuperAdmin = user.appUserProfile.isSuperAdmin; - return ( <> - {/* Table Item */} {index + 1} {`${user.user.firstName} ${user.user.lastName}`} @@ -178,7 +165,6 @@ const UsersTableItem = (props: Props): JSX.Element => { {t('view')} ({user.user.joinedOrganizations.length}) - - {/* Organizations joined modal */} { {user.user.joinedOrganizations.length !== 0 && (
    {
    ) : joinedOrgs.length == 0 ? ( - <> -
    -

    - {t('noResultsFoundFor')} "{searchByNameJoinedOrgs} - " -

    -
    - +
    +

    + {tCommon('noResultsFoundFor')} " + {searchByNameJoinedOrgs} + " +

    +
    ) : ( @@ -258,7 +241,6 @@ const UsersTableItem = (props: Props): JSX.Element => { {joinedOrgs.map((org) => { - // Check user is admin for this organization or not let isAdmin = false; user.appUserProfile.adminFor.map((item) => { if (item._id == org._id) { @@ -384,7 +366,6 @@ const UsersTableItem = (props: Props): JSX.Element => { - {/* Organizations blocked by modal */} { {user.user.organizationsBlockedBy.length !== 0 && (
    ) : orgsBlockedBy.length == 0 ? ( - <> -
    -

    - {t('noResultsFoundFor')} "{searchByNameOrgsBlockedBy} - " -

    -
    - +
    +

    {`${tCommon('noResultsFoundFor')} "${searchByNameOrgsBlockedBy}"`}

    +
    ) : (
    @@ -453,10 +428,8 @@ const UsersTableItem = (props: Props): JSX.Element => { - {orgsBlockedBy.map((org) => { - // Check user is admin for this organization or not let isAdmin = false; user.appUserProfile.adminFor.map((item) => { if (item._id == org._id) { @@ -576,7 +549,6 @@ const UsersTableItem = (props: Props): JSX.Element => { - {/* Remove user from Organization modal */} { ); }; - export default UsersTableItem; diff --git a/src/components/Venues/VenueCard.tsx b/src/components/Venues/VenueCard.tsx index 1132986e68..d4f6f97598 100644 --- a/src/components/Venues/VenueCard.tsx +++ b/src/components/Venues/VenueCard.tsx @@ -19,9 +19,7 @@ const VenueCard = ({ showEditVenueModal, handleDelete, }: InterfaceVenueCardProps): JSX.Element => { - const { t } = useTranslation('translation', { - keyPrefix: 'organizationVenues', - }); + const { t: tCommon } = useTranslation('common'); return (
    - {t('edit')} + {tCommon('edit')}
    diff --git a/src/components/Venues/VenueModal.tsx b/src/components/Venues/VenueModal.tsx index 470823bf68..2ed8f826a5 100644 --- a/src/components/Venues/VenueModal.tsx +++ b/src/components/Venues/VenueModal.tsx @@ -32,6 +32,7 @@ const VenueModal = ({ const { t } = useTranslation('translation', { keyPrefix: 'organizationVenues', }); + const { t: tCommon } = useTranslation('common'); const [venueImage, setVenueImage] = useState(false); const [formState, setFormState] = useState({ @@ -149,7 +150,7 @@ const VenueModal = ({ }); }} /> - + { const { t } = useTranslation('translation', { keyPrefix: 'blockUnblockUser', }); + const { t: tCommon } = useTranslation('common'); document.title = t('title'); const { orgId: currentUrl } = useParams(); @@ -87,7 +88,7 @@ const Requests = (): JSX.Element => { toast.success(t('blockedSuccessfully')); memberRefetch(); } - } catch (error: any) { + } catch (error: unknown) { /* istanbul ignore next */ errorHandler(t, error); } @@ -106,7 +107,7 @@ const Requests = (): JSX.Element => { toast.success(t('Un-BlockedSuccessfully')); memberRefetch(); } - } catch (error: any) { + } catch (error: unknown) { /* istanbul ignore next */ errorHandler(t, error); } @@ -126,9 +127,11 @@ const Requests = (): JSX.Element => { }); }; - const handleSearchByEnter = (e: any): void => { + const handleSearchByEnter = ( + e: React.KeyboardEvent, + ): void => { if (e.key === 'Enter') { - const { value } = e.target; + const { value } = e.currentTarget; handleSearch(value); } }; @@ -142,8 +145,8 @@ const Requests = (): JSX.Element => { const headerTitles: string[] = [ '#', - t('name'), - t('email'), + tCommon('name'), + tCommon('email'), t('block_unblock'), ]; @@ -235,7 +238,7 @@ const Requests = (): JSX.Element => { searchByName.length > 0 ? (

    - {t('noResultsFoundFor')} "{searchByName}" + {tCommon('noResultsFoundFor')} "{searchByName}"

    ) : loadingMembers == false && membersData.length === 0 ? ( @@ -268,7 +271,7 @@ const Requests = (): JSX.Element => {
    -
    {t('startDate')}
    +
    {tCommon('startDate')}
    -
    {t('endDate')}
    +
    {tCommon('endDate')}
    {t('pledgeAmount')}
    @@ -234,78 +243,67 @@ const fundCampaignPledge = (): JSX.Element => {
    - {fundCampaignPledgeData?.getFundraisingCampaignById.pledges.map( - (pledge, index) => ( -
    - -
    -
    - {pledge.users.map((user, index) => ( - - {user.firstName} - {index !== pledge.users.length - 1 && ', '} - - ))} -
    - - -
    - {dayjs(pledge.startDate).format('DD/MM/YYYY')} -
    - - -
    {dayjs(pledge.endDate).format('DD/MM/YYYY')}
    - - -
    - { - currencySymbols[ - pledge.currency as keyof typeof currencySymbols - ] - } - {pledge.amount} -
    - - - - - - - {fundCampaignPledgeData.getFundraisingCampaignById.pledges && - index !== - fundCampaignPledgeData.getFundraisingCampaignById.pledges - .length - - 1 &&
    } - - ), - )} + {pledges.map((pledge, index) => ( +
    + +
    +
    + {pledge.users.map((user, index) => ( + + {user.firstName} + {index !== pledge.users.length - 1 && ', '} + + ))} +
    + +
    +
    + {dayjs(pledge.startDate).format('DD/MM/YYYY')} +
    + +
    +
    {dayjs(pledge.endDate).format('DD/MM/YYYY')}
    + +
    +
    + { + currencySymbols[ + pledge.currency as keyof typeof currencySymbols + ] + } + {pledge.amount} +
    + +
    + + + + + {pledges && index !== pledges.length - 1 && ( +
    + )} + + ))} - {fundCampaignPledgeData?.getFundraisingCampaignById.pledges - .length === 0 && ( + {pledges.length === 0 && (
    {t('noPledges')}
    @@ -316,42 +314,37 @@ const fundCampaignPledge = (): JSX.Element => { {/* Create Pledge Modal */} closeModal(Modal.CREATE)} formState={formState} setFormState={setFormState} createPledgeHandler={createPledgeHandler} - startDate={ - fundCampaignPledgeData?.getFundraisingCampaignById.startDate as Date - } - endDate={ - fundCampaignPledgeData?.getFundraisingCampaignById.endDate as Date - } + startDate={pledgeData?.getFundraisingCampaignById.startDate as Date} + endDate={pledgeData?.getFundraisingCampaignById.endDate as Date} t={t} + tCommon={tCommon} /> {/* Update Pledge Modal */} closeModal(Modal.UPDATE)} formState={formState} setFormState={setFormState} updatePledgeHandler={updatePledgeHandler} - startDate={ - fundCampaignPledgeData?.getFundraisingCampaignById.startDate as Date - } - endDate={ - fundCampaignPledgeData?.getFundraisingCampaignById.endDate as Date - } + startDate={pledgeData?.getFundraisingCampaignById.startDate as Date} + endDate={pledgeData?.getFundraisingCampaignById.endDate as Date} t={t} + tCommon={tCommon} /> {/* Delete Pledge Modal */} closeModal(Modal.DELETE)} deletePledgeHandler={deleteHandler} t={t} + tCommon={tCommon} /> ); diff --git a/src/screens/FundCampaignPledge/PledgeCreateModal.tsx b/src/screens/FundCampaignPledge/PledgeCreateModal.tsx index 2c296ff216..53d78249a8 100644 --- a/src/screens/FundCampaignPledge/PledgeCreateModal.tsx +++ b/src/screens/FundCampaignPledge/PledgeCreateModal.tsx @@ -16,6 +16,7 @@ interface InterfaceCreatePledgeModal { startDate: Date; endDate: Date; t: (key: string) => string; + tCommon: (key: string) => string; } const PledgeCreateModal: React.FC = ({ @@ -27,6 +28,7 @@ const PledgeCreateModal: React.FC = ({ startDate, endDate, t, + tCommon, }) => { return ( <> @@ -51,7 +53,7 @@ const PledgeCreateModal: React.FC = ({
    { @@ -72,7 +74,7 @@ const PledgeCreateModal: React.FC = ({
    { if (date) { diff --git a/src/screens/FundCampaignPledge/PledgeDeleteModal.tsx b/src/screens/FundCampaignPledge/PledgeDeleteModal.tsx index b6bc9fb20e..2cc7fdeaff 100644 --- a/src/screens/FundCampaignPledge/PledgeDeleteModal.tsx +++ b/src/screens/FundCampaignPledge/PledgeDeleteModal.tsx @@ -7,12 +7,14 @@ interface InterfaceDeletePledgeModal { hideDeletePledgeModal: () => void; deletePledgeHandler: () => Promise; t: (key: string) => string; + tCommon: (key: string) => string; } const PledgeDeleteModal: React.FC = ({ deletePledgeModalIsOpen, hideDeletePledgeModal, deletePledgeHandler, t, + tCommon, }) => { return ( <> @@ -41,14 +43,14 @@ const PledgeDeleteModal: React.FC = ({ onClick={deletePledgeHandler} data-testid="deleteyesbtn" > - {t('yes')} + {tCommon('yes')} diff --git a/src/screens/FundCampaignPledge/PledgeEditModal.tsx b/src/screens/FundCampaignPledge/PledgeEditModal.tsx index afad814b86..af1e743221 100644 --- a/src/screens/FundCampaignPledge/PledgeEditModal.tsx +++ b/src/screens/FundCampaignPledge/PledgeEditModal.tsx @@ -16,6 +16,7 @@ interface InterfaceUpdatePledgeModal { startDate: Date; endDate: Date; t: (key: string) => string; + tCommon: (key: string) => string; } const PledgeEditModal: React.FC = ({ updatePledgeModalIsOpen, @@ -26,6 +27,7 @@ const PledgeEditModal: React.FC = ({ startDate, endDate, t, + tCommon, }) => { return ( <> @@ -50,7 +52,7 @@ const PledgeEditModal: React.FC = ({
    { @@ -71,7 +73,7 @@ const PledgeEditModal: React.FC = ({
    { if (date) { diff --git a/src/screens/LoginPage/LoginPage.tsx b/src/screens/LoginPage/LoginPage.tsx index 834232fb8a..56f2d38159 100644 --- a/src/screens/LoginPage/LoginPage.tsx +++ b/src/screens/LoginPage/LoginPage.tsx @@ -37,6 +37,9 @@ import { Autocomplete, TextField } from '@mui/material'; const loginPage = (): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'loginPage' }); + const { t: tCommon } = useTranslation('common'); + const { t: tErrors } = useTranslation('errors'); + const navigate = useNavigate(); const { getItem, setItem } = useLocalStorage(); @@ -293,7 +296,7 @@ const loginPage = (): JSX.Element => { appUserProfile.isSuperAdmin || appUserProfile.adminFor.length !== 0; if (role === 'admin' && !isAdmin) { - toast.warn(t('notAuthorised')); + toast.warn(tErrors('notAuthorised')); return; } const loggedInUserId = user._id; @@ -317,7 +320,7 @@ const loginPage = (): JSX.Element => { navigate(role === 'admin' ? '/orglist' : '/user/organizations'); } else { - toast.warn(t('notFound')); + toast.warn(tErrors('notFound')); } } catch (error) { /* istanbul ignore next */ @@ -418,13 +421,13 @@ const loginPage = (): JSX.Element => { >

    - {role === 'admin' ? t('login') : t('userLogin')} + {role === 'admin' ? tCommon('login') : t('userLogin')}

    - {t('email')} + {tCommon('email')}
    { @@ -443,12 +446,14 @@ const loginPage = (): JSX.Element => {
    - {t('password')} + + {tCommon('password')} +
    { className="text-secondary" tabIndex={-1} > - {t('forgotPassword')} + {tCommon('forgotPassword')}
    {REACT_APP_USE_RECAPTCHA === 'yes' ? ( @@ -502,11 +507,11 @@ const loginPage = (): JSX.Element => { value="Login" data-testid="loginBtn" > - {t('login')} + {tCommon('login')}

    - {t('OR')} + {tCommon('OR')}
    @@ -530,17 +535,17 @@ const loginPage = (): JSX.Element => { >

    - {t('register')} + {tCommon('register')}

    - {t('firstName')} + {tCommon('firstName')} { @@ -554,12 +559,12 @@ const loginPage = (): JSX.Element => {
    - {t('lastName')} + {tCommon('lastName')} { @@ -573,13 +578,13 @@ const loginPage = (): JSX.Element => {
    - {t('email')} + {tCommon('email')}
    {
    - {t('password')} + {tCommon('password')}
    setIsInputFocused(true)} onBlur={(): void => setIsInputFocused(false)} @@ -754,11 +759,11 @@ const loginPage = (): JSX.Element => {
    - {t('confirmPassword')} + {tCommon('confirmPassword')}
    { @@ -839,11 +844,11 @@ const loginPage = (): JSX.Element => { value="Register" data-testid="registrationBtn" > - {t('register')} + {tCommon('register')}

    - {t('OR')} + {tCommon('OR')}
    diff --git a/src/screens/MemberDetail/MemberDetail.tsx b/src/screens/MemberDetail/MemberDetail.tsx index 7e9213bd3e..49b9f60a7a 100644 --- a/src/screens/MemberDetail/MemberDetail.tsx +++ b/src/screens/MemberDetail/MemberDetail.tsx @@ -39,6 +39,7 @@ const MemberDetail: React.FC = ({ id }): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'memberDetail', }); + const { t: tCommon } = useTranslation('common'); const location = useLocation(); const isMounted = useRef(true); const { getItem, setItem } = useLocalStorage(); @@ -224,7 +225,7 @@ const MemberDetail: React.FC = ({ id }): JSX.Element => {
    -

    {t('firstName')}

    +

    {tCommon('firstName')}

    = ({ id }): JSX.Element => { name="firstName" onChange={handleChange} required - placeholder={t('firstName')} + placeholder={tCommon('firstName')} />
    -

    {t('lastName')}

    +

    {tCommon('lastName')}

    = ({ id }): JSX.Element => { name="lastName" onChange={handleChange} required - placeholder={t('lastName')} + placeholder={tCommon('lastName')} />
    @@ -306,7 +307,7 @@ const MemberDetail: React.FC = ({ id }): JSX.Element => {

    -

    {t('email')}

    +

    {tCommon('email')}

    = ({ id }): JSX.Element => { name="email" onChange={handleChange} required - placeholder={t('email')} + placeholder={tCommon('email')} />
    -

    {t('address')}

    +

    {tCommon('address')}

    @@ -511,12 +512,12 @@ const MemberDetail: React.FC = ({ id }): JSX.Element => {
    @@ -529,7 +530,7 @@ const MemberDetail: React.FC = ({ id }): JSX.Element => { value="savechanges" onClick={loginLink} > - {t('saveChanges')} + {tCommon('saveChanges')}
    diff --git a/src/screens/OrgList/OrgList.test.tsx b/src/screens/OrgList/OrgList.test.tsx index b848b72c90..e7e0f7d4be 100644 --- a/src/screens/OrgList/OrgList.test.tsx +++ b/src/screens/OrgList/OrgList.test.tsx @@ -499,7 +499,7 @@ describe('Organisations Page testing as Admin', () => { test('Testing sort latest and oldest toggle', async () => { setItem('id', '123'); setItem('SuperAdmin', false); - setItem('AdminFor', [{ name: 'adi', _id: '1234', image: '' }]); + setItem('AdminFor', [{ name: 'adi', _id: 'a0', image: '' }]); await act(async () => { render( diff --git a/src/screens/OrgList/OrgList.tsx b/src/screens/OrgList/OrgList.tsx index 7382aedd38..5c91678217 100644 --- a/src/screens/OrgList/OrgList.tsx +++ b/src/screens/OrgList/OrgList.tsx @@ -32,6 +32,7 @@ import OrganizationModal from './OrganizationModal'; function orgList(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'orgList' }); + const { t: tCommon } = useTranslation('common'); const [dialogModalisOpen, setdialogModalIsOpen] = useState(false); const [dialogRedirectOrgId, setDialogRedirectOrgId] = useState(''); @@ -108,12 +109,6 @@ function orgList(): JSX.Element { error: errorList, refetch: refetchOrgs, fetchMore, - }: { - data: InterfaceOrgConnectionType | undefined; - loading: boolean; - error?: Error | undefined; - refetch: any; - fetchMore: any; } = useQuery(ORGANIZATION_CONNECTION_LIST, { variables: { first: perPageResult, @@ -234,7 +229,7 @@ function orgList(): JSX.Element { }); toggleModal(); } - } catch (error: any) { + } catch (error: unknown) { /* istanbul ignore next */ errorHandler(t, error); } @@ -269,9 +264,11 @@ function orgList(): JSX.Element { }); }; - const handleSearchByEnter = (e: any): void => { + const handleSearchByEnter = ( + e: React.KeyboardEvent, + ): void => { if (e.key === 'Enter') { - const { value } = e.target; + const { value } = e.currentTarget; handleSearch(value); } }; @@ -345,7 +342,7 @@ function orgList(): JSX.Element { type="name" id="searchOrgname" className="bg-white" - placeholder={t('searchByName')} + placeholder={tCommon('searchByName')} data-testid="searchByName" autoComplete="off" required @@ -421,7 +418,7 @@ function orgList(): JSX.Element { /* istanbul ignore next */

    - {t('noResultsFoundFor')} "{searchByName}" + {tCommon('noResultsFoundFor')} "{searchByName}"

    ) : ( @@ -456,29 +453,33 @@ function orgList(): JSX.Element { data-testid="organizations-list" endMessage={
    -
    {t('endOfResults')}
    +
    {tCommon('endOfResults')}
    } > {userData && superAdmin - ? orgsData?.organizationsConnection.map((item) => { - return ( -
    - -
    - ); - }) - : userData && - adminFor.length > 0 && - orgsData?.organizationsConnection.map((item) => { - if (isAdminForCurrentOrg(item)) { + ? orgsData?.organizationsConnection.map( + (item: InterfaceOrgConnectionInfoType) => { return (
    ); - } - })} + }, + ) + : userData && + adminFor.length > 0 && + orgsData?.organizationsConnection.map( + (item: InterfaceOrgConnectionInfoType) => { + if (isAdminForCurrentOrg(item)) { + return ( +
    + +
    + ); + } + }, + )} {isLoading && ( <> @@ -525,6 +526,7 @@ function orgList(): JSX.Element { setFormState={setFormState} createOrg={createOrg} t={t} + tCommon={tCommon} userData={userData} triggerCreateSampleOrg={triggerCreateSampleOrg} /> diff --git a/src/screens/OrgList/OrgListMocks.ts b/src/screens/OrgList/OrgListMocks.ts index 0706ec8f1f..380313ffd5 100644 --- a/src/screens/OrgList/OrgListMocks.ts +++ b/src/screens/OrgList/OrgListMocks.ts @@ -113,10 +113,10 @@ const MOCKS = [ { request: { query: USER_ORGANIZATION_LIST, - variables: { id: '123' }, + variables: { userId: '123' }, }, result: { - data: superAdminUser, + data: { user: superAdminUser }, }, }, { @@ -183,10 +183,10 @@ const MOCKS_EMPTY = [ { request: { query: USER_ORGANIZATION_LIST, - variables: { id: '123' }, + variables: { userId: '123' }, }, result: { - data: superAdminUser, + data: { user: superAdminUser }, }, }, ]; @@ -211,10 +211,10 @@ const MOCKS_WITH_ERROR = [ { request: { query: USER_ORGANIZATION_LIST, - variables: { id: '123' }, + variables: { userId: '123' }, }, result: { - data: superAdminUser, + data: { user: superAdminUser }, }, }, { @@ -247,10 +247,10 @@ const MOCKS_ADMIN = [ { request: { query: USER_ORGANIZATION_LIST, - variables: { id: '123' }, + variables: { userId: '123' }, }, result: { - data: adminUser, + data: { user: adminUser }, }, }, ]; diff --git a/src/screens/OrgList/OrganizationModal.tsx b/src/screens/OrgList/OrganizationModal.tsx index 7be39cc246..8a44d2b851 100644 --- a/src/screens/OrgList/OrganizationModal.tsx +++ b/src/screens/OrgList/OrganizationModal.tsx @@ -43,6 +43,7 @@ interface InterfaceOrganizationModalProps { setFormState: (state: React.SetStateAction) => void; createOrg: (e: ChangeEvent) => Promise; t: (key: string) => string; + tCommon: (key: string) => string; userData: InterfaceUserType | undefined; triggerCreateSampleOrg: () => void; } @@ -58,6 +59,7 @@ const OrganizationModal: React.FC = ({ setFormState, createOrg, t, + tCommon, triggerCreateSampleOrg, }) => { // function to update the state of the parameters inside address. @@ -92,7 +94,7 @@ const OrganizationModal: React.FC = ({
    - {t('name')} + {tCommon('name')} = ({ } }} /> - {t('description')} + {tCommon('description')} = ({ } }} /> - {t('address')} + {tCommon('address')}
    = ({ /> - {t('displayImage')} + {tCommon('displayImage')} = ({

    - {t('OR')} + {tCommon('OR')}
    {(adminFor.length > 0 || superAdmin) && (
    diff --git a/src/screens/OrgPost/OrgPost.tsx b/src/screens/OrgPost/OrgPost.tsx index 677394e618..29b7de0614 100644 --- a/src/screens/OrgPost/OrgPost.tsx +++ b/src/screens/OrgPost/OrgPost.tsx @@ -47,6 +47,7 @@ function orgPost(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'orgPost', }); + const { t: tCommon } = useTranslation('common'); document.title = t('title'); const [postmodalisOpen, setPostModalIsOpen] = useState(false); @@ -95,7 +96,11 @@ function orgPost(): JSX.Element { }; loading: boolean; error?: ApolloError; - refetch: any; + refetch: (filterData?: { + id: string | undefined; + title_contains: string | null; + text_contains: string | null; + }) => void; } = useQuery(ORGANIZATION_POST_LIST, { variables: { id: currentUrl, @@ -167,7 +172,7 @@ function orgPost(): JSX.Element { }); setPostModalIsOpen(false); } - } catch (error: any) { + } catch (error: unknown) { errorHandler(t, error); } }; @@ -201,7 +206,7 @@ function orgPost(): JSX.Element { } }; - const handleSearch = (e: any): void => { + const handleSearch = (e: React.ChangeEvent): void => { const { value } = e.target; const filterData = { id: currentUrl, @@ -539,7 +544,7 @@ function orgPost(): JSX.Element { onClick={(): void => hideInviteModal()} data-testid="closeOrganizationModal" > - {t('cancel')} + {tCommon('cancel')} diff --git a/src/screens/OrganizationActionItems/OrganizationActionItems.test.tsx b/src/screens/OrganizationActionItems/OrganizationActionItems.test.tsx index d0672aac18..a7a00b6caa 100644 --- a/src/screens/OrganizationActionItems/OrganizationActionItems.test.tsx +++ b/src/screens/OrganizationActionItems/OrganizationActionItems.test.tsx @@ -14,7 +14,7 @@ import 'jest-location-mock'; import { I18nextProvider } from 'react-i18next'; import { Provider } from 'react-redux'; import { BrowserRouter } from 'react-router-dom'; -import i18nForTest from 'utils/i18nForTest'; +import i18n from 'utils/i18nForTest'; import { toast } from 'react-toastify'; import { LocalizationProvider } from '@mui/x-date-pickers'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; @@ -68,11 +68,15 @@ const link3 = new StaticMockLink(MOCKS_ERROR_MEMBERS_LIST_QUERY, true); const link4 = new StaticMockLink(MOCKS_ERROR_ACTION_ITEM_LIST_QUERY, true); const link5 = new StaticMockLink(MOCKS_ERROR_MUTATIONS, true); -const translations = JSON.parse( - JSON.stringify( - i18nForTest.getDataByLanguage('en')?.translation.organizationActionItems, +const translations = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.organizationActionItems ?? {}, + ), ), -); + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; describe('Testing Action Item Categories Component', () => { const formData = { @@ -87,7 +91,7 @@ describe('Testing Action Item Categories Component', () => { - + {} @@ -98,7 +102,7 @@ describe('Testing Action Item Categories Component', () => { await wait(); await waitFor(() => { - expect(getByText(translations.createActionItem)).toBeInTheDocument(); + expect(getByText(translations.create)).toBeInTheDocument(); }); }); @@ -107,7 +111,7 @@ describe('Testing Action Item Categories Component', () => { - + {} @@ -118,9 +122,7 @@ describe('Testing Action Item Categories Component', () => { await wait(); await waitFor(() => { - expect( - queryByText(translations.createActionItem), - ).not.toBeInTheDocument(); + expect(queryByText(translations.create)).not.toBeInTheDocument(); }); }); @@ -129,7 +131,7 @@ describe('Testing Action Item Categories Component', () => { - + {} @@ -140,9 +142,7 @@ describe('Testing Action Item Categories Component', () => { await wait(); await waitFor(() => { - expect( - queryByText(translations.createActionItem), - ).not.toBeInTheDocument(); + expect(queryByText(translations.create)).not.toBeInTheDocument(); }); }); @@ -151,7 +151,7 @@ describe('Testing Action Item Categories Component', () => { - + {} @@ -162,9 +162,7 @@ describe('Testing Action Item Categories Component', () => { await wait(); await waitFor(() => { - expect( - queryByText(translations.createActionItem), - ).not.toBeInTheDocument(); + expect(queryByText(translations.create)).not.toBeInTheDocument(); }); }); @@ -173,7 +171,7 @@ describe('Testing Action Item Categories Component', () => { - + {} @@ -221,7 +219,7 @@ describe('Testing Action Item Categories Component', () => { - + {} @@ -340,7 +338,7 @@ describe('Testing Action Item Categories Component', () => { - + {} @@ -447,7 +445,7 @@ describe('Testing Action Item Categories Component', () => { - + {} @@ -481,7 +479,7 @@ describe('Testing Action Item Categories Component', () => { - + {} @@ -542,7 +540,7 @@ describe('Testing Action Item Categories Component', () => { - + {} diff --git a/src/screens/OrganizationActionItems/OrganizationActionItems.tsx b/src/screens/OrganizationActionItems/OrganizationActionItems.tsx index 106ab8cf73..073a544ef4 100644 --- a/src/screens/OrganizationActionItems/OrganizationActionItems.tsx +++ b/src/screens/OrganizationActionItems/OrganizationActionItems.tsx @@ -31,6 +31,7 @@ function organizationActionItems(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'organizationActionItems', }); + const { t: tCommon } = useTranslation('common'); const { orgId: currentUrl } = useParams(); @@ -355,7 +356,7 @@ function organizationActionItems(): JSX.Element { className={styles.createActionItemButton} > - {t('createActionItem')} + {tCommon('create')}
    diff --git a/src/screens/OrganizationDashboard/OrganizationDashboard.tsx b/src/screens/OrganizationDashboard/OrganizationDashboard.tsx index 429ad81a84..5c32d292a3 100644 --- a/src/screens/OrganizationDashboard/OrganizationDashboard.tsx +++ b/src/screens/OrganizationDashboard/OrganizationDashboard.tsx @@ -31,6 +31,7 @@ import styles from './OrganizationDashboard.module.css'; function organizationDashboard(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'dashboard' }); + const { t: tCommon } = useTranslation('common'); document.title = t('title'); const { orgId: currentUrl } = useParams(); const peopleLink = `/orgpeople/${currentUrl}`; @@ -76,10 +77,6 @@ function organizationDashboard(): JSX.Element { data: eventData, loading: loadingEvent, error: errorEvent, - }: { - data: any; - loading: boolean; - error?: ApolloError; } = useQuery(ORGANIZATION_EVENT_CONNECTION_LIST, { variables: { organization_id: currentUrl, @@ -90,13 +87,15 @@ function organizationDashboard(): JSX.Element { useEffect(() => { if (eventData && eventData?.eventsByOrganizationConnection.length > 0) { const tempUpcomingEvents: InterfaceQueryOrganizationEventListItem[] = []; - eventData?.eventsByOrganizationConnection.map((event: any) => { - const startDate = new Date(event.startDate); - const now = new Date(); - if (startDate > now) { - tempUpcomingEvents.push(event); - } - }); + eventData?.eventsByOrganizationConnection.map( + (event: InterfaceQueryOrganizationEventListItem) => { + const startDate = new Date(event.startDate); + const now = new Date(); + if (startDate > now) { + tempUpcomingEvents.push(event); + } + }, + ); setUpcomingEvents(tempUpcomingEvents); } }, [eventData?.eventsByOrganizationConnection]); @@ -135,7 +134,7 @@ function organizationDashboard(): JSX.Element { > } /> @@ -150,7 +149,7 @@ function organizationDashboard(): JSX.Element { > } /> @@ -210,7 +209,7 @@ function organizationDashboard(): JSX.Element { > } /> @@ -286,7 +285,7 @@ function organizationDashboard(): JSX.Element { /* eslint-enable */ postData?.organizations[0].posts.edges .slice(0, 5) - .map((edge: any) => { + .map((edge) => { const post = edge.node; return ( { }); } -const translations = JSON.parse( - JSON.stringify( - i18nForTest.getDataByLanguage('en')?.translation.organizationEvents, +const translations = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.organizationEvents ?? {}, + ), ), -); + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; jest.mock('@mui/x-date-pickers/DateTimePicker', () => { return { @@ -131,7 +135,7 @@ describe('Organisation Events Page', () => { - + @@ -154,7 +158,7 @@ describe('Organisation Events Page', () => { - + @@ -178,7 +182,7 @@ describe('Organisation Events Page', () => { - + @@ -218,7 +222,7 @@ describe('Organisation Events Page', () => { - + @@ -246,10 +250,7 @@ describe('Organisation Events Page', () => { screen.getByPlaceholderText(/Enter Description/i), formData.description, ); - userEvent.type( - screen.getByPlaceholderText(/Enter Location/i), - formData.location, - ); + userEvent.type(screen.getByPlaceholderText(/Location/i), formData.location); const endDatePicker = screen.getByLabelText('End Date'); const startDatePicker = screen.getByLabelText('Start Date'); @@ -312,7 +313,7 @@ describe('Organisation Events Page', () => { - + @@ -339,14 +340,8 @@ describe('Organisation Events Page', () => { screen.getByPlaceholderText(/Enter Description/i), formData.description, ); - userEvent.type( - screen.getByPlaceholderText(/Enter Location/i), - formData.location, - ); - userEvent.type( - screen.getByPlaceholderText(/Enter Location/i), - formData.location, - ); + userEvent.type(screen.getByPlaceholderText(/Location/i), formData.location); + userEvent.type(screen.getByPlaceholderText(/Location/i), formData.location); const endDatePicker = screen.getByLabelText('End Date'); const startDatePicker = screen.getByLabelText('Start Date'); @@ -396,7 +391,7 @@ describe('Organisation Events Page', () => { - + @@ -425,10 +420,7 @@ describe('Organisation Events Page', () => { formData.description, ); - userEvent.type( - screen.getByPlaceholderText(/Enter Location/i), - formData.location, - ); + userEvent.type(screen.getByPlaceholderText(/Location/i), formData.location); const endDatePicker = screen.getByLabelText('End Date'); const startDatePicker = screen.getByLabelText('Start Date'); diff --git a/src/screens/OrganizationEvents/OrganizationEvents.tsx b/src/screens/OrganizationEvents/OrganizationEvents.tsx index 0bf561381f..aaa6f911a6 100644 --- a/src/screens/OrganizationEvents/OrganizationEvents.tsx +++ b/src/screens/OrganizationEvents/OrganizationEvents.tsx @@ -44,6 +44,7 @@ function organizationEvents(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'organizationEvents', }); + const { t: tCommon } = useTranslation('common'); const { getItem } = useLocalStorage(); @@ -293,7 +294,7 @@ function organizationEvents(): JSX.Element { }); }} /> - + - +
    { @@ -349,7 +350,7 @@ function organizationEvents(): JSX.Element {
    { @@ -365,7 +366,7 @@ function organizationEvents(): JSX.Element {
    )} diff --git a/src/screens/OrganizationFundCampaign/CampaignDeleteModal.tsx b/src/screens/OrganizationFundCampaign/CampaignDeleteModal.tsx index 97146c4bc9..58351e1d1d 100644 --- a/src/screens/OrganizationFundCampaign/CampaignDeleteModal.tsx +++ b/src/screens/OrganizationFundCampaign/CampaignDeleteModal.tsx @@ -7,12 +7,14 @@ interface InterfaceDeleteCampaignModal { hideDeleteCampaignModal: () => void; deleteCampaignHandler: () => Promise; t: (key: string) => string; + tCommon: (key: string) => string; } const CampaignDeleteModal: React.FC = ({ campaignDeleteModalIsOpen, hideDeleteCampaignModal, deleteCampaignHandler, t, + tCommon, }) => { return ( <> @@ -36,14 +38,14 @@ const CampaignDeleteModal: React.FC = ({ onClick={deleteCampaignHandler} data-testid="deleteyesbtn" > - {t('yes')} + {tCommon('yes')} diff --git a/src/screens/OrganizationFundCampaign/OrganizationFundCampagins.tsx b/src/screens/OrganizationFundCampaign/OrganizationFundCampagins.tsx index 254616affc..24542d7e19 100644 --- a/src/screens/OrganizationFundCampaign/OrganizationFundCampagins.tsx +++ b/src/screens/OrganizationFundCampaign/OrganizationFundCampagins.tsx @@ -57,6 +57,7 @@ const orgFundCampaign = (): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'fundCampaign', }); + const { t: tCommon } = useTranslation('common'); const navigate = useNavigate(); const { fundId: currentUrl, orgId: orgId } = useParams(); @@ -298,7 +299,7 @@ const orgFundCampaign = (): JSX.Element => { data-testid="filter" > - {t('filter')} + {tCommon('filter')}
    @@ -333,10 +334,10 @@ const orgFundCampaign = (): JSX.Element => { {t('campaignName')} - {t('startDate')} + {tCommon('startDate')} - {t('endDate')} + {tCommon('endDate')} {t('fundingGoal')} @@ -437,6 +438,7 @@ const orgFundCampaign = (): JSX.Element => { hideDeleteCampaignModal={hideDeleteCampaignModal} deleteCampaignHandler={deleteCampaignHandler} t={t} + tCommon={tCommon} />
    ); diff --git a/src/screens/OrganizationFunds/OrganizationFunds.tsx b/src/screens/OrganizationFunds/OrganizationFunds.tsx index 2f67f61edc..cecedff2f1 100644 --- a/src/screens/OrganizationFunds/OrganizationFunds.tsx +++ b/src/screens/OrganizationFunds/OrganizationFunds.tsx @@ -55,6 +55,7 @@ const organizationFunds = (): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'funds', }); + const { t: tCommon } = useTranslation('common'); const { orgId: currentUrl } = useParams(); const navigate = useNavigate(); @@ -274,7 +275,7 @@ const organizationFunds = (): JSX.Element => { data-testid="filter" > - {t('filter')} + {tCommon('filter')}
    diff --git a/src/screens/OrganizationPeople/OrganizationPeople.module.css b/src/screens/OrganizationPeople/OrganizationPeople.module.css index 4442bdb58f..5ff4b0d297 100644 --- a/src/screens/OrganizationPeople/OrganizationPeople.module.css +++ b/src/screens/OrganizationPeople/OrganizationPeople.module.css @@ -42,9 +42,9 @@ position: relative; } -input { +/* input { outline: 1px solid var(--bs-gray-400); -} +} */ .btnsContainer .input button { width: 52px; diff --git a/src/screens/OrganizationPeople/OrganizationPeople.tsx b/src/screens/OrganizationPeople/OrganizationPeople.tsx index 62be3becaf..227a645292 100644 --- a/src/screens/OrganizationPeople/OrganizationPeople.tsx +++ b/src/screens/OrganizationPeople/OrganizationPeople.tsx @@ -26,6 +26,7 @@ function organizationPeople(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'organizationPeople', }); + const { t: tCommon } = useTranslation('common'); document.title = t('title'); @@ -316,7 +317,9 @@ function organizationPeople(): JSX.Element { setState(2); }} > - {t('users')} + + {tCommon('users')} + - + - + diff --git a/src/screens/OrganizationVenues/OrganizationVenues.tsx b/src/screens/OrganizationVenues/OrganizationVenues.tsx index 4005816d16..6d760508f0 100644 --- a/src/screens/OrganizationVenues/OrganizationVenues.tsx +++ b/src/screens/OrganizationVenues/OrganizationVenues.tsx @@ -19,6 +19,7 @@ function organizationVenues(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'organizationVenues', }); + const { t: tCommon } = useTranslation('common'); document.title = t('title'); const [venueModal, setVenueModal] = useState(false); @@ -150,7 +151,7 @@ function organizationVenues(): JSX.Element { }} data-testid="name" > - {t('name')} + {tCommon('name')} - {t('desc')} + {tCommon('description')} diff --git a/src/screens/PageNotFound/PageNotFound.test.tsx b/src/screens/PageNotFound/PageNotFound.test.tsx index af9325ca7d..501d9f7ef3 100644 --- a/src/screens/PageNotFound/PageNotFound.test.tsx +++ b/src/screens/PageNotFound/PageNotFound.test.tsx @@ -49,7 +49,7 @@ describe('Testing Page not found component', () => { , ); - expect(screen.getByText(/Talawa Admin/i)).toBeTruthy(); + expect(screen.getByText(/Talawa Admin Portal/i)).toBeTruthy(); expect(screen.getByText(/404/i)).toBeTruthy(); expect( screen.getByText(/Oops! The Page you requested was not found!/i), diff --git a/src/screens/PageNotFound/PageNotFound.tsx b/src/screens/PageNotFound/PageNotFound.tsx index 445868b4e8..92f4a98f7e 100644 --- a/src/screens/PageNotFound/PageNotFound.tsx +++ b/src/screens/PageNotFound/PageNotFound.tsx @@ -10,6 +10,8 @@ const PageNotFound = (): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'pageNotFound', }); + const { t: tCommon } = useTranslation('common'); + const { t: tErrors } = useTranslation('errors'); document.title = t('title'); @@ -22,7 +24,9 @@ const PageNotFound = (): JSX.Element => {
    Logo {adminFor != undefined ? ( -

    {t('talawaAdmin')}

    +

    + {tCommon('talawaAdminPortal')} +

    ) : (

    {t('talawaUser')}

    )} @@ -30,7 +34,7 @@ const PageNotFound = (): JSX.Element => {

    {t('404')}

    -

    {t('notFoundMsg')}

    +

    {tErrors('notFoundMsg')}

    {adminFor != undefined ? ( {t('backToHome')} diff --git a/src/screens/Requests/Requests.test.tsx b/src/screens/Requests/Requests.test.tsx index 9380653e7e..bf1a533870 100644 --- a/src/screens/Requests/Requests.test.tsx +++ b/src/screens/Requests/Requests.test.tsx @@ -198,7 +198,7 @@ describe('Testing Requests screen', () => { ); await wait(); - expect(screen.getByText(/No Request Found/i)).toBeTruthy(); + expect(screen.getByText(/No Membership Requests Found/i)).toBeTruthy(); }); test('Should render warning alert when there are no organizations', async () => { diff --git a/src/screens/Requests/Requests.tsx b/src/screens/Requests/Requests.tsx index 16a85f15cd..a779bd414c 100644 --- a/src/screens/Requests/Requests.tsx +++ b/src/screens/Requests/Requests.tsx @@ -28,6 +28,7 @@ interface InterfaceRequestsListItem { const Requests = (): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'requests' }); + const { t: tCommon } = useTranslation('common'); document.title = t('title'); @@ -189,8 +190,8 @@ const Requests = (): JSX.Element => { const headerTitles: string[] = [ t('sl_no'), - t('name'), - t('email'), + tCommon('name'), + tCommon('email'), t('accept'), t('reject'), ]; @@ -241,7 +242,7 @@ const Requests = (): JSX.Element => { searchByName.length > 0 ? (

    - {t('noResultsFoundFor')} "{searchByName}" + {tCommon('noResultsFoundFor')} "{searchByName}"

    ) : !isLoading && data && displayedRequests.length === 0 ? ( @@ -267,7 +268,7 @@ const Requests = (): JSX.Element => { data-testid="requests-list" endMessage={
    -
    {t('endOfResults')}
    +
    {tCommon('endOfResults')}
    } > diff --git a/src/screens/UserPortal/Chat/Chat.tsx b/src/screens/UserPortal/Chat/Chat.tsx index 4757ac9dcc..ee6a6c04f1 100644 --- a/src/screens/UserPortal/Chat/Chat.tsx +++ b/src/screens/UserPortal/Chat/Chat.tsx @@ -30,6 +30,7 @@ export default function chat(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'userChat', }); + const { t: tCommon } = useTranslation('common'); const organizationId = getOrganizationId(location.href); const [selectedContact, setSelectedContact] = React.useState(''); @@ -37,10 +38,6 @@ export default function chat(): JSX.Element { const [contacts, setContacts] = React.useState([]); const [filterName, setFilterName] = React.useState(''); - const navbarProps = { - currentPage: 'chat', - }; - const chatRoomProps: InterfaceChatRoomProps = { selectedContact, }; @@ -63,9 +60,11 @@ export default function chat(): JSX.Element { firstName_contains: value, }); }; - const handleSearchByEnter = (e: any): void => { + const handleSearchByEnter = ( + e: React.KeyboardEvent, + ): void => { if (e.key === 'Enter') { - const { value } = e.target; + const { value } = e.currentTarget; handleSearch(value); } }; @@ -95,7 +94,7 @@ export default function chat(): JSX.Element { Loading...
    ) : ( - contacts.map((contact: any, index: number) => { - const cardProps: InterfaceContactCardProps = { - id: contact._id, - firstName: contact.firstName, - lastName: contact.lastName, - email: contact.email, - image: contact.image, - setSelectedContactName, - selectedContact, - setSelectedContact, - }; - return ; - }) + contacts.map( + (contact: InterfaceContactCardProps, index: number) => { + const cardProps: InterfaceContactCardProps = { + id: contact.id, + firstName: contact.firstName, + lastName: contact.lastName, + email: contact.email, + image: contact.image, + setSelectedContactName, + selectedContact, + setSelectedContact, + }; + return ; + }, + ) )}
    diff --git a/src/screens/UserPortal/Events/Events.tsx b/src/screens/UserPortal/Events/Events.tsx index 660ea5e10f..bf2de7e456 100644 --- a/src/screens/UserPortal/Events/Events.tsx +++ b/src/screens/UserPortal/Events/Events.tsx @@ -1,72 +1,25 @@ -import type { ChangeEvent } from 'react'; -import React from 'react'; -import EventCard from 'components/UserPortal/EventCard/EventCard'; -import { Button, Dropdown, Form, InputGroup } from 'react-bootstrap'; -import PaginationList from 'components/PaginationList/PaginationList'; +import { useMutation, useQuery } from '@apollo/client'; +import { DatePicker, TimePicker } from '@mui/x-date-pickers'; +import { CREATE_EVENT_MUTATION } from 'GraphQl/Mutations/mutations'; import { - ORGANIZATION_EVENTS_CONNECTION, ORGANIZATIONS_LIST, + ORGANIZATION_EVENTS_CONNECTION, } from 'GraphQl/Queries/Queries'; -import { useMutation, useQuery } from '@apollo/client'; -import { SearchOutlined } from '@mui/icons-material'; -import styles from './Events.module.css'; -import { useTranslation } from 'react-i18next'; -import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; -import Modal from 'react-bootstrap/Modal'; -import { TimePicker, DatePicker } from '@mui/x-date-pickers'; +import EventCalendar from 'components/EventCalendar/EventCalendar'; +import EventHeader from 'components/EventCalendar/EventHeader'; import type { Dayjs } from 'dayjs'; import dayjs from 'dayjs'; -import { CREATE_EVENT_MUTATION } from 'GraphQl/Mutations/mutations'; +import type { ChangeEvent } from 'react'; +import React from 'react'; +import { Button, Form } from 'react-bootstrap'; +import Modal from 'react-bootstrap/Modal'; +import { useTranslation } from 'react-i18next'; +import { useParams } from 'react-router-dom'; import { toast } from 'react-toastify'; +import { ViewType } from 'screens/OrganizationEvents/OrganizationEvents'; import { errorHandler } from 'utils/errorHandler'; -import EventCalendar from 'components/EventCalendar/EventCalendar'; import useLocalStorage from 'utils/useLocalstorage'; -import { useNavigate, useParams } from 'react-router-dom'; -import { ViewType } from 'screens/OrganizationEvents/OrganizationEvents'; -import EventHeader from 'components/EventCalendar/EventHeader'; -interface InterfaceEventCardProps { - id: string; - title: string; - description: string; - location: string; - startDate: string; - endDate: string; - isRegisterable: boolean; - isPublic: boolean; - endTime: string; - startTime: string; - recurring: boolean; - allDay: boolean; - creator: { - firstName: string; - lastName: string; - id: string; - }; - registrants: { - id: string; - }[]; -} - -interface InterfaceAttendee { - _id: string; - title: string; - description: string; - location: string; - startDate: string; - endDate: string; - isRegisterable: boolean; - isPublic: boolean; - endTime: string; - startTime: string; - recurring: boolean; - allDay: boolean; - attendees: { _id: string }[]; - creator: { - firstName: string; - lastName: string; - _id: string; - }; -} +import styles from './Events.module.css'; const timeToDayJs = (time: string): Dayjs => { const dateTimeString = dayjs().format('YYYY-MM-DD') + ' ' + time; @@ -77,14 +30,11 @@ export default function events(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'userEvents', }); + const { t: tCommon } = useTranslation('common'); const { getItem } = useLocalStorage(); - const [page, setPage] = React.useState(0); - const [rowsPerPage, setRowsPerPage] = React.useState(5); const [events, setEvents] = React.useState([]); - const [mode, setMode] = React.useState(0); - // const [showCreateEventModal, setShowCreateEventModal] = React.useState(false); const [eventTitle, setEventTitle] = React.useState(''); const [eventDescription, setEventDescription] = React.useState(''); const [eventLocation, setEventLocation] = React.useState(''); @@ -100,9 +50,7 @@ export default function events(): JSX.Element { const [createEventModal, setCreateEventmodalisOpen] = React.useState(false); const { orgId: organizationId } = useParams(); - const modes = [t('listView'), t('calendarView')]; - - const { data, loading, refetch } = useQuery(ORGANIZATION_EVENTS_CONNECTION, { + const { data, refetch } = useQuery(ORGANIZATION_EVENTS_CONNECTION, { variables: { organization_id: organizationId, title_contains: '', @@ -166,50 +114,10 @@ export default function events(): JSX.Element { } }; - /* istanbul ignore next */ - const handleChangePage = ( - _event: React.MouseEvent | null, - newPage: number, - ): void => { - setPage(newPage); - }; /* istanbul ignore next */ const toggleCreateEventModal = (): void => setCreateEventmodalisOpen(!createEventModal); - /* istanbul ignore next */ - const handleChangeRowsPerPage = ( - event: React.ChangeEvent, - ): void => { - const newRowsPerPage = event.target.value; - - setRowsPerPage(parseInt(newRowsPerPage, 10)); - setPage(0); - }; - /* istanbul ignore next */ - const handleSearch = (value: string): void => { - refetch({ - title_contains: value, - }); - setPage(0); - }; - /* istanbul ignore next */ - const handleSearchByEnter = ( - e: React.KeyboardEvent, - ): void => { - if (e.key === 'Enter') { - const { value } = e.target as HTMLInputElement; - handleSearch(value); - } - }; - /* istanbul ignore next */ - const handleSearchByBtnClick = (): void => { - const value = - (document.getElementById('searchEvents') as HTMLInputElement)?.value || - ''; - handleSearch(value); - }; - const handleEventTitleChange = ( event: React.ChangeEvent, ): void => { @@ -290,7 +198,7 @@ export default function events(): JSX.Element { onChange={handleEventTitleChange} data-testid="eventTitleInput" /> - + - +
    { @@ -329,7 +237,7 @@ export default function events(): JSX.Element {
    { @@ -345,7 +253,7 @@ export default function events(): JSX.Element {
    - {t('filter').toUpperCase()} + {tCommon('filter').toUpperCase()} {modes.map((value, index) => { diff --git a/src/screens/UserPortal/Posts/Posts.module.css b/src/screens/UserPortal/Posts/Posts.module.css index 0cd897266b..fc0263833e 100644 --- a/src/screens/UserPortal/Posts/Posts.module.css +++ b/src/screens/UserPortal/Posts/Posts.module.css @@ -6,10 +6,6 @@ color: white; } -.maxWidth { - max-width: 300px; -} - .colorLight { background-color: #f5f5f5; } @@ -17,9 +13,11 @@ .mainContainer { width: 50%; flex-grow: 3; - padding: 30px; + padding: 1rem; max-height: 100%; - overflow: auto; + overflow-y: auto; + overflow-x: hidden; + background-color: #f2f7ff; } .containerHeight { @@ -32,10 +30,20 @@ } .postInputContainer { - background-color: white; - padding: 10px; - border-radius: 10px; - margin-bottom: 20px; + margin-top: 0.5rem; + margin-bottom: 1rem; +} + +.maxWidth { + width: 100%; + /* min-width: 3rem; */ + /* padding: 0; */ +} + +.inputArea { + border: none; + outline: none; + background-color: #f1f3f6; } .postActionContainer { @@ -71,18 +79,37 @@ } .postContainer { - margin: 1rem auto; - background-color: transparent; + width: auto; + background-color: white; + margin-top: 1rem; padding: 1rem; - border-radius: 4px; - /* max-width: 40rem; */ - box-shadow: rgba(0, 0, 0, 0.16) 0px 1px 4px; + border: 1px solid #dddddd; + border-radius: 10px; +} + +.heading { + font-size: 1.1rem; +} + +.pinnedPostsCardsContainer { + overflow-x: scroll; + display: flex; + gap: 1rem; + --bs-gutter-x: 0; +} + +.postsCardsContainer { + /* display: flex; + flex-wrap: wrap; + gap: 1rem; + --bs-gutter-x: 0; */ } .userImage { display: flex; width: 50px; height: 50px; + margin-left: 1rem; align-items: center; justify-content: center; overflow: hidden; diff --git a/src/screens/UserPortal/Posts/Posts.test.tsx b/src/screens/UserPortal/Posts/Posts.test.tsx index b4c1344d2c..4c49b7ba04 100644 --- a/src/screens/UserPortal/Posts/Posts.test.tsx +++ b/src/screens/UserPortal/Posts/Posts.test.tsx @@ -262,7 +262,7 @@ describe('Testing Home Screen: User Portal', () => { renderHomeScreen(); await wait(); - const startPostBtn = await screen.findByTestId('startPostBtn'); + const startPostBtn = await screen.findByTestId('postBtn'); expect(startPostBtn).toBeInTheDocument(); }); @@ -270,7 +270,7 @@ describe('Testing Home Screen: User Portal', () => { renderHomeScreen(); await wait(); - const startPostBtn = await screen.findByTestId('startPostBtn'); + const startPostBtn = await screen.findByTestId('postBtn'); expect(startPostBtn).toBeInTheDocument(); userEvent.click(startPostBtn); @@ -282,7 +282,13 @@ describe('Testing Home Screen: User Portal', () => { renderHomeScreen(); await wait(); - const startPostBtn = await screen.findByTestId('startPostBtn'); + userEvent.upload( + screen.getByTestId('postImageInput'), + new File(['image content'], 'image.png', { type: 'image/png' }), + ); + await wait(); + + const startPostBtn = await screen.findByTestId('postBtn'); expect(startPostBtn).toBeInTheDocument(); userEvent.click(startPostBtn); @@ -290,10 +296,6 @@ describe('Testing Home Screen: User Portal', () => { expect(startPostModal).toBeInTheDocument(); userEvent.type(screen.getByTestId('postInput'), 'some content'); - userEvent.upload( - screen.getByTestId('postImageInput'), - new File(['image content'], 'image.png', { type: 'image/png' }), - ); // Check that the content and image have been added expect(screen.getByTestId('postInput')).toHaveValue('some content'); @@ -320,12 +322,23 @@ describe('Testing Home Screen: User Portal', () => { const postCardContainers = screen.findAllByTestId('postCardContainer'); expect(postCardContainers).not.toBeNull(); - expect(screen.queryByText('post one')).toBeInTheDocument(); - expect(screen.queryByText('This is the first post')).toBeInTheDocument(); + expect(screen.queryAllByText('post one')[0]).toBeInTheDocument(); + expect( + screen.queryAllByText('This is the first post')[0], + ).toBeInTheDocument(); expect(screen.queryByText('post two')).toBeInTheDocument(); expect(screen.queryByText('This is the post two')).toBeInTheDocument(); }); + + test('Checking if refetch works after deleting this post', async () => { + setItem('userId', '640d98d9eb6a743d75341067'); + renderHomeScreen(); + await wait(); + + userEvent.click(screen.getAllByTestId('dropdown')[1]); + userEvent.click(screen.getByTestId('deletePost')); + }); }); describe('HomeScreen with invalid orgId', () => { diff --git a/src/screens/UserPortal/Posts/Posts.tsx b/src/screens/UserPortal/Posts/Posts.tsx index 22de2a95f3..aaa5345f1c 100644 --- a/src/screens/UserPortal/Posts/Posts.tsx +++ b/src/screens/UserPortal/Posts/Posts.tsx @@ -1,6 +1,8 @@ import { useQuery } from '@apollo/client'; -import ChevronRightIcon from '@mui/icons-material/ChevronRight'; import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; +import SendIcon from '@mui/icons-material/Send'; +import ChevronRightIcon from '@mui/icons-material/ChevronRight'; +import ChevronLeftIcon from '@mui/icons-material/ChevronLeft'; import { ADVERTISEMENTS_GET, ORGANIZATION_POST_LIST, @@ -14,16 +16,13 @@ import type { import PromotedPost from 'components/UserPortal/PromotedPost/PromotedPost'; import StartPostModal from 'components/UserPortal/StartPostModal/StartPostModal'; import React, { useEffect, useState } from 'react'; -import { Button, Col, Container, Image, Row } from 'react-bootstrap'; +import { Button, Col, Form, Row } from 'react-bootstrap'; import { useTranslation } from 'react-i18next'; -import { Link, Navigate, useParams } from 'react-router-dom'; +import { Navigate, useParams } from 'react-router-dom'; import useLocalStorage from 'utils/useLocalstorage'; -import UserDefault from '../../../assets/images/defaultImg.png'; -import { ReactComponent as MediaIcon } from 'assets/svgs/media.svg'; -import { ReactComponent as ArticleIcon } from 'assets/svgs/article.svg'; -import { ReactComponent as EventIcon } from 'assets/svgs/userEvent.svg'; import styles from './Posts.module.css'; +import convertToBase64 from 'utils/convertToBase64'; interface InterfaceAdContent { _id: string; @@ -98,17 +97,23 @@ type InterfacePostNode = { export default function home(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'home' }); + const { t: tCommon } = useTranslation('common'); const { getItem } = useLocalStorage(); const [posts, setPosts] = useState([]); + const [pinnedPosts, setPinnedPosts] = useState([]); const [adContent, setAdContent] = useState({}); const [filteredAd, setFilteredAd] = useState([]); const [showModal, setShowModal] = useState(false); + const [postImg, setPostImg] = useState(''); const { orgId } = useParams(); if (!orgId) { return ; } + const navbarProps = { + currentPage: 'home', + }; const { data: promotedPostsData } = useQuery(ADVERTISEMENTS_GET); const { data, @@ -141,6 +146,14 @@ export default function home(): JSX.Element { setFilteredAd(filterAdContent(adContent, orgId)); }, [adContent]); + useEffect(() => { + setPinnedPosts( + posts.filter(({ node }: { node: InterfacePostNode }) => { + return node.pinned; + }), + ); + }, [posts]); + const filterAdContent = ( data: { advertisementsConnection?: { @@ -169,6 +182,87 @@ export default function home(): JSX.Element { return []; }; + const getCardProps = (node: InterfacePostNode): InterfacePostCard => { + const { + creator, + _id, + imageUrl, + videoUrl, + title, + text, + likeCount, + commentCount, + likedBy, + comments, + } = node; + + const allLikes: any = []; + + likedBy.forEach((value: any) => { + const singleLike = { + firstName: value.firstName, + lastName: value.lastName, + id: value._id, + }; + allLikes.push(singleLike); + }); + + const postComments: any = []; + + comments.forEach((value: any) => { + const commentLikes: any = []; + value.likedBy.forEach((commentLike: any) => { + const singleLike = { + id: commentLike._id, + }; + commentLikes.push(singleLike); + }); + + const comment = { + id: value._id, + creator: { + firstName: value.creator.firstName, + lastName: value.creator.lastName, + id: value.creator._id, + email: value.creator.email, + }, + likeCount: value.likeCount, + likedBy: commentLikes, + text: value.text, + }; + postComments.push(comment); + }); + + const date = new Date(node.createdAt); + const formattedDate = new Intl.DateTimeFormat('en-US', { + year: 'numeric', + month: 'short', + day: 'numeric', + }).format(date); + + const cardProps: InterfacePostCard = { + id: _id, + creator: { + id: creator._id, + firstName: creator.firstName, + lastName: creator.lastName, + email: creator.email, + }, + postedAt: formattedDate, + image: imageUrl, + video: videoUrl, + title, + text, + likeCount, + commentCount, + comments: postComments, + likedBy: allLikes, + fetchPosts: () => refetch(), + }; + + return cardProps; + }; + const handlePostButtonClick = (): void => { setShowModal(true); }; @@ -181,72 +275,62 @@ export default function home(): JSX.Element { <>
    -

    Posts

    - - -
    - - - - - - - - -
    -
    - -
    -

    {t('media')}

    -
    - -
    -
    - {/*
    {eventSvg}
    */} -
    - -
    -

    {t('event')}

    -
    - -
    -
    -
    - -
    -

    {t('article')}

    -
    - - - +

    {t('posts')}

    +
    +
    {t('startPost')}
    +
    + +
    + , + ): Promise => { + setPostImg(''); + const target = e.target as HTMLInputElement; + const file = target.files && target.files[0]; + const base64file = file && (await convertToBase64(file)); + setPostImg(base64file); + }} + /> + + + +
    + +
    +
    -

    {t('feed')}

    -
    - - {t('pinnedPosts')} - - -
    +

    {t('feed')}

    + {pinnedPosts.length > 0 && ( +
    +

    {t(`pinnedPosts`)}

    +
    + {pinnedPosts.map(({ node }: { node: InterfacePostNode }) => { + const cardProps = getCardProps(node); + return ; + })} +
    +
    + )}
    {filteredAd.length > 0 && ( @@ -262,94 +346,37 @@ export default function home(): JSX.Element { ))} )} - +

    {t(`yourFeed`)}

    +
    {loadingPosts ? (
    - Loading... + {tCommon('loading')}
    ) : ( <> - {posts.map(({ node }: { node: InterfacePostNode }) => { - const { - creator, - _id, - imageUrl, - videoUrl, - title, - text, - likeCount, - commentCount, - likedBy, - comments, - } = node; - - const allLikes: any = []; - - likedBy.forEach((value: any) => { - const singleLike = { - firstName: value.firstName, - lastName: value.lastName, - id: value._id, - }; - allLikes.push(singleLike); - }); - - const postComments: any = []; - - comments.forEach((value: any) => { - const commentLikes: any = []; - value.likedBy.forEach((commentLike: any) => { - const singleLike = { - id: commentLike._id, - }; - commentLikes.push(singleLike); - }); - - const comment = { - id: value._id, - creator: { - firstName: value.creator.firstName, - lastName: value.creator.lastName, - id: value.creator._id, - email: value.creator.email, - }, - likeCount: value.likeCount, - likedBy: commentLikes, - text: value.text, - }; - postComments.push(comment); - }); - - const cardProps: InterfacePostCard = { - id: _id, - creator: { - id: creator._id, - firstName: creator.firstName, - lastName: creator.lastName, - email: creator.email, - }, - image: imageUrl, - video: videoUrl, - title, - text, - likeCount, - commentCount, - comments: postComments, - likedBy: allLikes, - }; - - return ; - })} + {posts.length > 0 ? ( + + {posts.map(({ node }: { node: InterfacePostNode }) => { + const cardProps = getCardProps(node); + return ; + })} + + ) : ( +

    + {t(`nothingToShowHere`)} +

    + )} )} + - ); diff --git a/src/screens/UserPortal/Settings/Settings.tsx b/src/screens/UserPortal/Settings/Settings.tsx index 160137d07d..b1b4a0d0c6 100644 --- a/src/screens/UserPortal/Settings/Settings.tsx +++ b/src/screens/UserPortal/Settings/Settings.tsx @@ -26,6 +26,7 @@ export default function settings(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'settings', }); + const { t: tCommon } = useTranslation('common'); const [hideDrawer, setHideDrawer] = useState(null); @@ -85,7 +86,7 @@ export default function settings(): JSX.Element { const userFullName = `${userDetails.firstName} ${userDetails.lastName}`; setItem('name', userFullName); } - } catch (error: any) { + } catch (error: unknown) { errorHandler(t, error); } }; @@ -208,7 +209,7 @@ export default function settings(): JSX.Element {
    -

    {t('settings')}

    +

    {tCommon('settings')}

    - {t('firstName')} + {tCommon('firstName')} - {t('lastName')} + {tCommon('lastName')} - {t('emailAddress')} + {tCommon('emailAddress')} - {t('displayImage')} + {tCommon('displayImage')}
    diff --git a/src/screens/Users/Users.tsx b/src/screens/Users/Users.tsx index a97e226270..c03842069f 100644 --- a/src/screens/Users/Users.tsx +++ b/src/screens/Users/Users.tsx @@ -21,6 +21,7 @@ import useLocalStorage from 'utils/useLocalstorage'; const Users = (): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'users' }); + const { t: tCommon } = useTranslation('common'); document.title = t('title'); @@ -234,8 +235,8 @@ const Users = (): JSX.Element => { const headerTitles: string[] = [ '#', - t('name'), - t('email'), + tCommon('name'), + tCommon('email'), t('joined_organizations'), t('blocked_organizations'), ]; @@ -307,33 +308,33 @@ const Users = (): JSX.Element => { data-testid="filterUsers" > - {t('filter')} + {tCommon('filter')} handleFiltering('admin')} > - {t('admin')} + {tCommon('admin')} handleFiltering('superAdmin')} > - {t('superAdmin')} + {tCommon('superAdmin')} handleFiltering('user')} > - {t('user')} + {tCommon('user')} handleFiltering('cancel')} > - {t('cancel')} + {tCommon('cancel')} @@ -346,7 +347,7 @@ const Users = (): JSX.Element => { searchByName.length > 0 ? (

    - {t('noResultsFoundFor')} "{searchByName}" + {tCommon('noResultsFoundFor')} "{searchByName}"

    ) : isLoading == false && data && displayedUsers.length === 0 ? ( @@ -375,7 +376,7 @@ const Users = (): JSX.Element => { data-testid="users-list" endMessage={
    -
    {t('endOfResults')}
    +
    {tCommon('endOfResults')}
    } > diff --git a/src/state/reducers/routesReducer.test.ts b/src/state/reducers/routesReducer.test.ts index 36b630094e..0a474df0c3 100644 --- a/src/state/reducers/routesReducer.test.ts +++ b/src/state/reducers/routesReducer.test.ts @@ -23,7 +23,7 @@ describe('Testing Routes reducer', () => { }, { name: 'Advertisement', url: '/orgads/undefined' }, { name: 'Funds', url: '/orgfunds/undefined' }, - { name: 'Requests', url: '/requests/undefined' }, + { name: 'Membership Requests', url: '/requests/undefined' }, { name: 'Plugins', subTargets: [ @@ -76,7 +76,7 @@ describe('Testing Routes reducer', () => { component: 'OrganizationFunds', }, { - name: 'Requests', + name: 'Membership Requests', comp_id: 'requests', component: 'Requests', }, @@ -117,7 +117,7 @@ describe('Testing Routes reducer', () => { { name: 'Block/Unblock', url: '/blockuser/orgId' }, { name: 'Advertisement', url: '/orgads/orgId' }, { name: 'Funds', url: '/orgfunds/orgId' }, - { name: 'Requests', url: '/requests/orgId' }, + { name: 'Membership Requests', url: '/requests/orgId' }, { name: 'Plugins', subTargets: [ @@ -166,7 +166,7 @@ describe('Testing Routes reducer', () => { }, { name: 'Funds', comp_id: 'orgfunds', component: 'OrganizationFunds' }, { - name: 'Requests', + name: 'Membership Requests', comp_id: 'requests', component: 'Requests', }, @@ -210,7 +210,7 @@ describe('Testing Routes reducer', () => { }, { name: 'Advertisement', url: '/orgads/undefined' }, { name: 'Funds', url: '/orgfunds/undefined' }, - { name: 'Requests', url: '/requests/undefined' }, + { name: 'Membership Requests', url: '/requests/undefined' }, { name: 'Settings', url: '/orgsetting/undefined' }, { comp_id: null, @@ -266,7 +266,7 @@ describe('Testing Routes reducer', () => { component: 'OrganizationFunds', }, { - name: 'Requests', + name: 'Membership Requests', comp_id: 'requests', component: 'Requests', }, diff --git a/src/state/reducers/routesReducer.ts b/src/state/reducers/routesReducer.ts index e223b0754e..34cfdbbcca 100644 --- a/src/state/reducers/routesReducer.ts +++ b/src/state/reducers/routesReducer.ts @@ -80,7 +80,7 @@ const components: ComponentType[] = [ { name: 'Block/Unblock', comp_id: 'blockuser', component: 'BlockUser' }, { name: 'Advertisement', comp_id: 'orgads', component: 'Advertisements' }, { name: 'Funds', comp_id: 'orgfunds', component: 'OrganizationFunds' }, - { name: 'Requests', comp_id: 'requests', component: 'Requests' }, + { name: 'Membership Requests', comp_id: 'requests', component: 'Requests' }, { name: 'Plugins', comp_id: null, diff --git a/src/utils/errorHandler.test.tsx b/src/utils/errorHandler.test.tsx index a90ab859c7..1ca42441ab 100644 --- a/src/utils/errorHandler.test.tsx +++ b/src/utils/errorHandler.test.tsx @@ -10,16 +10,17 @@ jest.mock('react-toastify', () => ({ describe('Test if errorHandler is working properly', () => { const t: TFunction<'translation', string> = (key: string) => key; + const tErrors: TFunction<'errors', string> = (key: string) => key; it('should call toast.error with the correct message if error message is "Failed to fetch"', () => { - const error = { message: 'Failed to fetch' }; + const error = new Error('Failed to fetch'); errorHandler(t, error); - expect(toast.error).toHaveBeenCalledWith(t('talawaApiUnavailable')); + expect(toast.error).toHaveBeenCalledWith(tErrors('talawaApiUnavailable')); }); it('should call toast.error with the error message if it is not "Failed to fetch"', () => { - const error = { message: 'Some other error message' }; + const error = new Error('Some other error message'); errorHandler(t, error); expect(toast.error).toHaveBeenCalledWith(error.message); @@ -29,6 +30,8 @@ describe('Test if errorHandler is working properly', () => { const error = null; errorHandler(t, error); - expect(toast.error).toHaveBeenCalledWith(undefined); + expect(toast.error).toHaveBeenCalledWith( + tErrors('unknownError', { msg: error }), + ); }); }); diff --git a/src/utils/errorHandler.tsx b/src/utils/errorHandler.tsx index 508284db5a..aa7c6dc9dc 100644 --- a/src/utils/errorHandler.tsx +++ b/src/utils/errorHandler.tsx @@ -1,17 +1,23 @@ import type { TFunction } from 'react-i18next'; import { toast } from 'react-toastify'; +import i18n from './i18n'; /* This function is used to handle api errors in the application. It takes in the error object and displays the error message to the user. If the error is due to the Talawa API being unavailable, it displays a custom message. */ -export const errorHandler = ( - t: TFunction<'translation', string>, - error: any, -): void => { - if (error?.message === 'Failed to fetch') { - toast.error(t('talawaApiUnavailable')); +export const errorHandler = (a: unknown, error: unknown): void => { + const tErrors: TFunction = i18n.getFixedT(null, 'errors'); + if (error instanceof Error) { + switch (error.message) { + case 'Failed to fetch': + toast.error(tErrors('talawaApiUnavailable')); + break; + // Add more cases as needed + default: + toast.error(error.message); + } } else { - toast.error(error?.message); + toast.error(tErrors('unknownError', { msg: error })); } }; diff --git a/src/utils/i18n.ts b/src/utils/i18n.ts index 6fb7cd4ff0..3aafbd843d 100644 --- a/src/utils/i18n.ts +++ b/src/utils/i18n.ts @@ -10,6 +10,8 @@ i18n .use(LanguageDetector) .use(HttpApi) .init({ + ns: ['translation', 'errors', 'common'], + defaultNS: 'translation', fallbackLng: 'en', supportedLngs: languageArray, detection: { @@ -17,7 +19,7 @@ i18n caches: ['cookie'], }, backend: { - loadPath: '/locales/{{lng}}.json', + loadPath: '/locales/{{lng}}/{{ns}}.json', }, // debug: true, }); diff --git a/src/utils/i18nForTest.ts b/src/utils/i18nForTest.ts index 527b96b5f9..673b4b0750 100644 --- a/src/utils/i18nForTest.ts +++ b/src/utils/i18nForTest.ts @@ -4,13 +4,17 @@ import LanguageDetector from 'i18next-browser-languagedetector'; import HttpApi from 'i18next-http-backend'; import { languageArray } from './languages'; -import translationEnglish from '../../public/locales/en.json'; +import translationEnglish from '../../public/locales/en/translation.json'; +import translationCommonEnglish from '../../public/locales/en/common.json'; +import translationErrorEnglish from '../../public/locales/en/errors.json'; i18n .use(LanguageDetector) .use(HttpApi) .use(initReactI18next) .init({ + ns: ['translation', 'errors', 'common'], + defaultNS: 'translation', fallbackLng: 'en', supportedLngs: languageArray, detection: { @@ -20,6 +24,8 @@ i18n resources: { en: { translation: translationEnglish, + common: translationCommonEnglish, + errors: translationErrorEnglish, }, }, react: { useSuspense: false }, diff --git a/src/utils/interfaces.ts b/src/utils/interfaces.ts index 0ce6e2f78f..abaac2efcc 100644 --- a/src/utils/interfaces.ts +++ b/src/utils/interfaces.ts @@ -399,6 +399,7 @@ export interface InterfacePostCard { email: string; id: string; }; + postedAt: string; image: string | null; video: string | null; text: string; @@ -424,6 +425,7 @@ export interface InterfacePostCard { lastName: string; id: string; }[]; + fetchPosts: () => void; } export interface InterfaceCreateCampaign { campaignName: string; From 5010350d8fb6c0a0b1edeab6d9d2909ca50bfcde Mon Sep 17 00:00:00 2001 From: Peter Harrison <16875803+palisadoes@users.noreply.github.com> Date: Sat, 27 Jul 2024 11:46:01 -0700 Subject: [PATCH 23/34] Latest Develop 20240724 (#2127) * 20240727112607 Deleted all files in the main branch in anticipation of merging develop into main cleanly * 20240727112842 Merge develop into main --- package-lock.json | 19164 +++++++++++++++- package.json | 42 +- public/locales/en/common.json | 23 +- public/locales/en/errors.json | 3 +- public/locales/en/translation.json | 166 +- public/locales/fr/common.json | 23 +- public/locales/fr/errors.json | 3 +- public/locales/fr/translation.json | 164 +- public/locales/hi/common.json | 23 +- public/locales/hi/errors.json | 3 +- public/locales/hi/translation.json | 192 +- public/locales/sp/common.json | 23 +- public/locales/sp/errors.json | 3 +- public/locales/sp/translation.json | 193 +- public/locales/zh/common.json | 23 +- public/locales/zh/errors.json | 3 +- public/locales/zh/translation.json | 174 +- schema.graphql | 13 +- src/App.test.tsx | 1 + src/App.tsx | 8 +- .../Mutations/AgendaCategoryMutations.ts | 45 + src/GraphQl/Mutations/AgendaItemMutations.ts | 31 + .../Mutations/OrganizationMutations.ts | 118 +- src/GraphQl/Mutations/PledgeMutation.ts | 2 + src/GraphQl/Mutations/mutations.ts | 15 + src/GraphQl/Queries/AgendaCategoryQueries.ts | 23 + src/GraphQl/Queries/AgendaItemQueries.ts | 73 + src/GraphQl/Queries/PlugInQueries.ts | 149 + src/GraphQl/Queries/Queries.ts | 11 +- src/GraphQl/Queries/fundQueries.ts | 24 +- src/assets/css/app.css | 6 +- src/assets/svgs/agenda-category-icon.svg | 1 + src/assets/svgs/agenda-items.svg | 1 + src/assets/svgs/chat.svg | 4 + src/assets/svgs/newChat.svg | 4 + .../ActionItems/ActionItemsContainer.test.tsx | 107 + .../ActionItems/ActionItemsContainer.tsx | 68 +- .../core/AddOnRegister/AddOnRegister.test.tsx | 2 +- .../core/AddOnRegister/AddOnRegister.tsx | 2 +- .../Advertisements/Advertisements.test.tsx | 2 +- .../AdvertisementEntry/AdvertisementEntry.tsx | 2 +- .../AdvertisementRegister.test.tsx | 10 +- .../AdvertisementRegister.tsx | 16 +- .../AgendaCategoryContainer.module.css | 20 + .../AgendaCategoryContainer.test.tsx | 415 + .../AgendaCategoryContainer.tsx | 272 + .../AgendaCategoryContainerMocks.ts | 104 + .../AgendaCategoryContainerProps.ts | 34 + .../AgendaItemsContainer.module.css | 230 + .../AgendaItems/AgendaItemsContainer.test.tsx | 418 + .../AgendaItems/AgendaItemsContainer.tsx | 411 + .../AgendaItems/AgendaItemsContainerMocks.ts | 119 + .../AgendaItems/AgendaItemsContainerProps.ts | 101 + .../AgendaItemsCreateModal.test.tsx | 368 + .../AgendaItems/AgendaItemsCreateModal.tsx | 293 + .../AgendaItems/AgendaItemsDeleteModal.tsx | 63 + .../AgendaItemsPreviewModal.test.tsx | 102 + .../AgendaItems/AgendaItemsPreviewModal.tsx | 151 + .../AgendaItemsUpdateModal.test.tsx | 369 + .../AgendaItems/AgendaItemsUpdateModal.tsx | 296 + src/components/Avatar/Avatar.module.css | 3 + .../ChangeLanguageDropDown.tsx | 26 +- .../ChangeLanguageDropdown.test.tsx | 102 +- src/components/CheckIn/TableRow.test.tsx | 6 +- src/components/CheckIn/TableRow.tsx | 6 +- .../EditCustomFieldDropDown.test.tsx | 6 +- .../EditCustomFieldDropDown.tsx | 32 +- .../EventCalendar/EventCalendar.tsx | 3 +- .../EventActionItems.module.css | 50 +- .../EventActionItems.test.tsx | 745 +- .../EventActionItems/EventActionItems.tsx | 366 +- .../useEventActionColumnConfig.tsx | 200 + .../EventAgendaItems.module.css | 22 + .../EventAgendaItems.test.tsx | 205 + .../EventAgendaItems/EventAgendaItems.tsx | 203 + .../EventAgendaItems/EventAgendaItemsMocks.ts | 133 + .../EventRegistrantsModal.test.tsx | 16 +- .../EventRegistrantsModal.tsx | 29 +- .../IconComponent/IconComponent.tsx | 12 +- .../LeftDrawerOrg/LeftDrawerOrg.test.tsx | 20 +- .../OrgActionItemCategories.test.tsx | 20 +- .../OrganizationScreen/OrganizationScreen.tsx | 1 + .../ProfileDropdown/ProfileDropdown.test.tsx | 6 +- .../ProfileDropdown/ProfileDropdown.tsx | 6 +- .../UserPasswordUpdate.test.tsx | 4 +- .../UserPasswordUpdate/UserPasswordUpdate.tsx | 6 +- .../UserPortal/ChatRoom/ChatRoom.module.css | 99 +- .../UserPortal/ChatRoom/ChatRoom.test.tsx | 861 +- .../UserPortal/ChatRoom/ChatRoom.tsx | 393 +- .../ContactCard/ContactCard.module.css | 18 +- .../ContactCard/ContactCard.test.tsx | 7 +- .../UserPortal/ContactCard/ContactCard.tsx | 24 +- .../CreateDirectChat.module.css | 9 + .../CreateDirectChat.test.tsx | 2204 ++ .../CreateDirectChat/CreateDirectChat.tsx | 202 + .../CreateGroupChat.module.css | 9 + .../CreateGroupChat/CreateGroupChat.test.tsx | 2746 +++ .../CreateGroupChat/CreateGroupChat.tsx | 391 + .../UserPortal/Login/Login.module.css | 29 - .../UserPortal/Login/Login.test.tsx | 306 - src/components/UserPortal/Login/Login.tsx | 144 - .../OrganizationSidebar.tsx | 113 +- .../UserPortal/PostCard/PostCard.module.css | 7 +- .../UserPortal/PostCard/PostCard.test.tsx | 6 +- .../UserPortal/PostCard/PostCard.tsx | 22 +- .../StartPostModal/StartPostModal.tsx | 2 +- .../UserSidebar/UserSidebar.module.css | 4 +- .../UserPortal/UserSidebar/UserSidebar.tsx | 23 + .../UserSidebarOrg/UserSidebarOrg.tsx | 2 +- .../UserProfileSettings/UserProfile.test.tsx | 9 +- .../UserProfileSettings/UserProfile.tsx | 40 +- .../UserProfileSettings.module.css | 1 + .../UsersTableItem/UsersTableItem.tsx | 58 +- src/index.tsx | 11 +- src/reportWebVitals.ts | 16 +- .../CommunityProfile/CommunityProfile.tsx | 15 +- .../EventManagement/EventManagement.test.tsx | 6 + .../EventManagement/EventManagement.tsx | 20 +- .../FundCampaignPledge.module.css | 226 +- .../FundCampaignPledge.test.tsx | 595 +- .../FundCampaignPledge/FundCampaignPledge.tsx | 789 +- .../FundCampaignPledge/PledgeCreateModal.tsx | 150 - .../PledgeDeleteModal.test.tsx | 101 + .../FundCampaignPledge/PledgeDeleteModal.tsx | 63 +- .../FundCampaignPledge/PledgeEditModal.tsx | 149 - .../FundCampaignPledge/PledgeModal.test.tsx | 213 + .../FundCampaignPledge/PledgeModal.tsx | 322 + .../FundCampaignPledge/PledgesMocks.ts | 325 +- src/screens/LoginPage/LoginPage.tsx | 4 +- src/screens/MemberDetail/MemberDetail.tsx | 4 +- src/screens/OrgSettings/OrgSettings.test.tsx | 6 +- .../ActionItemCreateModal.tsx | 2 +- .../ActionItemUpdateModal.tsx | 55 +- .../OrganizationActionItemMocks.ts | 29 + .../OrganizationActionItems.test.tsx | 22 + .../OrganizationActionItems.tsx | 8 +- .../AgendaCategoryCreateModal.test.tsx | 125 + .../AgendaCategoryCreateModal.tsx | 89 + .../AgendaCategoryDeleteModal.tsx | 63 + .../AgendaCategoryPreviewModal.tsx | 91 + .../AgendaCategoryUpdateModal.test.tsx | 151 + .../AgendaCategoryUpdateModal.tsx | 86 + .../OrganizationAgendaCategory.module.css | 171 + .../OrganizationAgendaCategory.test.tsx | 235 + .../OrganizationAgendaCategory.tsx | 157 + .../OrganizationAgendaCategoryErrorMocks.ts | 51 + .../OrganizationAgendaCategoryMocks.ts | 47 + .../CampaignCreateModal.tsx | 158 - .../CampaignDeleteModal.test.tsx | 95 + .../CampaignDeleteModal.tsx | 56 +- .../CampaignModal.test.tsx | 266 + .../CampaignModal.tsx | 291 + .../CampaignUpdateModal.tsx | 170 - .../OrganizationFundCampagins.tsx | 674 +- .../OrganizationFundCampaign.module.css | 35 +- .../OrganizationFundCampaign.test.tsx | 745 +- ...s.tsx => OrganizationFundCampaignMocks.ts} | 262 +- .../OrganizationFunds/FundCreateModal.tsx | 118 - .../FundDeleteModal.test.tsx | 100 + .../OrganizationFunds/FundDeleteModal.tsx | 79 + .../OrganizationFunds/FundModal.test.tsx | 260 + src/screens/OrganizationFunds/FundModal.tsx | 258 + .../OrganizationFunds/FundUpdateModal.tsx | 155 - .../OrganizationFunds.module.css | 99 +- .../OrganizationFunds.test.tsx | 507 +- .../OrganizationFunds/OrganizationFunds.tsx | 681 +- .../OrganizationFundsMocks.ts | 322 +- src/screens/OrganizationPeople/AddMember.tsx | 6 +- .../OrganizationPeople/OrganizationPeople.tsx | 20 +- .../OrganizationVenues/OrganizationVenues.tsx | 2 +- src/screens/UserPortal/Chat/Chat.module.css | 197 +- src/screens/UserPortal/Chat/Chat.test.tsx | 2239 +- src/screens/UserPortal/Chat/Chat.tsx | 322 +- .../Organizations/Organizations.module.css | 3 +- src/screens/UserPortal/Posts/Posts.test.tsx | 122 +- src/screens/UserPortal/Posts/Posts.tsx | 120 +- .../UserPortal/Settings/Settings.module.css | 3 +- .../UserPortal/Settings/Settings.test.tsx | 142 + src/screens/UserPortal/Settings/Settings.tsx | 10 +- src/screens/Users/Users.test.tsx | 472 +- src/screens/Users/Users.tsx | 65 +- src/state/reducers/routesReducer.test.ts | 18 + src/state/reducers/routesReducer.ts | 5 + src/utils/currency.ts | 2 +- src/utils/interfaces.ts | 99 +- 185 files changed, 42585 insertions(+), 5676 deletions(-) create mode 100644 src/GraphQl/Mutations/AgendaCategoryMutations.ts create mode 100644 src/GraphQl/Mutations/AgendaItemMutations.ts create mode 100644 src/GraphQl/Queries/AgendaCategoryQueries.ts create mode 100644 src/GraphQl/Queries/AgendaItemQueries.ts create mode 100644 src/assets/svgs/agenda-category-icon.svg create mode 100644 src/assets/svgs/agenda-items.svg create mode 100644 src/assets/svgs/chat.svg create mode 100644 src/assets/svgs/newChat.svg create mode 100644 src/components/AgendaCategory/AgendaCategoryContainer.module.css create mode 100644 src/components/AgendaCategory/AgendaCategoryContainer.test.tsx create mode 100644 src/components/AgendaCategory/AgendaCategoryContainer.tsx create mode 100644 src/components/AgendaCategory/AgendaCategoryContainerMocks.ts create mode 100644 src/components/AgendaCategory/AgendaCategoryContainerProps.ts create mode 100644 src/components/AgendaItems/AgendaItemsContainer.module.css create mode 100644 src/components/AgendaItems/AgendaItemsContainer.test.tsx create mode 100644 src/components/AgendaItems/AgendaItemsContainer.tsx create mode 100644 src/components/AgendaItems/AgendaItemsContainerMocks.ts create mode 100644 src/components/AgendaItems/AgendaItemsContainerProps.ts create mode 100644 src/components/AgendaItems/AgendaItemsCreateModal.test.tsx create mode 100644 src/components/AgendaItems/AgendaItemsCreateModal.tsx create mode 100644 src/components/AgendaItems/AgendaItemsDeleteModal.tsx create mode 100644 src/components/AgendaItems/AgendaItemsPreviewModal.test.tsx create mode 100644 src/components/AgendaItems/AgendaItemsPreviewModal.tsx create mode 100644 src/components/AgendaItems/AgendaItemsUpdateModal.test.tsx create mode 100644 src/components/AgendaItems/AgendaItemsUpdateModal.tsx create mode 100644 src/components/EventManagement/EventActionItems/useEventActionColumnConfig.tsx create mode 100644 src/components/EventManagement/EventAgendaItems/EventAgendaItems.module.css create mode 100644 src/components/EventManagement/EventAgendaItems/EventAgendaItems.test.tsx create mode 100644 src/components/EventManagement/EventAgendaItems/EventAgendaItems.tsx create mode 100644 src/components/EventManagement/EventAgendaItems/EventAgendaItemsMocks.ts create mode 100644 src/components/UserPortal/CreateDirectChat/CreateDirectChat.module.css create mode 100644 src/components/UserPortal/CreateDirectChat/CreateDirectChat.test.tsx create mode 100644 src/components/UserPortal/CreateDirectChat/CreateDirectChat.tsx create mode 100644 src/components/UserPortal/CreateGroupChat/CreateGroupChat.module.css create mode 100644 src/components/UserPortal/CreateGroupChat/CreateGroupChat.test.tsx create mode 100644 src/components/UserPortal/CreateGroupChat/CreateGroupChat.tsx delete mode 100644 src/components/UserPortal/Login/Login.module.css delete mode 100644 src/components/UserPortal/Login/Login.test.tsx delete mode 100644 src/components/UserPortal/Login/Login.tsx delete mode 100644 src/screens/FundCampaignPledge/PledgeCreateModal.tsx create mode 100644 src/screens/FundCampaignPledge/PledgeDeleteModal.test.tsx delete mode 100644 src/screens/FundCampaignPledge/PledgeEditModal.tsx create mode 100644 src/screens/FundCampaignPledge/PledgeModal.test.tsx create mode 100644 src/screens/FundCampaignPledge/PledgeModal.tsx create mode 100644 src/screens/OrganizationAgendaCategory/AgendaCategoryCreateModal.test.tsx create mode 100644 src/screens/OrganizationAgendaCategory/AgendaCategoryCreateModal.tsx create mode 100644 src/screens/OrganizationAgendaCategory/AgendaCategoryDeleteModal.tsx create mode 100644 src/screens/OrganizationAgendaCategory/AgendaCategoryPreviewModal.tsx create mode 100644 src/screens/OrganizationAgendaCategory/AgendaCategoryUpdateModal.test.tsx create mode 100644 src/screens/OrganizationAgendaCategory/AgendaCategoryUpdateModal.tsx create mode 100644 src/screens/OrganizationAgendaCategory/OrganizationAgendaCategory.module.css create mode 100644 src/screens/OrganizationAgendaCategory/OrganizationAgendaCategory.test.tsx create mode 100644 src/screens/OrganizationAgendaCategory/OrganizationAgendaCategory.tsx create mode 100644 src/screens/OrganizationAgendaCategory/OrganizationAgendaCategoryErrorMocks.ts create mode 100644 src/screens/OrganizationAgendaCategory/OrganizationAgendaCategoryMocks.ts delete mode 100644 src/screens/OrganizationFundCampaign/CampaignCreateModal.tsx create mode 100644 src/screens/OrganizationFundCampaign/CampaignDeleteModal.test.tsx create mode 100644 src/screens/OrganizationFundCampaign/CampaignModal.test.tsx create mode 100644 src/screens/OrganizationFundCampaign/CampaignModal.tsx delete mode 100644 src/screens/OrganizationFundCampaign/CampaignUpdateModal.tsx rename src/screens/OrganizationFundCampaign/{OrganizationFundCampaignMocks.tsx => OrganizationFundCampaignMocks.ts} (59%) delete mode 100644 src/screens/OrganizationFunds/FundCreateModal.tsx create mode 100644 src/screens/OrganizationFunds/FundDeleteModal.test.tsx create mode 100644 src/screens/OrganizationFunds/FundDeleteModal.tsx create mode 100644 src/screens/OrganizationFunds/FundModal.test.tsx create mode 100644 src/screens/OrganizationFunds/FundModal.tsx delete mode 100644 src/screens/OrganizationFunds/FundUpdateModal.tsx diff --git a/package-lock.json b/package-lock.json index e60d88abe1..d44e07627c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,7 +1,7 @@ { "name": "talawa-admin", "version": "3.0.0", - "lockfileVersion": 3, + "lockfileVersion": 2, "requires": true, "packages": { "": { @@ -13,50 +13,53 @@ "@apollo/react-testing": "^4.0.0", "@dicebear/collection": "^8.0.1", "@dicebear/core": "^8.0.1", - "@emotion/react": "^11.11.1", + "@emotion/react": "^11.11.4", "@emotion/styled": "^11.11.5", - "@mui/icons-material": "^5.8.3", - "@mui/material": "^5.15.15", + "@mui/icons-material": "^5.16.1", + "@mui/material": "^5.16.4", "@mui/private-theming": "^5.15.12", "@mui/system": "^5.14.12", - "@mui/x-charts": "^7.4.0", - "@mui/x-data-grid": "^6.20.0", - "@mui/x-date-pickers": "^6.6.0", + "@mui/x-charts": "^7.8.0", + "@mui/x-data-grid": "^7.11.0", + "@mui/x-date-pickers": "^7.6.1", "@pdfme/generator": "^1.2.6", - "bootstrap": "^5.3.0", + "bootstrap": "^5.3.3", "customize-cra": "^1.0.0", "dayjs": "^1.11.11", "flag-icons": "^6.6.6", - "graphql": "^16.8.1", + "graphql": "^16.9.0", "graphql-tag": "^2.12.6", "graphql-ws": "^5.16.0", "history": "^5.3.0", "i18next": "^21.8.14", - "i18next-browser-languagedetector": "^6.1.4", - "i18next-http-backend": "^1.4.1", + "i18next-browser-languagedetector": "^8.0.0", + "i18next-http-backend": "^2.5.2", "inquirer": "^8.0.0", "js-cookie": "^3.0.1", "markdown-toc": "^1.2.0", - "prettier": "^3.2.5", + "prettier": "^3.3.2", "react": "^17.0.2", "react-app-rewired": "^2.2.1", + "react-beautiful-dnd": "^13.1.1", "react-bootstrap": "^2.7.4", - "react-datepicker": "^4.2.0", + "react-datepicker": "^7.3.0", "react-dom": "^17.0.2", - "react-google-recaptcha": "^2.1.0", + "react-google-recaptcha": "^3.1.0", "react-i18next": "^11.18.1", "react-icons": "^5.2.1", "react-infinite-scroll-component": "^6.1.0", + "react-multi-carousel": "^2.8.5", "react-redux": "^7.2.5", - "react-router-dom": "^6.22.2", + "react-router-dom": "^6.25.1", "react-scripts": "5.0.1", "react-toastify": "^9.0.3", + "react-tooltip": "^5.27.1", "redux": "^4.1.1", "redux-thunk": "^2.3.0", "sanitize-html": "^2.13.0", - "typedoc-plugin-markdown": "^4.0.2", + "typedoc-plugin-markdown": "^4.2.1", "typescript": "^4.3.5", - "web-vitals": "^1.0.1" + "web-vitals": "^4.2.2" }, "devDependencies": { "@babel/plugin-proposal-private-property-in-object": "^7.21.11", @@ -69,6 +72,7 @@ "@types/node": "^20.12.12", "@types/node-fetch": "^2.6.10", "@types/react": "^17.0.14", + "@types/react-beautiful-dnd": "^13.1.8", "@types/react-bootstrap": "^0.32.32", "@types/react-datepicker": "^4.1.4", "@types/react-dom": "^17.0.9", @@ -90,10 +94,10 @@ "jest-localstorage-mock": "^2.4.19", "jest-location-mock": "^2.0.0", "jest-preview": "^0.3.1", - "lint-staged": "^15.2.2", + "lint-staged": "^15.2.7", "postcss-modules": "^6.0.0", - "sass": "^1.71.1", - "tsx": "^3.11.0" + "sass": "^1.77.4", + "tsx": "^4.16.2" }, "engines": { "node": ">=20.x" @@ -2284,9 +2288,9 @@ "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" }, "node_modules/@babel/runtime": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.1.tgz", - "integrity": "sha512-+BIznRzyqBf+2wCTxcKE3wDjfGeCoVE61KSHGpkzqrLi8qxqFwBeUFyId2cxkTmm55fzDGnm0+yCxaxygrLUnQ==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.8.tgz", + "integrity": "sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -3071,14 +3075,14 @@ "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" }, "node_modules/@emotion/react": { - "version": "11.11.1", - "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.1.tgz", - "integrity": "sha512-5mlW1DquU5HaxjLkfkGN1GA/fvVGdyHURRiX/0FHl2cfIfRxSOfmxEH5YS43edp0OldZrZ+dkBKbngxcNCdZvA==", + "version": "11.11.4", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz", + "integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==", "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.11.0", "@emotion/cache": "^11.11.0", - "@emotion/serialize": "^1.1.2", + "@emotion/serialize": "^1.1.3", "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", "@emotion/utils": "^1.2.1", "@emotion/weak-memoize": "^0.3.1", @@ -3155,10 +3159,266 @@ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@esbuild/linux-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", "cpu": [ "x64" ], @@ -3171,6 +3431,102 @@ "node": ">=12" } }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -3301,10 +3657,24 @@ "@floating-ui/utils": "^0.2.0" } }, + "node_modules/@floating-ui/react": { + "version": "0.26.19", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.19.tgz", + "integrity": "sha512-Jk6zITdjjIvjO/VdQFvpRaD3qPwOHH6AoDHxjhpy+oK4KFgaSP871HYWUAPdnLmx1gQ+w/pB312co3tVml+BXA==", + "dependencies": { + "@floating-ui/react-dom": "^2.1.1", + "@floating-ui/utils": "^0.2.4", + "tabbable": "^6.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, "node_modules/@floating-ui/react-dom": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.9.tgz", - "integrity": "sha512-q0umO0+LQK4+p6aGyvzASqKbKOJcAHJ7ycE9CuUvfx3s9zTHWmGJTPOIlM/hmSBfUfg/XfY5YhLBLR/LHwShQQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.1.tgz", + "integrity": "sha512-4h84MJt3CHrtG18mGsXuLCHMrug49d7DFkU0RMIyshRveBeyV2hmV/pDaF2Uxtu8kgq5r46llp5E5FQiR0K2Yg==", "dependencies": { "@floating-ui/dom": "^1.0.0" }, @@ -3314,9 +3684,9 @@ } }, "node_modules/@floating-ui/utils": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.2.tgz", - "integrity": "sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw==" + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.4.tgz", + "integrity": "sha512-dWO2pw8hhi+WrXq1YJy2yCuWoL20PddgGaqTgVe4cOS9Q6qklXCiA1tJEqX6BEwRNSCP84/afac9hd4MS+zEUA==" }, "node_modules/@gar/promisify": { "version": "1.1.3", @@ -3894,27 +4264,27 @@ } }, "node_modules/@mui/core-downloads-tracker": { - "version": "5.15.15", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.15.tgz", - "integrity": "sha512-aXnw29OWQ6I5A47iuWEI6qSSUfH6G/aCsW9KmW3LiFqr7uXZBK4Ks+z8G+qeIub8k0T5CMqlT2q0L+ZJTMrqpg==", + "version": "5.16.4", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.4.tgz", + "integrity": "sha512-rNdHXhclwjEZnK+//3SR43YRx0VtjdHnUFhMSGYmAMJve+KiwEja/41EYh8V3pZKqF2geKyfcFUenTfDTYUR4w==", "funding": { "type": "opencollective", "url": "https://opencollective.com/mui-org" } }, "node_modules/@mui/icons-material": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.14.0.tgz", - "integrity": "sha512-z7lYNteDi1GMkF9JP/m2RWuCYK1M/FlaeBSUK7/IhIYzIXNhAVjfD8jRq5vFBV31qkEi2aGBS2z5SfLXwH6U0A==", + "version": "5.16.1", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.16.1.tgz", + "integrity": "sha512-ogQPweYba4+5XZykilwxn2/oS78uwoQ0BVBpOhhCJo0ooZsqTTsalhzP2qD/RdGqMQ8xyXPz1sYM2djTruVVVA==", "dependencies": { - "@babel/runtime": "^7.22.5" + "@babel/runtime": "^7.23.9" }, "engines": { "node": ">=12.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { "@mui/material": "^5.0.0", @@ -3928,21 +4298,21 @@ } }, "node_modules/@mui/material": { - "version": "5.15.15", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.15.tgz", - "integrity": "sha512-3zvWayJ+E1kzoIsvwyEvkTUKVKt1AjchFFns+JtluHCuvxgKcLSRJTADw37k0doaRtVAsyh8bz9Afqzv+KYrIA==", + "version": "5.16.4", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.16.4.tgz", + "integrity": "sha512-dBnh3/zRYgEVIS3OE4oTbujse3gifA0qLMmuUk13ywsDCbngJsdgwW5LuYeiT5pfA8PGPGSqM7mxNytYXgiMCw==", "dependencies": { "@babel/runtime": "^7.23.9", - "@mui/base": "5.0.0-beta.40", - "@mui/core-downloads-tracker": "^5.15.15", - "@mui/system": "^5.15.15", - "@mui/types": "^7.2.14", - "@mui/utils": "^5.15.14", + "@mui/core-downloads-tracker": "^5.16.4", + "@mui/system": "^5.16.4", + "@mui/types": "^7.2.15", + "@mui/utils": "^5.16.4", + "@popperjs/core": "^2.11.8", "@types/react-transition-group": "^4.4.10", "clsx": "^2.1.0", "csstype": "^3.1.3", "prop-types": "^15.8.1", - "react-is": "^18.2.0", + "react-is": "^18.3.1", "react-transition-group": "^4.4.5" }, "engines": { @@ -3980,12 +4350,12 @@ } }, "node_modules/@mui/private-theming": { - "version": "5.15.14", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.14.tgz", - "integrity": "sha512-UH0EiZckOWcxiXLX3Jbb0K7rC8mxTr9L9l6QhOZxYc4r8FHUkefltV9VDGLrzCaWh30SQiJvAEd7djX3XXY6Xw==", + "version": "5.16.4", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.16.4.tgz", + "integrity": "sha512-ZsAm8cq31SJ37SVWLRlu02v9SRthxnfQofaiv14L5Bht51B0dz6yQEoVU/V8UduZDCCIrWkBHuReVfKhE/UuXA==", "dependencies": { "@babel/runtime": "^7.23.9", - "@mui/utils": "^5.15.14", + "@mui/utils": "^5.16.4", "prop-types": "^15.8.1" }, "engines": { @@ -4006,9 +4376,9 @@ } }, "node_modules/@mui/styled-engine": { - "version": "5.15.14", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.15.14.tgz", - "integrity": "sha512-RILkuVD8gY6PvjZjqnWhz8fu68dVkqhM5+jYWfB5yhlSQKg+2rHkmEwm75XIeAqI3qwOndK6zELK5H6Zxn4NHw==", + "version": "5.16.4", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.16.4.tgz", + "integrity": "sha512-0+mnkf+UiAmTVB8PZFqOhqf729Yh0Cxq29/5cA3VAyDVTRIUUQ8FXQhiAhUIbijFmM72rY80ahFPXIm4WDbzcA==", "dependencies": { "@babel/runtime": "^7.23.9", "@emotion/cache": "^11.11.0", @@ -4037,15 +4407,15 @@ } }, "node_modules/@mui/system": { - "version": "5.15.15", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.15.tgz", - "integrity": "sha512-aulox6N1dnu5PABsfxVGOZffDVmlxPOVgj56HrUnJE8MCSh8lOvvkd47cebIVQQYAjpwieXQXiDPj5pwM40jTQ==", + "version": "5.16.4", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.16.4.tgz", + "integrity": "sha512-ET1Ujl2/8hbsD611/mqUuNArMCGv/fIWO/f8B3ZqF5iyPHM2aS74vhTNyjytncc4i6dYwGxNk+tLa7GwjNS0/w==", "dependencies": { "@babel/runtime": "^7.23.9", - "@mui/private-theming": "^5.15.14", - "@mui/styled-engine": "^5.15.14", - "@mui/types": "^7.2.14", - "@mui/utils": "^5.15.14", + "@mui/private-theming": "^5.16.4", + "@mui/styled-engine": "^5.16.4", + "@mui/types": "^7.2.15", + "@mui/utils": "^5.16.4", "clsx": "^2.1.0", "csstype": "^3.1.3", "prop-types": "^15.8.1" @@ -4084,9 +4454,9 @@ } }, "node_modules/@mui/types": { - "version": "7.2.14", - "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.14.tgz", - "integrity": "sha512-MZsBZ4q4HfzBsywtXgM1Ksj6HDThtiwmOKUXH1pKYISI9gAVXCNHNpo7TlGoGrBaYWZTdNoirIN7JsQcQUjmQQ==", + "version": "7.2.15", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.15.tgz", + "integrity": "sha512-nbo7yPhtKJkdf9kcVOF8JZHPZTmqXjJ/tI0bdWgHg5tp9AnIN4Y7f7wm9T+0SyGYJk76+GYZ8Q5XaTYAsUHN0Q==", "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0" }, @@ -4097,14 +4467,15 @@ } }, "node_modules/@mui/utils": { - "version": "5.15.14", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.14.tgz", - "integrity": "sha512-0lF/7Hh/ezDv5X7Pry6enMsbYyGKjADzvHyo3Qrc/SSlTsQ1VkbDMbH0m2t3OR5iIVLwMoxwM7yGd+6FCMtTFA==", + "version": "5.16.4", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.16.4.tgz", + "integrity": "sha512-nlppYwq10TBIFqp7qxY0SvbACOXeOjeVL3pOcDsK0FT8XjrEXh9/+lkg8AEIzD16z7YfiJDQjaJG2OLkE7BxNg==", "dependencies": { "@babel/runtime": "^7.23.9", - "@types/prop-types": "^15.7.11", + "@types/prop-types": "^15.7.12", + "clsx": "^2.1.1", "prop-types": "^15.8.1", - "react-is": "^18.2.0" + "react-is": "^18.3.1" }, "engines": { "node": ">=12.0.0" @@ -4123,15 +4494,23 @@ } } }, + "node_modules/@mui/utils/node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" + } + }, "node_modules/@mui/x-charts": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@mui/x-charts/-/x-charts-7.4.0.tgz", - "integrity": "sha512-W6A0ZJmfXLeAtuml0Yi7gvjxS6aW/2h6uO9PQNuE/rpV0iIEMU5bVfcJZGMVlh0WY+43FEicI1/8n6FzMcfZdg==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@mui/x-charts/-/x-charts-7.8.0.tgz", + "integrity": "sha512-SosaVtx4Ig1nu/loH6Mq4peH5Pq5UvVEnsMfe4G2IEVrMxfwrktWJo+86t9LxiHTERt4wxPKnsqlhkgBIf9ePQ==", "dependencies": { - "@babel/runtime": "^7.24.0", + "@babel/runtime": "^7.24.7", "@mui/base": "^5.0.0-beta.40", - "@mui/system": "^5.15.14", - "@mui/utils": "^5.15.14", + "@mui/system": "^5.15.20", + "@mui/utils": "^5.15.20", "@react-spring/rafz": "^9.7.3", "@react-spring/web": "^9.7.3", "clsx": "^2.1.1", @@ -4170,13 +4549,15 @@ } }, "node_modules/@mui/x-data-grid": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-6.20.0.tgz", - "integrity": "sha512-N9a4eJRmWgP5zT2AZ41BnBgCSQJiw4dc5Q2U9zQ5aOhOs+8Jb218tX79MIAfwt1s4rbTZmgAdsBUn9Xs93Kmrw==", - "dependencies": { - "@babel/runtime": "^7.23.2", - "@mui/utils": "^5.14.16", - "clsx": "^2.0.0", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-7.11.0.tgz", + "integrity": "sha512-dXaIw3Noxc4d6xenS7J+zMPORG9ptkTW7B81P6QFovILSEuI/qebQhijy/IkqRvcCsuZYLL3nA89bp+EDI503Q==", + "dependencies": { + "@babel/runtime": "^7.24.8", + "@mui/system": "^5.16.2", + "@mui/utils": "^5.16.2", + "@mui/x-internals": "7.11.0", + "clsx": "^2.1.1", "prop-types": "^15.8.1", "reselect": "^4.1.8" }, @@ -4185,11 +4566,10 @@ }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { - "@mui/material": "^5.4.1", - "@mui/system": "^5.4.1", + "@mui/material": "^5.15.14", "react": "^17.0.0 || ^18.0.0", "react-dom": "^17.0.0 || ^18.0.0" } @@ -4203,14 +4583,16 @@ } }, "node_modules/@mui/x-date-pickers": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-6.10.0.tgz", - "integrity": "sha512-tp0i65JqZarIRyyTyQy5OjOPgjJv5cO7oQAbOrAePIHn7UEYPXe3k4ISiUzEAjBBXy1HhwQxGRJslVp4BXe3MA==", - "dependencies": { - "@babel/runtime": "^7.22.5", - "@mui/utils": "^5.13.6", - "@types/react-transition-group": "^4.4.6", - "clsx": "^1.2.1", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-7.6.1.tgz", + "integrity": "sha512-erSq5cnOUyBgBmpHnMxIit5yhT3bl/lOaNZKpObvJtvEJetvNA9xWQ7dz/J/AufLzDuvThjusuRD0y+GmeXtiw==", + "dependencies": { + "@babel/runtime": "^7.24.6", + "@mui/base": "^5.0.0-beta.40", + "@mui/system": "^5.15.15", + "@mui/utils": "^5.15.14", + "@types/react-transition-group": "^4.4.10", + "clsx": "^2.1.1", "prop-types": "^15.8.1", "react-transition-group": "^4.4.5" }, @@ -4219,16 +4601,14 @@ }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { "@emotion/react": "^11.9.0", "@emotion/styled": "^11.8.1", - "@mui/base": "^5.0.0-alpha.87", - "@mui/material": "^5.8.6", - "@mui/system": "^5.8.0", - "date-fns": "^2.25.0", - "date-fns-jalali": "^2.13.0-0", + "@mui/material": "^5.15.14", + "date-fns": "^2.25.0 || ^3.2.0", + "date-fns-jalali": "^2.13.0-0 || ^3.2.0-0", "dayjs": "^1.10.7", "luxon": "^3.0.2", "moment": "^2.29.4", @@ -4267,6 +4647,33 @@ } } }, + "node_modules/@mui/x-date-pickers/node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@mui/x-internals": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-7.11.0.tgz", + "integrity": "sha512-GqCYylKiB4cLH9tK4JweJlT2JvPjnpXjS3TEIqtHB4BcSsezhdRrMGzHOO5zCJqkasqTirJh2t6X16Qw1llr4Q==", + "dependencies": { + "@babel/runtime": "^7.24.8", + "@mui/utils": "^5.16.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0" + } + }, "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { "version": "5.1.1-v1", "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", @@ -4606,9 +5013,9 @@ } }, "node_modules/@remix-run/router": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.2.tgz", - "integrity": "sha512-+Rnav+CaoTE5QJc4Jcwh5toUpnVLKYbpU6Ys0zqbakqbaLQHeglLVHPfxOiQqdNmUy5C2lXz5dwC6tQNX2JW2Q==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.18.0.tgz", + "integrity": "sha512-L3jkqmqoSVBVKHfpGZmLrex0lxR5SucGA0sUfFzGctehw+S/ggL9L/0NnC5mw6P8HUWpFZ3nQw3cRApjjWx9Sw==", "engines": { "node": ">=14.0.0" } @@ -4731,6 +5138,15 @@ "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.3.2.tgz", "integrity": "sha512-V+MvGwaHH03hYhY+k6Ef/xKd6RYlc4q8WBx+2ANmipHJcKuktNcI/NgEsJgdSUF6Lw32njT6OnrRsKYCdgHjYw==" }, + "node_modules/@shikijs/core": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.10.3.tgz", + "integrity": "sha512-D45PMaBaeDHxww+EkcDQtDAtzv00Gcsp72ukBtaLSmqRvh0WgGMq3Al0rl1QQBZfuneO75NXMIzEZGFitThWbg==", + "peer": true, + "dependencies": { + "@types/hast": "^3.0.4" + } + }, "node_modules/@sinclair/typebox": { "version": "0.24.51", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", @@ -5497,6 +5913,15 @@ "@types/node": "*" } }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "peer": true, + "dependencies": { + "@types/unist": "*" + } + }, "node_modules/@types/history": { "version": "4.7.11", "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", @@ -5678,6 +6103,15 @@ "csstype": "^3.0.2" } }, + "node_modules/@types/react-beautiful-dnd": { + "version": "13.1.8", + "resolved": "https://registry.npmjs.org/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.1.8.tgz", + "integrity": "sha512-E3TyFsro9pQuK4r8S/OL6G99eq7p8v29sX0PM7oT8Z+PJfZvSQTx4zTQbUJ+QZXioAF0e7TGBEcA1XhYhCweyQ==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/react-bootstrap": { "version": "0.32.32", "resolved": "https://registry.npmjs.org/@types/react-bootstrap/-/react-bootstrap-0.32.32.tgz", @@ -5852,6 +6286,12 @@ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.3.tgz", "integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==" }, + "node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", + "peer": true + }, "node_modules/@types/warning": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.0.tgz", @@ -6486,12 +6926,6 @@ "node": ">=8" } }, - "node_modules/ansi-sequence-parser": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz", - "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==", - "peer": true - }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -7345,9 +7779,9 @@ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" }, "node_modules/bootstrap": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.0.tgz", - "integrity": "sha512-UnBV3E3v4STVNQdms6jSGO2CvOkjUMdDAVR2V5N4uCMdaIkaQjbcEAMqRimDHIs4uqBYzDAKCQwCB+97tJgHQw==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz", + "integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==", "funding": [ { "type": "github", @@ -7359,7 +7793,7 @@ } ], "peerDependencies": { - "@popperjs/core": "^2.11.7" + "@popperjs/core": "^2.11.8" } }, "node_modules/boxen": { @@ -7434,11 +7868,11 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -8460,11 +8894,11 @@ } }, "node_modules/cross-fetch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", + "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", "dependencies": { - "node-fetch": "2.6.7" + "node-fetch": "^2.6.12" } }, "node_modules/cross-spawn": { @@ -8505,6 +8939,14 @@ "postcss": "^8.4" } }, + "node_modules/css-box-model": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz", + "integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==", + "dependencies": { + "tiny-invariant": "^1.0.6" + } + }, "node_modules/css-declaration-sorter": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", @@ -9106,6 +9548,7 @@ "version": "2.30.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "devOptional": true, "dependencies": { "@babel/runtime": "^7.21.0" }, @@ -9897,9 +10340,9 @@ } }, "node_modules/esbuild": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", - "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", "dev": true, "hasInstallScript": true, "bin": { @@ -9909,28 +10352,29 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.18.20", - "@esbuild/android-arm64": "0.18.20", - "@esbuild/android-x64": "0.18.20", - "@esbuild/darwin-arm64": "0.18.20", - "@esbuild/darwin-x64": "0.18.20", - "@esbuild/freebsd-arm64": "0.18.20", - "@esbuild/freebsd-x64": "0.18.20", - "@esbuild/linux-arm": "0.18.20", - "@esbuild/linux-arm64": "0.18.20", - "@esbuild/linux-ia32": "0.18.20", - "@esbuild/linux-loong64": "0.18.20", - "@esbuild/linux-mips64el": "0.18.20", - "@esbuild/linux-ppc64": "0.18.20", - "@esbuild/linux-riscv64": "0.18.20", - "@esbuild/linux-s390x": "0.18.20", - "@esbuild/linux-x64": "0.18.20", - "@esbuild/netbsd-x64": "0.18.20", - "@esbuild/openbsd-x64": "0.18.20", - "@esbuild/sunos-x64": "0.18.20", - "@esbuild/win32-arm64": "0.18.20", - "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" } }, "node_modules/escalade": { @@ -11213,9 +11657,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -11794,9 +12238,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz", - "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==", + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz", + "integrity": "sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==", "dev": true, "dependencies": { "resolve-pkg-maps": "^1.0.0" @@ -12055,9 +12499,9 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" }, "node_modules/graphql": { - "version": "16.8.1", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.8.1.tgz", - "integrity": "sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==", + "version": "16.9.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.9.0.tgz", + "integrity": "sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==", "engines": { "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" } @@ -12731,19 +13175,19 @@ } }, "node_modules/i18next-browser-languagedetector": { - "version": "6.1.8", - "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-6.1.8.tgz", - "integrity": "sha512-Svm+MduCElO0Meqpj1kJAriTC6OhI41VhlT/A0UPjGoPZBhAHIaGE5EfsHlTpgdH09UVX7rcc72pSDDBeKSQQA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.0.0.tgz", + "integrity": "sha512-zhXdJXTTCoG39QsrOCiOabnWj2jecouOqbchu3EfhtSHxIB5Uugnm9JaizenOy39h7ne3+fLikIjeW88+rgszw==", "dependencies": { - "@babel/runtime": "^7.19.0" + "@babel/runtime": "^7.23.2" } }, "node_modules/i18next-http-backend": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-1.4.5.tgz", - "integrity": "sha512-tLuHWuLWl6CmS07o+UB6EcQCaUjrZ1yhdseIN7sfq0u7phsMePJ8pqlGhIAdRDPF/q7ooyo5MID5DRFBCH+x5w==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-2.5.2.tgz", + "integrity": "sha512-+K8HbDfrvc1/2X8jpb7RLhI9ZxBDpx3xogYkQwGKlWAUXLSEGXzgdt3EcUjLlBCdMwdQY+K+EUF6oh8oB6rwHw==", "dependencies": { - "cross-fetch": "3.1.5" + "cross-fetch": "4.0.0" } }, "node_modules/iconv-lite": { @@ -15562,12 +16006,6 @@ "node": ">=6" } }, - "node_modules/jsonc-parser": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", - "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", - "peer": true - }, "node_modules/jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -15728,22 +16166,31 @@ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "peer": true, + "dependencies": { + "uc.micro": "^2.0.0" + } + }, "node_modules/lint-staged": { - "version": "15.2.2", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.2.tgz", - "integrity": "sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==", - "dev": true, - "dependencies": { - "chalk": "5.3.0", - "commander": "11.1.0", - "debug": "4.3.4", - "execa": "8.0.1", - "lilconfig": "3.0.0", - "listr2": "8.0.1", - "micromatch": "4.0.5", - "pidtree": "0.6.0", - "string-argv": "0.3.2", - "yaml": "2.3.4" + "version": "15.2.7", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.7.tgz", + "integrity": "sha512-+FdVbbCZ+yoh7E/RosSdqKJyUM2OEjTciH0TFNkawKgvFp1zbGlEC39RADg+xKBG1R4mhoH2j85myBQZ5wR+lw==", + "dev": true, + "dependencies": { + "chalk": "~5.3.0", + "commander": "~12.1.0", + "debug": "~4.3.4", + "execa": "~8.0.1", + "lilconfig": "~3.1.1", + "listr2": "~8.2.1", + "micromatch": "~4.0.7", + "pidtree": "~0.6.0", + "string-argv": "~0.3.2", + "yaml": "~2.4.2" }, "bin": { "lint-staged": "bin/lint-staged.js" @@ -15768,12 +16215,12 @@ } }, "node_modules/lint-staged/node_modules/commander": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", - "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", "dev": true, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/lint-staged/node_modules/execa": { @@ -15833,12 +16280,15 @@ } }, "node_modules/lint-staged/node_modules/lilconfig": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", - "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", "dev": true, "engines": { "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" } }, "node_modules/lint-staged/node_modules/mimic-fn": { @@ -15920,10 +16370,13 @@ } }, "node_modules/lint-staged/node_modules/yaml": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", - "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", + "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", "dev": true, + "bin": { + "yaml": "bin.mjs" + }, "engines": { "node": ">= 14" } @@ -15984,16 +16437,16 @@ } }, "node_modules/listr2": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.0.1.tgz", - "integrity": "sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.1.tgz", + "integrity": "sha512-irTfvpib/rNiD637xeevjO2l3Z5loZmuaRi0L0YE5LfijwVY96oyVn0DFD3o/teAok7nfobMG1THvvcHh/BP6g==", "dev": true, "dependencies": { "cli-truncate": "^4.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", "log-update": "^6.0.0", - "rfdc": "^1.3.0", + "rfdc": "^1.3.1", "wrap-ansi": "^9.0.0" }, "engines": { @@ -16225,13 +16678,10 @@ } }, "node_modules/log-update/node_modules/ansi-escapes": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz", - "integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", + "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", "dev": true, - "dependencies": { - "type-fest": "^3.0.0" - }, "engines": { "node": ">=14.16" }, @@ -16332,18 +16782,6 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/log-update/node_modules/type-fest": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", - "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/log-update/node_modules/wrap-ansi": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", @@ -16463,6 +16901,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "peer": true, + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/markdown-it/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "peer": true + }, "node_modules/markdown-link": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/markdown-link/-/markdown-link-0.1.1.tgz", @@ -16496,18 +16957,6 @@ "node": ">=0.10.0" } }, - "node_modules/marked": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", - "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", - "peer": true, - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 12" - } - }, "node_modules/math-random": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", @@ -16518,6 +16967,12 @@ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==" }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "peer": true + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -16537,6 +16992,11 @@ "node": ">= 4.0.0" } }, + "node_modules/memoize-one": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", + "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==" + }, "node_modules/meow": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", @@ -16610,11 +17070,11 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -16979,9 +17439,9 @@ } }, "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -19367,9 +19827,9 @@ } }, "node_modules/prettier": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", - "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", + "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", "bin": { "prettier": "bin/prettier.cjs" }, @@ -19595,6 +20055,15 @@ "node": ">=6" } }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "peer": true, + "engines": { + "node": ">=6" + } + }, "node_modules/pupa": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", @@ -19672,6 +20141,11 @@ "performance-now": "^2.1.0" } }, + "node_modules/raf-schd": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz", + "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==" + }, "node_modules/randomatic": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", @@ -19828,6 +20302,24 @@ "react": ">=16.4.1" } }, + "node_modules/react-beautiful-dnd": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.1.tgz", + "integrity": "sha512-0Lvs4tq2VcrEjEgDXHjT98r+63drkKEgqyxdA7qD3mvKwga6a5SscbdLPO2IExotU1jW8L0Ksdl0Cj2AF67nPQ==", + "dependencies": { + "@babel/runtime": "^7.9.2", + "css-box-model": "^1.2.0", + "memoize-one": "^5.1.1", + "raf-schd": "^4.0.2", + "react-redux": "^7.2.0", + "redux": "^4.0.4", + "use-memo-one": "^1.1.1" + }, + "peerDependencies": { + "react": "^16.8.5 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.5 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-bootstrap": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.8.0.tgz", @@ -19858,22 +20350,38 @@ } }, "node_modules/react-datepicker": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.16.0.tgz", - "integrity": "sha512-hNQ0PAg/LQoVbDUO/RWAdm/RYmPhN3cz7LuQ3hqbs24OSp69QCiKOJRrQ4jk1gv1jNR5oYu8SjjgfDh8q6Q1yw==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-7.3.0.tgz", + "integrity": "sha512-EqRKLAtLZUTztiq6a+tjSjQX9ES0Xd229JPckAtyZZ4GoY3rtvNWAzkYZnQUf6zTWT50Ki0+t+W9VRQIkSJLfg==", "dependencies": { - "@popperjs/core": "^2.11.8", - "classnames": "^2.2.6", - "date-fns": "^2.30.0", + "@floating-ui/react": "^0.26.2", + "clsx": "^2.1.0", + "date-fns": "^3.3.1", "prop-types": "^15.7.2", - "react-onclickoutside": "^6.12.2", - "react-popper": "^2.3.0" + "react-onclickoutside": "^6.13.0" }, "peerDependencies": { "react": "^16.9.0 || ^17 || ^18", "react-dom": "^16.9.0 || ^17 || ^18" } }, + "node_modules/react-datepicker/node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/react-datepicker/node_modules/date-fns": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, "node_modules/react-dev-utils": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", @@ -20001,15 +20509,16 @@ "node_modules/react-fast-compare": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", - "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==", + "dev": true }, "node_modules/react-google-recaptcha": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/react-google-recaptcha/-/react-google-recaptcha-2.1.0.tgz", - "integrity": "sha512-K9jr7e0CWFigi8KxC3WPvNqZZ47df2RrMAta6KmRoE4RUi7Ys6NmNjytpXpg4HI/svmQJLKR+PncEPaNJ98DqQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/react-google-recaptcha/-/react-google-recaptcha-3.1.0.tgz", + "integrity": "sha512-cYW2/DWas8nEKZGD7SCu9BSuVz8iOcOLHChHyi7upUuVhkpkhYG/6N3KDiTQ3XAiZ2UAZkfvYKMfAHOzBOcGEg==", "dependencies": { "prop-types": "^15.5.0", - "react-async-script": "^1.1.1" + "react-async-script": "^1.2.0" }, "peerDependencies": { "react": ">=16.4.1" @@ -20056,15 +20565,23 @@ } }, "node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" }, "node_modules/react-lifecycles-compat": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" }, + "node_modules/react-multi-carousel": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/react-multi-carousel/-/react-multi-carousel-2.8.5.tgz", + "integrity": "sha512-C5DAvJkfzR2JK9YixZ3oyF9x6R4LW6nzTpIXrl9Oujxi4uqP9SzVVCjl+JLM3tSdqdjAx/oWZK3dTVBSR73Q+w==", + "engines": { + "node": ">=8" + } + }, "node_modules/react-onclickoutside": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.13.0.tgz", @@ -20082,6 +20599,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz", "integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==", + "dev": true, "dependencies": { "react-fast-compare": "^3.0.1", "warning": "^4.0.2" @@ -20130,11 +20648,11 @@ } }, "node_modules/react-router": { - "version": "6.22.2", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.2.tgz", - "integrity": "sha512-YD3Dzprzpcq+tBMHBS822tCjnWD3iIZbTeSXMY9LPSG541EfoBGyZ3bS25KEnaZjLcmQpw2AVLkFyfgXY8uvcw==", + "version": "6.25.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.25.1.tgz", + "integrity": "sha512-u8ELFr5Z6g02nUtpPAggP73Jigj1mRePSwhS/2nkTrlPU5yEkH1vYzWNyvSnSzeeE2DNqWdH+P8OhIh9wuXhTw==", "dependencies": { - "@remix-run/router": "1.15.2" + "@remix-run/router": "1.18.0" }, "engines": { "node": ">=14.0.0" @@ -20144,12 +20662,12 @@ } }, "node_modules/react-router-dom": { - "version": "6.22.2", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.2.tgz", - "integrity": "sha512-WgqxD2qySEIBPZ3w0sHH+PUAiamDeszls9tzqMPBDA1YYVucTBXLU7+gtRfcSnhe92A3glPnvSxK2dhNoAVOIQ==", + "version": "6.25.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.25.1.tgz", + "integrity": "sha512-0tUDpbFvk35iv+N89dWNrJp+afLgd+y4VtorJZuOCXK0kkCWjEvb3vTJM++SYvMEpbVwXKf3FjeVveVEb6JpDQ==", "dependencies": { - "@remix-run/router": "1.15.2", - "react-router": "6.22.2" + "@remix-run/router": "1.18.0", + "react-router": "6.25.1" }, "engines": { "node": ">=14.0.0" @@ -20319,6 +20837,19 @@ "react-dom": ">=16" } }, + "node_modules/react-tooltip": { + "version": "5.27.1", + "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.27.1.tgz", + "integrity": "sha512-a+micPXcMOMt11CYlwJD4XShcqGziasHco4NPe1OFw298WBTILMyzUgNC1LAFViAe791JdHNVSJIpzhZm2MvDA==", + "dependencies": { + "@floating-ui/dom": "^1.6.1", + "classnames": "^2.3.0" + }, + "peerDependencies": { + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + } + }, "node_modules/react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", @@ -21299,9 +21830,9 @@ "integrity": "sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA==" }, "node_modules/sass": { - "version": "1.71.1", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.71.1.tgz", - "integrity": "sha512-wovtnV2PxzteLlfNzbgm1tFXPLoZILYAMJtvoXXkD7/+1uP41eKkIt1ypWq5/q2uT94qHjXehEYfmjKOvjL9sg==", + "version": "1.77.4", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.4.tgz", + "integrity": "sha512-vcF3Ckow6g939GMA4PeU7b2K/9FALXk2KF9J87txdHzXbUF9XRQRwSxcAs/fGaTnJeBFd7UoV22j3lzMLdM0Pw==", "devOptional": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0", @@ -21798,15 +22329,13 @@ } }, "node_modules/shiki": { - "version": "0.14.7", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.7.tgz", - "integrity": "sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg==", + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.10.3.tgz", + "integrity": "sha512-eneCLncGuvPdTutJuLyUGS8QNPAVFO5Trvld2wgEq1e002mwctAhJKeMGWtWVXOIEzmlcLRqcgPSorR6AVzOmQ==", "peer": true, "dependencies": { - "ansi-sequence-parser": "^1.1.0", - "jsonc-parser": "^3.2.0", - "vscode-oniguruma": "^1.7.0", - "vscode-textmate": "^8.0.0" + "@shikijs/core": "1.10.3", + "@types/hast": "^3.0.4" } }, "node_modules/side-channel": { @@ -22647,6 +23176,11 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/tabbable": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==" + }, "node_modules/tailwindcss": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz", @@ -22965,6 +23499,11 @@ "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==" }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" + }, "node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -23198,18 +23737,20 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/tsx": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-3.14.0.tgz", - "integrity": "sha512-xHtFaKtHxM9LOklMmJdI3BEnQq/D5F73Of2E1GDrITi9sgoVkvIsrQUTY1G8FlmGtA+awCI4EBlTRRYxkL2sRg==", + "version": "4.16.2", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.16.2.tgz", + "integrity": "sha512-C1uWweJDgdtX2x600HjaFaucXTilT7tgUZHbOE4+ypskZ1OP8CRCSDkCxG6Vya9EwaFIVagWwpaVAn5wzypaqQ==", "dev": true, "dependencies": { - "esbuild": "~0.18.20", - "get-tsconfig": "^4.7.2", - "source-map-support": "^0.5.21" + "esbuild": "~0.21.5", + "get-tsconfig": "^4.7.5" }, "bin": { "tsx": "dist/cli.mjs" }, + "engines": { + "node": ">=18.0.0" + }, "optionalDependencies": { "fsevents": "~2.3.3" } @@ -23359,32 +23900,36 @@ } }, "node_modules/typedoc": { - "version": "0.25.7", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.7.tgz", - "integrity": "sha512-m6A6JjQRg39p2ZVRIN3NKXgrN8vzlHhOS+r9ymUYtcUP/TIQPvWSq7YgE5ZjASfv5Vd5BW5xrir6Gm2XNNcOow==", + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.3.tgz", + "integrity": "sha512-6d2Sw9disvvpdk4K7VNjKr5/3hzijtfQVHRthhDqJgnhMHy1wQz4yPMJVKXElvnZhFr0nkzo+GzjXDTRV5yLpg==", "peer": true, "dependencies": { "lunr": "^2.3.9", - "marked": "^4.3.0", - "minimatch": "^9.0.3", - "shiki": "^0.14.7" + "markdown-it": "^14.1.0", + "minimatch": "^9.0.5", + "shiki": "^1.9.1", + "yaml": "^2.4.5" }, "bin": { "typedoc": "bin/typedoc" }, "engines": { - "node": ">= 16" + "node": ">= 18" }, "peerDependencies": { - "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x" + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x" } }, "node_modules/typedoc-plugin-markdown": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.0.2.tgz", - "integrity": "sha512-4MV3M+0lsmIaXuDBzeqLYemZqwTQDWQow+o8zdT9hC7KFu06GaFo2uUEbkjE6pgZA9hnkOTtzRVd0R9YJWcH8A==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.2.1.tgz", + "integrity": "sha512-7hQt/1WaW/VI4+x3sxwcCGsEylP1E1GvF6OTTELK5sfTEp6AeK+83jkCOgZGp1pI2DiOammMYQMnxxOny9TKsQ==", + "engines": { + "node": ">= 18" + }, "peerDependencies": { - "typedoc": "0.25.x" + "typedoc": "0.26.x" } }, "node_modules/typedoc/node_modules/brace-expansion": { @@ -23397,9 +23942,9 @@ } }, "node_modules/typedoc/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "peer": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -23411,6 +23956,18 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/typedoc/node_modules/yaml": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", + "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", + "peer": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/typescript": { "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", @@ -23423,6 +23980,12 @@ "node": ">=4.2.0" } }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "peer": true + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -23658,6 +24221,14 @@ "node": ">=4" } }, + "node_modules/use-memo-one": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz", + "integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -23768,18 +24339,6 @@ "node": ">=0.10.0" } }, - "node_modules/vscode-oniguruma": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", - "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", - "peer": true - }, - "node_modules/vscode-textmate": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", - "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", - "peer": true - }, "node_modules/w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", @@ -23845,9 +24404,9 @@ } }, "node_modules/web-vitals": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-1.1.2.tgz", - "integrity": "sha512-PFMKIY+bRSXlMxVAQ+m2aw9c/ioUYfDgrYot0YUa+/xa0sakubWhSDyxAKwzymvXVdF4CZI71g06W+mqhzu6ig==" + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.2.tgz", + "integrity": "sha512-nYfoOqb4EmElljyXU2qdeE76KsvoHdftQKY4DzA9Aw8DervCg2bG634pHLrJ/d6+B4mE3nWTSJv8Mo7B2mbZkw==" }, "node_modules/webidl-conversions": { "version": "6.1.0", @@ -24674,5 +25233,17982 @@ "url": "https://github.com/sponsors/colinhacks" } } + }, + "dependencies": { + "@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==" + }, + "@adobe/css-tools": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.3.tgz", + "integrity": "sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==", + "dev": true + }, + "@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==" + }, + "@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@apideck/better-ajv-errors": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.6.tgz", + "integrity": "sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==", + "requires": { + "json-schema": "^0.4.0", + "jsonpointer": "^5.0.0", + "leven": "^3.1.0" + } + }, + "@apollo/client": { + "version": "3.7.17", + "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.7.17.tgz", + "integrity": "sha512-0EErSHEtKPNl5wgWikHJbKFAzJ/k11O0WO2QyqZSHpdxdAnw7UWHY4YiLbHCFG7lhrD+NTQ3Z/H9Jn4rcikoJA==", + "requires": { + "@graphql-typed-document-node/core": "^3.1.1", + "@wry/context": "^0.7.0", + "@wry/equality": "^0.5.0", + "@wry/trie": "^0.4.0", + "graphql-tag": "^2.12.6", + "hoist-non-react-statics": "^3.3.2", + "optimism": "^0.16.2", + "prop-types": "^15.7.2", + "response-iterator": "^0.2.6", + "symbol-observable": "^4.0.0", + "ts-invariant": "^0.10.3", + "tslib": "^2.3.0", + "zen-observable-ts": "^1.2.5" + } + }, + "@apollo/link-error": { + "version": "2.0.0-beta.3", + "resolved": "https://registry.npmjs.org/@apollo/link-error/-/link-error-2.0.0-beta.3.tgz", + "integrity": "sha512-blNBBi9+4SEfb4Bhn8cYqGFhb0C7MjqLiRwNdUqwGefl1w+G8Ze8pCLHAyPxXLcslirtht9LY0i6ZOpCzSXHCg==", + "requires": { + "@apollo/client": "^3.0.0-beta.23", + "tslib": "^1.9.3" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + }, + "@apollo/react-testing": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@apollo/react-testing/-/react-testing-4.0.0.tgz", + "integrity": "sha512-P7Z/flUHpRRZYc3FkIqxZH9XD3FuP2Sgks1IXqGq2Zb7qI0aaTfVeRsLYmZNUcFOh2pTHxs0NXgPnH1VfYOpig==", + "requires": { + "@apollo/client": "latest" + } + }, + "@babel/code-frame": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "requires": { + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/compat-data": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==" + }, + "@babel/core": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.9.tgz", + "integrity": "sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==", + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.5", + "@babel/generator": "^7.22.9", + "@babel/helper-compilation-targets": "^7.22.9", + "@babel/helper-module-transforms": "^7.22.9", + "@babel/helpers": "^7.22.6", + "@babel/parser": "^7.22.7", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.8", + "@babel/types": "^7.22.5", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.2", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "@babel/eslint-parser": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.22.9.tgz", + "integrity": "sha512-xdMkt39/nviO/4vpVdrEYPwXCsYIXSSAr6mC7WQsNIlGnuxKyKE7GZjalcnbSWiC4OXGNNN3UQPeHfjSC6sTDA==", + "requires": { + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.1" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==" + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "@babel/generator": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "requires": { + "@babel/types": "^7.23.6", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", + "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", + "requires": { + "@babel/types": "^7.22.15" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "requires": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.23.10", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.10.tgz", + "integrity": "sha512-2XpP2XhkXzgxecPNEEK8Vz8Asj9aRxt08oKOqtiZoqV2UGZ5T+EkyP9sXQ9nwMxBIG34a7jmasVqoMop7VdPUw==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-member-expression-to-functions": "^7.23.0", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", + "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "@babel/helper-define-polyfill-provider": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.1.tgz", + "integrity": "sha512-kX4oXixDxG197yhX+J3Wp+NpL2wuCFjWQAr6yX2jtCnflK9ulMI51ULFGIrWiX1jGfvAxdHp+XQCcP2bZGPs9A==", + "requires": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + } + }, + "@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==" + }, + "@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "requires": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", + "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "requires": { + "@babel/types": "^7.23.0" + } + }, + "@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "requires": { + "@babel/types": "^7.22.15" + } + }, + "@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==" + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", + "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-wrap-function": "^7.22.20" + } + }, + "@babel/helper-replace-supers": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", + "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-optimise-call-expression": "^7.22.5" + } + }, + "@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-string-parser": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==" + }, + "@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==" + }, + "@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==" + }, + "@babel/helper-wrap-function": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", + "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", + "requires": { + "@babel/helper-function-name": "^7.22.5", + "@babel/template": "^7.22.15", + "@babel/types": "^7.22.19" + } + }, + "@babel/helpers": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz", + "integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==", + "requires": { + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.6", + "@babel/types": "^7.22.5" + } + }, + "@babel/highlight": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "requires": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/parser": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.0.tgz", + "integrity": "sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==" + }, + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz", + "integrity": "sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz", + "integrity": "sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.23.3" + } + }, + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz", + "integrity": "sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw==", + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-proposal-decorators": { + "version": "7.22.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.22.7.tgz", + "integrity": "sha512-omXqPF7Onq4Bb7wHxXjM3jSMSJvUUbvDvmmds7KI5n9Cq6Ln5I05I1W2nRlRof1rGdiUxJrxwe285WF96XlBXQ==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/plugin-syntax-decorators": "^7.22.5" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", + "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", + "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", + "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", + "requires": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + } + }, + "@babel/plugin-proposal-private-methods": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", + "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz", + "integrity": "sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.21.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-decorators": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.22.5.tgz", + "integrity": "sha512-avpUOBS7IU6al8MmF1XpAyj9QYeLPuSDJI5D4pVMSMdL7xQokKqJPYQC67RCT0aCTashUXPiGwMJ0DEXXCEmMA==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-flow": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.22.5.tgz", + "integrity": "sha512-9RdCl0i+q0QExayk2nOS7853w08yLucnnPML6EN9S8fgMPVtdLDCdx/cOQ/i44Lb9UeQX9A35yaqBBOMMZxPxQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-import-assertions": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz", + "integrity": "sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-import-attributes": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz", + "integrity": "sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", + "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", + "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz", + "integrity": "sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-async-generator-functions": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.9.tgz", + "integrity": "sha512-8Q3veQEDGe14dTYuwagbRtwxQDnytyg1JFu4/HwEMETeofocrB0U0ejBJIXoeG/t2oXZ8kzCyI0ZZfbT80VFNQ==", + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.20", + "@babel/plugin-syntax-async-generators": "^7.8.4" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz", + "integrity": "sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==", + "requires": { + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.20" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz", + "integrity": "sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz", + "integrity": "sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-class-properties": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz", + "integrity": "sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-class-static-block": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz", + "integrity": "sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.8.tgz", + "integrity": "sha512-yAYslGsY1bX6Knmg46RjiCiNSwJKv2IUC8qOdYKqMMr0491SXFhcHqOdRDeCRohOOIzwN/90C6mQ9qAKgrP7dg==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20", + "@babel/helper-split-export-declaration": "^7.22.6", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz", + "integrity": "sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/template": "^7.22.15" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz", + "integrity": "sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz", + "integrity": "sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz", + "integrity": "sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-dynamic-import": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz", + "integrity": "sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz", + "integrity": "sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==", + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-export-namespace-from": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz", + "integrity": "sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, + "@babel/plugin-transform-flow-strip-types": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.22.5.tgz", + "integrity": "sha512-tujNbZdxdG0/54g/oua8ISToaXTFBf8EnSb5PgQSciIXWOWKX3S4+JR7ZE9ol8FZwf9kxitzkGQ+QWeov/mCiA==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-flow": "^7.22.5" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz", + "integrity": "sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz", + "integrity": "sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==", + "requires": { + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-json-strings": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz", + "integrity": "sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-json-strings": "^7.8.3" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz", + "integrity": "sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-logical-assignment-operators": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz", + "integrity": "sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz", + "integrity": "sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz", + "integrity": "sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==", + "requires": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", + "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", + "requires": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.9.tgz", + "integrity": "sha512-KDlPRM6sLo4o1FkiSlXoAa8edLXFsKKIda779fbLrvmeuc3itnjCtaO6RrtoaANsIJANj+Vk1zqbZIMhkCAHVw==", + "requires": { + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz", + "integrity": "sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==", + "requires": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", + "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz", + "integrity": "sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz", + "integrity": "sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + } + }, + "@babel/plugin-transform-numeric-separator": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz", + "integrity": "sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-transform-object-rest-spread": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.4.tgz", + "integrity": "sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g==", + "requires": { + "@babel/compat-data": "^7.23.3", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.23.3" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz", + "integrity": "sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20" + } + }, + "@babel/plugin-transform-optional-catch-binding": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz", + "integrity": "sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + } + }, + "@babel/plugin-transform-optional-chaining": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz", + "integrity": "sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz", + "integrity": "sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-private-methods": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz", + "integrity": "sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-private-property-in-object": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz", + "integrity": "sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz", + "integrity": "sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-react-constant-elements": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.22.5.tgz", + "integrity": "sha512-BF5SXoO+nX3h5OhlN78XbbDrBOffv+AxPP2ENaJOVqjWCgBDeOY3WcaUcddutGSfoap+5NEQ/q/4I3WZIvgkXA==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-react-display-name": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.22.5.tgz", + "integrity": "sha512-PVk3WPYudRF5z4GKMEYUrLjPl38fJSKNaEOkFuoprioowGuWN6w2RKznuFNSlJx7pzzXXStPUnNSOEO0jL5EVw==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-react-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.5.tgz", + "integrity": "sha512-rog5gZaVbUip5iWDMTYbVM15XQq+RkUKhET/IHR6oizR+JEoN6CAfTTuHcK4vwUyzca30qqHqEpzBOnaRMWYMA==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-jsx": "^7.22.5", + "@babel/types": "^7.22.5" + } + }, + "@babel/plugin-transform-react-jsx-development": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz", + "integrity": "sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==", + "requires": { + "@babel/plugin-transform-react-jsx": "^7.22.5" + } + }, + "@babel/plugin-transform-react-pure-annotations": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.22.5.tgz", + "integrity": "sha512-gP4k85wx09q+brArVinTXhWiyzLl9UpmGva0+mWyKxk6JZequ05x3eUcIUE+FyttPKJFRRVtAvQaJ6YF9h1ZpA==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz", + "integrity": "sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "regenerator-transform": "^0.15.2" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz", + "integrity": "sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-runtime": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.22.9.tgz", + "integrity": "sha512-9KjBH61AGJetCPYp/IEyLEp47SyybZb0nDRpBvmtEkm+rUIwxdlKpyNHI1TmsGkeuLclJdleQHRZ8XLBnnh8CQ==", + "requires": { + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "babel-plugin-polyfill-corejs2": "^0.4.4", + "babel-plugin-polyfill-corejs3": "^0.8.2", + "babel-plugin-polyfill-regenerator": "^0.5.1", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz", + "integrity": "sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz", + "integrity": "sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz", + "integrity": "sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz", + "integrity": "sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz", + "integrity": "sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-typescript": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.23.6.tgz", + "integrity": "sha512-6cBG5mBvUu4VUD04OHKnYzbuHNP8huDsD3EDqqpIpsswTDoqHCjLoHb6+QgsV1WsT2nipRqCPgxD3LXnEO7XfA==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.23.6", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-typescript": "^7.23.3" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz", + "integrity": "sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-unicode-property-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz", + "integrity": "sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz", + "integrity": "sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-unicode-sets-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz", + "integrity": "sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/preset-env": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.9.tgz", + "integrity": "sha512-3kBGTNBBk9DQiPoXYS0g0BYlwTQYUTifqgKTjxUwEUkduRT2QOa0FPGBJ+NROQhGyYO5BuTJwGvBnqKDykac6A==", + "requires": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.23.5", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.23.3", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.23.3", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.23.7", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.23.3", + "@babel/plugin-syntax-import-attributes": "^7.23.3", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.23.3", + "@babel/plugin-transform-async-generator-functions": "^7.23.9", + "@babel/plugin-transform-async-to-generator": "^7.23.3", + "@babel/plugin-transform-block-scoped-functions": "^7.23.3", + "@babel/plugin-transform-block-scoping": "^7.23.4", + "@babel/plugin-transform-class-properties": "^7.23.3", + "@babel/plugin-transform-class-static-block": "^7.23.4", + "@babel/plugin-transform-classes": "^7.23.8", + "@babel/plugin-transform-computed-properties": "^7.23.3", + "@babel/plugin-transform-destructuring": "^7.23.3", + "@babel/plugin-transform-dotall-regex": "^7.23.3", + "@babel/plugin-transform-duplicate-keys": "^7.23.3", + "@babel/plugin-transform-dynamic-import": "^7.23.4", + "@babel/plugin-transform-exponentiation-operator": "^7.23.3", + "@babel/plugin-transform-export-namespace-from": "^7.23.4", + "@babel/plugin-transform-for-of": "^7.23.6", + "@babel/plugin-transform-function-name": "^7.23.3", + "@babel/plugin-transform-json-strings": "^7.23.4", + "@babel/plugin-transform-literals": "^7.23.3", + "@babel/plugin-transform-logical-assignment-operators": "^7.23.4", + "@babel/plugin-transform-member-expression-literals": "^7.23.3", + "@babel/plugin-transform-modules-amd": "^7.23.3", + "@babel/plugin-transform-modules-commonjs": "^7.23.3", + "@babel/plugin-transform-modules-systemjs": "^7.23.9", + "@babel/plugin-transform-modules-umd": "^7.23.3", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", + "@babel/plugin-transform-new-target": "^7.23.3", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.23.4", + "@babel/plugin-transform-numeric-separator": "^7.23.4", + "@babel/plugin-transform-object-rest-spread": "^7.23.4", + "@babel/plugin-transform-object-super": "^7.23.3", + "@babel/plugin-transform-optional-catch-binding": "^7.23.4", + "@babel/plugin-transform-optional-chaining": "^7.23.4", + "@babel/plugin-transform-parameters": "^7.23.3", + "@babel/plugin-transform-private-methods": "^7.23.3", + "@babel/plugin-transform-private-property-in-object": "^7.23.4", + "@babel/plugin-transform-property-literals": "^7.23.3", + "@babel/plugin-transform-regenerator": "^7.23.3", + "@babel/plugin-transform-reserved-words": "^7.23.3", + "@babel/plugin-transform-shorthand-properties": "^7.23.3", + "@babel/plugin-transform-spread": "^7.23.3", + "@babel/plugin-transform-sticky-regex": "^7.23.3", + "@babel/plugin-transform-template-literals": "^7.23.3", + "@babel/plugin-transform-typeof-symbol": "^7.23.3", + "@babel/plugin-transform-unicode-escapes": "^7.23.3", + "@babel/plugin-transform-unicode-property-regex": "^7.23.3", + "@babel/plugin-transform-unicode-regex": "^7.23.3", + "@babel/plugin-transform-unicode-sets-regex": "^7.23.3", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.8", + "babel-plugin-polyfill-corejs3": "^0.9.0", + "babel-plugin-polyfill-regenerator": "^0.5.5", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" + }, + "dependencies": { + "@babel/helper-define-polyfill-provider": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", + "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", + "requires": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + } + }, + "@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "requires": {} + }, + "babel-plugin-polyfill-corejs3": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.9.0.tgz", + "integrity": "sha512-7nZPG1uzK2Ymhy/NbaOWTg3uibM2BmGASS4vHS4szRZAIR8R6GwA/xAujpdrXU5iyklrimWnLWU+BLF9suPTqg==", + "requires": { + "@babel/helper-define-polyfill-provider": "^0.5.0", + "core-js-compat": "^3.34.0" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, + "@babel/preset-react": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.22.5.tgz", + "integrity": "sha512-M+Is3WikOpEJHgR385HbuCITPTaPRaNkibTEa9oiofmJvIsrceb4yp9RL9Kb+TE8LznmeyZqpP+Lopwcx59xPQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.5", + "@babel/plugin-transform-react-display-name": "^7.22.5", + "@babel/plugin-transform-react-jsx": "^7.22.5", + "@babel/plugin-transform-react-jsx-development": "^7.22.5", + "@babel/plugin-transform-react-pure-annotations": "^7.22.5" + } + }, + "@babel/preset-typescript": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.23.3.tgz", + "integrity": "sha512-17oIGVlqz6CchO9RFYn5U6ZpWRZIngayYCtrPRSgANSwC2V1Jb+iP74nVxzzXJte8b8BYxrL1yY96xfhTBrNNQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.15", + "@babel/plugin-syntax-jsx": "^7.23.3", + "@babel/plugin-transform-modules-commonjs": "^7.23.3", + "@babel/plugin-transform-typescript": "^7.23.3" + } + }, + "@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" + }, + "@babel/runtime": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.8.tgz", + "integrity": "sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==", + "requires": { + "regenerator-runtime": "^0.14.0" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + } + } + }, + "@babel/runtime-corejs3": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.22.6.tgz", + "integrity": "sha512-M+37LLIRBTEVjktoJjbw4KVhupF0U/3PYUCbBwgAd9k17hoKhRu1n935QiG7Tuxv0LJOMrb2vuKEeYUlv0iyiw==", + "dev": true, + "requires": { + "core-js-pure": "^3.30.2", + "regenerator-runtime": "^0.13.11" + } + }, + "@babel/template": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", + "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", + "requires": { + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9" + } + }, + "@babel/traverse": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.0.tgz", + "integrity": "sha512-HfuJlI8qq3dEDmNU5ChzzpZRWq+oxCZQyMzIMEqLho+AQnhMnKQUzH6ydo3RBl/YjPCuk68Y6s0Gx0AeyULiWw==", + "requires": { + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0", + "debug": "^4.3.1", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "requires": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + } + }, + "@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" + }, + "@csstools/normalize.css": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-12.0.0.tgz", + "integrity": "sha512-M0qqxAcwCsIVfpFQSlGN5XjXWu8l5JDZN+fPt1LeW5SZexQTgnaEvgXAY+CeygRw0EeppWHi12JxESWiWrB0Sg==" + }, + "@csstools/postcss-cascade-layers": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-1.1.1.tgz", + "integrity": "sha512-+KdYrpKC5TgomQr2DlZF4lDEpHcoxnj5IGddYYfBWJAKfj1JtuHUIqMa+E1pJJ+z3kvDViWMqyqPlG4Ja7amQA==", + "requires": { + "@csstools/selector-specificity": "^2.0.2", + "postcss-selector-parser": "^6.0.10" + } + }, + "@csstools/postcss-color-function": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-1.1.1.tgz", + "integrity": "sha512-Bc0f62WmHdtRDjf5f3e2STwRAl89N2CLb+9iAwzrv4L2hncrbDwnQD9PCq0gtAt7pOI2leIV08HIBUd4jxD8cw==", + "requires": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-font-format-keywords": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-1.0.1.tgz", + "integrity": "sha512-ZgrlzuUAjXIOc2JueK0X5sZDjCtgimVp/O5CEqTcs5ShWBa6smhWYbS0x5cVc/+rycTDbjjzoP0KTDnUneZGOg==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-hwb-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-1.0.2.tgz", + "integrity": "sha512-YHdEru4o3Rsbjmu6vHy4UKOXZD+Rn2zmkAmLRfPet6+Jz4Ojw8cbWxe1n42VaXQhD3CQUXXTooIy8OkVbUcL+w==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-ic-unit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-1.0.1.tgz", + "integrity": "sha512-Ot1rcwRAaRHNKC9tAqoqNZhjdYBzKk1POgWfhN4uCOE47ebGcLRqXjKkApVDpjifL6u2/55ekkpnFcp+s/OZUw==", + "requires": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-is-pseudo-class": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-2.0.7.tgz", + "integrity": "sha512-7JPeVVZHd+jxYdULl87lvjgvWldYu+Bc62s9vD/ED6/QTGjy0jy0US/f6BG53sVMTBJ1lzKZFpYmofBN9eaRiA==", + "requires": { + "@csstools/selector-specificity": "^2.0.0", + "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", + "integrity": "sha512-jcOanIbv55OFKQ3sYeFD/T0Ti7AMXc9nM1hZWu8m/2722gOTxFg7xYu4RDLJLeZmPUVQlGzo4jhzvTUq3x4ZUw==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-oklab-function": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-1.1.1.tgz", + "integrity": "sha512-nJpJgsdA3dA9y5pgyb/UfEzE7W5Ka7u0CX0/HIMVBNWzWemdcTH3XwANECU6anWv/ao4vVNLTMxhiPNZsTK6iA==", + "requires": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-progressive-custom-properties": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-1.3.0.tgz", + "integrity": "sha512-ASA9W1aIy5ygskZYuWams4BzafD12ULvSypmaLJT2jvQ8G0M3I8PRQhC0h7mG0Z3LI05+agZjqSR9+K9yaQQjA==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-stepped-value-functions": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-1.0.1.tgz", + "integrity": "sha512-dz0LNoo3ijpTOQqEJLY8nyaapl6umbmDcgj4AD0lgVQ572b2eqA1iGZYTTWhrcrHztWDDRAX2DGYyw2VBjvCvQ==", + "requires": { + "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", + "integrity": "sha512-woKaLO///4bb+zZC2s80l+7cm07M7268MsyG3M0ActXXEFi6SuhvriQYcb58iiKGbjwwIU7n45iRLEHypB47Og==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-unset-value": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-1.0.2.tgz", + "integrity": "sha512-c8J4roPBILnelAsdLr4XOAR/GsTm0GJi4XpcfvoWk3U6KiTCqiFYc63KhRMQQX35jYMp4Ao8Ij9+IZRgMfJp1g==", + "requires": {} + }, + "@csstools/selector-specificity": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz", + "integrity": "sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==", + "requires": {} + }, + "@dicebear/adventurer": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/adventurer/-/adventurer-8.0.1.tgz", + "integrity": "sha512-dlEycOH+yETbNo3EtswFJCnG02OEgpyPpOFmSgUuRhcRKsqbMlcsiYV4wKeRvq6VvudJXp8UiHwWszLjCHTvKA==", + "requires": {} + }, + "@dicebear/adventurer-neutral": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/adventurer-neutral/-/adventurer-neutral-8.0.1.tgz", + "integrity": "sha512-NgSz01T/K6MJn93Lk8rKPGKTx6cJe4/lNKMKjRM+4mez8S56WNdGDGUn/QY5GL3P1p01QAOMFF3hygJk3WAr3g==", + "requires": {} + }, + "@dicebear/avataaars": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/avataaars/-/avataaars-8.0.1.tgz", + "integrity": "sha512-TYXqP9mq3yHOdLlJr8saXnvxj14eY2YAmoVVbT15Rp5+kPzGDyfblNsM838sP5K6JyCNeojZsGE/sPJKk/G+mA==", + "requires": {} + }, + "@dicebear/avataaars-neutral": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/avataaars-neutral/-/avataaars-neutral-8.0.1.tgz", + "integrity": "sha512-vMV1Htaqpnz+qAVyn2tJWbRQIa6mpO/bu7dD0dumuIb45+LIpNwdUuCvkIQw2qf5ODhn1WAfYX3HEJaxRZc4lA==", + "requires": {} + }, + "@dicebear/big-ears": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/big-ears/-/big-ears-8.0.1.tgz", + "integrity": "sha512-lnPRFbXsHv2EXJR2OLqJdoUIrSVUpf1z4GkCOfAi01sYNYVpfnzg3kNF77QUhkXUhaONF7d4Wz8rUduBHRtjaA==", + "requires": {} + }, + "@dicebear/big-ears-neutral": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/big-ears-neutral/-/big-ears-neutral-8.0.1.tgz", + "integrity": "sha512-2FPvNpLI/ald3P8iWhX7SR986B8/DQlvrTNK/v+V0HRJvG1t6/7f9qfUL7OLf6plL7EgSUmKfMKacdiR5skZkA==", + "requires": {} + }, + "@dicebear/big-smile": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/big-smile/-/big-smile-8.0.1.tgz", + "integrity": "sha512-uh7FP0RgX8Qtr5zpeKUSNq028IQ3srF5LHJfQGjf4wA8R+ln/Sq0gPRJk6qMCCvPFV42b7A6f7rO7mHGnQ+qDA==", + "requires": {} + }, + "@dicebear/bottts": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/bottts/-/bottts-8.0.1.tgz", + "integrity": "sha512-WmaGZnKAT90EP/pzfUox22RshCk3GLB/p+6SsjD0ZIBNjcMXhaJroSoGVcHmPgQVzZBDIdW9C0qDKhkCNVVizg==", + "requires": {} + }, + "@dicebear/bottts-neutral": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/bottts-neutral/-/bottts-neutral-8.0.1.tgz", + "integrity": "sha512-krbD3U+UvzlY+kfQDpg9Hql1xJmmu3y9ensiU+XZXiuNw/ZavgGqpJtzpbYeF3J5GsggQlbBh/ZAK9AIKz7S3Q==", + "requires": {} + }, + "@dicebear/collection": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/collection/-/collection-8.0.1.tgz", + "integrity": "sha512-RlWvOOXTxqP1llNzWhrnm6wCMKFAku/Ty0YJNv+4LYA1YIDpyLNN2PwxxCuj7hU244qUwQcVPQPPPr0XQ+rA/g==", + "requires": { + "@dicebear/adventurer": "8.0.1", + "@dicebear/adventurer-neutral": "8.0.1", + "@dicebear/avataaars": "8.0.1", + "@dicebear/avataaars-neutral": "8.0.1", + "@dicebear/big-ears": "8.0.1", + "@dicebear/big-ears-neutral": "8.0.1", + "@dicebear/big-smile": "8.0.1", + "@dicebear/bottts": "8.0.1", + "@dicebear/bottts-neutral": "8.0.1", + "@dicebear/croodles": "8.0.1", + "@dicebear/croodles-neutral": "8.0.1", + "@dicebear/fun-emoji": "8.0.1", + "@dicebear/icons": "8.0.1", + "@dicebear/identicon": "8.0.1", + "@dicebear/initials": "8.0.1", + "@dicebear/lorelei": "8.0.1", + "@dicebear/lorelei-neutral": "8.0.1", + "@dicebear/micah": "8.0.1", + "@dicebear/miniavs": "8.0.1", + "@dicebear/notionists": "8.0.1", + "@dicebear/notionists-neutral": "8.0.1", + "@dicebear/open-peeps": "8.0.1", + "@dicebear/personas": "8.0.1", + "@dicebear/pixel-art": "8.0.1", + "@dicebear/pixel-art-neutral": "8.0.1", + "@dicebear/rings": "8.0.1", + "@dicebear/shapes": "8.0.1", + "@dicebear/thumbs": "8.0.1" + } + }, + "@dicebear/converter": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/converter/-/converter-8.0.1.tgz", + "integrity": "sha512-65L04fN4V07WcUnwQuDYDH+zrP8WA6/UeIuqqH/Pv7VWoJtIk9qHlaA+XGpPr4qgRtkmY7uXVkrED/RMlqvUDA==", + "requires": { + "@types/json-schema": "^7.0.11", + "tmp-promise": "^3.0.3" + } + }, + "@dicebear/core": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/core/-/core-8.0.1.tgz", + "integrity": "sha512-HWqvQRpVjkboQXinCOjU3poZIMd5p+32wPvc9N5fYiXe3KQLhJNw5T5XiRttDUm3XpoTvhQ4DVTPDsXT8CqrTg==", + "requires": { + "@dicebear/converter": "8.0.1", + "@types/json-schema": "^7.0.11" + } + }, + "@dicebear/croodles": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/croodles/-/croodles-8.0.1.tgz", + "integrity": "sha512-4si6gm61hEI8uDk+7OhSX+0qSPfotYx1dbdBphgGgiP9KTOgipnXzNtz8YnGzNf+V89nV4twHa6Bl6Wna4kFYA==", + "requires": {} + }, + "@dicebear/croodles-neutral": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/croodles-neutral/-/croodles-neutral-8.0.1.tgz", + "integrity": "sha512-DlR1wxzacRc3GhkMRg4MJ4CBfci/Z96SUl3YpvhHQ4ZtPldaQmdxs3jzOlnG1cuNRkqmiB1D66EXj5146V5WMA==", + "requires": {} + }, + "@dicebear/fun-emoji": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/fun-emoji/-/fun-emoji-8.0.1.tgz", + "integrity": "sha512-s2zXyZ7Rp3E2OHxAghhKIYmTtQ64D1VU+/p0VNaIQTPnyfxgpdrKlBMAlp4fXHyirhtAWCHSWgXcU9UFvlmr+w==", + "requires": {} + }, + "@dicebear/icons": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/icons/-/icons-8.0.1.tgz", + "integrity": "sha512-uInO34VW1etgMsbarXIeYULTk+dlj0L9vW7nUinWqwwEbimgXT4iqzNSjQyogmQ3wmaahI1zNwrGUkfkQojouw==", + "requires": {} + }, + "@dicebear/identicon": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/identicon/-/identicon-8.0.1.tgz", + "integrity": "sha512-mIHBuUlTs1RNZg+9k4NIjYXYjZBh08ksK/7Pmb+5twsoIPuAPjZ+FbQsfc27Wga/IuJfgf9mYBq6Sxc8/LQxjg==", + "requires": {} + }, + "@dicebear/initials": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/initials/-/initials-8.0.1.tgz", + "integrity": "sha512-ctO1f92XAms72qkhiKI/vvS/E6mco1RiTEACPJGv6hDPfdjR1vxpkzFpo3jm3RohfwOPCN5fH2l3BSinnlbzzw==", + "requires": {} + }, + "@dicebear/lorelei": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/lorelei/-/lorelei-8.0.1.tgz", + "integrity": "sha512-AY9XDeV7pIojDziiT/9flPWvH/5dswlVvezHQljmLa1H6EIQAIRWj9INeDaS2u2hRTFQKVeYQ1kuP3Omb+t26A==", + "requires": {} + }, + "@dicebear/lorelei-neutral": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/lorelei-neutral/-/lorelei-neutral-8.0.1.tgz", + "integrity": "sha512-vC5M7jg6UByJyFjBitLB3xKr435FdH8BHD8oVzf9A2MXi/ovQ0bEak9MnxVcrxUufJx7bsgS/XCRYNLUwaQKyw==", + "requires": {} + }, + "@dicebear/micah": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/micah/-/micah-8.0.1.tgz", + "integrity": "sha512-B7+YCX62CqnjLlJNY6+NXy+HJlyGMzCbrnE38bGdmnH7PZ1IrEnmJny41AcopKziE02h65kdwCZFXy/v7piT4g==", + "requires": {} + }, + "@dicebear/miniavs": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/miniavs/-/miniavs-8.0.1.tgz", + "integrity": "sha512-mzNAa2cIvsyeRuSnWoQ6l23yiw4BhmzrwdmfJZuDLloh/UNJjyiiCItYSTBmhtxcJrWX8YQTd/2hPdXjsdceTA==", + "requires": {} + }, + "@dicebear/notionists": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/notionists/-/notionists-8.0.1.tgz", + "integrity": "sha512-wOZPSj7lKIJkxiJHysGUVehPmaisWV9dUNhs4jDApiit3u6cbspDEOXvlAn/68cpGP8LfjsdyCp8yhZ9Wvk15Q==", + "requires": {} + }, + "@dicebear/notionists-neutral": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/notionists-neutral/-/notionists-neutral-8.0.1.tgz", + "integrity": "sha512-j70iiLZPpLw9JfyziRC8jUaVnbz2NPTZFMd+O08ba3FcTsG0H5+bYimTWL+6fxZ/psN1S3NS/onVvgPkvBWTjg==", + "requires": {} + }, + "@dicebear/open-peeps": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/open-peeps/-/open-peeps-8.0.1.tgz", + "integrity": "sha512-NQbXmnPjyz3YZOAIEzQY6OFXg3sCIIDZgQZjl3qzTqsmUtZVMRnX8Sk53ig1SIM1kxIAyJ908wplwIYV16zxsw==", + "requires": {} + }, + "@dicebear/personas": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/personas/-/personas-8.0.1.tgz", + "integrity": "sha512-qxivUbnx4xvE1PvqCg6pBQadVDJVjXaXnxtIUxIRJyDeYIJUxkeBr2A5JOIiNLdypqXoYwhURy5r3NCmesaAWg==", + "requires": {} + }, + "@dicebear/pixel-art": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/pixel-art/-/pixel-art-8.0.1.tgz", + "integrity": "sha512-WMRKdxP8/PL2UGiLAP7CdgTNaIRpFyLdr+u6RyXAUmWiI25ltnZQjctzCfUrO/Nxywc6L6lBkApZtTaP+X+UHg==", + "requires": {} + }, + "@dicebear/pixel-art-neutral": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/pixel-art-neutral/-/pixel-art-neutral-8.0.1.tgz", + "integrity": "sha512-jrbwMNjLk8hlOm+hMTT43z2DqXEFtv6/8hhms7VZE9FjcB1GrQy8j6tSClTq/ktkZlWofEGfvD8BrG5HsbKvaw==", + "requires": {} + }, + "@dicebear/rings": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/rings/-/rings-8.0.1.tgz", + "integrity": "sha512-RcSXPJDdDiyAscUhJMI6pgOgk4or0nzjKndur44U6I+6s0qS3c74zfT//whLUnDnSO2ZTaUGAjQ5gGJtzp5fqQ==", + "requires": {} + }, + "@dicebear/shapes": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/shapes/-/shapes-8.0.1.tgz", + "integrity": "sha512-Duhe3bcKmcYt7GcUsNP4/OIbcHzgb4L7rfuMpUgqjXKATLYq1Wizsw9/y9wrwII8h7wIMxG6RDSndNbd7ISTtA==", + "requires": {} + }, + "@dicebear/thumbs": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/thumbs/-/thumbs-8.0.1.tgz", + "integrity": "sha512-cK3UeVVWtiGbStpYeKJrCw3Wy+LGNS5sFja2O3ogc/qpjiL7WFX7kYJXOE2neqOUxVItDxg7dfGatxFrsgUTYA==", + "requires": {} + }, + "@emotion/babel-plugin": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", + "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", + "requires": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/serialize": "^1.1.2", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "@emotion/cache": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", + "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", + "requires": { + "@emotion/memoize": "^0.8.1", + "@emotion/sheet": "^1.2.2", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "stylis": "4.2.0" + } + }, + "@emotion/hash": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + }, + "@emotion/is-prop-valid": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz", + "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==", + "requires": { + "@emotion/memoize": "^0.8.1" + } + }, + "@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "@emotion/react": { + "version": "11.11.4", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz", + "integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==", + "requires": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.11.0", + "@emotion/cache": "^11.11.0", + "@emotion/serialize": "^1.1.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "hoist-non-react-statics": "^3.3.1" + } + }, + "@emotion/serialize": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.4.tgz", + "integrity": "sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==", + "requires": { + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/unitless": "^0.8.1", + "@emotion/utils": "^1.2.1", + "csstype": "^3.0.2" + } + }, + "@emotion/sheet": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", + "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" + }, + "@emotion/styled": { + "version": "11.11.5", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.5.tgz", + "integrity": "sha512-/ZjjnaNKvuMPxcIiUkf/9SHoG4Q196DRl1w82hQ3WCsjo1IUR8uaGWrC6a87CrYAW0Kb/pK7hk8BnLgLRi9KoQ==", + "requires": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.11.0", + "@emotion/is-prop-valid": "^1.2.2", + "@emotion/serialize": "^1.1.4", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", + "@emotion/utils": "^1.2.1" + } + }, + "@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + }, + "@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", + "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", + "requires": {} + }, + "@emotion/utils": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", + "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" + }, + "@emotion/weak-memoize": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", + "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" + }, + "@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "dev": true, + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "dev": true, + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "dev": true, + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "dev": true, + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "dev": true, + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "dev": true, + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "dev": true, + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "dev": true, + "optional": true + }, + "@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", + "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==" + }, + "@eslint/eslintrc": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz", + "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==", + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "requires": { + "type-fest": "^0.20.2" + } + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "requires": { + "argparse": "^2.0.1" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" + } + } + }, + "@eslint/js": { + "version": "8.44.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz", + "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==" + }, + "@floating-ui/core": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.1.tgz", + "integrity": "sha512-42UH54oPZHPdRHdw6BgoBD6cg/eVTmVrFcgeRDM3jbO7uxSoipVcmcIGFcA5jmOHO5apcyvBhkSKES3fQJnu7A==", + "requires": { + "@floating-ui/utils": "^0.2.0" + } + }, + "@floating-ui/dom": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.4.tgz", + "integrity": "sha512-0G8R+zOvQsAG1pg2Q99P21jiqxqGBW1iRe/iXHsBRBxnpXKFI8QwbB4x5KmYLggNO5m34IQgOIu9SCRfR/WWiQ==", + "requires": { + "@floating-ui/core": "^1.0.0", + "@floating-ui/utils": "^0.2.0" + } + }, + "@floating-ui/react": { + "version": "0.26.19", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.19.tgz", + "integrity": "sha512-Jk6zITdjjIvjO/VdQFvpRaD3qPwOHH6AoDHxjhpy+oK4KFgaSP871HYWUAPdnLmx1gQ+w/pB312co3tVml+BXA==", + "requires": { + "@floating-ui/react-dom": "^2.1.1", + "@floating-ui/utils": "^0.2.4", + "tabbable": "^6.0.0" + } + }, + "@floating-ui/react-dom": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.1.tgz", + "integrity": "sha512-4h84MJt3CHrtG18mGsXuLCHMrug49d7DFkU0RMIyshRveBeyV2hmV/pDaF2Uxtu8kgq5r46llp5E5FQiR0K2Yg==", + "requires": { + "@floating-ui/dom": "^1.0.0" + } + }, + "@floating-ui/utils": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.4.tgz", + "integrity": "sha512-dWO2pw8hhi+WrXq1YJy2yCuWoL20PddgGaqTgVe4cOS9Q6qklXCiA1tJEqX6BEwRNSCP84/afac9hd4MS+zEUA==" + }, + "@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "optional": true, + "peer": true + }, + "@graphql-typed-document-node/core": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", + "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", + "requires": {} + }, + "@humanwhocodes/config-array": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", + "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", + "requires": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + } + }, + "@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", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" + }, + "@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "requires": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==" + } + } + }, + "@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==" + }, + "@jedmao/location": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@jedmao/location/-/location-3.0.0.tgz", + "integrity": "sha512-p7mzNlgJbCioUYLUEKds3cQG4CHONVFJNYqMe6ocEtENCL/jYmMo1Q3ApwsMmU+L0ZkaDJEyv4HokaByLoPwlQ==", + "dev": true + }, + "@jest/console": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", + "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0" + }, + "dependencies": { + "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" + } + } + } + }, + "@jest/core": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", + "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", + "requires": { + "@jest/console": "^27.5.1", + "@jest/reporters": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^27.5.1", + "jest-config": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-resolve-dependencies": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "jest-watcher": "^27.5.1", + "micromatch": "^4.0.4", + "rimraf": "^3.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "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" + } + } + } + }, + "@jest/environment": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", + "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "requires": { + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1" + } + }, + "@jest/fake-timers": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", + "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "requires": { + "@jest/types": "^27.5.1", + "@sinonjs/fake-timers": "^8.0.1", + "@types/node": "*", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + } + }, + "@jest/globals": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", + "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", + "requires": { + "@jest/environment": "^27.5.1", + "@jest/types": "^27.5.1", + "expect": "^27.5.1" + } + }, + "@jest/reporters": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", + "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", + "requires": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.2", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-haste-map": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "slash": "^3.0.0", + "source-map": "^0.6.0", + "string-length": "^4.0.1", + "terminal-link": "^2.0.0", + "v8-to-istanbul": "^8.1.0" + }, + "dependencies": { + "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" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "@jest/schemas": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", + "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", + "requires": { + "@sinclair/typebox": "^0.24.1" + } + }, + "@jest/source-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", + "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "@jest/test-result": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", + "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", + "requires": { + "@jest/console": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/test-sequencer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", + "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", + "requires": { + "@jest/test-result": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-runtime": "^27.5.1" + } + }, + "@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + }, + "dependencies": { + "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" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "dependencies": { + "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" + } + } + } + }, + "@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" + }, + "@jridgewell/source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "@jridgewell/trace-mapping": { + "version": "0.3.18", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", + "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "requires": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + }, + "dependencies": { + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + } + } + }, + "@leichtgewicht/ip-codec": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", + "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" + }, + "@microsoft/tsdoc": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz", + "integrity": "sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==", + "dev": true + }, + "@microsoft/tsdoc-config": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.16.2.tgz", + "integrity": "sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==", + "dev": true, + "requires": { + "@microsoft/tsdoc": "0.14.2", + "ajv": "~6.12.6", + "jju": "~1.4.0", + "resolve": "~1.19.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "requires": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + } + } + } + }, + "@mui/base": { + "version": "5.0.0-beta.40", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.40.tgz", + "integrity": "sha512-I/lGHztkCzvwlXpjD2+SNmvNQvB4227xBXhISPjEaJUXGImOQ9f3D2Yj/T3KasSI/h0MLWy74X0J6clhPmsRbQ==", + "requires": { + "@babel/runtime": "^7.23.9", + "@floating-ui/react-dom": "^2.0.8", + "@mui/types": "^7.2.14", + "@mui/utils": "^5.15.14", + "@popperjs/core": "^2.11.8", + "clsx": "^2.1.0", + "prop-types": "^15.8.1" + }, + "dependencies": { + "clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" + } + } + }, + "@mui/core-downloads-tracker": { + "version": "5.16.4", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.4.tgz", + "integrity": "sha512-rNdHXhclwjEZnK+//3SR43YRx0VtjdHnUFhMSGYmAMJve+KiwEja/41EYh8V3pZKqF2geKyfcFUenTfDTYUR4w==" + }, + "@mui/icons-material": { + "version": "5.16.1", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.16.1.tgz", + "integrity": "sha512-ogQPweYba4+5XZykilwxn2/oS78uwoQ0BVBpOhhCJo0ooZsqTTsalhzP2qD/RdGqMQ8xyXPz1sYM2djTruVVVA==", + "requires": { + "@babel/runtime": "^7.23.9" + } + }, + "@mui/material": { + "version": "5.16.4", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.16.4.tgz", + "integrity": "sha512-dBnh3/zRYgEVIS3OE4oTbujse3gifA0qLMmuUk13ywsDCbngJsdgwW5LuYeiT5pfA8PGPGSqM7mxNytYXgiMCw==", + "requires": { + "@babel/runtime": "^7.23.9", + "@mui/core-downloads-tracker": "^5.16.4", + "@mui/system": "^5.16.4", + "@mui/types": "^7.2.15", + "@mui/utils": "^5.16.4", + "@popperjs/core": "^2.11.8", + "@types/react-transition-group": "^4.4.10", + "clsx": "^2.1.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1", + "react-is": "^18.3.1", + "react-transition-group": "^4.4.5" + }, + "dependencies": { + "clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" + } + } + }, + "@mui/private-theming": { + "version": "5.16.4", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.16.4.tgz", + "integrity": "sha512-ZsAm8cq31SJ37SVWLRlu02v9SRthxnfQofaiv14L5Bht51B0dz6yQEoVU/V8UduZDCCIrWkBHuReVfKhE/UuXA==", + "requires": { + "@babel/runtime": "^7.23.9", + "@mui/utils": "^5.16.4", + "prop-types": "^15.8.1" + } + }, + "@mui/styled-engine": { + "version": "5.16.4", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.16.4.tgz", + "integrity": "sha512-0+mnkf+UiAmTVB8PZFqOhqf729Yh0Cxq29/5cA3VAyDVTRIUUQ8FXQhiAhUIbijFmM72rY80ahFPXIm4WDbzcA==", + "requires": { + "@babel/runtime": "^7.23.9", + "@emotion/cache": "^11.11.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + } + }, + "@mui/system": { + "version": "5.16.4", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.16.4.tgz", + "integrity": "sha512-ET1Ujl2/8hbsD611/mqUuNArMCGv/fIWO/f8B3ZqF5iyPHM2aS74vhTNyjytncc4i6dYwGxNk+tLa7GwjNS0/w==", + "requires": { + "@babel/runtime": "^7.23.9", + "@mui/private-theming": "^5.16.4", + "@mui/styled-engine": "^5.16.4", + "@mui/types": "^7.2.15", + "@mui/utils": "^5.16.4", + "clsx": "^2.1.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "dependencies": { + "clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" + } + } + }, + "@mui/types": { + "version": "7.2.15", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.15.tgz", + "integrity": "sha512-nbo7yPhtKJkdf9kcVOF8JZHPZTmqXjJ/tI0bdWgHg5tp9AnIN4Y7f7wm9T+0SyGYJk76+GYZ8Q5XaTYAsUHN0Q==", + "requires": {} + }, + "@mui/utils": { + "version": "5.16.4", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.16.4.tgz", + "integrity": "sha512-nlppYwq10TBIFqp7qxY0SvbACOXeOjeVL3pOcDsK0FT8XjrEXh9/+lkg8AEIzD16z7YfiJDQjaJG2OLkE7BxNg==", + "requires": { + "@babel/runtime": "^7.23.9", + "@types/prop-types": "^15.7.12", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^18.3.1" + }, + "dependencies": { + "clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" + } + } + }, + "@mui/x-charts": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@mui/x-charts/-/x-charts-7.8.0.tgz", + "integrity": "sha512-SosaVtx4Ig1nu/loH6Mq4peH5Pq5UvVEnsMfe4G2IEVrMxfwrktWJo+86t9LxiHTERt4wxPKnsqlhkgBIf9ePQ==", + "requires": { + "@babel/runtime": "^7.24.7", + "@mui/base": "^5.0.0-beta.40", + "@mui/system": "^5.15.20", + "@mui/utils": "^5.15.20", + "@react-spring/rafz": "^9.7.3", + "@react-spring/web": "^9.7.3", + "clsx": "^2.1.1", + "d3-color": "^3.1.0", + "d3-delaunay": "^6.0.4", + "d3-interpolate": "^3.0.1", + "d3-scale": "^4.0.2", + "d3-shape": "^3.2.0", + "prop-types": "^15.8.1" + }, + "dependencies": { + "clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" + } + } + }, + "@mui/x-data-grid": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-7.11.0.tgz", + "integrity": "sha512-dXaIw3Noxc4d6xenS7J+zMPORG9ptkTW7B81P6QFovILSEuI/qebQhijy/IkqRvcCsuZYLL3nA89bp+EDI503Q==", + "requires": { + "@babel/runtime": "^7.24.8", + "@mui/system": "^5.16.2", + "@mui/utils": "^5.16.2", + "@mui/x-internals": "7.11.0", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "reselect": "^4.1.8" + }, + "dependencies": { + "clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" + } + } + }, + "@mui/x-date-pickers": { + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-7.6.1.tgz", + "integrity": "sha512-erSq5cnOUyBgBmpHnMxIit5yhT3bl/lOaNZKpObvJtvEJetvNA9xWQ7dz/J/AufLzDuvThjusuRD0y+GmeXtiw==", + "requires": { + "@babel/runtime": "^7.24.6", + "@mui/base": "^5.0.0-beta.40", + "@mui/system": "^5.15.15", + "@mui/utils": "^5.15.14", + "@types/react-transition-group": "^4.4.10", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-transition-group": "^4.4.5" + }, + "dependencies": { + "clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" + } + } + }, + "@mui/x-internals": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-7.11.0.tgz", + "integrity": "sha512-GqCYylKiB4cLH9tK4JweJlT2JvPjnpXjS3TEIqtHB4BcSsezhdRrMGzHOO5zCJqkasqTirJh2t6X16Qw1llr4Q==", + "requires": { + "@babel/runtime": "^7.24.8", + "@mui/utils": "^5.16.2" + } + }, + "@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "requires": { + "eslint-scope": "5.1.1" + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@pdf-lib/standard-fonts": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz", + "integrity": "sha512-hU30BK9IUN/su0Mn9VdlVKsWBS6GyhVfqjwl1FjZN4TxP6cCw0jP2w7V3Hf5uX7M0AZJ16vey9yE0ny7Sa59ZA==", + "requires": { + "pako": "^1.0.6" + } + }, + "@pdf-lib/upng": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@pdf-lib/upng/-/upng-1.0.1.tgz", + "integrity": "sha512-dQK2FUMQtowVP00mtIksrlZhdFXQZPC+taih1q4CvPZ5vqdxR/LKBaFg0oAfzd1GlHZXXSPdQfzQnt+ViGvEIQ==", + "requires": { + "pako": "^1.0.10" + } + }, + "@pdfme/common": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@pdfme/common/-/common-1.2.6.tgz", + "integrity": "sha512-ROmQ/iMUdmFS2QXD/kKDdcU5T6H3azDs2b1hE/OXs8531BPZ9ABbu9+1NRZQoNK4U/zP2F+Osb/B8ckr9lAmGg==", + "requires": { + "buffer": "^6.0.3", + "fontkit": "^2.0.2", + "zod": "^3.20.2" + } + }, + "@pdfme/generator": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@pdfme/generator/-/generator-1.2.6.tgz", + "integrity": "sha512-rAkhr4vYa0OxVubAvLI/UIgD9+sCrcBG1SZpFCBVILgZjpqkUsscXdyukRtmHP6WaNAFGINch6PZVoshyQdGPw==", + "requires": { + "@pdfme/common": "latest", + "@pdfme/pdf-lib": "^1.17.3", + "atob": "^2.1.2", + "bwip-js": "^3.2.2", + "fontkit": "^2.0.2" + } + }, + "@pdfme/pdf-lib": { + "version": "1.17.3", + "resolved": "https://registry.npmjs.org/@pdfme/pdf-lib/-/pdf-lib-1.17.3.tgz", + "integrity": "sha512-k3cyms42I7jVycwDuzZuLD7A9J/D8Ud1iGJ7BpAfF54QYKxG0mUG6jTDJnc+tHrpNrsoJ4iFqERy5XvMQ6SUsA==", + "requires": { + "@pdf-lib/standard-fonts": "^1.0.0", + "@pdf-lib/upng": "^1.0.1", + "pako": "^1.0.11", + "tslib": "^1.11.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + }, + "@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true + }, + "@pmmmwh/react-refresh-webpack-plugin": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.10.tgz", + "integrity": "sha512-j0Ya0hCFZPd4x40qLzbhGsh9TMtdb+CJQiso+WxLOPNasohq9cc5SNUcwsZaRH6++Xh91Xkm/xHCkuIiIu0LUA==", + "requires": { + "ansi-html-community": "^0.0.8", + "common-path-prefix": "^3.0.0", + "core-js-pure": "^3.23.3", + "error-stack-parser": "^2.0.6", + "find-up": "^5.0.0", + "html-entities": "^2.1.0", + "loader-utils": "^2.0.4", + "schema-utils": "^3.0.0", + "source-map": "^0.7.3" + }, + "dependencies": { + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "requires": { + "p-locate": "^5.0.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "requires": { + "p-limit": "^3.0.2" + } + }, + "source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==" + } + } + }, + "@polka/url": { + "version": "1.0.0-next.21", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz", + "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==", + "dev": true + }, + "@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==" + }, + "@react-aria/ssr": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.7.0.tgz", + "integrity": "sha512-bfufjg4ESE5giN+Fxj1XIzS5f/YIhqcGc+Ve+vUUKU8xZ8t/Xtjlv8F3kjqDBQdk//n3mluFY7xG1wQVB9rMLQ==", + "requires": { + "@swc/helpers": "^0.5.0" + }, + "dependencies": { + "@swc/helpers": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.1.tgz", + "integrity": "sha512-sJ902EfIzn1Fa+qYmjdQqh8tPsoxyBz+8yBKC2HKUxyezKJFwPGOn7pv4WY6QuQW//ySQi5lJjA/ZT9sNWWNTg==", + "requires": { + "tslib": "^2.4.0" + } + } + } + }, + "@react-spring/animated": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.3.tgz", + "integrity": "sha512-5CWeNJt9pNgyvuSzQH+uy2pvTg8Y4/OisoscZIR8/ZNLIOI+CatFBhGZpDGTF/OzdNFsAoGk3wiUYTwoJ0YIvw==", + "requires": { + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + } + }, + "@react-spring/core": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.7.3.tgz", + "integrity": "sha512-IqFdPVf3ZOC1Cx7+M0cXf4odNLxDC+n7IN3MDcVCTIOSBfqEcBebSv+vlY5AhM0zw05PDbjKrNmBpzv/AqpjnQ==", + "requires": { + "@react-spring/animated": "~9.7.3", + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + } + }, + "@react-spring/rafz": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.7.3.tgz", + "integrity": "sha512-9vzW1zJPcC4nS3aCV+GgcsK/WLaB520Iyvm55ARHfM5AuyBqycjvh1wbmWmgCyJuX4VPoWigzemq1CaaeRSHhQ==" + }, + "@react-spring/shared": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.7.3.tgz", + "integrity": "sha512-NEopD+9S5xYyQ0pGtioacLhL2luflh6HACSSDUZOwLHoxA5eku1UPuqcJqjwSD6luKjjLfiLOspxo43FUHKKSA==", + "requires": { + "@react-spring/types": "~9.7.3" + } + }, + "@react-spring/types": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.7.3.tgz", + "integrity": "sha512-Kpx/fQ/ZFX31OtlqVEFfgaD1ACzul4NksrvIgYfIFq9JpDHFwQkMVZ10tbo0FU/grje4rcL4EIrjekl3kYwgWw==" + }, + "@react-spring/web": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.7.3.tgz", + "integrity": "sha512-BXt6BpS9aJL/QdVqEIX9YoUy8CE6TJrU0mNCqSoxdXlIeNcEBWOfIyE6B14ENNsyQKS3wOWkiJfco0tCr/9tUg==", + "requires": { + "@react-spring/animated": "~9.7.3", + "@react-spring/core": "~9.7.3", + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + } + }, + "@remix-run/router": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.18.0.tgz", + "integrity": "sha512-L3jkqmqoSVBVKHfpGZmLrex0lxR5SucGA0sUfFzGctehw+S/ggL9L/0NnC5mw6P8HUWpFZ3nQw3cRApjjWx9Sw==" + }, + "@restart/hooks": { + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.10.tgz", + "integrity": "sha512-HVZhYHb+9xnN6vDPyiTmw6N4V5wD9tatL3y0zpHFeeatP1ooOD1edzd3MnJCXYlb3OeleDg+Vv16EikGrH57eA==", + "requires": { + "dequal": "^2.0.3" + } + }, + "@restart/ui": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.6.6.tgz", + "integrity": "sha512-eC3puKuWE1SRYbojWHXnvCNHGgf3uzHCb6JOhnF4OXPibOIPEkR1sqDSkL643ydigxwh+ruCa1CmYHlzk7ikKA==", + "requires": { + "@babel/runtime": "^7.21.0", + "@popperjs/core": "^2.11.6", + "@react-aria/ssr": "^3.5.0", + "@restart/hooks": "^0.4.9", + "@types/warning": "^3.0.0", + "dequal": "^2.0.3", + "dom-helpers": "^5.2.0", + "uncontrollable": "^8.0.1", + "warning": "^4.0.3" + }, + "dependencies": { + "uncontrollable": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-8.0.2.tgz", + "integrity": "sha512-/GDx+K1STGtpgTsj5Dj3J51YaKxZDblbCQHTH1zHLuoBEWodj6MjtRVv3TUijj1JYLRLSFsFzN8NV4M3QV4d9w==", + "requires": {} + } + } + }, + "@rollup/plugin-babel": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", + "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", + "requires": { + "@babel/helper-module-imports": "^7.10.4", + "@rollup/pluginutils": "^3.1.0" + } + }, + "@rollup/plugin-node-resolve": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", + "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==", + "requires": { + "@rollup/pluginutils": "^3.1.0", + "@types/resolve": "1.17.1", + "builtin-modules": "^3.1.0", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.19.0" + } + }, + "@rollup/plugin-replace": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz", + "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==", + "requires": { + "@rollup/pluginutils": "^3.1.0", + "magic-string": "^0.25.7" + } + }, + "@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "requires": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "dependencies": { + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==" + } + } + }, + "@rushstack/eslint-patch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.3.2.tgz", + "integrity": "sha512-V+MvGwaHH03hYhY+k6Ef/xKd6RYlc4q8WBx+2ANmipHJcKuktNcI/NgEsJgdSUF6Lw32njT6OnrRsKYCdgHjYw==" + }, + "@shikijs/core": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.10.3.tgz", + "integrity": "sha512-D45PMaBaeDHxww+EkcDQtDAtzv00Gcsp72ukBtaLSmqRvh0WgGMq3Al0rl1QQBZfuneO75NXMIzEZGFitThWbg==", + "peer": true, + "requires": { + "@types/hast": "^3.0.4" + } + }, + "@sinclair/typebox": { + "version": "0.24.51", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", + "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==" + }, + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true + }, + "@sinonjs/commons": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", + "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, + "@surma/rollup-plugin-off-main-thread": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", + "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==", + "requires": { + "ejs": "^3.1.6", + "json5": "^2.2.0", + "magic-string": "^0.25.0", + "string.prototype.matchall": "^4.0.6" + } + }, + "@svgr/babel-plugin-add-jsx-attribute": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.5.1.tgz", + "integrity": "sha512-9PYGcXrAxitycIjRmZB+Q0JaN07GZIWaTBIGQzfaZv+qr1n8X1XUEJ5rZ/vx6OVD9RRYlrNnXWExQXcmZeD/BQ==", + "dev": true, + "requires": {} + }, + "@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "dev": true, + "requires": {} + }, + "@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "dev": true, + "requires": {} + }, + "@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.5.1.tgz", + "integrity": "sha512-8DPaVVE3fd5JKuIC29dqyMB54sA6mfgki2H2+swh+zNJoynC8pMPzOkidqHOSc6Wj032fhl8Z0TVn1GiPpAiJg==", + "dev": true, + "requires": {} + }, + "@svgr/babel-plugin-svg-dynamic-title": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.5.1.tgz", + "integrity": "sha512-FwOEi0Il72iAzlkaHrlemVurgSQRDFbk0OC8dSvD5fSBPHltNh7JtLsxmZUhjYBZo2PpcU/RJvvi6Q0l7O7ogw==", + "dev": true, + "requires": {} + }, + "@svgr/babel-plugin-svg-em-dimensions": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.5.1.tgz", + "integrity": "sha512-gWGsiwjb4tw+ITOJ86ndY/DZZ6cuXMNE/SjcDRg+HLuCmwpcjOktwRF9WgAiycTqJD/QXqL2f8IzE2Rzh7aVXA==", + "dev": true, + "requires": {} + }, + "@svgr/babel-plugin-transform-react-native-svg": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.5.1.tgz", + "integrity": "sha512-2jT3nTayyYP7kI6aGutkyfJ7UMGtuguD72OjeGLwVNyfPRBD8zQthlvL+fAbAKk5n9ZNcvFkp/b1lZ7VsYqVJg==", + "dev": true, + "requires": {} + }, + "@svgr/babel-plugin-transform-svg-component": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.5.1.tgz", + "integrity": "sha512-a1p6LF5Jt33O3rZoVRBqdxL350oge54iZWHNI6LJB5tQ7EelvD/Mb1mfBiZNAan0dt4i3VArkFRjA4iObuNykQ==", + "dev": true, + "requires": {} + }, + "@svgr/babel-preset": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-6.5.1.tgz", + "integrity": "sha512-6127fvO/FF2oi5EzSQOAjo1LE3OtNVh11R+/8FXa+mHx1ptAaS4cknIjnUA7e6j6fwGGJ17NzaTJFUwOV2zwCw==", + "dev": true, + "requires": { + "@svgr/babel-plugin-add-jsx-attribute": "^6.5.1", + "@svgr/babel-plugin-remove-jsx-attribute": "*", + "@svgr/babel-plugin-remove-jsx-empty-expression": "*", + "@svgr/babel-plugin-replace-jsx-attribute-value": "^6.5.1", + "@svgr/babel-plugin-svg-dynamic-title": "^6.5.1", + "@svgr/babel-plugin-svg-em-dimensions": "^6.5.1", + "@svgr/babel-plugin-transform-react-native-svg": "^6.5.1", + "@svgr/babel-plugin-transform-svg-component": "^6.5.1" + } + }, + "@svgr/core": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-6.5.1.tgz", + "integrity": "sha512-/xdLSWxK5QkqG524ONSjvg3V/FkNyCv538OIBdQqPNaAta3AsXj/Bd2FbvR87yMbXO2hFSWiAe/Q6IkVPDw+mw==", + "dev": true, + "requires": { + "@babel/core": "^7.19.6", + "@svgr/babel-preset": "^6.5.1", + "@svgr/plugin-jsx": "^6.5.1", + "camelcase": "^6.2.0", + "cosmiconfig": "^7.0.1" + }, + "dependencies": { + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + } + } + }, + "@svgr/hast-util-to-babel-ast": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.5.1.tgz", + "integrity": "sha512-1hnUxxjd83EAxbL4a0JDJoD3Dao3hmjvyvyEV8PzWmLK3B9m9NPlW7GKjFyoWE8nM7HnXzPcmmSyOW8yOddSXw==", + "dev": true, + "requires": { + "@babel/types": "^7.20.0", + "entities": "^4.4.0" + } + }, + "@svgr/plugin-jsx": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-6.5.1.tgz", + "integrity": "sha512-+UdQxI3jgtSjCykNSlEMuy1jSRQlGC7pqBCPvkG/2dATdWo082zHTTK3uhnAju2/6XpE6B5mZ3z4Z8Ns01S8Gw==", + "dev": true, + "requires": { + "@babel/core": "^7.19.6", + "@svgr/babel-preset": "^6.5.1", + "@svgr/hast-util-to-babel-ast": "^6.5.1", + "svg-parser": "^2.0.4" + } + }, + "@svgr/plugin-svgo": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-5.5.0.tgz", + "integrity": "sha512-r5swKk46GuQl4RrVejVwpeeJaydoxkdwkM1mBKOgJLBUJPGaLci6ylg/IjhrRsREKDkr4kbMWdgOtbXEh0fyLQ==", + "requires": { + "cosmiconfig": "^7.0.0", + "deepmerge": "^4.2.2", + "svgo": "^1.2.2" + } + }, + "@svgr/webpack": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-5.5.0.tgz", + "integrity": "sha512-DOBOK255wfQxguUta2INKkzPj6AIS6iafZYiYmHn6W3pHlycSRRlvWKCfLDG10fXfLWqE3DJHgRUOyJYmARa7g==", + "requires": { + "@babel/core": "^7.12.3", + "@babel/plugin-transform-react-constant-elements": "^7.12.1", + "@babel/preset-env": "^7.12.1", + "@babel/preset-react": "^7.12.5", + "@svgr/core": "^5.5.0", + "@svgr/plugin-jsx": "^5.5.0", + "@svgr/plugin-svgo": "^5.5.0", + "loader-utils": "^2.0.0" + }, + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz", + "integrity": "sha512-ZFf2gs/8/6B8PnSofI0inYXr2SDNTDScPXhN7k5EqD4aZ3gi6u+rbmZHVB8IM3wDyx8ntKACZbtXSm7oZGRqVg==" + }, + "@svgr/babel-plugin-remove-jsx-attribute": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-5.4.0.tgz", + "integrity": "sha512-yaS4o2PgUtwLFGTKbsiAy6D0o3ugcUhWK0Z45umJ66EPWunAz9fuFw2gJuje6wqQvQWOTJvIahUwndOXb7QCPg==" + }, + "@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-5.0.1.tgz", + "integrity": "sha512-LA72+88A11ND/yFIMzyuLRSMJ+tRKeYKeQ+mR3DcAZ5I4h5CPWN9AHyUzJbWSYp/u2u0xhmgOe0+E41+GjEueA==" + }, + "@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-5.0.1.tgz", + "integrity": "sha512-PoiE6ZD2Eiy5mK+fjHqwGOS+IXX0wq/YDtNyIgOrc6ejFnxN4b13pRpiIPbtPwHEc+NT2KCjteAcq33/F1Y9KQ==" + }, + "@svgr/babel-plugin-svg-dynamic-title": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-5.4.0.tgz", + "integrity": "sha512-zSOZH8PdZOpuG1ZVx/cLVePB2ibo3WPpqo7gFIjLV9a0QsuQAzJiwwqmuEdTaW2pegyBE17Uu15mOgOcgabQZg==" + }, + "@svgr/babel-plugin-svg-em-dimensions": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-5.4.0.tgz", + "integrity": "sha512-cPzDbDA5oT/sPXDCUYoVXEmm3VIoAWAPT6mSPTJNbQaBNUuEKVKyGH93oDY4e42PYHRW67N5alJx/eEol20abw==" + }, + "@svgr/babel-plugin-transform-react-native-svg": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-5.4.0.tgz", + "integrity": "sha512-3eYP/SaopZ41GHwXma7Rmxcv9uRslRDTY1estspeB1w1ueZWd/tPlMfEOoccYpEMZU3jD4OU7YitnXcF5hLW2Q==" + }, + "@svgr/babel-plugin-transform-svg-component": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-5.5.0.tgz", + "integrity": "sha512-q4jSH1UUvbrsOtlo/tKcgSeiCHRSBdXoIoqX1pgcKK/aU3JD27wmMKwGtpB8qRYUYoyXvfGxUVKchLuR5pB3rQ==" + }, + "@svgr/babel-preset": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-5.5.0.tgz", + "integrity": "sha512-4FiXBjvQ+z2j7yASeGPEi8VD/5rrGQk4Xrq3EdJmoZgz/tpqChpo5hgXDvmEauwtvOc52q8ghhZK4Oy7qph4ig==", + "requires": { + "@svgr/babel-plugin-add-jsx-attribute": "^5.4.0", + "@svgr/babel-plugin-remove-jsx-attribute": "^5.4.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "^5.0.1", + "@svgr/babel-plugin-replace-jsx-attribute-value": "^5.0.1", + "@svgr/babel-plugin-svg-dynamic-title": "^5.4.0", + "@svgr/babel-plugin-svg-em-dimensions": "^5.4.0", + "@svgr/babel-plugin-transform-react-native-svg": "^5.4.0", + "@svgr/babel-plugin-transform-svg-component": "^5.5.0" + } + }, + "@svgr/core": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-5.5.0.tgz", + "integrity": "sha512-q52VOcsJPvV3jO1wkPtzTuKlvX7Y3xIcWRpCMtBF3MrteZJtBfQw/+u0B1BHy5ColpQc1/YVTrPEtSYIMNZlrQ==", + "requires": { + "@svgr/plugin-jsx": "^5.5.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^7.0.0" + } + }, + "@svgr/hast-util-to-babel-ast": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-5.5.0.tgz", + "integrity": "sha512-cAaR/CAiZRB8GP32N+1jocovUtvlj0+e65TB50/6Lcime+EA49m/8l+P2ko+XPJ4dw3xaPS3jOL4F2X4KWxoeQ==", + "requires": { + "@babel/types": "^7.12.6" + } + }, + "@svgr/plugin-jsx": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-5.5.0.tgz", + "integrity": "sha512-V/wVh33j12hGh05IDg8GpIUXbjAPnTdPTKuP4VNLggnwaHMPNQNae2pRnyTAILWCQdz5GyMqtO488g7CKM8CBA==", + "requires": { + "@babel/core": "^7.12.3", + "@svgr/babel-preset": "^5.5.0", + "@svgr/hast-util-to-babel-ast": "^5.5.0", + "svg-parser": "^2.0.2" + } + }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" + }, + "loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + } + } + }, + "@swc/helpers": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", + "integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==", + "requires": { + "tslib": "^2.4.0" + } + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "requires": { + "defer-to-connect": "^1.0.1" + } + }, + "@testing-library/dom": { + "version": "7.31.2", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.31.2.tgz", + "integrity": "sha512-3UqjCpey6HiTZT92vODYLPxTBWlM8ZOOjr3LX5F37/VRipW2M1kX6I/Cm4VXzteZqfGfagg8yXywpcOgQBlNsQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^4.2.0", + "aria-query": "^4.2.2", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.6", + "lz-string": "^1.4.4", + "pretty-format": "^26.6.2" + }, + "dependencies": { + "aria-query": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", + "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", + "dev": true, + "requires": { + "@babel/runtime": "^7.10.2", + "@babel/runtime-corejs3": "^7.10.2" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + } + } + }, + "@testing-library/jest-dom": { + "version": "5.16.5", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz", + "integrity": "sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA==", + "dev": true, + "requires": { + "@adobe/css-tools": "^4.0.1", + "@babel/runtime": "^7.9.2", + "@types/testing-library__jest-dom": "^5.9.1", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.5.6", + "lodash": "^4.17.15", + "redent": "^3.0.0" + } + }, + "@testing-library/react": { + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-11.2.7.tgz", + "integrity": "sha512-tzRNp7pzd5QmbtXNG/mhdcl7Awfu/Iz1RaVHY75zTdOkmHCuzMhRL83gWHSgOAcjS3CCbyfwUHMZgRJb4kAfpA==", + "dev": true, + "requires": { + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^7.28.1" + } + }, + "@testing-library/user-event": { + "version": "12.8.3", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-12.8.3.tgz", + "integrity": "sha512-IR0iWbFkgd56Bu5ZI/ej8yQwrkCv8Qydx6RzwbKz9faXazR/+5tvYKsZQgyXJiwgpcva127YO6JcWy7YlCfofQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.12.5" + } + }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==" + }, + "@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==" + }, + "@types/aria-query": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz", + "integrity": "sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==", + "dev": true + }, + "@types/babel__core": { + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", + "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==", + "requires": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", + "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", + "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz", + "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==", + "requires": { + "@babel/types": "^7.20.7" + } + }, + "@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/bonjour": { + "version": "3.5.10", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz", + "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==", + "requires": { + "@types/node": "*" + } + }, + "@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/connect-history-api-fallback": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz", + "integrity": "sha512-4x5FkPpLipqwthjPsF7ZRbOv3uoLUFkTA9G9v583qi4pACvq0uTELrB8OLUzPWUI4IJIyvM85vzkV1nyiI2Lig==", + "requires": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "@types/eslint": { + "version": "8.44.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.0.tgz", + "integrity": "sha512-gsF+c/0XOguWgaOgvFs+xnnRqt9GwgTvIks36WpE6ueeI4KCEHHd8K/CKHqhOqrJKsYH8m27kRzQEvWXAwXUTw==", + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "@types/eslint-scope": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", + "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", + "requires": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "@types/estree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", + "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==" + }, + "@types/express": { + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", + "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.35", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", + "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "@types/graceful-fs": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", + "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", + "requires": { + "@types/node": "*" + } + }, + "@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "peer": true, + "requires": { + "@types/unist": "*" + } + }, + "@types/history": { + "version": "4.7.11", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", + "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==", + "dev": true + }, + "@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "requires": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, + "@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" + }, + "@types/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==" + }, + "@types/http-proxy": { + "version": "1.17.11", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.11.tgz", + "integrity": "sha512-HC8G7c1WmaF2ekqpnFq626xd3Zz0uvaqFmBJNRZCGEZCXkvSdJoNFn/8Ygbd9fKNQj8UzLdCETaI0UWPAjK7IA==", + "requires": { + "@types/node": "*" + } + }, + "@types/inquirer": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-9.0.7.tgz", + "integrity": "sha512-Q0zyBupO6NxGRZut/JdmqYKOnN95Eg5V8Csg3PGKkP+FnvsUZx1jAyK7fztIszxxMuoBA6E3KXWvdZVXIpx60g==", + "dev": true, + "requires": { + "@types/through": "*", + "rxjs": "^7.2.0" + } + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==" + }, + "@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/jest": { + "version": "26.0.24", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.24.tgz", + "integrity": "sha512-E/X5Vib8BWqZNRlDxj9vYXhsDwPYbPINqKF9BsnSoon4RQ0D9moEuLD8txgyypFLH7J4+Lho9Nr/c8H0Fi+17w==", + "dev": true, + "requires": { + "jest-diff": "^26.0.0", + "pretty-format": "^26.0.0" + } + }, + "@types/js-cookie": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.6.tgz", + "integrity": "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==", + "dev": true + }, + "@types/json-schema": { + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==" + }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" + }, + "@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + }, + "@types/minimist": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", + "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", + "optional": true, + "peer": true + }, + "@types/node": { + "version": "20.12.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz", + "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==", + "requires": { + "undici-types": "~5.26.4" + } + }, + "@types/node-fetch": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", + "dev": true, + "requires": { + "@types/node": "*", + "form-data": "^4.0.0" + }, + "dependencies": { + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } + }, + "@types/normalize-package-data": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "optional": true, + "peer": true + }, + "@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" + }, + "@types/prettier": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==" + }, + "@types/prop-types": { + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" + }, + "@types/q": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz", + "integrity": "sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ==" + }, + "@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "@types/react": { + "version": "17.0.62", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.62.tgz", + "integrity": "sha512-eANCyz9DG8p/Vdhr0ZKST8JV12PhH2ACCDYlFw6DIO+D+ca+uP4jtEDEpVqXZrh/uZdXQGwk7whJa3ah5DtyLw==", + "requires": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "@types/react-beautiful-dnd": { + "version": "13.1.8", + "resolved": "https://registry.npmjs.org/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.1.8.tgz", + "integrity": "sha512-E3TyFsro9pQuK4r8S/OL6G99eq7p8v29sX0PM7oT8Z+PJfZvSQTx4zTQbUJ+QZXioAF0e7TGBEcA1XhYhCweyQ==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, + "@types/react-bootstrap": { + "version": "0.32.32", + "resolved": "https://registry.npmjs.org/@types/react-bootstrap/-/react-bootstrap-0.32.32.tgz", + "integrity": "sha512-GM9UtV7v+C2F0rbqgIpMWdCKBMdX3PQURoJQobPO4vDAeFadcExNtKffi13/MjaAks+riJKVGyiMe+6OmDYT2w==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, + "@types/react-datepicker": { + "version": "4.11.2", + "resolved": "https://registry.npmjs.org/@types/react-datepicker/-/react-datepicker-4.11.2.tgz", + "integrity": "sha512-ELYyX3lb3K1WltqdlF1hbnaDGgzlF6PIR5T4W38cSEcfrQDIrPE+Ioq5pwRe/KEJ+ihHMjvTVZQkwJx0pWMNHQ==", + "dev": true, + "requires": { + "@popperjs/core": "^2.9.2", + "@types/react": "*", + "date-fns": "^2.0.1", + "react-popper": "^2.2.5" + } + }, + "@types/react-dom": { + "version": "17.0.20", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.20.tgz", + "integrity": "sha512-4pzIjSxDueZZ90F52mU3aPoogkHIoSIDG+oQ+wQK7Cy2B9S+MvOqY0uEA/qawKz381qrEDkvpwyt8Bm31I8sbA==", + "dev": true, + "requires": { + "@types/react": "^17" + } + }, + "@types/react-google-recaptcha": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@types/react-google-recaptcha/-/react-google-recaptcha-2.1.5.tgz", + "integrity": "sha512-iWTjmVttlNgp0teyh7eBXqNOQzVq2RWNiFROWjraOptRnb1OcHJehQnji0sjqIRAk9K0z8stjyhU+OLpPb0N6w==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, + "@types/react-redux": { + "version": "7.1.25", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.25.tgz", + "integrity": "sha512-bAGh4e+w5D8dajd6InASVIyCo4pZLJ66oLb80F9OBLO1gKESbZcRCJpTT6uLXX+HAB57zw1WTdwJdAsewuTweg==", + "requires": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + } + }, + "@types/react-router": { + "version": "5.1.20", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz", + "integrity": "sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==", + "dev": true, + "requires": { + "@types/history": "^4.7.11", + "@types/react": "*" + } + }, + "@types/react-router-dom": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz", + "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==", + "dev": true, + "requires": { + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "*" + } + }, + "@types/react-transition-group": { + "version": "4.4.10", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz", + "integrity": "sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==", + "requires": { + "@types/react": "*" + } + }, + "@types/resolve": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", + "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", + "requires": { + "@types/node": "*" + } + }, + "@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" + }, + "@types/sanitize-html": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@types/sanitize-html/-/sanitize-html-2.11.0.tgz", + "integrity": "sha512-7oxPGNQHXLHE48r/r/qjn7q0hlrs3kL7oZnGj0Wf/h9tj/6ibFyRkNbsDxaBBZ4XUZ0Dx5LGCyDJ04ytSofacQ==", + "dev": true, + "requires": { + "htmlparser2": "^8.0.0" + } + }, + "@types/scheduler": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", + "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==" + }, + "@types/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==" + }, + "@types/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", + "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", + "requires": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "@types/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", + "requires": { + "@types/express": "*" + } + }, + "@types/serve-static": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", + "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", + "requires": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, + "@types/sockjs": { + "version": "0.3.33", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", + "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", + "requires": { + "@types/node": "*" + } + }, + "@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" + }, + "@types/testing-library__jest-dom": { + "version": "5.14.8", + "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.8.tgz", + "integrity": "sha512-NRfJE9Cgpmu4fx716q9SYmU4jxxhYRU1BQo239Txt/9N3EC745XZX1Yl7h/SBIDlo1ANVOCRB4YDXjaQdoKCHQ==", + "dev": true, + "requires": { + "@types/jest": "*" + } + }, + "@types/through": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.33.tgz", + "integrity": "sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/trusted-types": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.3.tgz", + "integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==" + }, + "@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", + "peer": true + }, + "@types/warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.0.tgz", + "integrity": "sha512-t/Tvs5qR47OLOr+4E9ckN8AmP2Tf16gWq+/qA4iUGS/OOyHVO8wv2vjJuX8SNOUTJyWb+2t7wJm6cXILFnOROA==" + }, + "@types/ws": { + "version": "8.5.5", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz", + "integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==", + "requires": { + "@types/node": "*" + } + }, + "@types/yargs": { + "version": "16.0.5", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.5.tgz", + "integrity": "sha512-AxO/ADJOBFJScHbWhq2xAhlWP24rY4aCEG/NFaMvbT3X2MgRsLjhjQwsn0Zi5zn0LG9jUhCCZMeX9Dkuw6k+vQ==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" + }, + "@typescript-eslint/eslint-plugin": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "requires": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/experimental-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.62.0.tgz", + "integrity": "sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==", + "requires": { + "@typescript-eslint/utils": "5.62.0" + } + }, + "@typescript-eslint/parser": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "requires": { + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "requires": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + } + }, + "@typescript-eslint/type-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "requires": { + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==" + }, + "@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "requires": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "requires": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + } + }, + "@webassemblyjs/ast": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "requires": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" + }, + "@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" + }, + "@webassemblyjs/helper-buffer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==" + }, + "@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "requires": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" + }, + "@webassemblyjs/wasm-edit": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "@wry/context": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@wry/context/-/context-0.7.3.tgz", + "integrity": "sha512-Nl8WTesHp89RF803Se9X3IiHjdmLBrIvPMaJkl+rKVJAYyPsz1TEUbu89943HpvujtSJgDUx9W4vZw3K1Mr3sA==", + "requires": { + "tslib": "^2.3.0" + } + }, + "@wry/equality": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@wry/equality/-/equality-0.5.6.tgz", + "integrity": "sha512-D46sfMTngaYlrH+OspKf8mIJETntFnf6Hsjb0V41jAXJ7Bx2kB8Rv8RCUujuVWYttFtHkUNp7g+FwxNQAr6mXA==", + "requires": { + "tslib": "^2.3.0" + } + }, + "@wry/trie": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@wry/trie/-/trie-0.4.3.tgz", + "integrity": "sha512-I6bHwH0fSf6RqQcnnXLJKhkSXG45MFral3GxPaY4uAl0LYDZM+YDVDAiU9bYwjTuysy1S0IeecWtmq1SZA3M1w==", + "requires": { + "tslib": "^2.3.0" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + }, + "abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==" + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "optional": true, + "peer": true + }, + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, + "acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==" + }, + "acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "requires": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" + } + } + }, + "acorn-import-assertions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "requires": {} + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "requires": {} + }, + "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.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", + "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==" + }, + "adjust-sourcemap-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz", + "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==", + "requires": { + "loader-utils": "^2.0.0", + "regex-parser": "^2.2.11" + }, + "dependencies": { + "loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + } + } + }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + } + }, + "agentkeepalive": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.3.0.tgz", + "integrity": "sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==", + "optional": true, + "peer": true, + "requires": { + "debug": "^4.1.0", + "depd": "^2.0.0", + "humanize-ms": "^1.2.1" + } + }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "optional": true, + "peer": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, + "ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "requires": { + "ajv": "^8.0.0" + } + }, + "ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "requires": { + "string-width": "^4.1.0" + } + }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "requires": { + "type-fest": "^0.21.3" + } + }, + "ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==" + }, + "ansi-red": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", + "integrity": "sha512-ewaIr5y+9CUTGFwZfpECUbFlGcC0GCw1oqR9RI6h1gQCd9Aj2GxSckCnPsVJnmfMZbwFYE+leZGASgkWl06Jow==", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "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" + } + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha512-ZyznvL8k/FZeQHr2T6LzcJ/+vBApDnMNZvfVFy3At0knswWd6rJ3/0Hhmpu8oqa6C92npmozs890sX9Dl6q+Qw==" + }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "optional": true, + "peer": true + }, + "are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "optional": true, + "peer": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + } + }, + "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", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "requires": { + "dequal": "^2.0.3" + } + }, + "array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "requires": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + } + }, + "array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" + }, + "array-includes": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", + "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-string": "^1.0.7" + } + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" + }, + "array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + } + }, + "array.prototype.findlastindex": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", + "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.2.1" + } + }, + "array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + } + }, + "array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + } + }, + "array.prototype.reduce": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz", + "integrity": "sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + } + }, + "array.prototype.toreversed": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", + "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + } + }, + "array.prototype.tosorted": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz", + "integrity": "sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==", + "requires": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.1.0", + "es-shim-unscopables": "^1.0.2" + } + }, + "arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "requires": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + } + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "optional": true, + "peer": true + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + }, + "asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "optional": true, + "peer": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "optional": true, + "peer": true + }, + "ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==" + }, + "async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + }, + "async-foreach": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", + "integrity": "sha512-VUeSMD8nEGBWaZK4lizI1sf3yEC7pnAQ/mrI7pC2fBz2s/tq5jWWEngTwaf0Gruu/OoXRGLGg1XFqpYBiGTYJA==", + "optional": true, + "peer": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + }, + "autolinker": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/autolinker/-/autolinker-0.28.1.tgz", + "integrity": "sha512-zQAFO1Dlsn69eXaO6+7YZc+v84aquQKbwpzCE3L0stj56ERn9hutFxPopViLjo9G+rWwjozRhgS5KJ25Xy19cQ==", + "requires": { + "gulp-header": "^1.7.1" + } + }, + "autoprefixer": { + "version": "10.4.14", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz", + "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==", + "requires": { + "browserslist": "^4.21.5", + "caniuse-lite": "^1.0.30001464", + "fraction.js": "^4.2.0", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + } + }, + "available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "requires": { + "possible-typed-array-names": "^1.0.0" + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "optional": true, + "peer": true + }, + "aws4": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", + "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", + "optional": true, + "peer": true + }, + "axe-core": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.2.tgz", + "integrity": "sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g==" + }, + "axobject-query": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", + "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", + "requires": { + "dequal": "^2.0.3" + } + }, + "babel-loader": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.3.0.tgz", + "integrity": "sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q==", + "requires": { + "find-cache-dir": "^3.3.1", + "loader-utils": "^2.0.0", + "make-dir": "^3.1.0", + "schema-utils": "^2.6.5" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "requires": {} + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + } + }, + "babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "requires": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + } + }, + "babel-plugin-named-asset-import": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.8.tgz", + "integrity": "sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q==", + "requires": {} + }, + "babel-plugin-polyfill-corejs2": { + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.8.tgz", + "integrity": "sha512-OtIuQfafSzpo/LhnJaykc0R/MMnuLSSVjVYy9mHArIZ9qTCSZ6TpWCuEKZYVoN//t8HqBNScHrOtCrIK5IaGLg==", + "requires": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.5.0", + "semver": "^6.3.1" + }, + "dependencies": { + "@babel/helper-define-polyfill-provider": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", + "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", + "requires": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "babel-plugin-polyfill-corejs3": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.2.tgz", + "integrity": "sha512-Cid+Jv1BrY9ReW9lIfNlNpsI53N+FN7gE+f73zLAUbr9C52W4gKLWSByx47pfDJsEysojKArqOtOKZSVIIUTuQ==", + "requires": { + "@babel/helper-define-polyfill-provider": "^0.4.1", + "core-js-compat": "^3.31.0" + } + }, + "babel-plugin-polyfill-regenerator": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.5.tgz", + "integrity": "sha512-OJGYZlhLqBh2DDHeqAxWB1XIvr49CxiJ2gIt61/PU55CQK4Z58OzMqjDe1zwQdQk+rBYsRc+1rJmdajM3gimHg==", + "requires": { + "@babel/helper-define-polyfill-provider": "^0.5.0" + }, + "dependencies": { + "@babel/helper-define-polyfill-provider": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", + "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", + "requires": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + } + } + } + }, + "babel-plugin-transform-react-remove-prop-types": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz", + "integrity": "sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==" + }, + "babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "requires": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + } + }, + "babel-preset-react-app": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-react-app/-/babel-preset-react-app-10.0.1.tgz", + "integrity": "sha512-b0D9IZ1WhhCWkrTXyFuIIgqGzSkRIH5D5AmB0bXbzYAB1OBAwHcUeyWW2LorutLWF5btNo/N7r/cIdmvvKJlYg==", + "requires": { + "@babel/core": "^7.16.0", + "@babel/plugin-proposal-class-properties": "^7.16.0", + "@babel/plugin-proposal-decorators": "^7.16.4", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.0", + "@babel/plugin-proposal-numeric-separator": "^7.16.0", + "@babel/plugin-proposal-optional-chaining": "^7.16.0", + "@babel/plugin-proposal-private-methods": "^7.16.0", + "@babel/plugin-transform-flow-strip-types": "^7.16.0", + "@babel/plugin-transform-react-display-name": "^7.16.0", + "@babel/plugin-transform-runtime": "^7.16.4", + "@babel/preset-env": "^7.16.4", + "@babel/preset-react": "^7.16.0", + "@babel/preset-typescript": "^7.16.0", + "@babel/runtime": "^7.16.3", + "babel-plugin-macros": "^3.1.0", + "babel-plugin-transform-react-remove-prop-types": "^0.4.24" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "optional": true, + "peer": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bfj": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/bfj/-/bfj-7.0.2.tgz", + "integrity": "sha512-+e/UqUzwmzJamNF50tBV6tZPTORow7gQ96iFow+8b562OdMpEK0BcJEq2OSPEDmAbSMBQ7PKZ87ubFkgxpYWgw==", + "requires": { + "bluebird": "^3.5.5", + "check-types": "^11.1.1", + "hoopy": "^0.1.4", + "tryer": "^1.0.1" + } + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + } + } + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, + "body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "requires": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "requires": { + "ee-first": "1.1.1" + } + } + } + }, + "bonjour-service": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.1.1.tgz", + "integrity": "sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg==", + "requires": { + "array-flatten": "^2.1.2", + "dns-equal": "^1.0.0", + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "bootstrap": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz", + "integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==", + "requires": {} + }, + "boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dev": true, + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "requires": { + "fill-range": "^7.1.1" + } + }, + "brotli": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz", + "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==", + "requires": { + "base64-js": "^1.1.2" + } + }, + "browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==" + }, + "browserslist": { + "version": "4.22.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz", + "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==", + "requires": { + "caniuse-lite": "^1.0.30001580", + "electron-to-chromium": "^1.4.648", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + } + }, + "bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "requires": { + "node-int64": "^0.4.0" + } + }, + "buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==" + }, + "bwip-js": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/bwip-js/-/bwip-js-3.4.3.tgz", + "integrity": "sha512-x+mQE/bq5V0Nlkn4Jd4cktNlEPH4zeIGSOEQNUtsV/cCJNiBba7u/S9PYR1pmD2WDeeZAIbYTjvGHjBQ21RXvw==" + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==" + }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true + }, + "normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "dev": true + } + } + }, + "call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "requires": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + }, + "camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "requires": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, + "camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==" + }, + "camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "optional": true, + "peer": true, + "requires": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + } + }, + "caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "requires": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "caniuse-lite": { + "version": "1.0.30001587", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001587.tgz", + "integrity": "sha512-HMFNotUmLXn71BQxg8cijvqxnIAofforZOwGsxyXJ0qugTdspUF4sPSJ2vhgprHCB996tIDzEq1ubumPDV8ULA==" + }, + "case-sensitive-paths-webpack-plugin": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", + "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "optional": true, + "peer": true + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==" + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + }, + "check-types": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/check-types/-/check-types-11.2.2.tgz", + "integrity": "sha512-HBiYvXvn9Z70Z88XKjz3AEKd4HJhBXsa3j7xFnITAzoS8+q6eIGi8qDB8FKPBAjtuxjI/zFpwuiCb8oDtKOYrA==" + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "optional": true, + "peer": true + }, + "chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==" + }, + "ci-info": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", + "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==" + }, + "cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==" + }, + "classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + }, + "clean-css": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.2.tgz", + "integrity": "sha512-JVJbM+f3d3Q704rF4bqQ5UUyTtuJ0JRKNbTKVEeujCCBoMdkEi+V+e8oktO9qGQNSvHrFTM6JZRXrUvGR1czww==", + "requires": { + "source-map": "~0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "optional": true, + "peer": true + }, + "cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true + }, + "cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "dev": true, + "requires": { + "restore-cursor": "^4.0.0" + } + }, + "cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==" + }, + "cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dev": true, + "requires": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dev": true, + "requires": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + } + } + }, + "cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==" + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==" + }, + "clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==" + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==" + }, + "coa": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", + "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", + "requires": { + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "coffee-script": { + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz", + "integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==" + }, + "collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==" + }, + "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==" + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "optional": true, + "peer": true + }, + "colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==" + }, + "colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true + }, + "common-path-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==" + }, + "common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==" + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==" + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "concat-with-sourcemaps": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", + "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", + "requires": { + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + } + }, + "confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==" + }, + "connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + } + } + }, + "connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==" + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "optional": true, + "peer": true + }, + "content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "requires": { + "safe-buffer": "5.2.1" + } + }, + "content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" + }, + "convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "core-js": { + "version": "3.31.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.31.1.tgz", + "integrity": "sha512-2sKLtfq1eFST7l7v62zaqXacPc7uG8ZAya8ogijLhTtaKNcpzpB4TMoTw2Si+8GYKRwFPMMtUT0263QFWFfqyQ==" + }, + "core-js-compat": { + "version": "3.36.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.0.tgz", + "integrity": "sha512-iV9Pd/PsgjNWBXeq8XRtWVSgz2tKAfhfvBs7qxYty+RlRd+OCksaWmOnc4JKrTc1cToXL1N0s3l/vwlxPtdElw==", + "requires": { + "browserslist": "^4.22.3" + } + }, + "core-js-pure": { + "version": "3.31.1", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.31.1.tgz", + "integrity": "sha512-w+C62kvWti0EPs4KPMCMVv9DriHSXfQOCQ94bGGBiEW5rrbtt/Rz8n5Krhfw9cpFyzXBjf3DB3QnPdEzGDY4Fw==" + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + } + }, + "cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.1" + } + }, + "cross-fetch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", + "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", + "requires": { + "node-fetch": "^2.6.12" + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" + }, + "css-blank-pseudo": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz", + "integrity": "sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ==", + "requires": { + "postcss-selector-parser": "^6.0.9" + } + }, + "css-box-model": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz", + "integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==", + "requires": { + "tiny-invariant": "^1.0.6" + } + }, + "css-declaration-sorter": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", + "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==", + "requires": {} + }, + "css-has-pseudo": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-3.0.4.tgz", + "integrity": "sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw==", + "requires": { + "postcss-selector-parser": "^6.0.9" + } + }, + "css-loader": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.8.1.tgz", + "integrity": "sha512-xDAXtEVGlD0gJ07iclwWVkLoZOpEvAWaSyf6W18S2pOC//K8+qUDIx8IIT3D+HjnmkJPQeesOPv5aiUaJsCM2g==", + "requires": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.21", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.3", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.3.8" + } + }, + "css-minimizer-webpack-plugin": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz", + "integrity": "sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==", + "requires": { + "cssnano": "^5.0.6", + "jest-worker": "^27.0.2", + "postcss": "^8.3.5", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1" + }, + "dependencies": { + "ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "requires": { + "fast-deep-equal": "^3.1.3" + } + }, + "schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "requires": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "css-prefers-color-scheme": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz", + "integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==", + "requires": {} + }, + "css-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + }, + "dependencies": { + "css-what": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", + "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==" + }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + } + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + }, + "dependencies": { + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + } + } + }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "requires": { + "boolbase": "~1.0.0" + } + } + } + }, + "css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==" + }, + "css-tree": { + "version": "1.0.0-alpha.37", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", + "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", + "requires": { + "mdn-data": "2.0.4", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==" + }, + "css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true + }, + "cssdb": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.6.0.tgz", + "integrity": "sha512-Nna7rph8V0jC6+JBY4Vk4ndErUmfJfV6NJCaZdurL0omggabiy+QB2HCQtu5c/ACLZ0I7REv7A4QyPIoYzZx0w==" + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" + }, + "cssnano": { + "version": "5.1.15", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.15.tgz", + "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==", + "requires": { + "cssnano-preset-default": "^5.2.14", + "lilconfig": "^2.0.3", + "yaml": "^1.10.2" + } + }, + "cssnano-preset-default": { + "version": "5.2.14", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz", + "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==", + "requires": { + "css-declaration-sorter": "^6.3.1", + "cssnano-utils": "^3.1.0", + "postcss-calc": "^8.2.3", + "postcss-colormin": "^5.3.1", + "postcss-convert-values": "^5.1.3", + "postcss-discard-comments": "^5.1.2", + "postcss-discard-duplicates": "^5.1.0", + "postcss-discard-empty": "^5.1.1", + "postcss-discard-overridden": "^5.1.0", + "postcss-merge-longhand": "^5.1.7", + "postcss-merge-rules": "^5.1.4", + "postcss-minify-font-values": "^5.1.0", + "postcss-minify-gradients": "^5.1.1", + "postcss-minify-params": "^5.1.4", + "postcss-minify-selectors": "^5.2.1", + "postcss-normalize-charset": "^5.1.0", + "postcss-normalize-display-values": "^5.1.0", + "postcss-normalize-positions": "^5.1.1", + "postcss-normalize-repeat-style": "^5.1.1", + "postcss-normalize-string": "^5.1.0", + "postcss-normalize-timing-functions": "^5.1.0", + "postcss-normalize-unicode": "^5.1.1", + "postcss-normalize-url": "^5.1.0", + "postcss-normalize-whitespace": "^5.1.1", + "postcss-ordered-values": "^5.1.3", + "postcss-reduce-initial": "^5.1.2", + "postcss-reduce-transforms": "^5.1.0", + "postcss-svgo": "^5.1.0", + "postcss-unique-selectors": "^5.1.1" + } + }, + "cssnano-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", + "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", + "requires": {} + }, + "csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "requires": { + "css-tree": "^1.1.2" + }, + "dependencies": { + "css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "requires": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + } + }, + "mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==" + }, + "cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "requires": { + "cssom": "~0.3.6" + }, + "dependencies": { + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" + } + } + }, + "csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "customize-cra": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/customize-cra/-/customize-cra-1.0.0.tgz", + "integrity": "sha512-DbtaLuy59224U+xCiukkxSq8clq++MOtJ1Et7LED1fLszWe88EoblEYFBJ895sB1mC6B4uu3xPT/IjClELhMbA==", + "requires": { + "lodash.flow": "^3.5.0" + } + }, + "d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "requires": { + "internmap": "1 - 2" + } + }, + "d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==" + }, + "d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "requires": { + "delaunator": "5" + } + }, + "d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==" + }, + "d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "requires": { + "d3-color": "1 - 3" + } + }, + "d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==" + }, + "d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "requires": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + } + }, + "d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "requires": { + "d3-path": "^3.1.0" + } + }, + "d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "requires": { + "d3-array": "2 - 3" + } + }, + "d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "requires": { + "d3-time": "1 - 3" + } + }, + "damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "optional": true, + "peer": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "data-urls": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "requires": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + } + }, + "data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "requires": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + } + }, + "data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "requires": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + } + }, + "data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "requires": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + } + }, + "date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "devOptional": true, + "requires": { + "@babel/runtime": "^7.21.0" + } + }, + "dayjs": { + "version": "1.11.11", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz", + "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "optional": true, + "peer": true + }, + "decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "optional": true, + "peer": true, + "requires": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "dependencies": { + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "optional": true, + "peer": true + } + } + }, + "decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==" + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + }, + "deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==" + }, + "default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "requires": { + "execa": "^5.0.0" + } + }, + "defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "requires": { + "clone": "^1.0.2" + }, + "dependencies": { + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==" + } + } + }, + "defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true + }, + "define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "requires": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + } + }, + "define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==" + }, + "define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "requires": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "delaunator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", + "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", + "requires": { + "robust-predicates": "^3.0.2" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "optional": true, + "peer": true + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==" + }, + "destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==", + "dev": true + }, + "detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" + }, + "detect-port-alt": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", + "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", + "requires": { + "address": "^1.0.1", + "debug": "^2.6.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "dfa": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz", + "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==" + }, + "diacritics-map": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/diacritics-map/-/diacritics-map-0.1.0.tgz", + "integrity": "sha512-3omnDTYrGigU0i4cJjvaKwD52B8aoqyX/NEIkukFFkogBemsIbhSa1O414fpTp5nuszJG6lvQ5vBvDVNCbSsaQ==" + }, + "didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" + }, + "diff-sequences": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.6.2.tgz", + "integrity": "sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==", + "dev": true + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "requires": { + "path-type": "^4.0.0" + } + }, + "dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" + }, + "dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==" + }, + "dns-packet": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.0.tgz", + "integrity": "sha512-rza3UH1LwdHh9qyPXp8lkwpjSNk/AMD3dPytUoRoqnypDUhY0xvbdmVhWOfxO68frEfV9BU8V12Ez7ZsHGZpCQ==", + "requires": { + "@leichtgewicht/ip-codec": "^2.0.1" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "requires": { + "esutils": "^2.0.2" + } + }, + "dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true + }, + "dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "requires": { + "utila": "~0.4" + } + }, + "dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "requires": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, + "dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "requires": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + } + }, + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" + }, + "domexception": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "requires": { + "webidl-conversions": "^5.0.0" + }, + "dependencies": { + "webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==" + } + } + }, + "domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "requires": { + "domelementtype": "^2.3.0" + } + }, + "domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "requires": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + } + }, + "dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "requires": { + "is-obj": "^2.0.0" + } + }, + "dotenv": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", + "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==" + }, + "dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==" + }, + "duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" + }, + "duplexer3": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", + "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==", + "dev": true + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "optional": true, + "peer": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "ejs": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz", + "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==", + "requires": { + "jake": "^10.8.5" + } + }, + "electron-to-chromium": { + "version": "1.4.668", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.668.tgz", + "integrity": "sha512-ZOBocMYCehr9W31+GpMclR+KBaDZOoAEabLdhpZ8oU1JFDwIaFY0UDbpXVEUFc0BIP2O2Qn3rkfCjQmMR4T/bQ==" + }, + "emittery": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", + "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==" + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + }, + "encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "peer": true, + "requires": { + "iconv-lite": "^0.6.2" + } + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "enhanced-resolve": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + } + }, + "entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==" + }, + "env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "optional": true, + "peer": true + }, + "err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "optional": true, + "peer": true + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "requires": { + "stackframe": "^1.3.4" + } + }, + "es-abstract": { + "version": "1.23.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.2.tgz", + "integrity": "sha512-60s3Xv2T2p1ICykc7c+DNDPLDMm9t4QxCOUU0K9JxiLjM3C1zB9YVdN7tjxrFd4+AkZ8CdX1ovUga4P2+1e+/w==", + "requires": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.5", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + } + }, + "es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" + }, + "es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "requires": { + "get-intrinsic": "^1.2.4" + } + }, + "es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" + }, + "es-iterator-helpers": { + "version": "1.0.18", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.18.tgz", + "integrity": "sha512-scxAJaewsahbqTYrGKJihhViaM6DDZDDoucfvzNbK0pOren1g/daDQ3IAhzn+1G14rBG7w+i5N+qul60++zlKA==", + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.2", + "safe-array-concat": "^1.1.2" + } + }, + "es-module-lexer": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.0.tgz", + "integrity": "sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==" + }, + "es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "requires": { + "es-errors": "^1.3.0" + } + }, + "es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "requires": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + } + }, + "es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "requires": { + "hasown": "^2.0.0" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "requires": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + }, + "escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" + }, + "escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "requires": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "source-map": "~0.6.1" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true + } + } + }, + "eslint": { + "version": "8.45.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.45.0.tgz", + "integrity": "sha512-pd8KSxiQpdYRfYa9Wufvdoct3ZPQQuVuU5O6scNgMuOMYuxvH0IGaYK0wUFjo4UYYQQCUndlXiMbnxopwvvTiw==", + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.1.0", + "@eslint/js": "8.44.0", + "@humanwhocodes/config-array": "^0.11.10", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.0", + "eslint-visitor-keys": "^3.4.1", + "espree": "^9.6.0", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "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" + } + }, + "eslint-scope": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.1.tgz", + "integrity": "sha512-CvefSOsDdaYYvxChovdrPo/ZGt8d5lrJWleAc1diXRKhHGiTYEI26cvo8Kle/wGnsizoCJjK73FMg1/IkIwiNA==", + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "requires": { + "is-glob": "^4.0.3" + } + }, + "globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "requires": { + "type-fest": "^0.20.2" + } + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "requires": { + "argparse": "^2.0.1" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "requires": { + "p-locate": "^5.0.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "requires": { + "p-limit": "^3.0.2" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" + } + } + }, + "eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "requires": {} + }, + "eslint-config-react-app": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-7.0.1.tgz", + "integrity": "sha512-K6rNzvkIeHaTd8m/QEh1Zko0KI7BACWkkneSs6s9cKZC/J27X3eZR6Upt1jkmZ/4FK+XUOPPxMEN7+lbUXfSlA==", + "requires": { + "@babel/core": "^7.16.0", + "@babel/eslint-parser": "^7.16.3", + "@rushstack/eslint-patch": "^1.1.0", + "@typescript-eslint/eslint-plugin": "^5.5.0", + "@typescript-eslint/parser": "^5.5.0", + "babel-preset-react-app": "^10.0.1", + "confusing-browser-globals": "^1.0.11", + "eslint-plugin-flowtype": "^8.0.3", + "eslint-plugin-import": "^2.25.3", + "eslint-plugin-jest": "^25.3.0", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-react": "^7.27.1", + "eslint-plugin-react-hooks": "^4.3.0", + "eslint-plugin-testing-library": "^5.0.1" + } + }, + "eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "requires": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "eslint-module-utils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", + "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "requires": { + "debug": "^3.2.7" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "eslint-plugin-flowtype": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-8.0.3.tgz", + "integrity": "sha512-dX8l6qUL6O+fYPtpNRideCFSpmWOUVx5QcaGLVqe/vlDiBSe4vYljDWDETwnyFzpl7By/WVIu6rcrniCgH9BqQ==", + "requires": { + "lodash": "^4.17.21", + "string-natural-compare": "^3.0.1" + } + }, + "eslint-plugin-import": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "requires": { + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "requires": { + "esutils": "^2.0.2" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "eslint-plugin-jest": { + "version": "25.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-25.7.0.tgz", + "integrity": "sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==", + "requires": { + "@typescript-eslint/experimental-utils": "^5.0.0" + } + }, + "eslint-plugin-jsx-a11y": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz", + "integrity": "sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==", + "requires": { + "@babel/runtime": "^7.20.7", + "aria-query": "^5.1.3", + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", + "ast-types-flow": "^0.0.7", + "axe-core": "^4.6.2", + "axobject-query": "^3.1.1", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "has": "^1.0.3", + "jsx-ast-utils": "^3.3.3", + "language-tags": "=1.0.5", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "eslint-plugin-prettier": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", + "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.6" + } + }, + "eslint-plugin-react": { + "version": "7.34.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz", + "integrity": "sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==", + "requires": { + "array-includes": "^3.1.7", + "array.prototype.findlast": "^1.2.4", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.toreversed": "^1.1.2", + "array.prototype.tosorted": "^1.1.3", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.17", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.7", + "object.fromentries": "^2.0.7", + "object.hasown": "^1.1.3", + "object.values": "^1.1.7", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.10" + }, + "dependencies": { + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "requires": { + "esutils": "^2.0.2" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + }, + "resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "requires": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "eslint-plugin-react-hooks": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", + "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "requires": {} + }, + "eslint-plugin-testing-library": { + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.11.0.tgz", + "integrity": "sha512-ELY7Gefo+61OfXKlQeXNIDVVLPcvKTeiQOoMZG9TeuWa7Ln4dUNRv8JdRWBQI9Mbb427XGlVB1aa1QPZxBJM8Q==", + "requires": { + "@typescript-eslint/utils": "^5.58.0" + } + }, + "eslint-plugin-tsdoc": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.17.tgz", + "integrity": "sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA==", + "dev": true, + "requires": { + "@microsoft/tsdoc": "0.14.2", + "@microsoft/tsdoc-config": "0.16.2" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-visitor-keys": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", + "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==" + }, + "eslint-webpack-plugin": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-3.2.0.tgz", + "integrity": "sha512-avrKcGncpPbPSUHX6B3stNGzkKFto3eL+DKM4+VyMrVnhPc3vRczVlCq3uhuFOdRvDHTVXuzwk1ZKUrqDQHQ9w==", + "requires": { + "@types/eslint": "^7.29.0 || ^8.4.1", + "jest-worker": "^28.0.2", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0" + }, + "dependencies": { + "ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "requires": { + "fast-deep-equal": "^3.1.3" + } + }, + "jest-worker": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.1.3.tgz", + "integrity": "sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g==", + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + } + }, + "schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "requires": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + } + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "requires": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + }, + "estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==" + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" + }, + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==" + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha512-AFASGfIlnIbkKPQwX1yHaDjFvh/1gyKJODme52V6IORh69uEYgZp0o9C+qsIGNVEiuuhQU0CSSl++Rlegg1qvA==", + "requires": { + "fill-range": "^2.1.0" + }, + "dependencies": { + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha512-QUzH43Gfb9+5yckcrSA0VBDwEtDUchrk4F6tfJZQuNzDJbEDB9cZNzSfXGQ1jqmdDY/kl41lUOWM9syA8z8jlg==", + "requires": { + "kind-of": "^3.0.2" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", + "requires": { + "isarray": "1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "expect": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", + "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "requires": { + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" + } + }, + "express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "requires": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "requires": { + "ee-first": "1.1.1" + } + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "optional": true, + "peer": true + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "optional": true, + "peer": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "fast-glob": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", + "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==", + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + }, + "fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "requires": { + "reusify": "^1.0.4" + } + }, + "faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "requires": { + "bser": "2.1.1" + } + }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "requires": { + "escape-string-regexp": "^1.0.5" + }, + "dependencies": { + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + } + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "requires": { + "flat-cache": "^3.0.4" + } + }, + "file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "dependencies": { + "loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + } + } + }, + "filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "requires": { + "minimatch": "^5.0.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "filesize": { + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", + "integrity": "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==" + }, + "fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + } + } + }, + "find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + } + }, + "find-node-modules": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/find-node-modules/-/find-node-modules-2.1.3.tgz", + "integrity": "sha512-UC2I2+nx1ZuOBclWVNdcnbDR5dlrOdVb7xNjmT/lHE+LsgztWks3dG7boJ37yTS/venXw84B/mAW9uHVoC5QRg==", + "dev": true, + "requires": { + "findup-sync": "^4.0.0", + "merge": "^2.1.1" + } + }, + "find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "findup-sync": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-4.0.0.tgz", + "integrity": "sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^4.0.2", + "resolve-dir": "^1.0.1" + } + }, + "flag-icons": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/flag-icons/-/flag-icons-6.7.0.tgz", + "integrity": "sha512-+KXrrrXN2jiETFxisFl+3f83Bq7tj5nuIWnbv9fX59k05lvldEXRCOffybb5hAIjMWt4nmG0E8OfKt7Flm99Eg==" + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" + }, + "follow-redirects": { + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==" + }, + "fontkit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-2.0.2.tgz", + "integrity": "sha512-jc4k5Yr8iov8QfS6u8w2CnHWVmbOGtdBtOXMze5Y+QD966Rx6PEVWXSEGwXlsDlKtu1G12cJjcsybnqhSk/+LA==", + "requires": { + "@swc/helpers": "^0.4.2", + "brotli": "^1.3.2", + "clone": "^2.1.2", + "dfa": "^1.2.0", + "fast-deep-equal": "^3.1.3", + "restructure": "^3.0.0", + "tiny-inflate": "^1.0.3", + "unicode-properties": "^1.4.0", + "unicode-trie": "^2.0.0" + } + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "requires": { + "is-callable": "^1.1.3" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "optional": true, + "peer": true + }, + "fork-ts-checker-webpack-plugin": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz", + "integrity": "sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==", + "requires": { + "@babel/code-frame": "^7.8.3", + "@types/json-schema": "^7.0.5", + "chalk": "^4.1.0", + "chokidar": "^3.4.2", + "cosmiconfig": "^6.0.0", + "deepmerge": "^4.2.2", + "fs-extra": "^9.0.0", + "glob": "^7.1.6", + "memfs": "^3.1.2", + "minimatch": "^3.0.4", + "schema-utils": "2.7.0", + "semver": "^7.3.2", + "tapable": "^1.0.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "requires": {} + }, + "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" + } + }, + "cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + } + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "requires": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + } + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" + } + } + }, + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + }, + "fraction.js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", + "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "optional": true, + "peer": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "fs-monkey": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.4.tgz", + "integrity": "sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ==" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "optional": true + }, + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" + }, + "function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + } + }, + "functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" + }, + "gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "optional": true, + "peer": true, + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + } + }, + "gaze": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", + "optional": true, + "peer": true, + "requires": { + "globule": "^1.0.0" + } + }, + "generic-names": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/generic-names/-/generic-names-4.0.0.tgz", + "integrity": "sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A==", + "dev": true, + "requires": { + "loader-utils": "^3.2.0" + } + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + "get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", + "dev": true + }, + "get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "requires": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + } + }, + "get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" + }, + "get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==" + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw==", + "optional": true, + "peer": true + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" + }, + "get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "requires": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + } + }, + "get-tsconfig": { + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz", + "integrity": "sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==", + "dev": true, + "requires": { + "resolve-pkg-maps": "^1.0.0" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "optional": true, + "peer": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "requires": { + "is-glob": "^4.0.1" + } + }, + "glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + }, + "global-dirs": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "dev": true, + "requires": { + "ini": "2.0.0" + }, + "dependencies": { + "ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true + } + } + }, + "global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "requires": { + "global-prefix": "^3.0.0" + } + }, + "global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "requires": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "dependencies": { + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + }, + "globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "requires": { + "define-properties": "^1.1.3" + } + }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, + "globule": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.4.tgz", + "integrity": "sha512-OPTIfhMBh7JbBYDpa5b+Q5ptmMWKwcNcFSR/0c6t8V4f3ZAVBEsKNY37QdVqmLRYSMhOUGYrY0QhSoEpzGr/Eg==", + "optional": true, + "peer": true, + "requires": { + "glob": "~7.1.1", + "lodash": "^4.17.21", + "minimatch": "~3.0.2" + }, + "dependencies": { + "glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "optional": true, + "peer": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", + "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", + "optional": true, + "peer": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "requires": { + "get-intrinsic": "^1.1.3" + } + }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "dependencies": { + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + } + } + }, + "graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" + }, + "graphql": { + "version": "16.9.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.9.0.tgz", + "integrity": "sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==" + }, + "graphql-tag": { + "version": "2.12.6", + "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz", + "integrity": "sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==", + "requires": { + "tslib": "^2.1.0" + } + }, + "graphql-ws": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.16.0.tgz", + "integrity": "sha512-Ju2RCU2dQMgSKtArPbEtsK5gNLnsQyTNIo/T7cZNp96niC1x0KdJNZV0TIoilceBPQwfb5itrGl8pkFeOUMl4A==", + "requires": {} + }, + "gray-matter": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-2.1.1.tgz", + "integrity": "sha512-vbmvP1Fe/fxuT2QuLVcqb2BfK7upGhhbLIt9/owWEvPYrZZEkelLcq2HqzxosV+PQ67dUFLaAeNpH7C4hhICAA==", + "requires": { + "ansi-red": "^0.1.1", + "coffee-script": "^1.12.4", + "extend-shallow": "^2.0.1", + "js-yaml": "^3.8.1", + "toml": "^2.3.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==" + } + } + }, + "gulp-header": { + "version": "1.8.12", + "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.12.tgz", + "integrity": "sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ==", + "requires": { + "concat-with-sourcemaps": "*", + "lodash.template": "^4.4.0", + "through2": "^2.0.0" + } + }, + "gzip-size": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", + "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "requires": { + "duplexer": "^0.1.2" + } + }, + "handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "optional": true, + "peer": true + }, + "har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "optional": true, + "peer": true, + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "optional": true, + "peer": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "optional": true, + "peer": true + } + } + }, + "hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "optional": true, + "peer": true + }, + "harmony-reflect": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", + "integrity": "sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==" + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "requires": { + "es-define-property": "^1.0.0" + } + }, + "has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==" + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "requires": { + "has-symbols": "^1.0.3" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "optional": true, + "peer": true + }, + "has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "dev": true + }, + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "requires": { + "function-bind": "^1.1.2" + } + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" + }, + "history": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/history/-/history-5.3.0.tgz", + "integrity": "sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==", + "requires": { + "@babel/runtime": "^7.7.6" + } + }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + } + } + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hoopy": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", + "integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==" + }, + "hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "optional": true, + "peer": true, + "requires": { + "lru-cache": "^6.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "optional": true, + "peer": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true, + "peer": true + } + } + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "requires": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "html-encoding-sniffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "requires": { + "whatwg-encoding": "^1.0.5" + } + }, + "html-entities": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz", + "integrity": "sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==" + }, + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==" + }, + "html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "requires": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "dependencies": { + "commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==" + } + } + }, + "html-parse-stringify": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", + "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==", + "requires": { + "void-elements": "3.1.0" + } + }, + "html-webpack-plugin": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.3.tgz", + "integrity": "sha512-6YrDKTuqaP/TquFH7h4srYWsZx+x6k6+FbsTm0ziCwGHDP78Unr1r9F/H4+sGmMbX08GQcJ+K64x55b+7VM/jg==", + "requires": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + } + }, + "htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "requires": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, + "http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "devOptional": true + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==" + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "dependencies": { + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" + } + } + }, + "http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, + "http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "requires": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "dependencies": { + "is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==" + } + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "optional": true, + "peer": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" + }, + "humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "optional": true, + "peer": true, + "requires": { + "ms": "^2.0.0" + } + }, + "husky": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", + "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", + "dev": true + }, + "i18next": { + "version": "21.10.0", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-21.10.0.tgz", + "integrity": "sha512-YeuIBmFsGjUfO3qBmMOc0rQaun4mIpGKET5WDwvu8lU7gvwpcariZLNtL0Fzj+zazcHUrlXHiptcFhBMFaxzfg==", + "requires": { + "@babel/runtime": "^7.17.2" + } + }, + "i18next-browser-languagedetector": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.0.0.tgz", + "integrity": "sha512-zhXdJXTTCoG39QsrOCiOabnWj2jecouOqbchu3EfhtSHxIB5Uugnm9JaizenOy39h7ne3+fLikIjeW88+rgszw==", + "requires": { + "@babel/runtime": "^7.23.2" + } + }, + "i18next-http-backend": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-2.5.2.tgz", + "integrity": "sha512-+K8HbDfrvc1/2X8jpb7RLhI9ZxBDpx3xogYkQwGKlWAUXLSEGXzgdt3EcUjLlBCdMwdQY+K+EUF6oh8oB6rwHw==", + "requires": { + "cross-fetch": "4.0.0" + } + }, + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "requires": {} + }, + "idb": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", + "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==" + }, + "identity-obj-proxy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz", + "integrity": "sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA==", + "requires": { + "harmony-reflect": "^1.4.6" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==" + }, + "immer": { + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==" + }, + "immutable": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz", + "integrity": "sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==", + "devOptional": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A==", + "dev": true + }, + "import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==" + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "devOptional": true + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "optional": true, + "peer": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "inquirer": { + "version": "8.2.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", + "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^6.0.1" + }, + "dependencies": { + "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" + } + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } + } + }, + "internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "requires": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + } + }, + "internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==" + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "^1.0.0" + } + }, + "ip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", + "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==", + "optional": true, + "peer": true + }, + "ipaddr.js": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", + "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==" + }, + "is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "requires": { + "has-bigints": "^1.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==" + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + }, + "dependencies": { + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + } + } + }, + "is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "requires": { + "hasown": "^2.0.0" + } + }, + "is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "requires": { + "is-typed-array": "^1.1.13" + } + }, + "is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" + }, + "is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==" + }, + "is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "dev": true, + "requires": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + } + }, + "is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==" + }, + "is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "optional": true, + "peer": true + }, + "is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==" + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==" + }, + "is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==" + }, + "is-npm": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", + "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==" + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "optional": true, + "peer": true + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + } + }, + "is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" + }, + "is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==" + }, + "is-root": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", + "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==" + }, + "is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==" + }, + "is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "requires": { + "call-bind": "^1.0.7" + } + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "requires": { + "has-symbols": "^1.0.2" + } + }, + "is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "requires": { + "which-typed-array": "^1.1.14" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==" + }, + "is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==" + }, + "is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-weakset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", + "requires": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + } + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "requires": { + "is-docker": "^2.0.0" + } + }, + "is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", + "dev": true + }, + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "optional": true, + "peer": true + }, + "istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==" + }, + "istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + } + }, + "istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "istanbul-reports": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", + "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", + "requires": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, + "iterator.prototype": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", + "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "requires": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + } + }, + "jake": { + "version": "10.8.7", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", + "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==", + "requires": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "dependencies": { + "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" + } + } + } + }, + "jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", + "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", + "requires": { + "@jest/core": "^27.5.1", + "import-local": "^3.0.2", + "jest-cli": "^27.5.1" + } + }, + "jest-changed-files": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", + "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", + "requires": { + "@jest/types": "^27.5.1", + "execa": "^5.0.0", + "throat": "^6.0.1" + } + }, + "jest-circus": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", + "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", + "requires": { + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^0.7.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3", + "throat": "^6.0.1" + }, + "dependencies": { + "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" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } + } + }, + "jest-cli": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", + "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", + "requires": { + "@jest/core": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "import-local": "^3.0.2", + "jest-config": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "prompts": "^2.0.1", + "yargs": "^16.2.0" + }, + "dependencies": { + "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" + } + } + } + }, + "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": { + "babel-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", + "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", + "requires": { + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + } + }, + "babel-plugin-jest-hoist": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", + "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", + "requires": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-preset-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", + "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", + "requires": { + "babel-plugin-jest-hoist": "^27.5.1", + "babel-preset-current-node-syntax": "^1.0.0" + } + }, + "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" + } + }, + "jest-environment-node": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", + "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", + "requires": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } + } + }, + "jest-diff": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.6.2.tgz", + "integrity": "sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^26.6.2", + "jest-get-type": "^26.3.0", + "pretty-format": "^26.6.2" + }, + "dependencies": { + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "jest-get-type": { + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.3.0.tgz", + "integrity": "sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==", + "dev": true + } + } + }, + "jest-docblock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", + "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", + "requires": { + "detect-newline": "^3.0.0" + }, + "dependencies": { + "detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==" + } + } + }, + "jest-each": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", + "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", + "requires": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "dependencies": { + "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" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } + } + }, + "jest-environment-jsdom": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", + "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", + "requires": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1", + "jsdom": "^16.6.0" + } + }, + "jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==" + }, + "jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "requires": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + } + }, + "jest-jasmine2": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", + "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", + "requires": { + "@jest/environment": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "throat": "^6.0.1" + }, + "dependencies": { + "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" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } + } + }, + "jest-leak-detector": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", + "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", + "requires": { + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } + } + }, + "jest-localstorage-mock": { + "version": "2.4.26", + "resolved": "https://registry.npmjs.org/jest-localstorage-mock/-/jest-localstorage-mock-2.4.26.tgz", + "integrity": "sha512-owAJrYnjulVlMIXOYQIPRCCn3MmqI3GzgfZCXdD3/pmwrIvFMXcKVWZ+aMc44IzaASapg0Z4SEFxR+v5qxDA2w==", + "dev": true + }, + "jest-location-mock": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jest-location-mock/-/jest-location-mock-2.0.0.tgz", + "integrity": "sha512-loakfclgY/y65/2i4s0fcdlZY3hRPfwNnmzRsGFQYQryiaow2DEIGTLXIPI8cAO1Is36xsVLVkIzgvhQ+FXHdw==", + "dev": true, + "requires": { + "@jedmao/location": "^3.0.0", + "jest-diff": "^29.6.4" + }, + "dependencies": { + "@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "requires": { + "@sinclair/typebox": "^0.27.8" + } + }, + "@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true + }, + "jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + } + }, + "jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true + }, + "pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "requires": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + } + } + }, + "jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "dependencies": { + "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" + } + }, + "diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==" + }, + "jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } + } + }, + "jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "dependencies": { + "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" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } + } + }, + "jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*" + } + }, + "jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "requires": {} + }, + "jest-preview": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/jest-preview/-/jest-preview-0.3.1.tgz", + "integrity": "sha512-gRR4shnXFSh8tdNaIncJC98d1zXD7w7LA52HQC0bu0DsPb+FXVEg+NQh9GTbO+n6/SCgcZNQAVt4MeCfsIkBPA==", + "dev": true, + "requires": { + "@svgr/core": "^6.2.1", + "camelcase": "^6.3.0", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "commander": "^9.2.0", + "connect": "^3.7.0", + "find-node-modules": "^2.1.3", + "open": "^8.4.0", + "postcss-import": "^14.1.0", + "postcss-load-config": "^4.0.1", + "sirv": "^2.0.2", + "slash": "^3.0.0", + "string-hash": "^1.1.3", + "update-notifier": "^5.1.0", + "ws": "^8.5.0" + }, + "dependencies": { + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + } + } + }, + "jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==" + }, + "jest-resolve": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", + "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", + "requires": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", + "slash": "^3.0.0" + }, + "dependencies": { + "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" + } + } + } + }, + "jest-resolve-dependencies": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", + "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", + "requires": { + "@jest/types": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-snapshot": "^27.5.1" + } + }, + "jest-runner": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", + "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", + "requires": { + "@jest/console": "^27.5.1", + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-leak-detector": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "source-map-support": "^0.5.6", + "throat": "^6.0.1" + }, + "dependencies": { + "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" + } + }, + "jest-environment-node": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", + "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", + "requires": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + } + } + } + }, + "jest-runtime": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", + "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", + "requires": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/globals": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "execa": "^5.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "dependencies": { + "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" + } + } + } + }, + "jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "requires": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + } + }, + "jest-snapshot": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", + "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", + "requires": { + "@babel/core": "^7.7.2", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/traverse": "^7.7.2", + "@babel/types": "^7.0.0", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__traverse": "^7.0.4", + "@types/prettier": "^2.1.5", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^27.5.1", + "semver": "^7.3.2" + }, + "dependencies": { + "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" + } + }, + "diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==" + }, + "jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "dependencies": { + "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" + } + } + } + }, + "jest-validate": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", + "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", + "requires": { + "@jest/types": "^27.5.1", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "leven": "^3.1.0", + "pretty-format": "^27.5.1" + }, + "dependencies": { + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" + }, + "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" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } + } + }, + "jest-watch-typeahead": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-1.1.0.tgz", + "integrity": "sha512-Va5nLSJTN7YFtC2jd+7wsoe1pNe5K4ShLux/E5iHEwlB9AxaxmggY7to9KUqKojhaJw3aXqt5WAb4jGPOolpEw==", + "requires": { + "ansi-escapes": "^4.3.1", + "chalk": "^4.0.0", + "jest-regex-util": "^28.0.0", + "jest-watcher": "^28.0.0", + "slash": "^4.0.0", + "string-length": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "dependencies": { + "@jest/console": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.3.tgz", + "integrity": "sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==", + "requires": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^28.1.3", + "jest-util": "^28.1.3", + "slash": "^3.0.0" + }, + "dependencies": { + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + } + } + }, + "@jest/test-result": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-28.1.3.tgz", + "integrity": "sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg==", + "requires": { + "@jest/console": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/types": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", + "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", + "requires": { + "@jest/schemas": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "17.0.24", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", + "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "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" + } + }, + "emittery": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", + "integrity": "sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==" + }, + "jest-message-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", + "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^28.1.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^28.1.3", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "dependencies": { + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + } + } + }, + "jest-regex-util": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", + "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==" + }, + "jest-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", + "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", + "requires": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "jest-watcher": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-28.1.3.tgz", + "integrity": "sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g==", + "requires": { + "@jest/test-result": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.10.2", + "jest-util": "^28.1.3", + "string-length": "^4.0.1" + }, + "dependencies": { + "string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "requires": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "pretty-format": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", + "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "requires": { + "@jest/schemas": "^28.1.3", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + } + } + }, + "slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==" + }, + "string-length": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-5.0.1.tgz", + "integrity": "sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==", + "requires": { + "char-regex": "^2.0.0", + "strip-ansi": "^7.0.1" + }, + "dependencies": { + "char-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-2.0.1.tgz", + "integrity": "sha512-oSvEeo6ZUD7NepqAat3RqoucZ5SeqLJgOvVIwkafu6IP3V0pO38s/ypdVUmDDK6qIIHNlYHJAKX9E7R7HoKElw==" + } + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "requires": { + "ansi-regex": "^6.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" + } + } + } + } + }, + "jest-watcher": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", + "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", + "requires": { + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "jest-util": "^27.5.1", + "string-length": "^4.0.1" + }, + "dependencies": { + "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" + } + } + } + }, + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jiti": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.1.tgz", + "integrity": "sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg==" + }, + "jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", + "dev": true + }, + "js-base64": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", + "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==", + "optional": true, + "peer": true + }, + "js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==" + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "optional": true, + "peer": true + }, + "jsdom": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "requires": { + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" + }, + "dependencies": { + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + } + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "optional": true, + "peer": true + }, + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==" + }, + "jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "optional": true, + "peer": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + } + }, + "jsx-ast-utils": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.4.tgz", + "integrity": "sha512-fX2TVdCViod6HwKEtSWGHs57oFhVfCMwieb9PuRDgjDPh5XeqJiHFFFJCHxU5cnTc3Bu/GRL+kPiFmw8XWOfKw==", + "requires": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + } + }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "requires": { + "json-buffer": "3.0.0" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==" + }, + "klona": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==" + }, + "language-subtag-registry": { + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", + "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==" + }, + "language-tags": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", + "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", + "requires": { + "language-subtag-registry": "~0.3.2" + } + }, + "latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "dev": true, + "requires": { + "package-json": "^6.3.0" + } + }, + "launch-editor": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz", + "integrity": "sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==", + "requires": { + "picocolors": "^1.0.0", + "shell-quote": "^1.7.3" + } + }, + "lazy-cache": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz", + "integrity": "sha512-7vp2Acd2+Kz4XkzxGxaB1FWOi8KjWIWsgdfD5MCb86DWvlLqhRPM+d6Pro3iNEL5VT9mstz5hKAlcd+QR6H3aA==", + "requires": { + "set-getter": "^0.1.0" + } + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==" + }, + "lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "peer": true, + "requires": { + "uc.micro": "^2.0.0" + } + }, + "lint-staged": { + "version": "15.2.7", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.7.tgz", + "integrity": "sha512-+FdVbbCZ+yoh7E/RosSdqKJyUM2OEjTciH0TFNkawKgvFp1zbGlEC39RADg+xKBG1R4mhoH2j85myBQZ5wR+lw==", + "dev": true, + "requires": { + "chalk": "~5.3.0", + "commander": "~12.1.0", + "debug": "~4.3.4", + "execa": "~8.0.1", + "lilconfig": "~3.1.1", + "listr2": "~8.2.1", + "micromatch": "~4.0.7", + "pidtree": "~0.6.0", + "string-argv": "~0.3.2", + "yaml": "~2.4.2" + }, + "dependencies": { + "chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true + }, + "commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true + }, + "execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + } + }, + "get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true + }, + "human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true + }, + "is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true + }, + "lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "dev": true + }, + "mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true + }, + "npm-run-path": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.2.0.tgz", + "integrity": "sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==", + "dev": true, + "requires": { + "path-key": "^4.0.0" + } + }, + "onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "requires": { + "mimic-fn": "^4.0.0" + } + }, + "path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true + }, + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + }, + "strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true + }, + "yaml": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", + "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", + "dev": true + } + } + }, + "list-item": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/list-item/-/list-item-1.1.1.tgz", + "integrity": "sha512-S3D0WZ4J6hyM8o5SNKWaMYB1ALSacPZ2nHGEuCjmHZ+dc03gFeNZoNDcqfcnO4vDhTZmNrqrpYZCdXsRh22bzw==", + "requires": { + "expand-range": "^1.8.1", + "extend-shallow": "^2.0.1", + "is-number": "^2.1.0", + "repeat-string": "^1.5.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==" + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha512-QUzH43Gfb9+5yckcrSA0VBDwEtDUchrk4F6tfJZQuNzDJbEDB9cZNzSfXGQ1jqmdDY/kl41lUOWM9syA8z8jlg==", + "requires": { + "kind-of": "^3.0.2" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "listr2": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.1.tgz", + "integrity": "sha512-irTfvpib/rNiD637xeevjO2l3Z5loZmuaRi0L0YE5LfijwVY96oyVn0DFD3o/teAok7nfobMG1THvvcHh/BP6g==", + "dev": true, + "requires": { + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.0.0", + "rfdc": "^1.3.1", + "wrap-ansi": "^9.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true + }, + "emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true + }, + "string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dev": true, + "requires": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "requires": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + } + } + } + }, + "loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==" + }, + "loader-utils": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", + "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==" + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==" + }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "dev": true + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, + "lodash.flow": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz", + "integrity": "sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw==" + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" + }, + "lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "requires": { + "lodash._reinterpolate": "^3.0.0" + } + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" + }, + "log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "requires": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "dependencies": { + "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" + } + } + } + }, + "log-update": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", + "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", + "dev": true, + "requires": { + "ansi-escapes": "^6.2.0", + "cli-cursor": "^4.0.0", + "slice-ansi": "^7.0.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "dependencies": { + "ansi-escapes": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", + "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", + "dev": true + }, + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true + }, + "emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "dev": true, + "requires": { + "get-east-asian-width": "^1.0.0" + } + }, + "slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "dev": true, + "requires": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + } + }, + "string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dev": true, + "requires": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "requires": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + } + } + } + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "requires": { + "tslib": "^2.0.3" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "^3.0.2" + } + }, + "lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "peer": true + }, + "lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true + }, + "magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "requires": { + "sourcemap-codec": "^1.4.8" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "requires": { + "tmpl": "1.0.5" + } + }, + "map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "optional": true, + "peer": true + }, + "markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "peer": true, + "requires": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "peer": true + } + } + }, + "markdown-link": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/markdown-link/-/markdown-link-0.1.1.tgz", + "integrity": "sha512-TurLymbyLyo+kAUUAV9ggR9EPcDjP/ctlv9QAFiqUH7c+t6FlsbivPo9OKTU8xdOx9oNd2drW/Fi5RRElQbUqA==" + }, + "markdown-toc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/markdown-toc/-/markdown-toc-1.2.0.tgz", + "integrity": "sha512-eOsq7EGd3asV0oBfmyqngeEIhrbkc7XVP63OwcJBIhH2EpG2PzFcbZdhy1jutXSlRBBVMNXHvMtSr5LAxSUvUg==", + "requires": { + "concat-stream": "^1.5.2", + "diacritics-map": "^0.1.0", + "gray-matter": "^2.1.0", + "lazy-cache": "^2.0.2", + "list-item": "^1.1.1", + "markdown-link": "^0.1.1", + "minimist": "^1.2.0", + "mixin-deep": "^1.1.3", + "object.pick": "^1.2.0", + "remarkable": "^1.7.1", + "repeat-string": "^1.6.1", + "strip-color": "^0.1.0" + } + }, + "math-random": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", + "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==" + }, + "mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==" + }, + "mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "peer": true + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" + }, + "memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "requires": { + "fs-monkey": "^1.0.4" + } + }, + "memoize-one": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", + "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==" + }, + "meow": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", + "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", + "optional": true, + "peer": true, + "requires": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize": "^1.2.0", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "dependencies": { + "type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "optional": true, + "peer": true + } + } + }, + "merge": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/merge/-/merge-2.1.1.tgz", + "integrity": "sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==", + "dev": true + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" + }, + "micromatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "requires": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true + }, + "min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "devOptional": true + }, + "mini-css-extract-plugin": { + "version": "2.7.6", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.6.tgz", + "integrity": "sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw==", + "requires": { + "schema-utils": "^4.0.0" + }, + "dependencies": { + "ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "requires": { + "fast-deep-equal": "^3.1.3" + } + }, + "schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "requires": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + } + } + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "optional": true, + "peer": true, + "requires": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + } + }, + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "optional": true, + "peer": true, + "requires": { + "yallist": "^4.0.0" + }, + "dependencies": { + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true, + "peer": true + } + } + }, + "minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "optional": true, + "peer": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "optional": true, + "peer": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "optional": true, + "peer": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "optional": true, + "peer": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "optional": true, + "peer": true, + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true, + "peer": true + } + } + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "optional": true, + "peer": true + }, + "mrmime": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", + "integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "requires": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + } + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + }, + "mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "requires": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "nan": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", + "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", + "optional": true, + "peer": true + }, + "nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==" + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + }, + "natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==" + }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "requires": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "requires": { + "whatwg-url": "^5.0.0" + }, + "dependencies": { + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } + }, + "node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==" + }, + "node-gyp": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", + "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "optional": true, + "peer": true, + "requires": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "dependencies": { + "@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "optional": true, + "peer": true, + "requires": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "optional": true, + "peer": true, + "requires": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + } + }, + "cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "optional": true, + "peer": true, + "requires": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "optional": true, + "peer": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "make-fetch-happen": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "optional": true, + "peer": true, + "requires": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + } + }, + "minipass-fetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "optional": true, + "peer": true, + "requires": { + "encoding": "^0.1.12", + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + } + }, + "socks-proxy-agent": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", + "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "optional": true, + "peer": true, + "requires": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + } + }, + "ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "optional": true, + "peer": true, + "requires": { + "minipass": "^3.1.1" + } + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "optional": true, + "peer": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "optional": true, + "peer": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true, + "peer": true + } + } + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" + }, + "node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + }, + "node-sass": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-7.0.3.tgz", + "integrity": "sha512-8MIlsY/4dXUkJDYht9pIWBhMil3uHmE8b/AdJPjmFn1nBx9X9BASzfzmsCy0uCCb8eqI3SYYzVPDswWqSx7gjw==", + "optional": true, + "peer": true, + "requires": { + "async-foreach": "^0.1.3", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "gaze": "^1.0.0", + "get-stdin": "^4.0.1", + "glob": "^7.0.3", + "lodash": "^4.17.15", + "meow": "^9.0.0", + "nan": "^2.13.2", + "node-gyp": "^8.4.1", + "npmlog": "^5.0.0", + "request": "^2.88.0", + "sass-graph": "^4.0.1", + "stdout-stream": "^1.4.0", + "true-case-path": "^1.0.2" + }, + "dependencies": { + "are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "optional": true, + "peer": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "optional": true, + "peer": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "optional": true, + "peer": true, + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + } + }, + "npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "optional": true, + "peer": true, + "requires": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + } + } + }, + "nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "optional": true, + "peer": true, + "requires": { + "abbrev": "1" + } + }, + "normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "optional": true, + "peer": true, + "requires": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==" + }, + "normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==" + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "requires": { + "path-key": "^3.0.0" + } + }, + "npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "optional": true, + "peer": true, + "requires": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + } + }, + "nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "requires": { + "boolbase": "^1.0.0" + } + }, + "nwsapi": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", + "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==" + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "optional": true, + "peer": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==" + }, + "object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==" + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "requires": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + } + }, + "object.entries": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + } + }, + "object.fromentries": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", + "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + } + }, + "object.getownpropertydescriptors": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.6.tgz", + "integrity": "sha512-lq+61g26E/BgHv0ZTFgRvi7NMEPuAxLkFU7rukXjc/AlwH4Am5xXVnIXy3un1bg/JPbXHrixRkK1itUzzPiIjQ==", + "requires": { + "array.prototype.reduce": "^1.0.5", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.21.2", + "safe-array-concat": "^1.0.0" + } + }, + "object.groupby": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", + "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1" + } + }, + "object.hasown": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.4.tgz", + "integrity": "sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==", + "requires": { + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", + "requires": { + "isobject": "^3.0.1" + } + }, + "object.values": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", + "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + } + }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "requires": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + } + }, + "optimism": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.16.2.tgz", + "integrity": "sha512-zWNbgWj+3vLEjZNIh/okkY2EUfX+vB9TJopzIZwT1xxaMqC5hRLLraePod4c5n4He08xuXNH+zhKFFCu390wiQ==", + "requires": { + "@wry/context": "^0.7.0", + "@wry/trie": "^0.3.0" + }, + "dependencies": { + "@wry/trie": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@wry/trie/-/trie-0.3.2.tgz", + "integrity": "sha512-yRTyhWSls2OY/pYLfwff867r8ekooZ4UI+/gxot5Wj8EFwSf2rG+n+Mo/6LoLQm1TKA4GRj2+LCpbfS937dClQ==", + "requires": { + "tslib": "^2.3.0" + } + } + } + }, + "optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "requires": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + } + }, + "ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "requires": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "dependencies": { + "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" + } + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + } + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==" + }, + "p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "optional": true, + "peer": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "requires": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "dependencies": { + "retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==" + } + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "dev": true, + "requires": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "requires": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", + "dev": true + }, + "parse-srcset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", + "integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==" + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + }, + "pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==" + }, + "pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==" + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "requires": { + "find-up": "^4.0.0" + } + }, + "pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "requires": { + "find-up": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==" + } + } + }, + "possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==" + }, + "postcss": { + "version": "8.4.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", + "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", + "requires": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, + "postcss-attribute-case-insensitive": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.2.tgz", + "integrity": "sha512-XIidXV8fDr0kKt28vqki84fRK8VW8eTuIa4PChv2MqKuT6C9UjmSKzen6KaWhWEoYvwxFCa7n/tC1SZ3tyq4SQ==", + "requires": { + "postcss-selector-parser": "^6.0.10" + } + }, + "postcss-browser-comments": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-browser-comments/-/postcss-browser-comments-4.0.0.tgz", + "integrity": "sha512-X9X9/WN3KIvY9+hNERUqX9gncsgBA25XaeR+jshHz2j8+sYyHktHw1JdKuMjeLpGktXidqDhA7b/qm1mrBDmgg==", + "requires": {} + }, + "postcss-calc": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", + "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", + "requires": { + "postcss-selector-parser": "^6.0.9", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-clamp": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz", + "integrity": "sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-color-functional-notation": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-4.2.4.tgz", + "integrity": "sha512-2yrTAUZUab9s6CpxkxC4rVgFEVaR6/2Pipvi6qcgvnYiVqZcbDHEoBDhrXzyb7Efh2CCfHQNtcqWcIruDTIUeg==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-color-hex-alpha": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-8.0.4.tgz", + "integrity": "sha512-nLo2DCRC9eE4w2JmuKgVA3fGL3d01kGq752pVALF68qpGLmx2Qrk91QTKkdUqqp45T1K1XV8IhQpcu1hoAQflQ==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-color-rebeccapurple": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-7.1.1.tgz", + "integrity": "sha512-pGxkuVEInwLHgkNxUc4sdg4g3py7zUeCQ9sMfwyHAT+Ezk8a4OaaVZ8lIY5+oNqA/BXXgLyXv0+5wHP68R79hg==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-colormin": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.1.tgz", + "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==", + "requires": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "colord": "^2.9.1", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-convert-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", + "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", + "requires": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-custom-media": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-8.0.2.tgz", + "integrity": "sha512-7yi25vDAoHAkbhAzX9dHx2yc6ntS4jQvejrNcC+csQJAXjj15e7VcWfMgLqBNAbOvqi5uIa9huOVwdHbf+sKqg==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-custom-properties": { + "version": "12.1.11", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-12.1.11.tgz", + "integrity": "sha512-0IDJYhgU8xDv1KY6+VgUwuQkVtmYzRwu+dMjnmdMafXYv86SWqfxkc7qdDvWS38vsjaEtv8e0vGOUQrAiMBLpQ==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-custom-selectors": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-6.0.3.tgz", + "integrity": "sha512-fgVkmyiWDwmD3JbpCmB45SvvlCD6z9CG6Ie6Iere22W5aHea6oWa7EM2bpnv2Fj3I94L3VbtvX9KqwSi5aFzSg==", + "requires": { + "postcss-selector-parser": "^6.0.4" + } + }, + "postcss-dir-pseudo-class": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-6.0.5.tgz", + "integrity": "sha512-eqn4m70P031PF7ZQIvSgy9RSJ5uI2171O/OO/zcRNYpJbvaeKFUlar1aJ7rmgiQtbm0FSPsRewjpdS0Oew7MPA==", + "requires": { + "postcss-selector-parser": "^6.0.10" + } + }, + "postcss-discard-comments": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", + "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", + "requires": {} + }, + "postcss-discard-duplicates": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", + "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", + "requires": {} + }, + "postcss-discard-empty": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", + "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", + "requires": {} + }, + "postcss-discard-overridden": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", + "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", + "requires": {} + }, + "postcss-double-position-gradients": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-3.1.2.tgz", + "integrity": "sha512-GX+FuE/uBR6eskOK+4vkXgT6pDkexLokPaz/AbJna9s5Kzp/yl488pKPjhy0obB475ovfT1Wv8ho7U/cHNaRgQ==", + "requires": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-env-function": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-4.0.6.tgz", + "integrity": "sha512-kpA6FsLra+NqcFnL81TnsU+Z7orGtDTxcOhl6pwXeEq1yFPpRMkCDpHhrz8CFQDr/Wfm0jLiNQ1OsGGPjlqPwA==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-flexbugs-fixes": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz", + "integrity": "sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==", + "requires": {} + }, + "postcss-focus-visible": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-6.0.4.tgz", + "integrity": "sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw==", + "requires": { + "postcss-selector-parser": "^6.0.9" + } + }, + "postcss-focus-within": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz", + "integrity": "sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ==", + "requires": { + "postcss-selector-parser": "^6.0.9" + } + }, + "postcss-font-variant": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", + "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", + "requires": {} + }, + "postcss-gap-properties": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-3.0.5.tgz", + "integrity": "sha512-IuE6gKSdoUNcvkGIqdtjtcMtZIFyXZhmFd5RUlg97iVEvp1BZKV5ngsAjCjrVy+14uhGBQl9tzmi1Qwq4kqVOg==", + "requires": {} + }, + "postcss-image-set-function": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-4.0.7.tgz", + "integrity": "sha512-9T2r9rsvYzm5ndsBE8WgtrMlIT7VbtTfE7b3BQnudUqnBcBo7L758oc+o+pdj/dUV0l5wjwSdjeOH2DZtfv8qw==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-import": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz", + "integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + } + }, + "postcss-initial": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz", + "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==", + "requires": {} + }, + "postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "requires": { + "camelcase-css": "^2.0.1" + } + }, + "postcss-lab-function": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-4.2.1.tgz", + "integrity": "sha512-xuXll4isR03CrQsmxyz92LJB2xX9n+pZJ5jE9JgcnmsCammLyKdlzrBin+25dy6wIjfhJpKBAN80gsTlCgRk2w==", + "requires": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-load-config": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.1.tgz", + "integrity": "sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==", + "requires": { + "lilconfig": "^2.0.5", + "yaml": "^2.1.1" + }, + "dependencies": { + "yaml": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", + "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==" + } + } + }, + "postcss-loader": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", + "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", + "requires": { + "cosmiconfig": "^7.0.0", + "klona": "^2.0.5", + "semver": "^7.3.5" + } + }, + "postcss-logical": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-5.0.4.tgz", + "integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==", + "requires": {} + }, + "postcss-media-minmax": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz", + "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==", + "requires": {} + }, + "postcss-merge-longhand": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", + "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", + "requires": { + "postcss-value-parser": "^4.2.0", + "stylehacks": "^5.1.1" + } + }, + "postcss-merge-rules": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz", + "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==", + "requires": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^3.1.0", + "postcss-selector-parser": "^6.0.5" + } + }, + "postcss-minify-font-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", + "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-minify-gradients": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", + "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", + "requires": { + "colord": "^2.9.1", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-minify-params": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", + "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", + "requires": { + "browserslist": "^4.21.4", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-minify-selectors": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", + "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", + "requires": { + "postcss-selector-parser": "^6.0.5" + } + }, + "postcss-modules": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules/-/postcss-modules-6.0.0.tgz", + "integrity": "sha512-7DGfnlyi/ju82BRzTIjWS5C4Tafmzl3R79YP/PASiocj+aa6yYphHhhKUOEoXQToId5rgyFgJ88+ccOUydjBXQ==", + "dev": true, + "requires": { + "generic-names": "^4.0.0", + "icss-utils": "^5.1.0", + "lodash.camelcase": "^4.3.0", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "string-hash": "^1.1.1" + } + }, + "postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "requires": {} + }, + "postcss-modules-local-by-default": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz", + "integrity": "sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==", + "requires": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "requires": { + "postcss-selector-parser": "^6.0.4" + } + }, + "postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "requires": { + "icss-utils": "^5.0.0" + } + }, + "postcss-nested": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", + "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", + "requires": { + "postcss-selector-parser": "^6.0.11" + } + }, + "postcss-nesting": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-10.2.0.tgz", + "integrity": "sha512-EwMkYchxiDiKUhlJGzWsD9b2zvq/r2SSubcRrgP+jujMXFzqvANLt16lJANC+5uZ6hjI7lpRmI6O8JIl+8l1KA==", + "requires": { + "@csstools/selector-specificity": "^2.0.0", + "postcss-selector-parser": "^6.0.10" + } + }, + "postcss-normalize": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize/-/postcss-normalize-10.0.1.tgz", + "integrity": "sha512-+5w18/rDev5mqERcG3W5GZNMJa1eoYYNGo8gB7tEwaos0ajk3ZXAI4mHGcNT47NE+ZnZD1pEpUOFLvltIwmeJA==", + "requires": { + "@csstools/normalize.css": "*", + "postcss-browser-comments": "^4", + "sanitize.css": "*" + } + }, + "postcss-normalize-charset": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", + "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", + "requires": {} + }, + "postcss-normalize-display-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", + "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-positions": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", + "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-repeat-style": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", + "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-string": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", + "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-timing-functions": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", + "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-unicode": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", + "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", + "requires": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", + "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", + "requires": { + "normalize-url": "^6.0.1", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-whitespace": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", + "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-opacity-percentage": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.3.tgz", + "integrity": "sha512-An6Ba4pHBiDtyVpSLymUUERMo2cU7s+Obz6BTrS+gxkbnSBNKSuD0AVUc+CpBMrpVPKKfoVz0WQCX+Tnst0i4A==", + "requires": {} + }, + "postcss-ordered-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", + "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", + "requires": { + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-overflow-shorthand": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.4.tgz", + "integrity": "sha512-otYl/ylHK8Y9bcBnPLo3foYFLL6a6Ak+3EQBPOTR7luMYCOsiVTUk1iLvNf6tVPNGXcoL9Hoz37kpfriRIFb4A==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-page-break": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", + "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", + "requires": {} + }, + "postcss-place": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-7.0.5.tgz", + "integrity": "sha512-wR8igaZROA6Z4pv0d+bvVrvGY4GVHihBCBQieXFY3kuSuMyOmEnnfFzHl/tQuqHZkfkIVBEbDvYcFfHmpSet9g==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-preset-env": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-7.8.3.tgz", + "integrity": "sha512-T1LgRm5uEVFSEF83vHZJV2z19lHg4yJuZ6gXZZkqVsqv63nlr6zabMH3l4Pc01FQCyfWVrh2GaUeCVy9Po+Aag==", + "requires": { + "@csstools/postcss-cascade-layers": "^1.1.1", + "@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.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.13", + "browserslist": "^4.21.4", + "css-blank-pseudo": "^3.0.3", + "css-has-pseudo": "^3.0.4", + "css-prefers-color-scheme": "^6.0.3", + "cssdb": "^7.1.0", + "postcss-attribute-case-insensitive": "^5.0.2", + "postcss-clamp": "^4.1.0", + "postcss-color-functional-notation": "^4.2.4", + "postcss-color-hex-alpha": "^8.0.4", + "postcss-color-rebeccapurple": "^7.1.1", + "postcss-custom-media": "^8.0.2", + "postcss-custom-properties": "^12.1.10", + "postcss-custom-selectors": "^6.0.3", + "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.5", + "postcss-image-set-function": "^4.0.7", + "postcss-initial": "^4.0.1", + "postcss-lab-function": "^4.2.1", + "postcss-logical": "^5.0.4", + "postcss-media-minmax": "^5.0.0", + "postcss-nesting": "^10.2.0", + "postcss-opacity-percentage": "^1.1.2", + "postcss-overflow-shorthand": "^3.0.4", + "postcss-page-break": "^3.0.4", + "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.1", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-pseudo-class-any-link": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.6.tgz", + "integrity": "sha512-9sCtZkO6f/5ML9WcTLcIyV1yz9D1rf0tWc+ulKcvV30s0iZKS/ONyETvoWsr6vnrmW+X+KmuK3gV/w5EWnT37w==", + "requires": { + "postcss-selector-parser": "^6.0.10" + } + }, + "postcss-reduce-initial": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz", + "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==", + "requires": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0" + } + }, + "postcss-reduce-transforms": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", + "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-replace-overflow-wrap": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", + "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", + "requires": {} + }, + "postcss-selector-not": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-6.0.1.tgz", + "integrity": "sha512-1i9affjAe9xu/y9uqWH+tD4r6/hDaXJruk8xn2x1vzxC2U3J3LKO3zJW4CyxlNhA56pADJ/djpEwpH1RClI2rQ==", + "requires": { + "postcss-selector-parser": "^6.0.10" + } + }, + "postcss-selector-parser": { + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", + "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + }, + "postcss-svgo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", + "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", + "requires": { + "postcss-value-parser": "^4.2.0", + "svgo": "^2.7.0" + }, + "dependencies": { + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" + }, + "css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + } + }, + "css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "requires": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + } + }, + "dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + } + }, + "domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "requires": { + "domelementtype": "^2.2.0" + } + }, + "domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" + }, + "mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "requires": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + } + } + } + }, + "postcss-unique-selectors": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", + "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", + "requires": { + "postcss-selector-parser": "^6.0.5" + } + }, + "postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==" + }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", + "dev": true + }, + "prettier": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", + "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==" + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, + "pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==" + }, + "pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "requires": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "15.0.15", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.15.tgz", + "integrity": "sha512-IziEYMU9XoVj8hWg7k+UJrXALkGFjWJhn5QFEv9q4p+v40oZhSuC135M38st8XPjICL7Ey4TV64ferBGUoJhBg==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + } + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "promise": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", + "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", + "requires": { + "asap": "~2.0.6" + } + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "optional": true, + "peer": true + }, + "promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "optional": true, + "peer": true, + "requires": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + } + }, + "prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + } + }, + "prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + } + } + }, + "prop-types-extra": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz", + "integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==", + "requires": { + "react-is": "^16.3.2", + "warning": "^4.0.0" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + } + } + }, + "proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "dependencies": { + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + } + } + }, + "psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==" + }, + "punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "peer": true + }, + "pupa": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "dev": true, + "requires": { + "escape-goat": "^2.0.0" + } + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==" + }, + "qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "requires": { + "side-channel": "^1.0.4" + } + }, + "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", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" + }, + "quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "optional": true, + "peer": true + }, + "raf": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", + "requires": { + "performance-now": "^2.1.0" + } + }, + "raf-schd": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz", + "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==" + }, + "randomatic": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "requires": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" + } + } + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "requires": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true + } + } + }, + "react": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", + "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "react-app-polyfill": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-3.0.0.tgz", + "integrity": "sha512-sZ41cxiU5llIB003yxxQBYrARBqe0repqPTTYBTmMqTz9szeBbE37BehCE891NZsmdZqqP+xWKdT3eo3vOzN8w==", + "requires": { + "core-js": "^3.19.2", + "object-assign": "^4.1.1", + "promise": "^8.1.0", + "raf": "^3.4.1", + "regenerator-runtime": "^0.13.9", + "whatwg-fetch": "^3.6.2" + } + }, + "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==", + "requires": { + "semver": "^5.6.0" + }, + "dependencies": { + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" + } + } + }, + "react-async-script": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/react-async-script/-/react-async-script-1.2.0.tgz", + "integrity": "sha512-bCpkbm9JiAuMGhkqoAiC0lLkb40DJ0HOEJIku+9JDjxX3Rcs+ztEOG13wbrOskt3n2DTrjshhaQ/iay+SnGg5Q==", + "requires": { + "hoist-non-react-statics": "^3.3.0", + "prop-types": "^15.5.0" + } + }, + "react-beautiful-dnd": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.1.tgz", + "integrity": "sha512-0Lvs4tq2VcrEjEgDXHjT98r+63drkKEgqyxdA7qD3mvKwga6a5SscbdLPO2IExotU1jW8L0Ksdl0Cj2AF67nPQ==", + "requires": { + "@babel/runtime": "^7.9.2", + "css-box-model": "^1.2.0", + "memoize-one": "^5.1.1", + "raf-schd": "^4.0.2", + "react-redux": "^7.2.0", + "redux": "^4.0.4", + "use-memo-one": "^1.1.1" + } + }, + "react-bootstrap": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.8.0.tgz", + "integrity": "sha512-e/aNtxl0Z2ozrIaR82jr6Zz7ss9GSoaXpQaxmvtDUsTZIq/XalkduR/ZXP6vbQHz2T4syvjA+4FbtwELxxmpww==", + "requires": { + "@babel/runtime": "^7.21.0", + "@restart/hooks": "^0.4.9", + "@restart/ui": "^1.6.3", + "@types/react-transition-group": "^4.4.5", + "classnames": "^2.3.2", + "dom-helpers": "^5.2.1", + "invariant": "^2.2.4", + "prop-types": "^15.8.1", + "prop-types-extra": "^1.1.0", + "react-transition-group": "^4.4.5", + "uncontrollable": "^7.2.1", + "warning": "^4.0.3" + } + }, + "react-datepicker": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-7.3.0.tgz", + "integrity": "sha512-EqRKLAtLZUTztiq6a+tjSjQX9ES0Xd229JPckAtyZZ4GoY3rtvNWAzkYZnQUf6zTWT50Ki0+t+W9VRQIkSJLfg==", + "requires": { + "@floating-ui/react": "^0.26.2", + "clsx": "^2.1.0", + "date-fns": "^3.3.1", + "prop-types": "^15.7.2", + "react-onclickoutside": "^6.13.0" + }, + "dependencies": { + "clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" + }, + "date-fns": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==" + } + } + }, + "react-dev-utils": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", + "integrity": "sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==", + "requires": { + "@babel/code-frame": "^7.16.0", + "address": "^1.1.2", + "browserslist": "^4.18.1", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "detect-port-alt": "^1.1.6", + "escape-string-regexp": "^4.0.0", + "filesize": "^8.0.6", + "find-up": "^5.0.0", + "fork-ts-checker-webpack-plugin": "^6.5.0", + "global-modules": "^2.0.0", + "globby": "^11.0.4", + "gzip-size": "^6.0.0", + "immer": "^9.0.7", + "is-root": "^2.1.0", + "loader-utils": "^3.2.0", + "open": "^8.4.0", + "pkg-up": "^3.1.0", + "prompts": "^2.4.2", + "react-error-overlay": "^6.0.11", + "recursive-readdir": "^2.2.2", + "shell-quote": "^1.7.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "dependencies": { + "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" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "requires": { + "p-locate": "^5.0.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "requires": { + "p-limit": "^3.0.2" + } + } + } + }, + "react-dom": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", + "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "scheduler": "^0.20.2" + } + }, + "react-error-overlay": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", + "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" + }, + "react-fast-compare": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==", + "dev": true + }, + "react-google-recaptcha": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/react-google-recaptcha/-/react-google-recaptcha-3.1.0.tgz", + "integrity": "sha512-cYW2/DWas8nEKZGD7SCu9BSuVz8iOcOLHChHyi7upUuVhkpkhYG/6N3KDiTQ3XAiZ2UAZkfvYKMfAHOzBOcGEg==", + "requires": { + "prop-types": "^15.5.0", + "react-async-script": "^1.2.0" + } + }, + "react-i18next": { + "version": "11.18.6", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.18.6.tgz", + "integrity": "sha512-yHb2F9BiT0lqoQDt8loZ5gWP331GwctHz9tYQ8A2EIEUu+CcEdjBLQWli1USG3RdWQt3W+jqQLg/d4rrQR96LA==", + "requires": { + "@babel/runtime": "^7.14.5", + "html-parse-stringify": "^3.0.1" + } + }, + "react-icons": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.2.1.tgz", + "integrity": "sha512-zdbW5GstTzXaVKvGSyTaBalt7HSfuK5ovrzlpyiWHAFXndXTdd/1hdDHI4xBM1Mn7YriT6aqESucFl9kEXzrdw==", + "requires": {} + }, + "react-infinite-scroll-component": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/react-infinite-scroll-component/-/react-infinite-scroll-component-6.1.0.tgz", + "integrity": "sha512-SQu5nCqy8DxQWpnUVLx7V7b7LcA37aM7tvoWjTLZp1dk6EJibM5/4EJKzOnl07/BsM1Y40sKLuqjCwwH/xV0TQ==", + "requires": { + "throttle-debounce": "^2.1.0" + } + }, + "react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" + }, + "react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, + "react-multi-carousel": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/react-multi-carousel/-/react-multi-carousel-2.8.5.tgz", + "integrity": "sha512-C5DAvJkfzR2JK9YixZ3oyF9x6R4LW6nzTpIXrl9Oujxi4uqP9SzVVCjl+JLM3tSdqdjAx/oWZK3dTVBSR73Q+w==" + }, + "react-onclickoutside": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.13.0.tgz", + "integrity": "sha512-ty8So6tcUpIb+ZE+1HAhbLROvAIJYyJe/1vRrrcmW+jLsaM+/powDRqxzo6hSh9CuRZGSL1Q8mvcF5WRD93a0A==", + "requires": {} + }, + "react-popper": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz", + "integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==", + "dev": true, + "requires": { + "react-fast-compare": "^3.0.1", + "warning": "^4.0.2" + } + }, + "react-redux": { + "version": "7.2.9", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz", + "integrity": "sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==", + "requires": { + "@babel/runtime": "^7.15.4", + "@types/react-redux": "^7.1.20", + "hoist-non-react-statics": "^3.3.2", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^17.0.2" + }, + "dependencies": { + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } + } + }, + "react-refresh": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", + "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==" + }, + "react-router": { + "version": "6.25.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.25.1.tgz", + "integrity": "sha512-u8ELFr5Z6g02nUtpPAggP73Jigj1mRePSwhS/2nkTrlPU5yEkH1vYzWNyvSnSzeeE2DNqWdH+P8OhIh9wuXhTw==", + "requires": { + "@remix-run/router": "1.18.0" + } + }, + "react-router-dom": { + "version": "6.25.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.25.1.tgz", + "integrity": "sha512-0tUDpbFvk35iv+N89dWNrJp+afLgd+y4VtorJZuOCXK0kkCWjEvb3vTJM++SYvMEpbVwXKf3FjeVveVEb6JpDQ==", + "requires": { + "@remix-run/router": "1.18.0", + "react-router": "6.25.1" + } + }, + "react-scripts": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", + "integrity": "sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==", + "requires": { + "@babel/core": "^7.16.0", + "@pmmmwh/react-refresh-webpack-plugin": "^0.5.3", + "@svgr/webpack": "^5.5.0", + "babel-jest": "^27.4.2", + "babel-loader": "^8.2.3", + "babel-plugin-named-asset-import": "^0.3.8", + "babel-preset-react-app": "^10.0.1", + "bfj": "^7.0.2", + "browserslist": "^4.18.1", + "camelcase": "^6.2.1", + "case-sensitive-paths-webpack-plugin": "^2.4.0", + "css-loader": "^6.5.1", + "css-minimizer-webpack-plugin": "^3.2.0", + "dotenv": "^10.0.0", + "dotenv-expand": "^5.1.0", + "eslint": "^8.3.0", + "eslint-config-react-app": "^7.0.1", + "eslint-webpack-plugin": "^3.1.1", + "file-loader": "^6.2.0", + "fs-extra": "^10.0.0", + "fsevents": "^2.3.2", + "html-webpack-plugin": "^5.5.0", + "identity-obj-proxy": "^3.0.0", + "jest": "^27.4.3", + "jest-resolve": "^27.4.2", + "jest-watch-typeahead": "^1.0.0", + "mini-css-extract-plugin": "^2.4.5", + "postcss": "^8.4.4", + "postcss-flexbugs-fixes": "^5.0.2", + "postcss-loader": "^6.2.1", + "postcss-normalize": "^10.0.1", + "postcss-preset-env": "^7.0.1", + "prompts": "^2.4.2", + "react-app-polyfill": "^3.0.0", + "react-dev-utils": "^12.0.1", + "react-refresh": "^0.11.0", + "resolve": "^1.20.0", + "resolve-url-loader": "^4.0.0", + "sass-loader": "^12.3.0", + "semver": "^7.3.5", + "source-map-loader": "^3.0.0", + "style-loader": "^3.3.1", + "tailwindcss": "^3.0.2", + "terser-webpack-plugin": "^5.2.5", + "webpack": "^5.64.4", + "webpack-dev-server": "^4.6.0", + "webpack-manifest-plugin": "^4.0.2", + "workbox-webpack-plugin": "^6.4.1" + }, + "dependencies": { + "babel-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", + "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", + "requires": { + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + } + }, + "babel-plugin-jest-hoist": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", + "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", + "requires": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-preset-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", + "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", + "requires": { + "babel-plugin-jest-hoist": "^27.5.1", + "babel-preset-current-node-syntax": "^1.0.0" + } + }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" + }, + "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" + } + } + } + }, + "react-toastify": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.1.3.tgz", + "integrity": "sha512-fPfb8ghtn/XMxw3LkxQBk3IyagNpF/LIKjOBflbexr2AWxAH1MJgvnESwEwBn9liLFXgTKWgBSdZpw9m4OTHTg==", + "requires": { + "clsx": "^1.1.1" + } + }, + "react-tooltip": { + "version": "5.27.1", + "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.27.1.tgz", + "integrity": "sha512-a+micPXcMOMt11CYlwJD4XShcqGziasHco4NPe1OFw298WBTILMyzUgNC1LAFViAe791JdHNVSJIpzhZm2MvDA==", + "requires": { + "@floating-ui/dom": "^1.6.1", + "classnames": "^2.3.0" + } + }, + "react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "requires": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + } + }, + "read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "requires": { + "pify": "^2.3.0" + } + }, + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "optional": true, + "peer": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "optional": true, + "peer": true + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "optional": true, + "peer": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "optional": true, + "peer": true + }, + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "optional": true, + "peer": true + } + } + }, + "read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "optional": true, + "peer": true, + "requires": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "dependencies": { + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "optional": true, + "peer": true + } + } + }, + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "requires": { + "picomatch": "^2.2.1" + } + }, + "recursive-readdir": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", + "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", + "requires": { + "minimatch": "^3.0.5" + } + }, + "redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "devOptional": true, + "requires": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + } + }, + "redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "requires": { + "@babel/runtime": "^7.9.2" + } + }, + "redux-thunk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz", + "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==", + "requires": {} + }, + "reflect.getprototypeof": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + } + }, + "regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + }, + "regenerate-unicode-properties": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz", + "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==", + "requires": { + "regenerate": "^1.4.2" + } + }, + "regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + }, + "regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "requires": { + "@babel/runtime": "^7.8.4" + } + }, + "regex-parser": { + "version": "2.2.11", + "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.11.tgz", + "integrity": "sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q==" + }, + "regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "requires": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" + } + }, + "regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "requires": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + } + }, + "registry-auth-token": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz", + "integrity": "sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==", + "dev": true, + "requires": { + "rc": "1.2.8" + } + }, + "registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dev": true, + "requires": { + "rc": "^1.2.8" + } + }, + "regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==" + } + } + }, + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==" + }, + "remarkable": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/remarkable/-/remarkable-1.7.4.tgz", + "integrity": "sha512-e6NKUXgX95whv7IgddywbeN/ItCkWbISmc2DiqHJb0wTrqZIexqdco5b8Z3XZoo/48IdNVKM9ZCvTPJ4F5uvhg==", + "requires": { + "argparse": "^1.0.10", + "autolinker": "~0.28.0" + } + }, + "renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "requires": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + } + }, + "dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + } + }, + "domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "requires": { + "domelementtype": "^2.2.0" + } + }, + "domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" + }, + "htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + } + } + }, + "repeat-element": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", + "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==" + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "optional": true, + "peer": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "optional": true, + "peer": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "optional": true, + "peer": true + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "optional": true, + "peer": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "optional": true, + "peer": true + } + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + }, + "reselect": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", + "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==" + }, + "resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "requires": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "requires": { + "resolve-from": "^5.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==" + } + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "dependencies": { + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" + }, + "resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true + }, + "resolve-url-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-4.0.0.tgz", + "integrity": "sha512-05VEMczVREcbtT7Bz+C+96eUO5HDNvdthIiMB34t7FcF8ehcu4wC0sSgPUubs3XW2Q3CNLJk/BJrCU9wVRymiA==", + "requires": { + "adjust-sourcemap-loader": "^4.0.0", + "convert-source-map": "^1.7.0", + "loader-utils": "^2.0.0", + "postcss": "^7.0.35", + "source-map": "0.6.1" + }, + "dependencies": { + "loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "resolve.exports": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.1.tgz", + "integrity": "sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==" + }, + "response-iterator": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/response-iterator/-/response-iterator-0.2.6.tgz", + "integrity": "sha512-pVzEEzrsg23Sh053rmDUvLSkGXluZio0qu8VT6ukrYuvtjVfCbDZH9d6PGXb8HZfzdNZt8feXv/jvUzlhRgLnw==" + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0" + } + }, + "restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "restructure": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/restructure/-/restructure-3.0.0.tgz", + "integrity": "sha512-Xj8/MEIhhfj9X2rmD9iJ4Gga9EFqVlpMj3vfLnV2r/Mh5jRMryNV+6lWh9GdJtDBcBSPIqzRdfBQ3wDtNFv/uw==" + }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "optional": true, + "peer": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" + }, + "rfdc": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + }, + "robust-predicates": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" + }, + "rollup": { + "version": "2.79.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", + "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", + "requires": { + "fsevents": "~2.3.2" + } + }, + "rollup-plugin-terser": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", + "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", + "requires": { + "@babel/code-frame": "^7.10.4", + "jest-worker": "^26.2.1", + "serialize-javascript": "^4.0.0", + "terser": "^5.0.0" + }, + "dependencies": { + "jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + } + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "requires": { + "randombytes": "^2.1.0" + } + } + } + }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==" + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "requires": { + "tslib": "^2.1.0" + } + }, + "safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "requires": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "requires": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sanitize-html": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.13.0.tgz", + "integrity": "sha512-Xff91Z+4Mz5QiNSLdLWwjgBDm5b1RU6xBT0+12rapjiaR7SwfRdjw8f+6Rir2MXKLrDicRFHdb51hGOAxmsUIA==", + "requires": { + "deepmerge": "^4.2.2", + "escape-string-regexp": "^4.0.0", + "htmlparser2": "^8.0.0", + "is-plain-object": "^5.0.0", + "parse-srcset": "^1.0.2", + "postcss": "^8.3.11" + }, + "dependencies": { + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" + } + } + }, + "sanitize.css": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-13.0.0.tgz", + "integrity": "sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA==" + }, + "sass": { + "version": "1.77.4", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.4.tgz", + "integrity": "sha512-vcF3Ckow6g939GMA4PeU7b2K/9FALXk2KF9J87txdHzXbUF9XRQRwSxcAs/fGaTnJeBFd7UoV22j3lzMLdM0Pw==", + "devOptional": true, + "requires": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + } + }, + "sass-graph": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-4.0.1.tgz", + "integrity": "sha512-5YCfmGBmxoIRYHnKK2AKzrAkCoQ8ozO+iumT8K4tXJXRVCPf+7s1/9KxTSW3Rbvf+7Y7b4FR3mWyLnQr3PHocA==", + "optional": true, + "peer": true, + "requires": { + "glob": "^7.0.0", + "lodash": "^4.17.11", + "scss-tokenizer": "^0.4.3", + "yargs": "^17.2.1" + }, + "dependencies": { + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "optional": true, + "peer": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "optional": true, + "peer": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "optional": true, + "peer": true + } + } + }, + "sass-loader": { + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.6.0.tgz", + "integrity": "sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA==", + "requires": { + "klona": "^2.0.4", + "neo-async": "^2.6.2" + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "requires": { + "xmlchars": "^2.2.0" + } + }, + "scheduler": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "requires": {} + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + } + } + }, + "scss-tokenizer": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.4.3.tgz", + "integrity": "sha512-raKLgf1LI5QMQnG+RxHz6oK0sL3x3I4FN2UDLqgLOGO8hodECNnNh5BXn7fAyBxrA8zVzdQizQ6XjNJQ+uBwMw==", + "optional": true, + "peer": true, + "requires": { + "js-base64": "^2.4.9", + "source-map": "^0.7.3" + }, + "dependencies": { + "source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "optional": true, + "peer": true + } + } + }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==" + }, + "selfsigned": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz", + "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==", + "requires": { + "node-forge": "^1" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } + }, + "semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "dev": true, + "requires": { + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "requires": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "requires": { + "ee-first": "1.1.1" + } + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" + } + } + }, + "serialize-javascript": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "requires": { + "randombytes": "^2.1.0" + } + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==" + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + } + } + }, + "serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "optional": true, + "peer": true + }, + "set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "requires": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + } + }, + "set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "requires": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + } + }, + "set-getter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.1.tgz", + "integrity": "sha512-9sVWOy+gthr+0G9DzqqLaYNA7+5OKkSmcqjL9cBpDEaZrr3ShQlyX2cZ/O/ozE41oxn/Tt0LGEM/w4Rub3A3gw==", + "requires": { + "to-object-path": "^0.3.0" + } + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + }, + "shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==" + }, + "shiki": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.10.3.tgz", + "integrity": "sha512-eneCLncGuvPdTutJuLyUGS8QNPAVFO5Trvld2wgEq1e002mwctAhJKeMGWtWVXOIEzmlcLRqcgPSorR6AVzOmQ==", + "peer": true, + "requires": { + "@shikijs/core": "1.10.3", + "@types/hast": "^3.0.4" + } + }, + "side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "requires": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + } + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "sirv": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.3.tgz", + "integrity": "sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA==", + "dev": true, + "requires": { + "@polka/url": "^1.0.0-next.20", + "mrmime": "^1.0.0", + "totalist": "^3.0.0" + } + }, + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + }, + "slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "requires": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true + } + } + }, + "smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "optional": true, + "peer": true + }, + "sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "requires": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "optional": true, + "peer": true, + "requires": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + } + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" + }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" + }, + "source-map-loader": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-3.0.2.tgz", + "integrity": "sha512-BokxPoLjyl3iOrgkWaakaxqnelAJSS+0V+De0kKIq6lyWrXuiPgYTGp6z3iHmqljKAaLXwZa+ctD8GccRJeVvg==", + "requires": { + "abab": "^2.0.5", + "iconv-lite": "^0.6.3", + "source-map-js": "^1.0.1" + } + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" + }, + "spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "optional": true, + "peer": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "optional": true, + "peer": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "optional": true, + "peer": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", + "optional": true, + "peer": true + }, + "spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "requires": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + } + }, + "spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "requires": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "sshpk": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "optional": true, + "peer": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==" + }, + "stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "requires": { + "escape-string-regexp": "^2.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" + } + } + }, + "stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==" + }, + "stdout-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", + "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", + "optional": true, + "peer": true, + "requires": { + "readable-stream": "^2.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "optional": true, + "peer": true + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "optional": true, + "peer": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "optional": true, + "peer": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "optional": true, + "peer": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true + }, + "string-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", + "integrity": "sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==", + "dev": true + }, + "string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "requires": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + } + }, + "string-natural-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/string-natural-compare/-/string-natural-compare-3.0.1.tgz", + "integrity": "sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + } + } + }, + "string.prototype.matchall": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + } + }, + "string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + } + }, + "string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + } + }, + "string.prototype.trimstart": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + } + }, + "stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "requires": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + }, + "dependencies": { + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==" + } + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==" + }, + "strip-color": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/strip-color/-/strip-color-0.1.0.tgz", + "integrity": "sha512-p9LsUieSjWNNAxVCXLeilaDlmuUOrDS5/dF9znM1nZc7EGX5+zEFC0bEevsNIaldjlks+2jns5Siz6F9iK6jwA==" + }, + "strip-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", + "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==" + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==" + }, + "strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "devOptional": true, + "requires": { + "min-indent": "^1.0.0" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" + }, + "style-loader": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.3.tgz", + "integrity": "sha512-53BiGLXAcll9maCYtZi2RCQZKa8NQQai5C4horqKyRmHj9H7QmcUyucrH+4KW/gBQbXM2AsB0axoEcFZPlfPcw==", + "requires": {} + }, + "stylehacks": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", + "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", + "requires": { + "browserslist": "^4.21.4", + "postcss-selector-parser": "^6.0.4" + } + }, + "stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + }, + "sucrase": { + "version": "3.33.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.33.0.tgz", + "integrity": "sha512-ARGC7vbufOHfpvyGcZZXFaXCMZ9A4fffOGC5ucOW7+WHDGlAe8LJdf3Jts1sWhDeiI1RSWrKy5Hodl+JWGdW2A==", + "requires": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "7.1.6", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "dependencies": { + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==" + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "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": { + "has-flag": "^4.0.0" + } + }, + "supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "requires": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" + }, + "svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" + }, + "svgo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", + "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", + "requires": { + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", + "css-tree": "1.0.0-alpha.37", + "csso": "^4.0.2", + "js-yaml": "^3.13.1", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "requires": { + "minimist": "^1.2.6" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "symbol-observable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", + "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==" + }, + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" + }, + "synckit": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", + "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", + "dev": true, + "requires": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + } + }, + "tabbable": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==" + }, + "tailwindcss": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz", + "integrity": "sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==", + "requires": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.2.12", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.18.2", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" + }, + "dependencies": { + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "requires": { + "is-glob": "^4.0.3" + } + }, + "postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "requires": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + } + } + } + }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" + }, + "tar": { + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", + "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", + "optional": true, + "peer": true, + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "optional": true, + "peer": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true, + "peer": true + } + } + }, + "temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==" + }, + "tempy": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz", + "integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==", + "requires": { + "is-stream": "^2.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^0.16.0", + "unique-string": "^2.0.0" + }, + "dependencies": { + "type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==" + } + } + }, + "terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "requires": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" + } + }, + "terser": { + "version": "5.19.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.19.0.tgz", + "integrity": "sha512-JpcpGOQLOXm2jsomozdMDpd5f8ZHh1rR48OFgWUH3QsyZcfPgv2qDCYbcDEAYNd4OZRj2bWYKpwdll/udZCk/Q==", + "requires": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + } + } + }, + "terser-webpack-plugin": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", + "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", + "requires": { + "@jridgewell/trace-mapping": "^0.3.17", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.16.8" + } + }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + }, + "thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "requires": { + "any-promise": "^1.0.0" + } + }, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "requires": { + "thenify": ">= 3.1.0 < 4" + } + }, + "throat": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz", + "integrity": "sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==" + }, + "throttle-debounce": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-2.3.0.tgz", + "integrity": "sha512-H7oLPV0P7+jgvrk+6mwwwBDmxTaxnu9HMXmloNLXwnNO0ZxZ31Orah2n8lU1eMPvsaowP2CX+USCgyovXfdOFQ==" + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" + }, + "tiny-inflate": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==" + }, + "tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "tmp-promise": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", + "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", + "requires": { + "tmp": "^0.2.0" + }, + "dependencies": { + "tmp": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==" + } + } + }, + "tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==" + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==" + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + }, + "toml": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/toml/-/toml-2.3.6.tgz", + "integrity": "sha512-gVweAectJU3ebq//Ferr2JUY4WKSDe5N+z0FvjDncLGyHmIDoxgY/2Ie4qfEIDm4IS7OA6Rmdm7pdEEdMcV/xQ==" + }, + "totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "dev": true + }, + "tough-cookie": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", + "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", + "requires": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "dependencies": { + "universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==" + } + } + }, + "tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "requires": { + "punycode": "^2.1.1" + } + }, + "trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "optional": true, + "peer": true + }, + "true-case-path": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", + "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", + "optional": true, + "peer": true, + "requires": { + "glob": "^7.1.2" + } + }, + "tryer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", + "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==" + }, + "ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" + }, + "ts-invariant": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.10.3.tgz", + "integrity": "sha512-uivwYcQaxAucv1CzRp2n/QdYPo4ILf9VXgH19zEIjFx2EJufV16P0JtJVpYHy89DItG6Kwj2oIUjrcK5au+4tQ==", + "requires": { + "tslib": "^2.1.0" + } + }, + "tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "requires": { + "minimist": "^1.2.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==" + } + } + }, + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "requires": { + "tslib": "^1.8.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + }, + "tsx": { + "version": "4.16.2", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.16.2.tgz", + "integrity": "sha512-C1uWweJDgdtX2x600HjaFaucXTilT7tgUZHbOE4+ypskZ1OP8CRCSDkCxG6Vya9EwaFIVagWwpaVAn5wzypaqQ==", + "dev": true, + "requires": { + "esbuild": "~0.21.5", + "fsevents": "~2.3.3", + "get-tsconfig": "^4.7.5" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "optional": true, + "peer": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "optional": true, + "peer": true + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" + }, + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==" + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "requires": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + } + }, + "typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "requires": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + } + }, + "typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "requires": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + } + }, + "typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "requires": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "requires": { + "is-typedarray": "^1.0.0" + } + }, + "typedoc": { + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.3.tgz", + "integrity": "sha512-6d2Sw9disvvpdk4K7VNjKr5/3hzijtfQVHRthhDqJgnhMHy1wQz4yPMJVKXElvnZhFr0nkzo+GzjXDTRV5yLpg==", + "peer": true, + "requires": { + "lunr": "^2.3.9", + "markdown-it": "^14.1.0", + "minimatch": "^9.0.5", + "shiki": "^1.9.1", + "yaml": "^2.4.5" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "peer": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "peer": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "yaml": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", + "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", + "peer": true + } + } + }, + "typedoc-plugin-markdown": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.2.1.tgz", + "integrity": "sha512-7hQt/1WaW/VI4+x3sxwcCGsEylP1E1GvF6OTTELK5sfTEp6AeK+83jkCOgZGp1pI2DiOammMYQMnxxOny9TKsQ==", + "requires": {} + }, + "typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==" + }, + "uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "peer": true + }, + "unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "requires": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + } + }, + "uncontrollable": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz", + "integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==", + "requires": { + "@babel/runtime": "^7.6.3", + "@types/react": ">=16.9.11", + "invariant": "^2.2.4", + "react-lifecycles-compat": "^3.0.4" + } + }, + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==" + }, + "unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "requires": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==" + }, + "unicode-properties": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz", + "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==", + "requires": { + "base64-js": "^1.3.0", + "unicode-trie": "^2.0.0" + } + }, + "unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==" + }, + "unicode-trie": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz", + "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==", + "requires": { + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" + }, + "dependencies": { + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==" + } + } + }, + "unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "requires": { + "crypto-random-string": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" + }, + "unquote": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", + "integrity": "sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg==" + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" + }, + "update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "update-notifier": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", + "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", + "dev": true, + "requires": { + "boxen": "^5.0.0", + "chalk": "^4.1.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.4.0", + "is-npm": "^5.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.1.0", + "pupa": "^2.1.1", + "semver": "^7.3.4", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + } + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "requires": { + "punycode": "^2.1.0" + } + }, + "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" + } + }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", + "dev": true, + "requires": { + "prepend-http": "^2.0.0" + } + }, + "use-memo-one": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz", + "integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==", + "requires": {} + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + } + }, + "utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + }, + "v8-to-istanbul": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", + "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0", + "source-map": "^0.7.3" + }, + "dependencies": { + "source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==" + } + } + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "optional": true, + "peer": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "optional": true, + "peer": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "dependencies": { + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "optional": true, + "peer": true + } + } + }, + "void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==" + }, + "w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "requires": { + "browser-process-hrtime": "^1.0.0" + } + }, + "w3c-xmlserializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "requires": { + "xml-name-validator": "^3.0.0" + } + }, + "walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "requires": { + "makeerror": "1.0.12" + } + }, + "warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "requires": { + "loose-envify": "^1.0.0" + } + }, + "watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "requires": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + } + }, + "wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "requires": { + "minimalistic-assert": "^1.0.0" + } + }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "requires": { + "defaults": "^1.0.3" + } + }, + "web-vitals": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.2.tgz", + "integrity": "sha512-nYfoOqb4EmElljyXU2qdeE76KsvoHdftQKY4DzA9Aw8DervCg2bG634pHLrJ/d6+B4mE3nWTSJv8Mo7B2mbZkw==" + }, + "webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==" + }, + "webpack": { + "version": "5.88.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.1.tgz", + "integrity": "sha512-FROX3TxQnC/ox4N+3xQoWZzvGXSuscxR32rbzjpXgEzWudJFEJBpdlkkob2ylrv5yzzufD1zph1OoFsLtm6stQ==", + "requires": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.9.0", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.7", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + } + }, + "webpack-dev-middleware": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", + "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", + "requires": { + "colorette": "^2.0.10", + "memfs": "^3.4.3", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "dependencies": { + "ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "requires": { + "fast-deep-equal": "^3.1.3" + } + }, + "schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "requires": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + } + } + } + }, + "webpack-dev-server": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz", + "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==", + "requires": { + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/serve-static": "^1.13.10", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.5.5", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.0.11", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.0.1", + "launch-editor": "^2.6.0", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "rimraf": "^3.0.2", + "schema-utils": "^4.0.0", + "selfsigned": "^2.1.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^5.3.1", + "ws": "^8.13.0" + }, + "dependencies": { + "ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "requires": { + "fast-deep-equal": "^3.1.3" + } + }, + "schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "requires": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + } + } + } + }, + "webpack-manifest-plugin": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/webpack-manifest-plugin/-/webpack-manifest-plugin-4.1.1.tgz", + "integrity": "sha512-YXUAwxtfKIJIKkhg03MKuiFAD72PlrqCiwdwO4VEXdRO5V0ORCNwaOwAZawPZalCbmH9kBDmXnNeQOw+BIEiow==", + "requires": { + "tapable": "^2.0.0", + "webpack-sources": "^2.2.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "webpack-sources": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", + "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", + "requires": { + "source-list-map": "^2.0.1", + "source-map": "^0.6.1" + } + } + } + }, + "webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==" + }, + "websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "requires": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==" + }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "requires": { + "iconv-lite": "0.4.24" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, + "whatwg-fetch": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", + "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==" + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==" + }, + "whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "requires": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "requires": { + "isexe": "^2.0.0" + } + }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, + "which-builtin-type": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", + "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "requires": { + "function.prototype.name": "^1.1.5", + "has-tostringtag": "^1.0.0", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + } + }, + "which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "requires": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + } + }, + "which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "requires": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + } + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "optional": true, + "peer": true, + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "requires": { + "string-width": "^4.0.0" + } + }, + "workbox-background-sync": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-6.6.0.tgz", + "integrity": "sha512-jkf4ZdgOJxC9u2vztxLuPT/UjlH7m/nWRQ/MgGL0v8BJHoZdVGJd18Kck+a0e55wGXdqyHO+4IQTk0685g4MUw==", + "requires": { + "idb": "^7.0.1", + "workbox-core": "6.6.0" + } + }, + "workbox-broadcast-update": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-6.6.0.tgz", + "integrity": "sha512-nm+v6QmrIFaB/yokJmQ/93qIJ7n72NICxIwQwe5xsZiV2aI93MGGyEyzOzDPVz5THEr5rC3FJSsO3346cId64Q==", + "requires": { + "workbox-core": "6.6.0" + } + }, + "workbox-build": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-6.6.0.tgz", + "integrity": "sha512-Tjf+gBwOTuGyZwMz2Nk/B13Fuyeo0Q84W++bebbVsfr9iLkDSo6j6PST8tET9HYA58mlRXwlMGpyWO8ETJiXdQ==", + "requires": { + "@apideck/better-ajv-errors": "^0.3.1", + "@babel/core": "^7.11.1", + "@babel/preset-env": "^7.11.0", + "@babel/runtime": "^7.11.2", + "@rollup/plugin-babel": "^5.2.0", + "@rollup/plugin-node-resolve": "^11.2.1", + "@rollup/plugin-replace": "^2.4.1", + "@surma/rollup-plugin-off-main-thread": "^2.2.3", + "ajv": "^8.6.0", + "common-tags": "^1.8.0", + "fast-json-stable-stringify": "^2.1.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", + "lodash": "^4.17.20", + "pretty-bytes": "^5.3.0", + "rollup": "^2.43.1", + "rollup-plugin-terser": "^7.0.0", + "source-map": "^0.8.0-beta.0", + "stringify-object": "^3.3.0", + "strip-comments": "^2.0.1", + "tempy": "^0.6.0", + "upath": "^1.2.0", + "workbox-background-sync": "6.6.0", + "workbox-broadcast-update": "6.6.0", + "workbox-cacheable-response": "6.6.0", + "workbox-core": "6.6.0", + "workbox-expiration": "6.6.0", + "workbox-google-analytics": "6.6.0", + "workbox-navigation-preload": "6.6.0", + "workbox-precaching": "6.6.0", + "workbox-range-requests": "6.6.0", + "workbox-recipes": "6.6.0", + "workbox-routing": "6.6.0", + "workbox-strategies": "6.6.0", + "workbox-streams": "6.6.0", + "workbox-sw": "6.6.0", + "workbox-window": "6.6.0" + }, + "dependencies": { + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "requires": { + "whatwg-url": "^7.0.0" + } + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "requires": { + "punycode": "^2.1.0" + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" + }, + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } + } + }, + "workbox-cacheable-response": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-6.6.0.tgz", + "integrity": "sha512-JfhJUSQDwsF1Xv3EV1vWzSsCOZn4mQ38bWEBR3LdvOxSPgB65gAM6cS2CX8rkkKHRgiLrN7Wxoyu+TuH67kHrw==", + "requires": { + "workbox-core": "6.6.0" + } + }, + "workbox-core": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.6.0.tgz", + "integrity": "sha512-GDtFRF7Yg3DD859PMbPAYPeJyg5gJYXuBQAC+wyrWuuXgpfoOrIQIvFRZnQ7+czTIQjIr1DhLEGFzZanAT/3bQ==" + }, + "workbox-expiration": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.6.0.tgz", + "integrity": "sha512-baplYXcDHbe8vAo7GYvyAmlS4f6998Jff513L4XvlzAOxcl8F620O91guoJ5EOf5qeXG4cGdNZHkkVAPouFCpw==", + "requires": { + "idb": "^7.0.1", + "workbox-core": "6.6.0" + } + }, + "workbox-google-analytics": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-6.6.0.tgz", + "integrity": "sha512-p4DJa6OldXWd6M9zRl0H6vB9lkrmqYFkRQ2xEiNdBFp9U0LhsGO7hsBscVEyH9H2/3eZZt8c97NB2FD9U2NJ+Q==", + "requires": { + "workbox-background-sync": "6.6.0", + "workbox-core": "6.6.0", + "workbox-routing": "6.6.0", + "workbox-strategies": "6.6.0" + } + }, + "workbox-navigation-preload": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-6.6.0.tgz", + "integrity": "sha512-utNEWG+uOfXdaZmvhshrh7KzhDu/1iMHyQOV6Aqup8Mm78D286ugu5k9MFD9SzBT5TcwgwSORVvInaXWbvKz9Q==", + "requires": { + "workbox-core": "6.6.0" + } + }, + "workbox-precaching": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.6.0.tgz", + "integrity": "sha512-eYu/7MqtRZN1IDttl/UQcSZFkHP7dnvr/X3Vn6Iw6OsPMruQHiVjjomDFCNtd8k2RdjLs0xiz9nq+t3YVBcWPw==", + "requires": { + "workbox-core": "6.6.0", + "workbox-routing": "6.6.0", + "workbox-strategies": "6.6.0" + } + }, + "workbox-range-requests": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-6.6.0.tgz", + "integrity": "sha512-V3aICz5fLGq5DpSYEU8LxeXvsT//mRWzKrfBOIxzIdQnV/Wj7R+LyJVTczi4CQ4NwKhAaBVaSujI1cEjXW+hTw==", + "requires": { + "workbox-core": "6.6.0" + } + }, + "workbox-recipes": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-6.6.0.tgz", + "integrity": "sha512-TFi3kTgYw73t5tg73yPVqQC8QQjxJSeqjXRO4ouE/CeypmP2O/xqmB/ZFBBQazLTPxILUQ0b8aeh0IuxVn9a6A==", + "requires": { + "workbox-cacheable-response": "6.6.0", + "workbox-core": "6.6.0", + "workbox-expiration": "6.6.0", + "workbox-precaching": "6.6.0", + "workbox-routing": "6.6.0", + "workbox-strategies": "6.6.0" + } + }, + "workbox-routing": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.6.0.tgz", + "integrity": "sha512-x8gdN7VDBiLC03izAZRfU+WKUXJnbqt6PG9Uh0XuPRzJPpZGLKce/FkOX95dWHRpOHWLEq8RXzjW0O+POSkKvw==", + "requires": { + "workbox-core": "6.6.0" + } + }, + "workbox-strategies": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.6.0.tgz", + "integrity": "sha512-eC07XGuINAKUWDnZeIPdRdVja4JQtTuc35TZ8SwMb1ztjp7Ddq2CJ4yqLvWzFWGlYI7CG/YGqaETntTxBGdKgQ==", + "requires": { + "workbox-core": "6.6.0" + } + }, + "workbox-streams": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-6.6.0.tgz", + "integrity": "sha512-rfMJLVvwuED09CnH1RnIep7L9+mj4ufkTyDPVaXPKlhi9+0czCu+SJggWCIFbPpJaAZmp2iyVGLqS3RUmY3fxg==", + "requires": { + "workbox-core": "6.6.0", + "workbox-routing": "6.6.0" + } + }, + "workbox-sw": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-6.6.0.tgz", + "integrity": "sha512-R2IkwDokbtHUE4Kus8pKO5+VkPHD2oqTgl+XJwh4zbF1HyjAbgNmK/FneZHVU7p03XUt9ICfuGDYISWG9qV/CQ==" + }, + "workbox-webpack-plugin": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-webpack-plugin/-/workbox-webpack-plugin-6.6.0.tgz", + "integrity": "sha512-xNZIZHalboZU66Wa7x1YkjIqEy1gTR+zPM+kjrYJzqN7iurYZBctBLISyScjhkJKYuRrZUP0iqViZTh8rS0+3A==", + "requires": { + "fast-json-stable-stringify": "^2.1.0", + "pretty-bytes": "^5.4.1", + "upath": "^1.2.0", + "webpack-sources": "^1.4.3", + "workbox-build": "6.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + } + } + }, + "workbox-window": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-6.6.0.tgz", + "integrity": "sha512-L4N9+vka17d16geaJXXRjENLFldvkWy7JyGxElRD0JvBxvFEd8LOhr+uXCcar/NzAmIBRv9EZ+M+Qr4mOoBITw==", + "requires": { + "@types/trusted-types": "^2.0.2", + "workbox-core": "6.6.0" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "ws": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "requires": {} + }, + "xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "dev": true + }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==" + }, + "xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==" + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" + }, + "zen-observable": { + "version": "0.8.15", + "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", + "integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==" + }, + "zen-observable-ts": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-1.2.5.tgz", + "integrity": "sha512-QZWQekv6iB72Naeake9hS1KxHlotfRpe+WGNbNx5/ta+R3DNjVO2bswf63gXlWDcs+EMd7XY8HfVQyP1X6T4Zg==", + "requires": { + "zen-observable": "0.8.15" + } + }, + "zod": { + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", + "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==" + } } } diff --git a/package.json b/package.json index 57e60288ce..52e08ba7c3 100644 --- a/package.json +++ b/package.json @@ -10,50 +10,53 @@ "@apollo/react-testing": "^4.0.0", "@dicebear/collection": "^8.0.1", "@dicebear/core": "^8.0.1", - "@emotion/react": "^11.11.1", + "@emotion/react": "^11.11.4", "@emotion/styled": "^11.11.5", - "@mui/icons-material": "^5.8.3", - "@mui/material": "^5.15.15", + "@mui/icons-material": "^5.16.1", + "@mui/material": "^5.16.4", "@mui/private-theming": "^5.15.12", "@mui/system": "^5.14.12", - "@mui/x-charts": "^7.4.0", - "@mui/x-data-grid": "^6.20.0", - "@mui/x-date-pickers": "^6.6.0", + "@mui/x-charts": "^7.8.0", + "@mui/x-data-grid": "^7.11.0", + "@mui/x-date-pickers": "^7.6.1", "@pdfme/generator": "^1.2.6", - "bootstrap": "^5.3.0", + "bootstrap": "^5.3.3", "customize-cra": "^1.0.0", "dayjs": "^1.11.11", "flag-icons": "^6.6.6", - "graphql": "^16.8.1", + "graphql": "^16.9.0", "graphql-tag": "^2.12.6", "graphql-ws": "^5.16.0", "history": "^5.3.0", "i18next": "^21.8.14", - "i18next-browser-languagedetector": "^6.1.4", - "i18next-http-backend": "^1.4.1", + "i18next-browser-languagedetector": "^8.0.0", + "i18next-http-backend": "^2.5.2", "inquirer": "^8.0.0", "js-cookie": "^3.0.1", "markdown-toc": "^1.2.0", - "prettier": "^3.2.5", + "prettier": "^3.3.2", "react": "^17.0.2", "react-app-rewired": "^2.2.1", + "react-beautiful-dnd": "^13.1.1", "react-bootstrap": "^2.7.4", - "react-datepicker": "^4.2.0", + "react-datepicker": "^7.3.0", "react-dom": "^17.0.2", - "react-google-recaptcha": "^2.1.0", + "react-google-recaptcha": "^3.1.0", "react-i18next": "^11.18.1", "react-icons": "^5.2.1", "react-infinite-scroll-component": "^6.1.0", + "react-multi-carousel": "^2.8.5", "react-redux": "^7.2.5", - "react-router-dom": "^6.22.2", + "react-router-dom": "^6.25.1", "react-scripts": "5.0.1", "react-toastify": "^9.0.3", + "react-tooltip": "^5.27.1", "redux": "^4.1.1", "redux-thunk": "^2.3.0", "sanitize-html": "^2.13.0", - "typedoc-plugin-markdown": "^4.0.2", + "typedoc-plugin-markdown": "^4.2.1", "typescript": "^4.3.5", - "web-vitals": "^1.0.1" + "web-vitals": "^4.2.2" }, "scripts": { "serve": "cross-env ESLINT_NO_DEV_ERRORS=true node ./scripts/config-overrides/custom_start.js", @@ -101,6 +104,7 @@ "@types/node": "^20.12.12", "@types/node-fetch": "^2.6.10", "@types/react": "^17.0.14", + "@types/react-beautiful-dnd": "^13.1.8", "@types/react-bootstrap": "^0.32.32", "@types/react-datepicker": "^4.1.4", "@types/react-dom": "^17.0.9", @@ -122,10 +126,10 @@ "jest-localstorage-mock": "^2.4.19", "jest-location-mock": "^2.0.0", "jest-preview": "^0.3.1", - "lint-staged": "^15.2.2", + "lint-staged": "^15.2.7", "postcss-modules": "^6.0.0", - "sass": "^1.71.1", - "tsx": "^3.11.0" + "sass": "^1.77.4", + "tsx": "^4.16.2" }, "resolutions": { "@apollo/client": "^3.4.0-beta.19", diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 54e46bdba6..d3f108c550 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -30,11 +30,13 @@ "search": "Search", "description": "Description", "saveChanges": "Save Changes", + "resetChanges": "Reset Changes", "displayImage": "Display Image", "enterEmail": "Enter Email", "emailAddress": "Email Address", "email": "Email", "name": "Name", + "desc": "Description", "enterPassword": "Enter Password", "password": "Password", "confirmPassword": "Confirm Password", @@ -61,5 +63,24 @@ "Membership Requests": "Membership Requests", "Plugins": "Plugins", "Plugin Store": "Plugin Store", - "Settings": "Settings" + "Settings": "Settings", + "createdOn": "Created On", + "createdBy": "Created By", + "usersRole": "User's Role", + "changeRole": "Change Role", + "action": "Action", + "removeUser": "Remove User", + "remove": "Remove", + "viewProfile": "View Profile", + "profile": "Profile", + "noFiltersApplied": "No filters applied", + "manage": "Manage", + "searchResultsFor": "Search results for {{text}}", + "none": "None", + "sort": "Sort", + "Donate": "Donate", + "addedSuccessfully": "{{item}} added Successfully", + "updatedSuccessfully": "{{item}} updated Successfully", + "removedSuccessfully": "{{item}} removed Successfully", + "successfullyUpdated": "Successfully Updated" } diff --git a/public/locales/en/errors.json b/public/locales/en/errors.json index 90b2acca9f..155d747bcf 100644 --- a/public/locales/en/errors.json +++ b/public/locales/en/errors.json @@ -5,5 +5,6 @@ "notAuthorised": "Sorry! you are not Authorised!", "errorSendingMail": "Error sending mail", "emailNotRegistered": "Email not registered", - "notFoundMsg": "Oops! The Page you requested was not found!" + "notFoundMsg": "Oops! The Page you requested was not found!", + "errorOccurredCouldntCreate": "An error occurred. Couldn't create {{entity}}" } diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 6e58a2ea2a..33cdd02286 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -148,7 +148,9 @@ "roleUpdated": "Role Updated.", "joinNow": "Join Now", "visit": "Visit", - "withdraw": "Widthdraw" + "withdraw": "Widthdraw", + "removeUserFrom": "Remove User from {{org}}", + "removeConfirmation": "Are you sure you want to remove '{{name}}' from organization '{{org}}'?" }, "communityProfile": { "title": "Community Profile", @@ -253,6 +255,7 @@ "clearFilters": "Clear Filters", "completed": "Completed", "completionDate": "Completion Date", + "createActionItem": "Create Action Items", "deleteActionItem": "Delete Action Item", "deleteActionItemMsg": "Do you want to remove this action item?", "details": "Details", @@ -261,13 +264,14 @@ "editActionItem": "Edit Action Item", "isCompleted": "Completed", "latest": "Latest", + "makeActive": "Active", "noActionItems": "No Action Items", "options": "Options", - "preCompletionNotes": "Pre Completion Notes", + "preCompletionNotes": "Notes", "actionItemActive": "Active", "markCompletion": "Mark Completion", "actionItemStatus": "Action Item Status", - "postCompletionNotes": "Post Completion Notes", + "postCompletionNotes": "Completion Notes", "selectActionItemCategory": "Select an action item category", "selectAssignee": "Select an assignee", "status": "Status", @@ -276,6 +280,57 @@ "successfulDeletion": "Action Item deleted successfully", "title": "Action Items" }, + "organizationAgendaCategory": { + "agendaCategoryDetails": "Agenda Category Details", + "updateAgendaCategory": "Update Agenda Category", + "title": "Agenda Categories", + "name": "Category", + "description": "Description", + "createdBy": "Created By", + "options": "Options", + "createAgendaCategory": "Create Agenda Category", + "noAgendaCategories": "No Agenda Categories", + "update": "Update", + "agendaCategoryCreated": "Agenda Category created successfully", + "agendaCategoryUpdated": "Agenda Category updated successfully", + "agendaCategoryDeleted": "Agenda Category deleted successfully", + "deleteAgendaCategory": "Delete Agenda Category", + "deleteAgendaCategoryMsg": "Do you want to remove this agenda category?" + }, + "agendaItems": { + "agendaItemDetails": "Agenda Item Details", + "updateAgendaItem": "Update Agenda Item", + "title": "Title", + "enterTitle": "Enter Title", + "sequence": "Sequence", + "description": "Description", + "enterDescription": "Enter Description", + "category": "Agenda Category", + "attachments": "Attachments", + "attachmentLimit": "Add any image file or video file upto 10MB", + "fileSizeExceedsLimit": "File size exceeds the limit which is 10MB", + "urls": "URLs", + "url": "add link to URL", + "enterUrl": "https://example.com", + "invalidUrl": "Please enter a valid URL", + "link": "Link", + "createdBy": "Created By", + "regular": "Regular", + "note": "Note", + "duration": "Duration", + "enterDuration": "mm:ss", + "options": "Options", + "createAgendaItem": "Create Agenda Item", + "noAgendaItems": "No Agenda Items", + "selectAgendaItemCategory": "Select an agenda item category", + "update": "Update", + "delete": "Delete", + "agendaItemCreated": "Agenda Item created successfully", + "agendaItemUpdated": "Agenda Item updated successfully", + "agendaItemDeleted": "Agenda Item deleted successfully", + "deleteAgendaItem": "Delete Agenda Item", + "deleteAgendaItemMsg": "Do you want to remove this agenda item?" + }, "eventListCard": { "deleteEvent": "Delete Event", "deleteEventMsg": "Do you want to remove this event?", @@ -306,33 +361,24 @@ "title": "Funds", "createFund": "Create Fund", "fundName": "Fund Name", - "fundId": "Fund ID", - "fundOptions": "Opitons", - "noFunds": "No Funds Found", - "fundDetails": "Fund Details", + "fundId": "Fund (Reference) ID", "taxDeductible": "Tax Deductible", - "enterfundName": "Enter Fund Name", - "enterfundId": "Enter Fund ID", - "default": "Default Fund", + "default": "Default", "archived": "Archived", - "nonArchive": "Non-Archived", "fundCreate": "Create Fund", "fundUpdate": "Update Fund", "fundDelete": "Delete Fund", - "manageFund": "Manage Fund", - "searchFullName": "Search By Name", "noFundsFound": "No Funds Found", "createdBy": "Created By", "createdOn": "Created On", "status": "Status", - "archiveFund": "Archive Fund", - "archiveFundMsg": "On Archiving this fund will remove it from the fund listing.Thisaction can be undone", "fundCreated": "Fund created successfully", "fundUpdated": "Fund updated successfully", "fundDeleted": "Fund deleted successfully", - "fundArchived": "Fund archived successfully", - "fundUnarchived": "Fund unarchived successfully", - "deleteFundMsg": "Do you want to remove this fund?" + "deleteFundMsg": "Are you sure you want to delete this fund?", + "createdLatest": "Created Latest", + "createdEarliest": "Created Earliest", + "viewCampaigns": "View Campaigns" }, "fundCampaign": { "title": "Fundraising Campaigns", @@ -345,17 +391,21 @@ "deletedCampaign": "Campaign deleted successfully", "deleteCampaignMsg": "Are you sure you want to delete this campaign?", "noCampaigns": "No Campaigns Found", - "createCampaign": "Create Fund Campaign", - "updateCampaign": "Update Fund Campaign", - "manageCampaign": "Manage Fund Campaign", - "deleteCampaign": "Delete Fund Campaign", + "createCampaign": "Create Campaign", + "updateCampaign": "Update Campaign", + "deleteCampaign": "Delete Campaign", "currency": "Currency", "selectCurrency": "Select Currency", - "searchFullName": "Search By Name" + "searchFullName": "Search By Name", + "viewPledges": "View Pledges", + "noCampaignsFound": "No Campaigns Found", + "latestEndDate": "Latest End Date", + "earliestEndDate": "Earliest End Date", + "lowestGoal": "Lowest Goal", + "highestGoal": "Highest Goal" }, "pledges": { "title": "Fund Campaign Pledges", - "volunteers": "Volunteers", "pledgeAmount": "Pledge Amount", "pledgeOptions": "Options", "pledgeCreated": "Pledge created successfully", @@ -370,7 +420,17 @@ "amount": "Amount", "editPledge": "Edit Pledge", "deletePledgeMsg": "Are you sure you want to delete this pledge?", - "noPledges": "No Pledges Found" + "noPledges": "No Pledges Found", + "searchPledger": "Search By Pledgers", + "highestAmount": "Highest Amount", + "lowestAmount": "Lowest Amount", + "latestEndDate": "Latest End Date", + "earliestEndDate": "Earliest End Date", + "campaigns": "Campaigns", + "pledges": "Pledges", + "endsOn": "Ends on", + "raisedAmount": "Raised amount ", + "pledgedAmount": "Pledged amount" }, "orgPost": { "title": "Posts", @@ -455,6 +515,7 @@ "dashboard": "Dashboard", "registrants": "Registrants", "eventActions": "Event Actions", + "eventAgendas": "Event Agendas", "eventStats": "Event Statistics", "to": "TO" }, @@ -527,7 +588,9 @@ "userPasswordUpdate": { "previousPassword": "Previous Password", "newPassword": "New Password", - "confirmNewPassword": "Confirm New Password" + "confirmNewPassword": "Confirm New Password", + "passCantBeEmpty": "Password can't be empty", + "passNoMatch": "New and Confirm password do not match." }, "orgDelete": { "deleteOrg": "Delete Org" @@ -564,6 +627,7 @@ "addOnStore": { "title": "Add On Store", "searchName": "Ex: Donations", + "search": "Search", "enable": "Enabled", "disable": "Disabled", "pHeading": "Plugins", @@ -655,7 +719,12 @@ "viewAll": "View all", "talawaUserPortal": "Talawa User Portal", "my organizations": "My Organizations", - "communityProfile": "Community Profile" + "users": "Users", + "requests": "Requests", + "communityProfile": "Community Profile", + "logout": "Logout", + "settings": "Settings", + "chat": "Chat" }, "organizationSidebar": { "viewAll": "View all", @@ -665,7 +734,10 @@ }, "postCard": { "likes": "Likes", - "comments": "Comments" + "comments": "Comments", + "viewPost": "View Post", + "editPost": "Edit Post", + "postedOn": "Posted on {{date}}" }, "home": { "posts": "Posts", @@ -682,7 +754,8 @@ "startPost": "Start a post", "media": "Media", "event": "Event", - "article": "Article" + "article": "Article", + "postNowVisibleInFeed": "Post now visible in feed" }, "settings": { "profileSettings": "Profile Settings", @@ -716,7 +789,7 @@ "widowed": "Widowed", "divorced": "Divorced", "engaged": "Engaged", - "seperated": "Seperated", + "separated": "Separated", "grade1": "Grade 1", "grade2": "Grade 2", "grade3": "Grade 3", @@ -791,10 +864,15 @@ "deleteAdvertisement": "Delete Advertisement", "deleteAdvertisementMsg": "Do you want to remove this advertisement?", "view": "View", - "editAdvertisement": "Edit Advertisement" + "editAdvertisement": "Edit Advertisement", + "advertisementDeleted": "Advertisement deleted successfully.", + "endDateGreaterOrEqual": "End Date should be greater than or equal to Start Date", + "advertisementCreated": "Advertisement created successfully." }, "userChat": { "chat": "Chat", + "search": "Search", + "messages": "Messages", "contacts": "Contacts" }, "userChatRoom": { @@ -809,7 +887,11 @@ "customFieldType": "Field Type", "Remove Custom Field": "Remove Custom Field", "fieldSuccessMessage": "Field added successfully", - "fieldRemovalSuccess": "Field removed successfully" + "fieldRemovalSuccess": "Field removed successfully", + "String": "String", + "Boolean": "Boolean", + "Date": "Date", + "Number": "Number" }, "orgActionItemCategories": { "enableButton": "Enable", @@ -868,8 +950,16 @@ "actionItemCategory": "Action Item Category", "selectActionItemCategory": "Select an action item category", "selectAssignee": "Select an assignee", - "preCompletionNotes": "Pre Completion Notes", - "postCompletionNotes": "Post Completion Notes", + "assignee": "Assignee", + "assigner": "Assigner", + "preCompletionNotes": "Notes", + "postCompletionNotes": "Completion Notes", + "assignmentDate": "Assignment Date", + "status": "Status", + "actionItemActive": "Active", + "actionItemStatus": "Action Item Status", + "actionItemCompleted": "Action Item Completed", + "markCompletion": "Mark Completion", "actionItemDetails": "Action Item Details", "dueDate": "Due Date", "completionDate": "Completion Date", @@ -881,5 +971,13 @@ "successfulUpdation": "Action Item updated successfully", "notes": "Notes", "save": "Save" + }, + "checkIn": { + "errorCheckingIn": "Error checking in", + "checkedInSuccessfully": "Checked in successfully" + }, + "eventRegistrantsModal": { + "errorAddingAttendee": "Error adding attendee", + "errorRemovingAttendee": "Error removing attendee" } } diff --git a/public/locales/fr/common.json b/public/locales/fr/common.json index bce0b3bcea..250584da70 100644 --- a/public/locales/fr/common.json +++ b/public/locales/fr/common.json @@ -30,11 +30,13 @@ "search": "Recherche", "description": "Description", "saveChanges": "Sauvegarder les modifications", + "resetChanges": "Réinitialiser les modifications", "displayImage": "Afficher l'image", "enterEmail": "Entrez l'e-mail", "emailAddress": "Adresse e-mail", "email": "E-mail", "name": "Nom", + "desc": "Description", "enterPassword": "Entrer le mot de passe", "password": "Mot de passe", "confirmPassword": "Confirmez le mot de passe", @@ -61,5 +63,24 @@ "Membership Requests": "Demandes d'Adhésion", "Plugins": "Plugins", "Plugin Store": "Magasin de Plugins", - "Settings": "Paramètres" + "Settings": "Paramètres", + "createdOn": "Créé Le", + "createdBy": "Créé Par", + "usersRole": "Rôle de l'Utilisateur", + "changeRole": "Changer de Rôle", + "action": "Action", + "removeUser": "Supprimer l'Utilisateur", + "remove": "Supprimer", + "viewProfile": "Voir le Profil", + "profile": "Profil", + "noFiltersApplied": "Aucun filtre appliqué", + "manage": "Gérer", + "searchResultsFor": "Résultats de recherche pour {{text}}", + "none": "Aucun", + "sort": "Trier", + "Donate": "Faire un don", + "addedSuccessfully": "{{item}} ajouté avec succès", + "updatedSuccessfully": "{{item}} mis à jour avec succès", + "removedSuccessfully": "{{item}} supprimé avec succès", + "successfullyUpdated": "Mis à jour avec succès" } diff --git a/public/locales/fr/errors.json b/public/locales/fr/errors.json index 5788340a97..f5aea03266 100644 --- a/public/locales/fr/errors.json +++ b/public/locales/fr/errors.json @@ -5,5 +5,6 @@ "notAuthorised": "Désolé! ", "errorSendingMail": "Erreur lors de l'envoi du courrier", "emailNotRegistered": "Email non enregistré", - "notFoundMsg": "Oops! " + "notFoundMsg": "Oops! ", + "errorOccurredCouldntCreate": "Une erreur s'est produite. Impossible de créer {{entity}}" } diff --git a/public/locales/fr/translation.json b/public/locales/fr/translation.json index e9168770ce..d5c084fcfe 100644 --- a/public/locales/fr/translation.json +++ b/public/locales/fr/translation.json @@ -148,7 +148,9 @@ "roleUpdated": "Rôle mis à jour.", "joinNow": "Adhérer maintenant", "visit": "Visite", - "withdraw": "Largeur de tirage" + "withdraw": "Largeur de tirage", + "removeUserFrom": "Supprimer l'Utilisateur de {{org}}", + "removeConfirmation": "Êtes-vous sûr de vouloir supprimer '{{name}}' de l'organisation '{{org}}' ?" }, "communityProfile": { "title": "Profil de la communauté", @@ -256,6 +258,7 @@ "clearFilters": "Effacer les filtres", "completed": "Complété", "completionDate": "Date d'achèvement", + "createActionItem": "Créer un élément d'action", "deleteActionItem": "Supprimer l'élément d'action", "deleteActionItemMsg": "Voulez-vous supprimer cette action ?", "details": "Détails", @@ -264,6 +267,7 @@ "editActionItem": "Modifier l'élément d'action", "isCompleted": "Complété", "latest": "Dernier", + "makeActive": "Actif", "noActionItems": "Aucune action", "options": "Possibilités", "preCompletionNotes": "Notes préalables à l'achèvement", @@ -279,6 +283,57 @@ "successfulDeletion": "Élément d'action supprimé avec succès", "title": "Éléments d'action" }, + "organizationAgendaCategory": { + "agendaCategoryDetails": "Détails de la catégorie d'ordre du jour", + "updateAgendaCategory": "Mettre à jour la catégorie d'ordre du jour", + "title": "Catégories d'ordre du jour", + "name": "Catégorie", + "description": "Description", + "createdBy": "Créé par", + "options": "Options", + "createAgendaCategory": "Créer une catégorie d'ordre du jour", + "noAgendaCategories": "Aucune catégorie d'ordre du jour", + "update": "Mettre à jour", + "agendaCategoryCreated": "Catégorie d'ordre du jour créée avec succès", + "agendaCategoryUpdated": "Catégorie d'ordre du jour mise à jour avec succès", + "agendaCategoryDeleted": "Catégorie d'ordre du jour supprimée avec succès", + "deleteAgendaCategory": "Supprimer la catégorie d'ordre du jour", + "deleteAgendaCategoryMsg": "Souhaitez-vous supprimer cette catégorie d'ordre du jour ?" + }, + "agendaItems": { + "agendaItemDetails": "Détails du point de l'ordre du jour", + "updateAgendaItem": "Mettre à jour le point de l'ordre du jour", + "title": "Titre", + "enterTitle": "Entrer le titre", + "sequence": "Ordre", + "description": "Description", + "enterDescription": "Entrer la description", + "category": "Catégorie de l'ordre du jour", + "attachments": "Pièces jointes", + "attachmentLimit": "Ajouter un fichier image ou vidéo jusqu'à 10 Mo", + "fileSizeExceedsLimit": "La taille du fichier dépasse la limite de 10 Mo", + "urls": "URL", + "url": "Ajouter un lien vers l'URL", + "enterUrl": "https://example.com", + "invalidUrl": "Veuillez saisir une URL valide", + "link": "Lien", + "createdBy": "Créé par", + "regular": "Régulier", + "note": "Note", + "duration": "Durée", + "enterDuration": "mm:ss", + "options": "Options", + "createAgendaItem": "Créer un point à l'ordre du jour", + "noAgendaItems": "Aucun point à l'ordre du jour", + "selectAgendaItemCategory": "Sélectionner une catégorie de point de l'ordre du jour", + "update": "Mettre à jour", + "delete": "Supprimer", + "agendaItemCreated": "Point de l'ordre du jour créé avec succès", + "agendaItemUpdated": "Point de l'ordre du jour mis à jour avec succès", + "agendaItemDeleted": "Point de l'ordre du jour supprimé avec succès", + "deleteAgendaItem": "Supprimer le point de l'ordre du jour", + "deleteAgendaItemMsg": "Voulez-vous supprimer ce point de l'ordre du jour ?" + }, "eventListCard": { "deleteEvent": "Supprimer l'événement", "deleteEventMsg": "Voulez-vous supprimer cet événement ?", @@ -311,56 +366,52 @@ "title": "Fonds", "createFund": "Créer un fonds", "fundName": "Nom du fonds", - "fundId": "ID du fonds", - "fundOptions": "Options", - "noFunds": "Aucun fonds trouvé", - "fundDetails": "Détails du fonds", - "taxDeductible": "Déductible d'impôts", - "enterfundName": "Entrez le nom du fonds", - "enterfundId": "Entrez l'ID du fonds", - "default": "Fonds de défaut", + "fundId": "ID de référence du fonds", + "taxDeductible": "Déductible d'impôt", + "default": "Par défaut", "archived": "Archivé", - "nonArchive": "Non archivé", "fundCreate": "Créer un fonds", "fundUpdate": "Mettre à jour le fonds", "fundDelete": "Supprimer le fonds", - "manageFund": "Gérer le fonds", - "searchFullName": "Rechercher par nom", + "searchByName": "Rechercher par nom", "noFundsFound": "Aucun fonds trouvé", "createdBy": "Créé par", - "createdOn": "Créé sur", + "createdOn": "Créé le", "status": "Statut", - "archiveFund": "Fonds d'archives", - "archiveFundMsg": "Lors de l'archivage, ce fonds le supprimera de la liste des fonds. Cette action peut être annulée.", "fundCreated": "Fonds créé avec succès", "fundUpdated": "Fonds mis à jour avec succès", "fundDeleted": "Fonds supprimé avec succès", - "fundArchived": "Fonds archivé avec succès", - "fundUnarchived": "Fonds désarchivé avec succès", - "deleteFundMsg": "Voulez-vous supprimer ce fonds ?" + "deleteFundMsg": "Êtes-vous sûr de vouloir supprimer ce fonds ?", + "createdLatest": "Créé le plus récemment", + "createdEarliest": "Créé le plus tôt", + "viewCampaigns": "Voir les campagnes" }, "fundCampaign": { "title": "Campagnes de collecte de fonds", "campaignName": "Nom de la campagne", - "campaignOptions": "Possibilités", + "campaignOptions": "Options", "fundingGoal": "Objectif de financement", "addCampaign": "Ajouter une campagne", "createdCampaign": "Campagne créée avec succès", "updatedCampaign": "Campagne mise à jour avec succès", "deletedCampaign": "Campagne supprimée avec succès", - "deleteCampaignMsg": "Êtes-vous sûr de vouloir supprimer cette campagne ?", + "deleteCampaignMsg": "Êtes-vous sûr de vouloir supprimer cette campagne ?", "noCampaigns": "Aucune campagne trouvée", - "createCampaign": "Créer une campagne de financement", - "updateCampaign": "Mettre à jour la campagne de financement", - "manageCampaign": "Gérer la campagne de financement", - "deleteCampaign": "Supprimer la campagne de financement", + "createCampaign": "Créer une campagne", + "updateCampaign": "Mettre à jour la campagne", + "deleteCampaign": "Supprimer la campagne", "currency": "Devise", - "selectCurrency": "Sélectionnez la devise", - "searchFullName": "Rechercher par nom" + "selectCurrency": "Sélectionner la devise", + "searchFullName": "Rechercher par nom", + "viewPledges": "Voir les promesses de dons", + "noCampaignsFound": "Aucune campagne trouvée", + "latestEndDate": "Dernière date de fin", + "earliestEndDate": "Date de fin la plus ancienne", + "lowestGoal": "Objectif le plus bas", + "highestGoal": "Objectif le plus élevé" }, "pledges": { "title": "Engagements de campagne de financement", - "volunteers": "Bénévoles", "pledgeAmount": "Montant de la promesse de don", "pledgeOptions": "Possibilités", "pledgeCreated": "Engagement créé avec succès", @@ -375,7 +426,17 @@ "amount": "Montant", "editPledge": "Modifier l'engagement", "deletePledgeMsg": "Etes-vous sûr de vouloir supprimer cet engagement ?", - "noPledges": "Aucun engagement trouvé" + "noPledges": "Aucun engagement trouvé", + "searchPledger": "Rechercher par les bailleurs de fonds", + "highestAmount": "Montant le plus élevé", + "lowestAmount": "Montant le plus bas", + "latestEndDate": "Date de fin la plus récente", + "earliestEndDate": "Date de fin la plus proche", + "campaigns": "Campagnes", + "pledges": "Promesses de dons", + "endsOn": "Se termine le", + "raisedAmount": "Montant collecté", + "pledgedAmount": "Montant promis" }, "orgPost": { "title": "Des postes", @@ -460,6 +521,7 @@ "dashboard": "Tableau de bord", "registrants": "Inscrits", "eventActions": "Actions d'événement", + "eventAgendas": "Ordres du jour des événements", "eventStats": "Statistiques des événements", "to": "À" }, @@ -532,7 +594,9 @@ "userPasswordUpdate": { "previousPassword": "Mot de passe précédent", "newPassword": "nouveau mot de passe", - "confirmNewPassword": "Confirmer le nouveau mot de passe" + "confirmNewPassword": "Confirmer le nouveau mot de passe", + "passCantBeEmpty": "Le mot de passe ne peut pas être vide", + "passNoMatch": "Le nouveau mot de passe et la confirmation du mot de passe ne correspondent pas." }, "orgDelete": { "deleteOrg": "Supprimer l'organisation" @@ -569,6 +633,7 @@ "addOnStore": { "title": "Ajouter sur la boutique", "searchName": "Ex : Dons", + "search": "Rechercher", "enable": "Activé", "disable": "Désactivé", "pHeading": "Plugins", @@ -669,7 +734,10 @@ }, "postCard": { "likes": "Aime", - "comments": "commentaires" + "comments": "commentaires", + "viewPost": "Voir le message", + "editPost": "Modifier le message", + "postedOn": "Publié le {{date}}" }, "home": { "posts": "Des postes", @@ -686,7 +754,8 @@ "startPost": "Démarrer un message", "media": "Médias", "event": "Événement", - "article": "Article" + "article": "Article", + "postNowVisibleInFeed": "Le post est maintenant visible dans le fil d'actualité" }, "settings": { "profileSettings": "Paramètres de profil", @@ -720,7 +789,7 @@ "widowed": "Veuf", "divorced": "Divorcé", "engaged": "Engagé", - "seperated": "Séparé", + "separated": "Séparé", "grade1": "1re année", "grade2": "2e année", "grade3": "3e année", @@ -798,7 +867,10 @@ "deleteAdvertisement": "Supprimer la publicité", "deleteAdvertisementMsg": "Voulez-vous supprimer cette publicité ?", "view": "Voir", - "editAdvertisement": "Modifier l'annonce" + "editAdvertisement": "Modifier l'annonce", + "advertisementDeleted": "Publicité supprimée avec succès.", + "endDateGreaterOrEqual": "La date de fin doit être supérieure ou égale à la date de début", + "advertisementCreated": "Publicité créée avec succès." }, "userChat": { "chat": "Chat", @@ -816,7 +888,11 @@ "customFieldType": "Type de champ", "Remove Custom Field": "Supprimer le champ personnalisé", "fieldSuccessMessage": "Champ ajouté avec succès", - "fieldRemovalSuccess": "Champ supprimé avec succès" + "fieldRemovalSuccess": "Champ supprimé avec succès", + "String": "Chaîne", + "Boolean": "Booléen", + "Date": "Date", + "Number": "Nombre" }, "orgActionItemCategories": { "enableButton": "Activer", @@ -875,8 +951,8 @@ "actionItemCategory": "Catégorie d'élément d'action", "selectActionItemCategory": "Sélectionnez une catégorie d'élément d'action", "selectAssignee": "Sélectionnez un responsable", - "preCompletionNotes": "Notes préalables à l'achèvement", - "postCompletionNotes": "Notes post-achèvement", + "preCompletionNotes": "Remarques", + "postCompletionNotes": "Notes d'achèvement", "actionItemDetails": "Détails de l'action", "dueDate": "Date d'échéance", "completionDate": "Date d'achèvement", @@ -887,6 +963,22 @@ "successfulCreation": "Élément d'action créé avec succès", "successfulUpdation": "Élément d'action mis à jour avec succès", "notes": "Remarques", + "assignee": "Cessionnaire", + "assigner": "Assigner", + "assignmentDate": "Date d'affectation", + "status": "Statut", + "actionItemActive": "Actif", + "actionItemStatus": "Statut de l'action", + "actionItemCompleted": "Élément d'action terminé", + "markCompletion": "Marquer l'achèvement", "save": "Sauvegarder" + }, + "checkIn": { + "errorCheckingIn": "Erreur lors de l'enregistrement", + "checkedInSuccessfully": "Enregistrement réussi" + }, + "eventRegistrantsModal": { + "errorAddingAttendee": "Erreur lors de l'ajout du participant", + "errorRemovingAttendee": "Erreur lors de la suppression du participant" } } diff --git a/public/locales/hi/common.json b/public/locales/hi/common.json index 1a6ed161e7..3889f73e59 100644 --- a/public/locales/hi/common.json +++ b/public/locales/hi/common.json @@ -30,11 +30,13 @@ "search": "खोज", "description": "विवरण", "saveChanges": "परिवर्तनों को सुरक्षित करें", + "resetChanges": "परिवर्तनों को रीसेट करें", "displayImage": "प्रदर्शन छवि", "enterEmail": "ईमेल दर्ज करें", "emailAddress": "मेल पता", "email": "ईमेल", "name": "नाम", + "desc": "विवरण", "enterPassword": "पास वर्ड दर्ज करें", "password": "पासवर्ड", "confirmPassword": "पासवर्ड की पुष्टि कीजिये", @@ -61,5 +63,24 @@ "Membership Requests": "सदस्यता अनुरोध", "Plugins": "प्लगइन्स", "Plugin Store": "प्लगइन स्टोर", - "Settings": "सेटिंग्स" + "Settings": "सेटिंग्स", + "createdOn": "बनाया गया", + "createdBy": "के द्वारा बनाया गया", + "usersRole": "उपयोगकर्ता की भूमिका", + "changeRole": "भूमिका बदलें", + "action": "क्रिया", + "removeUser": "उपयोगकर्ता हटाएं", + "remove": "हटाएं", + "viewProfile": "प्रोफ़ाइल देखें", + "profile": "प्रोफ़ाइल", + "noFiltersApplied": "कोई फ़िल्टर लागू नहीं हैं", + "manage": "प्रबंधित करें", + "searchResultsFor": "{{text}} के लिए खोज परिणाम", + "none": "कोई नहीं", + "sort": "क्रम से लगाना", + "Donate": "दान करें", + "addedSuccessfully": "{{item}} सफलतापूर्वक जोड़ा गया", + "updatedSuccessfully": "{{item}} सफलतापूर्वक अपडेट किया गया", + "removedSuccessfully": "{{item}} सफलतापूर्वक हटाया गया", + "successfullyUpdated": "सफलतापूर्वक अपडेट किया गया" } diff --git a/public/locales/hi/errors.json b/public/locales/hi/errors.json index 5e08ee8e9e..c31c72fa34 100644 --- a/public/locales/hi/errors.json +++ b/public/locales/hi/errors.json @@ -5,5 +5,6 @@ "notAuthorised": "क्षमा मांगना! ", "errorSendingMail": "मेल भेजने में त्रुटि", "emailNotRegistered": "ईमेल पंजीकृत नहीं है", - "notFoundMsg": "उफ़! " + "notFoundMsg": "उफ़! ", + "errorOccurredCouldntCreate": "एक त्रुटि हुई। {{entity}} नहीं बना सके" } diff --git a/public/locales/hi/translation.json b/public/locales/hi/translation.json index 41a8741eca..ab850249e2 100644 --- a/public/locales/hi/translation.json +++ b/public/locales/hi/translation.json @@ -148,7 +148,9 @@ "roleUpdated": "भूमिका अद्यतन की गई.", "joinNow": "अब शामिल हों", "visit": "मिलने जाना", - "withdraw": "चौड़ाई निकालना" + "withdraw": "चौड़ाई निकालना", + "removeUserFrom": "{{org}} से उपयोगकर्ता हटाएं", + "removeConfirmation": "क्या आप वाकई '{{org}}' संगठन से '{{name}}' को हटाना चाहते हैं?" }, "communityProfile": { "title": "सामुदायिक प्रोफ़ाइल", @@ -256,6 +258,7 @@ "clearFilters": "फ़िल्टर साफ़ करें", "completed": "पुरा होना।", "completionDate": "पूरा करने की तिथि", + "createActionItem": "कार्रवाई आइटम बनाएं", "deleteActionItem": "क्रिया आइटम हटाएँ", "deleteActionItemMsg": "क्या आप इस क्रिया आइटम को हटाना चाहते हैं?", "details": "विवरण", @@ -264,6 +267,7 @@ "editActionItem": "क्रिया आइटम संपादित करें", "isCompleted": "पुरा होना।", "latest": "नवीनतम", + "makeActive": "सक्रिय", "noActionItems": "कोई एक्शन आइटम नहीं", "options": "विकल्प", "preCompletionNotes": "समापन पूर्व नोट्स", @@ -279,6 +283,57 @@ "successfulDeletion": "कार्रवाई आइटम सफलतापूर्वक हटा दिया गया", "title": "एक्शन आइटम्स" }, + "organizationAgendaCategory": { + "agendaCategoryDetails": "एजेंडा श्रेणी विवरण", + "updateAgendaCategory": "एजेंडा श्रेणी अपडेट करें", + "title": "एजेंडा श्रेणियाँ", + "name": "श्रेणी", + "description": "विवरण", + "createdBy": "द्वारा बनाया गया", + "options": "विकल्प", + "createAgendaCategory": "एजेंडा श्रेणी बनाएं", + "noAgendaCategories": "कोई एजेंडा श्रेणी नहीं", + "update": "अपडेट करें", + "agendaCategoryCreated": "एजेंडा श्रेणी सफलतापूर्वक बनाई गई", + "agendaCategoryUpdated": "एजेंडा श्रेणी सफलतापूर्वक अपडेट की गई", + "agendaCategoryDeleted": "एजेंडा श्रेणी सफलतापूर्वक हटा दी गई", + "deleteAgendaCategory": "एजेंडा श्रेणी हटाएं", + "deleteAgendaCategoryMsg": "क्या आप इस एजेंडा श्रेणी को हटाना चाहते हैं?" + }, + "agendaItems": { + "agendaItemDetails": "एजेंडा आइटम विवरण", + "updateAgendaItem": "एजेंडा आइटम अपडेट करें", + "title": "शीर्षक", + "enterTitle": "शीर्षक दर्ज करें", + "sequence": "क्रम", + "description": "विवरण", + "enterDescription": "विवरण दर्ज करें", + "category": "एजेंडा श्रेणी", + "attachments": "संलग्नक", + "attachmentLimit": "10MB तक कोई भी छवि फ़ाइल या वीडियो फ़ाइल जोड़ें", + "fileSizeExceedsLimit": "फ़ाइल का आकार सीमा 10MB से अधिक है", + "urls": "URL", + "url": "URL में लिंक जोड़ें", + "enterUrl": "https://example.com", + "invalidUrl": "कृपया एक वैध URL दर्ज करें", + "link": "लिंक", + "createdBy": "बनाया गया द्वारा", + "regular": "नियमित", + "note": "नोट", + "duration": "अवधि", + "enterDuration": "मिमी:से", + "options": "विकल्प", + "createAgendaItem": "एजेंडा आइटम बनाएं", + "noAgendaItems": "कोई एजेंडा आइटम नहीं", + "selectAgendaItemCategory": "एजेंडा आइटम श्रेणी चुनें", + "update": "अपडेट करें", + "delete": "हटाएं", + "agendaItemCreated": "एजेंडा आइटम सफलतापूर्वक बनाया गया", + "agendaItemUpdated": "एजेंडा आइटम सफलतापूर्वक अपडेट किया गया", + "agendaItemDeleted": "एजेंडा आइटम सफलतापूर्वक हटा दिया गया", + "deleteAgendaItem": "एजेंडा आइटम हटाएं", + "deleteAgendaItemMsg": "क्या आप इस एजेंडा आइटम को हटाना चाहते हैं?" + }, "eventListCard": { "deleteEvent": "ईवेंट हटाएँ", "deleteEventMsg": "क्या आप इस ईवेंट को हटाना चाहते हैं?", @@ -309,58 +364,54 @@ }, "funds": { "title": "फंड", - "createFund": "फंड बनाएं", + "createFund": "फंड बनाएँ", "fundName": "फंड का नाम", - "fundId": "फंड आईडी", - "fundOptions": "Opitons", - "noFunds": "कोई फंड नहीं मिला", - "fundDetails": "फंड विवरण", - "taxDeductible": "कर छूट", - "enterfundName": "फंड का नाम दर्ज करें", - "enterfundId": "फंड आईडी दर्ज करें", - "default": "डिफ़ॉल्ट फंड", - "archived": "संग्रहीत", - "nonArchive": "गैर-अभिलेखित", - "fundCreate": "फंड बनाएं", - "fundUpdate": "अद्यतन निधि", - "fundDelete": "फ़ंड हटाएँ", - "manageFund": "फंड का प्रबंधन करें", - "searchFullName": "नाम से खोजें", + "fundId": "फंड (संदर्भ) आईडी", + "taxDeductible": "कर ड्यूटी कटाई", + "default": "डिफ़ॉल्ट", + "archived": "आर्काइव", + "fundCreate": "फंड बनाएँ", + "fundUpdate": "फंड अपडेट करें", + "fundDelete": "फंड को हटाएँ", + "searchByName": "नाम से खोजें", "noFundsFound": "कोई फंड नहीं मिला", - "createdBy": "के द्वारा बनाई गई", - "createdOn": "पर बनाया", + "createdBy": "द्वारा बनाया गया", + "createdOn": "पर बनाया गया", "status": "स्थिति", - "archiveFund": "पुरालेख कोष", - "archiveFundMsg": "इस फंड को संग्रहित करने पर इसे फंड सूची से हटा दिया जाएगा। इस कार्रवाई को पूर्ववत किया जा सकता है", "fundCreated": "फंड सफलतापूर्वक बनाया गया", "fundUpdated": "फंड सफलतापूर्वक अपडेट किया गया", - "fundDeleted": "फंड सफलतापूर्वक हटा दिया गया", - "fundArchived": "निधि सफलतापूर्वक संग्रहित की गई", - "fundUnarchived": "फंड सफलतापूर्वक संग्रहित किया गया", - "deleteFundMsg": "क्या आप इस फंड को हटाना चाहते हैं?" + "fundDeleted": "फंड सफलतापूर्वक हटाया गया", + "deleteFundMsg": "क्या आप वाकई इस फंड को हटाना चाहते हैं?", + "createdLatest": "सबसे पहले बनाया", + "createdEarliest": "सबसे जल्दी बनाया", + "viewCampaigns": "कैम्पेंस देखें" }, "fundCampaign": { - "title": "धन उगाही अभियान", - "campaignName": "अभियान का नाम", + "title": "फंडरेजिंग कैंपेन", + "campaignName": "कैंपेन का नाम", "campaignOptions": "विकल्प", - "fundingGoal": "वित्त पोषण लक्ष्य", - "addCampaign": "अभियान जोड़ें", - "createdCampaign": "अभियान सफलतापूर्वक बनाया गया", - "updatedCampaign": "अभियान सफलतापूर्वक अपडेट किया गया", - "deletedCampaign": "अभियान सफलतापूर्वक हटा दिया गया", - "deleteCampaignMsg": "क्या आप वाकई इस अभियान को हटाना चाहते हैं?", - "noCampaigns": "कोई अभियान नहीं मिला", - "createCampaign": "फंड अभियान बनाएं", - "updateCampaign": "अद्यतन निधि अभियान", - "manageCampaign": "फंड अभियान प्रबंधित करें", - "deleteCampaign": "फ़ंड अभियान हटाएँ", + "fundingGoal": "फंडिंग उद्देश्य", + "addCampaign": "कैंपेन जोड़ें", + "createdCampaign": "कैंपेन सफलतापूर्वक बनाई गई", + "updatedCampaign": "कैंपेन सफलतापूर्वक अपडेट की गई", + "deletedCampaign": "कैंपेन सफलतापूर्वक हटा दी गई", + "deleteCampaignMsg": "क्या आप वाकई इस कैंपेन को हटाना चाहते हैं?", + "noCampaigns": "कोई कैंपेन नहीं मिली", + "createCampaign": "कैंपेन बनाएँ", + "updateCampaign": "कैंपेन अपडेट करें", + "deleteCampaign": "कैंपेन को हटाएं", "currency": "मुद्रा", - "selectCurrency": "मुद्रा चुनें", - "searchFullName": "नाम से खोजें" + "selectCurrency": "मुद्रा का चयन करें", + "searchFullName": "नाम से खोजें", + "viewPledges": "प्लेज देखें", + "noCampaignsFound": "कोई कैंपेन नहीं मिली", + "latestEndDate": "अंतिम समाप्ति तिथि", + "earliestEndDate": "सबसे पहली समाप्ति तिथि", + "lowestGoal": "सबसे कम उद्देश्य", + "highestGoal": "सबसे ऊंचा उद्देश्य" }, "pledges": { "title": "निधि अभियान प्रतिज्ञाएँ", - "volunteers": "स्वयंसेवकों", "pledgeAmount": "प्रतिज्ञा राशि", "pledgeOptions": "विकल्प", "pledgeCreated": "प्रतिज्ञा सफलतापूर्वक बनाई गई", @@ -375,7 +426,17 @@ "amount": "मात्रा", "editPledge": "प्रतिज्ञा संपादित करें", "deletePledgeMsg": "क्या आप वाकई इस प्रतिज्ञा को हटाना चाहते हैं?", - "noPledges": "कोई प्रतिज्ञा नहीं मिली" + "noPledges": "कोई प्रतिज्ञा नहीं मिली", + "searchPledger": "प्लेजर्स के द्वारा खोजें", + "highestAmount": "सबसे अधिक राशि", + "lowestAmount": "सबसे कम राशि", + "latestEndDate": "नवीनतम समाप्ति तिथि", + "earliestEndDate": "सबसे प्रारंभिक समाप्ति तिथि", + "campaigns": "अभियान", + "pledges": "प्रतिज्ञाएँ", + "endsOn": "पर समाप्त होता है", + "raisedAmount": "उठाया गया राशि", + "pledgedAmount": "प्रतिबद्ध राशि" }, "orgPost": { "title": "पदों", @@ -460,6 +521,7 @@ "dashboard": "डैशबोर्ड", "registrants": "कुलसचिव", "eventActions": "घटना क्रियाएँ", + "eventAgendas": "इवेंट एजेंडा", "eventStats": "घटना सांख्यिकी", "to": "को" }, @@ -532,7 +594,9 @@ "userPasswordUpdate": { "previousPassword": "पिछला पासवर्ड", "newPassword": "नया पासवर्ड", - "confirmNewPassword": "नए पासवर्ड की पुष्टि करें" + "confirmNewPassword": "नए पासवर्ड की पुष्टि करें", + "passCantBeEmpty": "पासवर्ड खाली नहीं हो सकता", + "passNoMatch": "नया पासवर्ड और पुष्टि पासवर्ड मेल नहीं खाते।" }, "orgDelete": { "deleteOrg": "संगठन हटाएं" @@ -569,6 +633,7 @@ "addOnStore": { "title": "स्टोर पर जोड़ें", "searchName": "उदाहरणार्थ: दान", + "search": "खोजें", "enable": "सक्रिय", "disable": "अक्षम", "pHeading": "प्लग-इन", @@ -669,7 +734,10 @@ }, "postCard": { "likes": "पसंद है", - "comments": "टिप्पणियाँ" + "comments": "टिप्पणियाँ", + "viewPost": "पोस्ट देखें", + "editPost": "पोस्ट संपादित करें", + "postedOn": "{{date}} को पोस्ट किया गया" }, "home": { "posts": "पदों", @@ -686,7 +754,8 @@ "startPost": "एक पोस्ट प्रारंभ करें", "media": "मिडिया", "event": "आयोजन", - "article": "लेख" + "article": "लेख", + "postNowVisibleInFeed": "पोस्ट अब फीड में दिखाई दे रहा है" }, "settings": { "profileSettings": "पार्श्वचित्र समायोजन", @@ -720,7 +789,7 @@ "widowed": "विधवा", "divorced": "तलाकशुदा", "engaged": "काम में लगा हुआ", - "seperated": "विभाजित", + "separated": "विभाजित", "grade1": "ग्रेड 1", "grade2": "ग्रेड 2", "grade3": "ग्रेड 3", @@ -798,7 +867,10 @@ "deleteAdvertisement": "विज्ञापन हटाएँ", "deleteAdvertisementMsg": "क्या आप यह विज्ञापन हटाना चाहते हैं?", "view": "देखना", - "editAdvertisement": "विज्ञापन संपादित करें" + "editAdvertisement": "विज्ञापन संपादित करें", + "advertisementDeleted": "विज्ञापन सफलतापूर्वक हटाया गया।", + "endDateGreaterOrEqual": "समाप्ति तिथि प्रारंभ तिथि से अधिक या उसके बराबर होनी चाहिए", + "advertisementCreated": "विज्ञापन सफलतापूर्वक बनाया गया।" }, "userChat": { "chat": "बात करना", @@ -816,7 +888,11 @@ "customFieldType": "क्षेत्र प्रकार", "Remove Custom Field": "कस्टम फ़ील्ड हटाएँ", "fieldSuccessMessage": "फ़ील्ड सफलतापूर्वक जोड़ा गया", - "fieldRemovalSuccess": "फ़ील्ड सफलतापूर्वक हटा दी गई" + "fieldRemovalSuccess": "फ़ील्ड सफलतापूर्वक हटा दी गई", + "String": "स्ट्रिंग", + "Boolean": "बूलियन", + "Date": "तारीख", + "Number": "संख्या" }, "orgActionItemCategories": { "enableButton": "सक्षम", @@ -875,8 +951,8 @@ "actionItemCategory": "कार्य आइटम श्रेणी", "selectActionItemCategory": "एक क्रिया आइटम श्रेणी का चयन करें", "selectAssignee": "एक समनुदेशिती का चयन करें", - "preCompletionNotes": "समापन पूर्व नोट्स", - "postCompletionNotes": "समापन के बाद के नोट्स", + "preCompletionNotes": "टिप्पणियाँ", + "postCompletionNotes": "समापन नोट्स", "actionItemDetails": "कार्रवाई मद विवरण", "dueDate": "नियत तारीख", "completionDate": "पूरा करने की तिथि", @@ -887,6 +963,22 @@ "successfulCreation": "कार्रवाई आइटम सफलतापूर्वक बनाया गया", "successfulUpdation": "कार्रवाई आइटम सफलतापूर्वक अपडेट किया गया", "notes": "टिप्पणियाँ", + "assignee": "संपत्ति-भागी", + "assigner": "असाइनर", + "assignmentDate": "असाइनमेंट तिथि", + "status": "स्थिति", + "actionItemActive": "सक्रिय", + "actionItemStatus": "कार्रवाई आइटम स्थिति", + "actionItemCompleted": "कार्रवाई आइटम पूर्ण हुआ", + "markCompletion": "पूर्णता को चिह्नित करें", "save": "बचाना" + }, + "checkIn": { + "errorCheckingIn": "चेक-इन में त्रुटि", + "checkedInSuccessfully": "सफलतापूर्वक चेक-इन किया गया" + }, + "eventRegistrantsModal": { + "errorAddingAttendee": "उपस्थित होने वाले को जोड़ने में त्रुटि", + "errorRemovingAttendee": "उपस्थित होने वाले को हटाने में त्रुटि" } } diff --git a/public/locales/sp/common.json b/public/locales/sp/common.json index dfd1a960bd..d784652da5 100644 --- a/public/locales/sp/common.json +++ b/public/locales/sp/common.json @@ -30,11 +30,13 @@ "search": "Search", "description": "Description", "saveChanges": "Save Changes", + "resetChanges": "Reset Changes", "displayImage": "Display Image", "enterEmail": "Enter Email", "emailAddress": "Email Address", "email": "Email", "name": "Name", + "desc": "Description", "enterPassword": "Enter Password", "password": "Password", "confirmPassword": "Confirm Password", @@ -61,5 +63,24 @@ "Membership Requests": "Solicitudes de Membresía", "Plugins": "Complementos", "Plugin Store": "Tienda de Complementos", - "Settings": "Configuraciones" + "Settings": "Configuraciones", + "createdOn": "Creado En", + "createdBy": "Creado Por", + "usersRole": "Rol del Usuario", + "changeRole": "Cambiar Rol", + "action": "Acción", + "removeUser": "Eliminar Usuario", + "remove": "Eliminar", + "viewProfile": "Ver Perfil", + "profile": "Perfil", + "noFiltersApplied": "No se aplicaron filtros", + "manage": "Administrar", + "searchResultsFor": "Resultados de búsqueda para {{text}}", + "none": "Ninguno", + "sort": "Ordenar", + "Donate": "Donar", + "addedSuccessfully": "{{item}} agregado con éxito", + "updatedSuccessfully": "{{item}} actualizado con éxito", + "removedSuccessfully": "{{item}} eliminado con éxito", + "successfullyUpdated": "Actualizado con éxito" } diff --git a/public/locales/sp/errors.json b/public/locales/sp/errors.json index 90b2acca9f..7d5440637f 100644 --- a/public/locales/sp/errors.json +++ b/public/locales/sp/errors.json @@ -5,5 +5,6 @@ "notAuthorised": "Sorry! you are not Authorised!", "errorSendingMail": "Error sending mail", "emailNotRegistered": "Email not registered", - "notFoundMsg": "Oops! The Page you requested was not found!" + "notFoundMsg": "Oops! The Page you requested was not found!", + "errorOccurredCouldntCreate": "Ocurrió un error. No se pudo crear {{entity}}" } diff --git a/public/locales/sp/translation.json b/public/locales/sp/translation.json index c084402939..2d5f46db2b 100644 --- a/public/locales/sp/translation.json +++ b/public/locales/sp/translation.json @@ -225,7 +225,9 @@ "orgJoined": "Unido a la organización exitosamente", "MembershipRequestSent": "Solicitud de membresía enviada exitosamente", "AlreadyJoined": "Ya eres miembro de esta organización.", - "errorOccured": "Se produjo un error. Por favor, inténtalo de nuevo más tarde." + "errorOccured": "Se produjo un error. Por favor, inténtalo de nuevo más tarde.", + "removeUserFrom": "Eliminar Usuario de {{org}}", + "removeConfirmation": "¿Está seguro de que desea eliminar a '{{name}}' de la organización '{{org}}'?" }, "communityProfile": { "title": "Perfil de la comunidad", @@ -370,7 +372,7 @@ "close": "Cerrar", "completed": "Completado", "completionDate": "Fecha de finalización", - "createActionItem": "Crear", + "createActionItem": "Crear ítem de acción", "deleteActionItem": "Eliminar ítem de acción", "deleteActionItemMsg": "¿Desea eliminar este ítem de acción?", "details": "Detalles", @@ -396,6 +398,57 @@ "title": "Ítems de acción", "yes": "Sí" }, + "organizationAgendaCategory": { + "agendaCategoryDetails": "Detalles de la categoría de la agenda", + "updateAgendaCategory": "Actualizar categoría de la agenda", + "title": "Categorías de la agenda", + "name": "Categoría", + "description": "Descripción", + "createdBy": "Creado por", + "options": "Opciones", + "createAgendaCategory": "Crear categoría de la agenda", + "noAgendaCategories": "No hay categorías de la agenda", + "update": "Actualizar", + "agendaCategoryCreated": "Categoría de la agenda creada exitosamente", + "agendaCategoryUpdated": "Categoría de la agenda actualizada exitosamente", + "agendaCategoryDeleted": "Categoría de la agenda eliminada exitosamente", + "deleteAgendaCategory": "Eliminar categoría de la agenda", + "deleteAgendaCategoryMsg": "¿Desea eliminar esta categoría de la agenda?" + }, + "agendaItems": { + "agendaItemDetails": "Detalles del punto del orden del día", + "updateAgendaItem": "Actualizar punto del orden del día", + "title": "Título", + "enterTitle": "Ingresar título", + "sequence": "Secuencia", + "description": "Descripción", + "enterDescription": "Ingresar descripción", + "category": "Categoría del orden del día", + "attachments": "Archivos adjuntos", + "attachmentLimit": "Agregar cualquier archivo de imagen o video hasta 10MB", + "fileSizeExceedsLimit": "El tamaño del archivo excede el límite de 10MB", + "urls": "URLs", + "url": "Agregar enlace a URL", + "enterUrl": "https://example.com", + "invalidUrl": "Ingrese una URL válida", + "link": "Enlace", + "createdBy": "Creado por", + "regular": "Regular", + "note": "Nota", + "duration": "Duración", + "enterDuration": "mm:ss", + "options": "Opciones", + "createAgendaItem": "Crear punto del orden del día", + "noAgendaItems": "No hay puntos del orden del día", + "selectAgendaItemCategory": "Seleccionar una categoría de punto del orden del día", + "update": "Actualizar", + "delete": "Eliminar", + "agendaItemCreated": "Punto del orden del día creado exitosamente", + "agendaItemUpdated": "Punto del orden del día actualizado exitosamente", + "agendaItemDeleted": "Punto del orden del día eliminado exitosamente", + "deleteAgendaItem": "Eliminar punto del orden del día", + "deleteAgendaItemMsg": "¿Desea eliminar este punto del orden del día?" + }, "eventListCard": { "location": "Lugar del evento", "deleteEvent": "Eliminar evento", @@ -437,65 +490,53 @@ "funds": { "title": "Fondos", "createFund": "Crear fondo", - "fundName": "Nombre del Fondo", - "fundId": "ID del Fondo", - "fundOptions": "Opciones", - "noFunds": "No se encontraron fondos", - "fundDetails": "Detalles del Fondo", + "fundName": "Nombre del fondo", + "fundId": "ID de referencia del fondo", "taxDeductible": "Deducible de impuestos", - "enterfundName": "Ingrese el nombre del fondo", - "enterfundId": "Ingrese el ID del fondo", - "default": "Fondo predeterminado", + "default": "Predeterminado", "archived": "Archivado", - "nonArchive": "No archivado", - "fundCreate": "Crear Fondo", - "fundUpdate": "Actualizar Fondo", - "fundDelete": "Eliminar Fondo", - "no": "No", - "yes": "Sí", - "manageFund": "Administrar fondo", - "searchFullName": "Buscar por nombre", - "filter": "Filtrar", + "fundCreate": "Crear fondo", + "fundUpdate": "Actualizar fondo", + "fundDelete": "Eliminar fondo", + "searchByName": "Buscar por nombre", "noFundsFound": "No se encontraron fondos", "createdBy": "Creado por", - "createdOn": "Creado el", + "createdOn": "Creado en", "status": "Estado", - "archiveFund": "Archivar Fondo", - "archiveFundMsg": "¿Desea archivar este fondo?", - "fundCreated": "Fondo creado exitosamente", - "fundUpdated": "Fondo actualizado exitosamente", - "fundDeleted": "Fondo eliminado exitosamente", - "fundArchived": "Fondo archivado exitosamente", - "fundUnarchived": "Fondo no archivado exitosamente", - "deleteFundMsg": "¿Desea eliminar este fondo?" + "fundCreated": "Fondo creado correctamente", + "fundUpdated": "Fondo actualizado correctamente", + "fundDeleted": "Fondo eliminado correctamente", + "deleteFundMsg": "¿Está seguro de que desea eliminar este fondo?", + "createdLatest": "Creado más reciente", + "createdEarliest": "Creado más temprano", + "viewCampaigns": "Ver campañas" }, "fundCampaign": { "title": "Campañas de recaudación de fondos", "campaignName": "Nombre de la campaña", - "startDate": "Fecha de inicio", - "endDate": "Fecha de finalización", - "campaignOptions": "Opciones de la campaña", - "fundingGoal": "Meta de financiamiento", + "campaignOptions": "Opciones", + "fundingGoal": "Meta de financiación", "addCampaign": "Agregar campaña", - "createdCampaign": "Campaña creada exitosamente", - "updatedCampaign": "Campaña actualizada exitosamente", - "deletedCampaign": "Campaña eliminada exitosamente", - "deleteCampaignMsg": "¿Desea eliminar esta campaña?", + "createdCampaign": "Campaña creada correctamente", + "updatedCampaign": "Campaña actualizada correctamente", + "deletedCampaign": "Campaña eliminada correctamente", + "deleteCampaignMsg": "¿Está seguro de que desea eliminar esta campaña?", "noCampaigns": "No se encontraron campañas", - "createCampaign": "Crear campaña de recaudación de fondos", - "updateCampaign": "Actualizar campaña de recaudación de fondos", - "manageCampaign": "Administrar campaña de recaudación de fondos", - "deleteCampaign": "Eliminar campaña de recaudación de fondos", - "no": "No", - "yes": "Sí", + "createCampaign": "Crear campaña", + "updateCampaign": "Actualizar campaña", + "deleteCampaign": "Eliminar campaña", "currency": "Moneda", "selectCurrency": "Seleccionar moneda", - "filter": "Filtrar", - "searchFullName": "Buscar por nombre" + "searchFullName": "Buscar por nombre", + "viewPledges": "Ver compromisos", + "noCampaignsFound": "No se encontraron campañas", + "latestEndDate": "Fecha de finalización más reciente", + "earliestEndDate": "Fecha de finalización más temprana", + "lowestGoal": "Meta más baja", + "highestGoal": "Meta más alta" }, "pledges": { "title": "Compromisos de Campaña de Financiamiento", - "volunteers": "Voluntarios", "startDate": "Fecha de Inicio", "endDate": "Fecha de Finalización", "pledgeAmount": "Monto del Compromiso", @@ -512,9 +553,17 @@ "amount": "Monto", "editPledge": "Editar Compromiso", "deletePledgeMsg": "¿Estás seguro de que quieres eliminar este compromiso?", - "no": "No", - "yes": "Sí", - "noPledges": "No se encontraron compromisos" + "noPledges": "No se encontraron compromisos", + "searchPledger": "Buscar por compromisos", + "highestAmount": "Cantidad más alta", + "lowestAmount": "Cantidad más baja", + "latestEndDate": "Fecha de finalización más reciente", + "earliestEndDate": "Fecha de finalización más cercana", + "campaigns": "Campañas", + "pledges": "Compromisos", + "endsOn": "Finaliza el", + "raisedAmount": "Monto recaudado", + "pledgedAmount": "Monto comprometido" }, "orgPost": { @@ -611,6 +660,7 @@ "dashboard": "Tablero", "registrants": "Inscritos", "eventActions": "Acciones del evento", + "eventAgendas": "Agendas de eventos", "eventStats": "Estadísticas del evento", "to": "A" }, @@ -702,7 +752,9 @@ "newPassword": "Nueva contraseña", "confirmNewPassword": "Confirmar nueva contraseña", "saveChanges": "Guardar cambios", - "cancel": "Cancelar" + "cancel": "Cancelar", + "passCantBeEmpty": "La contraseña no puede estar vacía", + "passNoMatch": "La nueva contraseña y la confirmación no coinciden." }, "orgDelete": { "deleteOrg": "Eliminar organización" @@ -751,14 +803,14 @@ "addOnStore": { "title": "Tienda de complementos", "searchName": "Ej: Donaciones", + "search": "Buscar", "enable": "Activada", "disable": "Desactivada", "pHeading": "Complementos", "install": "Instalada", "available": "Disponible", "pMessage": "El complemento no existe", - "filter": "filtros", - "search": "Buscar" + "filter": "filtros" }, "addOnEntry": { "enable": "Activada", @@ -883,7 +935,10 @@ }, "postCard": { "likes": "Gustos", - "comments": "Comentarios" + "comments": "Comentarios", + "viewPost": "Ver publicación", + "editPost": "Editar publicación", + "postedOn": "Publicado el {{date}}" }, "home": { "feed": "Alimentar", @@ -893,7 +948,8 @@ "startPost": "Comenzar una publicación", "media": "Medios", "event": "Evento", - "article": "Artículo" + "article": "Artículo", + "postNowVisibleInFeed": "La publicación ahora es visible en el feed" }, "settings": { "settings": "Ajustes", @@ -934,7 +990,7 @@ "divorced": "Divorciado", "widowed": "Viudo", "engaged": "Comprometido", - "seperated": "Separado", + "separated": "Separado", "grade1": "1er Grado", "grade2": "2do Grado", "grade3": "3er Grado", @@ -1021,6 +1077,9 @@ "view": "Ver", "edit": "Editar", "editAdvertisement": "Editar Anuncio", + "advertisementDeleted": "Anuncio eliminado con éxito.", + "endDateGreaterOrEqual": "La fecha de finalización debe ser mayor o igual a la fecha de inicio", + "advertisementCreated": "Anuncio creado con éxito.", "saveChanges": "Guardar Cambios", "endOfResults": "Fin de los resultados" }, @@ -1042,7 +1101,11 @@ "saveChanges": "Guardar Cambios", "Remove Custom Field": "Eliminar Campo Personalizado", "fieldSuccessMessage": "Campo añadido exitosamente", - "fieldRemovalSuccess": "Campo eliminado exitosamente" + "fieldRemovalSuccess": "Campo eliminado exitosamente", + "String": "Cadena", + "Boolean": "Booleano", + "Date": "Fecha", + "Number": "Número" }, "orgActionItemCategories": { "createButton": "Crear", @@ -1118,8 +1181,8 @@ "actionItemCategory": "Categoría de elemento de acción", "selectActionItemCategory": "Seleccione una categoría de elemento de acción", "selectAssignee": "Seleccione un asignado", - "preCompletionNotes": "Notas previas a la finalización", - "postCompletionNotes": "Publicar notas de finalización", + "preCompletionNotes": "Notas", + "postCompletionNotes": "Notas finales", "actionItemDetails": "Detalles del elemento de acción", "dueDate": "Fecha de vencimiento", "completionDate": "Fecha de finalización", @@ -1132,6 +1195,22 @@ "successfulCreation": "Elemento de acción creado exitosamente", "successfulUpdation": "Elemento de acción actualizado correctamente", "notes": "Notas", + "assignee": "Cesionario", + "assigner": "Asignador", + "assignmentDate": "Fecha de asignación", + "status": "Estado", + "actionItemActive": "Activo", + "actionItemStatus": "Estado del elemento de acción", + "actionItemCompleted": "Elemento de acción completado", + "markCompletion": "Marcar finalización", "save": "Guardar" + }, + "checkIn": { + "errorCheckingIn": "Error al registrarse", + "checkedInSuccessfully": "Registrado con éxito" + }, + "eventRegistrantsModal": { + "errorAddingAttendee": "Error al agregar asistente", + "errorRemovingAttendee": "Error al eliminar asistente" } } diff --git a/public/locales/zh/common.json b/public/locales/zh/common.json index 5d6fc97310..71b697b354 100644 --- a/public/locales/zh/common.json +++ b/public/locales/zh/common.json @@ -30,11 +30,13 @@ "search": "搜索", "description": "描述", "saveChanges": "保存更改", + "resetChanges": "重置更改", "displayImage": "显示图像", "enterEmail": "输入电子邮件", "emailAddress": "电子邮件地址", "email": "电子邮件", "name": "姓名", + "desc": "描述", "enterPassword": "输入密码", "password": "密码", "confirmPassword": "确认密码", @@ -61,5 +63,24 @@ "Membership Requests": "会员请求", "Plugins": "插件", "Plugin Store": "插件商店", - "Settings": "设置" + "Settings": "设置", + "createdOn": "创建于", + "createdBy": "创建者", + "usersRole": "用户角色", + "changeRole": "更改角色", + "action": "操作", + "removeUser": "删除用户", + "remove": "删除", + "viewProfile": "查看个人资料", + "profile": "轮廓", + "noFiltersApplied": "未应用筛选器", + "manage": "管理", + "searchResultsFor": "搜索结果", + "none": "没有", + "sort": "种类", + "Donate": "捐赠", + "addedSuccessfully": "{{item}} 添加成功", + "updatedSuccessfully": "{{item}} 更新成功", + "removedSuccessfully": "{{item}} 删除成功", + "successfullyUpdated": "更新成功" } diff --git a/public/locales/zh/errors.json b/public/locales/zh/errors.json index 7ddfe06ab4..1466985403 100644 --- a/public/locales/zh/errors.json +++ b/public/locales/zh/errors.json @@ -5,5 +5,6 @@ "notAuthorised": "对不起!", "errorSendingMail": "发送邮件时出错", "emailNotRegistered": "邮箱未注册", - "notFoundMsg": "哎呀!" + "notFoundMsg": "哎呀!", + "errorOccurredCouldntCreate": "发生错误。 无法创建{{entity}}" } diff --git a/public/locales/zh/translation.json b/public/locales/zh/translation.json index 13e581a0a3..6f8cf9e278 100644 --- a/public/locales/zh/translation.json +++ b/public/locales/zh/translation.json @@ -148,7 +148,9 @@ "roleUpdated": "角色已更新。", "joinNow": "立即加入", "visit": "访问", - "withdraw": "拉幅" + "withdraw": "拉幅", + "removeUserFrom": "从{{org}}中删除用户", + "removeConfirmation": "您确定要将'{{name}}'从组织'{{org}}'中删除吗?" }, "communityProfile": { "title": "社区简介", @@ -256,6 +258,7 @@ "clearFilters": "清除过滤器", "completed": "完全的", "completionDate": "完成日期", + "createActionItem": "创建操作项", "deleteActionItem": "删除操作项", "deleteActionItemMsg": "您想删除此操作项吗?", "details": "细节", @@ -264,6 +267,7 @@ "editActionItem": "编辑操作项", "isCompleted": "完全的", "latest": "最新的", + "makeActive": "积极的", "noActionItems": "无行动项目", "options": "选项", "preCompletionNotes": "预完成注释", @@ -279,6 +283,57 @@ "successfulDeletion": "操作项已成功删除", "title": "行动项目" }, + "organizationAgendaCategory": { + "agendaCategoryDetails": "议程类别详情", + "updateAgendaCategory": "更新议程类别", + "title": "议程类别", + "name": "类别", + "description": "描述", + "createdBy": "创建人", + "options": "选项", + "createAgendaCategory": "创建议程类别", + "noAgendaCategories": "没有议程类别", + "update": "更新", + "agendaCategoryCreated": "议程类别创建成功", + "agendaCategoryUpdated": "议程类别更新成功", + "agendaCategoryDeleted": "议程类别删除成功", + "deleteAgendaCategory": "删除议程类别", + "deleteAgendaCategoryMsg": "是否要删除此议程类别?" + }, + "agendaItems": { + "agendaItemDetails": "议程项目详细信息", + "updateAgendaItem": "更新议程项目", + "title": "标题", + "enterTitle": "输入标题", + "sequence": "顺序", + "description": "描述", + "enterDescription": "输入描述", + "category": "议程类别", + "attachments": "附件", + "attachmentLimit": "添加任何图像文件或视频文件,最大 10MB", + "fileSizeExceedsLimit": "文件大小超过 10MB 的限制", + "urls": "网址", + "url": "添加链接到网址", + "enterUrl": "https://example.com", + "invalidUrl": "请输入有效的网址", + "link": "链接", + "createdBy": "创建人", + "regular": "常规", + "note": "注意", + "duration": "持续时间", + "enterDuration": "分:秒", + "options": "选项", + "createAgendaItem": "创建议程项目", + "noAgendaItems": "没有议程项目", + "selectAgendaItemCategory": "选择议程项目类别", + "update": "更新", + "delete": "删除", + "agendaItemCreated": "议程项目已成功创建", + "agendaItemUpdated": "议程项目已成功更新", + "agendaItemDeleted": "议程项目已成功删除", + "deleteAgendaItem": "删除议程项目", + "deleteAgendaItemMsg": "您要删除此议程项目吗?" + }, "eventListCard": { "deleteEvent": "删除事件", "deleteEventMsg": "您想删除此事件吗?", @@ -308,59 +363,55 @@ "occurences": "事件" }, "funds": { - "title": "资金", + "title": "基金", "createFund": "创建基金", "fundName": "基金名称", - "fundId": "基金编号", - "fundOptions": "奥皮通斯", - "noFunds": "未找到资金", - "fundDetails": "基金详情", - "taxDeductible": "免税额", - "enterfundName": "输入基金名称", - "enterfundId": "输入基金ID", - "default": "违约基金", + "fundId": "基金(参考)ID", + "taxDeductible": "税前扣除", + "default": "默认", "archived": "已归档", - "nonArchive": "非存档", "fundCreate": "创建基金", "fundUpdate": "更新基金", "fundDelete": "删除基金", - "manageFund": "管理基金", - "searchFullName": "按名称搜索", - "noFundsFound": "未找到资金", - "createdBy": "由...制作", + "searchByName": "按名称搜索", + "noFundsFound": "未找到基金", + "createdBy": "由...创建", "createdOn": "创建于", - "status": "地位", - "archiveFund": "档案基金", - "archiveFundMsg": "存档后,该基金将从基金列表中删除。此操作可以撤消", + "status": "状态", "fundCreated": "基金创建成功", "fundUpdated": "基金更新成功", - "fundDeleted": "资金删除成功", - "fundArchived": "资金归档成功", - "fundUnarchived": "基金已成功解档", - "deleteFundMsg": "您想删除该基金吗?" + "fundDeleted": "基金删除成功", + "deleteFundMsg": "您确定要删除此基金吗?", + "createdLatest": "最近创建", + "createdEarliest": "最早创建", + "viewCampaigns": "查看活动" }, "fundCampaign": { - "title": "筹款活动", + "title": "募捐活动", "campaignName": "活动名称", "campaignOptions": "选项", - "fundingGoal": "资助目标", + "fundingGoal": "资金目标", "addCampaign": "添加活动", "createdCampaign": "活动创建成功", "updatedCampaign": "活动更新成功", - "deletedCampaign": "营销活动删除成功", - "deleteCampaignMsg": "您确定要删除此广告活动吗?", + "deletedCampaign": "活动删除成功", + "deleteCampaignMsg": "您确定要删除此活动吗?", "noCampaigns": "未找到活动", - "createCampaign": "创建基金活动", - "updateCampaign": "更新基金活动", - "manageCampaign": "管理基金活动", - "deleteCampaign": "删除基金活动", + "createCampaign": "创建活动", + "updateCampaign": "更新活动", + "deleteCampaign": "删除活动", "currency": "货币", "selectCurrency": "选择货币", - "searchFullName": "按名称搜索" + "searchFullName": "按名称搜索", + "viewPledges": "查看承诺", + "noCampaignsFound": "未找到活动", + "latestEndDate": "最新结束日期", + "earliestEndDate": "最早结束日期", + "lowestGoal": "最低目标", + "highestGoal": "最高目标" }, "pledges": { "title": "基金活动承诺", - "volunteers": "志愿者", "pledgeAmount": "质押金额", "pledgeOptions": "选项", "pledgeCreated": "质押创建成功", @@ -375,7 +426,17 @@ "amount": "数量", "editPledge": "编辑承诺", "deletePledgeMsg": "您确定要删除此承诺吗?", - "noPledges": "未找到承诺" + "noPledges": "未找到承诺", + "searchPledger": "按承诺搜索", + "highestAmount": "最高金额", + "lowestAmount": "最低金额", + "latestEndDate": "最新结束日期", + "earliestEndDate": "最早结束日期", + "campaigns": "活动", + "pledges": "承诺", + "endsOn": "结束于", + "raisedAmount": "募集金額", + "pledgedAmount": "承诺金額" }, "orgPost": { "title": "帖子", @@ -460,6 +521,7 @@ "dashboard": "仪表板", "registrants": "注册者", "eventActions": "事件动作", + "eventAgendas": "活动议程", "eventStats": "事件统计", "to": "到" }, @@ -532,7 +594,9 @@ "userPasswordUpdate": { "previousPassword": "旧密码", "newPassword": "新密码", - "confirmNewPassword": "确认新密码" + "confirmNewPassword": "确认新密码", + "passCantBeEmpty": "密码不能为空", + "passNoMatch": "新密码和确认密码不匹配。" }, "orgDelete": { "deleteOrg": "删除组织" @@ -569,6 +633,7 @@ "addOnStore": { "title": "添加商店", "searchName": "例如:捐款", + "search": "搜索", "enable": "启用", "disable": "残疾人", "pHeading": "插件", @@ -669,7 +734,10 @@ }, "postCard": { "likes": "喜欢", - "comments": "评论" + "comments": "评论", + "viewPost": "查看帖子", + "editPost": "编辑帖子", + "postedOn": "发布于 {{date}}" }, "home": { "posts": "帖子", @@ -686,7 +754,8 @@ "startPost": "开始发帖", "media": "媒体", "event": "事件", - "article": "文章" + "article": "文章", + "postNowVisibleInFeed": "帖子现在在动态中可见" }, "settings": { "profileSettings": "配置文件设置", @@ -720,7 +789,7 @@ "widowed": "寡", "divorced": "离婚", "engaged": "已订婚的", - "seperated": "分离的", + "separated": "分离的", "grade1": "1级", "grade2": "二年级", "grade3": "三年级", @@ -798,7 +867,10 @@ "deleteAdvertisement": "删除广告", "deleteAdvertisementMsg": "您想删除该广告吗?", "view": "看法", - "editAdvertisement": "编辑广告" + "editAdvertisement": "编辑广告", + "advertisementDeleted": "广告已成功删除。", + "endDateGreaterOrEqual": "结束日期应大于或等于开始日期", + "advertisementCreated": "广告已成功创建。" }, "userChat": { "chat": "聊天", @@ -816,7 +888,11 @@ "customFieldType": "字段类型", "Remove Custom Field": "删除自定义字段", "fieldSuccessMessage": "字段添加成功", - "fieldRemovalSuccess": "字段删除成功" + "fieldRemovalSuccess": "字段删除成功", + "String": "字符串", + "Boolean": "布尔值", + "Date": "日期", + "Number": "数字" }, "orgActionItemCategories": { "enableButton": "使能够", @@ -875,8 +951,8 @@ "actionItemCategory": "行动项目类别", "selectActionItemCategory": "选择操作项类别", "selectAssignee": "选择受托人", - "preCompletionNotes": "预完成注释", - "postCompletionNotes": "完成后注释", + "preCompletionNotes": "笔记", + "postCompletionNotes": "完成说明", "actionItemDetails": "行动项目详情", "dueDate": "到期日", "completionDate": "完成日期", @@ -887,6 +963,22 @@ "successfulCreation": "操作项创建成功", "successfulUpdation": "操作项已成功更新", "notes": "笔记", + "assignee": "受让人", + "assigner": "分配者", + "assignmentDate": "任务分配日期", + "status": "地位", + "actionItemActive": "积极的", + "actionItemStatus": "行动项目状态", + "actionItemCompleted": "行动项目已完成", + "markCompletion": "标记完成", "save": "节省" + }, + "checkIn": { + "errorCheckingIn": "签到错误", + "checkedInSuccessfully": "成功签到" + }, + "eventRegistrantsModal": { + "errorAddingAttendee": "添加与会者时出错", + "errorRemovingAttendee": "删除与会者时出错" } } diff --git a/schema.graphql b/schema.graphql index 35c49f2cd4..6e00550083 100644 --- a/schema.graphql +++ b/schema.graphql @@ -210,7 +210,6 @@ type DirectChat { createdAt: DateTime! creator: User messages: [DirectChatMessage] - organization: Organization! updatedAt: DateTime! users: [User!]! } @@ -464,6 +463,7 @@ type Group { type GroupChat { _id: ID! + title: String! createdAt: DateTime! creator: User messages: [GroupChatMessage] @@ -1057,6 +1057,9 @@ type Query { customFieldsByOrganization(id: ID!): [OrganizationCustomField] directChatsByUserID(id: ID!): [DirectChat] directChatsMessagesByChatID(id: ID!): [DirectChatMessage] + directChatById(id: ID!): DirectChat + groupChatById(id: ID!): DirectChat + groupChatsByUserId(id: ID!): [GroupChat] event(id: ID!): Event eventVolunteersByEvent(id: ID!): [EventVolunteer] eventsByOrganization(id: ID, orderBy: EventOrderByInput): [Event] @@ -1152,8 +1155,8 @@ enum Status { type Subscription { directMessageChat: MessageChat - messageSentToDirectChat: DirectChatMessage - messageSentToGroupChat: GroupChatMessage + messageSentToDirectChat(userId: ID!): DirectChatMessage + messageSentToGroupChat(userId: ID!): GroupChatMessage onPluginUpdate: Plugin } @@ -1440,6 +1443,8 @@ enum UserOrderByInput { id_DESC lastName_ASC lastName_DESC + createdAt_ASC + createdAt_DESC } type UserPhone { @@ -1546,7 +1551,7 @@ enum WeekDays { } input createChatInput { - organizationId: ID! + organizationId: ID userIds: [ID!]! } diff --git a/src/App.test.tsx b/src/App.test.tsx index b20f75e1ce..3146066e26 100644 --- a/src/App.test.tsx +++ b/src/App.test.tsx @@ -33,6 +33,7 @@ const MOCKS = [ _id: '123', firstName: 'John', lastName: 'Doe', + createdAt: '2023-04-13T04:53:17.742+00:00', image: 'john.jpg', email: 'johndoe@gmail.com', birthDate: '1990-01-01', diff --git a/src/App.tsx b/src/App.tsx index 1d8787e7eb..7ee6ba72cb 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -14,6 +14,7 @@ import OrgList from 'screens/OrgList/OrgList'; import OrgPost from 'screens/OrgPost/OrgPost'; import OrgSettings from 'screens/OrgSettings/OrgSettings'; import OrganizationActionItems from 'screens/OrganizationActionItems/OrganizationActionItems'; +import OrganizationAgendaCategory from 'screens/OrganizationAgendaCategory/OrganizationAgendaCategory'; import OrganizationDashboard from 'screens/OrganizationDashboard/OrganizationDashboard'; import OrganizationEvents from 'screens/OrganizationEvents/OrganizationEvents'; import OrganizaitionFundCampiagn from 'screens/OrganizationFundCampaign/OrganizationFundCampagins'; @@ -34,7 +35,7 @@ import Organizations from 'screens/UserPortal/Organizations/Organizations'; import People from 'screens/UserPortal/People/People'; import Settings from 'screens/UserPortal/Settings/Settings'; // import UserLoginPage from 'screens/UserPortal/UserLoginPage/UserLoginPage'; -// import Chat from 'screens/UserPortal/Chat/Chat'; +import Chat from 'screens/UserPortal/Chat/Chat'; import { useQuery } from '@apollo/client'; import { CHECK_AUTH } from 'GraphQl/Queries/Queries'; import Advertisements from 'components/Advertisements/Advertisements'; @@ -135,6 +136,10 @@ function app(): JSX.Element { path="/orgactionitems/:orgId" element={} /> + } + /> } /> }> } /> } /> + } /> }> } /> } /> diff --git a/src/GraphQl/Mutations/AgendaCategoryMutations.ts b/src/GraphQl/Mutations/AgendaCategoryMutations.ts new file mode 100644 index 0000000000..c344eca7e2 --- /dev/null +++ b/src/GraphQl/Mutations/AgendaCategoryMutations.ts @@ -0,0 +1,45 @@ +import gql from 'graphql-tag'; + +/** + * GraphQL mutation to create an agenda category. + * + * @param input - Name, Description, OrganizationID of the AgendaCategory. + */ + +export const CREATE_AGENDA_ITEM_CATEGORY_MUTATION = gql` + mutation CreateAgendaCategory($input: CreateAgendaCategoryInput!) { + createAgendaCategory(input: $input) { + _id + } + } +`; + +/** + * GraphQL mutation to delete an agenda category. + * + * @param deleteAgendaCategoryId - The ID of the AgendaCategory to be deleted. + */ + +export const DELETE_AGENDA_ITEM_CATEGORY_MUTATION = gql` + mutation DeleteAgendaCategory($deleteAgendaCategoryId: ID!) { + deleteAgendaCategory(id: $deleteAgendaCategoryId) + } +`; + +/** + * GraphQL mutation to update an agenda category. + * + * @param updateAgendaCategoryId - The ID of the AgendaCategory to be updated. + * @param input - Updated Name, Description, OrganizationID of the AgendaCategory. + */ + +export const UPDATE_AGENDA_ITEM_CATEGORY_MUTATION = gql` + mutation UpdateAgendaCategory( + $updateAgendaCategoryId: ID! + $input: UpdateAgendaCategoryInput! + ) { + updateAgendaCategory(id: $updateAgendaCategoryId, input: $input) { + _id + } + } +`; diff --git a/src/GraphQl/Mutations/AgendaItemMutations.ts b/src/GraphQl/Mutations/AgendaItemMutations.ts new file mode 100644 index 0000000000..20191b1b7c --- /dev/null +++ b/src/GraphQl/Mutations/AgendaItemMutations.ts @@ -0,0 +1,31 @@ +import gql from 'graphql-tag'; + +export const CREATE_AGENDA_ITEM_MUTATION = gql` + mutation CreateAgendaItem($input: CreateAgendaItemInput!) { + createAgendaItem(input: $input) { + _id + title + } + } +`; + +export const DELETE_AGENDA_ITEM_MUTATION = gql` + mutation RemoveAgendaItem($removeAgendaItemId: ID!) { + removeAgendaItem(id: $removeAgendaItemId) { + _id + } + } +`; + +export const UPDATE_AGENDA_ITEM_MUTATION = gql` + mutation UpdateAgendaItem( + $updateAgendaItemId: ID! + $input: UpdateAgendaItemInput! + ) { + updateAgendaItem(id: $updateAgendaItemId, input: $input) { + _id + description + title + } + } +`; diff --git a/src/GraphQl/Mutations/OrganizationMutations.ts b/src/GraphQl/Mutations/OrganizationMutations.ts index c40d259429..b61d70607b 100644 --- a/src/GraphQl/Mutations/OrganizationMutations.ts +++ b/src/GraphQl/Mutations/OrganizationMutations.ts @@ -57,8 +57,26 @@ export const REMOVE_SAMPLE_ORGANIZATION_MUTATION = gql` * @returns The created direct chat object. */ +export const CREATE_GROUP_CHAT = gql` + mutation createGroupChat( + $userIds: [ID!]! + $organizationId: ID! + $title: String! + ) { + createGroupChat( + data: { + userIds: $userIds + organizationId: $organizationId + title: $title + } + ) { + _id + } + } +`; + export const CREATE_DIRECT_CHAT = gql` - mutation createDirectChat($userIds: [ID!]!, $organizationId: ID!) { + mutation createDirectChat($userIds: [ID!]!, $organizationId: ID) { createDirectChat( data: { userIds: $userIds, organizationId: $organizationId } ) { @@ -66,6 +84,104 @@ export const CREATE_DIRECT_CHAT = gql` } } `; + +export const SEND_MESSAGE_TO_DIRECT_CHAT = gql` + mutation sendMessageToDirectChat($chatId: ID!, $messageContent: String!) { + sendMessageToDirectChat(chatId: $chatId, messageContent: $messageContent) { + _id + createdAt + messageContent + receiver { + _id + firstName + lastName + } + sender { + _id + firstName + lastName + } + updatedAt + } + } +`; + +export const SEND_MESSAGE_TO_GROUP_CHAT = gql` + mutation sendMessageToGroupChat($chatId: ID!, $messageContent: String!) { + sendMessageToGroupChat(chatId: $chatId, messageContent: $messageContent) { + _id + createdAt + messageContent + sender { + _id + firstName + lastName + } + updatedAt + } + } +`; + +export const CREATE_MESSAGE_CHAT = gql` + mutation createMessageChat($receiver: ID!, $messageContent: String!) { + createMessageChat(data: { receiver: $receiver, message: $messageContent }) { + _id + createdAt + message + languageBarrier + receiver { + _id + } + sender { + _id + } + updatedAt + } + } +`; + +export const MESSAGE_SENT_TO_DIRECT_CHAT = gql` + subscription messageSentToDirectChat($userId: ID!) { + messageSentToDirectChat(userId: $userId) { + _id + createdAt + directChatMessageBelongsTo { + _id + } + messageContent + receiver { + _id + firstName + lastName + } + sender { + _id + firstName + lastName + } + updatedAt + } + } +`; + +export const MESSAGE_SENT_TO_GROUP_CHAT = gql` + subscription messageSentToGroupChat($userId: ID!) { + messageSentToGroupChat(userId: $userId) { + _id + createdAt + groupChatMessageBelongsTo { + _id + } + messageContent + sender { + _id + firstName + lastName + } + updatedAt + } + } +`; //Plugin WebSocket listner /** diff --git a/src/GraphQl/Mutations/PledgeMutation.ts b/src/GraphQl/Mutations/PledgeMutation.ts index aca0663635..321f7aa697 100644 --- a/src/GraphQl/Mutations/PledgeMutation.ts +++ b/src/GraphQl/Mutations/PledgeMutation.ts @@ -52,10 +52,12 @@ export const UPDATE_PLEDGE = gql` $currency: Currency $startDate: Date $endDate: Date + $users: [ID!] ) { updateFundraisingCampaignPledge( id: $id data: { + users: $users amount: $amount currency: $currency startDate: $startDate diff --git a/src/GraphQl/Mutations/mutations.ts b/src/GraphQl/Mutations/mutations.ts index 2ed67be88d..69e4c85e9e 100644 --- a/src/GraphQl/Mutations/mutations.ts +++ b/src/GraphQl/Mutations/mutations.ts @@ -97,6 +97,7 @@ export const UPDATE_USER_MUTATION = gql` $state: String $country: String $image: String + $appLanguageCode: String ) { updateUserProfile( data: { @@ -110,6 +111,7 @@ export const UPDATE_USER_MUTATION = gql` employmentStatus: $empStatus maritalStatus: $maritalStatus address: { line1: $address, state: $state, countryCode: $country } + appLanguageCode: $appLanguageCode } file: $image ) { @@ -185,6 +187,7 @@ export const LOGIN_MUTATION = gql` _id } isSuperAdmin + appLanguageCode } accessToken refreshToken @@ -687,6 +690,18 @@ export { UPDATE_ACTION_ITEM_MUTATION, } from './ActionItemMutations'; +export { + CREATE_AGENDA_ITEM_CATEGORY_MUTATION, + DELETE_AGENDA_ITEM_CATEGORY_MUTATION, + UPDATE_AGENDA_ITEM_CATEGORY_MUTATION, +} from './AgendaCategoryMutations'; + +export { + CREATE_AGENDA_ITEM_MUTATION, + DELETE_AGENDA_ITEM_MUTATION, + UPDATE_AGENDA_ITEM_MUTATION, +} from './AgendaItemMutations'; + // Changes the role of a event in an organization and add and remove the event from the organization export { ADD_EVENT_ATTENDEE, diff --git a/src/GraphQl/Queries/AgendaCategoryQueries.ts b/src/GraphQl/Queries/AgendaCategoryQueries.ts new file mode 100644 index 0000000000..f766337c22 --- /dev/null +++ b/src/GraphQl/Queries/AgendaCategoryQueries.ts @@ -0,0 +1,23 @@ +import gql from 'graphql-tag'; + +/** + * GraphQL query to retrieve agenda category by id. + * + * @param agendaCategoryId - The ID of the category which is being retrieved. + * @returns Agenda category associated with the id. + */ + +export const AGENDA_ITEM_CATEGORY_LIST = gql` + query AgendaItemCategoriesByOrganization($organizationId: ID!) { + agendaItemCategoriesByOrganization(organizationId: $organizationId) { + _id + name + description + createdBy { + _id + firstName + lastName + } + } + } +`; diff --git a/src/GraphQl/Queries/AgendaItemQueries.ts b/src/GraphQl/Queries/AgendaItemQueries.ts new file mode 100644 index 0000000000..92957983c8 --- /dev/null +++ b/src/GraphQl/Queries/AgendaItemQueries.ts @@ -0,0 +1,73 @@ +import gql from 'graphql-tag'; + +export const AgendaItemByOrganization = gql` + query AgendaItemByOrganization($organizationId: ID!) { + agendaItemByOrganization(organizationId: $organizationId) { + _id + title + description + duration + attachments + createdBy { + _id + firstName + lastName + } + urls + users { + _id + firstName + lastName + } + categories { + _id + name + } + sequence + organization { + _id + name + } + relatedEvent { + _id + title + } + } + } +`; + +export const AgendaItemByEvent = gql` + query AgendaItemByEvent($relatedEventId: ID!) { + agendaItemByEvent(relatedEventId: $relatedEventId) { + _id + title + description + duration + attachments + createdBy { + _id + firstName + lastName + } + urls + users { + _id + firstName + lastName + } + sequence + categories { + _id + name + } + organization { + _id + name + } + relatedEvent { + _id + title + } + } + } +`; diff --git a/src/GraphQl/Queries/PlugInQueries.ts b/src/GraphQl/Queries/PlugInQueries.ts index ff908ac57f..c93b3ad267 100644 --- a/src/GraphQl/Queries/PlugInQueries.ts +++ b/src/GraphQl/Queries/PlugInQueries.ts @@ -106,6 +106,119 @@ export const ORGANIZATION_EVENTS_CONNECTION = gql` * @returns The list of direct chats associated with the user, including details such as ID, creator, messages, organization, and participating users. */ +// directChatsMessagesByChatID(id: ID!): [DirectChatMessage] + +export const DIRECT_CHAT_MESSAGES_BY_CHAT_ID = gql` + query directChatsMessagesByChatID($id: ID!) { + directChatsMessagesByChatID(id: $id) { + _id + createdAt + messageContent + receiver { + _id + firstName + lastName + email + image + } + sender { + _id + firstName + lastName + email + image + } + } + } +`; + +export const DIRECT_CHAT_BY_ID = gql` + query directChatById($id: ID!) { + directChatById(id: $id) { + _id + createdAt + messages { + _id + createdAt + messageContent + receiver { + _id + firstName + lastName + email + image + } + sender { + _id + firstName + lastName + email + image + } + } + users { + _id + firstName + lastName + email + } + } + } +`; + +export const GROUP_CHAT_BY_ID = gql` + query groupChatById($id: ID!) { + groupChatById(id: $id) { + _id + createdAt + title + messages { + _id + createdAt + messageContent + sender { + _id + firstName + lastName + email + image + } + } + users { + _id + firstName + lastName + email + image + } + } + } +`; + +// directChatByChatId + +// export const GROUP_CHAT_MESSAGES_BY_CHAT_ID = gql` +// query directChatsMessagesByChatID($id: ID!) { +// directChatsMessagesByChatID(id: $id) { +// _id +// createdAt +// messageContent +// receiver { +// _id +// firstName +// lastName +// email +// } +// sender { +// _id +// firstName +// lastName +// email +// } +// } +// } +// `; + export const DIRECT_CHATS_LIST = gql` query DirectChatsByUserID($id: ID!) { directChatsByUserID(id: $id) { @@ -148,6 +261,42 @@ export const DIRECT_CHATS_LIST = gql` } `; +export const GROUP_CHAT_LIST = gql` + query GroupChatsByUserID($id: ID!) { + groupChatsByUserId(id: $id) { + _id + creator { + _id + firstName + lastName + email + } + title + messages { + _id + createdAt + messageContent + sender { + _id + firstName + lastName + email + } + } + organization { + _id + name + } + users { + _id + firstName + lastName + email + image + } + } + } +`; /** * GraphQL query to check if an organization is a sample organization. * diff --git a/src/GraphQl/Queries/Queries.ts b/src/GraphQl/Queries/Queries.ts index 101d020285..1235d65f9f 100644 --- a/src/GraphQl/Queries/Queries.ts +++ b/src/GraphQl/Queries/Queries.ts @@ -8,6 +8,7 @@ export const CHECK_AUTH = gql` _id firstName lastName + createdAt image email birthDate @@ -108,6 +109,7 @@ export const USER_LIST = gql` $lastName_contains: String $skip: Int $first: Int + $order: UserOrderByInput ) { users( where: { @@ -116,6 +118,7 @@ export const USER_LIST = gql` } skip: $skip first: $first + orderBy: $order ) { user { _id @@ -440,7 +443,6 @@ export const ORGANIZATIONS_MEMBER_CONNECTION_LIST = gql` $orgId: ID! $firstName_contains: String $lastName_contains: String - $event_title_contains: String $first: Int $skip: Int ) { @@ -451,7 +453,6 @@ export const ORGANIZATIONS_MEMBER_CONNECTION_LIST = gql` where: { firstName_contains: $firstName_contains lastName_contains: $lastName_contains - event_title_contains: $event_title_contains } ) { edges { @@ -782,6 +783,12 @@ export { ACTION_ITEM_CATEGORY_LIST } from './ActionItemCategoryQueries'; // get the list of Action Items export { ACTION_ITEM_LIST } from './ActionItemQueries'; +export { + AgendaItemByEvent, + AgendaItemByOrganization, +} from './AgendaItemQueries'; + +export { AGENDA_ITEM_CATEGORY_LIST } from './AgendaCategoryQueries'; // to take the list of the blocked users export { ADVERTISEMENTS_GET, diff --git a/src/GraphQl/Queries/fundQueries.ts b/src/GraphQl/Queries/fundQueries.ts index 85015f5f63..daec99a8c9 100644 --- a/src/GraphQl/Queries/fundQueries.ts +++ b/src/GraphQl/Queries/fundQueries.ts @@ -9,10 +9,15 @@ import gql from 'graphql-tag'; * @returns The list of members associated with the organization. */ export const FUND_LIST = gql` - query FundsByOrganization($organizationId: ID!, $filter: String) { + query FundsByOrganization( + $organizationId: ID! + $filter: String + $orderBy: FundOrderByInput + ) { fundsByOrganization( organizationId: $organizationId where: { name_contains: $filter } + orderBy: $orderBy ) { _id name @@ -32,8 +37,12 @@ export const FUND_LIST = gql` `; export const FUND_CAMPAIGN = gql` - query GetFundById($id: ID!) { - getFundById(id: $id) { + query GetFundById( + $id: ID! + $where: CampaignWhereInput + $orderBy: CampaignOrderByInput + ) { + getFundById(id: $id, where: $where, orderBy: $orderBy) { campaigns { _id endDate @@ -47,8 +56,11 @@ export const FUND_CAMPAIGN = gql` `; export const FUND_CAMPAIGN_PLEDGE = gql` - query GetFundraisingCampaignById($id: ID!) { - getFundraisingCampaignById(id: $id) { + query GetFundraisingCampaignById($id: ID!, $orderBy: PledgeOrderByInput) { + getFundraisingCampaignById(id: $id, orderBy: $orderBy) { + name + fundingGoal + currency startDate endDate pledges { @@ -60,6 +72,8 @@ export const FUND_CAMPAIGN_PLEDGE = gql` users { _id firstName + lastName + image } } } diff --git a/src/assets/css/app.css b/src/assets/css/app.css index a96b3afabe..d6c5ca665c 100644 --- a/src/assets/css/app.css +++ b/src/assets/css/app.css @@ -2166,7 +2166,7 @@ progress { color: var(--bs-body-color); background-color: #f2f2f2; background-clip: padding-box; - border: 0 solid var(--bs-border-color); + border: 1px solid var(--bs-border-color); appearance: none; border-radius: var(--bs-border-radius); transition: @@ -2401,8 +2401,8 @@ textarea.form-control-lg { .form-check-input { --bs-form-check-bg: #f2f2f2; - width: 1em; - height: 1em; + width: 1.3em; + height: 1.3em; margin-top: 0.25em; vertical-align: top; background-color: var(--bs-form-check-bg); diff --git a/src/assets/svgs/agenda-category-icon.svg b/src/assets/svgs/agenda-category-icon.svg new file mode 100644 index 0000000000..8e3d4562f3 --- /dev/null +++ b/src/assets/svgs/agenda-category-icon.svg @@ -0,0 +1 @@ +checklist \ No newline at end of file diff --git a/src/assets/svgs/agenda-items.svg b/src/assets/svgs/agenda-items.svg new file mode 100644 index 0000000000..343d1808b4 --- /dev/null +++ b/src/assets/svgs/agenda-items.svg @@ -0,0 +1 @@ +notebook diff --git a/src/assets/svgs/chat.svg b/src/assets/svgs/chat.svg new file mode 100644 index 0000000000..72787fab78 --- /dev/null +++ b/src/assets/svgs/chat.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/svgs/newChat.svg b/src/assets/svgs/newChat.svg new file mode 100644 index 0000000000..e3609e2895 --- /dev/null +++ b/src/assets/svgs/newChat.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/components/ActionItems/ActionItemsContainer.test.tsx b/src/components/ActionItems/ActionItemsContainer.test.tsx index dda9e07035..7cb9c9e9bb 100644 --- a/src/components/ActionItems/ActionItemsContainer.test.tsx +++ b/src/components/ActionItems/ActionItemsContainer.test.tsx @@ -86,6 +86,35 @@ describe('Testing Action Item Categories Component', () => { screen.queryByText(translations.noActionItems), ).not.toBeInTheDocument(); }); + + expect(screen.getByText('#')).toBeInTheDocument(); + expect(screen.getByText(translations.assignee)).toBeInTheDocument(); + expect( + screen.getByText(translations.actionItemCategory), + ).toBeInTheDocument(); + expect( + screen.getByText(translations.preCompletionNotes), + ).toBeInTheDocument(); + expect( + screen.getByText(translations.postCompletionNotes), + ).toBeInTheDocument(); + + await wait(); + expect(screen.getAllByText('Harve Lance')[0]).toBeInTheDocument(); + + const asigneeAnchorElement = screen.getAllByText('Harve Lance')[0]; + expect(asigneeAnchorElement.tagName).toBe('A'); + expect(asigneeAnchorElement).toHaveAttribute('href', '/member/event1'); + + expect(screen.getAllByText('ActionItemCategory 1')[0]).toBeInTheDocument(); + const updateButtons = screen.getAllByTestId('editActionItemModalBtn'); + const previewButtons = screen.getAllByTestId('previewActionItemModalBtn'); + const updateStatusButtons = screen.getAllByTestId( + 'actionItemStatusChangeCheckbox', + ); + expect(updateButtons[0]).toBeInTheDocument(); + expect(previewButtons[0]).toBeInTheDocument(); + expect(updateStatusButtons[0]).toBeInTheDocument(); }); test('component loads correctly with no action items', async () => { @@ -182,6 +211,48 @@ describe('Testing Action Item Categories Component', () => { ); }); + test('completed action item status change modal loads correctly', async () => { + render( + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.getAllByTestId('actionItemStatusChangeCheckbox')[1], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('actionItemStatusChangeCheckbox')[1]); + + await waitFor(() => { + return expect( + screen.findByTestId('actionItemStatusChangeModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + expect(screen.getByText(translations.actionItemStatus)).toBeInTheDocument(); + + expect( + screen.getByTestId('actionItemsStatusChangeNotes'), + ).toBeInTheDocument(); + expect( + screen.getByPlaceholderText(translations.actionItemCompleted), + ).toBeInTheDocument(); + expect( + screen.getByRole('button', { name: translations.makeActive }), + ).toBeInTheDocument(); + }); + test('opens and closes the preview modal correctly', async () => { render( @@ -473,6 +544,9 @@ describe('Testing Action Item Categories Component', () => { screen.getByTestId('actionItemStatusChangeSubmitBtn'), ).toBeInTheDocument(); }); + expect( + screen.getByTestId('actionItemStatusChangeSubmitBtn'), + ).toHaveTextContent(translations.markCompletion); userEvent.click(screen.getByTestId('actionItemStatusChangeSubmitBtn')); await waitFor(() => { @@ -506,6 +580,9 @@ describe('Testing Action Item Categories Component', () => { screen.getByTestId('actionItemStatusChangeSubmitBtn'), ).toBeInTheDocument(); }); + expect( + screen.getByTestId('actionItemStatusChangeSubmitBtn'), + ).toHaveTextContent(translations.makeActive); userEvent.click(screen.getByTestId('actionItemStatusChangeSubmitBtn')); await waitFor(() => { @@ -667,4 +744,34 @@ describe('Testing Action Item Categories Component', () => { ); }); }); + + test('Action Items loads with correct headers', async () => { + render( + + + + + + + + + , + ); + + await wait(); + + const actionItemHeaders = screen.getByTestId('actionItemsHeader'); + expect(actionItemHeaders).toBeInTheDocument(); + expect(screen.getByText(translations.assignee)).toBeInTheDocument(); + expect( + screen.getByText(translations.actionItemCategory), + ).toBeInTheDocument(); + expect( + screen.getByText(translations.preCompletionNotes), + ).toBeInTheDocument(); + expect( + screen.getByText(translations.postCompletionNotes), + ).toBeInTheDocument(); + expect(screen.getByText(translations.options)).toBeInTheDocument(); + }); }); diff --git a/src/components/ActionItems/ActionItemsContainer.tsx b/src/components/ActionItems/ActionItemsContainer.tsx index 0cb799c212..42e57f3822 100644 --- a/src/components/ActionItems/ActionItemsContainer.tsx +++ b/src/components/ActionItems/ActionItemsContainer.tsx @@ -27,6 +27,7 @@ import styles from './ActionItemsContainer.module.css'; import ActionItemUpdateModal from '../../screens/OrganizationActionItems/ActionItemUpdateModal'; import ActionItemPreviewModal from '../../screens/OrganizationActionItems/ActionItemPreviewModal'; import ActionItemDeleteModal from '../../screens/OrganizationActionItems/ActionItemDeleteModal'; +import { Link } from 'react-router-dom'; function actionItemsContainer({ actionItemsConnection, @@ -193,18 +194,28 @@ function actionItemsContainer({ > +
    +
    {'#'}
    +
    {t('assignee')}
    {t('preCompletionNotes')}
    {t('postCompletionNotes')}
    - +
    {t('options')}
    @@ -237,29 +253,44 @@ function actionItemsContainer({ {actionItemsData?.map((actionItem, index) => (
    +
    + {index + 1} + - {`${actionItem.assignee.firstName} ${actionItem.assignee.lastName}`} + + {`${actionItem.assignee.firstName} ${actionItem.assignee.lastName}`} + {actionItem.actionItemCategory.name} -
    +
    {actionItem.isCompleted ? ( @@ -311,7 +342,12 @@ function actionItemsContainer({ )}
    - +
    { userEvent.click(screen.getByTestId('addonregisterBtn')); await wait(100); - expect(toast.success).toBeCalledWith('Plugin Added Successfully'); + expect(toast.success).toBeCalledWith('Plugin added Successfully'); }); }); diff --git a/src/components/AddOn/core/AddOnRegister/AddOnRegister.tsx b/src/components/AddOn/core/AddOnRegister/AddOnRegister.tsx index 9f88775265..059eae5d43 100644 --- a/src/components/AddOn/core/AddOnRegister/AddOnRegister.tsx +++ b/src/components/AddOn/core/AddOnRegister/AddOnRegister.tsx @@ -52,7 +52,7 @@ function addOnRegister(): JSX.Element { }); if (data) { - toast.success('Plugin Added Successfully'); + toast.success(tCommon('addedSuccessfully', { item: 'Plugin' })); setTimeout(() => { navigate(0); }, 2000); diff --git a/src/components/Advertisements/Advertisements.test.tsx b/src/components/Advertisements/Advertisements.test.tsx index fcb8889dad..b45e1bab38 100644 --- a/src/components/Advertisements/Advertisements.test.tsx +++ b/src/components/Advertisements/Advertisements.test.tsx @@ -407,7 +407,7 @@ describe('Testing Advertisement Component', () => { userEvent.click(screen.getByTestId('addonregister')); expect( - await screen.findByText('Advertisement created successfully'), + await screen.findByText('Advertisement created successfully.'), ).toBeInTheDocument(); }); diff --git a/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.tsx b/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.tsx index cbc933a894..afb66e7ff4 100644 --- a/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.tsx +++ b/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.tsx @@ -54,7 +54,7 @@ function advertisementEntry({ id: id.toString(), }, }); - toast.error('Advertisement Deleted'); + toast.success(t('advertisementDeleted')); setButtonLoading(false); setAfter(null); } catch (error: unknown) { diff --git a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.test.tsx b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.test.tsx index a38823a97c..c3aa536d1f 100644 --- a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.test.tsx +++ b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.test.tsx @@ -229,7 +229,7 @@ describe('Testing Advertisement Register Component', () => { await waitFor(() => { fireEvent.click(getByText(translations.register)); }); - expect(toast.success).toBeCalledWith('Advertisement created successfully'); + expect(toast.success).toBeCalledWith('Advertisement created successfully.'); expect(setTimeoutSpy).toHaveBeenCalled(); }); @@ -295,7 +295,7 @@ describe('Testing Advertisement Register Component', () => { await waitFor(() => { fireEvent.click(getByText(translations.saveChanges)); }); - expect(toast.success).toBeCalledWith('Advertisement created successfully'); + expect(toast.success).toBeCalledWith('Advertisement created successfully.'); expect(setTimeoutSpy).toHaveBeenCalled(); }); @@ -330,7 +330,7 @@ describe('Testing Advertisement Register Component', () => { fireEvent.click(getByText(translations.register)); }); expect(toast.error).toBeCalledWith( - 'An error occured, could not create new advertisement', + `An error occurred. Couldn't create advertisement`, ); expect(setTimeoutSpy).toHaveBeenCalled(); }); @@ -400,7 +400,7 @@ describe('Testing Advertisement Register Component', () => { fireEvent.click(getByText(translations.register)); }); expect(toast.error).toBeCalledWith( - 'End date must be greater than or equal to start date', + 'End Date should be greater than or equal to Start Date', ); expect(setTimeoutSpy).toHaveBeenCalled(); }); @@ -521,7 +521,7 @@ describe('Testing Advertisement Register Component', () => { fireEvent.click(getByText(translations.saveChanges)); await waitFor(() => { expect(toast.error).toBeCalledWith( - 'End date must be greater than or equal to start date', + 'End Date should be greater than or equal to Start Date', ); }); }); diff --git a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.tsx b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.tsx index 78bfec9ead..ee812f2b00 100644 --- a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.tsx +++ b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.tsx @@ -47,6 +47,7 @@ function advertisementRegister({ }: InterfaceAddOnRegisterProps): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'advertisement' }); const { t: tCommon } = useTranslation('common'); + const { t: tErrors } = useTranslation('errors'); const { orgId: currentOrg } = useParams(); @@ -107,7 +108,7 @@ function advertisementRegister({ try { console.log('At handle register', formState); if (formState.endDate < formState.startDate) { - toast.error('End date must be greater than or equal to start date'); + toast.error(t('endDateGreaterOrEqual')); return; } const { data } = await create({ @@ -122,7 +123,7 @@ function advertisementRegister({ }); if (data) { - toast.success('Advertisement created successfully'); + toast.success(t('advertisementCreated')); setFormState({ name: '', advertisementMedia: '', @@ -135,7 +136,9 @@ function advertisementRegister({ setAfter(null); } catch (error: unknown) { if (error instanceof Error) { - toast.error('An error occured, could not create new advertisement'); + toast.error( + tErrors('errorOccurredCouldntCreate', { entity: 'advertisement' }), + ); console.log('error occured', error.message); } } @@ -155,7 +158,7 @@ function advertisementRegister({ updatedFields.type = formState.type; } if (formState.endDate < formState.startDate) { - toast.error('End date must be greater than or equal to start date'); + toast.error(t('endDateGreaterOrEqual')); return; } const startDateFormattedString = dayjs(formState.startDate).format( @@ -195,7 +198,9 @@ function advertisementRegister({ }); if (data) { - toast.success('Advertisement updated successfully'); + toast.success( + tCommon('updatedSuccessfully', { item: 'Advertisement' }), + ); handleClose(); setAfter(null); } @@ -223,7 +228,6 @@ function advertisementRegister({ {tCommon('edit')}
    )} - {formStatus === 'register' ? ( diff --git a/src/components/AgendaCategory/AgendaCategoryContainer.module.css b/src/components/AgendaCategory/AgendaCategoryContainer.module.css new file mode 100644 index 0000000000..7ad16b4c7c --- /dev/null +++ b/src/components/AgendaCategory/AgendaCategoryContainer.module.css @@ -0,0 +1,20 @@ +.createModal { + margin-top: 20vh; + margin-left: 13vw; + max-width: 80vw; +} + +.titlemodal { + color: var(--bs-gray-600); + font-weight: 600; + font-size: 20px; + margin-bottom: 20px; + padding-bottom: 5px; + border-bottom: 3px solid var(--bs-primary); + width: 65%; +} + +.agendaCategoryOptionsButton { + width: 24px; + height: 24px; +} diff --git a/src/components/AgendaCategory/AgendaCategoryContainer.test.tsx b/src/components/AgendaCategory/AgendaCategoryContainer.test.tsx new file mode 100644 index 0000000000..5ddab82aec --- /dev/null +++ b/src/components/AgendaCategory/AgendaCategoryContainer.test.tsx @@ -0,0 +1,415 @@ +import React from 'react'; +import { + render, + screen, + waitFor, + act, + waitForElementToBeRemoved, + fireEvent, +} from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import 'jest-localstorage-mock'; +import { MockedProvider } from '@apollo/client/testing'; +import 'jest-location-mock'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import i18nForTest from 'utils/i18nForTest'; +import { toast } from 'react-toastify'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; + +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; + +import AgendaCategoryContainer from './AgendaCategoryContainer'; +import { props, props2 } from './AgendaCategoryContainerProps'; +import { MOCKS, MOCKS_ERROR_MUTATIONS } from './AgendaCategoryContainerMocks'; + +const link = new StaticMockLink(MOCKS, true); +const link2 = new StaticMockLink(MOCKS_ERROR_MUTATIONS, true); + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +async function wait(ms = 100): Promise { + await act(async () => { + return new Promise((resolve) => setTimeout(resolve, ms)); + }); +} + +const translations = JSON.parse( + JSON.stringify( + i18nForTest.getDataByLanguage('en')?.translation.organizationAgendaCategory, + ), +); + +describe('Testing Agenda Category Component', () => { + const formData = { + name: 'AgendaCategory 1 Edited', + description: 'AgendaCategory 1 Description Edited', + }; + + test('component loads correctly with categories', async () => { + render( + + + + + + + + + , + ); + await wait(); + + await waitFor(() => { + expect( + screen.queryByText(translations.noAgendaCategories), + ).not.toBeInTheDocument(); + }); + }); + + test('component loads correctly with no agenda Categories', async () => { + render( + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.queryByText(translations.noAgendaCategories), + ).toBeInTheDocument(); + }); + }); + + test('opens and closes the update modal correctly', async () => { + render( + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.getAllByTestId('editAgendCategoryModalBtn')[0], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('editAgendCategoryModalBtn')[0]); + + await waitFor(() => { + return expect( + screen.findByTestId('updateAgendaCategoryModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('updateAgendaCategoryModalCloseBtn')); + + await waitForElementToBeRemoved(() => + screen.queryByTestId('updateAgendaCategoryModalCloseBtn'), + ); + }); + + test('opens and closes the preview modal correctly', async () => { + render( + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.getAllByTestId('previewAgendaCategoryModalBtn')[0], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('previewAgendaCategoryModalBtn')[0]); + + await waitFor(() => { + return expect( + screen.findByTestId('previewAgendaCategoryModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('previewAgendaCategoryModalCloseBtn')); + + await waitForElementToBeRemoved(() => + screen.queryByTestId('previewAgendaCategoryModalCloseBtn'), + ); + }); + + test('opens and closes the update and delete modals through the preview modal', async () => { + render( + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.getAllByTestId('previewAgendaCategoryModalBtn')[0], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('previewAgendaCategoryModalBtn')[0]); + + await waitFor(() => { + return expect( + screen.findByTestId('previewAgendaCategoryModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + + await waitFor(() => { + expect( + screen.getByTestId('deleteAgendaCategoryModalBtn'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('deleteAgendaCategoryModalBtn')); + + await waitFor(() => { + return expect( + screen.findByTestId('deleteAgendaCategoryCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('deleteAgendaCategoryCloseBtn')); + + await waitForElementToBeRemoved(() => + screen.queryByTestId('deleteAgendaCategoryCloseBtn'), + ); + + await waitFor(() => { + expect( + screen.getByTestId('editAgendaCategoryPreviewModalBtn'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('editAgendaCategoryPreviewModalBtn')); + + await waitFor(() => { + return expect( + screen.findByTestId('updateAgendaCategoryModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('updateAgendaCategoryModalCloseBtn')); + + await waitForElementToBeRemoved(() => + screen.queryByTestId('updateAgendaCategoryModalCloseBtn'), + ); + }); + + test('updates an agenda category and toasts success', async () => { + render( + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.getAllByTestId('editAgendCategoryModalBtn')[0], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('editAgendCategoryModalBtn')[0]); + + const name = screen.getByPlaceholderText(translations.name); + const description = screen.getByPlaceholderText(translations.description); + + fireEvent.change(name, { target: { value: '' } }); + userEvent.type(name, formData.name); + + fireEvent.change(description, { target: { value: '' } }); + userEvent.type(description, formData.description); + + await waitFor(() => { + expect(screen.getByTestId('editAgendaCategoryBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('editAgendaCategoryBtn')); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.agendaCategoryUpdated); + }); + }); + + test('toasts error on unsuccessful updation', async () => { + render( + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.getAllByTestId('editAgendCategoryModalBtn')[0], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('editAgendCategoryModalBtn')[0]); + + const nameInput = screen.getByLabelText(translations.name); + const descriptionInput = screen.getByLabelText(translations.description); + fireEvent.change(nameInput, { target: { value: '' } }); + fireEvent.change(descriptionInput, { + target: { value: '' }, + }); + userEvent.type(nameInput, formData.name); + userEvent.type(descriptionInput, formData.description); + + await waitFor(() => { + expect(screen.getByTestId('editAgendaCategoryBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('editAgendaCategoryBtn')); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); + + test('deletes the agenda category and toasts success', async () => { + render( + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.getAllByTestId('previewAgendaCategoryModalBtn')[0], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('previewAgendaCategoryModalBtn')[0]); + + await waitFor(() => { + return expect( + screen.findByTestId('previewAgendaCategoryModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + + await waitFor(() => { + expect( + screen.getByTestId('deleteAgendaCategoryModalBtn'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('deleteAgendaCategoryModalBtn')); + + await waitFor(() => { + return expect( + screen.findByTestId('deleteAgendaCategoryCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('deleteAgendaCategoryBtn')); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.agendaCategoryDeleted); + }); + }); + + test('toasts error on unsuccessful deletion', async () => { + render( + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.getAllByTestId('previewAgendaCategoryModalBtn')[0], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('previewAgendaCategoryModalBtn')[0]); + + await waitFor(() => { + return expect( + screen.findByTestId('previewAgendaCategoryModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + + await waitFor(() => { + expect( + screen.getByTestId('deleteAgendaCategoryModalBtn'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('deleteAgendaCategoryModalBtn')); + + await waitFor(() => { + return expect( + screen.findByTestId('deleteAgendaCategoryCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('deleteAgendaCategoryBtn')); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/components/AgendaCategory/AgendaCategoryContainer.tsx b/src/components/AgendaCategory/AgendaCategoryContainer.tsx new file mode 100644 index 0000000000..e803e77172 --- /dev/null +++ b/src/components/AgendaCategory/AgendaCategoryContainer.tsx @@ -0,0 +1,272 @@ +import React, { useState } from 'react'; +import type { ChangeEvent } from 'react'; +import { Button, Col, Row } from 'react-bootstrap'; +import { useTranslation } from 'react-i18next'; +import { toast } from 'react-toastify'; +import { useMutation } from '@apollo/client'; + +import { + DELETE_AGENDA_ITEM_CATEGORY_MUTATION, + UPDATE_AGENDA_ITEM_CATEGORY_MUTATION, +} from 'GraphQl/Mutations/mutations'; +import type { InterfaceAgendaItemCategoryInfo } from 'utils/interfaces'; +import styles from './AgendaCategoryContainer.module.css'; + +import AgendaCategoryDeleteModal from 'screens/OrganizationAgendaCategory/AgendaCategoryDeleteModal'; +import AgendaCategoryPreviewModal from 'screens/OrganizationAgendaCategory/AgendaCategoryPreviewModal'; +import AgendaCategoryUpdateModal from 'screens/OrganizationAgendaCategory/AgendaCategoryUpdateModal'; + +function agendaCategoryContainer({ + agendaCategoryConnection, + agendaCategoryData, + agendaCategoryRefetch, +}: { + agendaCategoryConnection: 'Organization'; + agendaCategoryData: InterfaceAgendaItemCategoryInfo[] | undefined; + agendaCategoryRefetch: () => void; +}): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'organizationAgendaCategory', + }); + const { t: tCommon } = useTranslation('common'); + const [ + agendaCategoryPreviewModalIsOpen, + setAgendaCategoryPreviewModalIsOpen, + ] = useState(false); + const [agendaCategoryUpdateModalIsOpen, setAgendaCategoryUpdateModalIsOpen] = + useState(false); + const [agendaCategoryDeleteModalIsOpen, setAgendaCategoryDeleteModalIsOpen] = + useState(false); + + const [agendaCategoryId, setAgendaCategoryId] = useState(''); + + const [formState, setFormState] = useState({ + name: '', + description: '', + createdBy: '', + }); + + const showPreviewModal = ( + agendaItemCategory: InterfaceAgendaItemCategoryInfo, + ): void => { + setAgendaCategoryState(agendaItemCategory); + setAgendaCategoryPreviewModalIsOpen(true); + }; + + const hidePreviewModal = (): void => { + setAgendaCategoryPreviewModalIsOpen(false); + }; + + const showUpdateModal = (): void => { + setAgendaCategoryUpdateModalIsOpen(!agendaCategoryUpdateModalIsOpen); + }; + + const hideUpdateModal = (): void => { + setAgendaCategoryUpdateModalIsOpen(!agendaCategoryUpdateModalIsOpen); + }; + + const toggleDeleteModal = (): void => { + setAgendaCategoryDeleteModalIsOpen(!agendaCategoryDeleteModalIsOpen); + }; + + const [updateAgendaCategory] = useMutation( + UPDATE_AGENDA_ITEM_CATEGORY_MUTATION, + ); + + const updateAgendaCategoryHandler = async ( + event: ChangeEvent, + ): Promise => { + event.preventDefault(); + try { + await updateAgendaCategory({ + variables: { + updateAgendaCategoryId: agendaCategoryId, + input: { + name: formState.name, + description: formState.description, + }, + }, + }); + + agendaCategoryRefetch(); + hideUpdateModal(); + toast.success(t('agendaCategoryUpdated')); + } catch (error: unknown) { + if (error instanceof Error) { + toast.error(`Agenda Category Update Failed ${error.message}`); + } + } + }; + + const [deleteAgendaCategory] = useMutation( + DELETE_AGENDA_ITEM_CATEGORY_MUTATION, + ); + + const deleteAgendaCategoryHandler = async (): Promise => { + try { + await deleteAgendaCategory({ + variables: { + deleteAgendaCategoryId: agendaCategoryId, + }, + }); + agendaCategoryRefetch(); + toggleDeleteModal(); + toast.success(t('agendaCategoryDeleted')); + } catch (error: unknown) { + if (error instanceof Error) { + toast.error(`Agenda Category Delete Failed, ${error.message}`); + } + } + }; + + const handleEditClick = ( + agendaItemCategory: InterfaceAgendaItemCategoryInfo, + ): void => { + setAgendaCategoryState(agendaItemCategory); + showUpdateModal(); + }; + + const setAgendaCategoryState = ( + agendaItemCategory: InterfaceAgendaItemCategoryInfo, + ): void => { + setFormState({ + ...formState, + name: `${agendaItemCategory.name} `, + description: `${agendaItemCategory.description}`, + createdBy: `${agendaItemCategory.createdBy.firstName} ${agendaItemCategory.createdBy.lastName}`, + }); + setAgendaCategoryId(agendaItemCategory._id); + }; + + return ( + <> +
    +
    + +
    +
    {t('name')}
    + +
    + {t('description')} + + +
    {t('createdBy')}
    + +
    +
    {t('options')}
    + + + +
    + {agendaCategoryData?.map((agendaCategory, index) => ( +
    + +
    + {`${agendaCategory.name}`} + + + {agendaCategory.description} + + + {`${agendaCategory.createdBy.firstName} ${agendaCategory.createdBy.lastName}`} + + + +
    + + +
    + + + + {index !== agendaCategoryData.length - 1 && ( +
    + )} + + ))} + {agendaCategoryData?.length === 0 && ( +
    + {t('noAgendaCategories')} +
    + )} + + + + {/* Preview model */} + + {/* Update model */} + + {/* Delete model */} + + + ); +} + +export default agendaCategoryContainer; diff --git a/src/components/AgendaCategory/AgendaCategoryContainerMocks.ts b/src/components/AgendaCategory/AgendaCategoryContainerMocks.ts new file mode 100644 index 0000000000..f5dee5cffd --- /dev/null +++ b/src/components/AgendaCategory/AgendaCategoryContainerMocks.ts @@ -0,0 +1,104 @@ +import { + UPDATE_AGENDA_ITEM_CATEGORY_MUTATION, + DELETE_AGENDA_ITEM_CATEGORY_MUTATION, +} from 'GraphQl/Mutations/AgendaCategoryMutations'; + +export const MOCKS = [ + { + request: { + query: UPDATE_AGENDA_ITEM_CATEGORY_MUTATION, + variables: { + updateAgendaCategoryId: 'agendaCategory1', + input: { + name: 'AgendaCategory 1 Edited', + description: 'AgendaCategory 1 Description Edited', + }, + }, + }, + result: { + data: { + updateAgendaCategory: { + _id: 'agendaCategory1', + }, + }, + }, + }, + { + request: { + query: UPDATE_AGENDA_ITEM_CATEGORY_MUTATION, + variables: { + updateAgendaCategoryId: 'agendaCategory1', + input: { + name: 'AgendaCategory 1', + description: 'AgendaCategory 1 Description', + }, + }, + }, + result: { + data: { + updateAgendaCategory: { + _id: 'agendaCategory1', + }, + }, + }, + }, + { + request: { + query: UPDATE_AGENDA_ITEM_CATEGORY_MUTATION, + variables: { + updateAgendaCategoryId: 'agendaCategory2', + input: { + name: 'AgendaCategory 2 edited', + description: 'AgendaCategory 2 Description', + }, + }, + }, + result: { + data: { + updateAgendaCategory: { + _id: 'agendaCategory2', + }, + }, + }, + }, + { + request: { + query: DELETE_AGENDA_ITEM_CATEGORY_MUTATION, + variables: { + deleteAgendaCategoryId: 'agendaCategory1', + }, + }, + result: { + data: { + deleteAgendaCategory: { + _id: 'agendaCategory1', + }, + }, + }, + }, +]; + +export const MOCKS_ERROR_MUTATIONS = [ + { + request: { + query: UPDATE_AGENDA_ITEM_CATEGORY_MUTATION, + variables: { + updateAgendaCategoryId: 'agendaCategory1', + input: { + name: 'AgendaCategory 1 Edited', + description: 'AgendaCategory 1 Description Edited', + }, + }, + }, + error: new Error('Mock Graphql Error'), + }, + { + request: { + query: DELETE_AGENDA_ITEM_CATEGORY_MUTATION, + variables: { + deleteAgendaCategoryId: 'agendaCategory1', + }, + }, + error: new Error('Mock Graphql Error'), + }, +]; diff --git a/src/components/AgendaCategory/AgendaCategoryContainerProps.ts b/src/components/AgendaCategory/AgendaCategoryContainerProps.ts new file mode 100644 index 0000000000..5181eec153 --- /dev/null +++ b/src/components/AgendaCategory/AgendaCategoryContainerProps.ts @@ -0,0 +1,34 @@ +type AgendaCategoryConnectionType = 'Organization'; + +export const props = { + agendaCategoryConnection: 'Organization' as AgendaCategoryConnectionType, + agendaCategoryData: [ + { + _id: 'agendaCategory1', + name: 'AgendaCategory 1', + description: 'AgendaCategory 1 Description', + createdBy: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + { + _id: 'agendaCategory2', + name: 'AgendaCategory 2', + description: 'AgendaCategory 2 Description', + createdBy: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + ], + agendaCategoryRefetch: jest.fn(), +}; + +export const props2 = { + agendaCategoryConnection: 'Organization' as AgendaCategoryConnectionType, + agendaCategoryData: [], + agendaCategoryRefetch: jest.fn(), +}; diff --git a/src/components/AgendaItems/AgendaItemsContainer.module.css b/src/components/AgendaItems/AgendaItemsContainer.module.css new file mode 100644 index 0000000000..f254e7aad7 --- /dev/null +++ b/src/components/AgendaItems/AgendaItemsContainer.module.css @@ -0,0 +1,230 @@ +.createModal { + margin-top: 20vh; + margin-left: 13vw; + max-width: 80vw; +} + +.titlemodal { + color: var(--bs-gray-600); + font-weight: 600; + font-size: 20px; + margin-bottom: 20px; + padding-bottom: 5px; + border-bottom: 3px solid var(--bs-primary); + width: 65%; +} + +.agendaItemsOptionsButton { + width: 24px; + height: 24px; +} + +.agendaItemModal { + max-width: 80vw; + margin-top: 2vh; + margin-left: 13vw; +} + +.iconContainer { + display: flex; + justify-content: flex-end; +} +.icon { + margin: 1px; +} + +.errorIcon { + transform: scale(1.5); + color: var(--bs-danger); + margin-bottom: 1rem; +} + +.greenregbtn { + margin: 1rem 0 0; + margin-top: 15px; + border: 1px solid var(--bs-gray-300); + box-shadow: 0 2px 2px var(--bs-gray-300); + padding: 10px 10px; + border-radius: 5px; + background-color: var(--bs-primary); + width: 100%; + font-size: 16px; + color: var(--bs-white); + outline: none; + font-weight: 600; + cursor: pointer; + transition: + transform 0.2s, + box-shadow 0.2s; + width: 100%; +} + +.preview { + display: flex; + flex-direction: row; + font-weight: 900; + font-size: 16px; + color: rgb(80, 80, 80); +} + +.view { + margin-left: 2%; + font-weight: 600; + font-size: 16px; + color: var(--bs-gray-600); +} + +.previewFile { + display: flex; + flex-direction: column; + align-items: center; + width: 100%; + margin-top: 10px; +} + +.previewFile img, +.previewFile video { + width: 100%; + max-width: 400px; + height: auto; + margin-bottom: 10px; +} + +.attachmentPreview { + position: relative; + width: 100%; +} + +.closeButtonFile { + position: absolute; + top: 10px; + right: 10px; + background: transparent; + transform: scale(1.2); + cursor: pointer; + border: none; + color: #707070; + font-weight: 600; + font-size: 16px; + cursor: pointer; +} + +.tableHeader { + background-color: var(--bs-primary); + color: var(--bs-white); + font-size: 16px; +} + +.noOutline input { + outline: none; +} + +.categoryContainer { + display: flex; + flex-wrap: wrap; + gap: 10px; + justify-content: center; +} + +.categoryChip { + display: inline-flex; + align-items: center; + background-color: #e0e0e0; + border-radius: 16px; + padding: 0 12px; + font-size: 14px; + height: 32px; + margin: 5px; +} + +.urlListItem { + display: flex; + align-items: center; + justify-content: space-between; + padding: 5px 0; +} + +.urlIcon { + margin-right: 10px; +} + +.deleteButton { + margin-left: auto; + padding: 2px 5px; +} + +.urlListItem a { + text-decoration: none; + color: inherit; +} + +.urlListItem a:hover { + text-decoration: underline; +} + +.agendaItemRow { + border: 1px solid #dee2e6; + border-radius: 4px; + transition: box-shadow 0.2s ease; + background-color: #fff; +} +.agendaItemRow:hover { + background-color: #f0f0f0; +} + +.dragging { + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); + z-index: 1000; + background-color: #f0f0f0; +} + +.droppable { + background-color: #f9f9f9; /* Background color of droppable area */ +} + +.droppableDraggingOver { + background-color: #e6f7ff; /* Background color of droppable area while dragging over */ +} + +.tableHead { + background-color: #31bb6b !important; + color: white; + border-radius: 20px 20px 0px 0px !important; + padding: 20px; +} + +@media (max-width: 768px) { + .createModal, + .agendaItemModal { + margin: 10vh auto; + max-width: 90%; + } + + .titlemodal { + width: 90%; + } + + .greenregbtn { + width: 90%; + } + + /* Add more specific styles for smaller screens as needed */ +} + +@media (max-width: 576px) { + .createModal, + .agendaItemModal { + margin: 5vh auto; + max-width: 95%; + } + + .titlemodal { + width: 100%; + } + + .greenregbtn { + width: 100%; + } + + /* Additional specific styles for even smaller screens */ +} diff --git a/src/components/AgendaItems/AgendaItemsContainer.test.tsx b/src/components/AgendaItems/AgendaItemsContainer.test.tsx new file mode 100644 index 0000000000..cb514bbfb9 --- /dev/null +++ b/src/components/AgendaItems/AgendaItemsContainer.test.tsx @@ -0,0 +1,418 @@ +import React from 'react'; +import { + render, + screen, + waitFor, + act, + waitForElementToBeRemoved, + fireEvent, +} from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import 'jest-localstorage-mock'; +import { MockedProvider } from '@apollo/client/testing'; +import 'jest-location-mock'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import i18nForTest from 'utils/i18nForTest'; +import { toast } from 'react-toastify'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; + +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; + +import { props, props2 } from './AgendaItemsContainerProps'; +import { MOCKS, MOCKS_ERROR } from './AgendaItemsContainerMocks'; +import AgendaItemsContainer from './AgendaItemsContainer'; + +const link = new StaticMockLink(MOCKS, true); +const link2 = new StaticMockLink(MOCKS_ERROR, true); + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +async function wait(ms = 100): Promise { + await act(async () => { + return new Promise((resolve) => setTimeout(resolve, ms)); + }); +} + +const translations = JSON.parse( + JSON.stringify(i18nForTest.getDataByLanguage('en')?.translation.agendaItems), +); + +describe('Testing Agenda Items components', () => { + const formData = { + title: 'AgendaItem 1 Edited', + description: 'AgendaItem 1 Description Edited', + }; + + test('component loads correctly with items', async () => { + render( + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.queryByText(translations.noAgendaItems), + ).not.toBeInTheDocument(); + }); + }); + + test('component loads correctly with no agenda items', async () => { + render( + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.queryByText(translations.noAgendaItems), + ).toBeInTheDocument(); + }); + }); + + test('opens and closes the update modal correctly', async () => { + render( + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.getAllByTestId('editAgendaItemModalBtn')[0], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('editAgendaItemModalBtn')[0]); + + await waitFor(() => { + return expect( + screen.findByTestId('updateAgendaItemModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('updateAgendaItemModalCloseBtn')); + + await waitForElementToBeRemoved(() => + screen.queryByTestId('updateAgendaItemModalCloseBtn'), + ); + }); + + test('opens and closes the preview modal correctly', async () => { + render( + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.getAllByTestId('previewAgendaItemModalBtn')[0], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('previewAgendaItemModalBtn')[0]); + + await waitFor(() => { + return expect( + screen.findByTestId('previewAgendaItemModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('previewAgendaItemModalCloseBtn')); + + await waitForElementToBeRemoved(() => + screen.queryByTestId('previewAgendaItemModalCloseBtn'), + ); + }); + + test('opens and closes the update and delete modals through the preview modal', async () => { + render( + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.getAllByTestId('previewAgendaItemModalBtn')[0], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('previewAgendaItemModalBtn')[0]); + + await waitFor(() => { + return expect( + screen.findByTestId('previewAgendaItemModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + + await waitFor(() => { + expect( + screen.getByTestId('previewAgendaItemModalDeleteBtn'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('previewAgendaItemModalDeleteBtn')); + + await waitFor(() => { + return expect( + screen.findByTestId('deleteAgendaItemCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('deleteAgendaItemCloseBtn')); + + await waitForElementToBeRemoved(() => + screen.queryByTestId('deleteAgendaItemCloseBtn'), + ); + + await waitFor(() => { + expect( + screen.getByTestId('previewAgendaItemModalUpdateBtn'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('previewAgendaItemModalUpdateBtn')); + + await waitFor(() => { + return expect( + screen.findByTestId('updateAgendaItemModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('updateAgendaItemModalCloseBtn')); + + await waitForElementToBeRemoved(() => + screen.queryByTestId('updateAgendaItemModalCloseBtn'), + ); + }); + + test('updates an agenda Items and toasts success', async () => { + render( + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.getAllByTestId('editAgendaItemModalBtn')[0], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('editAgendaItemModalBtn')[0]); + + const title = screen.getByPlaceholderText(translations.enterTitle); + const description = screen.getByPlaceholderText( + translations.enterDescription, + ); + + fireEvent.change(title, { target: { value: '' } }); + userEvent.type(title, formData.title); + + fireEvent.change(description, { target: { value: '' } }); + userEvent.type(description, formData.description); + + await waitFor(() => { + expect(screen.getByTestId('updateAgendaItemBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('updateAgendaItemBtn')); + + await waitFor(() => { + // expect(toast.success).toBeCalledWith(translations.agendaItemUpdated); + }); + }); + + test('toasts error on unsuccessful updation', async () => { + render( + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.getAllByTestId('editAgendaItemModalBtn')[0], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('editAgendaItemModalBtn')[0]); + + const titleInput = screen.getByLabelText(translations.title); + const descriptionInput = screen.getByLabelText(translations.description); + fireEvent.change(titleInput, { target: { value: '' } }); + fireEvent.change(descriptionInput, { + target: { value: '' }, + }); + userEvent.type(titleInput, formData.title); + userEvent.type(descriptionInput, formData.description); + + await waitFor(() => { + expect(screen.getByTestId('updateAgendaItemBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('updateAgendaItemBtn')); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); + + test('deletes the agenda item and toasts success', async () => { + render( + + + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.getAllByTestId('previewAgendaItemModalBtn')[0], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('previewAgendaItemModalBtn')[0]); + + await waitFor(() => { + return expect( + screen.findByTestId('previewAgendaItemModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + + await waitFor(() => { + expect( + screen.getByTestId('previewAgendaItemModalDeleteBtn'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('previewAgendaItemModalDeleteBtn')); + + await waitFor(() => { + return expect( + screen.findByTestId('deleteAgendaItemCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('deleteAgendaItemBtn')); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.agendaItemDeleted); + }); + }); + + test('toasts error on unsuccessful deletion', async () => { + render( + + + + + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + screen.getAllByTestId('previewAgendaItemModalBtn')[0], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('previewAgendaItemModalBtn')[0]); + + await waitFor(() => { + return expect( + screen.findByTestId('previewAgendaItemModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + + await waitFor(() => { + expect( + screen.getByTestId('previewAgendaItemModalDeleteBtn'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('previewAgendaItemModalDeleteBtn')); + + await waitFor(() => { + return expect( + screen.findByTestId('deleteAgendaItemCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('deleteAgendaItemBtn')); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); + + // write test case for drag and drop line:- 172-202 +}); diff --git a/src/components/AgendaItems/AgendaItemsContainer.tsx b/src/components/AgendaItems/AgendaItemsContainer.tsx new file mode 100644 index 0000000000..5b3a00b139 --- /dev/null +++ b/src/components/AgendaItems/AgendaItemsContainer.tsx @@ -0,0 +1,411 @@ +import React, { useState } from 'react'; +import type { ChangeEvent } from 'react'; +import { Button, Col, Row } from 'react-bootstrap'; +import { useTranslation } from 'react-i18next'; +import { toast } from 'react-toastify'; +import { useMutation } from '@apollo/client'; +import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd'; +import type { DropResult } from 'react-beautiful-dnd'; + +import { + DELETE_AGENDA_ITEM_MUTATION, + UPDATE_AGENDA_ITEM_MUTATION, +} from 'GraphQl/Mutations/mutations'; +import type { + InterfaceAgendaItemInfo, + InterfaceAgendaItemCategoryInfo, +} from 'utils/interfaces'; +import styles from './AgendaItemsContainer.module.css'; + +import AgendaItemsPreviewModal from 'components/AgendaItems/AgendaItemsPreviewModal'; +import AgendaItemsDeleteModal from 'components/AgendaItems/AgendaItemsDeleteModal'; +import AgendaItemsUpdateModal from 'components/AgendaItems/AgendaItemsUpdateModal'; + +function AgendaItemsContainer({ + agendaItemConnection, + agendaItemData, + agendaItemRefetch, + agendaItemCategories, +}: { + agendaItemConnection: 'Event'; + agendaItemData: InterfaceAgendaItemInfo[] | undefined; + agendaItemRefetch: () => void; + agendaItemCategories: InterfaceAgendaItemCategoryInfo[] | undefined; +}): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'agendaItems', + }); + const { t: tCommon } = useTranslation('common'); + + const [agendaItemPreviewModalIsOpen, setAgendaItemPreviewModalIsOpen] = + useState(false); + const [agendaItemUpdateModalIsOpen, setAgendaItemUpdateModalIsOpen] = + useState(false); + const [agendaItemDeleteModalIsOpen, setAgendaItemDeleteModalIsOpen] = + useState(false); + + const [agendaItemId, setAgendaItemId] = useState(''); + + const [formState, setFormState] = useState<{ + agendaItemCategoryIds: string[]; + agendaItemCategoryNames: string[]; + title: string; + description: string; + duration: string; + attachments: string[]; + urls: string[]; + createdBy: { + firstName: string; + lastName: string; + }; + }>({ + agendaItemCategoryIds: [], + agendaItemCategoryNames: [], + title: '', + description: '', + duration: '', + attachments: [], + urls: [], + createdBy: { + firstName: '', + lastName: '', + }, + }); + + const showPreviewModal = (agendaItem: InterfaceAgendaItemInfo): void => { + setAgendaItemState(agendaItem); + setAgendaItemPreviewModalIsOpen(true); + }; + + const hidePreviewModal = (): void => { + setAgendaItemPreviewModalIsOpen(false); + }; + + const showUpdateModal = (): void => { + setAgendaItemUpdateModalIsOpen(!agendaItemUpdateModalIsOpen); + }; + + const hideUpdateModal = (): void => { + setAgendaItemUpdateModalIsOpen(!agendaItemUpdateModalIsOpen); + }; + + const toggleDeleteModal = (): void => { + setAgendaItemDeleteModalIsOpen(!agendaItemDeleteModalIsOpen); + }; + + const [updateAgendaItem] = useMutation(UPDATE_AGENDA_ITEM_MUTATION); + + const updateAgendaItemHandler = async ( + e: ChangeEvent, + ): Promise => { + e.preventDefault(); + try { + await updateAgendaItem({ + variables: { + updateAgendaItemId: agendaItemId, + input: { + title: formState.title, + description: formState.description, + duration: formState.duration, + categories: formState.agendaItemCategoryIds, + attachments: formState.attachments, + urls: formState.urls, + }, + }, + }); + agendaItemRefetch(); + hideUpdateModal(); + toast.success(t('agendaItemUpdated')); + } catch (error) { + if (error instanceof Error) { + toast.error(`${error.message}`); + } + } + }; + + const [deleteAgendaItem] = useMutation(DELETE_AGENDA_ITEM_MUTATION); + + const deleteAgendaItemHandler = async (): Promise => { + try { + await deleteAgendaItem({ + variables: { + removeAgendaItemId: agendaItemId, + }, + }); + agendaItemRefetch(); + toggleDeleteModal(); + toast.success(t('agendaItemDeleted')); + } catch (error) { + if (error instanceof Error) { + toast.error(`${error.message}`); + } + } + }; + + const handleEditClick = (agendaItem: InterfaceAgendaItemInfo): void => { + setAgendaItemState(agendaItem); + showUpdateModal(); + }; + + const setAgendaItemState = (agendaItem: InterfaceAgendaItemInfo): void => { + setFormState({ + ...formState, + agendaItemCategoryIds: agendaItem.categories.map( + (category) => category._id, + ), + agendaItemCategoryNames: agendaItem.categories.map( + (category) => category.name, + ), + title: agendaItem.title, + description: agendaItem.description, + duration: agendaItem.duration, + attachments: agendaItem.attachments, + urls: agendaItem.urls, + createdBy: { + firstName: agendaItem.createdBy.firstName, + lastName: agendaItem.createdBy.lastName, + }, + }); + setAgendaItemId(agendaItem._id); + }; + + const onDragEnd = async (result: DropResult): Promise => { + if (!result.destination || !agendaItemData) { + return; + } + + const reorderedAgendaItems = Array.from(agendaItemData); + const [removed] = reorderedAgendaItems.splice(result.source.index, 1); + reorderedAgendaItems.splice(result.destination.index, 0, removed); + + try { + await Promise.all( + reorderedAgendaItems.map(async (item, index) => { + if (item.sequence !== index + 1) { + // Only update if the sequence has changed + await updateAgendaItem({ + variables: { + updateAgendaItemId: item._id, + input: { + sequence: index + 1, // Update sequence based on new index + }, + }, + }); + } + }), + ); + + // After updating all items, refetch data and notify success + agendaItemRefetch(); + } catch (error) { + if (error instanceof Error) { + toast.error(`${error.message}`); + } + } + }; + + return ( + <> +
    +
    + +
    +
    {t('sequence')}
    + +
    + {t('title')} + + + {t('category')} + + + {t('description')} + + +
    {t('options')}
    + + + + + + {(provided) => ( +
    + {agendaItemData && + agendaItemData.map((agendaItem, index) => ( + + {(provided, snapshot) => ( +
    + +
    + + + + {agendaItem.title} + + +
    + {agendaItem.categories.length > 0 ? ( + agendaItem.categories.map((category, idx) => ( + + {category.name} + {idx < agendaItem.categories.length - 1 && + ', '} + + )) + ) : ( + + No Category + + )} +
    + {' '} +
    + {agendaItem.description} + + +
    + + +
    + + + + )} + + ))} + {agendaItemData?.length === 0 && ( +
    + {t('noAgendaItems')} +
    + )} + + )} + + + + {/* Preview model */} + + {/* Delete model */} + + {/* Update model */} + + + ); +} + +export default AgendaItemsContainer; diff --git a/src/components/AgendaItems/AgendaItemsContainerMocks.ts b/src/components/AgendaItems/AgendaItemsContainerMocks.ts new file mode 100644 index 0000000000..11cd8b254e --- /dev/null +++ b/src/components/AgendaItems/AgendaItemsContainerMocks.ts @@ -0,0 +1,119 @@ +import { + UPDATE_AGENDA_ITEM_MUTATION, + DELETE_AGENDA_ITEM_MUTATION, +} from 'GraphQl/Mutations/AgendaItemMutations'; + +export const MOCKS = [ + { + request: { + query: UPDATE_AGENDA_ITEM_MUTATION, + variables: { + updateAgendaItemId: 'agendaItem1', + input: { + title: 'AgendaItem 1 Edited', + description: 'AgendaItem 1 Description Edited', + }, + }, + }, + result: { + data: { + updateAgendaItem: { + _id: 'agendaItem1', + }, + }, + }, + }, + { + request: { + query: UPDATE_AGENDA_ITEM_MUTATION, + variables: { + updateAgendaItemId: 'agendaItem1', + input: { + title: 'AgendaItem 1', + description: 'AgendaItem 1 Description', + }, + }, + }, + result: { + data: { + updateAgendaItem: { + _id: 'agendaItem1', + }, + }, + }, + }, + { + request: { + query: UPDATE_AGENDA_ITEM_MUTATION, + variables: { + updateAgendaItemId: 'agendaItem2', + input: { + title: 'AgendaItem 2 edited', + description: 'AgendaItem 2 Description', + }, + }, + }, + result: { + data: { + updateAgendaItem: { + _id: 'agendaItem2', + }, + }, + }, + }, + { + request: { + query: DELETE_AGENDA_ITEM_MUTATION, + variables: { + removeAgendaItemId: 'agendaItem1', + }, + }, + result: { + data: { + removeAgendaItem: { + _id: 'agendaItem1', + }, + }, + }, + }, + { + request: { + query: DELETE_AGENDA_ITEM_MUTATION, + variables: { + removeAgendaItemId: 'agendaItem2', + }, + }, + result: { + data: { + removeAgendaItem: { + _id: 'agendaItem2', + }, + }, + }, + }, +]; + +export const MOCKS_ERROR = [ + { + request: { + query: UPDATE_AGENDA_ITEM_MUTATION, + variables: { + updateAgendaItemId: 'agendaItem1', + input: { + title: 'AgendaItem 1 Edited', + description: 'AgendaItem 1 Description Edited', + }, + }, + }, + error: new Error('An error occurred'), + }, + { + request: { + query: DELETE_AGENDA_ITEM_MUTATION, + variables: { + removeAgendaItemId: 'agendaItem1', + }, + }, + error: new Error('An error occurred'), + }, +]; diff --git a/src/components/AgendaItems/AgendaItemsContainerProps.ts b/src/components/AgendaItems/AgendaItemsContainerProps.ts new file mode 100644 index 0000000000..d6dcf3feca --- /dev/null +++ b/src/components/AgendaItems/AgendaItemsContainerProps.ts @@ -0,0 +1,101 @@ +type AgendaItemConnectionType = 'Event'; + +export const props = { + agendaItemConnection: 'Event' as AgendaItemConnectionType, + agendaItemData: [ + { + _id: 'agendaItem1', + title: 'AgendaItem 1', + description: 'AgendaItem 1 Description', + duration: '2h', + attachments: ['attachment1'], + createdBy: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + urls: [], + users: [], + sequence: 1, + categories: [ + { + _id: 'category1', + name: 'Category 1', + }, + ], + organization: { + _id: 'org1', + name: 'Unity Foundation', + }, + relatedEvent: { + _id: 'event1', + title: 'Aerobics for Everyone', + }, + }, + { + _id: 'agendaItem2', + title: 'AgendaItem 2', + description: 'AgendaItem 2 Description', + duration: '1h', + attachments: ['attachment3'], + createdBy: { + _id: 'user1', + firstName: 'Jane', + lastName: 'Doe', + }, + urls: ['http://example.com'], + users: [ + { + _id: 'user2', + firstName: 'John', + lastName: 'Smith', + }, + ], + sequence: 2, + categories: [ + { + _id: 'category2', + name: 'Category 2', + }, + ], + organization: { + _id: 'org2', + name: 'Health Organization', + }, + relatedEvent: { + _id: 'event2', + title: 'Yoga for Beginners', + }, + }, + ], + agendaItemRefetch: jest.fn(), + agendaItemCategories: [ + { + _id: 'agendaCategory1', + name: 'AgendaCategory 1', + description: 'AgendaCategory 1 Description', + createdBy: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + { + _id: 'agendaCategory2', + name: 'AgendaCategory 2', + description: 'AgendaCategory 2 Description', + createdBy: { + _id: 'user1', + firstName: 'Jane', + lastName: 'Doe', + }, + }, + ], +}; + +export const props2 = { + agendaItemConnection: 'Event' as AgendaItemConnectionType, + agendaItemData: [], + agendaItemRefetch: jest.fn(), + agendaItemCategories: [], +}; diff --git a/src/components/AgendaItems/AgendaItemsCreateModal.test.tsx b/src/components/AgendaItems/AgendaItemsCreateModal.test.tsx new file mode 100644 index 0000000000..5b7339ad67 --- /dev/null +++ b/src/components/AgendaItems/AgendaItemsCreateModal.test.tsx @@ -0,0 +1,368 @@ +import React from 'react'; +import { + render, + screen, + fireEvent, + waitFor, + within, +} from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; + +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; + +import AgendaItemsCreateModal from './AgendaItemsCreateModal'; +import { toast } from 'react-toastify'; +import convertToBase64 from 'utils/convertToBase64'; + +const mockFormState = { + title: 'Test Title', + description: 'Test Description', + duration: '20', + attachments: ['Test Attachment'], + urls: ['https://example.com'], + agendaItemCategoryIds: ['category'], +}; +const mockHideCreateModal = jest.fn(); +const mockSetFormState = jest.fn(); +const mockCreateAgendaItemHandler = jest.fn(); +const mockT = (key: string): string => key; +const mockAgendaItemCategories = [ + { + _id: '1', + name: 'Test Name', + description: 'Test Description', + createdBy: { + _id: '1', + firstName: 'Test', + lastName: 'User', + }, + }, + { + _id: '2', + name: 'Another Category', + description: 'Another Description', + createdBy: { + _id: '2', + firstName: 'Another', + lastName: 'Creator', + }, + }, + { + _id: '3', + name: 'Third Category', + description: 'Third Description', + createdBy: { + _id: '3', + firstName: 'Third', + lastName: 'User', + }, + }, +]; +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); +jest.mock('utils/convertToBase64'); +const mockedConvertToBase64 = convertToBase64 as jest.MockedFunction< + typeof convertToBase64 +>; + +describe('AgendaItemsCreateModal', () => { + test('renders modal correctly', () => { + render( + + + + + + + + + + + , + ); + + expect(screen.getByText('agendaItemDetails')).toBeInTheDocument(); + expect(screen.getByTestId('createAgendaItemFormBtn')).toBeInTheDocument(); + expect( + screen.getByTestId('createAgendaItemModalCloseBtn'), + ).toBeInTheDocument(); + }); + + test('tests the condition for formState', async () => { + const mockFormState = { + title: 'Test Title', + description: 'Test Description', + duration: '20', + attachments: ['Test Attachment'], + urls: ['https://example.com'], + agendaItemCategoryIds: ['1'], + }; + render( + + + + + + + + + + + , + ); + + fireEvent.change(screen.getByLabelText('title'), { + target: { value: 'New title' }, + }); + + fireEvent.change(screen.getByLabelText('description'), { + target: { value: 'New description' }, + }); + + fireEvent.change(screen.getByLabelText('duration'), { + target: { value: '30' }, + }); + + fireEvent.click(screen.getByTestId('deleteUrl')); + fireEvent.click(screen.getByTestId('deleteAttachment')); + + expect(mockSetFormState).toHaveBeenCalledWith({ + ...mockFormState, + title: 'New title', + }); + expect(mockSetFormState).toHaveBeenCalledWith({ + ...mockFormState, + description: 'New description', + }); + + expect(mockSetFormState).toHaveBeenCalledWith({ + ...mockFormState, + duration: '30', + }); + + await waitFor(() => { + expect(mockSetFormState).toHaveBeenCalledWith({ + ...mockFormState, + urls: [], + }); + }); + + await waitFor(() => { + expect(mockSetFormState).toHaveBeenCalledWith({ + ...mockFormState, + attachments: [], + }); + }); + }); + test('handleAddUrl correctly adds valid URL', async () => { + render( + + + + + + + + + , + ); + + const urlInput = screen.getByTestId('urlInput'); + const linkBtn = screen.getByTestId('linkBtn'); + + fireEvent.change(urlInput, { target: { value: 'https://example.com' } }); + fireEvent.click(linkBtn); + + await waitFor(() => { + expect(mockSetFormState).toHaveBeenCalledWith({ + ...mockFormState, + urls: [...mockFormState.urls, 'https://example.com'], + }); + }); + }); + + test('shows error toast for invalid URL', async () => { + render( + + + + + + + + + + + , + ); + + const urlInput = screen.getByTestId('urlInput'); + const linkBtn = screen.getByTestId('linkBtn'); + + fireEvent.change(urlInput, { target: { value: 'invalid-url' } }); + fireEvent.click(linkBtn); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalledWith('invalidUrl'); + }); + }); + + test('shows error toast for file size exceeding limit', async () => { + render( + + + + + + + + + + + , + ); + + const fileInput = screen.getByTestId('attachment'); + const largeFile = new File( + ['a'.repeat(11 * 1024 * 1024)], + 'large-file.jpg', + ); // 11 MB file + + Object.defineProperty(fileInput, 'files', { + value: [largeFile], + }); + + fireEvent.change(fileInput); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalledWith('fileSizeExceedsLimit'); + }); + }); + + test('adds files correctly when within size limit', async () => { + mockedConvertToBase64.mockResolvedValue('base64-file'); + + render( + + + + + + + + + + + , + ); + + const fileInput = screen.getByTestId('attachment'); + const smallFile = new File(['small-file-content'], 'small-file.jpg'); // Small file + + Object.defineProperty(fileInput, 'files', { + value: [smallFile], + }); + + fireEvent.change(fileInput); + + await waitFor(() => { + expect(mockSetFormState).toHaveBeenCalledWith({ + ...mockFormState, + attachments: [...mockFormState.attachments, 'base64-file'], + }); + }); + }); + test('renders autocomplete and selects categories correctly', async () => { + render( + + + + + + + + + + + , + ); + + const autocomplete = screen.getByTestId('categorySelect'); + expect(autocomplete).toBeInTheDocument(); + + const input = within(autocomplete).getByRole('combobox'); + fireEvent.mouseDown(input); + + const options = screen.getAllByRole('option'); + expect(options).toHaveLength(mockAgendaItemCategories.length); + + fireEvent.click(options[0]); + fireEvent.click(options[1]); + }); +}); diff --git a/src/components/AgendaItems/AgendaItemsCreateModal.tsx b/src/components/AgendaItems/AgendaItemsCreateModal.tsx new file mode 100644 index 0000000000..8506319285 --- /dev/null +++ b/src/components/AgendaItems/AgendaItemsCreateModal.tsx @@ -0,0 +1,293 @@ +import React, { useState, useEffect } from 'react'; +import { Modal, Form, Button, Row, Col } from 'react-bootstrap'; +import { Autocomplete, TextField } from '@mui/material'; + +import { FaLink, FaTrash } from 'react-icons/fa'; +import { toast } from 'react-toastify'; +import styles from './AgendaItemsContainer.module.css'; +import type { ChangeEvent } from 'react'; +import type { InterfaceAgendaItemCategoryInfo } from 'utils/interfaces'; +import convertToBase64 from 'utils/convertToBase64'; + +interface InterfaceFormStateType { + agendaItemCategoryIds: string[]; + title: string; + description: string; + duration: string; + attachments: string[]; + urls: string[]; +} + +interface InterfaceAgendaItemsCreateModalProps { + agendaItemCreateModalIsOpen: boolean; + hideCreateModal: () => void; + formState: InterfaceFormStateType; + setFormState: (state: React.SetStateAction) => void; + createAgendaItemHandler: (e: ChangeEvent) => Promise; + t: (key: string) => string; + agendaItemCategories: InterfaceAgendaItemCategoryInfo[] | undefined; +} + +const AgendaItemsCreateModal: React.FC< + InterfaceAgendaItemsCreateModalProps +> = ({ + agendaItemCreateModalIsOpen, + hideCreateModal, + formState, + setFormState, + createAgendaItemHandler, + t, + agendaItemCategories, +}) => { + const [newUrl, setNewUrl] = useState(''); + + useEffect(() => { + setFormState((prevState) => ({ + ...prevState, + urls: prevState.urls.filter((url) => url.trim() !== ''), + attachments: prevState.attachments.filter((att) => att !== ''), + })); + }, []); + + // Function to validate URL + const isValidUrl = (url: string): boolean => { + // Regular expression for basic URL validation + const urlRegex = /^(ftp|http|https):\/\/[^ "]+$/; + return urlRegex.test(url); + }; + + const handleAddUrl = (): void => { + if (newUrl.trim() !== '' && isValidUrl(newUrl.trim())) { + setFormState({ + ...formState, + urls: [...formState.urls.filter((url) => url.trim() !== ''), newUrl], + }); + setNewUrl(''); + } else { + toast.error(t('invalidUrl')); + } + }; + + const handleRemoveUrl = (url: string): void => { + setFormState({ + ...formState, + urls: formState.urls.filter((item) => item !== url), + }); + }; + + const handleFileChange = async ( + e: React.ChangeEvent, + ): Promise => { + const target = e.target as HTMLInputElement; + if (target.files) { + const files = Array.from(target.files); + let totalSize = 0; + files.forEach((file) => { + totalSize += file.size; + }); + if (totalSize > 10 * 1024 * 1024) { + toast.error(t('fileSizeExceedsLimit')); + return; + } + const base64Files = await Promise.all( + files.map(async (file) => await convertToBase64(file)), + ); + setFormState({ + ...formState, + attachments: [...formState.attachments, ...base64Files], + }); + } + }; + + const handleRemoveAttachment = (attachment: string): void => { + setFormState({ + ...formState, + attachments: formState.attachments.filter((item) => item !== attachment), + }); + }; + + return ( + + +

    {t('agendaItemDetails')}

    + +
    + + + + + formState.agendaItemCategoryIds.includes(category._id), + ) || [] + } + // isOptionEqualToValue={(option, value) => option._id === value._id} + filterSelectedOptions={true} + getOptionLabel={( + category: InterfaceAgendaItemCategoryInfo, + ): string => category.name} + onChange={(_, newCategories): void => { + setFormState({ + ...formState, + agendaItemCategoryIds: newCategories.map( + (category) => category._id, + ), + }); + }} + renderInput={(params) => ( + + )} + /> + + +
    + + {t('title')} + + setFormState({ ...formState, title: e.target.value }) + } + /> + + + + + {t('duration')} + + setFormState({ ...formState, duration: e.target.value }) + } + /> + + + + + {t('description')} + + setFormState({ ...formState, description: e.target.value }) + } + /> + + + + {t('url')} +
    + setNewUrl(e.target.value)} + /> + +
    + + {formState.urls.map((url, index) => ( +
  • + + + {url.length > 50 ? url.substring(0, 50) + '...' : url} + + +
  • + ))} +
    + + {t('attachments')} + + {t('attachmentLimit')} + + {formState.attachments && ( +
    + {formState.attachments.map((attachment, index) => ( +
    + {attachment.includes('video') ? ( + + ) : ( + Attachment preview + )} + +
    + ))} +
    + )} + + + + + ); +}; + +export default AgendaItemsCreateModal; diff --git a/src/components/AgendaItems/AgendaItemsDeleteModal.tsx b/src/components/AgendaItems/AgendaItemsDeleteModal.tsx new file mode 100644 index 0000000000..5361ca4985 --- /dev/null +++ b/src/components/AgendaItems/AgendaItemsDeleteModal.tsx @@ -0,0 +1,63 @@ +import React from 'react'; +import { Modal, Button } from 'react-bootstrap'; +import styles from './AgendaItemsContainer.module.css'; + +interface InterfaceAgendaItemsDeleteModalProps { + agendaItemDeleteModalIsOpen: boolean; + toggleDeleteModal: () => void; + deleteAgendaItemHandler: () => Promise; + t: (key: string) => string; + tCommon: (key: string) => string; +} + +const AgendaItemsDeleteModal: React.FC< + InterfaceAgendaItemsDeleteModalProps +> = ({ + agendaItemDeleteModalIsOpen, + toggleDeleteModal, + deleteAgendaItemHandler, + t, + tCommon, +}) => { + return ( + + + + {t('deleteAgendaItem')} + + + +

    {t('deleteAgendaItemMsg')}

    +
    + + + + +
    + ); +}; + +export default AgendaItemsDeleteModal; diff --git a/src/components/AgendaItems/AgendaItemsPreviewModal.test.tsx b/src/components/AgendaItems/AgendaItemsPreviewModal.test.tsx new file mode 100644 index 0000000000..0a7b4646ba --- /dev/null +++ b/src/components/AgendaItems/AgendaItemsPreviewModal.test.tsx @@ -0,0 +1,102 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; + +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; + +import AgendaItemsPreviewModal from './AgendaItemsPreviewModal'; + +const mockFormState = { + title: 'Test Title', + description: 'Test Description', + duration: '20', + attachments: [ + 'https://example.com/video.mp4', + 'https://example.com/image.jpg', + ], + urls: [ + 'https://example.com', + 'https://thisisaverylongurlthatexceedsfiftycharacters.com/very/long/path', + ], + agendaItemCategoryIds: ['category'], + agendaItemCategoryNames: ['category'], + createdBy: { + firstName: 'Test', + lastName: 'User', + }, +}; + +const mockT = (key: string): string => key; + +describe('AgendaItemsPreviewModal', () => { + test('check url and attachment links', () => { + render( + + + + + + + + + + + , + ); + + expect(screen.getByText('Test Title')).toBeInTheDocument(); + expect(screen.getByText('Test Description')).toBeInTheDocument(); + expect(screen.getByText('20')).toBeInTheDocument(); + expect(screen.getByText('https://example.com')).toBeInTheDocument(); + + // Check attachments + const videoLink = screen.getByText( + (content, element) => + element?.tagName.toLowerCase() === 'a' && + (element as HTMLAnchorElement)?.href === + 'https://example.com/video.mp4', + ); + expect(videoLink).toBeInTheDocument(); + + const imageLink = screen.getByText( + (content, element) => + element?.tagName.toLowerCase() === 'a' && + (element as HTMLAnchorElement)?.href === + 'https://example.com/image.jpg', + ); + expect(imageLink).toBeInTheDocument(); + + // Check URLs + const shortUrlLink = screen.getByText( + (content, element) => + element?.tagName.toLowerCase() === 'a' && + (element as HTMLAnchorElement)?.href === 'https://example.com/', + ); + expect(shortUrlLink).toBeInTheDocument(); + expect(shortUrlLink).toHaveTextContent('https://example.com'); + + const longUrlLink = screen.getByText( + (content, element) => + element?.tagName.toLowerCase() === 'a' && + (element as HTMLAnchorElement)?.href === + 'https://thisisaverylongurlthatexceedsfiftycharacters.com/very/long/path', + ); + expect(longUrlLink).toBeInTheDocument(); + expect(longUrlLink).toHaveTextContent( + 'https://thisisaverylongurlthatexceedsfiftycharacte...', + ); + }); +}); diff --git a/src/components/AgendaItems/AgendaItemsPreviewModal.tsx b/src/components/AgendaItems/AgendaItemsPreviewModal.tsx new file mode 100644 index 0000000000..fc8cb257a2 --- /dev/null +++ b/src/components/AgendaItems/AgendaItemsPreviewModal.tsx @@ -0,0 +1,151 @@ +import React from 'react'; +import { Modal, Form, Button } from 'react-bootstrap'; +import styles from './AgendaItemsContainer.module.css'; +import { FaLink } from 'react-icons/fa'; + +interface InterfaceFormStateType { + agendaItemCategoryIds: string[]; + agendaItemCategoryNames: string[]; + title: string; + description: string; + duration: string; + attachments: string[]; + urls: string[]; + createdBy: { + firstName: string; + lastName: string; + }; +} + +interface InterfaceAgendaItemsPreviewModalProps { + agendaItemPreviewModalIsOpen: boolean; + hidePreviewModal: () => void; + showUpdateModal: () => void; + toggleDeleteModal: () => void; + formState: InterfaceFormStateType; + t: (key: string) => string; +} + +const AgendaItemsPreviewModal: React.FC< + InterfaceAgendaItemsPreviewModalProps +> = ({ + agendaItemPreviewModalIsOpen, + hidePreviewModal, + showUpdateModal, + toggleDeleteModal, + formState, + t, +}) => { + const renderAttachments = (): JSX.Element[] => { + return formState.attachments.map((attachment, index) => ( +
    + {attachment.includes('video') ? ( + + + + ) : ( + + Attachment preview + + )} +
    + )); + }; + + const renderUrls = (): JSX.Element[] => { + return formState.urls.map((url, index) => ( +
  • + + + {url.length > 50 ? `${url.substring(0, 50)}...` : url} + +
  • + )); + }; + + return ( + + +

    {t('agendaItemDetails')}

    + +
    + +
    +
    +
    +

    {t('category')}

    + + {formState.agendaItemCategoryNames.join(', ')} + +
    +
    +

    {t('title')}

    + {formState.title} +
    +
    +

    {t('description')}

    + {formState.description} +
    +
    +

    {t('duration')}

    + {formState.duration} +
    +
    +

    {t('createdBy')}

    + + {`${formState.createdBy.firstName} ${formState.createdBy.lastName}`} + +
    +
    +

    {t('urls')}

    + {renderUrls()} +
    +
    +

    {t('attachments')}

    + {renderAttachments()} +
    +
    +
    + + +
    + +
    +
    + ); +}; + +export default AgendaItemsPreviewModal; diff --git a/src/components/AgendaItems/AgendaItemsUpdateModal.test.tsx b/src/components/AgendaItems/AgendaItemsUpdateModal.test.tsx new file mode 100644 index 0000000000..0f11ea31b2 --- /dev/null +++ b/src/components/AgendaItems/AgendaItemsUpdateModal.test.tsx @@ -0,0 +1,369 @@ +import React from 'react'; +import { + render, + screen, + fireEvent, + waitFor, + within, +} from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; + +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; + +import AgendaItemsUpdateModal from './AgendaItemsUpdateModal'; +import { toast } from 'react-toastify'; +import convertToBase64 from 'utils/convertToBase64'; + +const mockFormState = { + title: 'Test Title', + description: 'Test Description', + duration: '20', + attachments: ['Test Attachment'], + urls: ['https://example.com'], + agendaItemCategoryIds: ['category'], + agendaItemCategoryNames: ['category'], + createdBy: { + firstName: 'Test', + lastName: 'User', + }, +}; + +const mockAgendaItemCategories = [ + { + _id: '1', + name: 'Test Name', + description: 'Test Description', + createdBy: { + _id: '1', + firstName: 'Test', + lastName: 'User', + }, + }, + { + _id: '2', + name: 'Another Category', + description: 'Another Description', + createdBy: { + _id: '2', + firstName: 'Another', + lastName: 'Creator', + }, + }, + { + _id: '3', + name: 'Third Category', + description: 'Third Description', + createdBy: { + _id: '3', + firstName: 'Third', + lastName: 'User', + }, + }, +]; + +const mockHideUpdateModal = jest.fn(); +const mockSetFormState = jest.fn(); +const mockUpdateAgendaItemHandler = jest.fn(); +const mockT = (key: string): string => key; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); +jest.mock('utils/convertToBase64'); +const mockedConvertToBase64 = convertToBase64 as jest.MockedFunction< + typeof convertToBase64 +>; + +describe('AgendaItemsUpdateModal', () => { + test('renders modal correctly', () => { + render( + + + + + + + + + + + , + ); + + expect(screen.getByText('updateAgendaItem')).toBeInTheDocument(); + expect(screen.getByTestId('updateAgendaItemBtn')).toBeInTheDocument(); + expect( + screen.getByTestId('updateAgendaItemModalCloseBtn'), + ).toBeInTheDocument(); + }); + + test('tests the condition for formState.title and formState.description', async () => { + render( + + + + + + + + + + + , + ); + + fireEvent.change(screen.getByLabelText('title'), { + target: { value: 'New title' }, + }); + + fireEvent.change(screen.getByLabelText('description'), { + target: { value: 'New description' }, + }); + + fireEvent.change(screen.getByLabelText('duration'), { + target: { value: '30' }, + }); + + fireEvent.click(screen.getByTestId('deleteUrl')); + fireEvent.click(screen.getByTestId('deleteAttachment')); + + expect(mockSetFormState).toHaveBeenCalledWith({ + ...mockFormState, + title: 'New title', + }); + expect(mockSetFormState).toHaveBeenCalledWith({ + ...mockFormState, + description: 'New description', + }); + + expect(mockSetFormState).toHaveBeenCalledWith({ + ...mockFormState, + duration: '30', + }); + + await waitFor(() => { + expect(mockSetFormState).toHaveBeenCalledWith({ + ...mockFormState, + urls: [], + }); + }); + + await waitFor(() => { + expect(mockSetFormState).toHaveBeenCalledWith({ + ...mockFormState, + attachments: [], + }); + }); + }); + + test('handleAddUrl correctly adds valid URL', async () => { + render( + + + + + + + + + , + ); + + const urlInput = screen.getByTestId('urlInput'); + const linkBtn = screen.getByTestId('linkBtn'); + + fireEvent.change(urlInput, { target: { value: 'https://example.com' } }); + fireEvent.click(linkBtn); + + await waitFor(() => { + expect(mockSetFormState).toHaveBeenCalledWith({ + ...mockFormState, + urls: [...mockFormState.urls, 'https://example.com'], + }); + }); + }); + + test('shows error toast for invalid URL', async () => { + render( + + + + + + + + + + + , + ); + + const urlInput = screen.getByTestId('urlInput'); + const linkBtn = screen.getByTestId('linkBtn'); + + fireEvent.change(urlInput, { target: { value: 'invalid-url' } }); + fireEvent.click(linkBtn); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalledWith('invalidUrl'); + }); + }); + + test('shows error toast for file size exceeding limit', async () => { + render( + + + + + + + + + + + , + ); + + const fileInput = screen.getByTestId('attachment'); + const largeFile = new File( + ['a'.repeat(11 * 1024 * 1024)], + 'large-file.jpg', + ); // 11 MB file + + Object.defineProperty(fileInput, 'files', { + value: [largeFile], + }); + + fireEvent.change(fileInput); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalledWith('fileSizeExceedsLimit'); + }); + }); + + test('adds files correctly when within size limit', async () => { + mockedConvertToBase64.mockResolvedValue('base64-file'); + + render( + + + + + + + + + + + , + ); + + const fileInput = screen.getByTestId('attachment'); + const smallFile = new File(['small-file-content'], 'small-file.jpg'); // Small file + + Object.defineProperty(fileInput, 'files', { + value: [smallFile], + }); + + fireEvent.change(fileInput); + + await waitFor(() => { + expect(mockSetFormState).toHaveBeenCalledWith({ + ...mockFormState, + attachments: [...mockFormState.attachments, 'base64-file'], + }); + }); + }); + test('renders autocomplete and selects categories correctly', async () => { + render( + + + + + + + + + + + , + ); + + const autocomplete = screen.getByTestId('categorySelect'); + expect(autocomplete).toBeInTheDocument(); + + const input = within(autocomplete).getByRole('combobox'); + fireEvent.mouseDown(input); + + const options = screen.getAllByRole('option'); + expect(options).toHaveLength(mockAgendaItemCategories.length); + + fireEvent.click(options[0]); + fireEvent.click(options[1]); + }); +}); diff --git a/src/components/AgendaItems/AgendaItemsUpdateModal.tsx b/src/components/AgendaItems/AgendaItemsUpdateModal.tsx new file mode 100644 index 0000000000..d2be91e15a --- /dev/null +++ b/src/components/AgendaItems/AgendaItemsUpdateModal.tsx @@ -0,0 +1,296 @@ +import React, { useState, useEffect } from 'react'; +import { Modal, Form, Button, Row, Col } from 'react-bootstrap'; +import type { ChangeEvent } from 'react'; +import { Autocomplete, TextField } from '@mui/material'; +import { FaLink, FaTrash } from 'react-icons/fa'; +import { toast } from 'react-toastify'; +import convertToBase64 from 'utils/convertToBase64'; + +import styles from './AgendaItemsContainer.module.css'; +import type { InterfaceAgendaItemCategoryInfo } from 'utils/interfaces'; + +interface InterfaceFormStateType { + agendaItemCategoryIds: string[]; + agendaItemCategoryNames: string[]; + title: string; + description: string; + duration: string; + attachments: string[]; + urls: string[]; + createdBy: { + firstName: string; + lastName: string; + }; +} + +interface InterfaceAgendaItemsUpdateModalProps { + agendaItemUpdateModalIsOpen: boolean; + hideUpdateModal: () => void; + formState: InterfaceFormStateType; + setFormState: (state: React.SetStateAction) => void; + updateAgendaItemHandler: (e: ChangeEvent) => Promise; + t: (key: string) => string; + agendaItemCategories: InterfaceAgendaItemCategoryInfo[] | undefined; +} + +const AgendaItemsUpdateModal: React.FC< + InterfaceAgendaItemsUpdateModalProps +> = ({ + agendaItemUpdateModalIsOpen, + hideUpdateModal, + formState, + setFormState, + updateAgendaItemHandler, + t, + agendaItemCategories, +}) => { + const [newUrl, setNewUrl] = useState(''); + + useEffect(() => { + setFormState((prevState) => ({ + ...prevState, + urls: prevState.urls.filter((url) => url.trim() !== ''), + attachments: prevState.attachments.filter((att) => att !== ''), + })); + }, []); + + // Function to validate URL + const isValidUrl = (url: string): boolean => { + // Regular expression for basic URL validation + const urlRegex = /^(ftp|http|https):\/\/[^ "]+$/; + return urlRegex.test(url); + }; + + const handleAddUrl = (): void => { + if (newUrl.trim() !== '' && isValidUrl(newUrl.trim())) { + setFormState({ + ...formState, + urls: [...formState.urls.filter((url) => url.trim() !== ''), newUrl], + }); + setNewUrl(''); + } else { + toast.error(t('invalidUrl')); + } + }; + + const handleRemoveUrl = (url: string): void => { + setFormState({ + ...formState, + urls: formState.urls.filter((item) => item !== url), + }); + }; + + const handleFileChange = async ( + e: React.ChangeEvent, + ): Promise => { + const target = e.target as HTMLInputElement; + if (target.files) { + const files = Array.from(target.files); + let totalSize = 0; + files.forEach((file) => { + totalSize += file.size; + }); + if (totalSize > 10 * 1024 * 1024) { + toast.error(t('fileSizeExceedsLimit')); + return; + } + const base64Files = await Promise.all( + files.map(async (file) => await convertToBase64(file)), + ); + setFormState({ + ...formState, + attachments: [...formState.attachments, ...base64Files], + }); + } + }; + + const handleRemoveAttachment = (attachment: string): void => { + setFormState({ + ...formState, + attachments: formState.attachments.filter((item) => item !== attachment), + }); + }; + + return ( + + +

    {t('updateAgendaItem')}

    + +
    + +
    + + + formState.agendaItemCategoryIds.includes(category._id), + ) || [] + } + // isOptionEqualToValue={(option, value) => option._id === value._id} + filterSelectedOptions={true} + getOptionLabel={( + category: InterfaceAgendaItemCategoryInfo, + ): string => category.name} + onChange={(_, newCategories): void => { + setFormState({ + ...formState, + agendaItemCategoryIds: newCategories.map( + (category) => category._id, + ), + }); + }} + renderInput={(params) => ( + + )} + /> + + + +
    + + {t('title')} + + setFormState({ ...formState, title: e.target.value }) + } + /> + + + + + {t('duration')} + + setFormState({ ...formState, duration: e.target.value }) + } + /> + + + + + + {t('description')} + + setFormState({ ...formState, description: e.target.value }) + } + /> + + + + {t('url')} +
    + setNewUrl(e.target.value)} + /> + +
    + + {formState.urls.map((url, index) => ( +
  • + + + {url.length > 50 ? url.substring(0, 50) + '...' : url} + + +
  • + ))} +
    + + {t('attachments')} + + {t('attachmentLimit')} + + {formState.attachments && ( +
    + {formState.attachments.map((attachment, index) => ( +
    + {attachment.includes('video') ? ( + + ) : ( + Attachment preview + )} + +
    + ))} +
    + )} + + + + + ); +}; + +export default AgendaItemsUpdateModal; diff --git a/src/components/Avatar/Avatar.module.css b/src/components/Avatar/Avatar.module.css index 14aa36e9ad..2a3190892f 100644 --- a/src/components/Avatar/Avatar.module.css +++ b/src/components/Avatar/Avatar.module.css @@ -1,6 +1,9 @@ .imageContainer { width: 56px; height: 56px; + display: flex; + align-items: center; + justify-content: center; border-radius: 100%; } .imageContainer img { diff --git a/src/components/ChangeLanguageDropdown/ChangeLanguageDropDown.tsx b/src/components/ChangeLanguageDropdown/ChangeLanguageDropDown.tsx index e3ee7a987f..e4bda6fd7f 100644 --- a/src/components/ChangeLanguageDropdown/ChangeLanguageDropDown.tsx +++ b/src/components/ChangeLanguageDropdown/ChangeLanguageDropDown.tsx @@ -3,6 +3,10 @@ import { Dropdown } from 'react-bootstrap'; import i18next from 'i18next'; import { languages } from 'utils/languages'; import cookies from 'js-cookie'; +import { UPDATE_USER_MUTATION } from 'GraphQl/Mutations/mutations'; +import { useMutation } from '@apollo/client'; +import useLocalStorage from 'utils/useLocalstorage'; +const { getItem } = useLocalStorage(); interface InterfaceChangeLanguageDropDownProps { parentContainerStyle?: string; @@ -10,14 +14,28 @@ interface InterfaceChangeLanguageDropDownProps { btnTextStyle?: string; } -export const changeLanguage = async (languageCode: string): Promise => { - await i18next.changeLanguage(languageCode); -}; - const ChangeLanguageDropDown = ( props: InterfaceChangeLanguageDropDownProps, ): JSX.Element => { const currentLanguageCode = cookies.get('i18next') || 'en'; + const userId = getItem('userId'); + const [updateUser] = useMutation(UPDATE_USER_MUTATION); + + const changeLanguage = async (languageCode: string): Promise => { + if (userId) { + try { + await updateUser({ + variables: { + appLanguageCode: languageCode, + }, + }); + await i18next.changeLanguage(languageCode); + cookies.set('i18next', languageCode); + } catch (error) { + console.log('Error in changing language', error); + } + } + }; return ( { await act(() => { @@ -16,14 +23,44 @@ async function wait(ms = 100): Promise { }); } +const MOCKS = [ + { + request: { + query: UPDATE_USER_MUTATION, + variables: { + appLanguageCode: 'fr', + }, + }, + result: { + data: { + updateUserProfile: { + _id: '1', + }, + }, + }, + }, + { + request: { + query: UPDATE_USER_MUTATION, + variables: { + appLanguageCode: 'hi', + }, + }, + error: new Error('An error occurred'), + }, +]; + +const link = new StaticMockLink(MOCKS, true); describe('Testing Change Language Dropdown', () => { test('Component Should be rendered properly', async () => { const { getByTestId } = render( - - - - - , + + + + + + + , ); expect(getByTestId('language-dropdown-container')).toBeInTheDocument(); @@ -51,11 +88,13 @@ describe('Testing Change Language Dropdown', () => { btnTextStyle: 'btnTextStyle', }; const { getByTestId } = render( - - - - - , + + + + + + + , ); getByTestId('language-dropdown-container').className.includes( props.parentContainerStyle, @@ -71,9 +110,11 @@ describe('Testing Change Language Dropdown', () => { }); render( - - - , + + + + + , ); await wait(); @@ -83,24 +124,35 @@ describe('Testing Change Language Dropdown', () => { test('Testing change language functionality', async () => { Object.defineProperty(window.document, 'cookie', { writable: true, - value: 'i18next=en', + value: 'i18next=sp', }); + setItem('userId', '1'); const { getByTestId } = render( - - - , + + + + + , ); userEvent.click(getByTestId('language-dropdown-btn')); await wait(); - languages.map((language) => { - const changeLanguageBtn = getByTestId( - `change-language-btn-${language.code}`, - ); - expect(changeLanguageBtn).toBeInTheDocument(); - userEvent.click(changeLanguageBtn); - expect(cookies.get('i18next')).toBe(language.code); - }); + const changeLanguageBtn = getByTestId(`change-language-btn-fr`); + await wait(); + expect(changeLanguageBtn).toBeInTheDocument(); + await wait(); + userEvent.click(changeLanguageBtn); + await wait(); + expect(cookies.get('i18next')).toBe('fr'); + await wait(); + userEvent.click(getByTestId('language-dropdown-btn')); + await wait(); + const changeLanguageBtnHi = getByTestId(`change-language-btn-hi`); + await wait(); + expect(changeLanguageBtnHi).toBeInTheDocument(); + await wait(); + userEvent.click(changeLanguageBtnHi); + await wait(); }); }); diff --git a/src/components/CheckIn/TableRow.test.tsx b/src/components/CheckIn/TableRow.test.tsx index 8d41f1036b..9a206047d0 100644 --- a/src/components/CheckIn/TableRow.test.tsx +++ b/src/components/CheckIn/TableRow.test.tsx @@ -45,7 +45,7 @@ describe('Testing Table Row for CheckIn Table', () => { fireEvent.click(queryByText('Check In') as Element); await waitFor(() => - expect(queryByText('Checked in successfully!')).toBeInTheDocument(), + expect(queryByText('Checked in successfully')).toBeInTheDocument(), ); }); @@ -130,9 +130,7 @@ describe('Testing Table Row for CheckIn Table', () => { fireEvent.click(queryByText('Check In') as Element); await waitFor(() => - expect( - queryByText('There was an error in checking in!'), - ).toBeInTheDocument(), + expect(queryByText('Error checking in')).toBeInTheDocument(), ); await waitFor(() => expect(queryByText('Oops')).toBeInTheDocument()); }); diff --git a/src/components/CheckIn/TableRow.tsx b/src/components/CheckIn/TableRow.tsx index bceaf3a49d..8daa5ed222 100644 --- a/src/components/CheckIn/TableRow.tsx +++ b/src/components/CheckIn/TableRow.tsx @@ -6,6 +6,7 @@ import { MARK_CHECKIN } from 'GraphQl/Mutations/mutations'; import { toast } from 'react-toastify'; import { generate } from '@pdfme/generator'; import { tagTemplate } from './tagTemplate'; +import { useTranslation } from 'react-i18next'; export const TableRow = ({ data, @@ -15,6 +16,7 @@ export const TableRow = ({ refetch: () => void; }): JSX.Element => { const [checkInMutation] = useMutation(MARK_CHECKIN); + const { t } = useTranslation('translation', { keyPrefix: 'checkIn' }); const markCheckIn = (): void => { // as we do not want to clutter the UI currently with the same (only provide the most basic of operations) @@ -25,11 +27,11 @@ export const TableRow = ({ }, }) .then(() => { - toast.success('Checked in successfully!'); + toast.success(t('checkedInSuccessfully')); refetch(); }) .catch((err) => { - toast.error('There was an error in checking in!'); + toast.error(t('errorCheckingIn')); toast.error(err.message); }); }; diff --git a/src/components/EditCustomFieldDropDown/EditCustomFieldDropDown.test.tsx b/src/components/EditCustomFieldDropDown/EditCustomFieldDropDown.test.tsx index d4b92007e2..2e3c52ad38 100644 --- a/src/components/EditCustomFieldDropDown/EditCustomFieldDropDown.test.tsx +++ b/src/components/EditCustomFieldDropDown/EditCustomFieldDropDown.test.tsx @@ -6,6 +6,8 @@ import EditOrgCustomFieldDropDown from './EditCustomFieldDropDown'; import type { InterfaceCustomFieldData } from 'components/OrgProfileFieldSettings/OrgProfileFieldSettings'; import userEvent from '@testing-library/user-event'; import availableFieldTypes from 'utils/fieldTypes'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; async function wait(ms = 100): Promise { await act(() => { @@ -39,7 +41,9 @@ describe('Testing Custom Field Dropdown', () => { const { getByTestId, getByText } = render( - + + + , ); diff --git a/src/components/EditCustomFieldDropDown/EditCustomFieldDropDown.tsx b/src/components/EditCustomFieldDropDown/EditCustomFieldDropDown.tsx index 5ef7780627..7a81e78e27 100644 --- a/src/components/EditCustomFieldDropDown/EditCustomFieldDropDown.tsx +++ b/src/components/EditCustomFieldDropDown/EditCustomFieldDropDown.tsx @@ -3,6 +3,7 @@ import type { SetStateAction, Dispatch } from 'react'; import { Dropdown } from 'react-bootstrap'; import availableFieldTypes from 'utils/fieldTypes'; import type { InterfaceCustomFieldData } from 'components/OrgProfileFieldSettings/OrgProfileFieldSettings'; +import { useTranslation } from 'react-i18next'; interface InterfaceEditCustomFieldDropDownProps { customFieldData: InterfaceCustomFieldData; @@ -11,38 +12,45 @@ interface InterfaceEditCustomFieldDropDownProps { btnStyle?: string; btnTextStyle?: string; } -[]; -const EditOrgCustomFieldDropDown = ( - props: InterfaceEditCustomFieldDropDownProps, -): JSX.Element => { +const EditOrgCustomFieldDropDown = ({ + customFieldData, + setCustomFieldData, + parentContainerStyle, + btnStyle, +}: InterfaceEditCustomFieldDropDownProps): JSX.Element => { + const { t } = useTranslation('translation', { + keyPrefix: 'orgProfileField', + }); + const { t: tCommon } = useTranslation('common'); + return ( - {props.customFieldData.type || 'None'} + {customFieldData.type ? t(customFieldData.type) : tCommon('none')} {availableFieldTypes.map((customFieldType, index: number) => ( { - props.setCustomFieldData({ - ...props.customFieldData, + setCustomFieldData({ + ...customFieldData, type: customFieldType, }); }} - disabled={props.customFieldData.type == customFieldType} + disabled={customFieldData.type === customFieldType} > - {customFieldType} + {t(customFieldType)} ))} diff --git a/src/components/EventCalendar/EventCalendar.tsx b/src/components/EventCalendar/EventCalendar.tsx index c06f3c5fea..566e66d62a 100644 --- a/src/components/EventCalendar/EventCalendar.tsx +++ b/src/components/EventCalendar/EventCalendar.tsx @@ -318,7 +318,8 @@ const Calendar: React.FC = ({ ); if ( - datas.startTime?.slice(0, 2) == (index % 24).toString() && + parseInt(datas.startTime?.slice(0, 2) as string).toString() == + (index % 24).toString() && datas.startDate == dayjs(currDate).format('YYYY-MM-DD') ) { return datas; diff --git a/src/components/EventManagement/EventActionItems/EventActionItems.module.css b/src/components/EventManagement/EventActionItems/EventActionItems.module.css index 1253dd7a2f..120177d155 100644 --- a/src/components/EventManagement/EventActionItems/EventActionItems.module.css +++ b/src/components/EventManagement/EventActionItems/EventActionItems.module.css @@ -3,6 +3,11 @@ width: 98%; } } +.actionItemModal { + max-width: 80vw; + margin-top: 2vh; + margin-left: 13vw; +} .modalContent { width: 670px; max-width: 680px; @@ -71,6 +76,10 @@ height: 50px !important; border-radius: 100% !important; } +.datagrid { + overflow: auto; + border-radius: 10px; +} .tableHead { background-color: #31bb6b !important; color: white; @@ -94,9 +103,8 @@ background-color: var(--bs-white); } .tableHeader { - background-color: var(--bs-primary); - color: var(--bs-white); - font-size: 16px; + color: var(--bs-black); + font-size: var(--bs-body-font-size); } .addButton { width: 7em; @@ -128,18 +136,33 @@ color: var(--bs-gray-600); font-weight: 600; font-size: 20px; - margin-top: 1rem; + margin-bottom: 20px; + padding-bottom: 5px; + border-bottom: 3px solid var(--bs-primary); width: 65%; } .editDelBtns { - display: flex; - justify-content: space-around; + margin-top: 15px; + border: 1px solid var(--bs-gray-300); + box-shadow: 0 2px 2px var(--bs-gray-300); + padding: 10px 10px; + border-radius: 5px; + background-color: var(--bs-primary); + width: 100%; + font-size: 16px; + color: var(--bs-white); + outline: none; + font-weight: 600; + cursor: pointer; + transition: + transform 0.2s, + box-shadow 0.2s; + width: 100%; } .greenregbtn { - margin-bottom: 20px; - margin-left: 85%; + margin-left: 93%; } .datatable { @@ -148,6 +171,17 @@ .datediv { display: flex; + flex-direction: row; +} +.datebox { + width: 90%; + border-radius: 7px; + outline: none; + box-shadow: none; +} +.actionItemsOptionsButton { + width: 24px; + height: 24px; } @-webkit-keyframes load8 { diff --git a/src/components/EventManagement/EventActionItems/EventActionItems.test.tsx b/src/components/EventManagement/EventActionItems/EventActionItems.test.tsx index ef69796da4..9da0b5247a 100644 --- a/src/components/EventManagement/EventActionItems/EventActionItems.test.tsx +++ b/src/components/EventManagement/EventActionItems/EventActionItems.test.tsx @@ -2,7 +2,15 @@ import React from 'react'; import { MockedProvider } from '@apollo/react-testing'; import { LocalizationProvider } from '@mui/x-date-pickers'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; -import { act, fireEvent, render, screen } from '@testing-library/react'; +import { + act, + fireEvent, + render, + screen, + waitFor, + waitForElementToBeRemoved, +} from '@testing-library/react'; +import 'jest-localstorage-mock'; import { Provider } from 'react-redux'; import { BrowserRouter } from 'react-router-dom'; import userEvent from '@testing-library/user-event'; @@ -59,16 +67,58 @@ const MOCKS = [ }, }, }, + { + request: { + query: UPDATE_ACTION_ITEM_MUTATION, + variables: { + actionItemId: '_6613ef741677gygwuyu', + assigneeId: '658930fd2caa9d8d690sfhgush', + preCompletionNotes: 'pre completion notes edited', + postCompletionNotes: 'Post Completion Notes', + dueDate: '2024-02-14', + completionDate: '2024-02-21', + isCompleted: false, + }, + }, + result: { + data: { + updateActionItem: { + _id: '_6613ef741677gygwuyu', + }, + }, + }, + }, { request: { query: UPDATE_ACTION_ITEM_MUTATION, variables: { actionItemId: '_6613ef741677gygwuyu', assigneeId: '658930fd2caa9d8d6908745c', - preCompletionNotes: 'task to be done with high priority', - postCompletionNotes: 'Done', - dueDate: '2024-04-05', - completionDate: '2024-04-05', + preCompletionNotes: 'Pre Completion Notes', + postCompletionNotes: 'this action item has been completed successfully', + dueDate: '2024-02-21', + completionDate: '2024-02-21', + isCompleted: true, + }, + }, + result: { + data: { + updateActionItem: { + _id: '_6613ef741677gygwuyu', + }, + }, + }, + }, + { + request: { + query: UPDATE_ACTION_ITEM_MUTATION, + variables: { + actionItemId: 'actionItem2', + assigneeId: 'user1', + preCompletionNotes: 'this action item has been made active again', + postCompletionNotes: 'Post Completion Notes', + dueDate: '2024-02-21', + completionDate: '2024-02-21', isCompleted: false, }, }, @@ -76,7 +126,6 @@ const MOCKS = [ data: { updateActionItem: { _id: '_6613ef741677gygwuyu', - __typename: 'ActionItem', }, }, }, @@ -131,7 +180,7 @@ const MOCKS = [ _id: '111', members: [ { - createdAt: '2023-04-13T04:53:17.742Z', + createdAt: '2023-04-13', email: 'testuser4@example.com', firstName: 'Teresa', image: null, @@ -141,7 +190,7 @@ const MOCKS = [ _id: '658930fd2caa9d8d6908745c', }, { - createdAt: '2024-04-13T04:53:17.742Z', + createdAt: '2024-04-13', email: 'testuser2@example.com', firstName: 'Anna', image: null, @@ -175,7 +224,7 @@ const MOCKS = [ }, assignee: { __typename: 'User', - _id: '6589387e2caa9d8d69087485', + _id: '658930fd2caa9d8d6908745c', firstName: 'Burton', lastName: 'Sanders', }, @@ -185,23 +234,89 @@ const MOCKS = [ firstName: 'Wilt', lastName: 'Shepherd', }, - assignmentDate: '2024-04-08', - completionDate: '2024-04-08', + assignmentDate: new Date('2024-02-14'), + dueDate: new Date('2024-02-21'), + completionDate: new Date('2024-02-21'), creator: { __typename: 'User', _id: '64378abd85008f171cf2990d', firstName: 'Wilt', lastName: 'Shepherd', }, - dueDate: '2024-04-08', event: { __typename: 'Event', _id: '123', title: 'Adult Painting Lessons', }, isCompleted: false, - postCompletionNotes: 'Post Completion Note', - preCompletionNotes: 'Pre Completion Note', + postCompletionNotes: 'Post Completion Notes', + preCompletionNotes: 'Pre Completion Notes', + }, + { + _id: 'actionItem2', + assignee: { + _id: '658930fd2caa9d8d6908745c', + firstName: 'Harve', + lastName: 'Lance', + }, + actionItemCategory: { + _id: 'actionItemCategory1', + name: 'ActionItemCategory 1', + }, + preCompletionNotes: + 'Long Pre Completion Notes Text that exceeds 25 characters', + postCompletionNotes: + 'Long Post Completion Notes Text that exceeds 25 characters', + assignmentDate: new Date('2024-02-14'), + dueDate: new Date('2024-02-21'), + completionDate: new Date('2024-02-21'), + isCompleted: true, + assigner: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + event: { + _id: 'event1', + title: 'event 1', + }, + creator: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + { + _id: 'actionItem3', + assignee: { + _id: '658930fd2caa9d8d6908745c', + firstName: 'Harve', + lastName: 'Lance', + }, + actionItemCategory: { + _id: 'actionItemCategory1', + name: 'ActionItemCategory 1', + }, + preCompletionNotes: 'Pre Completion Text', + postCompletionNotes: 'Post Completion Text', + assignmentDate: new Date('2024-02-14'), + dueDate: new Date('2024-02-21'), + completionDate: new Date('2024-02-21'), + isCompleted: true, + assigner: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + event: { + _id: 'event1', + title: 'event 1', + }, + creator: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, }, ], }, @@ -252,7 +367,7 @@ const UPDATE_ACTION_ITEM_ERROR_MOCK = [ }, assignee: { __typename: 'User', - _id: '6589387e2caa9d8d69087485', + _id: '658930fd2caa9d8d6908745c', firstName: 'Burton', lastName: 'Sanders', }, @@ -262,15 +377,15 @@ const UPDATE_ACTION_ITEM_ERROR_MOCK = [ firstName: 'Wilt', lastName: 'Shepherd', }, - assignmentDate: '2024-04-08', - completionDate: '2024-04-08', + assignmentDate: new Date('2024-02-14'), + dueDate: new Date('2024-02-21'), + completionDate: new Date('2024-02-21'), creator: { __typename: 'User', _id: '64378abd85008f171cf2990d', firstName: 'Wilt', lastName: 'Shepherd', }, - dueDate: '2024-04-08', event: { __typename: 'Event', _id: '123', @@ -287,29 +402,70 @@ const UPDATE_ACTION_ITEM_ERROR_MOCK = [ }, { request: { - query: UPDATE_ACTION_ITEM_MUTATION, + query: MEMBERS_LIST, variables: { - actionItemId: '_6613ef741677gygwuyu', - assigneeId: '658930fd2caa9d8d6908745c', - preCompletionNotes: 'task to be done with high priority', - postCompletionNotes: 'Done', - dueDate: '2024-04-05', - completionDate: '2024-04-05', - isCompleted: false, + id: '111', }, }, result: { data: { - updateActionItem: { - _id: undefined, - __typename: 'ActionItem', - }, + organizations: [ + { + _id: '111', + members: [ + { + createdAt: '2023-04-13', + email: 'testuser4@example.com', + firstName: 'Teresa', + image: null, + lastName: 'Bradley', + organizationsBlockedBy: [], + __typename: 'User', + _id: '658930fd2caa9d8d6908745c', + }, + { + createdAt: '2024-04-13', + email: 'testuser2@example.com', + firstName: 'Anna', + image: null, + lastName: 'Bradley', + organizationsBlockedBy: [], + __typename: 'User', + _id: '658930fd2caa9d8d690sfhgush', + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: DELETE_ACTION_ITEM_MUTATION, + variables: { + actionItemId: '_6613ef741677gygwuyu', + }, + }, + error: new Error('Mock Graphql Error'), + }, + { + request: { + query: UPDATE_ACTION_ITEM_MUTATION, + variables: { + actionItemId: '_6613ef741677gygwuyu', + assigneeId: '658930fd2caa9d8d690sfhgush', + preCompletionNotes: 'pre completion notes edited', + postCompletionNotes: '', + dueDate: '2024-02-14', + completionDate: '2024-02-21', + isCompleted: false, }, }, + error: new Error('Mock Graphql Error'), }, ]; -const NO_ACTION_ITEMs_ERROR_MOCK = [ +const NO_ACTION_ITEMS_ERROR_MOCK = [ { request: { query: ACTION_ITEM_LIST_BY_EVENTS, @@ -329,7 +485,7 @@ const NO_ACTION_ITEMs_ERROR_MOCK = [ const link = new StaticMockLink(MOCKS, true); const link2 = new StaticMockLink(CREATE_ACTION_ITEM_ERROR_MOCK, true); const link3 = new StaticMockLink(UPDATE_ACTION_ITEM_ERROR_MOCK, true); -const link4 = new StaticMockLink(NO_ACTION_ITEMs_ERROR_MOCK, true); +const link4 = new StaticMockLink(NO_ACTION_ITEMS_ERROR_MOCK, true); const translations = JSON.parse( JSON.stringify( @@ -338,6 +494,12 @@ const translations = JSON.parse( ); describe('Event Action Items Page', () => { + const formData = { + assignee: 'Anna Bradley', + preCompletionNotes: 'pre completion notes edited', + dueDate: '02/14/2024', + completionDate: '02/21/2024', + }; test('Testing add new action item modal', async () => { window.location.assign('/event/111/123'); render( @@ -357,7 +519,9 @@ describe('Event Action Items Page', () => { userEvent.click(screen.getByTestId('createEventActionItemBtn')); await wait(); - expect(screen.getByText('Action Item Details')).toBeInTheDocument(); + expect( + screen.getByText(translations.actionItemDetails), + ).toBeInTheDocument(); const categoryDropdown = screen.getByTestId('formSelectActionItemCategory'); userEvent.selectOptions(categoryDropdown, 'Default'); @@ -369,17 +533,22 @@ describe('Event Action Items Page', () => { expect(assigneeDropdown).toHaveValue('658930fd2caa9d8d6908745c'); - fireEvent.change(screen.getByPlaceholderText('Notes'), { - target: { value: 'task to be done with high priority' }, - }); - expect(screen.getByPlaceholderText('Notes')).toHaveValue( - 'task to be done with high priority', + fireEvent.change( + screen.getByPlaceholderText(translations.preCompletionNotes), + { + target: { value: 'task to be done with high priority' }, + }, ); + expect( + screen.getByPlaceholderText(translations.preCompletionNotes), + ).toHaveValue('task to be done with high priority'); - fireEvent.change(screen.getByLabelText('Due Date'), { + fireEvent.change(screen.getByLabelText(translations.dueDate), { target: { value: '04/05/2024' }, }); - expect(screen.getByLabelText('Due Date')).toHaveValue('04/05/2024'); + expect(screen.getByLabelText(translations.dueDate)).toHaveValue( + '04/05/2024', + ); userEvent.click(screen.getByTestId('createActionItemFormSubmitBtn')); @@ -406,22 +575,51 @@ describe('Event Action Items Page', () => { await wait(); expect(screen.getByText('#')).toBeInTheDocument(); - expect(screen.getByText('Assignee')).toBeInTheDocument(); - expect(screen.getByText('Action Item Category')).toBeInTheDocument(); - expect(screen.getByText('Notes')).toBeInTheDocument(); - expect(screen.getByText('Completion Notes')).toBeInTheDocument(); + expect(screen.getByText(translations.assignee)).toBeInTheDocument(); + expect( + screen.getByText(translations.actionItemCategory), + ).toBeInTheDocument(); + expect( + screen.getByText(translations.preCompletionNotes), + ).toBeInTheDocument(); + expect( + screen.getByText(translations.postCompletionNotes), + ).toBeInTheDocument(); await wait(); + const asigneeAnchorElement = screen.getByText('Burton Sanders'); + expect(asigneeAnchorElement.tagName).toBe('A'); + expect(asigneeAnchorElement).toHaveAttribute('href', '/member/123'); + expect(screen.getByText('Burton Sanders')).toBeInTheDocument(); - expect(screen.getByText('Pre Completion Note')).toBeInTheDocument(); - const updateButtons = screen.getAllByText(/Manage Actions/i); + const updateButtons = screen.getAllByTestId('editActionItemModalBtn'); + const previewButtons = screen.getAllByTestId('previewActionItemModalBtn'); + const updateStatusButtons = screen.getAllByTestId( + 'actionItemStatusChangeCheckbox', + ); expect(updateButtons[0]).toBeInTheDocument(); + expect(previewButtons[0]).toBeInTheDocument(); + expect(updateStatusButtons[0]).toBeInTheDocument(); + + // Truncate notes and long completion notes txt + expect( + screen.getAllByTestId('actionItemPreCompletionNotesOverlay')[1], + ).toHaveTextContent('Long Pre Completion Notes...'); + expect( + screen.getAllByTestId('actionItemPostCompletionNotesOverlay')[0], + ).toHaveTextContent('Long Post Completion Note...'); + expect( + screen.getAllByTestId('actionItemPostCompletionNotesOverlay')[1], + ).toHaveTextContent('Post Completion Text'); + expect( + screen.getAllByTestId('actionItemPreCompletionNotesOverlay')[2], + ).toHaveTextContent('Pre Completion Text'); }); - test('Testing update action item modal', async () => { + test('opens and closes the update and delete modals through the preview modal', async () => { window.location.assign('/event/111/123'); render( - + @@ -433,45 +631,235 @@ describe('Event Action Items Page', () => { , ); + await wait(); - const updateButtons = screen.getAllByText(/Manage Actions/i); - userEvent.click(updateButtons[0]); - expect(screen.getByText('Action Item Details')).toBeInTheDocument(); + expect( + screen.getAllByTestId('previewActionItemModalBtn')[0], + ).toBeInTheDocument(); + userEvent.click(screen.getAllByTestId('previewActionItemModalBtn')[0]); - const assigneeDropdown = screen.getByTestId('formUpdateAssignee'); - userEvent.selectOptions(assigneeDropdown, 'Teresa Bradley'); + await waitFor(() => { + return expect( + screen.findByTestId('previewActionItemModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); - expect(assigneeDropdown).toHaveValue('658930fd2caa9d8d6908745c'); - fireEvent.change(screen.getByPlaceholderText('Notes'), { - target: { value: 'task to be done with high priority' }, + await waitFor(() => { + expect( + screen.getByTestId('deleteActionItemPreviewModalBtn'), + ).toBeInTheDocument(); }); - expect(screen.getByPlaceholderText('Notes')).toHaveValue( - 'task to be done with high priority', + userEvent.click(screen.getByTestId('deleteActionItemPreviewModalBtn')); + + await waitFor(() => { + return expect( + screen.findByTestId('actionItemDeleteModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('actionItemDeleteModalCloseBtn')); + + await waitForElementToBeRemoved(() => + screen.queryByTestId('actionItemDeleteModalCloseBtn'), ); - fireEvent.change(screen.getByPlaceholderText('Post Completion Notes'), { - target: { value: 'Done' }, + expect( + screen.getByTestId('editActionItemPreviewModalBtn'), + ).toBeInTheDocument(); + userEvent.click(screen.getByTestId('editActionItemPreviewModalBtn')); + + await waitFor(() => { + return expect( + screen.findByTestId('updateActionItemModalCloseBtn'), + ).resolves.toBeInTheDocument(); }); - expect(screen.getByPlaceholderText('Post Completion Notes')).toHaveValue( - 'Done', + userEvent.click(screen.getByTestId('updateActionItemModalCloseBtn')); + + await waitForElementToBeRemoved(() => + screen.queryByTestId('updateActionItemModalCloseBtn'), ); + }); + test('opens and closes the action item status change modal correctly', async () => { + window.location.assign('/event/111/123'); + render( + + + + + + {} + + + + + , + ); + await wait(); - fireEvent.change(screen.getByLabelText('Due Date'), { - target: { value: '04/05/2024' }, + await waitFor(() => { + expect( + screen.getAllByTestId('actionItemStatusChangeCheckbox')[0], + ).toBeInTheDocument(); }); - expect(screen.getByLabelText('Due Date')).toHaveValue('04/05/2024'); + userEvent.click(screen.getAllByTestId('actionItemStatusChangeCheckbox')[0]); - fireEvent.change(screen.getByLabelText('Completion Date'), { - target: { value: '04/05/2024' }, + await waitFor(() => { + return expect( + screen.findByTestId('actionItemStatusChangeModalCloseBtn'), + ).resolves.toBeInTheDocument(); }); - expect(screen.getByLabelText('Completion Date')).toHaveValue('04/05/2024'); + userEvent.click(screen.getByTestId('actionItemStatusChangeModalCloseBtn')); - userEvent.click(screen.getByTestId('updateActionItemFormSubmitBtn')); + await waitForElementToBeRemoved(() => + screen.queryByTestId('actionItemStatusChangeModalCloseBtn'), + ); + }); + + test('updates an action item status through the action item status change modal', async () => { + window.location.assign('/event/111/123'); + render( + + + + + + {} + + + + + , + ); + await wait(); + + await waitFor(() => { + expect( + screen.getAllByTestId('actionItemStatusChangeCheckbox')[0], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('actionItemStatusChangeCheckbox')[0]); + + await waitFor(() => { + expect( + screen.getByTestId('actionItemsStatusChangeNotes'), + ).toBeInTheDocument(); + }); + + const postCompletionNotes = screen.getByTestId( + 'actionItemsStatusChangeNotes', + ); + fireEvent.change(postCompletionNotes, { target: { value: '' } }); + userEvent.type( + postCompletionNotes, + 'this action item has been completed successfully', + ); + + await waitFor(() => { + expect( + screen.getByTestId('actionItemStatusChangeSubmitBtn'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('actionItemStatusChangeSubmitBtn')); + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.successfulUpdation); + }); + + await waitFor(() => { + expect( + screen.getAllByTestId('actionItemStatusChangeCheckbox')[1], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('actionItemStatusChangeCheckbox')[1]); + + await waitFor(() => { + expect( + screen.getByTestId('actionItemsStatusChangeNotes'), + ).toBeInTheDocument(); + }); + + const preCompletionNotes = screen.getByTestId( + 'actionItemsStatusChangeNotes', + ); + fireEvent.change(preCompletionNotes, { target: { value: '' } }); + userEvent.type( + preCompletionNotes, + 'this action item has been made active again', + ); + + await waitFor(() => { + expect( + screen.getByTestId('actionItemStatusChangeSubmitBtn'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('actionItemStatusChangeSubmitBtn')); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.successfulUpdation); + }); + }); + + test('Testing update action item modal', async () => { + window.location.assign('/event/111/123'); + render( + + + + + + {} + + + + + , + ); await wait(); - expect(toast.success).toBeCalledWith(translations.successfulUpdation); + await waitFor(() => { + expect( + screen.getAllByTestId('editActionItemModalBtn')[0], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('editActionItemModalBtn')[0]); + + await waitFor(() => { + expect(screen.getByTestId('formUpdateAssignee')).toBeInTheDocument(); + }); + + userEvent.selectOptions( + screen.getByTestId('formUpdateAssignee'), + formData.assignee, + ); + + const preCompletionNotes = screen.getByPlaceholderText( + translations.preCompletionNotes, + ); + fireEvent.change(preCompletionNotes, { target: { value: '' } }); + userEvent.type(preCompletionNotes, formData.preCompletionNotes); + + const dueDatePicker = screen.getByLabelText(translations.dueDate); + fireEvent.change(dueDatePicker, { + target: { value: formData.dueDate }, + }); + + const completionDatePicker = screen.getByLabelText( + translations.completionDate, + ); + fireEvent.change(completionDatePicker, { + target: { value: formData.completionDate }, + }); + + await waitFor(() => { + expect( + screen.getByTestId('updateActionItemFormSubmitBtn'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('updateActionItemFormSubmitBtn')); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.successfulUpdation); + }); }); test('Testing delete action item modal and delete the record', async () => { window.location.assign('/event/111/123'); @@ -489,16 +877,20 @@ describe('Event Action Items Page', () => { , ); await wait(); - const updateButtons = screen.getAllByText(/Manage Actions/i); - userEvent.click(updateButtons[0]); - - expect(screen.getByText('Action Item Details')).toBeInTheDocument(); + expect( + screen.getAllByTestId('previewActionItemModalBtn')[0], + ).toBeInTheDocument(); + userEvent.click(screen.getAllByTestId('previewActionItemModalBtn')[0]); - expect(screen.getByTestId('deleteActionItemBtn')).toBeInTheDocument(); - userEvent.click(screen.getByTestId('deleteActionItemBtn')); + await waitFor(() => { + expect( + screen.getByTestId('deleteActionItemPreviewModalBtn'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('deleteActionItemPreviewModalBtn')); await wait(); expect( - screen.getByText('Do you want to remove this action item?'), + screen.getByText(translations.deleteActionItemMsg), ).toBeInTheDocument(); userEvent.click(screen.getByText('Yes')); await wait(); @@ -522,20 +914,137 @@ describe('Event Action Items Page', () => { , ); await wait(); - const updateButtons = screen.getAllByText(/Manage Actions/i); - userEvent.click(updateButtons[0]); - - expect(screen.getByText('Action Item Details')).toBeInTheDocument(); + expect( + screen.getAllByTestId('previewActionItemModalBtn')[0], + ).toBeInTheDocument(); + userEvent.click(screen.getAllByTestId('previewActionItemModalBtn')[0]); - expect(screen.getByTestId('deleteActionItemBtn')).toBeInTheDocument(); - userEvent.click(screen.getByTestId('deleteActionItemBtn')); + await waitFor(() => { + expect( + screen.getByTestId('deleteActionItemPreviewModalBtn'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('deleteActionItemPreviewModalBtn')); await wait(); expect( - screen.getByText('Do you want to remove this action item?'), + screen.getByText(translations.deleteActionItemMsg), ).toBeInTheDocument(); userEvent.click(screen.getByText('No')); await wait(); - expect(screen.getByText('Teresa Bradley')).toBeInTheDocument(); + expect(screen.getByRole('dialog')).toBeInTheDocument(); + expect( + screen.getByText(translations.actionItemDetails), + ).toBeInTheDocument(); + }); + + test('toasts error on unsuccessful deletion', async () => { + window.location.assign('/event/111/123'); + render( + + + + + + {} + + + + + , + ); + await wait(); + + expect( + screen.getAllByTestId('previewActionItemModalBtn')[0], + ).toBeInTheDocument(); + userEvent.click(screen.getAllByTestId('previewActionItemModalBtn')[0]); + + await waitFor(() => { + return expect( + screen.findByTestId('previewActionItemModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + + await waitFor(() => { + expect( + screen.getByTestId('deleteActionItemPreviewModalBtn'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('deleteActionItemPreviewModalBtn')); + + await waitFor(() => { + return expect( + screen.findByTestId('actionItemDeleteModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('deleteActionItemBtn')); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); + + test('toasts error on unsuccessful updation', async () => { + window.location.assign('/event/111/123'); + render( + + + + + + {} + + + + + , + ); + await wait(); + + await waitFor(() => { + expect( + screen.getAllByTestId('editActionItemModalBtn')[0], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('editActionItemModalBtn')[0]); + + await waitFor(() => { + expect(screen.getByTestId('formUpdateAssignee')).toBeInTheDocument(); + }); + + userEvent.selectOptions( + screen.getByTestId('formUpdateAssignee'), + formData.assignee, + ); + + const preCompletionNotes = screen.getByPlaceholderText( + translations.preCompletionNotes, + ); + fireEvent.change(preCompletionNotes, { target: { value: '' } }); + userEvent.type(preCompletionNotes, formData.preCompletionNotes); + + const dueDatePicker = screen.getByLabelText(translations.dueDate); + fireEvent.change(dueDatePicker, { + target: { value: formData.dueDate }, + }); + + const completionDatePicker = screen.getByLabelText( + translations.completionDate, + ); + fireEvent.change(completionDatePicker, { + target: { value: formData.completionDate }, + }); + + await waitFor(() => { + expect( + screen.getByTestId('updateActionItemFormSubmitBtn'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('updateActionItemFormSubmitBtn')); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); }); test('Raises an error when incorrect information is filled while creation', async () => { @@ -557,19 +1066,26 @@ describe('Event Action Items Page', () => { userEvent.click(screen.getByTestId('createEventActionItemBtn')); await wait(); - expect(screen.getByText('Action Item Details')).toBeInTheDocument(); + expect( + screen.getByText(translations.actionItemDetails), + ).toBeInTheDocument(); - fireEvent.change(screen.getByPlaceholderText('Notes'), { - target: { value: 'task to be done with high priority' }, - }); - expect(screen.getByPlaceholderText('Notes')).toHaveValue( - 'task to be done with high priority', + fireEvent.change( + screen.getByPlaceholderText(translations.preCompletionNotes), + { + target: { value: 'task to be done with high priority' }, + }, ); + expect( + screen.getByPlaceholderText(translations.preCompletionNotes), + ).toHaveValue('task to be done with high priority'); - fireEvent.change(screen.getByLabelText('Due Date'), { + fireEvent.change(screen.getByLabelText(translations.dueDate), { target: { value: '04/05/2024' }, }); - expect(screen.getByLabelText('Due Date')).toHaveValue('04/05/2024'); + expect(screen.getByLabelText(translations.dueDate)).toHaveValue( + '04/05/2024', + ); userEvent.click(screen.getByTestId('createActionItemFormSubmitBtn')); await wait(); @@ -593,17 +1109,17 @@ describe('Event Action Items Page', () => { , ); await wait(); - const updateButtons = screen.getAllByText(/Manage Actions/i); + const updateButtons = screen.getAllByTestId('editActionItemModalBtn'); userEvent.click(updateButtons[0]); - expect(screen.getByText('Action Item Details')).toBeInTheDocument(); + expect( + screen.getByText(translations.actionItemDetails), + ).toBeInTheDocument(); userEvent.click(screen.getByTestId('updateActionItemFormSubmitBtn')); await wait(); - expect(toast.success).toBeCalledWith(translations.successfulUpdation); - expect(toast.error).toBeCalled(); }); @@ -625,4 +1141,39 @@ describe('Event Action Items Page', () => { await wait(); expect(screen.getByText('Nothing Found !!')).toBeInTheDocument(); }); + + test('Testing update action modal to have correct initial values', async () => { + window.location.assign('/event/111/123'); + render( + + + + + + {} + + + + + , + ); + await wait(); + const updateButtons = screen.getAllByTestId('editActionItemModalBtn'); + userEvent.click(updateButtons[0]); + + expect(screen.getByText('Action Item Details')).toBeInTheDocument(); + const assigneeDropdown = screen.getByTestId( + 'formUpdateAssignee', + ) as HTMLSelectElement; + expect(assigneeDropdown.value).toBe('658930fd2caa9d8d6908745c'); + expect(assigneeDropdown).toHaveTextContent('Teresa Bradley'); + + expect( + screen.getByPlaceholderText(translations.preCompletionNotes), + ).toHaveValue('Pre Completion Notes'); + const editActionItem = screen.getByRole('button', { + name: translations.editActionItem, + }); + expect(editActionItem).toBeInTheDocument(); + }); }); diff --git a/src/components/EventManagement/EventActionItems/EventActionItems.tsx b/src/components/EventManagement/EventActionItems/EventActionItems.tsx index 26273c213d..cbe878fa07 100644 --- a/src/components/EventManagement/EventActionItems/EventActionItems.tsx +++ b/src/components/EventManagement/EventActionItems/EventActionItems.tsx @@ -5,11 +5,10 @@ import type { ChangeEvent } from 'react'; import React, { useEffect, useState } from 'react'; import { Button, Form } from 'react-bootstrap'; import { useTranslation } from 'react-i18next'; -import { Link } from 'react-router-dom'; import { toast } from 'react-toastify'; import styles from './EventActionItems.module.css'; import { DataGrid } from '@mui/x-data-grid'; -import type { GridColDef, GridCellParams } from '@mui/x-data-grid'; +import type { GridCellParams } from '@mui/x-data-grid'; import { Stack } from '@mui/material'; import Modal from 'react-bootstrap/Modal'; import { @@ -19,6 +18,7 @@ import { } from 'GraphQl/Mutations/ActionItemMutations'; import type { InterfaceActionItemCategoryList, + InterfaceActionItemInfo, InterfaceMembersList, } from 'utils/interfaces'; import { DatePicker } from '@mui/x-date-pickers'; @@ -27,6 +27,9 @@ import { MEMBERS_LIST, } from 'GraphQl/Queries/Queries'; import { ACTION_ITEM_LIST_BY_EVENTS } from 'GraphQl/Queries/ActionItemQueries'; +import { useEventActionColumnConfig } from './useEventActionColumnConfig'; +import ActionItemPreviewModal from 'screens/OrganizationActionItems/ActionItemPreviewModal'; +import ActionItemDeleteModal from 'screens/OrganizationActionItems/ActionItemDeleteModal'; function eventActionItems(props: { eventId: string }): JSX.Element { const { eventId } = props; @@ -35,6 +38,11 @@ function eventActionItems(props: { eventId: string }): JSX.Element { }); const { t: tCommon } = useTranslation('common'); + const [actionItemPreviewModalIsOpen, setActionItemPreviewModalIsOpen] = + useState(false); + const [actionItemStatusModal, setActionItemStatusModal] = useState(false); + const [isActionItemCompleted, setIsActionItemCompleted] = useState(false); + const [assignmentDate, setAssignmentDate] = useState(new Date()); const [actionItemCreateModalIsOpen, setActionItemCreateModalIsOpen] = useState(false); const [actionItemUpdateModalIsOpen, setActionItemUpdateModalIsOpen] = @@ -74,6 +82,21 @@ function eventActionItems(props: { eventId: string }): JSX.Element { const toggleDeleteModal = (): void => { setActionItemDeleteModalIsOpen(!actionItemDeleteModalIsOpen); }; + const setActionItemState = (actionItem: InterfaceActionItemInfo): void => { + setFormState((prevState) => ({ + ...prevState, + assignee: `${actionItem.assignee.firstName} ${actionItem.assignee.lastName}`, + assigner: `${actionItem.assigner.firstName} ${actionItem.assigner.lastName}`, + assigneeId: actionItem.assignee._id, + preCompletionNotes: actionItem.preCompletionNotes, + postCompletionNotes: actionItem.postCompletionNotes, + isCompleted: actionItem.isCompleted, + })); + setActionItemId(actionItem._id); + setDueDate(actionItem.dueDate); + setAssignmentDate(actionItem.assignmentDate); + setCompletionDate(actionItem.completionDate); + }; const { data: actionItemCategoriesData, }: { @@ -164,6 +187,7 @@ function eventActionItems(props: { eventId: string }): JSX.Element { }); actionItemsRefetch(); hideUpdateModal(); + hideActionItemStatusModal(); toast.success(t('successfulUpdation')); } catch (error: unknown) { if (error instanceof Error) { @@ -173,116 +197,60 @@ function eventActionItems(props: { eventId: string }): JSX.Element { }; const [removeActionItem] = useMutation(DELETE_ACTION_ITEM_MUTATION); const deleteActionItemHandler = async (): Promise => { - await removeActionItem({ - variables: { - actionItemId, - }, - }); - actionItemsRefetch(); - toggleDeleteModal(); - hideUpdateModal(); - toast.success(t('successfulDeletion')); + try { + await removeActionItem({ + variables: { + actionItemId, + }, + }); + actionItemsRefetch(); + toggleDeleteModal(); + hidePreviewModal(); + toast.success(t('successfulDeletion')); + } catch (error: unknown) { + if (error instanceof Error) { + toast.error(error.message); + console.log(error.message); + } + } }; - const columns: GridColDef[] = [ - { - field: 'serialNo', - headerName: '#', - flex: 1, - minWidth: 50, - align: 'center', - headerAlign: 'center', - headerClassName: `${styles.tableHeader}`, - sortable: false, - renderCell: (params: GridCellParams) => { - return params.row?.index; - }, - }, - { - field: 'assignee', - headerName: 'Assignee', - flex: 2, - minWidth: 150, - align: 'center', - headerAlign: 'center', - headerClassName: `${styles.tableHeader}`, - sortable: false, - renderCell: (params: GridCellParams) => { - return ( - - {params.row?.assignee.firstName + - ' ' + - params.row?.assignee.lastName} - - ); - }, - }, - { - field: 'actionItemCategory', - headerName: 'Action Item Category', - flex: 2, - minWidth: 100, - align: 'center', - headerAlign: 'center', - headerClassName: `${styles.tableHeader}`, - sortable: false, - renderCell: (params: GridCellParams) => { - return params.row.actionItemCategory.name; - }, - }, - { - field: 'notes', - headerName: 'Notes', - minWidth: 150, - align: 'center', - headerAlign: 'center', - headerClassName: `${styles.tableHeader}`, - flex: 2, - sortable: false, - renderCell: (params: GridCellParams) => { - return params.row.preCompletionNotes; - }, - }, - { - field: 'completionNotes', - headerName: 'Completion Notes', - minWidth: 150, - align: 'center', - headerAlign: 'center', - headerClassName: `${styles.tableHeader}`, - flex: 2, - sortable: false, - renderCell: (params: GridCellParams) => { - return params.row.postCompletionNotes; - }, - }, - { - field: 'options', - headerName: 'Options', - flex: 2, - minWidth: 100, - align: 'center', - headerAlign: 'center', - headerClassName: `${styles.tableHeader}`, - sortable: false, - renderCell: (params: GridCellParams) => { - return ( - - ); - }, - }, - ]; + + const handleActionItemStatusChange = ( + actionItem: InterfaceActionItemInfo, + ): void => { + actionItem = { ...actionItem, isCompleted: !actionItem.isCompleted }; + setIsActionItemCompleted(!actionItem.isCompleted); + setActionItemState(actionItem); + setActionItemStatusModal(true); + }; + + const showPreviewModal = (actionItem: InterfaceActionItemInfo): void => { + setActionItemState(actionItem); + setActionItemPreviewModalIsOpen(true); + }; + + const handleEditClick = (actionItem: InterfaceActionItemInfo): void => { + setActionItemId(actionItem._id); + setActionItemState(actionItem); + showUpdateModal(); + }; + + const hidePreviewModal = (): void => { + setActionItemPreviewModalIsOpen(false); + }; + + const hideActionItemStatusModal = (): void => { + setActionItemStatusModal(false); + setActionItemUpdateModalIsOpen(false); + }; + + const { columns } = useEventActionColumnConfig({ + eventId, + handleActionItemStatusChange, + showPreviewModal, + handleEditClick, + }); + return ( <> +
    {/* create action item modal */} - Assignee + {t('assignee')} Assignee setFormState({ ...formState, assigneeId: e.target.value }) } > - {membersData?.organizations[0].members.map((member, index) => { @@ -447,24 +417,6 @@ function eventActionItems(props: { eventId: string }): JSX.Element { }); }} /> - - { - setFormState({ - ...formState, - postCompletionNotes: e.target.value, - }); - }} - className="mb-2" - /> -

    { - if (date) { - setCompletionDate(date?.toDate()); + onChange={ + /* istanbul ignore next */ (date: Dayjs | null): void => { + /* istanbul ignore next */ + if (date) { + setCompletionDate(date?.toDate()); + } } - }} + } />
    -

    -
    +
    - -
    - {/* delete modal */} + + {/* preview modal */} + + + {/* Delete Modal */} + + + {/* action item status change modal */} - - - {t('deleteActionItem')} - - - {t('deleteActionItemMsg')} - - + +

    {t('actionItemStatus')}

    -
    + + +
    + + {isActionItemCompleted + ? t('preCompletionNotes') + : t('postCompletionNotes')} + + { + if (isActionItemCompleted) { + setFormState({ + ...formState, + preCompletionNotes: e.target.value, + }); + } else { + setFormState({ + ...formState, + postCompletionNotes: e.target.value, + }); + } + }} + /> + + +
    {actionItemsData && (
    row._id} - components={{ - NoRowsOverlay: () => ( + slots={{ + noRowsOverlay: () => ( `${styles.rowBackground}`} autoHeight - rowHeight={70} + rowHeight={50} + columnHeaderHeight={40} rows={actionItemsData?.actionItemsByEvent?.map( (item: object, index: number) => ({ ...item, diff --git a/src/components/EventManagement/EventActionItems/useEventActionColumnConfig.tsx b/src/components/EventManagement/EventActionItems/useEventActionColumnConfig.tsx new file mode 100644 index 0000000000..0db74323f6 --- /dev/null +++ b/src/components/EventManagement/EventActionItems/useEventActionColumnConfig.tsx @@ -0,0 +1,200 @@ +import React from 'react'; +import type { GridCellParams, GridColDef } from '@mui/x-data-grid'; +import { Link } from 'react-router-dom'; +import { Button, OverlayTrigger, Popover } from 'react-bootstrap'; +import styles from './EventActionItems.module.css'; +import type { InterfaceActionItemInfo } from 'utils/interfaces'; +import { useTranslation } from 'react-i18next'; + +export type Props = { + eventId: string; + handleActionItemStatusChange: (actionItem: InterfaceActionItemInfo) => void; + showPreviewModal: (actionItem: InterfaceActionItemInfo) => void; + handleEditClick: (actionItem: InterfaceActionItemInfo) => void; +}; + +type ColumnConfig = { + columns: GridColDef[]; +}; + +const popover = ( + actionItemId: string, + actionItemNotes: string, +): JSX.Element => { + return ( + + {actionItemNotes} + + ); +}; + +export const useEventActionColumnConfig = ({ + eventId, + handleActionItemStatusChange, + showPreviewModal, + handleEditClick, +}: Props): ColumnConfig => { + const { t } = useTranslation('translation', { + keyPrefix: 'eventActionItems', + }); + const columns: GridColDef[] = [ + { + field: 'serialNo', + headerName: '#', + flex: 1, + minWidth: 50, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return params.row?.index; + }, + }, + { + field: 'assignee', + headerName: 'Assignee', + flex: 2, + minWidth: 150, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return ( + + {params.row?.assignee.firstName + + ' ' + + params.row?.assignee.lastName} + + ); + }, + }, + { + field: 'actionItemCategory', + headerName: 'Action Item Category', + flex: 2, + minWidth: 100, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return params.row.actionItemCategory.name; + }, + }, + { + field: 'notes', + headerName: 'Notes', + minWidth: 150, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + flex: 2, + sortable: false, + renderCell: (params: GridCellParams) => { + const actionItem = params.row; + return ( + + + {actionItem.preCompletionNotes.length > 25 + ? `${actionItem.preCompletionNotes.substring(0, 25)}...` + : actionItem.preCompletionNotes} + + + ); + }, + }, + { + field: 'completionNotes', + headerName: 'Completion Notes', + minWidth: 150, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + flex: 2, + sortable: false, + renderCell: (params: GridCellParams) => { + const actionItem = params.row; + return actionItem.isCompleted ? ( + + + {actionItem.postCompletionNotes?.length > 25 + ? `${actionItem.postCompletionNotes.substring(0, 25)}...` + : actionItem.postCompletionNotes} + + + ) : ( + + {t('actionItemActive')} + + ); + }, + }, + { + field: 'options', + headerName: 'Options', + flex: 2, + minWidth: 100, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return ( +
    + handleActionItemStatusChange(params.row)} + /> + + +
    + ); + }, + }, + ]; + return { + columns, + }; +}; diff --git a/src/components/EventManagement/EventAgendaItems/EventAgendaItems.module.css b/src/components/EventManagement/EventAgendaItems/EventAgendaItems.module.css new file mode 100644 index 0000000000..9d1c32b766 --- /dev/null +++ b/src/components/EventManagement/EventAgendaItems/EventAgendaItems.module.css @@ -0,0 +1,22 @@ +.eventAgendaItemContainer h2 { + margin: 0.6rem 0; +} + +.btnsContainer { + display: flex; + gap: 10px; +} + +@media (max-width: 768px) { + .btnsContainer { + margin-bottom: 0; + display: flex; + flex-direction: column; + } + + .createAgendaItemButton { + position: absolute; + top: 1rem; + right: 2rem; + } +} diff --git a/src/components/EventManagement/EventAgendaItems/EventAgendaItems.test.tsx b/src/components/EventManagement/EventAgendaItems/EventAgendaItems.test.tsx new file mode 100644 index 0000000000..b1b3ed6094 --- /dev/null +++ b/src/components/EventManagement/EventAgendaItems/EventAgendaItems.test.tsx @@ -0,0 +1,205 @@ +import React from 'react'; +import { + render, + screen, + waitFor, + act, + waitForElementToBeRemoved, +} from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import 'jest-localstorage-mock'; +import { MockedProvider } from '@apollo/client/testing'; +import 'jest-location-mock'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import i18n from 'utils/i18nForTest'; +import { toast } from 'react-toastify'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; + +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; + +import EventAgendaItems from './EventAgendaItems'; + +import { + MOCKS, + MOCKS_ERROR_QUERY, + MOCKS_ERROR_MUTATION, +} from './EventAgendaItemsMocks'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ eventId: '123' }), +})); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +const link = new StaticMockLink(MOCKS, true); +const link2 = new StaticMockLink(MOCKS_ERROR_QUERY, true); +const link3 = new StaticMockLink(MOCKS_ERROR_MUTATION, true); + +const translations = JSON.parse( + JSON.stringify(i18n.getDataByLanguage('en')?.translation.agendaItems), +); + +describe('Testing Agenda Items Components', () => { + const formData = { + title: 'AgendaItem 1', + description: 'AgendaItem 1 Description', + duration: '30', + relatedEventId: '123', + organizationId: '111', + sequence: 1, + categories: ['Category 1'], + attachments: [], + urls: [], + }; + test('Component loads correctly', async () => { + window.location.assign('/event/111/123'); + const { getByText } = render( + + + + + {} + + + + , + ); + + await wait(); + + await waitFor(() => { + expect(getByText(translations.createAgendaItem)).toBeInTheDocument(); + }); + }); + + test('render error component on unsuccessful agenda item query', async () => { + window.location.assign('/event/111/123'); + const { queryByText } = render( + + + + + {} + + + + , + ); + + await wait(); + + await waitFor(() => { + expect( + queryByText(translations.createAgendaItem), + ).not.toBeInTheDocument(); + }); + }); + + test('opens and closes the create agenda item modal', async () => { + window.location.assign('/event/111/123'); + render( + + + + + + {} + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('createAgendaItemBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('createAgendaItemBtn')); + + await waitFor(() => { + return expect( + screen.findByTestId('createAgendaItemModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('createAgendaItemModalCloseBtn')); + + await waitForElementToBeRemoved(() => + screen.queryByTestId('createAgendaItemModalCloseBtn'), + ); + }); + test('creates new agenda item', async () => { + window.location.assign('/event/111/123'); + render( + + + + + + {} + + + + + , + ); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('createAgendaItemBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('createAgendaItemBtn')); + + await waitFor(() => { + expect( + screen.getByTestId('createAgendaItemModalCloseBtn'), + ).toBeInTheDocument(); + }); + + userEvent.type( + screen.getByPlaceholderText(translations.enterTitle), + formData.title, + ); + + userEvent.type( + screen.getByPlaceholderText(translations.enterDescription), + formData.description, + ); + userEvent.type( + screen.getByPlaceholderText(translations.enterDuration), + formData.duration, + ); + const categorySelect = screen.getByTestId('categorySelect'); + userEvent.click(categorySelect); + await waitFor(() => { + const categoryOption = screen.getByText('Category 1'); + userEvent.click(categoryOption); + }); + + userEvent.click(screen.getByTestId('createAgendaItemFormBtn')); + + await waitFor(() => { + // expect(toast.success).toBeCalledWith(translations.agendaItemCreated); + }); + }); +}); diff --git a/src/components/EventManagement/EventAgendaItems/EventAgendaItems.tsx b/src/components/EventManagement/EventAgendaItems/EventAgendaItems.tsx new file mode 100644 index 0000000000..09cc560bf1 --- /dev/null +++ b/src/components/EventManagement/EventAgendaItems/EventAgendaItems.tsx @@ -0,0 +1,203 @@ +import React, { useState } from 'react'; +import type { ChangeEvent } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Button } from 'react-bootstrap'; + +import { WarningAmberRounded } from '@mui/icons-material'; +import { toast } from 'react-toastify'; + +import { useMutation, useQuery } from '@apollo/client'; +import { + AGENDA_ITEM_CATEGORY_LIST, + AgendaItemByEvent, +} from 'GraphQl/Queries/Queries'; +import { CREATE_AGENDA_ITEM_MUTATION } from 'GraphQl/Mutations/mutations'; + +import type { + InterfaceAgendaItemCategoryList, + InterfaceAgendaItemList, +} from 'utils/interfaces'; +import AgendaItemsContainer from 'components/AgendaItems/AgendaItemsContainer'; +import AgendaItemsCreateModal from 'components/AgendaItems/AgendaItemsCreateModal'; + +import styles from './EventAgendaItems.module.css'; +import Loader from 'components/Loader/Loader'; + +function EventAgendaItems(props: { eventId: string }): JSX.Element { + const { eventId } = props; + + const { t } = useTranslation('translation', { + keyPrefix: 'agendaItems', + }); + + const url: string = window.location.href; + const startIdx: number = url.indexOf('/event/') + '/event/'.length; + const orgId: string = url.slice(startIdx, url.indexOf('/', startIdx)); + + const [agendaItemCreateModalIsOpen, setAgendaItemCreateModalIsOpen] = + useState(false); + + const [formState, setFormState] = useState({ + agendaItemCategoryIds: [''], + title: '', + description: '', + duration: '', + attachments: [''], + urls: [''], + }); + + const { + data: agendaCategoryData, + loading: agendaCategoryLoading, + error: agendaCategoryError, + }: { + data: InterfaceAgendaItemCategoryList | undefined; + loading: boolean; + error?: Error | undefined; + } = useQuery(AGENDA_ITEM_CATEGORY_LIST, { + variables: { organizationId: orgId }, + notifyOnNetworkStatusChange: true, + }); + + const { + data: agendaItemData, + loading: agendaItemLoading, + error: agendaItemError, + refetch: refetchAgendaItem, + }: { + data: InterfaceAgendaItemList | undefined; + loading: boolean; + error?: unknown | undefined; + refetch: () => void; + } = useQuery(AgendaItemByEvent, { + variables: { relatedEventId: eventId }, //eventId + notifyOnNetworkStatusChange: true, + }); + + const [createAgendaItem] = useMutation(CREATE_AGENDA_ITEM_MUTATION); + + const createAgendaItemHandler = async ( + e: ChangeEvent, + ): Promise => { + e.preventDefault(); + try { + await createAgendaItem({ + variables: { + input: { + title: formState.title, + description: formState.description, + relatedEventId: eventId, + organizationId: orgId, + sequence: (agendaItemData?.agendaItemByEvent.length || 0) + 1 || 1, // Assign sequence based on current length + duration: formState.duration, + categories: formState.agendaItemCategoryIds, + attachments: formState.attachments, + urls: formState.urls, + }, + }, + }); + + setFormState({ + title: '', + description: '', + duration: '', + agendaItemCategoryIds: [''], + attachments: [''], + urls: [''], + }); + hideCreateModal(); + refetchAgendaItem(); + toast.success(t('agendaItemCreated')); + } catch (error: unknown) { + if (error instanceof Error) { + toast.error(error.message); + } + } + }; + + const showCreateModal = (): void => { + setAgendaItemCreateModalIsOpen(!agendaItemCreateModalIsOpen); + }; + + const hideCreateModal = (): void => { + setAgendaItemCreateModalIsOpen(!agendaItemCreateModalIsOpen); + }; + + if (agendaItemLoading || agendaCategoryLoading) return ; + + if (agendaItemError || agendaCategoryError) { + return ( +
    +
    + +
    + Error occurred while loading{' '} + {agendaCategoryError + ? 'Agenda Categories' + : agendaItemError && 'Agenda Items'} + Data +
    + {agendaCategoryError + ? agendaCategoryError.message + : agendaItemError && (agendaItemError as Error).message} +
    +
    +
    + ); + } + + return ( +
    +
    +
    +
    +
    + {/* setSearchValue(e.target.value)} + value={searchValue} + data-testid="search" + /> */} +
    + + +
    +
    + +
    + + +
    + + +
    + ); +} + +export default EventAgendaItems; diff --git a/src/components/EventManagement/EventAgendaItems/EventAgendaItemsMocks.ts b/src/components/EventManagement/EventAgendaItems/EventAgendaItemsMocks.ts new file mode 100644 index 0000000000..619a1e70f8 --- /dev/null +++ b/src/components/EventManagement/EventAgendaItems/EventAgendaItemsMocks.ts @@ -0,0 +1,133 @@ +import { CREATE_AGENDA_ITEM_MUTATION } from 'GraphQl/Mutations/AgendaItemMutations'; + +import { AgendaItemByEvent } from 'GraphQl/Queries/AgendaItemQueries'; +import { AGENDA_ITEM_CATEGORY_LIST } from 'GraphQl/Queries/AgendaCategoryQueries'; + +export const MOCKS = [ + { + request: { + query: AGENDA_ITEM_CATEGORY_LIST, + variables: { organizationId: '111' }, + }, + result: { + data: { + agendaItemCategoriesByOrganization: [ + { + _id: 'agendaItemCategory1', + name: 'Category 1', + description: 'Test Description', + createdBy: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + ], + }, + }, + }, + { + request: { + query: AgendaItemByEvent, + variables: { relatedEventId: '123' }, + }, + result: { + data: { + agendaItemByEvent: [ + { + _id: 'agendaItem1', + title: 'AgendaItem 1', + description: 'AgendaItem 1 Description', + duration: '30', + attachments: [], + createdBy: { + _id: 'user0', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + urls: [], + users: [], + sequence: 1, + categories: [ + { + _id: 'agendaItemCategory1', + name: 'Category 1', + }, + ], + organization: { + _id: '111', + name: 'Unity Foundation', + }, + relatedEvent: { + _id: '123', + title: 'Aerobics for Everyone', + }, + }, + ], + }, + }, + }, + { + request: { + query: CREATE_AGENDA_ITEM_MUTATION, + variables: { + input: { + title: 'AgendaItem 1', + description: 'AgendaItem 1 Description', + duration: '30', + relatedEventId: '123', + organizationId: '111', + sequence: 1, + categories: ['Category 1'], + attachments: [], + urls: [], + }, + }, + }, + result: { + data: { + createAgendaItem: { + _id: 'agendaItem1', + }, + }, + }, + }, +]; + +export const MOCKS_ERROR_MUTATION = [ + { + request: { + query: CREATE_AGENDA_ITEM_MUTATION, + variables: { + input: { + title: 'AgendaItem 1', + description: 'AgendaItem 1 Description', + duration: '30', + relatedEventId: '123', + organizationId: '111', + sequence: 1, + categories: ['agendaItemCategory1'], + attachments: [], + urls: [], + }, + }, + }, + error: new Error('Mock Graphql Error'), + }, + { + request: { + query: AgendaItemByEvent, + variables: { relatedEventId: '123' }, + }, + error: new Error('Mock Graphql Error'), + }, + { + request: { + query: AGENDA_ITEM_CATEGORY_LIST, + variables: { organizationId: '111' }, + }, + error: new Error('Mock Graphql Error'), + }, +]; + +export const MOCKS_ERROR_QUERY = []; diff --git a/src/components/EventRegistrantsModal/EventRegistrantsModal.test.tsx b/src/components/EventRegistrantsModal/EventRegistrantsModal.test.tsx index 597502ac8e..8a084fef24 100644 --- a/src/components/EventRegistrantsModal/EventRegistrantsModal.test.tsx +++ b/src/components/EventRegistrantsModal/EventRegistrantsModal.test.tsx @@ -194,9 +194,7 @@ describe('Testing Event Registrants Modal', () => { ); await waitFor(() => - expect( - queryByText('Added the attendee successfully!'), - ).toBeInTheDocument(), + expect(queryByText('Attendee added Successfully')).toBeInTheDocument(), ); }); @@ -244,9 +242,7 @@ describe('Testing Event Registrants Modal', () => { ); await waitFor(() => - expect( - queryByText('There was an error in adding the attendee!'), - ).toBeInTheDocument(), + expect(queryByText('Error adding attendee')).toBeInTheDocument(), ); }); @@ -286,9 +282,7 @@ describe('Testing Event Registrants Modal', () => { ); await waitFor(() => - expect( - queryByText('Removed the attendee successfully!'), - ).toBeInTheDocument(), + expect(queryByText('Attendee removed Successfully')).toBeInTheDocument(), ); }); @@ -328,9 +322,7 @@ describe('Testing Event Registrants Modal', () => { ); await waitFor(() => - expect( - queryByText('There was an error in removing the attendee!'), - ).toBeInTheDocument(), + expect(queryByText('Error removing attendee')).toBeInTheDocument(), ); }); }); diff --git a/src/components/EventRegistrantsModal/EventRegistrantsModal.tsx b/src/components/EventRegistrantsModal/EventRegistrantsModal.tsx index 0b3ef64d28..811dd44941 100644 --- a/src/components/EventRegistrantsModal/EventRegistrantsModal.tsx +++ b/src/components/EventRegistrantsModal/EventRegistrantsModal.tsx @@ -13,6 +13,7 @@ import Chip from '@mui/material/Chip'; import Stack from '@mui/material/Stack'; import TextField from '@mui/material/TextField'; import Autocomplete from '@mui/material/Autocomplete'; +import { useTranslation } from 'react-i18next'; type ModalPropType = { show: boolean; @@ -28,21 +29,26 @@ interface InterfaceUser { } export const EventRegistrantsModal = (props: ModalPropType): JSX.Element => { + const { eventId, orgId, handleClose, show } = props; const [member, setMember] = useState(null); const [addRegistrantMutation] = useMutation(ADD_EVENT_ATTENDEE); const [removeRegistrantMutation] = useMutation(REMOVE_EVENT_ATTENDEE); + const { t } = useTranslation('translation', { + keyPrefix: 'eventRegistrantsModal', + }); + const { t: tCommon } = useTranslation('common'); const { data: attendeesData, loading: attendeesLoading, refetch: attendeesRefetch, } = useQuery(EVENT_ATTENDEES, { - variables: { id: props.eventId }, + variables: { id: eventId }, }); const { data: memberData, loading: memberLoading } = useQuery(MEMBERS_LIST, { - variables: { id: props.orgId }, + variables: { id: orgId }, }); const addRegistrant = (): void => { @@ -54,15 +60,15 @@ export const EventRegistrantsModal = (props: ModalPropType): JSX.Element => { addRegistrantMutation({ variables: { userId: member._id, - eventId: props.eventId, + eventId: eventId, }, }) .then(() => { - toast.success('Added the attendee successfully!'); + toast.success(tCommon('addedSuccessfully', { item: 'Attendee' })); attendeesRefetch(); }) .catch((err) => { - toast.error('There was an error in adding the attendee!'); + toast.error(t('errorAddingAttendee')); toast.error(err.message); }); }; @@ -72,15 +78,15 @@ export const EventRegistrantsModal = (props: ModalPropType): JSX.Element => { removeRegistrantMutation({ variables: { userId, - eventId: props.eventId, + eventId: eventId, }, }) .then(() => { - toast.success('Removed the attendee successfully!'); + toast.success(tCommon('removedSuccessfully', { item: 'Attendee' })); attendeesRefetch(); }) .catch((err) => { - toast.error('There was an error in removing the attendee!'); + toast.error(t('errorRemovingAttendee')); toast.error(err.message); }); }; @@ -96,12 +102,7 @@ export const EventRegistrantsModal = (props: ModalPropType): JSX.Element => { return ( <> - + Event Registrants diff --git a/src/components/IconComponent/IconComponent.tsx b/src/components/IconComponent/IconComponent.tsx index d65982edef..17f9af8b32 100644 --- a/src/components/IconComponent/IconComponent.tsx +++ b/src/components/IconComponent/IconComponent.tsx @@ -1,5 +1,6 @@ import { QuestionMarkOutlined } from '@mui/icons-material'; import { ReactComponent as ActionItemIcon } from 'assets/svgs/actionItem.svg'; +import { ReactComponent as AgendaCategoryIcon } from 'assets/svgs/agenda-category-icon.svg'; import { ReactComponent as BlockUserIcon } from 'assets/svgs/blockUser.svg'; import { ReactComponent as CheckInRegistrantsIcon } from 'assets/svgs/checkInRegistrants.svg'; import { ReactComponent as DashboardIcon } from 'assets/svgs/dashboard.svg'; @@ -14,8 +15,8 @@ import { ReactComponent as PostsIcon } from 'assets/svgs/posts.svg'; import { ReactComponent as SettingsIcon } from 'assets/svgs/settings.svg'; import { ReactComponent as VenueIcon } from 'assets/svgs/venues.svg'; import { ReactComponent as RequestsIcon } from 'assets/svgs/requests.svg'; -import { ReactComponent as HomeIcon } from 'assets/svgs/home.svg'; -import { ReactComponent as DonateIcon } from 'assets/svgs/donate.svg'; +// import { ReactComponent as HomeIcon } from 'assets/svgs/home.svg'; +// import { ReactComponent as DonateIcon } from 'assets/svgs/donate.svg'; import React from 'react'; @@ -54,6 +55,13 @@ const iconComponent = (props: InterfaceIconComponent): JSX.Element => { data-testid="Icon-Component-ActionItemIcon" /> ); + case 'Agenda Items Category': + return ( + + ); case 'Posts': return ; case 'Block/Unblock': diff --git a/src/components/LeftDrawerOrg/LeftDrawerOrg.test.tsx b/src/components/LeftDrawerOrg/LeftDrawerOrg.test.tsx index 9bd2ffd1d9..58a7168552 100644 --- a/src/components/LeftDrawerOrg/LeftDrawerOrg.test.tsx +++ b/src/components/LeftDrawerOrg/LeftDrawerOrg.test.tsx @@ -24,41 +24,41 @@ const props: InterfaceLeftDrawerProps = { targets: [ { name: 'Dashboard', - url: '/orgdash/id=123', + url: '/orgdash/123', }, { name: 'People', - url: '/orgpeople/id=123', + url: '/orgpeople/123', }, { name: 'Events', - url: '/orgevents/id=123', + url: '/orgevents/123', }, { name: 'Posts', - url: '/orgpost/id=123', + url: '/orgpost/123', }, { name: 'Block/Unblock', - url: '/blockuser/id=123', + url: '/blockuser/123', }, { name: 'Plugins', subTargets: [ { name: 'Plugin Store', - url: '/orgstore/id=123', + url: '/orgstore/123', icon: 'fa-store', }, ], }, { name: 'Settings', - url: '/orgsetting/id=123', + url: '/orgsetting/123', }, { name: 'All Organizations', - url: '/orglist/id=123', + url: '/orglist/123', }, ], hideDrawer: false, @@ -327,7 +327,7 @@ describe('Testing LeftDrawerOrg component for SUPERADMIN', () => { ); await wait(); userEvent.click(screen.getByText('Dashboard')); - expect(global.window.location.pathname).toContain('/orgdash/id=123'); + expect(global.window.location.pathname).toContain('/orgdash/123'); }); test('Testing when screen size is less than 820px', async () => { @@ -351,7 +351,7 @@ describe('Testing LeftDrawerOrg component for SUPERADMIN', () => { const peopelBtn = screen.getByTestId(/People/i); userEvent.click(peopelBtn); await wait(); - expect(window.location.pathname).toContain('/orgpeople/id=123'); + expect(window.location.pathname).toContain('/orgpeople/123'); }); test('Testing when image is present for Organization', async () => { diff --git a/src/components/OrgActionItemCategories/OrgActionItemCategories.test.tsx b/src/components/OrgActionItemCategories/OrgActionItemCategories.test.tsx index d410611c61..0665ce6fc4 100644 --- a/src/components/OrgActionItemCategories/OrgActionItemCategories.test.tsx +++ b/src/components/OrgActionItemCategories/OrgActionItemCategories.test.tsx @@ -61,7 +61,7 @@ const translations = { describe('Testing Action Item Categories Component', () => { test('Component loads correctly', async () => { - window.location.assign('/orgsetting/id=123'); + window.location.assign('/orgsetting/123'); const { getByText } = render( @@ -82,7 +82,7 @@ describe('Testing Action Item Categories Component', () => { }); test('render error component on unsuccessful query', async () => { - window.location.assign('/orgsetting/id=123'); + window.location.assign('/orgsetting/123'); const { queryByText } = render( @@ -103,7 +103,7 @@ describe('Testing Action Item Categories Component', () => { }); test('opens and closes create and update modals on button clicks', async () => { - window.location.assign('/orgsetting/id=123'); + window.location.assign('/orgsetting/123'); render( @@ -132,7 +132,7 @@ describe('Testing Action Item Categories Component', () => { }); test('create a new action item category', async () => { - window.location.assign('/orgsetting/id=123'); + window.location.assign('/orgsetting/123'); render( @@ -163,7 +163,7 @@ describe('Testing Action Item Categories Component', () => { }); test('toast error on unsuccessful creation', async () => { - window.location.assign('/orgsetting/id=123'); + window.location.assign('/orgsetting/123'); render( @@ -194,7 +194,7 @@ describe('Testing Action Item Categories Component', () => { }); test('update an action item category', async () => { - window.location.assign('/orgsetting/id=123'); + window.location.assign('/orgsetting/123'); render( @@ -231,7 +231,7 @@ describe('Testing Action Item Categories Component', () => { }); test('toast error on unsuccessful updation', async () => { - window.location.assign('/orgsetting/id=123'); + window.location.assign('/orgsetting/123'); render( @@ -268,7 +268,7 @@ describe('Testing Action Item Categories Component', () => { }); test('toast error on providing the same name on updation', async () => { - window.location.assign('/orgsetting/id=123'); + window.location.assign('/orgsetting/123'); render( @@ -305,7 +305,7 @@ describe('Testing Action Item Categories Component', () => { }); test('toggle the disablity status of an action item category', async () => { - window.location.assign('/orgsetting/id=123'); + window.location.assign('/orgsetting/123'); render( @@ -338,7 +338,7 @@ describe('Testing Action Item Categories Component', () => { }); test('toast error on unsuccessful toggling of the disablity status', async () => { - window.location.assign('/orgsetting/id=123'); + window.location.assign('/orgsetting/123'); render( diff --git a/src/components/OrganizationScreen/OrganizationScreen.tsx b/src/components/OrganizationScreen/OrganizationScreen.tsx index 59b6f289c9..a8f9d16b9c 100644 --- a/src/components/OrganizationScreen/OrganizationScreen.tsx +++ b/src/components/OrganizationScreen/OrganizationScreen.tsx @@ -112,6 +112,7 @@ const map: InterfaceMapType = { member: 'memberDetail', orgevents: 'organizationEvents', orgactionitems: 'organizationActionItems', + orgagendacategory: 'organizationAgendaCategory', orgcontribution: 'orgContribution', orgpost: 'orgPost', orgfunds: 'funds', diff --git a/src/components/ProfileDropdown/ProfileDropdown.test.tsx b/src/components/ProfileDropdown/ProfileDropdown.test.tsx index 73d32f5022..0efef50591 100644 --- a/src/components/ProfileDropdown/ProfileDropdown.test.tsx +++ b/src/components/ProfileDropdown/ProfileDropdown.test.tsx @@ -7,6 +7,8 @@ import 'jest-localstorage-mock'; import { MockedProvider } from '@apollo/react-testing'; import { REVOKE_REFRESH_TOKEN } from 'GraphQl/Mutations/mutations'; import useLocalStorage from 'utils/useLocalstorage'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; const { setItem } = useLocalStorage(); const MOCKS = [ @@ -57,7 +59,9 @@ describe('ProfileDropdown Component', () => { render( - + + + , ); diff --git a/src/components/ProfileDropdown/ProfileDropdown.tsx b/src/components/ProfileDropdown/ProfileDropdown.tsx index f5c3af8664..28c96a988c 100644 --- a/src/components/ProfileDropdown/ProfileDropdown.tsx +++ b/src/components/ProfileDropdown/ProfileDropdown.tsx @@ -6,8 +6,10 @@ import useLocalStorage from 'utils/useLocalstorage'; import styles from './ProfileDropdown.module.css'; import { REVOKE_REFRESH_TOKEN } from 'GraphQl/Mutations/mutations'; import { useMutation } from '@apollo/client'; +import { useTranslation } from 'react-i18next'; const profileDropdown = (): JSX.Element => { + const { t: tCommon } = useTranslation('common'); const [revokeRefreshToken] = useMutation(REVOKE_REFRESH_TOKEN); const { getItem } = useLocalStorage(); const superAdmin = getItem('SuperAdmin'); @@ -90,14 +92,14 @@ const profileDropdown = (): JSX.Element => { } aria-label="View Profile" > - View Profile + {tCommon('viewProfile')} - Logout + {tCommon('logout')} diff --git a/src/components/UserPasswordUpdate/UserPasswordUpdate.test.tsx b/src/components/UserPasswordUpdate/UserPasswordUpdate.test.tsx index 2aa5756717..4fcbb18070 100644 --- a/src/components/UserPasswordUpdate/UserPasswordUpdate.test.tsx +++ b/src/components/UserPasswordUpdate/UserPasswordUpdate.test.tsx @@ -110,9 +110,7 @@ describe('Testing User Password Update', () => { userEvent.click(screen.getByText(/Save Changes/i)); await wait(); - expect(mockToast.error).toHaveBeenCalledWith( - 'The password field cannot be empty.', - ); + expect(mockToast.error).toHaveBeenCalledWith(`Password can't be empty`); }); test('displays an error when new and confirm password field does not match', async () => { diff --git a/src/components/UserPasswordUpdate/UserPasswordUpdate.tsx b/src/components/UserPasswordUpdate/UserPasswordUpdate.tsx index 78fea1df53..f9cb899f2d 100644 --- a/src/components/UserPasswordUpdate/UserPasswordUpdate.tsx +++ b/src/components/UserPasswordUpdate/UserPasswordUpdate.tsx @@ -32,12 +32,12 @@ const UserUpdate: React.FC< !formState.newPassword || !formState.confirmNewPassword ) { - toast.error('The password field cannot be empty.'); + toast.error(t('passCantBeEmpty')); return; } if (formState.newPassword !== formState.confirmNewPassword) { - toast.error('New and Confirm password do not match.'); + toast.error(t('passNoMatch')); return; } @@ -51,7 +51,7 @@ const UserUpdate: React.FC< }); /* istanbul ignore next */ if (data) { - toast.success('Successful updated'); + toast.success(tCommon('updatedSuccessfully', { item: 'Password' })); setTimeout(() => { window.location.reload(); }, 2000); diff --git a/src/components/UserPortal/ChatRoom/ChatRoom.module.css b/src/components/UserPortal/ChatRoom/ChatRoom.module.css index 592004d523..f6aa3e374b 100644 --- a/src/components/UserPortal/ChatRoom/ChatRoom.module.css +++ b/src/components/UserPortal/ChatRoom/ChatRoom.module.css @@ -1,7 +1,7 @@ .chatAreaContainer { padding: 10px; flex-grow: 1; - background-color: rgba(196, 255, 211, 0.3); + /* background-color: rgba(196, 255, 211, 0.3); */ } .backgroundWhite { @@ -11,3 +11,100 @@ .grey { color: grey; } + +.header { + position: sticky; + top: 0px; + background: white; +} + +.userInfo { + display: flex; + border-bottom: 1px solid black; + padding-bottom: 5px; + align-items: center; + margin-top: 5px; +} + +.contactImage { + width: 45px !important; + height: auto !important; + border-radius: 10px; + display: flex; + align-items: center; + justify-content: center; +} + +.messageSentContainer { + display: flex; + justify-content: flex-end; +} + +.messageReceivedContainer { + display: flex; + align-items: flex-end; +} + +.messageReceived { + border: 1px solid #c2c2c2; + border-radius: 8px 8px 8px 0px; + padding: 4px 6px; + margin: 4px 6px; + width: fit-content; + max-width: 75%; + min-width: 80px; +} + +.messageSent { + border: 1px solid #c2c2c2; + border-radius: 8px 8px 0px 8px; + padding: 4px 6px; + margin: 4px 6px; + width: fit-content; + max-width: 75%; + background-color: rgba(196, 255, 211, 0.3); + min-width: 80px; + padding-bottom: 0; +} + +.messageTime { + font-size: 10px; + display: flex; + align-items: flex-end; + justify-content: flex-end; + margin-bottom: 0px; +} + +.messageContent { + margin-bottom: 0px; +} + +.createChat { + border: none; + background-color: white; +} + +.chatMessages { + margin: 10px 0; +} + +.userDetails .subtitle { + font-size: 12px; + color: #959595; + margin: 0; +} + +.userDetails .title { + font-size: 18px; + margin: 0; +} + +.contactImage { + height: fit-content; +} + +.senderInfo { + margin: 2px 2px 0px 2px; + font-size: 12px; + font-weight: 600; +} diff --git a/src/components/UserPortal/ChatRoom/ChatRoom.test.tsx b/src/components/UserPortal/ChatRoom/ChatRoom.test.tsx index 9b63779582..7d72837767 100644 --- a/src/components/UserPortal/ChatRoom/ChatRoom.test.tsx +++ b/src/components/UserPortal/ChatRoom/ChatRoom.test.tsx @@ -1,6 +1,13 @@ import React from 'react'; -import { act, render, screen, fireEvent } from '@testing-library/react'; +import { + act, + render, + screen, + fireEvent, + waitFor, + findAllByTestId, +} from '@testing-library/react'; import { MockedProvider } from '@apollo/react-testing'; import { I18nextProvider } from 'react-i18next'; @@ -9,7 +16,21 @@ import { Provider } from 'react-redux'; import { store } from 'state/store'; import i18nForTest from 'utils/i18nForTest'; import { StaticMockLink } from 'utils/StaticMockLink'; -import ContactCard from './ChatRoom'; +import { + DIRECT_CHAT_BY_ID, + GROUP_CHAT_BY_ID, +} from 'GraphQl/Queries/PlugInQueries'; +import { + MESSAGE_SENT_TO_DIRECT_CHAT, + MESSAGE_SENT_TO_GROUP_CHAT, + SEND_MESSAGE_TO_DIRECT_CHAT, + SEND_MESSAGE_TO_GROUP_CHAT, +} from 'GraphQl/Mutations/OrganizationMutations'; +import userEvent from '@testing-library/user-event'; +import ChatRoom from './ChatRoom'; +import { useLocalStorage } from 'utils/useLocalstorage'; + +const { setItem } = useLocalStorage(); const link = new StaticMockLink([], true); @@ -21,29 +42,757 @@ async function wait(ms = 100): Promise { }); } +const SEND_MESSAGE_TO_DIRECT_CHAT_MOCK = { + request: { + query: SEND_MESSAGE_TO_DIRECT_CHAT, + variables: { + messageContent: 'Hello', + chatId: '1', + }, + }, + result: { + data: { + sendMessageToDirectChat: { + _id: '', + createdAt: '', + messageContent: '', + receiver: { + _id: '', + firstName: '', + lastName: '', + }, + sender: { + _id: '', + firstName: '', + lastName: '', + }, + updatedAt: '', + }, + }, + }, +}; + +const SEND_MESSAGE_TO_GROUP_CHAT_MOCK = { + request: { + query: SEND_MESSAGE_TO_GROUP_CHAT, + variables: { + messageContent: 'Test message', + chatId: '1', + }, + }, + result: { + data: { + sendMessageToGroupChat: { + _id: '', + createdAt: '', + messageContent: '', + sender: { + _id: '', + firstName: '', + lastName: '', + }, + updatedAt: '', + }, + }, + }, +}; + +const MESSAGE_SENT_TO_GROUP_CHAT_MOCK = [ + { + request: { + query: MESSAGE_SENT_TO_GROUP_CHAT, + variables: { + userId: null, + }, + }, + result: { + data: { + messageSentToGroupChat: { + _id: '668ec1f1364e03ac47a151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, + { + request: { + query: MESSAGE_SENT_TO_GROUP_CHAT, + variables: { + userId: '2', + }, + }, + result: { + data: { + messageSentToGroupChat: { + _id: '668ec1f1df364e03ac47a151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, + { + request: { + query: MESSAGE_SENT_TO_GROUP_CHAT, + variables: { + userId: '1', + }, + }, + result: { + data: { + messageSentToGroupChat: { + _id: '668ec1f13603ac4697a151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, +]; + +const MESSAGE_SENT_TO_DIRECT_CHAT_MOCK = [ + { + request: { + query: MESSAGE_SENT_TO_DIRECT_CHAT, + variables: { + userId: '1', + }, + }, + result: { + data: { + messageSentToDirectChat: { + _id: '668ec1f1364e03ac4697a151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + receiver: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + image: '', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, + { + request: { + query: MESSAGE_SENT_TO_DIRECT_CHAT, + variables: { + userId: '2', + }, + }, + result: { + data: { + messageSentToDirectChat: { + _id: '668ec1f1364e03ac4697vgfa151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + receiver: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + image: '', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, + { + request: { + query: MESSAGE_SENT_TO_DIRECT_CHAT, + variables: { + userId: null, + }, + }, + result: { + data: { + messageSentToDirectChat: { + _id: '6ec1f1364e03ac4697a151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + receiver: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + image: '', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, +]; + +const DIRECT_CHAT_BY_ID_QUERY_MOCK = [ + { + request: { + query: DIRECT_CHAT_BY_ID, + variables: { + id: '1', + }, + }, + result: { + data: { + directChatById: { + _id: '1', + createdAt: '2345678903456', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + receiver: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: DIRECT_CHAT_BY_ID, + variables: { + id: '1', + }, + }, + result: { + data: { + directChatById: { + _id: '1', + createdAt: '2345678903456', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + receiver: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: DIRECT_CHAT_BY_ID, + variables: { + id: '2', + }, + }, + result: { + data: { + directChatById: { + _id: '65844efc814dd4003db811c4', + createdAt: '2345678903456', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + receiver: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: DIRECT_CHAT_BY_ID, + variables: { + id: '', + }, + }, + result: { + data: { + directChatById: { + _id: '65844efc814dd4003db811c4', + createdAt: '2345678903456', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + receiver: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + ], + }, + }, + }, + }, +]; + +const GROUP_CHAT_BY_ID_QUERY_MOCK = [ + { + request: { + query: GROUP_CHAT_BY_ID, + variables: { + id: '1', + }, + }, + result: { + data: { + groupChatById: { + _id: '65844efc814dd4003db811c4', + createdAt: '2345678903456', + title: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: GROUP_CHAT_BY_ID, + variables: { + id: '1', + }, + }, + result: { + data: { + groupChatById: { + _id: '1', + createdAt: '2345678903456', + title: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: GROUP_CHAT_BY_ID, + variables: { + id: '2', + }, + }, + result: { + data: { + groupChatById: { + _id: '65844efc814dd4003db811c4', + createdAt: '2345678903456', + title: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: GROUP_CHAT_BY_ID, + variables: { + id: '', + }, + }, + result: { + data: { + groupChatById: { + _id: '65844efc814dd4003db811c4', + createdAt: '2345678903456', + title: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + }, + }, + }, +]; + describe('Testing Chatroom Component [User Portal]', () => { - test('Component should be rendered properly if the selectedContact is undefined', async () => { + window.HTMLElement.prototype.scrollIntoView = jest.fn(); + + test('Chat room should display fallback content if no chat is active', async () => { + const mocks = [ + ...DIRECT_CHAT_BY_ID_QUERY_MOCK, + ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, + ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ...GROUP_CHAT_BY_ID_QUERY_MOCK, + ]; render( - + - + , ); await wait(); + expect(await screen.findByTestId('noChatSelected')).toBeInTheDocument(); }); - test('Component should be rendered properly if selectedContact is not undefined', async () => { + test('Selected contact is direct chat', async () => { + const mocks = [ + ...DIRECT_CHAT_BY_ID_QUERY_MOCK, + ...GROUP_CHAT_BY_ID_QUERY_MOCK, + ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, + ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ]; render( - + - + @@ -52,21 +801,107 @@ describe('Testing Chatroom Component [User Portal]', () => { await wait(); }); - test('Message should change when the user types in the input', async () => { + test('Test send message direct chat', async () => { + setItem('userId', '2'); + const mocks = [ + SEND_MESSAGE_TO_DIRECT_CHAT_MOCK, + ...DIRECT_CHAT_BY_ID_QUERY_MOCK, + ...GROUP_CHAT_BY_ID_QUERY_MOCK, + ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, + ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ]; render( - + - + , ); - const input = screen.getByTestId('messageInput') as HTMLInputElement; - fireEvent.change(input, { target: { value: 'Hello' } }); + await wait(); + const input = (await screen.findByTestId( + 'messageInput', + )) as HTMLInputElement; + + act(() => { + fireEvent.change(input, { target: { value: 'Hello' } }); + }); expect(input.value).toBe('Hello'); + + const sendBtn = await screen.findByTestId('sendMessage'); + + expect(sendBtn).toBeInTheDocument(); + act(() => { + fireEvent.click(sendBtn); + }); + await waitFor(() => { + expect(input.value).toBeFalsy(); + }); + }); + + test('Selected contact is group chat', async () => { + const mocks = [ + ...DIRECT_CHAT_BY_ID_QUERY_MOCK, + ...GROUP_CHAT_BY_ID_QUERY_MOCK, + ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, + ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ]; + render( + + + + + + + + + , + ); + await wait(); + }); + + test('Test send message group chat', async () => { + const mocks = [ + SEND_MESSAGE_TO_GROUP_CHAT_MOCK, + ...DIRECT_CHAT_BY_ID_QUERY_MOCK, + ...GROUP_CHAT_BY_ID_QUERY_MOCK, + ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, + ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ]; + render( + + + + + + + + + , + ); + await wait(); + + const input = (await screen.findByTestId( + 'messageInput', + )) as HTMLInputElement; + + act(() => { + fireEvent.change(input, { target: { value: 'Test message' } }); + }); + expect(input.value).toBe('Test message'); + + const sendBtn = await screen.findByTestId('sendMessage'); + + expect(sendBtn).toBeInTheDocument(); + act(() => { + fireEvent.click(sendBtn); + }); + await waitFor(() => { + expect(input.value).toBeFalsy(); + }); }); }); diff --git a/src/components/UserPortal/ChatRoom/ChatRoom.tsx b/src/components/UserPortal/ChatRoom/ChatRoom.tsx index ac65a76199..d29de8b766 100644 --- a/src/components/UserPortal/ChatRoom/ChatRoom.tsx +++ b/src/components/UserPortal/ChatRoom/ChatRoom.tsx @@ -1,66 +1,392 @@ -import React from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import type { ChangeEvent } from 'react'; -import { Paper } from '@mui/material'; import SendIcon from '@mui/icons-material/Send'; import { Button, Form, InputGroup } from 'react-bootstrap'; import styles from './ChatRoom.module.css'; import PermContactCalendarIcon from '@mui/icons-material/PermContactCalendar'; import { useTranslation } from 'react-i18next'; +import { + DIRECT_CHAT_BY_ID, + GROUP_CHAT_BY_ID, +} from 'GraphQl/Queries/PlugInQueries'; +import { useMutation, useQuery, useSubscription } from '@apollo/client'; +import { + MESSAGE_SENT_TO_DIRECT_CHAT, + MESSAGE_SENT_TO_GROUP_CHAT, + SEND_MESSAGE_TO_DIRECT_CHAT, + SEND_MESSAGE_TO_GROUP_CHAT, +} from 'GraphQl/Mutations/OrganizationMutations'; +import useLocalStorage from 'utils/useLocalstorage'; +import Avatar from 'components/Avatar/Avatar'; interface InterfaceChatRoomProps { selectedContact: string; + selectedChatType: string; } +type DirectMessage = { + _id: string; + createdAt: Date; + sender: { + _id: string; + firstName: string; + lastName: string; + image: string; + }; + messageContent: string; + receiver: { + _id: string; + firstName: string; + lastName: string; + }; +}; + +type Chat = { + _id: string; + messages: { + _id: string; + createdAt: Date; + sender: { + _id: string; + firstName: string; + lastName: string; + image: string; + }; + messageContent: string; + receiver: { + _id: string; + firstName: string; + lastName: string; + }; + }[]; + users: { + _id: string; + firstName: string; + lastName: string; + email: string; + }[]; +}; + export default function chatRoom(props: InterfaceChatRoomProps): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'userChatRoom', }); + const isMountedRef = useRef(true); - const [newMessage, setNewMessage] = React.useState(''); + useEffect(() => { + return () => { + isMountedRef.current = false; + }; + }, []); + + const { getItem } = useLocalStorage(); + const userId = getItem('userId'); + const [chatTitle, setChatTitle] = useState(''); + const [chatSubtitle, setChatSubtitle] = useState(''); + const [newMessage, setNewMessage] = useState(''); + const [directChat, setDirectChat] = useState(); + const [groupChat, setGroupChat] = useState(); const handleNewMessageChange = (e: ChangeEvent): void => { const newMessageValue = e.target.value; - setNewMessage(newMessageValue); }; + const [sendMessageToDirectChat] = useMutation(SEND_MESSAGE_TO_DIRECT_CHAT, { + variables: { + chatId: props.selectedContact, + messageContent: newMessage, + }, + }); + + const [sendMessageToGroupChat] = useMutation(SEND_MESSAGE_TO_GROUP_CHAT, { + variables: { + chatId: props.selectedContact, + messageContent: newMessage, + }, + }); + + const { + data: chatData, + loading: chatLoading, + refetch: chatRefetch, + } = useQuery(DIRECT_CHAT_BY_ID, { + variables: { + id: props.selectedContact, + }, + }); + + const { + data: chatDataGorup, + loading: groupChatLoading, + refetch: groupChatRefresh, + } = useQuery(GROUP_CHAT_BY_ID, { + variables: { + id: props.selectedContact, + }, + }); + + useEffect(() => { + if (props.selectedChatType == 'direct') { + chatRefetch(); + } else if (props.selectedChatType == 'group') { + groupChatRefresh(); + } + }, [props.selectedContact]); + + useEffect(() => { + if ( + props.selectedChatType === 'direct' && + chatData && + isMountedRef.current + ) { + const directChatData = chatData.directChatById; + setDirectChat(directChatData); + const otherUser = directChatData.users.find( + (user: any) => user._id !== userId, + ); + if (otherUser) { + setChatTitle(`${otherUser.firstName} ${otherUser.lastName}`); + setChatSubtitle(otherUser.email); + } + } + }, [chatData]); + + useEffect(() => { + if ( + props.selectedChatType === 'group' && + chatDataGorup && + isMountedRef.current + ) { + const groupChatData = chatDataGorup.groupChatById; + setGroupChat(groupChatData); + setChatTitle(groupChatData.title); + setChatSubtitle(`${groupChatData.users.length} members`); + } + }, [chatDataGorup]); + + const sendMessage = async (): Promise => { + console.log(props.selectedChatType); + if (props.selectedChatType === 'direct') { + await sendMessageToDirectChat(); + await chatRefetch(); + } else if (props.selectedChatType === 'group') { + const data = await sendMessageToGroupChat(); + await groupChatRefresh(); + } + setNewMessage(''); + }; + + useSubscription(MESSAGE_SENT_TO_DIRECT_CHAT, { + variables: { + userId: userId, + }, + onData: (directMessageSubscriptionData) => { + console.log( + directMessageSubscriptionData?.data.data.messageSentToDirectChat + .directChatMessageBelongsTo['_id'], + props.selectedContact, + ); + if ( + directMessageSubscriptionData?.data.data.messageSentToDirectChat && + directMessageSubscriptionData?.data.data.messageSentToDirectChat + .directChatMessageBelongsTo['_id'] == props.selectedContact + ) { + const updatedChat = directChat + ? JSON.parse(JSON.stringify(directChat)) + : { messages: [] }; + updatedChat?.messages.push( + directMessageSubscriptionData?.data.data.messageSentToDirectChat, + ); + setDirectChat(updatedChat); + chatRefetch(); + } + }, + }); + + useSubscription(MESSAGE_SENT_TO_GROUP_CHAT, { + variables: { + userId: userId, + }, + onData: (groupMessageSubscriptionData) => { + if ( + groupMessageSubscriptionData?.data.data.messageSentToGroupChat && + groupMessageSubscriptionData?.data.data.messageSentToGroupChat + .groupChatMessageBelongsTo['_id'] == props.selectedContact + ) { + const updatedChat = groupChat + ? JSON.parse(JSON.stringify(groupChat)) + : { messages: [] }; + updatedChat?.messages.push( + groupMessageSubscriptionData.data.data.messageSentToGroupChat, + ); + setGroupChat(updatedChat); + groupChatRefresh({ + id: props.selectedContact, + }); + } else { + groupChatRefresh({ + id: groupMessageSubscriptionData?.data.data.messageSentToGroupChat + .groupChatMessageBelongsTo['_id'], + }); + groupChatRefresh({ + id: props.selectedContact, + }); + } + }, + }); + + useEffect(() => { + document + .getElementById('chat-area') + ?.lastElementChild?.scrollIntoView({ block: 'end' }); + }); + return ( -
    +
    {!props.selectedContact ? (
    -
    {t('selectContact')}
    +
    {t('selectContact')}
    ) : ( <> +
    +
    + +
    +

    {chatTitle}

    +

    + {chatSubtitle}{' '} + {props.selectedChatType == 'direct' ? '' : 'members'} +

    +
    +
    +
    - - My message - - - Other message - +
    + {!!( + directChat?.messages.length || groupChat?.messages.length + ) && ( +
    + {props.selectedChatType == 'direct' + ? directChat?.messages.map( + (message: DirectMessage, index: number) => { + return ( +
    +
    + + {message.messageContent} + + + {new Date( + message?.createdAt, + ).toLocaleTimeString('it-IT', { + hour: '2-digit', + minute: '2-digit', + })} + +
    +
    + ); + }, + ) + : groupChat?.messages.map( + (message: DirectMessage, index: number) => { + return ( +
    + {message.sender._id !== userId ? ( + message.sender?.image ? ( + {message.sender.image} + ) : ( + + ) + ) : ( + '' + )} +
    + {message.sender._id !== userId && ( +

    + {message.sender.firstName + + ' ' + + message.sender.lastName} +

    + )} + + {message.messageContent} + + + {new Date( + message?.createdAt, + ).toLocaleTimeString('it-IT', { + hour: '2-digit', + minute: '2-digit', + })} + +
    +
    + ); + }, + )} +
    + )} +
    -
    +
    - diff --git a/src/components/UserPortal/ContactCard/ContactCard.module.css b/src/components/UserPortal/ContactCard/ContactCard.module.css index d722a3a302..19d66596c9 100644 --- a/src/components/UserPortal/ContactCard/ContactCard.module.css +++ b/src/components/UserPortal/ContactCard/ContactCard.module.css @@ -1,31 +1,35 @@ .contact { display: flex; flex-direction: row; - padding: 10px 10px; + padding: 5px 10px; cursor: pointer; border-radius: 10px; - margin-bottom: 10px; - border: 2px solid #f5f5f5; + /* margin-bottom: 10px; */ + /* border: 2px solid #f5f5f5; */ } .contactImage { - width: 50px; - height: auto; + width: 45px !important; + height: auto !important; border-radius: 10px; + display: flex; + align-items: center; + justify-content: center; } .contactNameContainer { display: flex; flex-direction: column; padding: 0px 10px; + justify-content: center; } .grey { color: grey; } -.bgGrey { - background-color: #f5f5f5; +.bgGreen { + background-color: rgba(196, 255, 211, 0.3); } .bgWhite { diff --git a/src/components/UserPortal/ContactCard/ContactCard.test.tsx b/src/components/UserPortal/ContactCard/ContactCard.test.tsx index 7e7530bc58..7f55196bb0 100644 --- a/src/components/UserPortal/ContactCard/ContactCard.test.tsx +++ b/src/components/UserPortal/ContactCard/ContactCard.test.tsx @@ -23,13 +23,14 @@ async function wait(ms = 100): Promise { let props = { id: '1', - firstName: 'Noble', - lastName: 'Mittal', + title: 'Disha Talreja', + subtitle: 'disha@example.com', email: 'noble@mittal.com', image: '', selectedContact: '', + type: '', setSelectedContact: jest.fn(), - setSelectedContactName: jest.fn(), + setSelectedChatType: jest.fn(), }; describe('Testing ContactCard Component [User Portal]', () => { diff --git a/src/components/UserPortal/ContactCard/ContactCard.tsx b/src/components/UserPortal/ContactCard/ContactCard.tsx index be4247205b..69221e7583 100644 --- a/src/components/UserPortal/ContactCard/ContactCard.tsx +++ b/src/components/UserPortal/ContactCard/ContactCard.tsx @@ -4,21 +4,19 @@ import Avatar from 'components/Avatar/Avatar'; interface InterfaceContactCardProps { id: string; - firstName: string; - lastName: string; - email: string; + title: string; + subtitle: string; image: string; selectedContact: string; setSelectedContact: React.Dispatch>; - setSelectedContactName: React.Dispatch>; + type: string; + setSelectedChatType: React.Dispatch>; } function contactCard(props: InterfaceContactCardProps): JSX.Element { - const contactName = `${props.firstName} ${props.lastName}`; - const handleSelectedContactChange = (): void => { props.setSelectedContact(props.id); - props.setSelectedContactName(contactName); + props.setSelectedChatType(props.type); }; const [isSelected, setIsSelected] = React.useState( @@ -33,7 +31,7 @@ function contactCard(props: InterfaceContactCardProps): JSX.Element { <>
    ) : ( )}
    - {contactName} - {props.email} + {props.title} + {props.subtitle}
    diff --git a/src/components/UserPortal/CreateDirectChat/CreateDirectChat.module.css b/src/components/UserPortal/CreateDirectChat/CreateDirectChat.module.css new file mode 100644 index 0000000000..3795e402fa --- /dev/null +++ b/src/components/UserPortal/CreateDirectChat/CreateDirectChat.module.css @@ -0,0 +1,9 @@ +.userData { + height: 400px; + overflow-y: scroll; + overflow-x: hidden !important; +} + +.modalContent { + width: 530px; +} diff --git a/src/components/UserPortal/CreateDirectChat/CreateDirectChat.test.tsx b/src/components/UserPortal/CreateDirectChat/CreateDirectChat.test.tsx new file mode 100644 index 0000000000..b8c1dd86fb --- /dev/null +++ b/src/components/UserPortal/CreateDirectChat/CreateDirectChat.test.tsx @@ -0,0 +1,2204 @@ +import React from 'react'; +import { + act, + fireEvent, + render, + screen, + waitFor, +} from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider, useTranslation } from 'react-i18next'; + +import { + DIRECT_CHATS_LIST, + USERS_CONNECTION_LIST, +} from 'GraphQl/Queries/Queries'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import Chat from '../../../screens/UserPortal/Chat/Chat'; +import { + CREATE_DIRECT_CHAT, + MESSAGE_SENT_TO_DIRECT_CHAT, + MESSAGE_SENT_TO_GROUP_CHAT, +} from 'GraphQl/Mutations/OrganizationMutations'; +import { + DIRECT_CHAT_BY_ID, + GROUP_CHAT_BY_ID, + GROUP_CHAT_LIST, +} from 'GraphQl/Queries/PlugInQueries'; +import useLocalStorage from 'utils/useLocalstorage'; + +const { setItem } = useLocalStorage(); + +const MOCKS = [ + { + request: { + query: GROUP_CHAT_LIST, + variables: { + id: null, + }, + }, + result: { + data: { + groupChatsByUserId: [ + { + _id: '1', + creator: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + }, + messages: { + _id: '1', + createdAt: '', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@email.com', + }, + }, + title: 'Test GroupChat', + organization: { + _id: '1', + name: 'Test Org', + }, + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@email.com', + image: 'img', + }, + ], + }, + { + _id: '2', + creator: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + }, + messages: { + _id: '1', + createdAt: '', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@email.com', + }, + }, + title: 'Test GroupChat', + organization: { + _id: '1', + name: 'Test Org', + }, + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@email.com', + image: 'img', + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: GROUP_CHAT_LIST, + variables: { + id: '1', + }, + }, + result: { + data: { + groupChatsByUserId: [ + { + _id: '1', + creator: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + }, + messages: { + _id: '1', + createdAt: '', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@email.com', + }, + }, + title: 'Test GroupChat', + organization: { + _id: '1', + name: 'Test Org', + }, + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@email.com', + image: 'img', + }, + ], + }, + { + _id: '2', + creator: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + }, + messages: { + _id: '1', + createdAt: '', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@email.com', + }, + }, + title: 'Test GroupChat', + organization: { + _id: '1', + name: 'Test Org', + }, + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@email.com', + image: 'img', + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: GROUP_CHAT_LIST, + variables: { + id: null, + }, + }, + result: { + data: { + groupChatsByUserId: [ + { + _id: '1', + creator: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + }, + messages: { + _id: '1', + createdAt: '', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@email.com', + }, + }, + title: 'Test GroupChat', + organization: { + _id: '1', + name: 'Test Org', + }, + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@email.com', + image: 'img', + }, + ], + }, + { + _id: '1', + creator: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + }, + messages: { + _id: '1', + createdAt: '', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@email.com', + }, + }, + title: 'Test GroupChat', + organization: { + _id: '1', + name: 'Test Org', + }, + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@email.com', + image: 'img', + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: DIRECT_CHATS_LIST, + variables: { + id: null, + }, + }, + result: { + data: { + directChatsByUserID: [ + { + _id: '666c88dd92e995354d98527c', + creator: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + __typename: 'User', + }, + messages: [ + { + _id: '668930bae43ce54e6e302cf1', + createdAt: '2024-07-06T11:55:38.933Z', + messageContent: 'hJnkank', + receiver: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + __typename: 'User', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + __typename: 'User', + }, + __typename: 'DirectChatMessage', + }, + ], + organization: { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + __typename: 'Organization', + }, + users: [ + { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + image: null, + __typename: 'User', + }, + { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + image: null, + __typename: 'User', + }, + ], + __typename: 'DirectChat', + }, + { + _id: '666f09c892e995354d98a5ee', + creator: { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + __typename: 'User', + }, + messages: [ + { + _id: '6676932692e995354d98ab7f', + createdAt: '2024-06-22T09:02:30.776Z', + messageContent: 'hii', + receiver: { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + __typename: 'User', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + __typename: 'User', + }, + __typename: 'DirectChatMessage', + }, + ], + organization: { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + __typename: 'Organization', + }, + users: [ + { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + image: null, + __typename: 'User', + }, + { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + image: null, + __typename: 'User', + }, + ], + __typename: 'DirectChat', + }, + ], + }, + }, + }, + { + request: { + query: DIRECT_CHATS_LIST, + variables: { + id: '1', + }, + }, + result: { + data: { + directChatsByUserID: [ + { + _id: '666c88dd92e995354d98527c', + creator: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + __typename: 'User', + }, + messages: [ + { + _id: '668930bae43ce54e6e302cf1', + createdAt: '2024-07-06T11:55:38.933Z', + messageContent: 'hJnkank', + receiver: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + __typename: 'User', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + __typename: 'User', + }, + __typename: 'DirectChatMessage', + }, + ], + organization: { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + __typename: 'Organization', + }, + users: [ + { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + image: null, + __typename: 'User', + }, + { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + image: null, + __typename: 'User', + }, + ], + __typename: 'DirectChat', + }, + { + _id: '666f09c892e995354d98a5ee', + creator: { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + __typename: 'User', + }, + messages: [ + { + _id: '6676932692e995354d98ab7f', + createdAt: '2024-06-22T09:02:30.776Z', + messageContent: 'hii', + receiver: { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + __typename: 'User', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + __typename: 'User', + }, + __typename: 'DirectChatMessage', + }, + ], + organization: { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + __typename: 'Organization', + }, + users: [ + { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + image: null, + __typename: 'User', + }, + { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + image: null, + __typename: 'User', + }, + ], + __typename: 'DirectChat', + }, + ], + }, + }, + }, + { + request: { + query: DIRECT_CHATS_LIST, + variables: { + id: '1', + }, + }, + result: { + data: { + directChatsByUserID: [ + { + _id: '666c88dd92e995354d98527c', + creator: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + __typename: 'User', + }, + messages: [ + { + _id: '668930bae43ce54e6e302cf1', + createdAt: '2024-07-06T11:55:38.933Z', + messageContent: 'hJnkank', + receiver: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + __typename: 'User', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + __typename: 'User', + }, + __typename: 'DirectChatMessage', + }, + ], + organization: { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + __typename: 'Organization', + }, + users: [ + { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + image: null, + __typename: 'User', + }, + { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + image: null, + __typename: 'User', + }, + ], + __typename: 'DirectChat', + }, + { + _id: '666f09c892e995354d98a5ee', + creator: { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + __typename: 'User', + }, + messages: [ + { + _id: '6676932692e995354d98ab7f', + createdAt: '2024-06-22T09:02:30.776Z', + messageContent: 'hii', + receiver: { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + __typename: 'User', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + __typename: 'User', + }, + __typename: 'DirectChatMessage', + }, + ], + organization: { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + __typename: 'Organization', + }, + users: [ + { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + image: null, + __typename: 'User', + }, + { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + image: null, + __typename: 'User', + }, + ], + __typename: 'DirectChat', + }, + ], + }, + }, + }, + { + request: { + query: DIRECT_CHATS_LIST, + variables: { + id: '1', + }, + }, + result: { + data: { + directChatsByUserID: [ + { + _id: '666c88dd92e995354d98527c', + creator: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + __typename: 'User', + }, + messages: [ + { + _id: '668930bae43ce54e6e302cf1', + createdAt: '2024-07-06T11:55:38.933Z', + messageContent: 'hJnkank', + receiver: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + __typename: 'User', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + __typename: 'User', + }, + __typename: 'DirectChatMessage', + }, + ], + organization: { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + __typename: 'Organization', + }, + users: [ + { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + image: null, + __typename: 'User', + }, + { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + image: null, + __typename: 'User', + }, + ], + __typename: 'DirectChat', + }, + { + _id: '666f09c892e995354d98a5ee', + creator: { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + __typename: 'User', + }, + messages: [ + { + _id: '6676932692e995354d98ab7f', + createdAt: '2024-06-22T09:02:30.776Z', + messageContent: 'hii', + receiver: { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + __typename: 'User', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + __typename: 'User', + }, + __typename: 'DirectChatMessage', + }, + ], + organization: { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + __typename: 'Organization', + }, + users: [ + { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + image: null, + __typename: 'User', + }, + { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + image: null, + __typename: 'User', + }, + ], + __typename: 'DirectChat', + }, + ], + }, + }, + }, + { + request: { + query: DIRECT_CHATS_LIST, + variables: { + id: '', + }, + }, + result: { + data: { + directChatsByUserID: [ + { + _id: '666c88dd92e995354d98527c', + creator: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + __typename: 'User', + }, + messages: [ + { + _id: '668930bae43ce54e6e302cf1', + createdAt: '2024-07-06T11:55:38.933Z', + messageContent: 'hJnkank', + receiver: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + __typename: 'User', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + __typename: 'User', + }, + __typename: 'DirectChatMessage', + }, + ], + organization: { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + __typename: 'Organization', + }, + users: [ + { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + image: null, + __typename: 'User', + }, + { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + image: null, + __typename: 'User', + }, + ], + __typename: 'DirectChat', + }, + { + _id: '666f09c892e995354d98a5ee', + creator: { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + __typename: 'User', + }, + messages: [ + { + _id: '6676932692e995354d98ab7f', + createdAt: '2024-06-22T09:02:30.776Z', + messageContent: 'hii', + receiver: { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + __typename: 'User', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + __typename: 'User', + }, + __typename: 'DirectChatMessage', + }, + ], + organization: { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + __typename: 'Organization', + }, + users: [ + { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + image: null, + __typename: 'User', + }, + { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + image: null, + __typename: 'User', + }, + ], + __typename: 'DirectChat', + }, + ], + }, + }, + }, +]; + +const UserConnectionListMock = [ + { + request: { + query: USERS_CONNECTION_LIST, + variables: { + firstName_contains: '', + lastName_contains: '', + }, + }, + result: { + data: { + users: [ + { + user: { + firstName: 'Deanne', + lastName: 'Marks', + image: null, + _id: '6589389d2caa9d8d69087487', + email: 'testuser8@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + organizationsBlockedBy: [], + joinedOrganizations: [ + { + _id: '6537904485008f171cf29924', + name: 'Unity Foundation', + image: null, + address: { + city: 'Queens', + countryCode: 'US', + dependentLocality: 'Some Dependent Locality', + line1: '123 Coffee Street', + line2: 'Apartment 501', + postalCode: '11427', + sortingCode: 'ABC-133', + state: 'NYC', + __typename: 'Address', + }, + createdAt: '2023-04-13T05:16:52.827Z', + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + __typename: 'Organization', + }, + { + _id: '6637904485008f171cf29924', + name: 'Unity Foundation', + image: null, + address: { + city: 'Staten Island', + countryCode: 'US', + dependentLocality: 'Some Dependent Locality', + line1: '123 church Street', + line2: 'Apartment 499', + postalCode: '10301', + sortingCode: 'ABC-122', + state: 'NYC', + __typename: 'Address', + }, + createdAt: '2023-04-13T05:16:52.827Z', + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + __typename: 'Organization', + }, + { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + image: null, + address: { + city: 'Brooklyn', + countryCode: 'US', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Main Street', + line2: 'Apt 456', + postalCode: '10004', + sortingCode: 'ABC-789', + state: 'NY', + __typename: 'Address', + }, + createdAt: '2023-04-13T05:16:52.827Z', + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + __typename: 'Organization', + }, + { + _id: '6437904485008f171cf29924', + name: 'Unity Foundation', + image: null, + address: { + city: 'Bronx', + countryCode: 'US', + dependentLocality: 'Some Dependent Locality', + line1: '123 Random Street', + line2: 'Apartment 456', + postalCode: '10451', + sortingCode: 'ABC-123', + state: 'NYC', + __typename: 'Address', + }, + createdAt: '2023-04-13T05:16:52.827Z', + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + __typename: 'Organization', + }, + ], + __typename: 'User', + }, + appUserProfile: { + _id: '64378abd85308f171cf2993d', + adminFor: [], + isSuperAdmin: false, + createdOrganizations: [], + createdEvents: [], + eventAdmin: [], + __typename: 'AppUserProfile', + }, + __typename: 'UserData', + }, + ], + }, + }, + }, + { + request: { + query: USERS_CONNECTION_LIST, + variables: { + firstName_contains: 'Disha', + lastName_contains: '', + }, + }, + result: { + data: { + users: [ + { + user: { + firstName: 'Deanne', + lastName: 'Marks', + image: null, + _id: '6589389d2caa9d8d69087487', + email: 'testuser8@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + organizationsBlockedBy: [], + joinedOrganizations: [ + { + _id: '6537904485008f171cf29924', + name: 'Unity Foundation', + image: null, + address: { + city: 'Queens', + countryCode: 'US', + dependentLocality: 'Some Dependent Locality', + line1: '123 Coffee Street', + line2: 'Apartment 501', + postalCode: '11427', + sortingCode: 'ABC-133', + state: 'NYC', + __typename: 'Address', + }, + createdAt: '2023-04-13T05:16:52.827Z', + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + __typename: 'Organization', + }, + { + _id: '6637904485008f171cf29924', + name: 'Unity Foundation', + image: null, + address: { + city: 'Staten Island', + countryCode: 'US', + dependentLocality: 'Some Dependent Locality', + line1: '123 church Street', + line2: 'Apartment 499', + postalCode: '10301', + sortingCode: 'ABC-122', + state: 'NYC', + __typename: 'Address', + }, + createdAt: '2023-04-13T05:16:52.827Z', + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + __typename: 'Organization', + }, + { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + image: null, + address: { + city: 'Brooklyn', + countryCode: 'US', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Main Street', + line2: 'Apt 456', + postalCode: '10004', + sortingCode: 'ABC-789', + state: 'NY', + __typename: 'Address', + }, + createdAt: '2023-04-13T05:16:52.827Z', + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + __typename: 'Organization', + }, + { + _id: '6437904485008f171cf29924', + name: 'Unity Foundation', + image: null, + address: { + city: 'Bronx', + countryCode: 'US', + dependentLocality: 'Some Dependent Locality', + line1: '123 Random Street', + line2: 'Apartment 456', + postalCode: '10451', + sortingCode: 'ABC-123', + state: 'NYC', + __typename: 'Address', + }, + createdAt: '2023-04-13T05:16:52.827Z', + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + __typename: 'Organization', + }, + ], + __typename: 'User', + }, + appUserProfile: { + _id: '64378abd85308f171cf2993d', + adminFor: [], + isSuperAdmin: false, + createdOrganizations: [], + createdEvents: [], + eventAdmin: [], + __typename: 'AppUserProfile', + }, + __typename: 'UserData', + }, + ], + }, + }, + }, + { + request: { + query: USERS_CONNECTION_LIST, + variables: { + firstName_contains: '', + lastName_contains: '', + }, + }, + result: { + data: { + users: { + user: [ + { + firstName: 'Disha', + lastName: 'Talreja', + image: 'img', + _id: '1', + email: 'disha@email.com', + createdAt: '', + appUserProfile: { + _id: '12', + isSuperAdmin: 'false', + createdOrganizations: { + _id: '345678', + }, + createdEvents: { + _id: '34567890', + }, + }, + organizationsBlockedBy: [], + joinedOrganizations: [], + }, + { + firstName: 'Disha', + lastName: 'Talreja', + image: 'img', + _id: '1', + email: 'disha@email.com', + createdAt: '', + appUserProfile: { + _id: '12', + isSuperAdmin: 'false', + createdOrganizations: { + _id: '345678', + }, + createdEvents: { + _id: '34567890', + }, + }, + organizationsBlockedBy: [], + joinedOrganizations: [], + }, + { + firstName: 'Disha', + lastName: 'Talreja', + image: 'img', + _id: '1', + email: 'disha@email.com', + createdAt: '', + appUserProfile: { + _id: '12', + isSuperAdmin: 'false', + createdOrganizations: { + _id: '345678', + }, + createdEvents: { + _id: '34567890', + }, + }, + organizationsBlockedBy: [], + joinedOrganizations: [], + }, + ], + }, + }, + }, + }, +]; + +const MESSAGE_SENT_TO_GROUP_CHAT_MOCK = [ + { + request: { + query: MESSAGE_SENT_TO_GROUP_CHAT, + variables: { + userId: null, + }, + }, + result: { + data: { + messageSentToGroupChat: { + _id: '668ec1f1364e03ac47a151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, + { + request: { + query: MESSAGE_SENT_TO_GROUP_CHAT, + variables: { + userId: '2', + }, + }, + result: { + data: { + messageSentToGroupChat: { + _id: '668ec1f1df364e03ac47a151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, + { + request: { + query: MESSAGE_SENT_TO_GROUP_CHAT, + variables: { + userId: '1', + }, + }, + result: { + data: { + messageSentToGroupChat: { + _id: '668ec1f13603ac4697a151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, +]; + +const MESSAGE_SENT_TO_DIRECT_CHAT_MOCK = [ + { + request: { + query: MESSAGE_SENT_TO_DIRECT_CHAT, + variables: { + userId: '1', + }, + }, + result: { + data: { + messageSentToDirectChat: { + _id: '668ec1f1364e03ac4697a151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + receiver: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + image: '', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, + { + request: { + query: MESSAGE_SENT_TO_DIRECT_CHAT, + variables: { + userId: '2', + }, + }, + result: { + data: { + messageSentToDirectChat: { + _id: '668ec1f1364e03ac4697vgfa151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + receiver: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + image: '', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, + { + request: { + query: MESSAGE_SENT_TO_DIRECT_CHAT, + variables: { + userId: null, + }, + }, + result: { + data: { + messageSentToDirectChat: { + _id: '6ec1f1364e03ac4697a151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + receiver: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + image: '', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, +]; + +const DIRECT_CHAT_BY_ID_QUERY_MOCK = [ + { + request: { + query: DIRECT_CHAT_BY_ID, + variables: { + id: '1', + }, + }, + result: { + data: { + directChatById: { + _id: '1', + createdAt: '2345678903456', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + receiver: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: DIRECT_CHAT_BY_ID, + variables: { + id: '1', + }, + }, + result: { + data: { + directChatById: { + _id: '1', + createdAt: '2345678903456', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + receiver: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: DIRECT_CHAT_BY_ID, + variables: { + id: '', + }, + }, + result: { + data: { + directChatById: { + _id: '1', + createdAt: '2345678903456', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + receiver: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: DIRECT_CHAT_BY_ID, + variables: { + id: '2', + }, + }, + result: { + data: { + directChatById: { + _id: '65844efc814dd4003db811c4', + createdAt: '2345678903456', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + receiver: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: DIRECT_CHAT_BY_ID, + variables: { + id: null, + }, + }, + result: { + data: { + directChatById: { + _id: '65844efc814dd4003db811c4', + createdAt: '2345678903456', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + receiver: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + ], + }, + }, + }, + }, +]; + +const GROUP_CHAT_BY_ID_QUERY_MOCK = [ + { + request: { + query: GROUP_CHAT_BY_ID, + variables: { + id: '1', + }, + }, + result: { + data: { + groupChatById: { + _id: '65844efc814dd4003db811c4', + createdAt: '2345678903456', + title: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: GROUP_CHAT_BY_ID, + variables: { + id: '1', + }, + }, + result: { + data: { + groupChatById: { + _id: '65844efc814dd4003db811c4', + createdAt: '2345678903456', + title: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: GROUP_CHAT_BY_ID, + variables: { + id: '', + }, + }, + result: { + data: { + groupChatById: { + _id: '1', + createdAt: '2345678903456', + title: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: GROUP_CHAT_BY_ID, + variables: { + id: '2', + }, + }, + result: { + data: { + groupChatById: { + _id: '65844efc814dd4003db811c4', + createdAt: '2345678903456', + title: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: GROUP_CHAT_BY_ID, + variables: { + id: null, + }, + }, + result: { + data: { + groupChatById: { + _id: '65844efc814dd4003db811c4', + createdAt: '2345678903456', + title: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + }, + }, + }, +]; + +const CREATE_DIRECT_CHAT_MOCK = { + request: { + query: CREATE_DIRECT_CHAT, + variables: { + userIds: ['1', '6589389d2caa9d8d69087487'], + organizationId: undefined, + }, + }, + result: { + data: { + createDirectChat: { + _id: '669394c180e96b740ba1c0ce', + __typename: 'DirectChat', + }, + }, + }, +}; + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Testing Create Direct Chat Modal [User Portal]', () => { + window.HTMLElement.prototype.scrollIntoView = jest.fn(); + + Object.defineProperty(window, 'matchMedia', { + writable: true, + value: jest.fn().mockImplementation((query) => ({ + matches: false, + media: query, + onchange: null, + addListener: jest.fn(), // Deprecated + removeListener: jest.fn(), // Deprecated + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn(), + })), + }); + + test('Test open and close create new direct chat modal', async () => { + const mock = [ + ...GROUP_CHAT_BY_ID_QUERY_MOCK, + ...DIRECT_CHAT_BY_ID_QUERY_MOCK, + ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, + ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ...UserConnectionListMock, + ...MOCKS, + ]; + render( + + + + + + + + + , + ); + + await wait(); + + const dropdown = await screen.findByTestId('dropdown'); + expect(dropdown).toBeInTheDocument(); + fireEvent.click(dropdown); + const newDirectChatBtn = await screen.findByTestId('newDirectChat'); + expect(newDirectChatBtn).toBeInTheDocument(); + fireEvent.click(newDirectChatBtn); + + const submitBtn = await screen.findByTestId('submitBtn'); + expect(submitBtn).toBeInTheDocument(); + + const searchInput = (await screen.findByTestId( + 'searchUser', + )) as HTMLInputElement; + expect(searchInput).toBeInTheDocument(); + + fireEvent.change(searchInput, { target: { value: 'Disha' } }); + + expect(searchInput.value).toBe('Disha'); + + fireEvent.click(submitBtn); + + const closeButton = screen.getByRole('button', { name: /close/i }); + expect(closeButton).toBeInTheDocument(); + + fireEvent.click(closeButton); + }); + + test('Test create new direct chat', async () => { + setItem('userId', '1'); + const mock = [ + CREATE_DIRECT_CHAT_MOCK, + ...GROUP_CHAT_BY_ID_QUERY_MOCK, + ...DIRECT_CHAT_BY_ID_QUERY_MOCK, + ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, + ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ...UserConnectionListMock, + ...MOCKS, + ]; + render( + + + + + + + + + , + ); + + await wait(); + + const dropdown = await screen.findByTestId('dropdown'); + expect(dropdown).toBeInTheDocument(); + fireEvent.click(dropdown); + const newDirectChatBtn = await screen.findByTestId('newDirectChat'); + expect(newDirectChatBtn).toBeInTheDocument(); + fireEvent.click(newDirectChatBtn); + + const addBtn = await screen.findAllByTestId('addBtn'); + waitFor(() => { + expect(addBtn[0]).toBeInTheDocument(); + }); + + fireEvent.click(addBtn[0]); + + const closeButton = screen.getByRole('button', { name: /close/i }); + expect(closeButton).toBeInTheDocument(); + + fireEvent.click(closeButton); + }); +}); diff --git a/src/components/UserPortal/CreateDirectChat/CreateDirectChat.tsx b/src/components/UserPortal/CreateDirectChat/CreateDirectChat.tsx new file mode 100644 index 0000000000..565dfd422f --- /dev/null +++ b/src/components/UserPortal/CreateDirectChat/CreateDirectChat.tsx @@ -0,0 +1,202 @@ +import { Paper, TableBody } from '@mui/material'; +import React, { useState } from 'react'; +import { Button, Form, Modal } from 'react-bootstrap'; +import styles from './CreateDirectChat.module.css'; +import type { ApolloQueryResult } from '@apollo/client'; +import { useMutation, useQuery } from '@apollo/client'; +import useLocalStorage from 'utils/useLocalstorage'; +import { CREATE_DIRECT_CHAT } from 'GraphQl/Mutations/OrganizationMutations'; +import Table from '@mui/material/Table'; +import TableCell, { tableCellClasses } from '@mui/material/TableCell'; +import TableContainer from '@mui/material/TableContainer'; +import TableHead from '@mui/material/TableHead'; +import TableRow from '@mui/material/TableRow'; +import { styled } from '@mui/material/styles'; +import type { InterfaceQueryUserListItem } from 'utils/interfaces'; +import { USERS_CONNECTION_LIST } from 'GraphQl/Queries/Queries'; +import Loader from 'components/Loader/Loader'; +import { Search } from '@mui/icons-material'; +import { useTranslation } from 'react-i18next'; +import { useParams } from 'react-router-dom'; + +interface InterfaceCreateDirectChatProps { + toggleCreateDirectChatModal: () => void; + createDirectChatModalisOpen: boolean; + contactRefetch: ( + variables?: + | Partial<{ + id: any; + }> + | undefined, + ) => Promise>; +} + +const StyledTableCell = styled(TableCell)(({ theme }) => ({ + [`&.${tableCellClasses.head}`]: { + backgroundColor: ['#31bb6b', '!important'], + color: theme.palette.common.white, + }, + [`&.${tableCellClasses.body}`]: { + fontSize: 14, + }, +})); + +const StyledTableRow = styled(TableRow)(() => ({ + '&:last-child td, &:last-child th': { + border: 0, + }, +})); + +const { getItem } = useLocalStorage(); + +export default function groupChat({ + toggleCreateDirectChatModal, + createDirectChatModalisOpen, + contactRefetch, +}: InterfaceCreateDirectChatProps): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'userChat', + }); + + const { orgId: organizationId } = useParams(); + + const userId: string | null = getItem('userId'); + + const [userName, setUserName] = useState(''); + + const [createDirectChat] = useMutation(CREATE_DIRECT_CHAT); + + const handleCreateDirectChat = async (id: string): Promise => { + console.log(organizationId); + await createDirectChat({ + variables: { + organizationId, + userIds: [userId, id], + }, + }); + contactRefetch(); + toggleCreateDirectChatModal(); + }; + + const { + data: allUsersData, + loading: allUsersLoading, + refetch: allUsersRefetch, + } = useQuery(USERS_CONNECTION_LIST, { + variables: { + firstName_contains: '', + lastName_contains: '', + }, + }); + + const handleUserModalSearchChange = (e: React.FormEvent): void => { + e.preventDefault(); + /* istanbul ignore next */ + const [firstName, lastName] = userName.split(' '); + + const newFilterData = { + firstName_contains: firstName || '', + lastName_contains: lastName || '', + }; + + allUsersRefetch({ + ...newFilterData, + }); + }; + + return ( + <> + + + {'Chat'} + + + {allUsersLoading ? ( + <> + + + ) : ( + <> +
    +
    + { + const { value } = e.target; + setUserName(value); + }} + /> + + +
    + +
    Action
    {user.email} {user.organizationsBlockedBy.some( - (spam: any) => spam._id === currentUrl, + (spam) => spam._id === currentUrl, ) ? (
    + + + # + {'user'} + {'Chat'} + + + + {allUsersData && + allUsersData.users.length > 0 && + allUsersData.users.map( + ( + userDetails: InterfaceQueryUserListItem, + index: number, + ) => ( + + + {index + 1} + + + {userDetails.user.firstName + + ' ' + + userDetails.user.lastName} +
    + {userDetails.user.email} +
    + + + +
    + ), + )} +
    +
    + + + )} + +
    + + ); +} diff --git a/src/components/UserPortal/CreateGroupChat/CreateGroupChat.module.css b/src/components/UserPortal/CreateGroupChat/CreateGroupChat.module.css new file mode 100644 index 0000000000..3795e402fa --- /dev/null +++ b/src/components/UserPortal/CreateGroupChat/CreateGroupChat.module.css @@ -0,0 +1,9 @@ +.userData { + height: 400px; + overflow-y: scroll; + overflow-x: hidden !important; +} + +.modalContent { + width: 530px; +} diff --git a/src/components/UserPortal/CreateGroupChat/CreateGroupChat.test.tsx b/src/components/UserPortal/CreateGroupChat/CreateGroupChat.test.tsx new file mode 100644 index 0000000000..3898653f47 --- /dev/null +++ b/src/components/UserPortal/CreateGroupChat/CreateGroupChat.test.tsx @@ -0,0 +1,2746 @@ +import React from 'react'; +import { + act, + fireEvent, + render, + screen, + waitFor, +} from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider } from 'react-i18next'; + +import { + DIRECT_CHATS_LIST, + USERS_CONNECTION_LIST, + USER_JOINED_ORGANIZATIONS, +} from 'GraphQl/Queries/Queries'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import Chat from '../../../screens/UserPortal/Chat/Chat'; +import { + CREATE_GROUP_CHAT, + MESSAGE_SENT_TO_DIRECT_CHAT, + MESSAGE_SENT_TO_GROUP_CHAT, +} from 'GraphQl/Mutations/OrganizationMutations'; +import { + DIRECT_CHAT_BY_ID, + GROUP_CHAT_BY_ID, + GROUP_CHAT_LIST, +} from 'GraphQl/Queries/PlugInQueries'; +import useLocalStorage from 'utils/useLocalstorage'; + +const { setItem } = useLocalStorage(); + +const MOCKS = [ + { + request: { + query: GROUP_CHAT_LIST, + variables: { + id: null, + }, + }, + result: { + data: { + groupChatsByUserId: [ + { + _id: '1', + creator: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + }, + messages: { + _id: '1', + createdAt: '', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@email.com', + }, + }, + title: 'Test GroupChat', + organization: { + _id: '1', + name: 'Test Org', + }, + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@email.com', + image: 'img', + }, + ], + }, + { + _id: '2', + creator: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + }, + messages: { + _id: '1', + createdAt: '', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@email.com', + }, + }, + title: 'Test GroupChat', + organization: { + _id: '1', + name: 'Test Org', + }, + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@email.com', + image: 'img', + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: GROUP_CHAT_LIST, + variables: { + id: '1', + }, + }, + result: { + data: { + groupChatsByUserId: [ + { + _id: '1', + creator: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + }, + messages: { + _id: '1', + createdAt: '', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@email.com', + }, + }, + title: 'Test GroupChat', + organization: { + _id: '1', + name: 'Test Org', + }, + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@email.com', + image: 'img', + }, + ], + }, + { + _id: '2', + creator: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + }, + messages: { + _id: '1', + createdAt: '', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@email.com', + }, + }, + title: 'Test GroupChat', + organization: { + _id: '1', + name: 'Test Org', + }, + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@email.com', + image: 'img', + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: GROUP_CHAT_LIST, + variables: { + id: null, + }, + }, + result: { + data: { + groupChatsByUserId: [ + { + _id: '1', + creator: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + }, + messages: { + _id: '1', + createdAt: '', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@email.com', + }, + }, + title: 'Test GroupChat', + organization: { + _id: '1', + name: 'Test Org', + }, + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@email.com', + image: 'img', + }, + ], + }, + { + _id: '2', + creator: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + }, + messages: { + _id: '1', + createdAt: '', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@email.com', + }, + }, + title: 'Test GroupChat', + organization: { + _id: '1', + name: 'Test Org', + }, + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@email.com', + image: 'img', + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: DIRECT_CHATS_LIST, + variables: { + id: null, + }, + }, + result: { + data: { + directChatsByUserID: [ + { + _id: '666c88dd92e995354d98527c', + creator: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + __typename: 'User', + }, + messages: [ + { + _id: '668930bae43ce54e6e302cf1', + createdAt: '2024-07-06T11:55:38.933Z', + messageContent: 'hJnkank', + receiver: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + __typename: 'User', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + __typename: 'User', + }, + __typename: 'DirectChatMessage', + }, + ], + organization: { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + __typename: 'Organization', + }, + users: [ + { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + image: null, + __typename: 'User', + }, + { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + image: null, + __typename: 'User', + }, + ], + __typename: 'DirectChat', + }, + { + _id: '666f09c892e995354d98a5ee', + creator: { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + __typename: 'User', + }, + messages: [ + { + _id: '6676932692e995354d98ab7f', + createdAt: '2024-06-22T09:02:30.776Z', + messageContent: 'hii', + receiver: { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + __typename: 'User', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + __typename: 'User', + }, + __typename: 'DirectChatMessage', + }, + ], + organization: { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + __typename: 'Organization', + }, + users: [ + { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + image: null, + __typename: 'User', + }, + { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + image: null, + __typename: 'User', + }, + ], + __typename: 'DirectChat', + }, + ], + }, + }, + }, + { + request: { + query: DIRECT_CHATS_LIST, + variables: { + id: '1', + }, + }, + result: { + data: { + directChatsByUserID: [ + { + _id: '666c88dd92e995354d98527c', + creator: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + __typename: 'User', + }, + messages: [ + { + _id: '668930bae43ce54e6e302cf1', + createdAt: '2024-07-06T11:55:38.933Z', + messageContent: 'hJnkank', + receiver: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + __typename: 'User', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + __typename: 'User', + }, + __typename: 'DirectChatMessage', + }, + ], + organization: { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + __typename: 'Organization', + }, + users: [ + { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + image: null, + __typename: 'User', + }, + { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + image: null, + __typename: 'User', + }, + ], + __typename: 'DirectChat', + }, + { + _id: '666f09c892e995354d98a5ee', + creator: { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + __typename: 'User', + }, + messages: [ + { + _id: '6676932692e995354d98ab7f', + createdAt: '2024-06-22T09:02:30.776Z', + messageContent: 'hii', + receiver: { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + __typename: 'User', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + __typename: 'User', + }, + __typename: 'DirectChatMessage', + }, + ], + organization: { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + __typename: 'Organization', + }, + users: [ + { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + image: null, + __typename: 'User', + }, + { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + image: null, + __typename: 'User', + }, + ], + __typename: 'DirectChat', + }, + ], + }, + }, + }, + { + request: { + query: DIRECT_CHATS_LIST, + variables: { + id: '1', + }, + }, + result: { + data: { + directChatsByUserID: [ + { + _id: '666c88dd92e995354d98527c', + creator: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + __typename: 'User', + }, + messages: [ + { + _id: '668930bae43ce54e6e302cf1', + createdAt: '2024-07-06T11:55:38.933Z', + messageContent: 'hJnkank', + receiver: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + __typename: 'User', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + __typename: 'User', + }, + __typename: 'DirectChatMessage', + }, + ], + organization: { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + __typename: 'Organization', + }, + users: [ + { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + image: null, + __typename: 'User', + }, + { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + image: null, + __typename: 'User', + }, + ], + __typename: 'DirectChat', + }, + { + _id: '666f09c892e995354d98a5ee', + creator: { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + __typename: 'User', + }, + messages: [ + { + _id: '6676932692e995354d98ab7f', + createdAt: '2024-06-22T09:02:30.776Z', + messageContent: 'hii', + receiver: { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + __typename: 'User', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + __typename: 'User', + }, + __typename: 'DirectChatMessage', + }, + ], + organization: { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + __typename: 'Organization', + }, + users: [ + { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + image: null, + __typename: 'User', + }, + { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + image: null, + __typename: 'User', + }, + ], + __typename: 'DirectChat', + }, + ], + }, + }, + }, + { + request: { + query: DIRECT_CHATS_LIST, + variables: { + id: '1', + }, + }, + result: { + data: { + directChatsByUserID: [ + { + _id: '666c88dd92e995354d98527c', + creator: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + __typename: 'User', + }, + messages: [ + { + _id: '668930bae43ce54e6e302cf1', + createdAt: '2024-07-06T11:55:38.933Z', + messageContent: 'hJnkank', + receiver: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + __typename: 'User', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + __typename: 'User', + }, + __typename: 'DirectChatMessage', + }, + ], + organization: { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + __typename: 'Organization', + }, + users: [ + { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + image: null, + __typename: 'User', + }, + { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + image: null, + __typename: 'User', + }, + ], + __typename: 'DirectChat', + }, + { + _id: '666f09c892e995354d98a5ee', + creator: { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + __typename: 'User', + }, + messages: [ + { + _id: '6676932692e995354d98ab7f', + createdAt: '2024-06-22T09:02:30.776Z', + messageContent: 'hii', + receiver: { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + __typename: 'User', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + __typename: 'User', + }, + __typename: 'DirectChatMessage', + }, + ], + organization: { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + __typename: 'Organization', + }, + users: [ + { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + image: null, + __typename: 'User', + }, + { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + image: null, + __typename: 'User', + }, + ], + __typename: 'DirectChat', + }, + ], + }, + }, + }, + { + request: { + query: DIRECT_CHATS_LIST, + variables: { + id: '', + }, + }, + result: { + data: { + directChatsByUserID: [ + { + _id: '666c88dd92e995354d98527c', + creator: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + __typename: 'User', + }, + messages: [ + { + _id: '668930bae43ce54e6e302cf1', + createdAt: '2024-07-06T11:55:38.933Z', + messageContent: 'hJnkank', + receiver: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + __typename: 'User', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + __typename: 'User', + }, + __typename: 'DirectChatMessage', + }, + ], + organization: { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + __typename: 'Organization', + }, + users: [ + { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + image: null, + __typename: 'User', + }, + { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + image: null, + __typename: 'User', + }, + ], + __typename: 'DirectChat', + }, + { + _id: '666f09c892e995354d98a5ee', + creator: { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + __typename: 'User', + }, + messages: [ + { + _id: '6676932692e995354d98ab7f', + createdAt: '2024-06-22T09:02:30.776Z', + messageContent: 'hii', + receiver: { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + __typename: 'User', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + __typename: 'User', + }, + __typename: 'DirectChatMessage', + }, + ], + organization: { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + __typename: 'Organization', + }, + users: [ + { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + image: null, + __typename: 'User', + }, + { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + image: null, + __typename: 'User', + }, + ], + __typename: 'DirectChat', + }, + ], + }, + }, + }, +]; + +const USER_JOINED_ORG_MOCK = [ + { + request: { + query: USER_JOINED_ORGANIZATIONS, + variables: { + id: '1', + }, + }, + result: { + data: { + users: [ + { + user: { + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + name: 'Test Org 1', + image: '', + description: 'New Desc', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + createdAt: '1234567890', + userRegistrationRequired: true, + creator: { + __typename: 'User', + firstName: 'John', + lastName: 'Doe', + }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + }, + ], + }, + }, + ], + }, + }, + }, + { + request: { + query: USER_JOINED_ORGANIZATIONS, + variables: { + id: '1', + }, + }, + result: { + data: { + users: [ + { + user: { + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + name: 'Any Organization', + image: '', + description: 'New Desc', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + createdAt: '1234567890', + userRegistrationRequired: true, + creator: { + __typename: 'User', + firstName: 'John', + lastName: 'Doe', + }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + }, + ], + }, + }, + ], + }, + }, + }, + { + request: { + query: USER_JOINED_ORGANIZATIONS, + variables: { + id: '1', + }, + }, + result: { + data: { + users: [ + { + user: { + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + name: 'Any Organization', + image: '', + description: 'New Desc', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + createdAt: '1234567890', + userRegistrationRequired: true, + creator: { + __typename: 'User', + firstName: 'John', + lastName: 'Doe', + }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + }, + ], + }, + }, + ], + }, + }, + }, + { + request: { + query: USER_JOINED_ORGANIZATIONS, + variables: { + id: null, + }, + }, + result: { + data: { + users: [ + { + user: { + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + name: 'Any Organization', + image: '', + description: 'New Desc', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + createdAt: '1234567890', + userRegistrationRequired: true, + creator: { + __typename: 'User', + firstName: 'John', + lastName: 'Doe', + }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + }, + ], + }, + }, + ], + }, + }, + }, + { + request: { + query: USER_JOINED_ORGANIZATIONS, + variables: { + id: null, + }, + }, + result: { + data: { + users: [ + { + user: { + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + name: 'Any Organization', + image: '', + description: 'New Desc', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + createdAt: '1234567890', + userRegistrationRequired: true, + creator: { + __typename: 'User', + firstName: 'John', + lastName: 'Doe', + }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + }, + ], + }, + }, + ], + }, + }, + }, + { + request: { + query: USER_JOINED_ORGANIZATIONS, + variables: { + id: null, + }, + }, + result: { + data: { + users: [ + { + user: { + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + name: 'Any Organization', + image: '', + description: 'New Desc', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + createdAt: '1234567890', + userRegistrationRequired: true, + creator: { + __typename: 'User', + firstName: 'John', + lastName: 'Doe', + }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + }, + ], + }, + }, + ], + }, + }, + }, +]; + +const UserConnectionListMock = [ + { + request: { + query: USERS_CONNECTION_LIST, + variables: { + firstName_contains: '', + lastName_contains: '', + }, + }, + result: { + data: { + users: [ + { + user: { + firstName: 'Deanne', + lastName: 'Marks', + image: null, + _id: '6589389d2caa9d8d69087487', + email: 'testuser8@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + organizationsBlockedBy: [], + joinedOrganizations: [ + { + _id: '6537904485008f171cf29924', + name: 'Unity Foundation', + image: null, + address: { + city: 'Queens', + countryCode: 'US', + dependentLocality: 'Some Dependent Locality', + line1: '123 Coffee Street', + line2: 'Apartment 501', + postalCode: '11427', + sortingCode: 'ABC-133', + state: 'NYC', + __typename: 'Address', + }, + createdAt: '2023-04-13T05:16:52.827Z', + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + __typename: 'Organization', + }, + { + _id: '6637904485008f171cf29924', + name: 'Unity Foundation', + image: null, + address: { + city: 'Staten Island', + countryCode: 'US', + dependentLocality: 'Some Dependent Locality', + line1: '123 church Street', + line2: 'Apartment 499', + postalCode: '10301', + sortingCode: 'ABC-122', + state: 'NYC', + __typename: 'Address', + }, + createdAt: '2023-04-13T05:16:52.827Z', + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + __typename: 'Organization', + }, + { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + image: null, + address: { + city: 'Brooklyn', + countryCode: 'US', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Main Street', + line2: 'Apt 456', + postalCode: '10004', + sortingCode: 'ABC-789', + state: 'NY', + __typename: 'Address', + }, + createdAt: '2023-04-13T05:16:52.827Z', + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + __typename: 'Organization', + }, + { + _id: '6437904485008f171cf29924', + name: 'Unity Foundation', + image: null, + address: { + city: 'Bronx', + countryCode: 'US', + dependentLocality: 'Some Dependent Locality', + line1: '123 Random Street', + line2: 'Apartment 456', + postalCode: '10451', + sortingCode: 'ABC-123', + state: 'NYC', + __typename: 'Address', + }, + createdAt: '2023-04-13T05:16:52.827Z', + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + __typename: 'Organization', + }, + ], + __typename: 'User', + }, + appUserProfile: { + _id: '64378abd85308f171cf2993d', + adminFor: [], + isSuperAdmin: false, + createdOrganizations: [], + createdEvents: [], + eventAdmin: [], + __typename: 'AppUserProfile', + }, + __typename: 'UserData', + }, + ], + }, + }, + }, + { + request: { + query: USERS_CONNECTION_LIST, + variables: { + firstName_contains: 'Disha', + lastName_contains: '', + }, + }, + result: { + data: { + users: [ + { + user: { + firstName: 'Deanne', + lastName: 'Marks', + image: null, + _id: '6589389d2caa9d8d69087487', + email: 'testuser8@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + organizationsBlockedBy: [], + joinedOrganizations: [ + { + _id: '6537904485008f171cf29924', + name: 'Unity Foundation', + image: null, + address: { + city: 'Queens', + countryCode: 'US', + dependentLocality: 'Some Dependent Locality', + line1: '123 Coffee Street', + line2: 'Apartment 501', + postalCode: '11427', + sortingCode: 'ABC-133', + state: 'NYC', + __typename: 'Address', + }, + createdAt: '2023-04-13T05:16:52.827Z', + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + __typename: 'Organization', + }, + { + _id: '6637904485008f171cf29924', + name: 'Unity Foundation', + image: null, + address: { + city: 'Staten Island', + countryCode: 'US', + dependentLocality: 'Some Dependent Locality', + line1: '123 church Street', + line2: 'Apartment 499', + postalCode: '10301', + sortingCode: 'ABC-122', + state: 'NYC', + __typename: 'Address', + }, + createdAt: '2023-04-13T05:16:52.827Z', + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + __typename: 'Organization', + }, + { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + image: null, + address: { + city: 'Brooklyn', + countryCode: 'US', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Main Street', + line2: 'Apt 456', + postalCode: '10004', + sortingCode: 'ABC-789', + state: 'NY', + __typename: 'Address', + }, + createdAt: '2023-04-13T05:16:52.827Z', + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + __typename: 'Organization', + }, + { + _id: '6437904485008f171cf29924', + name: 'Unity Foundation', + image: null, + address: { + city: 'Bronx', + countryCode: 'US', + dependentLocality: 'Some Dependent Locality', + line1: '123 Random Street', + line2: 'Apartment 456', + postalCode: '10451', + sortingCode: 'ABC-123', + state: 'NYC', + __typename: 'Address', + }, + createdAt: '2023-04-13T05:16:52.827Z', + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + __typename: 'Organization', + }, + ], + __typename: 'User', + }, + appUserProfile: { + _id: '64378abd85308f171cf2993d', + adminFor: [], + isSuperAdmin: false, + createdOrganizations: [], + createdEvents: [], + eventAdmin: [], + __typename: 'AppUserProfile', + }, + __typename: 'UserData', + }, + ], + }, + }, + }, + { + request: { + query: USERS_CONNECTION_LIST, + variables: { + firstName_contains: '', + lastName_contains: '', + }, + }, + result: { + data: { + users: { + user: [ + { + firstName: 'Disha', + lastName: 'Talreja', + image: 'img', + _id: '1', + email: 'disha@email.com', + createdAt: '', + appUserProfile: { + _id: '12', + isSuperAdmin: 'false', + createdOrganizations: { + _id: '345678', + }, + createdEvents: { + _id: '34567890', + }, + }, + organizationsBlockedBy: [], + joinedOrganizations: [], + }, + { + firstName: 'Disha', + lastName: 'Talreja', + image: 'img', + _id: '2', + email: 'disha@email.com', + createdAt: '', + appUserProfile: { + _id: '12', + isSuperAdmin: 'false', + createdOrganizations: { + _id: '345678', + }, + createdEvents: { + _id: '34567890', + }, + }, + organizationsBlockedBy: [], + joinedOrganizations: [], + }, + { + firstName: 'Disha', + lastName: 'Talreja', + image: 'img', + _id: '3', + email: 'disha@email.com', + createdAt: '', + appUserProfile: { + _id: '12', + isSuperAdmin: 'false', + createdOrganizations: { + _id: '345678', + }, + createdEvents: { + _id: '34567890', + }, + }, + organizationsBlockedBy: [], + joinedOrganizations: [], + }, + ], + }, + }, + }, + }, +]; + +const MESSAGE_SENT_TO_GROUP_CHAT_MOCK = [ + { + request: { + query: MESSAGE_SENT_TO_GROUP_CHAT, + variables: { + userId: null, + }, + }, + result: { + data: { + messageSentToGroupChat: { + _id: '668ec1f1364e03ac47a151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, + { + request: { + query: MESSAGE_SENT_TO_GROUP_CHAT, + variables: { + userId: '2', + }, + }, + result: { + data: { + messageSentToGroupChat: { + _id: '668ec1f1df364e03ac47a151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, + { + request: { + query: MESSAGE_SENT_TO_GROUP_CHAT, + variables: { + userId: '1', + }, + }, + result: { + data: { + messageSentToGroupChat: { + _id: '668ec1f13603ac4697a151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, +]; + +const MESSAGE_SENT_TO_DIRECT_CHAT_MOCK = [ + { + request: { + query: MESSAGE_SENT_TO_DIRECT_CHAT, + variables: { + userId: '1', + }, + }, + result: { + data: { + messageSentToDirectChat: { + _id: '668ec1f1364e03ac4697a151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + receiver: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + image: '', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, + { + request: { + query: MESSAGE_SENT_TO_DIRECT_CHAT, + variables: { + userId: '2', + }, + }, + result: { + data: { + messageSentToDirectChat: { + _id: '668ec1f1364e03ac4697vgfa151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + receiver: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + image: '', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, + { + request: { + query: MESSAGE_SENT_TO_DIRECT_CHAT, + variables: { + userId: null, + }, + }, + result: { + data: { + messageSentToDirectChat: { + _id: '6ec1f1364e03ac4697a151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + receiver: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + image: '', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, +]; + +const DIRECT_CHAT_BY_ID_QUERY_MOCK = [ + { + request: { + query: DIRECT_CHAT_BY_ID, + variables: { + id: '1', + }, + }, + result: { + data: { + directChatById: { + _id: '1', + createdAt: '2345678903456', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + receiver: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: DIRECT_CHAT_BY_ID, + variables: { + id: '1', + }, + }, + result: { + data: { + directChatById: { + _id: '1', + createdAt: '2345678903456', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + receiver: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: DIRECT_CHAT_BY_ID, + variables: { + id: '', + }, + }, + result: { + data: { + directChatById: { + _id: '1', + createdAt: '2345678903456', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + receiver: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: DIRECT_CHAT_BY_ID, + variables: { + id: '2', + }, + }, + result: { + data: { + directChatById: { + _id: '65844efc814dd4003db811c4', + createdAt: '2345678903456', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + receiver: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: DIRECT_CHAT_BY_ID, + variables: { + id: null, + }, + }, + result: { + data: { + directChatById: { + _id: '65844efc814dd4003db811c4', + createdAt: '2345678903456', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + receiver: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + ], + }, + }, + }, + }, +]; + +const GROUP_CHAT_BY_ID_QUERY_MOCK = [ + { + request: { + query: GROUP_CHAT_BY_ID, + variables: { + id: '1', + }, + }, + result: { + data: { + groupChatById: { + _id: '65844efc814dd4003db811c4', + createdAt: '2345678903456', + title: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: GROUP_CHAT_BY_ID, + variables: { + id: '1', + }, + }, + result: { + data: { + groupChatById: { + _id: '65844efc814dd4003db811c4', + createdAt: '2345678903456', + title: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: GROUP_CHAT_BY_ID, + variables: { + id: '', + }, + }, + result: { + data: { + groupChatById: { + _id: '1', + createdAt: '2345678903456', + title: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: GROUP_CHAT_BY_ID, + variables: { + id: '2', + }, + }, + result: { + data: { + groupChatById: { + _id: '65844efc814dd4003db811c4', + createdAt: '2345678903456', + title: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: GROUP_CHAT_BY_ID, + variables: { + id: null, + }, + }, + result: { + data: { + groupChatById: { + _id: '65844efc814dd4003db811c4', + createdAt: '2345678903456', + title: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + }, + }, + }, +]; + +const CREATE_GROUP_CHAT_MOCK = [ + { + request: { + query: CREATE_GROUP_CHAT, + variables: { + organizationId: '6401ff65ce8e8406b8f07af2', + userIds: [null], + title: 'Test Group', + }, + }, + result: { + data: { + createGroupChat: { + _id: '669394c180e96b740ba1c0ce', + __typename: 'GroupChat', + }, + }, + }, + }, + { + request: { + query: CREATE_GROUP_CHAT, + variables: { + organizationId: '', + userIds: [null], + title: 'Test Group', + }, + }, + result: { + data: { + createGroupChat: { + _id: '669394c180e96b740ba1c0ce', + __typename: 'GroupChat', + }, + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Testing Create Direct Chat Modal [User Portal]', () => { + window.HTMLElement.prototype.scrollIntoView = jest.fn(); + + Object.defineProperty(window, 'matchMedia', { + writable: true, + value: jest.fn().mockImplementation((query) => ({ + matches: false, + media: query, + onchange: null, + addListener: jest.fn(), // Deprecated + removeListener: jest.fn(), // Deprecated + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn(), + })), + }); + + test('Test open and close create new direct chat modal', async () => { + const mock = [ + ...USER_JOINED_ORG_MOCK, + ...GROUP_CHAT_BY_ID_QUERY_MOCK, + ...DIRECT_CHAT_BY_ID_QUERY_MOCK, + ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, + ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ...UserConnectionListMock, + ...MOCKS, + ]; + render( + + + + + + + + + , + ); + + await wait(); + + const dropdown = await screen.findByTestId('dropdown'); + expect(dropdown).toBeInTheDocument(); + fireEvent.click(dropdown); + const newGroupChatBtn = await screen.findByTestId('newGroupChat'); + expect(newGroupChatBtn).toBeInTheDocument(); + fireEvent.click(newGroupChatBtn); + + const closeButton = screen.getByRole('button', { name: /close/i }); + expect(closeButton).toBeInTheDocument(); + + fireEvent.click(closeButton); + }); + + test('Test create new group chat', async () => { + const mock = [ + ...CREATE_GROUP_CHAT_MOCK, + ...USER_JOINED_ORG_MOCK, + ...GROUP_CHAT_BY_ID_QUERY_MOCK, + ...DIRECT_CHAT_BY_ID_QUERY_MOCK, + ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, + ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ...UserConnectionListMock, + ...MOCKS, + ]; + render( + + + + + + + + + , + ); + + await wait(); + + const dropdown = await screen.findByTestId('dropdown'); + expect(dropdown).toBeInTheDocument(); + fireEvent.click(dropdown); + + const newGroupChatBtn = await screen.findByTestId('newGroupChat'); + expect(newGroupChatBtn).toBeInTheDocument(); + + fireEvent.click(newGroupChatBtn); + + await waitFor(async () => { + expect( + await screen.findByTestId('createGroupChatModal'), + ).toBeInTheDocument(); + }); + + const groupTitleInput = screen.getByLabelText( + 'Group name', + ) as HTMLInputElement; + + expect(groupTitleInput).toBeInTheDocument(); + + fireEvent.change(groupTitleInput, { target: { value: 'Test Group' } }); + await waitFor(() => { + expect(groupTitleInput.value).toBe('Test Group'); + }); + + const orgSelect = screen.getByLabelText('Select Organization'); + + fireEvent.change(orgSelect, { + target: { value: '6401ff65ce8e8406b8f07af2' }, + }); + + const nextBtn = await screen.findByTestId('nextBtn'); + + act(() => { + fireEvent.click(nextBtn); + }); + + const createBtn = await screen.findByTestId('createBtn'); + await waitFor(async () => { + expect(createBtn).toBeInTheDocument(); + }); + + await act(async () => { + fireEvent.click(await screen.findByTestId('createBtn')); + }); + + await waitFor(() => { + expect(createBtn).not.toBeInTheDocument(); + }); + }, 3000); + + test('Test add and remove user ', async () => { + setItem('userId', '1'); + const mock = [ + ...USER_JOINED_ORG_MOCK, + ...CREATE_GROUP_CHAT_MOCK, + ...GROUP_CHAT_BY_ID_QUERY_MOCK, + ...DIRECT_CHAT_BY_ID_QUERY_MOCK, + ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, + ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ...UserConnectionListMock, + ...MOCKS, + ]; + render( + + + + + + + + + , + ); + + await wait(); + + const dropdown = await screen.findByTestId('dropdown'); + expect(dropdown).toBeInTheDocument(); + fireEvent.click(dropdown); + const newGroupChatBtn = await screen.findByTestId('newGroupChat'); + expect(newGroupChatBtn).toBeInTheDocument(); + fireEvent.click(newGroupChatBtn); + + await waitFor(async () => { + expect( + await screen.findByTestId('createGroupChatModal'), + ).toBeInTheDocument(); + }); + + const nextBtn = await screen.findByTestId('nextBtn'); + + act(() => { + fireEvent.click(nextBtn); + }); + + await waitFor(async () => { + const addBtn = await screen.findAllByTestId('addBtn'); + expect(addBtn[0]).toBeInTheDocument(); + }); + + const addBtn = await screen.findAllByTestId('addBtn'); + + fireEvent.click(addBtn[0]); + + const removeBtn = await screen.findAllByText('Remove'); + await waitFor(async () => { + expect(removeBtn[0]).toBeInTheDocument(); + }); + fireEvent.click(removeBtn[0]); + + await waitFor(() => { + expect(addBtn[0]).toBeInTheDocument(); + }); + + const submitBtn = await screen.findByTestId('submitBtn'); + + expect(submitBtn).toBeInTheDocument(); + + const searchInput = (await screen.findByTestId( + 'searchUser', + )) as HTMLInputElement; + expect(searchInput).toBeInTheDocument(); + + fireEvent.change(searchInput, { target: { value: 'Disha' } }); + + expect(searchInput.value).toBe('Disha'); + + fireEvent.click(submitBtn); + + const closeButton = screen.getAllByRole('button', { name: /close/i }); + expect(closeButton[0]).toBeInTheDocument(); + + fireEvent.click(closeButton[0]); + + await wait(500); + }); +}); diff --git a/src/components/UserPortal/CreateGroupChat/CreateGroupChat.tsx b/src/components/UserPortal/CreateGroupChat/CreateGroupChat.tsx new file mode 100644 index 0000000000..29884fc2bd --- /dev/null +++ b/src/components/UserPortal/CreateGroupChat/CreateGroupChat.tsx @@ -0,0 +1,391 @@ +import { + FormControl, + FormControlLabel, + FormHelperText, + InputLabel, + MenuItem, + Paper, + RadioGroup, + Select, + FormLabel, + TableBody, + Radio, +} from '@mui/material'; +import type { SelectChangeEvent } from '@mui/material/Select'; +import React, { useEffect, useState } from 'react'; +import { Button, Form, Modal } from 'react-bootstrap'; +import styles from './CreateGroupChat.module.css'; +import type { ApolloQueryResult } from '@apollo/client'; +import { useMutation, useQuery } from '@apollo/client'; +import { USER_JOINED_ORGANIZATIONS } from 'GraphQl/Queries/OrganizationQueries'; +import useLocalStorage from 'utils/useLocalstorage'; +import { CREATE_GROUP_CHAT } from 'GraphQl/Mutations/OrganizationMutations'; +import Table from '@mui/material/Table'; +import TableCell, { tableCellClasses } from '@mui/material/TableCell'; +import TableContainer from '@mui/material/TableContainer'; +import TableHead from '@mui/material/TableHead'; +import TableRow from '@mui/material/TableRow'; +import { styled } from '@mui/material/styles'; +import type { InterfaceQueryUserListItem } from 'utils/interfaces'; +import { USERS_CONNECTION_LIST } from 'GraphQl/Queries/Queries'; +import Loader from 'components/Loader/Loader'; +import { LocalPoliceTwoTone, Search } from '@mui/icons-material'; +import { style } from '@mui/system'; +import { useTranslation } from 'react-i18next'; + +interface InterfaceCreateGroupChatProps { + toggleCreateGroupChatModal: () => void; + createGroupChatModalisOpen: boolean; + groupChatListRefetch: ( + variables?: + | Partial<{ + id: any; + }> + | undefined, + ) => Promise>; +} + +interface InterfaceOrganization { + _id: string; + name: string; + image: string; + description: string; + admins: []; + members: []; + address: { + city: string; + countryCode: string; + line1: string; + postalCode: string; + state: string; + }; + membershipRequestStatus: string; + userRegistrationRequired: boolean; + membershipRequests: { + _id: string; + user: { + _id: string; + }; + }[]; +} + +const StyledTableCell = styled(TableCell)(({ theme }) => ({ + [`&.${tableCellClasses.head}`]: { + backgroundColor: ['#31bb6b', '!important'], + color: theme.palette.common.white, + }, + [`&.${tableCellClasses.body}`]: { + fontSize: 14, + }, +})); + +const StyledTableRow = styled(TableRow)(() => ({ + '&:last-child td, &:last-child th': { + border: 0, + }, +})); + +const { getItem } = useLocalStorage(); + +export default function CreateGroupChat({ + toggleCreateGroupChatModal, + createGroupChatModalisOpen, + groupChatListRefetch, +}: InterfaceCreateGroupChatProps): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'userChat', + }); + + const userId: string | null = getItem('userId'); + + const [createGroupChat] = useMutation(CREATE_GROUP_CHAT); + + const [organizations, setOrganizations] = useState([]); + const [selectedOrganization, setSelectedOrganization] = useState(''); + const [title, setTitle] = useState(''); + let [userIds, setUserIds] = useState([]); + + const [addUserModalisOpen, setAddUserModalisOpen] = useState(false); + + function openAddUserModal(): void { + setAddUserModalisOpen(true); + } + + const toggleAddUserModal = /* istanbul ignore next */ (): void => + setAddUserModalisOpen(!addUserModalisOpen); + + const handleChange = (event: React.ChangeEvent): void => { + setSelectedOrganization(event.target.value as string); + }; + + const { data: joinedOrganizationsData } = useQuery( + USER_JOINED_ORGANIZATIONS, + { + variables: { id: userId }, + }, + ); + + function reset(): void { + setOrganizations([]); + setTitle(''); + setUserIds([]); + setSelectedOrganization(''); + } + + useEffect(() => { + setUserIds(userIds); + }, [userIds]); + + async function handleCreateGroupChat(): Promise { + const groupChat = await createGroupChat({ + variables: { + organizationId: selectedOrganization, + userIds: [userId, ...userIds], + title, + }, + }); + groupChatListRefetch(); + toggleAddUserModal(); + toggleCreateGroupChatModal(); + reset(); + } + + const [userName, setUserName] = useState(''); + + const { + data: allUsersData, + loading: allUsersLoading, + refetch: allUsersRefetch, + } = useQuery(USERS_CONNECTION_LIST, { + variables: { + firstName_contains: '', + lastName_contains: '', + }, + }); + + const handleUserModalSearchChange = (e: React.FormEvent): void => { + e.preventDefault(); + /* istanbul ignore next */ + const [firstName, lastName] = userName.split(' '); + + const newFilterData = { + firstName_contains: firstName || '', + lastName_contains: lastName || '', + }; + + allUsersRefetch({ + ...newFilterData, + }); + }; + + useEffect(() => { + if (joinedOrganizationsData && joinedOrganizationsData.users.length > 0) { + const organizations = + joinedOrganizationsData.users[0]?.user?.joinedOrganizations || []; + setOrganizations(organizations); + } + }, [joinedOrganizationsData]); + + return ( + <> + + + New Group + + +
    + + Select Organization + handleChange(e)} + > + {organizations && + organizations.length && + organizations.map((organization: InterfaceOrganization) => ( + + ))} + + + + {/* + Select Organization + + */} + + Group name + { + setTitle(e.target.value); + }} + /> + + +
    +
    +
    + + + {'Chat'} + + + {allUsersLoading ? ( + <> + + + ) : ( + <> +
    +
    + { + const { value } = e.target; + setUserName(value); + }} + /> + + +
    + + + + + + # + {'user'} + {'Chat'} + + + + {allUsersData && + allUsersData.users.length > 0 && + allUsersData.users.map( + ( + userDetails: InterfaceQueryUserListItem, + index: number, + ) => ( + + + {index + 1} + + + {userDetails.user.firstName + + ' ' + + userDetails.user.lastName} +
    + {userDetails.user.email} +
    + + {userIds.includes(userDetails.user._id) ? ( + + ) : ( + + )} + +
    + ), + )} +
    +
    +
    + + )} + +
    +
    + + ); +} diff --git a/src/components/UserPortal/Login/Login.module.css b/src/components/UserPortal/Login/Login.module.css deleted file mode 100644 index 98be9db02a..0000000000 --- a/src/components/UserPortal/Login/Login.module.css +++ /dev/null @@ -1,29 +0,0 @@ -.forgotPasswordContainer { - display: flex; - justify-content: flex-end; - flex-direction: row; - margin: 5px 0px; -} - -.forgotPasswordText { - color: black; - font-size: 12px; - margin: 2px 0px; -} - -.borderNone { - border: none; -} - -.colorWhite { - color: white; -} - -.colorPrimary { - background: #31bb6b; -} - -.colorPrimaryHover:hover { - background: #31bb6b; - border: none; -} diff --git a/src/components/UserPortal/Login/Login.test.tsx b/src/components/UserPortal/Login/Login.test.tsx deleted file mode 100644 index 9248c5e9ec..0000000000 --- a/src/components/UserPortal/Login/Login.test.tsx +++ /dev/null @@ -1,306 +0,0 @@ -import type { SetStateAction } from 'react'; -import React from 'react'; -import { act, render, screen } from '@testing-library/react'; -import { MockedProvider } from '@apollo/react-testing'; -import userEvent from '@testing-library/user-event'; -import { I18nextProvider } from 'react-i18next'; - -import { LOGIN_MUTATION } from 'GraphQl/Mutations/mutations'; -import { BrowserRouter } from 'react-router-dom'; -import { Provider } from 'react-redux'; -import { store } from 'state/store'; -import i18nForTest from 'utils/i18nForTest'; -import { StaticMockLink } from 'utils/StaticMockLink'; -import Login from './Login'; -import { toast } from 'react-toastify'; - -const MOCKS = [ - { - request: { - query: LOGIN_MUTATION, - variables: { - email: 'johndoe@gmail.com', - password: 'johndoe', - }, - }, - result: { - data: { - login: { - user: { - _id: '1', - firstName: 'firstname', - lastName: 'secondname', - email: 'tempemail@example.com', - image: 'image', - }, - accessToken: 'accessToken', - refreshToken: 'refreshToken', - appUserProfile: { - adminFor: [ - { - _id: 'id', - }, - ], - isSuperAdmin: true, - }, - }, - }, - }, - }, - { - request: { - query: LOGIN_MUTATION, - variables: { - email: 'johndoe@gmail.com', - password: 'jdoe', - }, - }, - result: { - data: { - login: { - user: { - _id: '1', - firstName: 'firstname', - lastName: 'secondname', - email: 'tempemail@example.com', - image: 'image', - }, - appUserProfile: { - adminFor: {}, - isSuperAdmin: false, - }, - accessToken: 'accessToken', - refreshToken: 'refreshToken', - }, - }, - }, - }, - { - request: { - query: LOGIN_MUTATION, - variables: { - email: 'invalid@gmail.com', - password: 'anything', - }, - }, - result: {}, - }, -]; - -const link = new StaticMockLink(MOCKS, true); - -async function wait(ms = 100): Promise { - await act(() => { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); - }); -} - -jest.mock('react-toastify', () => ({ - toast: { - success: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - }, -})); -const mockNavigate = jest.fn(); -jest.mock('react-router-dom', () => ({ - ...jest.requireActual('react-router-dom'), - useNavigate: () => mockNavigate, -})); - -const setCurrentMode: React.Dispatch> = jest.fn(); - -const props = { - setCurrentMode, -}; - -describe('Testing Login Component [User Portal]', () => { - test('Component should be rendered properly', async () => { - render( - - - - - - - - - , - ); - - await wait(); - }); - - test('Expect the mode to be changed to Register', async () => { - render( - - - - - - - - - , - ); - - await wait(); - - userEvent.click(screen.getByTestId('setRegisterBtn')); - - expect(setCurrentMode).toBeCalledWith('register'); - }); - - test('toast.error is triggered if the email input is empty.', async () => { - render( - - - - - - - - - , - ); - - await wait(); - - userEvent.click(screen.getByTestId('loginBtn')); - - expect(toast.error).toBeCalledWith( - 'Please enter a valid email and password.', - ); - }); - - test('toast.error is triggered if the password input is empty.', async () => { - const formData = { - email: 'johndoe@gmail.com', - password: 'joe', - }; - - render( - - - - - - - - - , - ); - - await wait(); - - userEvent.type(screen.getByPlaceholderText(/Enter Email/i), formData.email); - userEvent.click(screen.getByTestId('loginBtn')); - - expect(toast.error).toBeCalledWith( - 'Please enter a valid email and password.', - ); - }); - - test('Incorrect password is entered.', async () => { - const formData = { - email: 'invalid@gmail.com', - password: 'anything', - }; - - render( - - - - - - - - - , - ); - - await wait(); - - userEvent.type(screen.getByPlaceholderText(/Enter Email/i), formData.email); - - userEvent.type( - screen.getByPlaceholderText(/Enter Password/i), - formData.password, - ); - - userEvent.click(screen.getByTestId('loginBtn')); - - expect(toast.error).toBeCalled(); - - await wait(); - }); - - test('Login details are entered correctly.', async () => { - const formData = { - email: 'johndoe@gmail.com', - password: 'johndoe', - }; - - render( - - - - - - - - - , - ); - - await wait(); - - userEvent.type(screen.getByPlaceholderText(/Enter Email/i), formData.email); - - userEvent.type( - screen.getByPlaceholderText(/Enter Password/i), - formData.password, - ); - - userEvent.click(screen.getByTestId('loginBtn')); - - await wait(); - expect(mockNavigate).toHaveBeenCalledWith('/user/organizations'); - }); - - test('Current user has not been approved by admin.', async () => { - const formData = { - email: 'johndoe@gmail.com', - password: 'jdoe', - }; - - render( - - - - - - - - - , - ); - - await wait(); - - userEvent.type(screen.getByPlaceholderText(/Enter Email/i), formData.email); - - userEvent.type( - screen.getByPlaceholderText(/Enter Password/i), - formData.password, - ); - - userEvent.click(screen.getByTestId('loginBtn')); - - expect(toast.error).toBeCalled(); - - await wait(); - }); -}); diff --git a/src/components/UserPortal/Login/Login.tsx b/src/components/UserPortal/Login/Login.tsx deleted file mode 100644 index 517170263e..0000000000 --- a/src/components/UserPortal/Login/Login.tsx +++ /dev/null @@ -1,144 +0,0 @@ -import { useMutation } from '@apollo/client'; -import { LockOutlined } from '@mui/icons-material'; -import EmailOutlinedIcon from '@mui/icons-material/EmailOutlined'; -import type { ChangeEvent, SetStateAction } from 'react'; -import React from 'react'; -import { Button, Form, InputGroup } from 'react-bootstrap'; -import { useTranslation } from 'react-i18next'; -import { Link, useNavigate } from 'react-router-dom'; -import { toast } from 'react-toastify'; - -import { LOGIN_MUTATION } from 'GraphQl/Mutations/mutations'; -import { errorHandler } from 'utils/errorHandler'; -import useLocalStorage from 'utils/useLocalstorage'; -import styles from './Login.module.css'; - -interface InterfaceLoginProps { - setCurrentMode: React.Dispatch>; -} - -export default function login(props: InterfaceLoginProps): JSX.Element { - const { t } = useTranslation('translation', { keyPrefix: 'userLogin' }); - const { t: tCommon } = useTranslation('common'); - - const navigate = useNavigate(); - - const { setCurrentMode } = props; - - const { setItem } = useLocalStorage(); - - const handleModeChangeToRegister = (): void => { - setCurrentMode('register'); - }; - - const [loginMutation] = useMutation(LOGIN_MUTATION); - - const [loginVariables, setLoginVariables] = React.useState({ - email: '', - password: '', - }); - - const handleLogin = async (): Promise => { - if (!(loginVariables.email && loginVariables.password)) { - toast.error(t('invalidDetailsMessage')); - } else { - try { - const { data } = await loginMutation({ - variables: { - email: loginVariables.email, - password: loginVariables.password, - }, - }); - - setItem('token', data.login.accessToken); - setItem('userId', data.login.user._id); - navigate('/user/organizations'); - } catch (error: unknown) { - errorHandler(t, error); - } - } - }; - - /* istanbul ignore next */ - const handleEmailChange = (e: ChangeEvent): void => { - const email = e.target.value; - - setLoginVariables({ - email, - password: loginVariables.password, - }); - }; - - /* istanbul ignore next */ - const handlePasswordChange = (e: ChangeEvent): void => { - const password = e.target.value; - - setLoginVariables({ - email: loginVariables.email, - password, - }); - }; - - return ( - <> -

    {tCommon('login')}

    - -
    -
    {tCommon('emailAddress')}
    - - - - - - -
    {tCommon('password')}
    - - - - - - -
    - -
    - - {tCommon('forgotPassword')} - -
    - - -
    - - - ); -} diff --git a/src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.tsx b/src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.tsx index 6e5aa42d70..ede5e0a103 100644 --- a/src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.tsx +++ b/src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.tsx @@ -17,6 +17,7 @@ import type { InterfaceQueryOrganizationEventListItem, InterfaceMemberInfo, } from 'utils/interfaces'; +import { skip } from 'node:test'; export default function organizationSidebar(): JSX.Element { const { t } = useTranslation('translation', { @@ -25,10 +26,14 @@ export default function organizationSidebar(): JSX.Element { const { t: tCommon } = useTranslation('common'); const { orgId: organizationId } = useParams(); - const [members, setMembers] = React.useState([]); - const [events, setEvents] = React.useState([]); - const eventsLink = `/user/events/id=${organizationId}`; - const peopleLink = `/user/people/id=${organizationId}`; + const [members, setMembers] = React.useState< + InterfaceMemberInfo[] | undefined + >(undefined); + const [events, setEvents] = React.useState< + InterfaceQueryOrganizationEventListItem[] | undefined + >(undefined); + const eventsLink = `/user/events/${organizationId}`; + const peopleLink = `/user/people/${organizationId}`; const { data: memberData, loading: memberLoading } = useQuery( ORGANIZATIONS_MEMBER_CONNECTION_LIST, @@ -77,32 +82,27 @@ export default function organizationSidebar(): JSX.Element {
    ) : ( - {members.length ? ( - members.map( - ( - member: InterfaceMemberInfo, - index: React.Key | null | undefined, - ) => { - const memberName = `${member.firstName} ${member.lastName}`; - return ( - -
    - -
    {memberName}
    -
    -
    - ); - }, - ) + {members && members.length ? ( + members.map((member: InterfaceMemberInfo) => { + const memberName = `${member.firstName} ${member.lastName}`; + return ( + +
    + +
    {memberName}
    +
    +
    + ); + }) ) : (
    {t('noMembers')}
    )} @@ -124,37 +124,32 @@ export default function organizationSidebar(): JSX.Element {
    ) : ( - {events.length ? ( - events.map( - ( - event: InterfaceQueryOrganizationEventListItem, - index: React.Key | null | undefined, - ) => { - return ( - -
    -
    -
    {event.title}
    -
    - -
    -
    -
    - Starts{' '} - {dayjs(event.startDate).format("D MMMM 'YY")} -
    -
    - Ends {dayjs(event.endDate).format("D MMMM 'YY")} + {events && events.length ? ( + events.map((event: InterfaceQueryOrganizationEventListItem) => { + return ( + +
    +
    +
    {event.title}
    +
    +
    - - ); - }, - ) +
    + Starts{' '} + {dayjs(event.startDate).format("D MMMM 'YY")} +
    +
    + Ends {dayjs(event.endDate).format("D MMMM 'YY")} +
    +
    +
    + ); + }) ) : (
    {t('noEvents')}
    )} diff --git a/src/components/UserPortal/PostCard/PostCard.module.css b/src/components/UserPortal/PostCard/PostCard.module.css index 857c4d0799..e8edc2d82c 100644 --- a/src/components/UserPortal/PostCard/PostCard.module.css +++ b/src/components/UserPortal/PostCard/PostCard.module.css @@ -1,6 +1,4 @@ .cardStyles { - height: 28rem; - max-height: 30rem; width: 20rem; background-color: white; padding: 0; @@ -178,3 +176,8 @@ outline: none; background-color: #f1f3f6; } + +.postImage { + height: 300px; + object-fit: cover; +} diff --git a/src/components/UserPortal/PostCard/PostCard.test.tsx b/src/components/UserPortal/PostCard/PostCard.test.tsx index 1ba0459b6d..64f6670223 100644 --- a/src/components/UserPortal/PostCard/PostCard.test.tsx +++ b/src/components/UserPortal/PostCard/PostCard.test.tsx @@ -185,7 +185,7 @@ describe('Testing PostCard Component [User Portal]', () => { { id: '64eb13beca85de60ebe0ed0e', creator: { - _id: '63d6064458fce20ee25c3bf7', + id: '63d6064458fce20ee25c3bf7', firstName: 'Noble', lastName: 'Mittal', email: 'test@gmail.com', @@ -199,7 +199,7 @@ describe('Testing PostCard Component [User Portal]', () => { { id: '64eb13beca85de60ebe0ed0b', creator: { - _id: '63d6064458fce20ee25c3bf8', + id: '63d6064458fce20ee25c3bf8', firstName: 'Priyanshu', lastName: 'Bartwal', email: 'test1@gmail.com', @@ -338,7 +338,7 @@ describe('Testing PostCard Component [User Portal]', () => { userEvent.click(screen.getByTestId('editPostBtn')); await wait(); - expect(toast.success).toBeCalledWith('Successfully edited the Post.'); + expect(toast.success).toBeCalledWith('Post updated Successfully'); }); test('Delete post should work properly', async () => { diff --git a/src/components/UserPortal/PostCard/PostCard.tsx b/src/components/UserPortal/PostCard/PostCard.tsx index d1b84412fb..d1bfbb1391 100644 --- a/src/components/UserPortal/PostCard/PostCard.tsx +++ b/src/components/UserPortal/PostCard/PostCard.tsx @@ -180,10 +180,10 @@ export default function postCard(props: InterfacePostCard): JSX.Element { setCommentInput(''); setNumComments((numComments) => numComments + 1); - const newComment: any = { - id: createEventData.createComment._id, + const newComment: InterfaceCommentCardProps = { + id: createEventData.createComment.id, creator: { - id: createEventData.createComment.creator.id, + id: createEventData.createComment.creator._id, firstName: createEventData.createComment.creator.firstName, lastName: createEventData.createComment.creator.lastName, email: createEventData.createComment.creator.email, @@ -214,7 +214,7 @@ export default function postCard(props: InterfacePostCard): JSX.Element { props.fetchPosts(); toggleEditPost(); - toast.success('Successfully edited the Post.'); + toast.success(tCommon('updatedSuccessfully', { item: 'Post' })); } catch (error: unknown) { /* istanbul ignore next */ errorHandler(t, error); @@ -274,6 +274,7 @@ export default function postCard(props: InterfacePostCard): JSX.Element { - Posted On: {props.postedAt} + {t('postedOn', { date: props.postedAt })} {props.text} - {props.image && ( - - )}
    @@ -304,7 +302,7 @@ export default function postCard(props: InterfacePostCard): JSX.Element { data-testid={'viewPostBtn'} onClick={toggleViewPost} > - View Post + {t('viewPost')}
    @@ -341,7 +339,7 @@ export default function postCard(props: InterfacePostCard): JSX.Element {

    Comments

    {numComments ? ( - comments.map((comment: any, index: any) => { + comments.map((comment, index: number) => { const cardProps: InterfaceCommentCardProps = { id: comment.id, creator: { @@ -417,7 +415,7 @@ export default function postCard(props: InterfacePostCard): JSX.Element {

    - Edit Post + {t('editPost')}

    @@ -441,7 +439,7 @@ export default function postCard(props: InterfacePostCard): JSX.Element { data-testid={'editPostBtn'} onClick={handleEditPost} > - Edit Post + {t('editPost')}
    diff --git a/src/components/UserPortal/StartPostModal/StartPostModal.tsx b/src/components/UserPortal/StartPostModal/StartPostModal.tsx index 036bcd904e..91f3563147 100644 --- a/src/components/UserPortal/StartPostModal/StartPostModal.tsx +++ b/src/components/UserPortal/StartPostModal/StartPostModal.tsx @@ -60,7 +60,7 @@ const startPostModal = ({ /* istanbul ignore next */ if (data) { toast.dismiss(); - toast.success('Your post is now visible in the feed.'); + toast.success(t('postNowVisibleInFeed')); fetchPosts(); handleHide(); } diff --git a/src/components/UserPortal/UserSidebar/UserSidebar.module.css b/src/components/UserPortal/UserSidebar/UserSidebar.module.css index a9d330339f..aafeaeff97 100644 --- a/src/components/UserPortal/UserSidebar/UserSidebar.module.css +++ b/src/components/UserPortal/UserSidebar/UserSidebar.module.css @@ -1,5 +1,5 @@ .leftDrawer { - width: calc(300px + 2rem); + width: calc(300px); position: fixed; top: 0; bottom: 0; @@ -13,7 +13,7 @@ } .activeDrawer { - width: calc(300px + 2rem); + width: calc(300px); position: fixed; top: 0; left: 0; diff --git a/src/components/UserPortal/UserSidebar/UserSidebar.tsx b/src/components/UserPortal/UserSidebar/UserSidebar.tsx index 563172fc07..dc0c1e3622 100644 --- a/src/components/UserPortal/UserSidebar/UserSidebar.tsx +++ b/src/components/UserPortal/UserSidebar/UserSidebar.tsx @@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next'; import { NavLink } from 'react-router-dom'; import { ReactComponent as OrganizationsIcon } from 'assets/svgs/organizations.svg'; import { ReactComponent as SettingsIcon } from 'assets/svgs/settings.svg'; +import { ReactComponent as ChatIcon } from 'assets/svgs/chat.svg'; import { ReactComponent as TalawaLogo } from 'assets/svgs/talawa.svg'; import styles from './UserSidebar.module.css'; @@ -87,6 +88,28 @@ const userSidebar = ({ )} + + {({ isActive }) => ( + + )} +
    diff --git a/src/components/UserPortal/UserSidebarOrg/UserSidebarOrg.tsx b/src/components/UserPortal/UserSidebarOrg/UserSidebarOrg.tsx index 7d78d3765e..b56d5ea085 100644 --- a/src/components/UserPortal/UserSidebarOrg/UserSidebarOrg.tsx +++ b/src/components/UserPortal/UserSidebarOrg/UserSidebarOrg.tsx @@ -150,7 +150,7 @@ const UserSidebarOrg = ({ } />
    - {name} + {tCommon(name)} )} diff --git a/src/components/UserProfileSettings/UserProfile.test.tsx b/src/components/UserProfileSettings/UserProfile.test.tsx index 979310685f..82caad5d81 100644 --- a/src/components/UserProfileSettings/UserProfile.test.tsx +++ b/src/components/UserProfileSettings/UserProfile.test.tsx @@ -9,8 +9,9 @@ import i18nForTest from 'utils/i18nForTest'; describe('UserProfile component', () => { test('renders user profile details correctly', () => { const userDetails = { - firstName: 'John', + firstName: 'Christopher', lastName: 'Doe', + createdAt: '2023-04-13T04:53:17.742+00:00', email: 'john.doe@example.com', image: 'profile-image-url', }; @@ -24,14 +25,14 @@ describe('UserProfile component', () => { , ); - expect(getByText('John')).toBeInTheDocument(); - expect(getByText('john.doe@example.com')).toBeInTheDocument(); + expect(getByText('Chris..')).toBeInTheDocument(); + expect(getByText('john..@example.com')).toBeInTheDocument(); const profileImage = getByAltText('profile picture'); expect(profileImage).toBeInTheDocument(); expect(profileImage).toHaveAttribute('src', 'profile-image-url'); - expect(getByText('Joined 1st May, 2021')).toBeInTheDocument(); + expect(getByText('Joined 13 April 2023')).toBeInTheDocument(); expect(getByText('Copy Profile Link')).toBeInTheDocument(); }); diff --git a/src/components/UserProfileSettings/UserProfile.tsx b/src/components/UserProfileSettings/UserProfile.tsx index 77e1542c82..7af0939a75 100644 --- a/src/components/UserProfileSettings/UserProfile.tsx +++ b/src/components/UserProfileSettings/UserProfile.tsx @@ -4,17 +4,30 @@ import { Button, Card } from 'react-bootstrap'; import CalendarMonthOutlinedIcon from '@mui/icons-material/CalendarMonthOutlined'; import { useTranslation } from 'react-i18next'; import styles from './UserProfileSettings.module.css'; +import { Tooltip as ReactTooltip } from 'react-tooltip'; interface InterfaceUserProfile { firstName: string; lastName: string; + createdAt: string; email: string; image: string; } +const joinedDate = (param: string): string => { + const date = new Date(param); + if (date?.toDateString() === 'Invalid Date') { + return 'Unavailable'; + } + const day = date.getDate(); + const month = date.toLocaleString('default', { month: 'long' }); + const year = date.getFullYear(); + return `${day} ${month} ${year}`; +}; const UserProfile: React.FC = ({ firstName, lastName, + createdAt, email, image, }): JSX.Element => { @@ -41,20 +54,35 @@ const UserProfile: React.FC = ({ )}
    - - {`${firstName}`.charAt(0).toUpperCase() + - `${firstName}`.slice(1)} + + {firstName.length > 10 + ? firstName.slice(0, 5) + '..' + : firstName} + + + + {email.length > 10 + ? email.slice(0, 4) + '..' + email.slice(email.indexOf('@')) + : email} - {email} + - {tCommon('joined')} 1st May, 2021 + {tCommon('joined')} {joinedDate(createdAt)}
    -
    +
    diff --git a/src/components/UserProfileSettings/UserProfileSettings.module.css b/src/components/UserProfileSettings/UserProfileSettings.module.css index 603c5a677d..2c7cc76f57 100644 --- a/src/components/UserProfileSettings/UserProfileSettings.module.css +++ b/src/components/UserProfileSettings/UserProfileSettings.module.css @@ -48,6 +48,7 @@ flex-direction: column; align-items: center; justify-content: space-evenly; + margin-left: 10%; } @media screen and (max-width: 1280px) and (min-width: 992px) { diff --git a/src/components/UsersTableItem/UsersTableItem.tsx b/src/components/UsersTableItem/UsersTableItem.tsx index b7c7670239..9d6ec65187 100644 --- a/src/components/UsersTableItem/UsersTableItem.tsx +++ b/src/components/UsersTableItem/UsersTableItem.tsx @@ -56,7 +56,7 @@ const UsersTableItem = (props: Props): JSX.Element => { }, }); if (data) { - toast.success('Removed User from Organization successfully'); + toast.success(tCommon('removedSuccessfully', { item: 'User' })); resetAndRefetch(); } } catch (error: unknown) { @@ -230,13 +230,13 @@ const UsersTableItem = (props: Props): JSX.Element => { - - - - - - - + + + + + + + @@ -345,7 +345,7 @@ const UsersTableItem = (props: Props): JSX.Element => { setShowRemoveUserModal(true); }} > - Remove User + {tCommon('removeUser')} @@ -362,7 +362,7 @@ const UsersTableItem = (props: Props): JSX.Element => { onClick={() => setShowJoinedOrganizations(false)} data-testid={`closeJoinedOrgsBtn${user.user._id}`} > - Close + {tCommon('close')} @@ -419,13 +419,13 @@ const UsersTableItem = (props: Props): JSX.Element => {
    NameAddressCreated onCreated ByUsers RoleChange RoleAction{tCommon('name')}{tCommon('address')}{tCommon('createdOn')}{tCommon('createdBy')}{tCommon('usersRole')}{tCommon('changeRole')}{tCommon('action')}
    - - - - - - - + + + + + + + @@ -528,7 +528,7 @@ const UsersTableItem = (props: Props): JSX.Element => { setShowRemoveUserModal(true); }} > - Remove User + {tCommon('removeUser')} @@ -545,7 +545,7 @@ const UsersTableItem = (props: Props): JSX.Element => { onClick={() => setShowBlockedOrganizations(false)} data-testid={`closeBlockedByOrgsBtn${user.user._id}`} > - Close + {tCommon('close')} @@ -557,21 +557,15 @@ const UsersTableItem = (props: Props): JSX.Element => { > - Remove User from {removeUserProps.orgName} + {t('removeUserFrom', { org: removeUserProps.orgName })}

    - Are you sure you want to remove{' '} - - “{user.user.firstName} {user.user.lastName}” - {' '} - from organization{' '} - - “ - {removeUserProps.orgName}” - {' '} - ? + {t('removeConfirmation', { + name: `${user.user.firstName} ${user.user.lastName}`, + org: removeUserProps.orgName, + })}

    @@ -580,14 +574,14 @@ const UsersTableItem = (props: Props): JSX.Element => { onClick={() => onHideRemoveUserModal()} data-testid={`closeRemoveUserModal${user.user._id}`} > - Close + {tCommon('close')} diff --git a/src/index.tsx b/src/index.tsx index 015f0cac2a..44cb0578b6 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -25,7 +25,6 @@ import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; import App from './App'; import { store } from './state/store'; -import './utils/i18n'; import { BACKEND_URL, REACT_APP_BACKEND_WEBSOCKET_URL, @@ -44,14 +43,16 @@ const theme = createTheme({ }, }); import useLocalStorage from 'utils/useLocalstorage'; +import i18n from './utils/i18n'; const { getItem } = useLocalStorage(); - const authLink = setContext((_, { headers }) => { + const lng = i18n.language; return { headers: { ...headers, authorization: 'Bearer ' + getItem('token') || '', + 'Accept-Language': lng, }, }; }); @@ -99,6 +100,12 @@ const wsLink = new GraphQLWsLink( url: REACT_APP_BACKEND_WEBSOCKET_URL, }), ); + +// const wsLink = new GraphQLWsLink( +// createClient({ +// url: 'ws://localhost:4000/subscriptions', +// }), +// ); // The split function takes three parameters: // // * A function that's called for each operation to execute diff --git a/src/reportWebVitals.ts b/src/reportWebVitals.ts index 59de1b72a4..f49db29f28 100644 --- a/src/reportWebVitals.ts +++ b/src/reportWebVitals.ts @@ -1,13 +1,13 @@ -import type { ReportHandler } from 'web-vitals'; +import { promises } from 'dns'; +import type { MetricType } from 'web-vitals'; -const reportWebVitals = (onPerfEntry?: ReportHandler): void => { +const reportWebVitals = (onPerfEntry?: (metric: MetricType) => void): void => { if (onPerfEntry && onPerfEntry instanceof Function) { - import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { - getCLS(onPerfEntry); - getFID(onPerfEntry); - getFCP(onPerfEntry); - getLCP(onPerfEntry); - getTTFB(onPerfEntry); + import('web-vitals').then(({ onCLS, onFCP, onLCP, onTTFB }) => { + onCLS(onPerfEntry); + onFCP(onPerfEntry); + onLCP(onPerfEntry); + onTTFB(onPerfEntry); }); } }; diff --git a/src/screens/CommunityProfile/CommunityProfile.tsx b/src/screens/CommunityProfile/CommunityProfile.tsx index 9282f112bc..96650c1ed8 100644 --- a/src/screens/CommunityProfile/CommunityProfile.tsx +++ b/src/screens/CommunityProfile/CommunityProfile.tsx @@ -25,6 +25,7 @@ const CommunityProfile = (): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'communityProfile', }); + const { t: tCommon } = useTranslation('common'); document.title = t('title'); @@ -82,7 +83,7 @@ const CommunityProfile = (): JSX.Element => { }); }, [data]); - const handleOnChange = (e: any): void => { + const handleOnChange = (e: React.ChangeEvent): void => { setProfileVariable({ ...profileVariable, [e.target.name]: e.target.value, @@ -114,9 +115,9 @@ const CommunityProfile = (): JSX.Element => { }, }); toast.success(t('profileChangedMsg')); - } catch (error: any) { + } catch (error: unknown) { /* istanbul ignore next */ - errorHandler(t, error); + errorHandler(t, error as Error); } }; @@ -144,9 +145,9 @@ const CommunityProfile = (): JSX.Element => { }, }); toast.success(t(`resetData`)); - } catch (error: any) { + } catch (error: unknown) { /* istanbul ignore next */ - errorHandler(t, error); + errorHandler(t, error as Error); } }; @@ -358,14 +359,14 @@ const CommunityProfile = (): JSX.Element => { data-testid="resetChangesBtn" disabled={isDisabled()} > - Reset Changes + {tCommon('resetChanges')} diff --git a/src/screens/EventManagement/EventManagement.test.tsx b/src/screens/EventManagement/EventManagement.test.tsx index c51f4eaf12..fb851ec72f 100644 --- a/src/screens/EventManagement/EventManagement.test.tsx +++ b/src/screens/EventManagement/EventManagement.test.tsx @@ -99,6 +99,12 @@ describe('Event Management', () => { const eventActionsTab = screen.getByTestId('eventActionsTab'); expect(eventActionsTab).toBeInTheDocument(); + const eventAgendasButton = screen.getByTestId('eventAgendasBtn'); + userEvent.click(eventAgendasButton); + + const eventAgendasTab = screen.getByTestId('eventAgendasTab'); + expect(eventAgendasTab).toBeInTheDocument(); + const eventStatsButton = screen.getByTestId('eventStatsBtn'); userEvent.click(eventStatsButton); diff --git a/src/screens/EventManagement/EventManagement.tsx b/src/screens/EventManagement/EventManagement.tsx index 869992cc0f..4a2acdee1b 100644 --- a/src/screens/EventManagement/EventManagement.tsx +++ b/src/screens/EventManagement/EventManagement.tsx @@ -7,11 +7,13 @@ import { ReactComponent as AngleLeftIcon } from 'assets/svgs/angleLeft.svg'; import { ReactComponent as EventDashboardIcon } from 'assets/svgs/eventDashboard.svg'; import { ReactComponent as EventRegistrantsIcon } from 'assets/svgs/people.svg'; import { ReactComponent as EventActionsIcon } from 'assets/svgs/settings.svg'; +import { ReactComponent as EventAgendaItemsIcon } from 'assets/svgs/agenda-items.svg'; import { ReactComponent as EventStatisticsIcon } from 'assets/svgs/eventStats.svg'; import { useTranslation } from 'react-i18next'; import { Button } from 'react-bootstrap'; import EventDashboard from 'components/EventManagement/Dashboard/EventDashboard'; import EventActionItems from 'components/EventManagement/EventActionItems/EventActionItems'; +import EventAgendaItems from 'components/EventManagement/EventAgendaItems/EventAgendaItems'; import useLocalStorage from 'utils/useLocalstorage'; const eventDashboardTabs: { @@ -30,13 +32,23 @@ const eventDashboardTabs: { value: 'eventActions', icon: , }, + { + value: 'eventAgendas', + icon: , + }, + { value: 'eventStats', icon: , }, ]; -type TabOptions = 'dashboard' | 'registrants' | 'eventActions' | 'eventStats'; +type TabOptions = + | 'dashboard' + | 'registrants' + | 'eventActions' + | 'eventAgendas' + | 'eventStats'; const EventManagement = (): JSX.Element => { const { t } = useTranslation('translation', { @@ -140,6 +152,12 @@ const EventManagement = (): JSX.Element => { ); + case 'eventAgendas': + return ( +
    + +
    + ); case 'eventStats': return (
    diff --git a/src/screens/FundCampaignPledge/FundCampaignPledge.module.css b/src/screens/FundCampaignPledge/FundCampaignPledge.module.css index 8ddc6c01b1..c46adfada3 100644 --- a/src/screens/FundCampaignPledge/FundCampaignPledge.module.css +++ b/src/screens/FundCampaignPledge/FundCampaignPledge.module.css @@ -2,11 +2,6 @@ margin: 0.6rem 0; } -.createPledgeBtn { - position: absolute; - top: 1.3rem; - right: 2rem; -} .container { min-height: 100vh; } @@ -16,15 +11,24 @@ margin-top: 2vh; margin-left: 13vw; } + .titlemodal { - color: var(--bs-gray-600); + color: #707070; font-weight: 600; - font-size: 20px; - margin-bottom: 20px; - padding-bottom: 5px; - border-bottom: 3px solid var(--bs-primary); + font-size: 32px; width: 65%; + margin-bottom: 0px; } + +.modalCloseBtn { + width: 40px; + height: 40px; + padding: 1rem; + display: flex; + justify-content: center; + align-items: center; +} + .greenregbtn { margin: 1rem 0 0; margin-top: 15px; @@ -51,3 +55,205 @@ align-items: center; flex-direction: column; } + +.btnsContainer { + display: flex; + gap: 0.8rem; + margin: 2.2rem 0 0.8rem 0; +} + +.btnsContainer .input { + flex: 1; + min-width: 18rem; + position: relative; +} + +.btnsContainer input { + outline: 1px solid var(--bs-gray-400); +} + +.btnsContainer .input button { + width: 52px; +} + +.inputField { + background-color: white; + box-shadow: 0 1px 1px #31bb6b; +} + +.dropdown { + background-color: white; + border: 1px solid #31bb6b; + position: relative; + display: inline-block; + color: #31bb6b; +} + +.tableHeader { + background-color: var(--bs-primary); + color: var(--bs-white); + font-size: 1rem; +} + +.rowBackground { + background-color: var(--bs-white); + max-height: 120px; +} + +.TableImage { + object-fit: cover; + width: 25px !important; + height: 25px !important; + border-radius: 100% !important; +} + +.avatarContainer { + width: 28px; + height: 26px; +} + +.pledgerContainer { + display: flex; + align-items: center; + justify-content: center; + margin: 0.1rem 0.25rem; + gap: 0.25rem; + padding: 0.25rem 0.45rem; + border-radius: 0.35rem; + background-color: #31bb6b33; +} + +.noOutline input { + outline: none; +} + +.overviewContainer { + display: flex; + gap: 7rem; + width: 100%; + justify-content: space-between; + margin: 1.5rem 0 0 0; + padding: 1.25rem 2rem; + background-color: rgba(255, 255, 255, 0.591); + + box-shadow: rgba(0, 0, 0, 0.16) 0px 1px 4px; + border-radius: 0.5rem; +} + +.titleContainer { + display: flex; + flex-direction: column; + gap: 0.6rem; +} + +.titleContainer h3 { + font-size: 1.75rem; + font-weight: 750; + color: #5e5e5e; + margin-top: 0.2rem; +} + +.titleContainer span { + font-size: 0.9rem; + margin-left: 0.5rem; + font-weight: lighter; + color: #707070; +} + +.raisedAmount { + display: flex; + justify-content: center; + align-items: center; + font-size: 1.25rem; + font-weight: 750; + color: #5e5e5e; +} + +.progressContainer { + display: flex; + flex-direction: column; + gap: 0.5rem; + flex-grow: 1; +} + +.progress { + margin-top: 0.2rem; + display: flex; + flex-direction: column; + gap: 0.3rem; +} + +.endpoints { + display: flex; + position: relative; + font-size: 0.85rem; +} + +.start { + position: absolute; + top: 0px; +} + +.end { + position: absolute; + top: 0px; + right: 0px; +} + +.moreContainer { + display: flex; + align-items: center; +} + +.moreContainer:hover { + text-decoration: underline; + cursor: pointer; +} + +.popup { + z-index: 50; + border-radius: 0.5rem; + font-family: sans-serif; + font-weight: 500; + font-size: 0.875rem; + margin-top: 0.5rem; + padding: 0.75rem; + border: 1px solid #e2e8f0; + background-color: white; + color: #1e293b; + box-shadow: 0 0.5rem 1rem rgb(0 0 0 / 0.15); + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.popupExtra { + max-height: 15rem; + overflow-y: auto; +} + +.toggleGroup { + width: 50%; + min-width: 27.75rem; + margin: 0.5rem 0rem; +} + +.toggleBtn { + padding: 0rem; + height: 30px; + display: flex; + justify-content: center; + align-items: center; +} + +.toggleBtn:hover { + color: #31bb6b !important; +} + +input[type='radio']:checked + label { + background-color: #31bb6a50 !important; +} + +input[type='radio']:checked + label:hover { + color: black !important; +} diff --git a/src/screens/FundCampaignPledge/FundCampaignPledge.test.tsx b/src/screens/FundCampaignPledge/FundCampaignPledge.test.tsx index f949168c8a..25e049e19d 100644 --- a/src/screens/FundCampaignPledge/FundCampaignPledge.test.tsx +++ b/src/screens/FundCampaignPledge/FundCampaignPledge.test.tsx @@ -1,32 +1,29 @@ import { MockedProvider } from '@apollo/react-testing'; import { LocalizationProvider } from '@mui/x-date-pickers'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import type { RenderResult } from '@testing-library/react'; import { + cleanup, fireEvent, render, screen, waitFor, - waitForElementToBeRemoved, } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { act } from 'react-dom/test-utils'; import { I18nextProvider } from 'react-i18next'; import { Provider } from 'react-redux'; -import { BrowserRouter } from 'react-router-dom'; -import { toast } from 'react-toastify'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; import { store } from 'state/store'; import { StaticMockLink } from 'utils/StaticMockLink'; -import i18n from '../../utils/i18nForTest'; +import i18nForTest from '../../utils/i18nForTest'; import FundCampaignPledge from './FundCampaignPledge'; import { EMPTY_MOCKS, MOCKS, - MOCKS_CREATE_PLEDGE_ERROR, - MOCKS_DELETE_PLEDGE_ERROR, MOCKS_FUND_CAMPAIGN_PLEDGE_ERROR, - MOCKS_UPDATE_PLEDGE_ERROR, } from './PledgesMocks'; import React from 'react'; +import type { ApolloLink } from '@apollo/client'; jest.mock('react-toastify', () => ({ toast: { @@ -42,407 +39,317 @@ jest.mock('@mui/x-date-pickers/DateTimePicker', () => { }; }); -async function wait(ms = 100): Promise { - await act(() => { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); - }); -} const link1 = new StaticMockLink(MOCKS); const link2 = new StaticMockLink(MOCKS_FUND_CAMPAIGN_PLEDGE_ERROR); -const link3 = new StaticMockLink(MOCKS_CREATE_PLEDGE_ERROR); -const link4 = new StaticMockLink(MOCKS_UPDATE_PLEDGE_ERROR); -const link5 = new StaticMockLink(MOCKS_DELETE_PLEDGE_ERROR); -const link6 = new StaticMockLink(EMPTY_MOCKS); - -const translations = { - ...JSON.parse( - JSON.stringify(i18n.getDataByLanguage('en')?.translation.pledges ?? {}), - ), - ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), - ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +const link3 = new StaticMockLink(EMPTY_MOCKS); +const translations = JSON.parse( + JSON.stringify(i18nForTest.getDataByLanguage('en')?.translation.pledges), +); + +const renderFundCampaignPledge = (link: ApolloLink): RenderResult => { + return render( + + + + + + + } + /> +
    } + /> + + + + + + , + ); }; describe('Testing Campaign Pledge Screen', () => { - const formData = { - pledgeAmount: 100, - pledgeCurrency: 'USD', - pledgeEndDate: '03/10/2024', - pledgeStartDate: '03/10/2024', - }; + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId', fundCampaignId: 'fundCampaignId' }), + })); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + afterEach(() => { + cleanup(); + }); it('should render the Campaign Pledge screen', async () => { - const { getByText } = render( - - - - - {} - - - - , - ); - await wait(); + renderFundCampaignPledge(link1); await waitFor(() => { - expect(getByText(translations.addPledge)).toBeInTheDocument(); + expect(screen.getByTestId('searchPledger')).toBeInTheDocument(); }); }); - it('should render the Campaign Pledge screen with error', async () => { - const { queryByText } = render( - - - - - {} + + it('should redirect to fallback URL if URL params are undefined', async () => { + render( + + + + + + } + /> + } + /> + - - + + , ); - await wait(); + await waitFor(() => { + expect(screen.getByTestId('paramsError')).toBeInTheDocument(); + }); + }); + + it('open and closes Create Pledge modal', async () => { + renderFundCampaignPledge(link1); + + const addPledgeBtn = await screen.findByTestId('addPledgeBtn'); + expect(addPledgeBtn).toBeInTheDocument(); + userEvent.click(addPledgeBtn); + await waitFor(() => - expect(queryByText(translations.addPledge)).not.toBeInTheDocument(), + expect(screen.getAllByText(translations.createPledge)).toHaveLength(2), ); + userEvent.click(screen.getByTestId('pledgeModalCloseBtn')); await waitFor(() => - expect(screen.getByTestId('errorMsg')).toBeInTheDocument(), + expect(screen.queryByTestId('pledgeModalCloseBtn')).toBeNull(), ); }); - it('open and closes Create Pledge modal', async () => { - render( - - - - - - {} - - - - - , - ); - await wait(); + it('open and closes update pledge modal', async () => { + renderFundCampaignPledge(link1); + + const editPledgeBtn = await screen.findAllByTestId('editPledgeBtn'); + await waitFor(() => expect(editPledgeBtn[0]).toBeInTheDocument()); + userEvent.click(editPledgeBtn[0]); + await waitFor(() => - expect(screen.getByTestId('addPledgeBtn')).toBeInTheDocument(), + expect(screen.getByText(translations.editPledge)).toBeInTheDocument(), ); - userEvent.click(screen.getByTestId('addPledgeBtn')); - await waitFor(() => { - return expect( - screen.findByTestId('createPledgeCloseBtn'), - ).resolves.toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('createPledgeCloseBtn')); - await waitForElementToBeRemoved(() => - screen.queryByTestId('createPledgeCloseBtn'), + userEvent.click(screen.getByTestId('pledgeModalCloseBtn')); + await waitFor(() => + expect(screen.queryByTestId('pledgeModalCloseBtn')).toBeNull(), ); }); - it('creates a pledge', async () => { - render( - - - - - - {} - - - - - , + + it('open and closes delete pledge modal', async () => { + renderFundCampaignPledge(link1); + + const deletePledgeBtn = await screen.findAllByTestId('deletePledgeBtn'); + await waitFor(() => expect(deletePledgeBtn[0]).toBeInTheDocument()); + userEvent.click(deletePledgeBtn[0]); + + await waitFor(() => + expect(screen.getByText(translations.deletePledge)).toBeInTheDocument(), ); - await wait(); + userEvent.click(screen.getByTestId('deletePledgeCloseBtn')); await waitFor(() => - expect(screen.getByTestId('addPledgeBtn')).toBeInTheDocument(), + expect(screen.queryByTestId('deletePledgeCloseBtn')).toBeNull(), ); - userEvent.click(screen.getByTestId('addPledgeBtn')); - await waitFor(() => { - return expect( - screen.findByTestId('createPledgeCloseBtn'), - ).resolves.toBeInTheDocument(); + }); + + it('Search the Pledges list by Users', async () => { + renderFundCampaignPledge(link1); + const searchPledger = await screen.findByTestId('searchPledger'); + fireEvent.change(searchPledger, { + target: { value: 'John' }, }); - const currency = screen.getByTestId('currencySelect'); - fireEvent.change(currency, { target: { value: formData.pledgeCurrency } }); - const startDate = screen.getByLabelText(translations.startDate); - const endDate = screen.getByLabelText(translations.endDate); - fireEvent.change(startDate, { - target: { value: formData.pledgeStartDate }, + + await waitFor(() => { + expect(screen.getByText('John Doe')).toBeInTheDocument(); + expect(screen.queryByText('Jane Doe')).toBeNull(); }); - fireEvent.change(endDate, { target: { value: formData.pledgeEndDate } }); - userEvent.type( - screen.getByPlaceholderText('Enter Pledge Amount'), - formData.pledgeAmount.toString(), - ); - userEvent.click(screen.getByTestId('createPledgeBtn')); + }); + + it('should render the Campaign Pledge screen with error', async () => { + renderFundCampaignPledge(link2); await waitFor(() => { - return expect(toast.success).toHaveBeenCalledWith( - translations.pledgeCreated, - ); + expect(screen.getByTestId('errorMsg')).toBeInTheDocument(); }); }); - it('toasts an error on unsuccessful pledge creation', async () => { - render( - - - - - - {} - - - - - , - ); - await wait(); + + it('renders the empty pledge component', async () => { + renderFundCampaignPledge(link3); await waitFor(() => - expect(screen.getByTestId('addPledgeBtn')).toBeInTheDocument(), + expect(screen.getByText(translations.noPledges)).toBeInTheDocument(), ); - userEvent.click(screen.getByTestId('addPledgeBtn')); + }); + + it('check if user image renders', async () => { + renderFundCampaignPledge(link1); await waitFor(() => { - return expect( - screen.findByTestId('createPledgeCloseBtn'), - ).resolves.toBeInTheDocument(); + expect(screen.getByTestId('searchPledger')).toBeInTheDocument(); }); - const currency = screen.getByTestId('currencySelect'); - fireEvent.change(currency, { target: { value: formData.pledgeCurrency } }); - const startDate = screen.getByLabelText(translations.startDate); - const endDate = screen.getByLabelText(translations.endDate); - fireEvent.change(startDate, { - target: { value: formData.pledgeStartDate }, + + const image = await screen.findByTestId('image1'); + expect(image).toBeInTheDocument(); + expect(image).toHaveAttribute('src', 'img-url'); + }); + + it('should render extraUserDetails in Popup', async () => { + renderFundCampaignPledge(link1); + await waitFor(() => { + expect(screen.getByTestId('searchPledger')).toBeInTheDocument(); }); - fireEvent.change(endDate, { target: { value: formData.pledgeEndDate } }); - userEvent.type( - screen.getByPlaceholderText('Enter Pledge Amount'), - formData.pledgeAmount.toString(), - ); - userEvent.click(screen.getByTestId('createPledgeBtn')); + + expect(screen.getByText('John Doe')).toBeInTheDocument(); + expect(screen.getByText('John Doe2')).toBeInTheDocument(); + expect(screen.queryByText('John Doe3')).toBeNull(); + expect(screen.queryByText('John Doe4')).toBeNull(); + + const moreContainer = await screen.findAllByTestId('moreContainer'); + userEvent.click(moreContainer[0]); + await waitFor(() => { - return expect(toast.error).toHaveBeenCalled(); + expect(screen.getByText('John Doe3')).toBeInTheDocument(); + expect(screen.getByText('John Doe4')).toBeInTheDocument(); + expect(screen.getByTestId('extra1')).toBeInTheDocument(); + expect(screen.getByTestId('extra2')).toBeInTheDocument(); + expect(screen.getByTestId('extraAvatar8')).toBeInTheDocument(); + const image = screen.getByTestId('extraImage1'); + expect(image).toBeInTheDocument(); + expect(image).toHaveAttribute('src', 'img-url3'); }); - }); - it('open and closes update pledge modal', async () => { - render( - - - - - - {} - - - - - , - ); - await wait(); - await waitFor(() => - expect(screen.getAllByTestId('editPledgeBtn')[0]).toBeInTheDocument(), - ); - userEvent.click(screen.getAllByTestId('editPledgeBtn')[0]); + userEvent.click(moreContainer[0]); await waitFor(() => { - return expect( - screen.findByTestId('updatePledgeCloseBtn'), - ).resolves.toBeInTheDocument(); + expect(screen.queryByText('John Doe3')).toBeNull(); + expect(screen.queryByText('John Doe4')).toBeNull(); }); - userEvent.click(screen.getByTestId('updatePledgeCloseBtn')); - await waitForElementToBeRemoved(() => - screen.queryByTestId('updatePledgeCloseBtn'), - ); }); - it('updates a pledge', async () => { - render( - - - - - - {} - - - - - , - ); - await wait(); - await waitFor(() => - expect(screen.getAllByTestId('editPledgeBtn')[0]).toBeInTheDocument(), - ); - userEvent.click(screen.getAllByTestId('editPledgeBtn')[0]); + + it('should render Progress Bar with Raised amount (CONSTANT) & Pledged Amount', async () => { + renderFundCampaignPledge(link1); await waitFor(() => { - return expect( - screen.findByTestId('updatePledgeCloseBtn'), - ).resolves.toBeInTheDocument(); + expect(screen.getByTestId('searchPledger')).toBeInTheDocument(); }); - const currency = screen.getByTestId('currencySelect'); - fireEvent.change(currency, { target: { value: 'INR' } }); - const startDate = screen.getByLabelText(translations.startDate); - const endDate = screen.getByLabelText(translations.endDate); - fireEvent.change(startDate, { - target: { value: formData.pledgeStartDate }, + const raised = screen.getByText('Raised amount'); + const pledged = screen.getByText('Pledged amount'); + expect(pledged).toBeInTheDocument(); + expect(raised).toBeInTheDocument(); + + userEvent.click(raised); + + await waitFor(() => { + expect(screen.getByTestId('progressBar')).toBeInTheDocument(); + expect(screen.getByTestId('progressBar')).toHaveTextContent('$0'); }); - fireEvent.change(endDate, { target: { value: formData.pledgeEndDate } }); - userEvent.type( - screen.getByPlaceholderText('Enter Pledge Amount'), - formData.pledgeAmount.toString(), - ); - userEvent.click(screen.getByTestId('updatePledgeBtn')); + + userEvent.click(pledged); + await waitFor(() => { - return expect(toast.success).toHaveBeenCalledWith( - translations.pledgeUpdated, - ); + expect(screen.getByTestId('progressBar')).toBeInTheDocument(); + expect(screen.getByTestId('progressBar')).toHaveTextContent('$300'); }); }); - it('toasts an error on unsuccessful pledge update', async () => { - render( - - - - - - {} - - - - - , - ); - await wait(); - await waitFor(() => - expect(screen.getAllByTestId('editPledgeBtn')[0]).toBeInTheDocument(), - ); - userEvent.click(screen.getAllByTestId('editPledgeBtn')[0]); + + it('Sort the Pledges list by Lowest Amount', async () => { + renderFundCampaignPledge(link1); + + const searchPledger = await screen.findByTestId('searchPledger'); + expect(searchPledger).toBeInTheDocument(); + + fireEvent.click(screen.getByTestId('filter')); await waitFor(() => { - return expect( - screen.findByTestId('updatePledgeCloseBtn'), - ).resolves.toBeInTheDocument(); + expect(screen.getByTestId('amount_ASC')).toBeInTheDocument(); }); - const currency = screen.getByTestId('currencySelect'); - fireEvent.change(currency, { target: { value: 'INR' } }); - const startDate = screen.getByLabelText(translations.startDate); - const endDate = screen.getByLabelText(translations.endDate); - fireEvent.change(startDate, { - target: { value: formData.pledgeStartDate }, + fireEvent.click(screen.getByTestId('amount_ASC')); + + await waitFor(() => { + expect(screen.getByText('John Doe')).toBeInTheDocument(); + expect(screen.queryByText('Jane Doe')).toBeInTheDocument(); }); - fireEvent.change(endDate, { target: { value: formData.pledgeEndDate } }); - userEvent.type( - screen.getByPlaceholderText('Enter Pledge Amount'), - formData.pledgeAmount.toString(), - ); - userEvent.click(screen.getByTestId('updatePledgeBtn')); + await waitFor(() => { - return expect(toast.error).toHaveBeenCalled(); + expect(screen.getAllByTestId('amountCell')[0]).toHaveTextContent('100'); }); }); - it('open and closes delete pledge modal', async () => { - render( - - - - - - {} - - - - - , - ); - await wait(); - await waitFor(() => - expect(screen.getAllByTestId('deletePledgeBtn')[0]).toBeInTheDocument(), - ); - userEvent.click(screen.getAllByTestId('deletePledgeBtn')[0]); + + it('Sort the Pledges list by Highest Amount', async () => { + renderFundCampaignPledge(link1); + + const searchPledger = await screen.findByTestId('searchPledger'); + expect(searchPledger).toBeInTheDocument(); + + fireEvent.click(screen.getByTestId('filter')); await waitFor(() => { - return expect( - screen.findByTestId('deletePledgeCloseBtn'), - ).resolves.toBeInTheDocument(); + expect(screen.getByTestId('amount_DESC')).toBeInTheDocument(); }); - userEvent.click(screen.getByTestId('deletePledgeCloseBtn')); - await waitForElementToBeRemoved(() => - screen.queryByTestId('deletePledgeCloseBtn'), - ); - }); - it('deletes a pledge', async () => { - render( - - - - - - {} - - - - - , - ); - await wait(); - await waitFor(() => - expect(screen.getAllByTestId('deletePledgeBtn')[0]).toBeInTheDocument(), - ); - userEvent.click(screen.getAllByTestId('deletePledgeBtn')[0]); + fireEvent.click(screen.getByTestId('amount_DESC')); + await waitFor(() => { - return expect( - screen.findByTestId('deletePledgeCloseBtn'), - ).resolves.toBeInTheDocument(); + expect(screen.getByText('John Doe')).toBeInTheDocument(); + expect(screen.queryByText('Jane Doe')).toBeInTheDocument(); }); - userEvent.click(screen.getByTestId('deleteyesbtn')); + await waitFor(() => { - return expect(toast.success).toHaveBeenCalledWith( - translations.pledgeDeleted, - ); + expect(screen.getAllByTestId('amountCell')[0]).toHaveTextContent('200'); }); }); - it('toasts an error on unsuccessful pledge deletion', async () => { - render( - - - - - - {} - - - - - , - ); - await wait(); - await waitFor(() => - expect(screen.getAllByTestId('deletePledgeBtn')[0]).toBeInTheDocument(), - ); - userEvent.click(screen.getAllByTestId('deletePledgeBtn')[0]); + + it('Sort the Pledges list by latest endDate', async () => { + renderFundCampaignPledge(link1); + + const searchPledger = await screen.findByTestId('searchPledger'); + expect(searchPledger).toBeInTheDocument(); + + fireEvent.click(screen.getByTestId('filter')); await waitFor(() => { - return expect( - screen.findByTestId('deletePledgeCloseBtn'), - ).resolves.toBeInTheDocument(); + expect(screen.getByTestId('endDate_DESC')).toBeInTheDocument(); }); - userEvent.click(screen.getByTestId('deleteyesbtn')); + fireEvent.click(screen.getByTestId('endDate_DESC')); + await waitFor(() => { - return expect(toast.error).toHaveBeenCalled(); + expect(screen.getByText('John Doe')).toBeInTheDocument(); + expect(screen.queryByText('Jane Doe')).toBeInTheDocument(); + }); + + await waitFor(() => { + expect(screen.getAllByTestId('amountCell')[0]).toHaveTextContent('100'); }); }); - it('renders the empty pledge component', async () => { - render( - - - - - - {} - - - - - , - ); - await wait(); - await waitFor(() => - expect(screen.getByText(translations.noPledges)).toBeInTheDocument(), - ); + + it('Sort the Pledges list by earliest endDate', async () => { + renderFundCampaignPledge(link1); + + const searchPledger = await screen.findByTestId('searchPledger'); + expect(searchPledger).toBeInTheDocument(); + + fireEvent.click(screen.getByTestId('filter')); + await waitFor(() => { + expect(screen.getByTestId('endDate_ASC')).toBeInTheDocument(); + }); + fireEvent.click(screen.getByTestId('endDate_ASC')); + + await waitFor(() => { + expect(screen.getByText('John Doe')).toBeInTheDocument(); + expect(screen.queryByText('Jane Doe')).toBeInTheDocument(); + }); + + await waitFor(() => { + expect(screen.getAllByTestId('amountCell')[0]).toHaveTextContent('200'); + }); }); }); diff --git a/src/screens/FundCampaignPledge/FundCampaignPledge.tsx b/src/screens/FundCampaignPledge/FundCampaignPledge.tsx index 9b983ed2b8..9798336412 100644 --- a/src/screens/FundCampaignPledge/FundCampaignPledge.tsx +++ b/src/screens/FundCampaignPledge/FundCampaignPledge.tsx @@ -1,62 +1,104 @@ -import { useMutation, useQuery } from '@apollo/client'; -import { WarningAmberRounded } from '@mui/icons-material'; -import { - CREATE_PlEDGE, - DELETE_PLEDGE, - UPDATE_PLEDGE, -} from 'GraphQl/Mutations/PledgeMutation'; +import { useQuery, type ApolloQueryResult } from '@apollo/client'; +import { Search, Sort, WarningAmberRounded } from '@mui/icons-material'; import { FUND_CAMPAIGN_PLEDGE } from 'GraphQl/Queries/fundQueries'; import Loader from 'components/Loader/Loader'; +import { Unstable_Popup as BasePopup } from '@mui/base/Unstable_Popup'; import dayjs from 'dayjs'; -import React, { useCallback, useMemo, useState, type ChangeEvent } from 'react'; -import { Button, Col, Row } from 'react-bootstrap'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import { Button, Dropdown, Form } from 'react-bootstrap'; import { useTranslation } from 'react-i18next'; -import { useParams } from 'react-router-dom'; -import { toast } from 'react-toastify'; +import { Navigate, useParams } from 'react-router-dom'; import { currencySymbols } from 'utils/currency'; +import styles from './FundCampaignPledge.module.css'; +import PledgeDeleteModal from './PledgeDeleteModal'; +import PledgeModal from './PledgeModal'; +import { Breadcrumbs, Link, Stack, Typography } from '@mui/material'; +import { DataGrid } from '@mui/x-data-grid'; +import Avatar from 'components/Avatar/Avatar'; +import type { GridCellParams, GridColDef } from '@mui/x-data-grid'; import type { - InterfaceCreatePledge, InterfacePledgeInfo, + InterfacePledger, InterfaceQueryFundCampaignsPledges, } from 'utils/interfaces'; -import type { ApolloQueryResult } from '@apollo/client'; -import useLocalStorage from 'utils/useLocalstorage'; -import styles from './FundCampaignPledge.module.css'; -import PledgeCreateModal from './PledgeCreateModal'; -import PledgeDeleteModal from './PledgeDeleteModal'; -import PledgeEditModal from './PledgeEditModal'; +import ProgressBar from 'react-bootstrap/ProgressBar'; + +interface InterfaceCampaignInfo { + name: string; + goal: number; + startDate: Date; + endDate: Date; + currency: string; +} -enum Modal { - CREATE = 'create', - UPDATE = 'update', +enum ModalState { + SAME = 'same', DELETE = 'delete', } +const dataGridStyle = { + '&.MuiDataGrid-root .MuiDataGrid-cell:focus-within': { + outline: 'none !important', + }, + '&.MuiDataGrid-root .MuiDataGrid-columnHeader:focus-within': { + outline: 'none', + }, + '& .MuiDataGrid-row:hover': { + backgroundColor: 'transparent', + }, + '& .MuiDataGrid-row.Mui-hovered': { + backgroundColor: 'transparent', + }, + '& .MuiDataGrid-root': { + borderRadius: '0.5rem', + }, + '& .MuiDataGrid-main': { + borderRadius: '0.5rem', + }, +}; + const fundCampaignPledge = (): JSX.Element => { - const { fundCampaignId: currentUrl } = useParams(); - const { getItem } = useLocalStorage(); const { t } = useTranslation('translation', { keyPrefix: 'pledges', }); const { t: tCommon } = useTranslation('common'); - const [modalState, setModalState] = useState<{ [key in Modal]: boolean }>({ - [Modal.CREATE]: false, - [Modal.UPDATE]: false, - [Modal.DELETE]: false, + const { fundCampaignId, orgId } = useParams(); + if (!fundCampaignId || !orgId) { + return ; + } + + const [campaignInfo, setCampaignInfo] = useState({ + name: '', + goal: 0, + startDate: new Date(), + endDate: new Date(), + currency: '', }); + const [modalState, setModalState] = useState<{ + [key in ModalState]: boolean; + }>({ + [ModalState.SAME]: false, + [ModalState.DELETE]: false, + }); + + const [anchor, setAnchor] = useState(null); + const [extraUsers, setExtraUsers] = useState([]); + const [progressIndicator, setProgressIndicator] = useState< + 'raised' | 'pledged' + >('pledged'); + const open = Boolean(anchor); + const id = open ? 'simple-popup' : undefined; + const [pledgeModalMode, setPledgeModalMode] = useState<'edit' | 'create'>( + 'create', + ); const [pledge, setPledge] = useState(null); + const [searchTerm, setSearchTerm] = useState(''); - const [formState, setFormState] = useState({ - pledgeAmount: 0, - pledgeCurrency: 'USD', - pledgeEndDate: new Date(), - pledgeStartDate: new Date(), - }); - const [createPledge] = useMutation(CREATE_PlEDGE); - const [updatePledge] = useMutation(UPDATE_PLEDGE); - const [deletePledge] = useMutation(DELETE_PLEDGE); + const [sortBy, setSortBy] = useState< + 'amount_ASC' | 'amount_DESC' | 'endDate_ASC' | 'endDate_DESC' + >('endDate_DESC'); const { data: pledgeData, @@ -76,127 +118,79 @@ const fundCampaignPledge = (): JSX.Element => { >; } = useQuery(FUND_CAMPAIGN_PLEDGE, { variables: { - id: currentUrl, + id: fundCampaignId, + orderBy: sortBy, }, }); - const pledges = useMemo(() => { - return pledgeData?.getFundraisingCampaignById.pledges ?? []; + const endDate = dayjs( + pledgeData?.getFundraisingCampaignById?.endDate, + 'YYYY-MM-DD', + ).toDate(); + + const { pledges, totalPledged } = useMemo(() => { + let totalPledged = 0; + const pledges = + pledgeData?.getFundraisingCampaignById.pledges.filter((pledge) => { + totalPledged += pledge.amount; + const search = searchTerm.toLowerCase(); + return pledge.users.some((user) => { + const fullName = `${user.firstName} ${user.lastName}`; + return fullName.toLowerCase().includes(search); + }); + }) ?? []; + return { pledges, totalPledged }; + }, [pledgeData, searchTerm]); + + useEffect(() => { + if (pledgeData) { + setCampaignInfo({ + name: pledgeData.getFundraisingCampaignById.name, + goal: pledgeData.getFundraisingCampaignById.fundingGoal, + startDate: pledgeData.getFundraisingCampaignById.startDate, + endDate: pledgeData.getFundraisingCampaignById.endDate, + currency: pledgeData.getFundraisingCampaignById.currency, + }); + } }, [pledgeData]); - const openModal = (modal: Modal): void => { + useEffect(() => { + refetchPledge(); + }, [sortBy, refetchPledge]); + + const openModal = (modal: ModalState): void => { setModalState((prevState) => ({ ...prevState, [modal]: true })); }; - const closeModal = (modal: Modal): void => { + const closeModal = (modal: ModalState): void => { setModalState((prevState) => ({ ...prevState, [modal]: false })); }; - const handleEditClick = useCallback( - (pledge: InterfacePledgeInfo): void => { - setFormState({ - pledgeAmount: pledge.amount, - pledgeCurrency: pledge.currency, - pledgeEndDate: new Date(pledge.endDate), - pledgeStartDate: new Date(pledge.startDate), - }); + const handleOpenModal = useCallback( + (pledge: InterfacePledgeInfo | null, mode: 'edit' | 'create'): void => { setPledge(pledge); - openModal(Modal.UPDATE); + setPledgeModalMode(mode); + openModal(ModalState.SAME); }, [openModal], ); + const handleDeleteClick = useCallback( (pledge: InterfacePledgeInfo): void => { setPledge(pledge); - openModal(Modal.DELETE); + openModal(ModalState.DELETE); }, [openModal], ); - const createPledgeHandler = async ( - e: ChangeEvent, - ): Promise => { - try { - e.preventDefault(); - const userId = getItem('id'); - await createPledge({ - variables: { - campaignId: currentUrl, - amount: formState.pledgeAmount, - currency: formState.pledgeCurrency, - startDate: dayjs(formState.pledgeStartDate).format('YYYY-MM-DD'), - endDate: dayjs(formState.pledgeEndDate).format('YYYY-MM-DD'), - userIds: [userId], - }, - }); - await refetchPledge(); - closeModal(Modal.CREATE); - toast.success(t('pledgeCreated')); - setFormState({ - pledgeAmount: 0, - pledgeCurrency: 'USD', - pledgeEndDate: new Date(), - pledgeStartDate: new Date(), - }); - } catch (error: unknown) { - toast.error((error as Error).message); - } - }; - const updatePledgeHandler = async ( - e: ChangeEvent, - ): Promise => { - try { - e.preventDefault(); - const updatedFields: { [key: string]: number | string | undefined } = {}; - if (formState.pledgeAmount !== pledge?.amount) { - updatedFields.amount = formState.pledgeAmount; - } - if (formState.pledgeCurrency !== pledge?.currency) { - updatedFields.currency = formState.pledgeCurrency; - } - if ( - dayjs(formState.pledgeStartDate).format('YYYY-MM-DD') !== - dayjs(pledge?.startDate).format('YYYY-MM-DD') - ) { - updatedFields.startDate = dayjs(formState.pledgeStartDate).format( - 'YYYY-MM-DD', - ); - } - if ( - dayjs(formState.pledgeEndDate).format('YYYY-MM-DD') !== - dayjs(pledge?.endDate).format('YYYY-MM-DD') - ) { - updatedFields.endDate = dayjs(formState.pledgeEndDate).format( - 'YYYY-MM-DD', - ); - } - await updatePledge({ - variables: { - id: pledge?._id, - ...updatedFields, - }, - }); - await refetchPledge(); - closeModal(Modal.UPDATE); - toast.success(t('pledgeUpdated')); - } catch (error: unknown) { - toast.error((error as Error).message); - } - }; - const deleteHandler = async (): Promise => { - try { - await deletePledge({ - variables: { - id: pledge?._id, - }, - }); - await refetchPledge(); - closeModal(Modal.DELETE); - toast.success(t('pledgeDeleted')); - } catch (error: unknown) { - toast.error((error as Error).message); - } + const handleClick = ( + event: React.MouseEvent, + users: InterfacePledger[], + ): void => { + setExtraUsers(users); + setAnchor(anchor ? null : event.currentTarget); }; + if (pledgeLoading) return ; if (pledgeError) { return ( @@ -212,140 +206,421 @@ const fundCampaignPledge = (): JSX.Element => { ); } - return ( -
    - -
    -
    - -
    -
    {t('volunteers')}
    - -
    -
    {tCommon('startDate')}
    - -
    -
    {tCommon('endDate')}
    - -
    -
    {t('pledgeAmount')}
    - -
    -
    {t('pledgeOptions')}
    - - -
    - {pledges.map((pledge, index) => ( -
    - -
    -
    - {pledge.users.map((user, index) => ( - - {user.firstName} - {index !== pledge.users.length - 1 && ', '} - - ))} -
    - -
    -
    - {dayjs(pledge.startDate).format('DD/MM/YYYY')} -
    - -
    -
    {dayjs(pledge.endDate).format('DD/MM/YYYY')}
    - -
    -
    - { - currencySymbols[ - pledge.currency as keyof typeof currencySymbols - ] - } - {pledge.amount} -
    - -
    - - - - - {pledges && index !== pledges.length - 1 && ( -
    - )} - - ))} - {pledges.length === 0 && ( -
    -
    {t('noPledges')}
    + const columns: GridColDef[] = [ + { + field: 'pledgers', + headerName: 'Pledgers', + flex: 3, + minWidth: 50, + align: 'left', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return ( +
    + {params.row.users + .slice(0, 2) + .map((user: InterfacePledger, index: number) => ( +
    + {user.image ? ( + pledge + ) : ( +
    + +
    + )} + + {user.firstName + ' ' + user.lastName} + +
    + ))} + {params.row.users.length > 2 && ( +
    handleClick(e, params.row.users.slice(2))} + > + +{params.row.users.length - 2} more...
    )}
    + ); + }, + }, + { + field: 'startDate', + headerName: 'Start Date', + flex: 1, + minWidth: 150, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return dayjs(params.row.startDate).format('DD/MM/YYYY'); + }, + }, + { + field: 'endDate', + headerName: 'End Date', + minWidth: 150, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + flex: 1, + sortable: false, + renderCell: (params: GridCellParams) => { + return dayjs(params.row.endDate).format('DD/MM/YYYY'); + }, + }, + { + field: 'amount', + headerName: 'Pledged', + flex: 1, + minWidth: 100, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return ( +
    + { + currencySymbols[ + params.row.currency as keyof typeof currencySymbols + ] + } + {params.row.amount} +
    + ); + }, + }, + { + field: 'donated', + headerName: 'Donated', + flex: 1, + minWidth: 100, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return ( +
    + { + currencySymbols[ + params.row.currency as keyof typeof currencySymbols + ] + } + 0 +
    + ); + }, + }, + { + field: 'action', + headerName: 'Action', + flex: 1, + minWidth: 100, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return ( + <> + + + + ); + }, + }, + ]; + + return ( +
    + + history.go(-2) + } + > + {tCommon('Funds')} + + history.back() + } + > + {t('campaigns')} + + {t('pledges')} + +
    +
    +

    {campaignInfo?.name}

    + + {t('endsOn')} {campaignInfo?.endDate.toString()} +
    -
    +
    +
    +
    + setProgressIndicator('pledged')} + /> + - {/* Create Pledge Modal */} - closeModal(Modal.CREATE)} - formState={formState} - setFormState={setFormState} - createPledgeHandler={createPledgeHandler} - startDate={pledgeData?.getFundraisingCampaignById.startDate as Date} - endDate={pledgeData?.getFundraisingCampaignById.endDate as Date} - t={t} - tCommon={tCommon} - /> + setProgressIndicator('raised')} + checked={progressIndicator === 'raised'} + /> + +
    +
    - {/* Update Pledge Modal */} - closeModal(Modal.UPDATE)} - formState={formState} - setFormState={setFormState} - updatePledgeHandler={updatePledgeHandler} - startDate={pledgeData?.getFundraisingCampaignById.startDate as Date} +
    + +
    +
    $0
    +
    ${campaignInfo?.goal}
    +
    +
    +
    +
    +
    +
    + setSearchTerm(e.target.value)} + data-testid="searchPledger" + /> + +
    +
    +
    + + + + {tCommon('sort')} + + + setSortBy('amount_ASC')} + data-testid="amount_ASC" + > + {t('lowestAmount')} + + setSortBy('amount_DESC')} + data-testid="amount_DESC" + > + {t('highestAmount')} + + setSortBy('endDate_DESC')} + data-testid="endDate_DESC" + > + {t('latestEndDate')} + + setSortBy('endDate_ASC')} + data-testid="endDate_ASC" + > + {t('earliestEndDate')} + + + +
    +
    + +
    +
    +
    + row._id} + slots={{ + noRowsOverlay: () => ( + + {t('noPledges')} + + ), + }} + sx={dataGridStyle} + getRowClassName={() => `${styles.rowBackground}`} + autoHeight + rowHeight={65} + rows={pledges.map((pledge) => ({ + _id: pledge._id, + users: pledge.users, + startDate: pledge.startDate, + endDate: pledge.endDate, + amount: pledge.amount, + currency: pledge.currency, + }))} + columns={columns} + isRowSelectable={() => false} + /> + {/* Update Pledge ModalState */} + closeModal(ModalState.SAME)} + campaignId={fundCampaignId} + orgId={orgId} + pledge={pledge} + refetchPledge={refetchPledge} endDate={pledgeData?.getFundraisingCampaignById.endDate as Date} - t={t} - tCommon={tCommon} + mode={pledgeModalMode} /> - - {/* Delete Pledge Modal */} + {/* Delete Pledge ModalState */} closeModal(Modal.DELETE)} - deletePledgeHandler={deleteHandler} - t={t} - tCommon={tCommon} + isOpen={modalState[ModalState.DELETE]} + hide={() => closeModal(ModalState.DELETE)} + pledge={pledge} + refetchPledge={refetchPledge} /> + 4 ? styles.popupExtra : ''}`} + > + {extraUsers.map((user: InterfacePledger, index: number) => ( +
    + {user.image ? ( + pledger + ) : ( +
    + +
    + )} + + {user.firstName + ' ' + user.lastName} + +
    + ))} +
    ); }; diff --git a/src/screens/FundCampaignPledge/PledgeCreateModal.tsx b/src/screens/FundCampaignPledge/PledgeCreateModal.tsx deleted file mode 100644 index 53d78249a8..0000000000 --- a/src/screens/FundCampaignPledge/PledgeCreateModal.tsx +++ /dev/null @@ -1,150 +0,0 @@ -import { DatePicker } from '@mui/x-date-pickers'; -import dayjs, { type Dayjs } from 'dayjs'; -import { type ChangeEvent } from 'react'; -import { Button, Form, Modal } from 'react-bootstrap'; -import { currencyOptions } from 'utils/currency'; -import type { InterfaceCreatePledge } from 'utils/interfaces'; -import styles from './FundCampaignPledge.module.css'; -import React from 'react'; - -interface InterfaceCreatePledgeModal { - createCamapignModalIsOpen: boolean; - hideCreateCampaignModal: () => void; - formState: InterfaceCreatePledge; - setFormState: (state: React.SetStateAction) => void; - createPledgeHandler: (e: ChangeEvent) => Promise; - startDate: Date; - endDate: Date; - t: (key: string) => string; - tCommon: (key: string) => string; -} - -const PledgeCreateModal: React.FC = ({ - createCamapignModalIsOpen, - hideCreateCampaignModal, - formState, - setFormState, - createPledgeHandler, - startDate, - endDate, - t, - tCommon, -}) => { - return ( - <> - - -

    {t('createPledge')}

    - -
    - -
    - -
    - { - if (date) { - setFormState({ - ...formState, - pledgeStartDate: date.toDate(), - pledgeEndDate: - formState.pledgeEndDate && - (formState.pledgeEndDate < date?.toDate() - ? date.toDate() - : formState.pledgeEndDate), - }); - } - }} - minDate={dayjs(startDate)} - /> -
    -
    - { - if (date) { - setFormState({ - ...formState, - pledgeEndDate: date.toDate(), - }); - } - }} - minDate={dayjs(startDate)} - /> -
    -
    - - - {t('currency')} -
    - { - setFormState({ - ...formState, - pledgeCurrency: e.target.value, - }); - }} - > - - {currencyOptions.map((currency) => ( - - ))} - -
    -
    - - {t('amount')} - { - if (parseInt(e.target.value) > 0) { - setFormState({ - ...formState, - pledgeAmount: parseInt(e.target.value), - }); - } - }} - /> - -
    - - -
    -
    - - ); -}; -export default PledgeCreateModal; diff --git a/src/screens/FundCampaignPledge/PledgeDeleteModal.test.tsx b/src/screens/FundCampaignPledge/PledgeDeleteModal.test.tsx new file mode 100644 index 0000000000..dbaae76504 --- /dev/null +++ b/src/screens/FundCampaignPledge/PledgeDeleteModal.test.tsx @@ -0,0 +1,101 @@ +import React from 'react'; +import type { ApolloLink } from '@apollo/client'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import type { RenderResult } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import type { InterfaceDeletePledgeModal } from './PledgeDeleteModal'; +import PledgeDeleteModal from './PledgeDeleteModal'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import i18nForTest from '../../utils/i18nForTest'; +import { MOCKS_DELETE_PLEDGE_ERROR, MOCKS } from './PledgesMocks'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { toast } from 'react-toastify'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +const link = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(MOCKS_DELETE_PLEDGE_ERROR); +const translations = JSON.parse( + JSON.stringify(i18nForTest.getDataByLanguage('en')?.translation.pledges), +); + +const pledgeProps: InterfaceDeletePledgeModal = { + isOpen: true, + hide: jest.fn(), + pledge: { + _id: '1', + amount: 100, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-01-10', + users: [ + { + _id: '1', + firstName: 'John', + lastName: 'Doe', + image: 'img-url', + }, + ], + }, + refetchPledge: jest.fn(), +}; + +const renderPledgeDeleteModal = ( + link: ApolloLink, + props: InterfaceDeletePledgeModal, +): RenderResult => { + return render( + + + + + + + + + + + , + ); +}; + +describe('PledgeDeleteModal', () => { + it('should render PledgeDeleteModal', () => { + renderPledgeDeleteModal(link, pledgeProps); + expect(screen.getByTestId('deletePledgeCloseBtn')).toBeInTheDocument(); + }); + + it('should successfully Delete pledge', async () => { + renderPledgeDeleteModal(link, pledgeProps); + expect(screen.getByTestId('deletePledgeCloseBtn')).toBeInTheDocument(); + + fireEvent.click(screen.getByTestId('deleteyesbtn')); + + await waitFor(() => { + expect(pledgeProps.refetchPledge).toHaveBeenCalled(); + expect(pledgeProps.hide).toHaveBeenCalled(); + expect(toast.success).toHaveBeenCalledWith(translations.pledgeDeleted); + }); + }); + + it('should fail to Delete pledge', async () => { + renderPledgeDeleteModal(link2, pledgeProps); + expect(screen.getByTestId('deletePledgeCloseBtn')).toBeInTheDocument(); + + fireEvent.click(screen.getByTestId('deleteyesbtn')); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalledWith('Error deleting pledge'); + }); + }); +}); diff --git a/src/screens/FundCampaignPledge/PledgeDeleteModal.tsx b/src/screens/FundCampaignPledge/PledgeDeleteModal.tsx index 2cc7fdeaff..a16d0df905 100644 --- a/src/screens/FundCampaignPledge/PledgeDeleteModal.tsx +++ b/src/screens/FundCampaignPledge/PledgeDeleteModal.tsx @@ -1,33 +1,54 @@ import { Button, Modal } from 'react-bootstrap'; import styles from './FundCampaignPledge.module.css'; import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { useMutation } from '@apollo/client'; +import { DELETE_PLEDGE } from 'GraphQl/Mutations/PledgeMutation'; +import type { InterfacePledgeInfo } from 'utils/interfaces'; +import { toast } from 'react-toastify'; -interface InterfaceDeletePledgeModal { - deletePledgeModalIsOpen: boolean; - hideDeletePledgeModal: () => void; - deletePledgeHandler: () => Promise; - t: (key: string) => string; - tCommon: (key: string) => string; +export interface InterfaceDeletePledgeModal { + isOpen: boolean; + hide: () => void; + pledge: InterfacePledgeInfo | null; + refetchPledge: () => void; } const PledgeDeleteModal: React.FC = ({ - deletePledgeModalIsOpen, - hideDeletePledgeModal, - deletePledgeHandler, - t, - tCommon, + isOpen, + hide, + pledge, + refetchPledge, }) => { + const { t } = useTranslation('translation', { + keyPrefix: 'pledges', + }); + const { t: tCommon } = useTranslation('common'); + + const [deletePledge] = useMutation(DELETE_PLEDGE); + + const deleteHandler = async (): Promise => { + try { + await deletePledge({ + variables: { + id: pledge?._id, + }, + }); + refetchPledge(); + hide(); + toast.success(t('pledgeDeleted')); + } catch (error: unknown) { + toast.error((error as Error).message); + } + }; return ( <> - +

    {t('deletePledge')}

    - diff --git a/src/screens/FundCampaignPledge/PledgeEditModal.tsx b/src/screens/FundCampaignPledge/PledgeEditModal.tsx deleted file mode 100644 index af1e743221..0000000000 --- a/src/screens/FundCampaignPledge/PledgeEditModal.tsx +++ /dev/null @@ -1,149 +0,0 @@ -import { DatePicker } from '@mui/x-date-pickers'; -import dayjs, { type Dayjs } from 'dayjs'; -import type { ChangeEvent } from 'react'; -import { Button, Form, Modal } from 'react-bootstrap'; -import { currencyOptions } from 'utils/currency'; -import type { InterfaceCreatePledge } from 'utils/interfaces'; -import styles from './FundCampaignPledge.module.css'; -import React from 'react'; - -interface InterfaceUpdatePledgeModal { - updatePledgeModalIsOpen: boolean; - hideUpdatePledgeModal: () => void; - formState: InterfaceCreatePledge; - setFormState: (state: React.SetStateAction) => void; - updatePledgeHandler: (e: ChangeEvent) => Promise; - startDate: Date; - endDate: Date; - t: (key: string) => string; - tCommon: (key: string) => string; -} -const PledgeEditModal: React.FC = ({ - updatePledgeModalIsOpen, - hideUpdatePledgeModal, - formState, - setFormState, - updatePledgeHandler, - startDate, - endDate, - t, - tCommon, -}) => { - return ( - <> - - -

    {t('editPledge')}

    - -
    - -
    - -
    - { - if (date) { - setFormState({ - ...formState, - pledgeStartDate: date.toDate(), - pledgeEndDate: - formState.pledgeEndDate && - (formState.pledgeEndDate < date?.toDate() - ? date.toDate() - : formState.pledgeEndDate), - }); - } - }} - minDate={dayjs(startDate)} - /> -
    -
    - { - if (date) { - setFormState({ - ...formState, - pledgeEndDate: date.toDate(), - }); - } - }} - minDate={dayjs(startDate)} - /> -
    -
    - - - {t('currency')} -
    - { - setFormState({ - ...formState, - pledgeCurrency: e.target.value, - }); - }} - > - - {currencyOptions.map((currency) => ( - - ))} - -
    -
    - - {t('amount')} - { - if (parseInt(e.target.value) > 0) { - setFormState({ - ...formState, - pledgeAmount: parseInt(e.target.value), - }); - } - }} - /> - -
    - - -
    -
    - - ); -}; -export default PledgeEditModal; diff --git a/src/screens/FundCampaignPledge/PledgeModal.test.tsx b/src/screens/FundCampaignPledge/PledgeModal.test.tsx new file mode 100644 index 0000000000..49c0447992 --- /dev/null +++ b/src/screens/FundCampaignPledge/PledgeModal.test.tsx @@ -0,0 +1,213 @@ +import type { ApolloLink } from '@apollo/client'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import type { RenderResult } from '@testing-library/react'; +import { + cleanup, + fireEvent, + render, + screen, + waitFor, +} from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import i18nForTest from '../../utils/i18nForTest'; +import { PLEDGE_MODAL_MOCKS } from './PledgesMocks'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { toast } from 'react-toastify'; +import type { InterfacePledgeModal } from './PledgeModal'; +import PledgeModal from './PledgeModal'; +import React from 'react'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +jest.mock('@mui/x-date-pickers/DateTimePicker', () => { + return { + DateTimePicker: jest.requireActual( + '@mui/x-date-pickers/DesktopDateTimePicker', + ).DesktopDateTimePicker, + }; +}); + +const link1 = new StaticMockLink(PLEDGE_MODAL_MOCKS); +const translations = JSON.parse( + JSON.stringify(i18nForTest.getDataByLanguage('en')?.translation.pledges), +); + +const pledgeProps: InterfacePledgeModal[] = [ + { + isOpen: true, + hide: jest.fn(), + pledge: { + _id: '1', + amount: 100, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-01-10', + users: [ + { + _id: '1', + firstName: 'John', + lastName: 'Doe', + image: null, + }, + ], + }, + refetchPledge: jest.fn(), + campaignId: 'campaignId', + orgId: 'orgId', + endDate: new Date(), + mode: 'create', + }, + { + isOpen: true, + hide: jest.fn(), + pledge: { + _id: '1', + amount: 100, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-01-10', + users: [ + { + _id: '1', + firstName: 'John', + lastName: 'Doe', + image: null, + }, + ], + }, + refetchPledge: jest.fn(), + campaignId: 'campaignId', + orgId: 'orgId', + endDate: new Date(), + mode: 'edit', + }, +]; +const renderPledgeModal = ( + link: ApolloLink, + props: InterfacePledgeModal, +): RenderResult => { + return render( + + + + + + + + + + + , + ); +}; + +describe('PledgeModal', () => { + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId', fundCampaignId: 'fundCampaignId' }), + })); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + afterEach(() => { + cleanup(); + }); + it('should populate form fields with correct values in edit mode', async () => { + renderPledgeModal(link1, pledgeProps[1]); + await waitFor(() => + expect(screen.getByText(translations.editPledge)).toBeInTheDocument(), + ); + expect(screen.getByTestId('pledgerSelect')).toHaveTextContent('John Doe'); + expect(screen.getByLabelText('Start Date')).toHaveValue('01/01/2024'); + expect(screen.getByLabelText('End Date')).toHaveValue('10/01/2024'); + expect(screen.getByLabelText('Currency')).toHaveTextContent('USD ($)'); + expect(screen.getByLabelText('Amount')).toHaveValue('100'); + }); + + it('should update pledgeAmount when input value changes', async () => { + renderPledgeModal(link1, pledgeProps[1]); + const amountInput = screen.getByLabelText('Amount'); + expect(amountInput).toHaveValue('100'); + fireEvent.change(amountInput, { target: { value: '200' } }); + expect(amountInput).toHaveValue('200'); + }); + + it('should not update pledgeAmount when input value is less than or equal to 0', async () => { + renderPledgeModal(link1, pledgeProps[1]); + const amountInput = screen.getByLabelText('Amount'); + expect(amountInput).toHaveValue('100'); + fireEvent.change(amountInput, { target: { value: '-10' } }); + expect(amountInput).toHaveValue('100'); + }); + + it('should update pledgeStartDate when a new date is selected', async () => { + renderPledgeModal(link1, pledgeProps[1]); + const startDateInput = screen.getByLabelText('Start Date'); + fireEvent.change(startDateInput, { target: { value: '02/01/2024' } }); + expect(startDateInput).toHaveValue('02/01/2024'); + expect(pledgeProps[1].pledge?.startDate).toEqual('2024-01-01'); + }); + + it('pledgeStartDate onChange when its null', async () => { + renderPledgeModal(link1, pledgeProps[1]); + const startDateInput = screen.getByLabelText('Start Date'); + fireEvent.change(startDateInput, { target: { value: null } }); + expect(pledgeProps[1].pledge?.startDate).toEqual('2024-01-01'); + }); + + it('should update pledgeEndDate when a new date is selected', async () => { + renderPledgeModal(link1, pledgeProps[1]); + const startDateInput = screen.getByLabelText('End Date'); + fireEvent.change(startDateInput, { target: { value: '02/01/2024' } }); + expect(startDateInput).toHaveValue('02/01/2024'); + expect(pledgeProps[1].pledge?.endDate).toEqual('2024-01-10'); + }); + + it('pledgeEndDate onChange when its null', async () => { + renderPledgeModal(link1, pledgeProps[1]); + const endDateInput = screen.getByLabelText('End Date'); + fireEvent.change(endDateInput, { target: { value: null } }); + expect(pledgeProps[1].pledge?.endDate).toEqual('2024-01-10'); + }); + + it('should create pledge', async () => { + renderPledgeModal(link1, pledgeProps[0]); + + fireEvent.change(screen.getByLabelText('Amount'), { + target: { value: '200' }, + }); + fireEvent.change(screen.getByLabelText('Start Date'), { + target: { value: '02/01/2024' }, + }); + fireEvent.change(screen.getByLabelText('End Date'), { + target: { value: '02/01/2024' }, + }); + + expect(screen.getByLabelText('Amount')).toHaveValue('200'); + expect(screen.getByLabelText('Start Date')).toHaveValue('02/01/2024'); + expect(screen.getByLabelText('End Date')).toHaveValue('02/01/2024'); + expect(screen.getByTestId('submitPledgeBtn')).toBeInTheDocument(); + + fireEvent.click(screen.getByTestId('submitPledgeBtn')); + + await waitFor(() => { + expect(toast.success).toHaveBeenCalled(); + expect(pledgeProps[0].refetchPledge).toHaveBeenCalled(); + expect(pledgeProps[0].hide).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/screens/FundCampaignPledge/PledgeModal.tsx b/src/screens/FundCampaignPledge/PledgeModal.tsx new file mode 100644 index 0000000000..3e22d604a0 --- /dev/null +++ b/src/screens/FundCampaignPledge/PledgeModal.tsx @@ -0,0 +1,322 @@ +import { DatePicker } from '@mui/x-date-pickers'; +import dayjs, { type Dayjs } from 'dayjs'; +import type { ChangeEvent } from 'react'; +import { Button, Form, Modal } from 'react-bootstrap'; +import { currencyOptions, currencySymbols } from 'utils/currency'; +import type { + InterfaceCreatePledge, + InterfacePledgeInfo, + InterfacePledger, +} from 'utils/interfaces'; +import styles from './FundCampaignPledge.module.css'; +import React, { useCallback, useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useMutation, useQuery } from '@apollo/client'; +import { CREATE_PlEDGE, UPDATE_PLEDGE } from 'GraphQl/Mutations/PledgeMutation'; +import { toast } from 'react-toastify'; +import { + Autocomplete, + FormControl, + InputLabel, + MenuItem, + Select, + TextField, +} from '@mui/material'; + +import { MEMBERS_LIST } from 'GraphQl/Queries/Queries'; + +export interface InterfacePledgeModal { + isOpen: boolean; + hide: () => void; + campaignId: string; + orgId: string; + pledge: InterfacePledgeInfo | null; + refetchPledge: () => void; + endDate: Date; + mode: 'create' | 'edit'; +} +const PledgeModal: React.FC = ({ + isOpen, + hide, + campaignId, + orgId, + pledge, + refetchPledge, + endDate, + mode, +}) => { + const { t } = useTranslation('translation', { + keyPrefix: 'pledges', + }); + const { t: tCommon } = useTranslation('common'); + + const [formState, setFormState] = useState({ + pledgeUsers: [], + pledgeAmount: pledge?.amount ?? 0, + pledgeCurrency: pledge?.currency ?? 'USD', + pledgeEndDate: new Date(pledge?.endDate ?? new Date()), + pledgeStartDate: new Date(pledge?.startDate ?? new Date()), + }); + const [pledgers, setPledgers] = useState([]); + const [updatePledge] = useMutation(UPDATE_PLEDGE); + const [createPledge] = useMutation(CREATE_PlEDGE); + + const { data: memberData } = useQuery(MEMBERS_LIST, { + variables: { id: orgId }, + }); + + useEffect(() => { + setFormState({ + pledgeUsers: pledge?.users ?? [], + pledgeAmount: pledge?.amount ?? 0, + pledgeCurrency: pledge?.currency ?? 'USD', + pledgeEndDate: new Date(pledge?.endDate ?? new Date()), + pledgeStartDate: new Date(pledge?.startDate ?? new Date()), + }); + }, [pledge]); + + useEffect(() => { + if (memberData) { + /*istanbul ignore next*/ + setPledgers(memberData.organizations[0].members); + } + }, [memberData]); + + const { + pledgeUsers, + pledgeAmount, + pledgeCurrency, + pledgeStartDate, + pledgeEndDate, + } = formState; + + /*istanbul ignore next*/ + const updatePledgeHandler = useCallback( + async (e: ChangeEvent): Promise => { + e.preventDefault(); + const startDate = dayjs(pledgeStartDate).format('YYYY-MM-DD'); + const endDate = dayjs(pledgeEndDate).format('YYYY-MM-DD'); + + const updatedFields: { + [key: string]: number | string | string[] | undefined; + } = {}; + // checks if there are changes to the pledge and adds them to the updatedFields object + if (pledgeAmount !== pledge?.amount) { + updatedFields.amount = pledgeAmount; + } + if (pledgeCurrency !== pledge?.currency) { + updatedFields.currency = pledgeCurrency; + } + if (startDate !== dayjs(pledge?.startDate).format('YYYY-MM-DD')) { + updatedFields.startDate = startDate; + } + if (endDate !== dayjs(pledge?.endDate).format('YYYY-MM-DD')) { + updatedFields.endDate = endDate; + } + if (pledgeUsers !== pledge?.users) { + updatedFields.users = pledgeUsers.map((user) => user._id); + } + try { + await updatePledge({ + variables: { + id: pledge?._id, + ...updatedFields, + }, + }); + toast.success(t('pledgeUpdated')); + refetchPledge(); + hide(); + } catch (error: unknown) { + toast.error((error as Error).message); + } + }, + [formState, pledge], + ); + + // Function to create a new pledge + const createPledgeHandler = useCallback( + async (e: ChangeEvent): Promise => { + try { + e.preventDefault(); + await createPledge({ + variables: { + campaignId, + amount: pledgeAmount, + currency: pledgeCurrency, + startDate: dayjs(pledgeStartDate).format('YYYY-MM-DD'), + endDate: dayjs(pledgeEndDate).format('YYYY-MM-DD'), + userIds: pledgeUsers.map((user) => user._id), + }, + }); + + toast.success(t('pledgeCreated')); + refetchPledge(); + setFormState({ + pledgeUsers: [], + pledgeAmount: 0, + pledgeCurrency: 'USD', + pledgeEndDate: new Date(), + pledgeStartDate: new Date(), + }); + hide(); + } catch (error: unknown) { + /*istanbul ignore next*/ + toast.error((error as Error).message); + } + }, + [formState, campaignId], + ); + + return ( + + +

    + {t(mode === 'edit' ? 'editPledge' : 'createPledge')} +

    + +
    + +
    + {/* A Multi-select dropdown enables admin to select more than one pledger for participating in a pledge */} + + option._id === value._id} + filterSelectedOptions={true} + getOptionLabel={(member: InterfacePledger): string => + `${member.firstName} ${member.lastName}` + } + onChange={ + /*istanbul ignore next*/ + (_, newPledgers): void => { + setFormState({ + ...formState, + pledgeUsers: newPledgers, + }); + } + } + renderInput={(params) => ( + + )} + /> + + + {/* Date Calendar Component to select start date of an event */} + { + if (date) { + setFormState({ + ...formState, + pledgeStartDate: date.toDate(), + pledgeEndDate: + pledgeEndDate && + /*istanbul ignore next*/ + (pledgeEndDate < date?.toDate() + ? date.toDate() + : pledgeEndDate), + }); + } + }} + minDate={dayjs(pledgeStartDate)} + maxDate={dayjs(endDate)} + /> + {/* Date Calendar Component to select end Date of an event */} + { + if (date) { + setFormState({ + ...formState, + pledgeEndDate: date.toDate(), + }); + } + }} + minDate={dayjs(pledgeStartDate)} + maxDate={dayjs(endDate)} + /> + + + {/* Dropdown to select the currency in which amount is to be pledged */} + + + {t('currency')} + + + + {/* Input field to enter amount to be pledged */} + + { + if (parseInt(e.target.value) > 0) { + setFormState({ + ...formState, + pledgeAmount: parseInt(e.target.value), + }); + } + }} + /> + + + {/* Button to submit the pledge form */} + + +
    +
    + ); +}; +export default PledgeModal; diff --git a/src/screens/FundCampaignPledge/PledgesMocks.ts b/src/screens/FundCampaignPledge/PledgesMocks.ts index e5d668d53e..71d74b1805 100644 --- a/src/screens/FundCampaignPledge/PledgesMocks.ts +++ b/src/screens/FundCampaignPledge/PledgesMocks.ts @@ -3,6 +3,7 @@ import { DELETE_PLEDGE, UPDATE_PLEDGE, } from 'GraphQl/Mutations/PledgeMutation'; +import { MEMBERS_LIST } from 'GraphQl/Queries/Queries'; import { FUND_CAMPAIGN_PLEDGE } from 'GraphQl/Queries/fundQueries'; export const MOCKS = [ @@ -10,25 +11,85 @@ export const MOCKS = [ request: { query: FUND_CAMPAIGN_PLEDGE, variables: { - id: undefined, + id: 'fundCampaignId', + orderBy: 'endDate_DESC', }, }, result: { data: { getFundraisingCampaignById: { + name: 'Campaign Name', + fundingGoal: 1000, + currency: 'USD', startDate: '2024-01-01', - endDate: '2024-01-01', + endDate: '2024-08-08', pledges: [ { _id: '1', amount: 100, currency: 'USD', startDate: '2024-01-01', - endDate: '2024-01-01', + endDate: '2024-01-10', users: [ { _id: '1', firstName: 'John', + lastName: 'Doe', + image: 'img-url', + }, + { + _id: '2', + firstName: 'John', + lastName: 'Doe2', + image: 'img-url2', + }, + { + _id: '3', + firstName: 'John', + lastName: 'Doe3', + image: 'img-url3', + }, + { + _id: '4', + firstName: 'John', + lastName: 'Doe4', + image: 'img-url4', + }, + { + _id: '5', + firstName: 'John', + lastName: 'Doe5', + image: 'img-url5', + }, + { + _id: '6', + firstName: 'John', + lastName: 'Doe6', + image: 'img-url6', + }, + { + _id: '7', + firstName: 'John', + lastName: 'Doe7', + image: 'img-url7', + }, + { + _id: '8', + firstName: 'John', + lastName: 'Doe8', + image: 'img-url8', + }, + { + _id: '9', + firstName: 'John', + lastName: 'Doe9', + image: 'img-url9', + }, + { + _id: '10', + firstName: 'John', + lastName: 'Doe10', + image: null, }, ], }, @@ -36,12 +97,14 @@ export const MOCKS = [ _id: '2', amount: 200, currency: 'USD', - startDate: '2024-03-03', - endDate: '2024-04-03', + startDate: '2024-01-01', + endDate: '2024-01-09', users: [ { _id: '2', firstName: 'Jane', + lastName: 'Doe', + image: null, }, ], }, @@ -52,39 +115,156 @@ export const MOCKS = [ }, { request: { - query: CREATE_PlEDGE, + query: FUND_CAMPAIGN_PLEDGE, variables: { - campaignId: undefined, - amount: 100, - currency: 'USD', - startDate: '2024-03-10', - endDate: '2024-03-10', - userIds: [null], + id: 'fundCampaignId', + orderBy: 'endDate_ASC', }, }, result: { data: { - createFundraisingCampaignPledge: { - _id: '3', + getFundraisingCampaignById: { + name: 'Campaign Name', + fundingGoal: 1000, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-08-08', + pledges: [ + { + _id: '2', + amount: 200, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-01-09', + users: [ + { + _id: '2', + firstName: 'Jane', + lastName: 'Doe', + image: null, + }, + ], + }, + { + _id: '1', + amount: 100, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-01-10', + users: [ + { + _id: '1', + firstName: 'John', + lastName: 'Doe', + image: null, + }, + ], + }, + ], }, }, }, }, { request: { - query: UPDATE_PLEDGE, + query: FUND_CAMPAIGN_PLEDGE, variables: { - id: '1', - amount: 100100, - currency: 'INR', - startDate: '2024-03-10', - endDate: '2024-03-10', + id: 'fundCampaignId', + orderBy: 'amount_DESC', }, }, result: { data: { - updateFundraisingCampaignPledge: { - _id: '1', + getFundraisingCampaignById: { + name: 'Campaign Name', + fundingGoal: 1000, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-08-08', + pledges: [ + { + _id: '2', + amount: 200, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-01-09', + users: [ + { + _id: '2', + firstName: 'Jane', + lastName: 'Doe', + image: null, + }, + ], + }, + { + _id: '1', + amount: 100, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-01-10', + users: [ + { + _id: '1', + firstName: 'John', + lastName: 'Doe', + image: null, + }, + ], + }, + ], + }, + }, + }, + }, + { + request: { + query: FUND_CAMPAIGN_PLEDGE, + variables: { + id: 'fundCampaignId', + orderBy: 'amount_ASC', + }, + }, + result: { + data: { + getFundraisingCampaignById: { + name: 'Campaign Name', + fundingGoal: 1000, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-08-08', + pledges: [ + { + _id: '1', + amount: 100, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-01-10', + users: [ + { + _id: '1', + firstName: 'John', + lastName: 'Doe', + image: null, + }, + ], + }, + { + _id: '2', + amount: 200, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-01-09', + users: [ + { + _id: '2', + firstName: 'Jane', + lastName: 'Doe', + image: null, + }, + ], + }, + ], }, }, }, @@ -105,12 +285,14 @@ export const MOCKS = [ }, }, ]; + export const MOCKS_FUND_CAMPAIGN_PLEDGE_ERROR = [ { request: { query: FUND_CAMPAIGN_PLEDGE, variables: { - id: undefined, + id: 'fundCampaignId', + orderBy: 'endDate_DESC', }, }, error: new Error('Error fetching pledges'), @@ -166,17 +348,18 @@ export const MOCKS_CREATE_PLEDGE_ERROR = [ request: { query: CREATE_PlEDGE, variables: { - campaignId: undefined, - amount: 100, + campaignId: 'campaignId', + amount: 200, currency: 'USD', - startDate: '2024-03-10', - endDate: '2024-03-10', - userIds: null, + startDate: '2024-01-02', + endDate: '2024-01-02', + userIds: ['1'], }, }, error: new Error('Error creating pledge'), }, ]; + export const MOCKS_UPDATE_PLEDGE_ERROR = [ { request: { @@ -236,6 +419,7 @@ export const MOCKS_UPDATE_PLEDGE_ERROR = [ error: new Error('Error updating pledge'), }, ]; + export const MOCKS_DELETE_PLEDGE_ERROR = [ { request: { @@ -291,17 +475,22 @@ export const MOCKS_DELETE_PLEDGE_ERROR = [ error: new Error('Error deleting pledge'), }, ]; + export const EMPTY_MOCKS = [ { request: { query: FUND_CAMPAIGN_PLEDGE, variables: { - id: undefined, + id: 'fundCampaignId', + orderBy: 'endDate_DESC', }, }, result: { data: { getFundraisingCampaignById: { + name: 'Campaign Name', + fundingGoal: 1000, + currency: 'USD', startDate: '2024-01-01', endDate: '2024-01-01', pledges: [], @@ -310,3 +499,81 @@ export const EMPTY_MOCKS = [ }, }, ]; + +export const PLEDGE_MODAL_MOCKS = [ + { + request: { + query: MEMBERS_LIST, + variables: { + id: 'orgId', + }, + }, + result: { + data: { + organizations: [ + { + _id: 'orgId', + members: [ + { + createdAt: '2023-04-13T04:53:17.742Z', + email: 'testuser4@example.com', + firstName: 'John', + image: 'img-url', + lastName: 'Doe', + organizationsBlockedBy: [], + __typename: 'User', + _id: '1', + }, + { + createdAt: '2024-04-13T04:53:17.742Z', + email: 'testuser2@example.com', + firstName: 'Anna', + image: null, + lastName: 'Bradley', + organizationsBlockedBy: [], + __typename: 'User', + _id: '2', + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: UPDATE_PLEDGE, + variables: { + id: '1', + amount: 200, + }, + }, + result: { + data: { + updateFundraisingCampaignPledge: { + _id: '1', + }, + }, + }, + }, + { + request: { + query: CREATE_PlEDGE, + variables: { + campaignId: 'campaignId', + amount: 200, + currency: 'USD', + startDate: '2024-01-02', + endDate: '2024-01-02', + userIds: ['1'], + }, + }, + result: { + data: { + createFundraisingCampaignPledge: { + _id: '3', + }, + }, + }, + }, +]; diff --git a/src/screens/LoginPage/LoginPage.tsx b/src/screens/LoginPage/LoginPage.tsx index 56f2d38159..24b247e427 100644 --- a/src/screens/LoginPage/LoginPage.tsx +++ b/src/screens/LoginPage/LoginPage.tsx @@ -34,6 +34,7 @@ import { socialMediaLinks } from '../../constants'; import styles from './LoginPage.module.css'; import type { InterfaceQueryOrganizationListObject } from 'utils/interfaces'; import { Autocomplete, TextField } from '@mui/material'; +import i18n from 'utils/i18n'; const loginPage = (): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'loginPage' }); @@ -133,7 +134,7 @@ const loginPage = (): JSX.Element => { id: string; }; tempObj['label'] = - `${org.name}(${org.address.city},${org.address.state},${org.address.countryCode})`; + `${org.name}(${org.address?.city},${org.address?.state},${org.address?.countryCode})`; tempObj['id'] = org._id; return tempObj; }, @@ -290,6 +291,7 @@ const loginPage = (): JSX.Element => { /* istanbul ignore next */ if (loginData) { + i18n.changeLanguage(loginData.login.appUserProfile.appLanguageCode); const { login } = loginData; const { user, appUserProfile } = login; const isAdmin: boolean = diff --git a/src/screens/MemberDetail/MemberDetail.tsx b/src/screens/MemberDetail/MemberDetail.tsx index 49b9f60a7a..be9b891b3c 100644 --- a/src/screens/MemberDetail/MemberDetail.tsx +++ b/src/screens/MemberDetail/MemberDetail.tsx @@ -185,7 +185,7 @@ const MemberDetail: React.FC = ({ id }): JSX.Element => { setItem('Email', email); setItem('UserImage', image); } - toast.success('Successful updated'); + toast.success(tCommon('successfullyUpdated')); } } catch (error: unknown) { if (error instanceof Error) { @@ -490,7 +490,6 @@ const MemberDetail: React.FC = ({ id }): JSX.Element => {
    + + + + + +
    + + + + + + ); +} + +export default organizationAgendaCategory; diff --git a/src/screens/OrganizationAgendaCategory/OrganizationAgendaCategoryErrorMocks.ts b/src/screens/OrganizationAgendaCategory/OrganizationAgendaCategoryErrorMocks.ts new file mode 100644 index 0000000000..10809c3da8 --- /dev/null +++ b/src/screens/OrganizationAgendaCategory/OrganizationAgendaCategoryErrorMocks.ts @@ -0,0 +1,51 @@ +import { CREATE_AGENDA_ITEM_CATEGORY_MUTATION } from 'GraphQl/Mutations/AgendaCategoryMutations'; + +import { AGENDA_ITEM_CATEGORY_LIST } from 'GraphQl/Queries/AgendaCategoryQueries'; + +export const MOCKS_ERROR_AGENDA_ITEM_CATEGORY_LIST_QUERY = [ + { + request: { + query: AGENDA_ITEM_CATEGORY_LIST, + variables: { organizationId: '123' }, + }, + error: new Error('Mock Graphql Error'), + }, +]; + +export const MOCKS_ERROR_MUTATION = [ + { + request: { + query: AGENDA_ITEM_CATEGORY_LIST, + variables: { organizationId: '123' }, + }, + result: { + data: { + agendaItemCategoriesByOrganization: [ + { + _id: 'agendaItemCategory1', + name: 'Category', + description: 'Test Description', + createdBy: { + _id: 'user1', + firstName: 'Harve', + lastName: 'Lance', + }, + }, + ], + }, + }, + }, + { + request: { + query: CREATE_AGENDA_ITEM_CATEGORY_MUTATION, + variables: { + input: { + organizationId: '123', + name: 'Category', + description: 'Test Description', + }, + }, + }, + error: new Error('Mock Graphql Error'), + }, +]; diff --git a/src/screens/OrganizationAgendaCategory/OrganizationAgendaCategoryMocks.ts b/src/screens/OrganizationAgendaCategory/OrganizationAgendaCategoryMocks.ts new file mode 100644 index 0000000000..434b0dcad2 --- /dev/null +++ b/src/screens/OrganizationAgendaCategory/OrganizationAgendaCategoryMocks.ts @@ -0,0 +1,47 @@ +import { CREATE_AGENDA_ITEM_CATEGORY_MUTATION } from 'GraphQl/Mutations/AgendaCategoryMutations'; + +import { AGENDA_ITEM_CATEGORY_LIST } from 'GraphQl/Queries/AgendaCategoryQueries'; + +export const MOCKS = [ + { + request: { + query: AGENDA_ITEM_CATEGORY_LIST, + variables: { organizationId: '123' }, + }, + result: { + data: { + agendaItemCategoriesByOrganization: [ + { + _id: 'agendaItemCategory1', + name: 'Category', + description: 'Test Description', + createdBy: { + _id: 'user1', + firstName: 'Harve', + lastName: 'Lance', + }, + }, + ], + }, + }, + }, + { + request: { + query: CREATE_AGENDA_ITEM_CATEGORY_MUTATION, + variables: { + input: { + organizationId: '123', + name: 'Category', + description: 'Test Description', + }, + }, + }, + result: { + data: { + createAgendaCategory: { + _id: 'agendaItemCategory1', + }, + }, + }, + }, +]; diff --git a/src/screens/OrganizationFundCampaign/CampaignCreateModal.tsx b/src/screens/OrganizationFundCampaign/CampaignCreateModal.tsx deleted file mode 100644 index a466e9326e..0000000000 --- a/src/screens/OrganizationFundCampaign/CampaignCreateModal.tsx +++ /dev/null @@ -1,158 +0,0 @@ -import { DatePicker } from '@mui/x-date-pickers'; -import type { Dayjs } from 'dayjs'; -import dayjs from 'dayjs'; -import type { ChangeEvent } from 'react'; -import React from 'react'; -import { Button, Col, Form, Modal } from 'react-bootstrap'; -import { currencyOptions } from 'utils/currency'; -import type { InterfaceCreateCampaign } from 'utils/interfaces'; -import styles from './OrganizationFundCampaign.module.css'; - -interface InterfaceCampaignCreateModal { - campaignCreateModalIsOpen: boolean; - hideCreateCampaignModal: () => void; - formState: InterfaceCreateCampaign; - setFormState: (state: React.SetStateAction) => void; - createCampaignHandler: (e: ChangeEvent) => Promise; - t: (key: string) => string; -} - -const CampaignCreateModal: React.FC = ({ - campaignCreateModalIsOpen, - hideCreateCampaignModal, - formState, - setFormState, - createCampaignHandler, - t, -}) => { - return ( - <> - - -

    {t('createCampaign')}

    - -
    - -
    - - {t('campaignName')} - - setFormState({ - ...formState, - campaignName: e.target.value, - }) - } - /> - - -
    - { - if (date) { - setFormState({ - ...formState, - campaignStartDate: date.toDate(), - campaignEndDate: - formState.campaignEndDate && - (formState.campaignEndDate < date?.toDate() - ? date.toDate() - : formState.campaignEndDate), - }); - } - }} - minDate={dayjs(new Date())} - /> -
    -
    - { - if (date) { - setFormState({ - ...formState, - campaignEndDate: date.toDate(), - }); - } - }} - minDate={dayjs(formState.campaignStartDate)} - /> -
    -
    - - - {t('currency')} -
    - { - setFormState({ - ...formState, - campaignCurrency: e.target.value, - }); - }} - > - - {currencyOptions.map((currency) => ( - - ))} - - - - - {t('fundingGoal')} - { - if (parseInt(e.target.value) > 0) { - setFormState({ - ...formState, - campaignGoal: parseInt(e.target.value), - }); - } - }} - /> - - - - - - - - ); -}; -export default CampaignCreateModal; diff --git a/src/screens/OrganizationFundCampaign/CampaignDeleteModal.test.tsx b/src/screens/OrganizationFundCampaign/CampaignDeleteModal.test.tsx new file mode 100644 index 0000000000..7baf9bd933 --- /dev/null +++ b/src/screens/OrganizationFundCampaign/CampaignDeleteModal.test.tsx @@ -0,0 +1,95 @@ +import React from 'react'; +import type { ApolloLink } from '@apollo/client'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import type { RenderResult } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import i18nForTest from '../../utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { toast } from 'react-toastify'; +import { MOCKS, MOCK_ERROR } from './OrganizationFundCampaignMocks'; +import CampaignDeleteModal, { + type InterfaceDeleteCampaignModal, +} from './CampaignDeleteModal'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(MOCK_ERROR); +const translations = JSON.parse( + JSON.stringify(i18nForTest.getDataByLanguage('en')?.translation.fundCampaign), +); + +const campaignProps: InterfaceDeleteCampaignModal = { + isOpen: true, + hide: jest.fn(), + campaign: { + _id: 'campaignId1', + name: 'Campaign 1', + fundingGoal: 100, + startDate: new Date('2021-01-01'), + endDate: new Date('2024-01-01'), + currency: 'USD', + createdAt: '2021-01-01', + }, + refetchCampaign: jest.fn(), +}; +const renderFundDeleteModal = ( + link: ApolloLink, + props: InterfaceDeleteCampaignModal, +): RenderResult => { + return render( + + + + + + + + + + + , + ); +}; + +describe('CampaignDeleteModal', () => { + it('should render CampaignDeleteModal', () => { + renderFundDeleteModal(link1, campaignProps); + expect(screen.getByTestId('deleteCampaignCloseBtn')).toBeInTheDocument(); + }); + + it('should successfully Delete Campaign', async () => { + renderFundDeleteModal(link1, campaignProps); + expect(screen.getByTestId('deleteCampaignCloseBtn')).toBeInTheDocument(); + + fireEvent.click(screen.getByTestId('deleteyesbtn')); + + await waitFor(() => { + expect(campaignProps.refetchCampaign).toHaveBeenCalled(); + expect(campaignProps.hide).toHaveBeenCalled(); + expect(toast.success).toHaveBeenCalledWith(translations.deletedCampaign); + }); + }); + + it('should fail to Delete Campaign', async () => { + renderFundDeleteModal(link2, campaignProps); + expect(screen.getByTestId('deleteCampaignCloseBtn')).toBeInTheDocument(); + + fireEvent.click(screen.getByTestId('deleteyesbtn')); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalledWith('Mock graphql error'); + }); + }); +}); diff --git a/src/screens/OrganizationFundCampaign/CampaignDeleteModal.tsx b/src/screens/OrganizationFundCampaign/CampaignDeleteModal.tsx index 58351e1d1d..840c4869bb 100644 --- a/src/screens/OrganizationFundCampaign/CampaignDeleteModal.tsx +++ b/src/screens/OrganizationFundCampaign/CampaignDeleteModal.tsx @@ -1,29 +1,53 @@ import React from 'react'; import { Button, Modal } from 'react-bootstrap'; import styles from './OrganizationFundCampaign.module.css'; +import { useMutation } from '@apollo/client'; +import { DELETE_CAMPAIGN_MUTATION } from 'GraphQl/Mutations/CampaignMutation'; +import type { InterfaceCampaignInfo } from 'utils/interfaces'; +import { toast } from 'react-toastify'; +import { useTranslation } from 'react-i18next'; -interface InterfaceDeleteCampaignModal { - campaignDeleteModalIsOpen: boolean; - hideDeleteCampaignModal: () => void; - deleteCampaignHandler: () => Promise; - t: (key: string) => string; - tCommon: (key: string) => string; +export interface InterfaceDeleteCampaignModal { + isOpen: boolean; + hide: () => void; + campaign: InterfaceCampaignInfo | null; + refetchCampaign: () => void; } const CampaignDeleteModal: React.FC = ({ - campaignDeleteModalIsOpen, - hideDeleteCampaignModal, - deleteCampaignHandler, - t, - tCommon, + isOpen, + hide, + campaign, + refetchCampaign, }) => { + const { t } = useTranslation('translation', { + keyPrefix: 'fundCampaign', + }); + const { t: tCommon } = useTranslation('common'); + + const [deleteCampaign] = useMutation(DELETE_CAMPAIGN_MUTATION); + + const deleteCampaignHandler = async (): Promise => { + try { + await deleteCampaign({ + variables: { + id: campaign?._id, + }, + }); + toast.success(t('deletedCampaign')); + refetchCampaign(); + hide(); + } catch (error: unknown) { + toast.error((error as Error).message); + } + }; return ( <> - +

    {t('deleteCampaign')}

    - diff --git a/src/screens/OrganizationFundCampaign/CampaignModal.test.tsx b/src/screens/OrganizationFundCampaign/CampaignModal.test.tsx new file mode 100644 index 0000000000..cdf631f87c --- /dev/null +++ b/src/screens/OrganizationFundCampaign/CampaignModal.test.tsx @@ -0,0 +1,266 @@ +import React from 'react'; +import type { ApolloLink } from '@apollo/client'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import type { RenderResult } from '@testing-library/react'; +import { + cleanup, + fireEvent, + render, + screen, + waitFor, +} from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import i18nForTest from '../../utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { toast } from 'react-toastify'; +import { MOCKS, MOCK_ERROR } from './OrganizationFundCampaignMocks'; +import type { InterfaceCampaignModal } from './CampaignModal'; +import CampaignModal from './CampaignModal'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +jest.mock('@mui/x-date-pickers/DateTimePicker', () => { + return { + DateTimePicker: jest.requireActual( + '@mui/x-date-pickers/DesktopDateTimePicker', + ).DesktopDateTimePicker, + }; +}); + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(MOCK_ERROR); +const translations = JSON.parse( + JSON.stringify(i18nForTest.getDataByLanguage('en')?.translation.fundCampaign), +); + +const campaignProps: InterfaceCampaignModal[] = [ + { + isOpen: true, + hide: jest.fn(), + fundId: 'fundId', + campaign: { + _id: 'campaignId1', + name: 'Campaign 1', + fundingGoal: 100, + startDate: new Date('2021-01-01'), + endDate: new Date('2024-01-01'), + currency: 'USD', + createdAt: '2021-01-01', + }, + refetchCampaign: jest.fn(), + mode: 'create', + }, + { + isOpen: true, + hide: jest.fn(), + fundId: 'fundId', + campaign: { + _id: 'campaignId1', + name: 'Campaign 1', + fundingGoal: 100, + startDate: new Date('2021-01-01'), + endDate: new Date('2024-01-01'), + currency: 'USD', + createdAt: '2021-01-01', + }, + refetchCampaign: jest.fn(), + mode: 'edit', + }, +]; +const renderCampaignModal = ( + link: ApolloLink, + props: InterfaceCampaignModal, +): RenderResult => { + return render( + + + + + + + + + + + , + ); +}; + +describe('CampaignModal', () => { + afterEach(() => { + jest.clearAllMocks(); + cleanup(); + }); + + it('should populate form fields with correct values in edit mode', async () => { + renderCampaignModal(link1, campaignProps[1]); + await waitFor(() => + expect(screen.getAllByText(translations.updateCampaign)).toHaveLength(2), + ); + + expect(screen.getByLabelText(translations.campaignName)).toHaveValue( + 'Campaign 1', + ); + expect(screen.getByLabelText('Start Date')).toHaveValue('01/01/2021'); + expect(screen.getByLabelText('End Date')).toHaveValue('01/01/2024'); + expect(screen.getByLabelText(translations.currency)).toHaveTextContent( + 'USD ($)', + ); + expect(screen.getByLabelText(translations.fundingGoal)).toHaveValue('100'); + }); + + it('should update fundingGoal when input value changes', async () => { + renderCampaignModal(link1, campaignProps[1]); + const goalInput = screen.getByLabelText(translations.fundingGoal); + expect(goalInput).toHaveValue('100'); + fireEvent.change(goalInput, { target: { value: '200' } }); + expect(goalInput).toHaveValue('200'); + }); + + it('should not update fundingGoal when input value is less than or equal to 0', async () => { + renderCampaignModal(link1, campaignProps[1]); + const goalInput = screen.getByLabelText(translations.fundingGoal); + expect(goalInput).toHaveValue('100'); + fireEvent.change(goalInput, { target: { value: '-10' } }); + expect(goalInput).toHaveValue('100'); + }); + + it('should update Start Date when a new date is selected', async () => { + renderCampaignModal(link1, campaignProps[1]); + const startDateInput = screen.getByLabelText('Start Date'); + fireEvent.change(startDateInput, { target: { value: '02/01/2024' } }); + expect(startDateInput).toHaveValue('02/01/2024'); + }); + + it('Start Date onChange when its null', async () => { + renderCampaignModal(link1, campaignProps[1]); + const startDateInput = screen.getByLabelText('Start Date'); + expect(startDateInput).toHaveValue('01/01/2021'); + fireEvent.change(startDateInput, { target: { value: null } }); + expect(startDateInput).toHaveValue(''); + }); + + it('should update End Date when a new date is selected', async () => { + renderCampaignModal(link1, campaignProps[1]); + const endDateInput = screen.getByLabelText('End Date'); + fireEvent.change(endDateInput, { target: { value: '02/01/2024' } }); + expect(endDateInput).toHaveValue('02/01/2024'); + }); + + it('End Date onChange when its null', async () => { + renderCampaignModal(link1, campaignProps[1]); + const endDateInput = screen.getByLabelText('End Date'); + fireEvent.change(endDateInput, { target: { value: null } }); + expect(endDateInput).toHaveValue(''); + }); + + it('should create campaign', async () => { + renderCampaignModal(link1, campaignProps[0]); + + const campaignName = screen.getByLabelText(translations.campaignName); + fireEvent.change(campaignName, { target: { value: 'Campaign 2' } }); + + const startDate = screen.getByLabelText('Start Date'); + fireEvent.change(startDate, { target: { value: '02/01/2024' } }); + + const endDate = screen.getByLabelText('End Date'); + fireEvent.change(endDate, { target: { value: '02/02/2024' } }); + + const fundingGoal = screen.getByLabelText(translations.fundingGoal); + fireEvent.change(fundingGoal, { target: { value: '200' } }); + + const submitBtn = screen.getByTestId('submitCampaignBtn'); + expect(submitBtn).toBeInTheDocument(); + fireEvent.click(submitBtn); + + await waitFor(() => { + expect(toast.success).toHaveBeenCalledWith(translations.createdCampaign); + expect(campaignProps[0].refetchCampaign).toHaveBeenCalled(); + expect(campaignProps[0].hide).toHaveBeenCalled(); + }); + }); + + it('should update campaign', async () => { + renderCampaignModal(link1, campaignProps[1]); + + const campaignName = screen.getByLabelText(translations.campaignName); + fireEvent.change(campaignName, { target: { value: 'Campaign 4' } }); + + const startDate = screen.getByLabelText('Start Date'); + fireEvent.change(startDate, { target: { value: '02/01/2023' } }); + + const endDate = screen.getByLabelText('End Date'); + fireEvent.change(endDate, { target: { value: '02/02/2023' } }); + + const fundingGoal = screen.getByLabelText(translations.fundingGoal); + fireEvent.change(fundingGoal, { target: { value: '400' } }); + + const submitBtn = screen.getByTestId('submitCampaignBtn'); + expect(submitBtn).toBeInTheDocument(); + + fireEvent.click(submitBtn); + await waitFor(() => { + expect(toast.success).toHaveBeenCalledWith(translations.updatedCampaign); + expect(campaignProps[1].refetchCampaign).toHaveBeenCalled(); + expect(campaignProps[1].hide).toHaveBeenCalled(); + }); + }); + + it('Error: should create campaign', async () => { + renderCampaignModal(link2, campaignProps[0]); + + const campaignName = screen.getByLabelText(translations.campaignName); + fireEvent.change(campaignName, { target: { value: 'Campaign 2' } }); + + const startDate = screen.getByLabelText('Start Date'); + fireEvent.change(startDate, { target: { value: '02/01/2024' } }); + + const endDate = screen.getByLabelText('End Date'); + fireEvent.change(endDate, { target: { value: '02/02/2024' } }); + + const fundingGoal = screen.getByLabelText(translations.fundingGoal); + fireEvent.change(fundingGoal, { target: { value: '200' } }); + + const submitBtn = screen.getByTestId('submitCampaignBtn'); + expect(submitBtn).toBeInTheDocument(); + fireEvent.click(submitBtn); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalledWith('Mock graphql error'); + }); + }); + + it('Error: should update campaign', async () => { + renderCampaignModal(link2, campaignProps[1]); + + const campaignName = screen.getByLabelText(translations.campaignName); + fireEvent.change(campaignName, { target: { value: 'Campaign 4' } }); + + const startDate = screen.getByLabelText('Start Date'); + fireEvent.change(startDate, { target: { value: '02/01/2023' } }); + + const endDate = screen.getByLabelText('End Date'); + fireEvent.change(endDate, { target: { value: '02/02/2023' } }); + + const fundingGoal = screen.getByLabelText(translations.fundingGoal); + fireEvent.change(fundingGoal, { target: { value: '400' } }); + + const submitBtn = screen.getByTestId('submitCampaignBtn'); + expect(submitBtn).toBeInTheDocument(); + + fireEvent.click(submitBtn); + await waitFor(() => { + expect(toast.error).toHaveBeenCalledWith('Mock graphql error'); + }); + }); +}); diff --git a/src/screens/OrganizationFundCampaign/CampaignModal.tsx b/src/screens/OrganizationFundCampaign/CampaignModal.tsx new file mode 100644 index 0000000000..dfe0738c07 --- /dev/null +++ b/src/screens/OrganizationFundCampaign/CampaignModal.tsx @@ -0,0 +1,291 @@ +import { DatePicker } from '@mui/x-date-pickers'; +import type { Dayjs } from 'dayjs'; +import dayjs from 'dayjs'; +import type { ChangeEvent } from 'react'; +import React, { useEffect, useState } from 'react'; +import { Button, Col, Form, Modal } from 'react-bootstrap'; +import { currencyOptions, currencySymbols } from 'utils/currency'; +import styles from './OrganizationFundCampaign.module.css'; +import { useTranslation } from 'react-i18next'; +import { useMutation } from '@apollo/client'; +import { + CREATE_CAMPAIGN_MUTATION, + UPDATE_CAMPAIGN_MUTATION, +} from 'GraphQl/Mutations/CampaignMutation'; +import { toast } from 'react-toastify'; +import { + FormControl, + InputLabel, + MenuItem, + Select, + TextField, +} from '@mui/material'; +import type { InterfaceCampaignInfo } from 'utils/interfaces'; + +export interface InterfaceCampaignModal { + isOpen: boolean; + hide: () => void; + fundId: string; + campaign: InterfaceCampaignInfo | null; + refetchCampaign: () => void; + mode: 'create' | 'edit'; +} + +const CampaignModal: React.FC = ({ + isOpen, + hide, + fundId, + refetchCampaign, + mode, + campaign, +}) => { + const { t } = useTranslation('translation', { + keyPrefix: 'fundCampaign', + }); + const { t: tCommon } = useTranslation('common'); + + const [formState, setFormState] = useState({ + campaignName: campaign?.name ?? '', + campaignCurrency: campaign?.currency ?? 'USD', + campaignGoal: campaign?.fundingGoal ?? 0, + campaignStartDate: campaign?.startDate ?? new Date(), + campaignEndDate: campaign?.endDate ?? new Date(), + }); + + useEffect(() => { + setFormState({ + campaignCurrency: campaign?.currency ?? 'USD', + campaignEndDate: campaign?.endDate ?? new Date(), + campaignGoal: campaign?.fundingGoal ?? 0, + campaignName: campaign?.name ?? '', + campaignStartDate: campaign?.startDate ?? new Date(), + }); + }, [campaign]); + + const { + campaignName, + campaignCurrency, + campaignEndDate, + campaignGoal, + campaignStartDate, + } = formState; + + const [createCampaign] = useMutation(CREATE_CAMPAIGN_MUTATION); + const [updateCampaign] = useMutation(UPDATE_CAMPAIGN_MUTATION); + + const createCampaignHandler = async ( + e: ChangeEvent, + ): Promise => { + e.preventDefault(); + try { + await createCampaign({ + variables: { + name: formState.campaignName, + currency: formState.campaignCurrency, + fundingGoal: formState.campaignGoal, + startDate: dayjs(formState.campaignStartDate).format('YYYY-MM-DD'), + endDate: dayjs(formState.campaignEndDate).format('YYYY-MM-DD'), + fundId, + }, + }); + toast.success(t('createdCampaign')); + setFormState({ + campaignName: '', + campaignCurrency: 'USD', + campaignGoal: 0, + campaignStartDate: new Date(), + campaignEndDate: new Date(), + }); + refetchCampaign(); + hide(); + } catch (error: unknown) { + toast.error((error as Error).message); + } + }; + + /*istanbul ignore next*/ + const updateCampaignHandler = async ( + e: ChangeEvent, + ): Promise => { + e.preventDefault(); + try { + const updatedFields: { [key: string]: string | number | undefined } = {}; + if (campaign?.name !== campaignName) { + updatedFields.name = campaignName; + } + if (campaign?.currency !== campaignCurrency) { + updatedFields.currency = campaignCurrency; + } + if (campaign?.fundingGoal !== campaignGoal) { + updatedFields.fundingGoal = campaignGoal; + } + if (campaign?.startDate !== campaignStartDate) { + updatedFields.startDate = dayjs(campaignStartDate).format('YYYY-MM-DD'); + } + if (campaign?.endDate !== formState.campaignEndDate) { + updatedFields.endDate = dayjs(formState.campaignEndDate).format( + 'YYYY-MM-DD', + ); + } + await updateCampaign({ + variables: { + id: campaign?._id, + ...updatedFields, + }, + }); + setFormState({ + campaignName: '', + campaignCurrency: 'USD', + campaignGoal: 0, + campaignStartDate: new Date(), + campaignEndDate: new Date(), + }); + refetchCampaign(); + hide(); + toast.success(t('updatedCampaign')); + } catch (error: unknown) { + toast.error((error as Error).message); + } + }; + + return ( + <> + + +

    + {t(mode === 'edit' ? 'updateCampaign' : 'createCampaign')} +

    + +
    + +
    + + + + setFormState({ + ...formState, + campaignName: e.target.value, + }) + } + /> + + + + + {/* Date Calendar Component to select start date of campaign*/} + { + if (date) { + setFormState({ + ...formState, + campaignStartDate: date.toDate(), + campaignEndDate: + campaignEndDate && + (campaignEndDate < date?.toDate() + ? date.toDate() + : campaignEndDate), + }); + } + }} + minDate={dayjs(new Date())} + /> + {/* Date Calendar Component to select end Date of campaign */} + { + if (date) { + setFormState({ + ...formState, + campaignEndDate: date.toDate(), + }); + } + }} + minDate={dayjs(campaignStartDate)} + /> + + + + {/* Dropdown to select the currency for funding goal of the campaign*/} + + + {t('currency')} + + + + {/* Input field to enter funding goal for the campaign */} + + { + if (parseInt(e.target.value) > 0) { + setFormState({ + ...formState, + campaignGoal: parseInt(e.target.value), + }); + } + }} + /> + + + {/* Button to create the campaign */} + + +
    +
    + + ); +}; +export default CampaignModal; diff --git a/src/screens/OrganizationFundCampaign/CampaignUpdateModal.tsx b/src/screens/OrganizationFundCampaign/CampaignUpdateModal.tsx deleted file mode 100644 index 561c7c9252..0000000000 --- a/src/screens/OrganizationFundCampaign/CampaignUpdateModal.tsx +++ /dev/null @@ -1,170 +0,0 @@ -import { DatePicker } from '@mui/x-date-pickers'; -import type { Dayjs } from 'dayjs'; -import dayjs from 'dayjs'; -import type { ChangeEvent } from 'react'; -import React from 'react'; -import { Button, Col, Form, Modal } from 'react-bootstrap'; -import { currencyOptions } from 'utils/currency'; -import type { InterfaceCreateCampaign } from 'utils/interfaces'; -import styles from './OrganizationFundCampaign.module.css'; - -interface InterfaceCampaignUpdateModal { - campaignUpdateModalIsOpen: boolean; - hideUpdateCampaignModal: () => void; - formState: InterfaceCreateCampaign; - setFormState: (state: React.SetStateAction) => void; - updateCampaignHandler: (e: ChangeEvent) => Promise; - t: (key: string) => string; - showDeleteCampaignModal: () => void; -} - -const CampaignUpdateModal: React.FC = ({ - campaignUpdateModalIsOpen, - hideUpdateCampaignModal, - formState, - setFormState, - updateCampaignHandler, - t, - showDeleteCampaignModal, -}) => { - return ( - <> - - -

    {t('manageCampaign')}

    - -
    - -
    - - {t('campaignName')} - - setFormState({ - ...formState, - campaignName: e.target.value, - }) - } - /> - - -
    - { - if (date) { - setFormState({ - ...formState, - campaignStartDate: date.toDate(), - campaignEndDate: - formState.campaignEndDate && - (formState.campaignEndDate < date?.toDate() - ? date.toDate() - : formState.campaignEndDate), - }); - } - }} - minDate={dayjs(new Date())} - /> -
    -
    - { - if (date) { - setFormState({ - ...formState, - campaignEndDate: date.toDate(), - }); - } - }} - minDate={dayjs(formState.campaignStartDate)} - /> -
    -
    - - - {t('currency')} -
    - { - setFormState({ - ...formState, - campaignCurrency: e.target.value, - }); - }} - > - - {currencyOptions.map((currency) => ( - - ))} - - - - - {t('fundingGoal')} - { - if (parseInt(e.target.value) > 0) { - setFormState({ - ...formState, - campaignGoal: parseInt(e.target.value), - }); - } - }} - /> - - -
    - - -
    - - - - - ); -}; -export default CampaignUpdateModal; diff --git a/src/screens/OrganizationFundCampaign/OrganizationFundCampagins.tsx b/src/screens/OrganizationFundCampaign/OrganizationFundCampagins.tsx index 24542d7e19..6cc671c5b1 100644 --- a/src/screens/OrganizationFundCampaign/OrganizationFundCampagins.tsx +++ b/src/screens/OrganizationFundCampaign/OrganizationFundCampagins.tsx @@ -1,57 +1,52 @@ -/*eslint-disable*/ -import { useMutation, useQuery } from '@apollo/client'; -import { Search, WarningAmberRounded } from '@mui/icons-material'; +import { useQuery } from '@apollo/client'; +import { Search, Sort, WarningAmberRounded } from '@mui/icons-material'; +import { Stack, Typography, Breadcrumbs, Link } from '@mui/material'; import { - CREATE_CAMPAIGN_MUTATION, - DELETE_CAMPAIGN_MUTATION, - UPDATE_CAMPAIGN_MUTATION, -} from 'GraphQl/Mutations/CampaignMutation'; -import { FUND_CAMPAIGN } from 'GraphQl/Queries/fundQueries'; -import Loader from 'components/Loader/Loader'; -import dayjs from 'dayjs'; -import { useState, type ChangeEvent } from 'react'; -import { Button, Col, Row, Dropdown, Form } from 'react-bootstrap'; + DataGrid, + type GridCellParams, + type GridColDef, +} from '@mui/x-data-grid'; +import { Button, Dropdown, Form } from 'react-bootstrap'; import { useTranslation } from 'react-i18next'; -import { useNavigate, useParams } from 'react-router-dom'; -import { toast } from 'react-toastify'; +import { Navigate, useNavigate, useParams } from 'react-router-dom'; +import React, { useCallback, useMemo, useState } from 'react'; +import dayjs from 'dayjs'; +import Loader from 'components/Loader/Loader'; +import CampaignModal from './CampaignModal'; +import CampaignDeleteModal from './CampaignDeleteModal'; +import { FUND_CAMPAIGN } from 'GraphQl/Queries/fundQueries'; +import styles from './OrganizationFundCampaign.module.css'; import { currencySymbols } from 'utils/currency'; -import FilterAltOutlinedIcon from '@mui/icons-material/FilterAltOutlined'; import type { InterfaceCampaignInfo, - InterfaceCreateCampaign, InterfaceQueryOrganizationFundCampaigns, } from 'utils/interfaces'; -import CampaignCreateModal from './CampaignCreateModal'; -import CampaignDeleteModal from './CampaignDeleteModal'; -import CampaignUpdateModal from './CampaignUpdateModal'; -import styles from './OrganizationFundCampaign.module.css'; -import { - Paper, - Table, - TableBody, - TableCell, - TableContainer, - TableHead, - TableRow, - styled, - tableCellClasses, -} from '@mui/material'; -const StyledTableCell = styled(TableCell)(({ theme }) => ({ - [`&.${tableCellClasses.head}`]: { - backgroundColor: ['#31bb6b', '!important'], - color: theme.palette.common.white, +const dataGridStyle = { + '&.MuiDataGrid-root .MuiDataGrid-cell:focus-within': { + outline: 'none !important', }, - [`&.${tableCellClasses.body}`]: { - fontSize: 14, + '&.MuiDataGrid-root .MuiDataGrid-columnHeader:focus-within': { + outline: 'none', }, -})); - -const StyledTableRow = styled(TableRow)(() => ({ - '&:last-child td, &:last-child th': { - border: 0, + '& .MuiDataGrid-row:hover': { + backgroundColor: 'transparent', + }, + '& .MuiDataGrid-row.Mui-hovered': { + backgroundColor: 'transparent', + }, + '& .MuiDataGrid-root': { + borderRadius: '0.5rem', }, -})); + '& .MuiDataGrid-main': { + borderRadius: '0.5rem', + }, +}; + +enum ModalState { + SAME = 'same', + DELETE = 'delete', +} const orgFundCampaign = (): JSX.Element => { const { t } = useTranslation('translation', { @@ -60,197 +55,84 @@ const orgFundCampaign = (): JSX.Element => { const { t: tCommon } = useTranslation('common'); const navigate = useNavigate(); - const { fundId: currentUrl, orgId: orgId } = useParams(); - const [campaignCreateModalIsOpen, setcampaignCreateModalIsOpen] = - useState(false); - const [campaignUpdateModalIsOpen, setcampaignUpdateModalIsOpen] = - useState(false); - const [campaignDeleteModalIsOpen, setcampaignDeleteModalIsOpen] = - useState(false); + const { fundId, orgId } = useParams(); + + if (!fundId || !orgId) { + return ; + } const [campaign, setCampaign] = useState(null); - const [formState, setFormState] = useState({ - campaignName: '', - campaignCurrency: 'USD', - campaignGoal: 0, - campaignStartDate: new Date(), - campaignEndDate: new Date(), + const [searchTerm, setSearchTerm] = useState(''); + const [sortBy, setSortBy] = useState(null); + + const [modalState, setModalState] = useState<{ + [key in ModalState]: boolean; + }>({ + [ModalState.SAME]: false, + [ModalState.DELETE]: false, }); + const [campaignModalMode, setCampaignModalMode] = useState<'edit' | 'create'>( + 'create', + ); + const openModal = (modal: ModalState): void => + setModalState((prevState) => ({ ...prevState, [modal]: true })); + + const closeModal = (modal: ModalState): void => + setModalState((prevState) => ({ ...prevState, [modal]: false })); + + const handleOpenModal = useCallback( + (campaign: InterfaceCampaignInfo | null, mode: 'edit' | 'create'): void => { + setCampaign(campaign); + setCampaignModalMode(mode); + openModal(ModalState.SAME); + }, + [openModal], + ); + + const handleDeleteClick = useCallback( + (campaign: InterfaceCampaignInfo): void => { + setCampaign(campaign); + openModal(ModalState.DELETE); + }, + [openModal], + ); + const { - data: fundCampaignData, - loading: fundCampaignLoading, - error: fundCampaignError, - refetch: refetchFundCampaign, + data: campaignData, + loading: campaignLoading, + error: campaignError, + refetch: refetchCampaign, }: { data?: { getFundById: InterfaceQueryOrganizationFundCampaigns; }; loading: boolean; error?: Error | undefined; - refetch: any; + refetch: () => void; } = useQuery(FUND_CAMPAIGN, { variables: { - id: currentUrl, + id: fundId, + orderBy: sortBy, + where: { + name_contains: searchTerm, + }, }, }); - const [createCampaign] = useMutation(CREATE_CAMPAIGN_MUTATION); - const [updateCampaign] = useMutation(UPDATE_CAMPAIGN_MUTATION); - const [deleteCampaign] = useMutation(DELETE_CAMPAIGN_MUTATION); - - const showCreateCampaignModal = (): void => { - setcampaignCreateModalIsOpen(!campaignCreateModalIsOpen); - }; - const hideCreateCampaignModal = (): void => { - setcampaignCreateModalIsOpen(!campaignCreateModalIsOpen); - }; - const showUpdateCampaignModal = (): void => { - setcampaignUpdateModalIsOpen(!campaignUpdateModalIsOpen); - }; - const hideUpdateCampaignModal = (): void => { - setcampaignUpdateModalIsOpen(!campaignUpdateModalIsOpen); - setFormState({ - campaignName: '', - campaignCurrency: 'USD', - campaignGoal: 0, - campaignStartDate: new Date(), - campaignEndDate: new Date(), - }); - }; - const showDeleteCampaignModal = (): void => { - setcampaignDeleteModalIsOpen(!campaignDeleteModalIsOpen); - }; - const hideDeleteCampaignModal = (): void => { - setcampaignDeleteModalIsOpen(!campaignDeleteModalIsOpen); - }; - - const handleEditClick = (campaign: InterfaceCampaignInfo): void => { - setFormState({ - campaignName: campaign.name, - campaignCurrency: campaign.currency, - campaignGoal: campaign.fundingGoal, - campaignStartDate: new Date(campaign.startDate), - campaignEndDate: new Date(campaign.endDate), - }); - setCampaign(campaign); - showUpdateCampaignModal(); - }; - - const createCampaignHandler = async ( - e: ChangeEvent, - ): Promise => { - e.preventDefault(); - try { - await createCampaign({ - variables: { - name: formState.campaignName, - currency: formState.campaignCurrency, - fundingGoal: formState.campaignGoal, - startDate: dayjs(formState.campaignStartDate).format('YYYY-MM-DD'), - endDate: dayjs(formState.campaignEndDate).format('YYYY-MM-DD'), - fundId: currentUrl, - }, - }); - toast.success(t('createdCampaign')); - setFormState({ - campaignName: '', - campaignCurrency: 'USD', - campaignGoal: 0, - campaignStartDate: new Date(), - campaignEndDate: new Date(), - }); - refetchFundCampaign(); - hideCreateCampaignModal(); - } catch (error: unknown) { - if (error instanceof Error) { - toast.error(error.message); - console.log(error.message); - } - } - }; - - const updateCampaignHandler = async ( - e: ChangeEvent, - ): Promise => { - e.preventDefault(); - try { - const updatedFields: { [key: string]: any } = {}; - if (campaign?.name !== formState.campaignName) { - updatedFields.name = formState.campaignName; - } - if (campaign?.currency !== formState.campaignCurrency) { - updatedFields.currency = formState.campaignCurrency; - } - if (campaign?.fundingGoal !== formState.campaignGoal) { - updatedFields.fundingGoal = formState.campaignGoal; - } - if (campaign?.startDate !== formState.campaignStartDate) { - updatedFields.startDate = dayjs(formState.campaignStartDate).format( - 'YYYY-MM-DD', - ); - } - if (campaign?.endDate !== formState.campaignEndDate) { - updatedFields.endDate = dayjs(formState.campaignEndDate).format( - 'YYYY-MM-DD', - ); - } - await updateCampaign({ - variables: { - id: campaign?._id, - ...updatedFields, - }, - }); - setFormState({ - campaignName: '', - campaignCurrency: 'USD', - campaignGoal: 0, - campaignStartDate: new Date(), - campaignEndDate: new Date(), - }); - refetchFundCampaign(); - hideUpdateCampaignModal(); - toast.success(t('updatedCampaign')); - } catch (error: unknown) { - if (error instanceof Error) { - toast.error(error.message); - console.log(error.message); - } - } - }; - - const deleteCampaignHandler = async (): Promise => { - try { - await deleteCampaign({ - variables: { - id: campaign?._id, - }, - }); - toast.success(t('deletedCampaign')); - refetchFundCampaign(); - hideDeleteCampaignModal(); - } catch (error: unknown) { - if (error instanceof Error) { - toast.error(error.message); - console.log(error.message); - } - } - }; - - const handleClick = (campaignId: String) => { + const handleClick = (campaignId: string): void => { navigate(`/fundCampaignPledge/${orgId}/${campaignId}`); }; - const [searchQuery, setSearchQuery] = useState(''); - const [searchText, setSearchText] = useState(''); - const filteredCampaigns = fundCampaignData?.getFundById.campaigns.filter( - (campaign) => - campaign.name.toLowerCase().includes(searchQuery.toLowerCase()), - ); + const campaigns = useMemo(() => { + if (campaignData?.getFundById?.campaigns) + return campaignData.getFundById.campaigns; + return []; + }, [campaignData]); - if (fundCampaignLoading) { + if (campaignLoading) { return ; } - if (fundCampaignError) { + if (campaignError) { return (
    @@ -258,32 +140,199 @@ const orgFundCampaign = (): JSX.Element => {
    Error occured while loading Campaigns
    - {fundCampaignError.message} + {campaignError.message}
    ); } + const columns: GridColDef[] = [ + { + field: 'id', + headerName: 'Sr. No.', + flex: 1, + minWidth: 100, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return
    {params.row.id}
    ; + }, + }, + { + field: 'campaignName', + headerName: 'Campaign Name', + flex: 2, + minWidth: 150, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return ( +
    handleClick(params.row.campaign._id as string)} + > + {params.row.campaign.name} +
    + ); + }, + }, + { + field: 'startDate', + headerName: 'Start Date', + flex: 1, + minWidth: 150, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return dayjs(params.row.campaign.startDate).format('DD/MM/YYYY'); + }, + }, + { + field: 'endDate', + headerName: 'End Date', + minWidth: 150, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + flex: 1, + sortable: false, + renderCell: (params: GridCellParams) => { + return ( +
    + {dayjs(params.row.campaign.endDate).format('DD/MM/YYYY')}{' '} +
    + ); + }, + }, + { + field: 'fundingGoal', + headerName: 'Funding Goal', + flex: 1, + minWidth: 100, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return ( +
    + { + currencySymbols[ + params.row.campaign.currency as keyof typeof currencySymbols + ] + } + {params.row.campaign.fundingGoal} +
    + ); + }, + }, + { + field: 'action', + headerName: 'Action', + flex: 1, + minWidth: 100, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return ( + <> + + + + ); + }, + }, + { + field: 'assocPledge', + headerName: 'Associated Pledges', + flex: 2, + minWidth: 100, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return ( + + ); + }, + }, + ]; + return (
    + + navigate(`/orgfunds/${orgId}`)} + > + {tCommon('Funds')} + + FundRaising Campaign + +
    { - setSearchText(e.target.value); - }} + value={searchTerm} + onChange={(e) => setSearchTerm(e.target.value)} data-testid="searchFullName" />
    -
    - {filteredCampaigns && filteredCampaigns.length > 0 ? ( -
    - -
    NameAddressCreated onCreated ByUsers RoleChange RoleAction{tCommon('name')}{tCommon('address')}{tCommon('createdOn')}{tCommon('createdBy')}{tCommon('usersRole')}{tCommon('changeRole')}{tCommon('action')}
    - - - # - - {t('campaignName')} - - - {tCommon('startDate')} - - - {tCommon('endDate')} - - - {t('fundingGoal')} - - - {t('campaignOptions')} - - - - - {filteredCampaigns.map((campaign, index) => ( - - - {index + 1} - - handleClick(campaign._id)} - > - - {campaign.name} - - - - {dayjs(campaign.startDate).format('DD/MM/YYYY')} - - - {dayjs(campaign.endDate).format('DD/MM/YYYY')} - - - - {`${currencySymbols[campaign.currency as keyof typeof currencySymbols]}${campaign.fundingGoal}`} - - - - - - - ))} - -
    - -
    - ) : ( -
    -
    {t('noCampaigns')}
    -
    - )} -
    - - {/* Create Campaign Modal */} - row.campaign._id} + slots={{ + noRowsOverlay: () => ( + + {t('noCampaignsFound')} + + ), + }} + sx={dataGridStyle} + getRowClassName={() => `${styles.rowBackground}`} + autoHeight + rowHeight={65} + rows={campaigns.map((campaign, index) => ({ + id: index + 1, + campaign, + }))} + columns={columns} + isRowSelectable={() => false} /> - {/* Update Campaign Modal */} - closeModal(ModalState.SAME)} + refetchCampaign={refetchCampaign} + fundId={fundId} + campaign={campaign} + mode={campaignModalMode} /> - {/* Delete Campaign Modal */} closeModal(ModalState.DELETE)} + campaign={campaign} + refetchCampaign={refetchCampaign} />
    ); diff --git a/src/screens/OrganizationFundCampaign/OrganizationFundCampaign.module.css b/src/screens/OrganizationFundCampaign/OrganizationFundCampaign.module.css index 3ed22aa094..55202baef9 100644 --- a/src/screens/OrganizationFundCampaign/OrganizationFundCampaign.module.css +++ b/src/screens/OrganizationFundCampaign/OrganizationFundCampaign.module.css @@ -1,5 +1,5 @@ .organizationFundCampaignContainer { - margin: 0.6rem 0; + margin: 0.5rem 0; } .goalButton { border: 1px solid rgba(49, 187, 107, 1) !important; @@ -11,6 +11,10 @@ margin: auto; box-shadow: 5px 5px 4px 0px rgba(49, 187, 107, 0.12); } +.rowBackground { + background-color: var(--bs-white); + max-height: 120px; +} .container { min-height: 100vh; } @@ -20,13 +24,22 @@ margin-left: 13vw; } .titlemodal { - color: var(--bs-gray-600); + color: #707070; font-weight: 600; - font-size: 20px; - margin-bottom: 20px; - padding-bottom: 5px; - border-bottom: 3px solid var(--bs-primary); + font-size: 32px; width: 65%; + margin-bottom: 0px; +} +.noOutline input { + outline: none; +} +.modalCloseBtn { + width: 40px; + height: 40px; + padding: 1rem; + display: flex; + justify-content: center; + align-items: center; } .greenregbtn { margin: 1rem 0 0; @@ -99,11 +112,13 @@ .btnsContainer { display: flex; - margin: 2.5rem 0 2.5rem 0; + margin: 2rem 0 2rem 0; + gap: 0.8rem; } .btnsContainer .btnsBlock { display: flex; + gap: 0.8rem; } .btnsContainer .btnsBlock div button { @@ -134,6 +149,12 @@ margin-bottom: 20px; } +.tableHeader { + background-color: var(--bs-primary); + color: var(--bs-white); + font-size: 1rem; +} + @media (max-width: 1020px) { .btnsContainer { flex-direction: column; diff --git a/src/screens/OrganizationFundCampaign/OrganizationFundCampaign.test.tsx b/src/screens/OrganizationFundCampaign/OrganizationFundCampaign.test.tsx index 16f069444f..74f646f51a 100644 --- a/src/screens/OrganizationFundCampaign/OrganizationFundCampaign.test.tsx +++ b/src/screens/OrganizationFundCampaign/OrganizationFundCampaign.test.tsx @@ -1,19 +1,19 @@ +import React from 'react'; import { MockedProvider } from '@apollo/react-testing'; import { LocalizationProvider } from '@mui/x-date-pickers'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import type { RenderResult } from '@testing-library/react'; import { + cleanup, fireEvent, render, screen, waitFor, - waitForElementToBeRemoved, } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { act } from 'react-dom/test-utils'; import { I18nextProvider } from 'react-i18next'; import { Provider } from 'react-redux'; -import { BrowserRouter } from 'react-router-dom'; -import { toast } from 'react-toastify'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; import { store } from '../../state/store'; import { StaticMockLink } from '../../utils/StaticMockLink'; import i18nForTest from '../../utils/i18nForTest'; @@ -21,24 +21,17 @@ import OrganizaitionFundCampiagn from './OrganizationFundCampagins'; import { EMPTY_MOCKS, MOCKS, - MOCKS_ERROR_CREATE_CAMPAIGN, - MOCKS_ERROR_DELETE_CAMPAIGN, - MOCKS_ERROR_UPDATE_CAMPAIGN, - MOCK_FUND_CAMPAIGN_ERROR, + MOCK_ERROR, } from './OrganizationFundCampaignMocks'; -import React from 'react'; +import type { ApolloLink } from '@apollo/client'; -const mockNavigate = jest.fn(); -jest.mock('react-router-dom', () => ({ - ...jest.requireActual('react-router-dom'), - useNavigate: () => mockNavigate, -})); jest.mock('react-toastify', () => ({ toast: { success: jest.fn(), error: jest.fn(), }, })); + jest.mock('@mui/x-date-pickers/DateTimePicker', () => { return { DateTimePicker: jest.requireActual( @@ -47,617 +40,297 @@ jest.mock('@mui/x-date-pickers/DateTimePicker', () => { }; }); -async function wait(ms = 100): Promise { - await act(() => { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); - }); -} const link1 = new StaticMockLink(MOCKS, true); -const link2 = new StaticMockLink(MOCK_FUND_CAMPAIGN_ERROR, true); -const link3 = new StaticMockLink(MOCKS_ERROR_CREATE_CAMPAIGN, true); -const link4 = new StaticMockLink(MOCKS_ERROR_UPDATE_CAMPAIGN, true); -const link5 = new StaticMockLink(MOCKS_ERROR_DELETE_CAMPAIGN, true); -const link6 = new StaticMockLink(EMPTY_MOCKS, true); +const link2 = new StaticMockLink(MOCK_ERROR, true); +const link3 = new StaticMockLink(EMPTY_MOCKS, true); const translations = JSON.parse( JSON.stringify(i18nForTest.getDataByLanguage('en')?.translation.fundCampaign), ); -describe('Testing FundCampaigns Screen', () => { - const formData = { - campaignName: 'Campaign 1', - campaignCurrency: 'USD', - campaignGoal: 100, - campaignStartDate: '03/10/2024', - campaignEndDate: '03/10/2024', - }; - - it('loads the Fund Campaigns screen', async () => { - const { getByText } = render( - +const renderFundCampaign = (link: ApolloLink): RenderResult => { + return render( + + - + - {} + + } + /> + } + /> + } + /> + } + /> + - +
    -
    , - ); - await wait(); - await waitFor(() => { - expect(getByText(translations.addCampaign)).toBeInTheDocument(); - }); + + , + ); +}; + +describe('FundCampaigns Screen', () => { + beforeEach(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId', fundId: 'fundId' }), + })); }); - it('renders the campaign screen with error', async () => { - const { queryByText } = render( - - - - - {} - - - - , - ); - await wait(); - await waitFor(() => { - expect(queryByText(translations.addCampaign)).not.toBeInTheDocument(); - }); + + afterEach(() => { + cleanup(); }); - it('renders the Error Component', async () => { - render( - - - - - {} - - - - , - ); - await wait(); - await waitFor(() => { - expect(screen.getByTestId('errorMsg')).toBeInTheDocument(); - }); + + afterAll(() => { + jest.clearAllMocks(); }); - it("opens and closes the 'Create Campaign' modal", async () => { - render( - - - - - - {} - - - - - , - ); - await wait(); - await waitFor(() => - expect(screen.getByTestId('addCampaignBtn')).toBeInTheDocument(), - ); - userEvent.click(screen.getByTestId('addCampaignBtn')); + + it('should render the Campaign Pledge screen', async () => { + renderFundCampaign(link1); await waitFor(() => { - return expect( - screen.findByTestId('createCampaignCloseBtn'), - ).resolves.toBeInTheDocument(); + expect(screen.getByTestId('searchFullName')).toBeInTheDocument(); }); - userEvent.click(screen.getByTestId('createCampaignCloseBtn')); - await waitForElementToBeRemoved(() => - screen.queryByTestId('createCampaignCloseBtn'), - ); + + expect(screen.getByText('Campaign 1')).toBeInTheDocument(); + expect(screen.getByText('Campaign 2')).toBeInTheDocument(); }); - it('creates a new Campaign', async () => { + + it('should redirect to fallback URL if URL params are undefined', async () => { render( - - + + - {} + + } + /> + } + /> + - - + + , ); - await wait(); - await waitFor(() => - expect(screen.getByTestId('addCampaignBtn')).toBeInTheDocument(), - ); - userEvent.click(screen.getByTestId('addCampaignBtn')); await waitFor(() => { - return expect( - screen.findByTestId('createCampaignCloseBtn'), - ).resolves.toBeInTheDocument(); - }); - userEvent.type( - screen.getByPlaceholderText('Enter Campaign Name'), - formData.campaignName, - ); - userEvent.type( - screen.getByPlaceholderText('Enter Funding Goal'), - formData.campaignGoal.toString(), - ); - const currency = screen.getByTestId('currencySelect'); - fireEvent.change(currency, { - target: { value: formData.campaignCurrency }, - }); - const startDate = screen.getByLabelText('Start Date'); - const endDate = screen.getByLabelText('End Date'); - fireEvent.change(startDate, { - target: { value: formData.campaignStartDate }, - }); - fireEvent.change(endDate, { - target: { value: formData.campaignEndDate }, + expect(screen.getByTestId('paramsError')).toBeInTheDocument(); }); + }); - userEvent.click(screen.getByTestId('createCampaignBtn')); + it('open and close Create Campaign modal', async () => { + renderFundCampaign(link1); + + const addCampaignBtn = await screen.findByTestId('addCampaignBtn'); + expect(addCampaignBtn).toBeInTheDocument(); + userEvent.click(addCampaignBtn); - await waitFor(() => { - expect(toast.success).toHaveBeenCalledWith(translations.createdCampaign); - }); - }); - it('toast an error on unsuccessful campaign creation', async () => { - render( - - - - - - {} - - - - - , - ); - await wait(); await waitFor(() => - expect(screen.getByTestId('addCampaignBtn')).toBeInTheDocument(), + expect(screen.getAllByText(translations.createCampaign)).toHaveLength(2), ); - userEvent.click(screen.getByTestId('addCampaignBtn')); - await waitFor(() => { - return expect( - screen.findByTestId('createCampaignCloseBtn'), - ).resolves.toBeInTheDocument(); - }); - userEvent.type( - screen.getByPlaceholderText('Enter Campaign Name'), - formData.campaignName, - ); - userEvent.type( - screen.getByPlaceholderText('Enter Funding Goal'), - formData.campaignGoal.toString(), + userEvent.click(screen.getByTestId('campaignCloseBtn')); + await waitFor(() => + expect(screen.queryByTestId('campaignCloseBtn')).toBeNull(), ); - const endDateDatePicker = screen.getByLabelText('End Date'); - const startDateDatePicker = screen.getByLabelText('Start Date'); - - fireEvent.change(endDateDatePicker, { - target: { value: formData.campaignEndDate }, - }); - fireEvent.change(startDateDatePicker, { - target: { value: formData.campaignStartDate }, - }); + }); - userEvent.click(screen.getByTestId('createCampaignBtn')); + it('open and close update campaign modal', async () => { + renderFundCampaign(link1); await waitFor(() => { - expect(toast.error).toHaveBeenCalled(); + expect(screen.getByTestId('searchFullName')).toBeInTheDocument(); }); - }); - it('opens and closes the Edit Campaign modal', async () => { - render( - - - - - - {} - - - - - , - ); - await wait(); + + const editCampaignBtn = await screen.findAllByTestId('editCampaignBtn'); + await waitFor(() => expect(editCampaignBtn[0]).toBeInTheDocument()); + userEvent.click(editCampaignBtn[0]); + await waitFor(() => - expect(screen.getAllByTestId('editCampaignBtn')[0]).toBeInTheDocument(), + expect( + screen.getAllByText(translations.updateCampaign)[0], + ).toBeInTheDocument(), ); - userEvent.click(screen.getAllByTestId('editCampaignBtn')[0]); - await waitFor(() => { - return expect( - screen.findByTestId('editCampaignCloseBtn'), - ).resolves.toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('editCampaignCloseBtn')); - await waitForElementToBeRemoved(() => - screen.queryByTestId('editCampaignCloseBtn'), + userEvent.click(screen.getByTestId('campaignCloseBtn')); + await waitFor(() => + expect(screen.queryByTestId('campaignCloseBtn')).toBeNull(), ); }); - it("updates the Campaign's details", async () => { - render( - - - - - - {} - - - - - , + it('open and closes delete campaign modal', async () => { + renderFundCampaign(link1); + + const deleteCampaignBtn = await screen.findAllByTestId('deleteCampaignBtn'); + await waitFor(() => expect(deleteCampaignBtn[0]).toBeInTheDocument()); + userEvent.click(deleteCampaignBtn[0]); + + await waitFor(() => + expect(screen.getByText(translations.deleteCampaign)).toBeInTheDocument(), ); - await wait(); + userEvent.click(screen.getByTestId('deleteCampaignCloseBtn')); await waitFor(() => - expect(screen.getAllByTestId('editCampaignBtn')[0]).toBeInTheDocument(), + expect(screen.queryByTestId('deleteCampaignCloseBtn')).toBeNull(), ); - userEvent.click(screen.getAllByTestId('editCampaignBtn')[0]); - await waitFor(() => { - return expect( - screen.findByTestId('editCampaignCloseBtn'), - ).resolves.toBeInTheDocument(); - }); - const campaignName = screen.getByPlaceholderText('Enter Campaign Name'); - fireEvent.change(campaignName, { - target: { value: 'Campaign 4' }, - }); - const fundingGoal = screen.getByPlaceholderText('Enter Funding Goal'); - fireEvent.change(fundingGoal, { - target: { value: 1000 }, - }); - const currency = screen.getByTestId('currencySelect'); - fireEvent.change(currency, { - target: { value: 'INR' }, - }); - const endDateDatePicker = screen.getByLabelText('End Date'); - const startDateDatePicker = screen.getByLabelText('Start Date'); - - const endDate = - formData.campaignEndDate < formData.campaignStartDate - ? formData.campaignStartDate - : formData.campaignEndDate; - fireEvent.change(endDateDatePicker, { - target: { value: endDate }, - }); + }); - fireEvent.change(startDateDatePicker, { - target: { value: formData.campaignStartDate }, + it('Search the Campaigns list by Name', async () => { + renderFundCampaign(link1); + const searchField = await screen.findByTestId('searchFullName'); + fireEvent.change(searchField, { + target: { value: '2' }, }); - userEvent.click(screen.getByTestId('editCampaignSubmitBtn')); - await waitFor(() => { - expect(toast.success).toHaveBeenCalledWith(translations.updatedCampaign); + expect(screen.getByText('Campaign 2')).toBeInTheDocument(); + expect(screen.queryByText('Campaign 1')).toBeNull(); }); }); - it("updates the Campaign's details when date is null", async () => { - render( - - - - - - {} - - - - - , - ); - await wait(); - await waitFor(() => - expect(screen.getAllByTestId('editCampaignBtn')[0]).toBeInTheDocument(), - ); - userEvent.click(screen.getAllByTestId('editCampaignBtn')[0]); + it('should render the Campaign screen with error', async () => { + renderFundCampaign(link2); await waitFor(() => { - return expect( - screen.findByTestId('editCampaignCloseBtn'), - ).resolves.toBeInTheDocument(); - }); - const endDateDatePicker = screen.getByLabelText('End Date'); - const startDateDatePicker = screen.getByLabelText('Start Date'); - - fireEvent.change(endDateDatePicker, { - target: { value: null }, - }); - - fireEvent.change(startDateDatePicker, { - target: { value: null }, + expect(screen.getByTestId('errorMsg')).toBeInTheDocument(); }); - - expect(startDateDatePicker.getAttribute('value')).toBe(''); - expect(endDateDatePicker.getAttribute('value')).toBe(''); }); - it("updates the Campaign's details when endDate is less than date", async () => { - const formData = { - campaignName: 'Campaign 1', - campaignCurrency: 'USD', - campaignGoal: 100, - campaignStartDate: '03/10/2024', - campaignEndDate: '03/10/2023', - }; - render( - - - - - - {} - - - - - , - ); - await wait(); + it('renders the empty campaign component', async () => { + renderFundCampaign(link3); await waitFor(() => - expect(screen.getAllByTestId('editCampaignBtn')[0]).toBeInTheDocument(), + expect( + screen.getByText(translations.noCampaignsFound), + ).toBeInTheDocument(), ); - userEvent.click(screen.getAllByTestId('editCampaignBtn')[0]); - await waitFor(() => { - return expect( - screen.findByTestId('editCampaignCloseBtn'), - ).resolves.toBeInTheDocument(); - }); + }); - const endDateDatePicker = screen.getByLabelText('End Date'); - const startDateDatePicker = screen.getByLabelText('Start Date'); + it('Sort the Campaigns list by Latest end Date', async () => { + renderFundCampaign(link1); - fireEvent.change(endDateDatePicker, { - target: { value: formData.campaignEndDate }, - }); + const sortBtn = await screen.findByTestId('filter'); + expect(sortBtn).toBeInTheDocument(); - fireEvent.change(startDateDatePicker, { - target: { value: formData.campaignStartDate }, - }); - }); + fireEvent.click(sortBtn); + fireEvent.click(screen.getByTestId('endDate_DESC')); - it("doesn't update when fund field has value less than or equal to 0", async () => { - render( - - - - - - {} - - - - - , - ); - await wait(); - await waitFor(() => - expect(screen.getAllByTestId('editCampaignBtn')[0]).toBeInTheDocument(), - ); - userEvent.click(screen.getAllByTestId('editCampaignBtn')[0]); await waitFor(() => { - return expect( - screen.findByTestId('editCampaignCloseBtn'), - ).resolves.toBeInTheDocument(); + expect(screen.getByText('Campaign 1')).toBeInTheDocument(); + expect(screen.queryByText('Campaign 2')).toBeInTheDocument(); }); - const fundingGoal = screen.getByPlaceholderText( - 'Enter Funding Goal', - ) as HTMLInputElement; - - const initialValue = fundingGoal.value; //Vakue before updating - fireEvent.change(fundingGoal, { - target: { value: 0 }, + await waitFor(() => { + expect(screen.getAllByTestId('endDateCell')[0]).toHaveTextContent( + '01/01/2024', + ); }); - - expect(fundingGoal.value).toBe(initialValue); //Retains previous value }); - it('toast an error on unsuccessful campaign update', async () => { - render( - - - - - - {} - - - - - , - ); - await wait(); - await waitFor(() => - expect(screen.getAllByTestId('editCampaignBtn')[0]).toBeInTheDocument(), - ); - userEvent.click(screen.getAllByTestId('editCampaignBtn')[0]); - await waitFor(() => { - return expect( - screen.findByTestId('editCampaignCloseBtn'), - ).resolves.toBeInTheDocument(); - }); - userEvent.type( - screen.getByPlaceholderText('Enter Campaign Name'), - formData.campaignName, - ); + it('Sort the Campaigns list by Earliest end Date', async () => { + renderFundCampaign(link1); - userEvent.click(screen.getByTestId('editCampaignSubmitBtn')); + const sortBtn = await screen.findByTestId('filter'); + expect(sortBtn).toBeInTheDocument(); + + fireEvent.click(sortBtn); + fireEvent.click(screen.getByTestId('endDate_ASC')); await waitFor(() => { - expect(toast.error).toHaveBeenCalled(); + expect(screen.getByText('Campaign 1')).toBeInTheDocument(); + expect(screen.queryByText('Campaign 2')).toBeInTheDocument(); }); - }); - it("opens and closes the 'Delete Campaign' modal", async () => { - render( - - - - - - {} - - - - - , - ); - await wait(); - await waitFor(() => - expect(screen.getAllByTestId('editCampaignBtn')[0]).toBeInTheDocument(), - ); - userEvent.click(screen.getAllByTestId('editCampaignBtn')[0]); - await wait(); - await waitFor(() => - expect(screen.getAllByTestId('deleteCampaignBtn')[0]).toBeInTheDocument(), - ); - userEvent.click(screen.getAllByTestId('deleteCampaignBtn')[0]); + await waitFor(() => { - return expect( - screen.findByTestId('deleteCampaignCloseBtn'), - ).resolves.toBeInTheDocument(); + expect(screen.getAllByTestId('endDateCell')[0]).toHaveTextContent( + '01/01/2021', + ); }); - userEvent.click(screen.getByTestId('deleteCampaignCloseBtn')); - await waitForElementToBeRemoved(() => - screen.queryByTestId('deleteCampaignCloseBtn'), - ); }); - it('deletes a Campaign', async () => { - render( - - - - - - {} - - - - - , - ); - await wait(); - await waitFor(() => - expect(screen.getAllByTestId('editCampaignBtn')[0]).toBeInTheDocument(), - ); - userEvent.click(screen.getAllByTestId('editCampaignBtn')[0]); - await wait(); - await waitFor(() => - expect(screen.getAllByTestId('deleteCampaignBtn')[0]).toBeInTheDocument(), - ); - userEvent.click(screen.getAllByTestId('deleteCampaignBtn')[0]); + + it('Sort the Campaigns list by lowest goal', async () => { + renderFundCampaign(link1); + + const sortBtn = await screen.findByTestId('filter'); + expect(sortBtn).toBeInTheDocument(); + + fireEvent.click(sortBtn); + fireEvent.click(screen.getByTestId('fundingGoal_ASC')); + await waitFor(() => { - return expect( - screen.findByTestId('deleteCampaignCloseBtn'), - ).resolves.toBeInTheDocument(); + expect(screen.getByText('Campaign 1')).toBeInTheDocument(); + expect(screen.queryByText('Campaign 2')).toBeInTheDocument(); }); - userEvent.click(screen.getByTestId('deleteyesbtn')); + await waitFor(() => { - expect(toast.success).toHaveBeenCalledWith(translations.deletedCampaign); + expect(screen.getAllByTestId('goalCell')[0]).toHaveTextContent('100'); }); }); - it('toast an error on unsuccessful campaign deletion', async () => { - render( - - - - - - {} - - - - - , - ); - await wait(); - await waitFor(() => - expect(screen.getAllByTestId('editCampaignBtn')[0]).toBeInTheDocument(), - ); - userEvent.click(screen.getAllByTestId('editCampaignBtn')[0]); - await wait(); - await waitFor(() => - expect(screen.getAllByTestId('deleteCampaignBtn')[0]).toBeInTheDocument(), - ); - userEvent.click(screen.getAllByTestId('deleteCampaignBtn')[0]); + + it('Sort the Campaigns list by highest goal', async () => { + renderFundCampaign(link1); + + const sortBtn = await screen.findByTestId('filter'); + expect(sortBtn).toBeInTheDocument(); + + fireEvent.click(sortBtn); + fireEvent.click(screen.getByTestId('fundingGoal_DESC')); + await waitFor(() => { - return expect( - screen.findByTestId('deleteCampaignCloseBtn'), - ).resolves.toBeInTheDocument(); + expect(screen.getByText('Campaign 1')).toBeInTheDocument(); + expect(screen.queryByText('Campaign 2')).toBeInTheDocument(); }); - userEvent.click(screen.getByTestId('deleteyesbtn')); + await waitFor(() => { - expect(toast.error).toHaveBeenCalled(); + expect(screen.getAllByTestId('goalCell')[0]).toHaveTextContent('200'); }); }); - it('renders the Empty Campaigns Component', async () => { - render( - - - - - - {} - - - - - , - ); - await wait(); + + it('Click on Campaign Name', async () => { + renderFundCampaign(link1); + + const campaignName = await screen.findAllByTestId('campaignName'); + expect(campaignName[0]).toBeInTheDocument(); + fireEvent.click(campaignName[0]); + await waitFor(() => { - expect(screen.getByText(translations.noCampaigns)).toBeInTheDocument(); + expect(screen.getByTestId('pledgeScreen')).toBeInTheDocument(); }); }); - it("redirects to 'FundCampaignPledge' screen", async () => { - render( - - - - - - {} - - - - - , - ); - await wait(); - await waitFor(() => - expect(screen.getAllByTestId('campaignName')[0]).toBeInTheDocument(), - ); - userEvent.click(screen.getAllByTestId('campaignName')[0]); + + it('Click on View Pledge', async () => { + renderFundCampaign(link1); + + const viewBtn = await screen.findAllByTestId('viewBtn'); + expect(viewBtn[0]).toBeInTheDocument(); + fireEvent.click(viewBtn[0]); + await waitFor(() => { - expect(mockNavigate).toHaveBeenCalledWith( - '/fundCampaignPledge/undefined/1', - ); + expect(screen.getByTestId('pledgeScreen')).toBeInTheDocument(); }); }); - it('search funds by name', async () => { - render( - - - - - {} - - - - , - ); - await wait(); - userEvent.type(screen.getByTestId('searchFullName'), 'Funndds'); - await wait(); - userEvent.click(screen.getByTestId('searchBtn')); + it('should render the Fund screen on fund breadcrumb click', async () => { + renderFundCampaign(link1); + + const fundBreadcrumb = await screen.findByTestId('fundsLink'); + expect(fundBreadcrumb).toBeInTheDocument(); + fireEvent.click(fundBreadcrumb); + + await waitFor(() => { + expect(screen.getByTestId('fundScreen')).toBeInTheDocument(); + }); }); }); diff --git a/src/screens/OrganizationFundCampaign/OrganizationFundCampaignMocks.tsx b/src/screens/OrganizationFundCampaign/OrganizationFundCampaignMocks.ts similarity index 59% rename from src/screens/OrganizationFundCampaign/OrganizationFundCampaignMocks.tsx rename to src/screens/OrganizationFundCampaign/OrganizationFundCampaignMocks.ts index 09fbb9f4b2..160dfad5fb 100644 --- a/src/screens/OrganizationFundCampaign/OrganizationFundCampaignMocks.tsx +++ b/src/screens/OrganizationFundCampaign/OrganizationFundCampaignMocks.ts @@ -10,7 +10,9 @@ export const MOCKS = [ request: { query: FUND_CAMPAIGN, variables: { - id: undefined, + id: 'fundId', + orderBy: null, + where: { name_contains: '' }, }, }, result: { @@ -18,7 +20,7 @@ export const MOCKS = [ getFundById: { campaigns: [ { - _id: '1', + _id: 'campaignId1', name: 'Campaign 1', fundingGoal: 100, startDate: '2024-01-01', @@ -40,92 +42,111 @@ export const MOCKS = [ }, { request: { - query: CREATE_CAMPAIGN_MUTATION, + query: FUND_CAMPAIGN, variables: { - fundId: undefined, - name: 'Campaign 1', - fundingGoal: 100, - startDate: '2024-03-10', - endDate: '2024-03-10', - currency: 'USD', + id: 'fundId', + orderBy: null, + where: { name_contains: '2' }, }, }, result: { data: { - createFundraisingCampaign: { - _id: '3', + getFundById: { + campaigns: [ + { + _id: '2', + name: 'Campaign 2', + fundingGoal: 200, + startDate: '2021-01-01', + endDate: '2021-01-01', + currency: 'USD', + }, + ], }, }, }, }, { request: { - query: UPDATE_CAMPAIGN_MUTATION, + query: FUND_CAMPAIGN, variables: { - id: '1', - name: 'Campaign 4', - startDate: '2024-03-10', - endDate: '2024-03-10', - fundingGoal: 1000, - currency: 'INR', + id: 'fundId', + orderBy: 'endDate_DESC', + where: { name_contains: '' }, }, }, result: { data: { - updateFundraisingCampaign: { - _id: '1', + getFundById: { + campaigns: [ + { + _id: '1', + name: 'Campaign 1', + fundingGoal: 100, + startDate: '2024-01-01', + endDate: '2024-01-01', + currency: 'USD', + }, + { + _id: '2', + name: 'Campaign 2', + fundingGoal: 200, + startDate: '2021-01-01', + endDate: '2021-01-01', + currency: 'USD', + }, + ], }, }, }, }, { request: { - query: DELETE_CAMPAIGN_MUTATION, + query: FUND_CAMPAIGN, variables: { - id: '1', + id: 'fundId', + orderBy: 'endDate_ASC', + where: { name_contains: '' }, }, }, result: { data: { - removeFundraisingCampaign: { - _id: '1', + getFundById: { + campaigns: [ + { + _id: '2', + name: 'Campaign 2', + fundingGoal: 200, + startDate: '2021-01-01', + endDate: '2021-01-01', + currency: 'USD', + }, + { + _id: '1', + name: 'Campaign 1', + fundingGoal: 100, + startDate: '2024-01-01', + endDate: '2024-01-01', + currency: 'USD', + }, + ], }, }, }, }, -]; - -export const MOCK_FUND_CAMPAIGN_ERROR = [ - { - request: { - query: FUND_CAMPAIGN, - variables: { - id: undefined, - }, - }, - error: new Error('An error occurred'), - }, -]; -export const MOCKS_ERROR_CREATE_CAMPAIGN = [ { request: { query: FUND_CAMPAIGN, variables: { - id: undefined, + id: 'fundId', + orderBy: 'fundingGoal_DESC', + where: { name_contains: '' }, }, }, result: { data: { getFundById: { campaigns: [ - { - _id: '1', - name: 'Campaign 1', - fundingGoal: 100, - startDate: '2021-01-01', - endDate: '2021-01-01', - currency: 'USD', - }, { _id: '2', name: 'Campaign 2', @@ -134,33 +155,26 @@ export const MOCKS_ERROR_CREATE_CAMPAIGN = [ endDate: '2021-01-01', currency: 'USD', }, + { + _id: '1', + name: 'Campaign 1', + fundingGoal: 100, + startDate: '2024-01-01', + endDate: '2024-01-01', + currency: 'USD', + }, ], }, }, }, }, - - { - request: { - query: CREATE_CAMPAIGN_MUTATION, - variables: { - fundId: undefined, - name: 'Campaign 1', - fundingGoal: 100, - startDate: '2024-03-10', - endDate: '2024-03-10', - currency: 'USD', - }, - }, - error: new Error('An error occurred'), - }, -]; -export const MOCKS_ERROR_UPDATE_CAMPAIGN = [ { request: { query: FUND_CAMPAIGN, variables: { - id: undefined, + id: 'fundId', + orderBy: 'fundingGoal_ASC', + where: { name_contains: '' }, }, }, result: { @@ -171,8 +185,8 @@ export const MOCKS_ERROR_UPDATE_CAMPAIGN = [ _id: '1', name: 'Campaign 1', fundingGoal: 100, - startDate: '2021-01-01', - endDate: '2021-01-01', + startDate: '2024-01-01', + endDate: '2024-01-01', currency: 'USD', }, { @@ -190,48 +204,39 @@ export const MOCKS_ERROR_UPDATE_CAMPAIGN = [ }, { request: { - query: UPDATE_CAMPAIGN_MUTATION, + query: CREATE_CAMPAIGN_MUTATION, variables: { - id: undefined, - name: 'Campaign 1', - fundingGoal: 100, - startDate: '2024-03-10', - endDate: '2024-03-10', + fundId: 'fundId', + name: 'Campaign 2', + fundingGoal: 200, + startDate: '2024-01-02', + endDate: '2024-02-02', currency: 'USD', }, }, - error: new Error('An error occurred'), + result: { + data: { + createFundraisingCampaign: { + _id: 'fundId', + }, + }, + }, }, -]; -export const MOCKS_ERROR_DELETE_CAMPAIGN = [ { request: { - query: FUND_CAMPAIGN, + query: UPDATE_CAMPAIGN_MUTATION, variables: { - id: undefined, + id: 'campaignId1', + name: 'Campaign 4', + fundingGoal: 400, + startDate: '2023-01-02', + endDate: '2023-02-02', }, }, result: { data: { - getFundById: { - campaigns: [ - { - _id: '1', - name: 'Campaign 1', - fundingGoal: 100, - startDate: '2021-01-01', - endDate: '2021-01-01', - currency: 'USD', - }, - { - _id: '2', - name: 'Campaign 2', - fundingGoal: 200, - startDate: '2021-01-01', - endDate: '2021-01-01', - currency: 'USD', - }, - ], + updateFundraisingCampaign: { + _id: 'campaignId1', }, }, }, @@ -240,18 +245,77 @@ export const MOCKS_ERROR_DELETE_CAMPAIGN = [ request: { query: DELETE_CAMPAIGN_MUTATION, variables: { - id: '1', + id: 'campaignId1', + }, + }, + result: { + data: { + removeFundraisingCampaign: { + _id: 'campaignId1', + }, + }, + }, + }, +]; + +export const MOCK_ERROR = [ + { + request: { + query: FUND_CAMPAIGN, + variables: { + id: 'fundId', + orderBy: null, + where: { name_contains: '2' }, }, }, error: new Error('An error occurred'), }, + { + request: { + query: CREATE_CAMPAIGN_MUTATION, + variables: { + fundId: 'fundId', + name: 'Campaign 2', + fundingGoal: 200, + startDate: '2024-01-02', + endDate: '2024-02-02', + currency: 'USD', + }, + }, + error: new Error('Mock graphql error'), + }, + { + request: { + query: UPDATE_CAMPAIGN_MUTATION, + variables: { + id: 'campaignId1', + name: 'Campaign 4', + fundingGoal: 400, + startDate: '2023-01-02', + endDate: '2023-02-02', + }, + }, + error: new Error('Mock graphql error'), + }, + { + request: { + query: DELETE_CAMPAIGN_MUTATION, + variables: { + id: 'campaignId1', + }, + }, + error: new Error('Mock graphql error'), + }, ]; + export const EMPTY_MOCKS = [ { request: { query: FUND_CAMPAIGN, variables: { - id: undefined, + id: 'fundId', + orderBy: null, + where: { name_contains: '' }, }, }, result: { diff --git a/src/screens/OrganizationFunds/FundCreateModal.tsx b/src/screens/OrganizationFunds/FundCreateModal.tsx deleted file mode 100644 index 4dcf32c265..0000000000 --- a/src/screens/OrganizationFunds/FundCreateModal.tsx +++ /dev/null @@ -1,118 +0,0 @@ -import React from 'react'; -import type { ChangeEvent } from 'react'; -import { Button, Form, Modal } from 'react-bootstrap'; -import type { InterfaceCreateFund } from 'utils/interfaces'; -import styles from './OrganizationFunds.module.css'; - -interface InterfaceFundCreateModal { - fundCreateModalIsOpen: boolean; - hideCreateModal: () => void; - formState: InterfaceCreateFund; - setFormState: (state: React.SetStateAction) => void; - createFundHandler: (e: ChangeEvent) => Promise; - taxDeductible: boolean; - setTaxDeductible: (state: React.SetStateAction) => void; - isDefault: boolean; - setIsDefault: (state: React.SetStateAction) => void; - t: (key: string) => string; -} - -const FundCreateModal: React.FC = ({ - fundCreateModalIsOpen, - hideCreateModal, - formState, - setFormState, - createFundHandler, - taxDeductible, - setTaxDeductible, - isDefault, - setIsDefault, - t, -}) => { - return ( - <> - - -

    {t('fundCreate')}

    - -
    - -
    - - {t('fundName')} - - setFormState({ - ...formState, - fundName: e.target.value, - }) - } - /> - - - {t('fundId')} - - setFormState({ - ...formState, - fundRef: e.target.value, - }) - } - /> - -
    - -
    - - setTaxDeductible(!taxDeductible)} - /> -
    -
    - -
    - - setIsDefault(!isDefault)} - /> -
    -
    -
    - -
    -
    -
    - - ); -}; -export default FundCreateModal; diff --git a/src/screens/OrganizationFunds/FundDeleteModal.test.tsx b/src/screens/OrganizationFunds/FundDeleteModal.test.tsx new file mode 100644 index 0000000000..41fcd3ec5e --- /dev/null +++ b/src/screens/OrganizationFunds/FundDeleteModal.test.tsx @@ -0,0 +1,100 @@ +import React from 'react'; +import type { ApolloLink } from '@apollo/client'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import type { RenderResult } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import i18nForTest from '../../utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { toast } from 'react-toastify'; +import type { InterfaceDeleteFundModal } from './FundDeleteModal'; +import FundDeleteModal from './FundDeleteModal'; +import { MOCKS, MOCKS_ERROR } from './OrganizationFundsMocks'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(MOCKS_ERROR); +const translations = JSON.parse( + JSON.stringify(i18nForTest.getDataByLanguage('en')?.translation.funds), +); + +const fundProps: InterfaceDeleteFundModal = { + isOpen: true, + hide: jest.fn(), + fund: { + _id: 'fundId', + name: 'Fund 1', + refrenceNumber: '1111', + taxDeductible: true, + isArchived: false, + isDefault: false, + createdAt: '2024-06-22', + organizationId: 'orgId', + creator: { + _id: 'creatorId1', + firstName: 'John', + lastName: 'Doe', + }, + }, + refetchFunds: jest.fn(), +}; +const renderFundDeleteModal = ( + link: ApolloLink, + props: InterfaceDeleteFundModal, +): RenderResult => { + return render( + + + + + + + + + + + , + ); +}; + +describe('FundDeleteModal', () => { + it('should render FundDeleteModal', () => { + renderFundDeleteModal(link1, fundProps); + expect(screen.getByTestId('deleteFundCloseBtn')).toBeInTheDocument(); + }); + + it('should successfully Delete Fund', async () => { + renderFundDeleteModal(link1, fundProps); + expect(screen.getByTestId('deleteFundCloseBtn')).toBeInTheDocument(); + + fireEvent.click(screen.getByTestId('deleteyesbtn')); + + await waitFor(() => { + expect(fundProps.refetchFunds).toHaveBeenCalled(); + expect(fundProps.hide).toHaveBeenCalled(); + expect(toast.success).toHaveBeenCalledWith(translations.fundDeleted); + }); + }); + + it('should fail to Delete Fund', async () => { + renderFundDeleteModal(link2, fundProps); + expect(screen.getByTestId('deleteFundCloseBtn')).toBeInTheDocument(); + + fireEvent.click(screen.getByTestId('deleteyesbtn')); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalledWith('Mock graphql error'); + }); + }); +}); diff --git a/src/screens/OrganizationFunds/FundDeleteModal.tsx b/src/screens/OrganizationFunds/FundDeleteModal.tsx new file mode 100644 index 0000000000..fb13206f1a --- /dev/null +++ b/src/screens/OrganizationFunds/FundDeleteModal.tsx @@ -0,0 +1,79 @@ +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import type { InterfaceFundInfo } from 'utils/interfaces'; +import styles from './OrganizationFunds.module.css'; +import { Button, Modal } from 'react-bootstrap'; +import { REMOVE_FUND_MUTATION } from 'GraphQl/Mutations/FundMutation'; +import { useMutation } from '@apollo/client'; +import { toast } from 'react-toastify'; + +export interface InterfaceDeleteFundModal { + isOpen: boolean; + hide: () => void; + fund: InterfaceFundInfo | null; + refetchFunds: () => void; +} + +const FundDeleteModal: React.FC = ({ + isOpen, + hide, + fund, + refetchFunds, +}) => { + const { t } = useTranslation('translation', { + keyPrefix: 'funds', + }); + const { t: tCommon } = useTranslation('common'); + + const [deleteFund] = useMutation(REMOVE_FUND_MUTATION); + + const deleteFundHandler = async (): Promise => { + try { + await deleteFund({ + variables: { + id: fund?._id, + }, + }); + refetchFunds(); + hide(); + toast.success(t('fundDeleted')); + } catch (error: unknown) { + toast.error((error as Error).message); + } + }; + + return ( + <> + + +

    {t('fundDelete')}

    + +
    + +

    {t('deleteFundMsg')}

    +
    + + + + +
    + + ); +}; + +export default FundDeleteModal; diff --git a/src/screens/OrganizationFunds/FundModal.test.tsx b/src/screens/OrganizationFunds/FundModal.test.tsx new file mode 100644 index 0000000000..c74b0434c3 --- /dev/null +++ b/src/screens/OrganizationFunds/FundModal.test.tsx @@ -0,0 +1,260 @@ +import React from 'react'; +import type { ApolloLink } from '@apollo/client'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import type { RenderResult } from '@testing-library/react'; +import { + cleanup, + fireEvent, + render, + screen, + waitFor, +} from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import i18nForTest from '../../utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { toast } from 'react-toastify'; +import { MOCKS, MOCKS_ERROR } from './OrganizationFundsMocks'; +import type { InterfaceFundModal } from './FundModal'; +import FundModal from './FundModal'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(MOCKS_ERROR); +const translations = JSON.parse( + JSON.stringify(i18nForTest.getDataByLanguage('en')?.translation.funds), +); + +const fundProps: InterfaceFundModal[] = [ + { + isOpen: true, + hide: jest.fn(), + fund: { + _id: 'fundId', + name: 'Fund 1', + refrenceNumber: '1111', + taxDeductible: true, + isArchived: false, + isDefault: false, + createdAt: '2024-06-22', + organizationId: 'orgId', + creator: { + _id: 'creatorId1', + firstName: 'John', + lastName: 'Doe', + }, + }, + refetchFunds: jest.fn(), + orgId: 'orgId', + mode: 'create', + }, + { + isOpen: true, + hide: jest.fn(), + fund: { + _id: 'fundId', + name: 'Fund 1', + refrenceNumber: '1111', + taxDeductible: true, + isArchived: false, + isDefault: false, + createdAt: '2024-06-22', + organizationId: 'orgId', + creator: { + _id: 'creatorId1', + firstName: 'John', + lastName: 'Doe', + }, + }, + refetchFunds: jest.fn(), + orgId: 'orgId', + mode: 'edit', + }, +]; + +const renderFundModal = ( + link: ApolloLink, + props: InterfaceFundModal, +): RenderResult => { + return render( + + + + + + + + + + + , + ); +}; + +describe('PledgeModal', () => { + afterEach(() => { + cleanup(); + }); + + it('should populate form fields with correct values in edit mode', async () => { + renderFundModal(link1, fundProps[1]); + await waitFor(() => + expect( + screen.getAllByText(translations.fundUpdate)[0], + ).toBeInTheDocument(), + ); + expect(screen.getByLabelText(translations.fundName)).toHaveValue('Fund 1'); + expect(screen.getByLabelText(translations.fundId)).toHaveValue('1111'); + expect(screen.getByTestId('setTaxDeductibleSwitch')).toBeChecked(); + expect(screen.getByTestId('setDefaultSwitch')).not.toBeChecked(); + expect(screen.getByTestId('archivedSwitch')).not.toBeChecked(); + }); + + it('should update Fund Name when input value changes', async () => { + renderFundModal(link1, fundProps[1]); + const fundNameInput = screen.getByLabelText(translations.fundName); + expect(fundNameInput).toHaveValue('Fund 1'); + fireEvent.change(fundNameInput, { target: { value: 'Fund 2' } }); + expect(fundNameInput).toHaveValue('Fund 2'); + }); + + it('should update Fund Reference ID when input value changes', async () => { + renderFundModal(link1, fundProps[1]); + const fundIdInput = screen.getByLabelText(translations.fundId); + expect(fundIdInput).toHaveValue('1111'); + fireEvent.change(fundIdInput, { target: { value: '2222' } }); + expect(fundIdInput).toHaveValue('2222'); + }); + + it('should update Tax Deductible Switch when input value changes', async () => { + renderFundModal(link1, fundProps[1]); + const taxDeductibleSwitch = screen.getByTestId('setTaxDeductibleSwitch'); + expect(taxDeductibleSwitch).toBeChecked(); + fireEvent.click(taxDeductibleSwitch); + expect(taxDeductibleSwitch).not.toBeChecked(); + }); + + it('should update Tax Default switch when input value changes', async () => { + renderFundModal(link1, fundProps[1]); + const defaultSwitch = screen.getByTestId('setDefaultSwitch'); + expect(defaultSwitch).not.toBeChecked(); + fireEvent.click(defaultSwitch); + expect(defaultSwitch).toBeChecked(); + }); + + it('should update Tax isArchived switch when input value changes', async () => { + renderFundModal(link1, fundProps[1]); + const archivedSwitch = screen.getByTestId('archivedSwitch'); + expect(archivedSwitch).not.toBeChecked(); + fireEvent.click(archivedSwitch); + expect(archivedSwitch).toBeChecked(); + }); + + it('should create fund', async () => { + renderFundModal(link1, fundProps[0]); + + const fundNameInput = screen.getByLabelText(translations.fundName); + fireEvent.change(fundNameInput, { target: { value: 'Fund 2' } }); + + const fundIdInput = screen.getByLabelText(translations.fundId); + fireEvent.change(fundIdInput, { target: { value: '2222' } }); + + const taxDeductibleSwitch = screen.getByTestId('setTaxDeductibleSwitch'); + fireEvent.click(taxDeductibleSwitch); + + const defaultSwitch = screen.getByTestId('setDefaultSwitch'); + fireEvent.click(defaultSwitch); + + fireEvent.click(screen.getByTestId('createFundFormSubmitBtn')); + + await waitFor(() => { + expect(toast.success).toHaveBeenCalledWith(translations.fundCreated); + expect(fundProps[0].refetchFunds).toHaveBeenCalled(); + expect(fundProps[0].hide).toHaveBeenCalled(); + }); + }); + + it('should update fund', async () => { + renderFundModal(link1, fundProps[1]); + + const fundNameInput = screen.getByLabelText(translations.fundName); + fireEvent.change(fundNameInput, { target: { value: 'Fund 2' } }); + + const fundIdInput = screen.getByLabelText(translations.fundId); + fireEvent.change(fundIdInput, { target: { value: '2222' } }); + + const taxDeductibleSwitch = screen.getByTestId('setTaxDeductibleSwitch'); + fireEvent.click(taxDeductibleSwitch); + + const defaultSwitch = screen.getByTestId('setDefaultSwitch'); + fireEvent.click(defaultSwitch); + + const archivedSwitch = screen.getByTestId('archivedSwitch'); + fireEvent.click(archivedSwitch); + + fireEvent.click(screen.getByTestId('createFundFormSubmitBtn')); + + await waitFor(() => { + expect(toast.success).toHaveBeenCalledWith(translations.fundUpdated); + expect(fundProps[1].refetchFunds).toHaveBeenCalled(); + expect(fundProps[1].hide).toHaveBeenCalled(); + }); + }); + + it('Error: should create fund', async () => { + renderFundModal(link2, fundProps[0]); + + const fundNameInput = screen.getByLabelText(translations.fundName); + fireEvent.change(fundNameInput, { target: { value: 'Fund 2' } }); + + const fundIdInput = screen.getByLabelText(translations.fundId); + fireEvent.change(fundIdInput, { target: { value: '2222' } }); + + const taxDeductibleSwitch = screen.getByTestId('setTaxDeductibleSwitch'); + fireEvent.click(taxDeductibleSwitch); + + const defaultSwitch = screen.getByTestId('setDefaultSwitch'); + fireEvent.click(defaultSwitch); + + fireEvent.click(screen.getByTestId('createFundFormSubmitBtn')); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalledWith('Mock graphql error'); + }); + }); + + it('Error: should update fund', async () => { + renderFundModal(link2, fundProps[1]); + + const fundNameInput = screen.getByLabelText(translations.fundName); + fireEvent.change(fundNameInput, { target: { value: 'Fund 2' } }); + + const fundIdInput = screen.getByLabelText(translations.fundId); + fireEvent.change(fundIdInput, { target: { value: '2222' } }); + + const taxDeductibleSwitch = screen.getByTestId('setTaxDeductibleSwitch'); + fireEvent.click(taxDeductibleSwitch); + + const defaultSwitch = screen.getByTestId('setDefaultSwitch'); + fireEvent.click(defaultSwitch); + + const archivedSwitch = screen.getByTestId('archivedSwitch'); + fireEvent.click(archivedSwitch); + + fireEvent.click(screen.getByTestId('createFundFormSubmitBtn')); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalledWith('Mock graphql error'); + }); + }); +}); diff --git a/src/screens/OrganizationFunds/FundModal.tsx b/src/screens/OrganizationFunds/FundModal.tsx new file mode 100644 index 0000000000..f4c6350a1c --- /dev/null +++ b/src/screens/OrganizationFunds/FundModal.tsx @@ -0,0 +1,258 @@ +import React, { useEffect, useState } from 'react'; +import type { ChangeEvent } from 'react'; +import { Button, Form, Modal } from 'react-bootstrap'; +import type { InterfaceCreateFund, InterfaceFundInfo } from 'utils/interfaces'; +import styles from './OrganizationFunds.module.css'; +import { useTranslation } from 'react-i18next'; +import { useMutation } from '@apollo/client'; +import { + CREATE_FUND_MUTATION, + UPDATE_FUND_MUTATION, +} from 'GraphQl/Mutations/FundMutation'; +import { toast } from 'react-toastify'; +import { FormControl, TextField } from '@mui/material'; + +export interface InterfaceFundModal { + isOpen: boolean; + hide: () => void; + refetchFunds: () => void; + fund: InterfaceFundInfo | null; + orgId: string; + mode: 'create' | 'edit'; +} + +const FundModal: React.FC = ({ + isOpen, + hide, + refetchFunds, + fund, + orgId, + mode, +}) => { + const { t } = useTranslation('translation', { + keyPrefix: 'funds', + }); + + const [formState, setFormState] = useState({ + fundName: fund?.name ?? '', + fundRef: fund?.refrenceNumber ?? '', + isDefault: fund?.isDefault ?? false, + taxDeductible: fund?.taxDeductible ?? false, + isArchived: fund?.isArchived ?? false, + }); + + useEffect(() => { + setFormState({ + fundName: fund?.name ?? '', + fundRef: fund?.refrenceNumber ?? '', + isDefault: fund?.isDefault ?? false, + taxDeductible: fund?.taxDeductible ?? false, + isArchived: fund?.isArchived ?? false, + }); + }, [fund]); + + const [createFund] = useMutation(CREATE_FUND_MUTATION); + const [updateFund] = useMutation(UPDATE_FUND_MUTATION); + + const createFundHandler = async ( + e: ChangeEvent, + ): Promise => { + e.preventDefault(); + const { fundName, fundRef, isDefault, taxDeductible, isArchived } = + formState; + try { + await createFund({ + variables: { + name: fundName, + refrenceNumber: fundRef, + organizationId: orgId, + taxDeductible, + isArchived, + isDefault, + }, + }); + + setFormState({ + fundName: '', + fundRef: '', + isDefault: false, + taxDeductible: false, + isArchived: false, + }); + toast.success(t('fundCreated')); + refetchFunds(); + hide(); + } catch (error: unknown) { + toast.error((error as Error).message); + } + }; + + /*istanbul ignore next*/ + const updateFundHandler = async ( + e: ChangeEvent, + ): Promise => { + e.preventDefault(); + const { fundName, fundRef, taxDeductible, isArchived, isDefault } = + formState; + try { + const updatedFields: { [key: string]: string | boolean } = {}; + if (fundName != fund?.name) { + updatedFields.name = fundName; + } + if (fundRef != fund?.refrenceNumber) { + updatedFields.refrenceNumber = fundRef; + } + if (taxDeductible != fund?.taxDeductible) { + updatedFields.taxDeductible = taxDeductible; + } + if (isArchived != fund?.isArchived) { + updatedFields.isArchived = isArchived; + } + if (isDefault != fund?.isDefault) { + updatedFields.isDefault = isDefault; + } + + await updateFund({ + variables: { + id: fund?._id, + ...updatedFields, + }, + }); + setFormState({ + fundName: '', + fundRef: '', + isDefault: false, + taxDeductible: false, + isArchived: false, + }); + refetchFunds(); + hide(); + toast.success(t('fundUpdated')); + } catch (error: unknown) { + if (error instanceof Error) { + toast.error(error.message); + } + } + }; + + return ( + <> + + +

    + {t(mode === 'create' ? 'fundCreate' : 'fundUpdate')} +

    + +
    + +
    + + + + setFormState({ + ...formState, + fundName: e.target.value, + }) + } + /> + + + + + + setFormState({ + ...formState, + fundRef: e.target.value, + }) + } + /> + + + +
    + + + + setFormState({ + ...formState, + taxDeductible: !formState.taxDeductible, + }) + } + /> + + + + + setFormState({ + ...formState, + isDefault: !formState.isDefault, + }) + } + /> + + {mode === 'edit' && ( + + + + setFormState({ + ...formState, + isArchived: !formState.isArchived, + }) + } + /> + + )} +
    + +
    +
    +
    + + ); +}; +export default FundModal; diff --git a/src/screens/OrganizationFunds/FundUpdateModal.tsx b/src/screens/OrganizationFunds/FundUpdateModal.tsx deleted file mode 100644 index 2a351a1c8c..0000000000 --- a/src/screens/OrganizationFunds/FundUpdateModal.tsx +++ /dev/null @@ -1,155 +0,0 @@ -import type { ChangeEvent } from 'react'; -import React from 'react'; -import { Button, Form, Modal } from 'react-bootstrap'; -import type { InterfaceCreateFund } from 'utils/interfaces'; -import styles from './OrganizationFunds.module.css'; - -interface InterfaceFundUpdateModal { - fundUpdateModalIsOpen: boolean; - hideUpdateModal: () => void; - formState: InterfaceCreateFund; - setFormState: (state: React.SetStateAction) => void; - updateFundHandler: (e: ChangeEvent) => Promise; - taxDeductible: boolean; - setTaxDeductible: (state: React.SetStateAction) => void; - isArchived: boolean; - deleteFundHandler: () => Promise; - setIsArchived: (state: React.SetStateAction) => void; - isDefault: boolean; - setIsDefault: (state: React.SetStateAction) => void; - t: (key: string) => string; -} - -const FundUpdateModal: React.FC = ({ - fundUpdateModalIsOpen, - hideUpdateModal, - formState, - setFormState, - updateFundHandler, - taxDeductible, - setTaxDeductible, - isArchived, - deleteFundHandler, - setIsArchived, - isDefault, - setIsDefault, - t, -}) => { - return ( - <> - - -

    {t('manageFund')}

    - -
    - -
    - - {t('fundName')} - - setFormState({ - ...formState, - fundName: e.target.value, - }) - } - /> - - - {t('fundId')} - - setFormState({ - ...formState, - fundRef: e.target.value, - }) - } - /> - - -
    -
    - -
    - - setTaxDeductible(!taxDeductible)} - /> -
    -
    - -
    - - setIsDefault(!isDefault)} - /> -
    -
    -
    -
    - -
    - - setIsArchived(!isArchived)} - /> -
    -
    -
    -
    -
    - - -
    -
    -
    -
    - - ); -}; -export default FundUpdateModal; diff --git a/src/screens/OrganizationFunds/OrganizationFunds.module.css b/src/screens/OrganizationFunds/OrganizationFunds.module.css index 07e16ad0a8..aa9d89dfb1 100644 --- a/src/screens/OrganizationFunds/OrganizationFunds.module.css +++ b/src/screens/OrganizationFunds/OrganizationFunds.module.css @@ -21,24 +21,13 @@ border: 1px solid #31bb6b; position: relative; display: inline-block; - margin-top: 10px; - margin-bottom: 10px; color: #31bb6b; } -.createFundBtn { - margin-top: 10px; -} - .fundName { font-weight: 600; cursor: pointer; } -.fundModal { - max-width: 80vw; - margin-top: 2vh; - margin-left: 13vw; -} .modalHeader { border: none; @@ -49,12 +38,33 @@ color: var(--bs-emphasis-color); } +.fundModal { + max-width: 80vw; + margin-top: 2vh; + margin-left: 13vw; +} + .titlemodal { + color: #707070; font-weight: 600; - font-size: 25px; - margin-top: 1rem; + font-size: 32px; width: 65%; + margin-bottom: 0px; } + +.noOutline input { + outline: none; +} + +.modalCloseBtn { + width: 40px; + height: 40px; + padding: 1rem; + display: flex; + justify-content: center; + align-items: center; +} + .greenregbtn { margin: 1rem 0 0; margin-top: 15px; @@ -95,22 +105,12 @@ .btnsContainer { display: flex; - margin: 2.5rem 0 2.5rem 0; -} - -.btnsContainer .btnsBlock { - display: flex; -} - -.btnsContainer .btnsBlock div button { - display: flex; - margin-left: 1rem; - justify-content: center; - align-items: center; + margin: 2rem 0 2.5rem 0; } .btnsContainer .input { flex: 1; + min-width: 18rem; position: relative; } @@ -130,48 +130,13 @@ margin-bottom: 20px; } -@media (max-width: 1020px) { - .btnsContainer { - flex-direction: column; - margin: 1.5rem 0; - } - - .btnsContainer .btnsBlock { - margin: 1.5rem 0 0 0; - justify-content: space-between; - } - - .btnsContainer .btnsBlock div button { - margin: 0; - } - - .createFundBtn { - margin-top: 0; - } -} - -@media screen and (max-width: 575.5px) { - .mainpageright { - width: 98%; - } +.rowBackground { + background-color: var(--bs-white); + max-height: 120px; } -/* For mobile devices */ - -@media (max-width: 520px) { - .btnsContainer { - margin-bottom: 0; - } - - .btnsContainer .btnsBlock { - display: block; - margin-top: 1rem; - margin-right: 0; - } - - .btnsContainer .btnsBlock div button { - margin-bottom: 1rem; - margin-right: 0; - width: 100%; - } +.tableHeader { + background-color: var(--bs-primary); + color: var(--bs-white); + font-size: 1rem; } diff --git a/src/screens/OrganizationFunds/OrganizationFunds.test.tsx b/src/screens/OrganizationFunds/OrganizationFunds.test.tsx index 93be2c281c..a1b49e68eb 100644 --- a/src/screens/OrganizationFunds/OrganizationFunds.test.tsx +++ b/src/screens/OrganizationFunds/OrganizationFunds.test.tsx @@ -1,407 +1,260 @@ import React from 'react'; import { MockedProvider } from '@apollo/client/testing'; +import type { RenderResult } from '@testing-library/react'; import { - act, + cleanup, fireEvent, render, screen, waitFor, - waitForElementToBeRemoved, } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { I18nextProvider } from 'react-i18next'; import { Provider } from 'react-redux'; -import { BrowserRouter } from 'react-router-dom'; -import { toast } from 'react-toastify'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; import { store } from 'state/store'; import { StaticMockLink } from 'utils/StaticMockLink'; import i18nForTest from 'utils/i18nForTest'; import OrganizationFunds from './OrganizationFunds'; -import { - MOCKS, - MOCKS_ERROR_CREATE_FUND, - MOCKS_ERROR_ORGANIZATIONS_FUNDS, - MOCKS_ERROR_REMOVE_FUND, - MOCKS_ERROR_UPDATE_FUND, - NO_FUNDS, -} from './OrganizationFundsMocks'; -const mockNavigate = jest.fn(); -jest.mock('react-router-dom', () => ({ - ...jest.requireActual('react-router-dom'), - useNavigate: () => mockNavigate, -})); +import { MOCKS, MOCKS_ERROR, NO_FUNDS } from './OrganizationFundsMocks'; +import type { ApolloLink } from '@apollo/client'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; + jest.mock('react-toastify', () => ({ toast: { success: jest.fn(), error: jest.fn(), }, })); -async function wait(ms = 100): Promise { - await act(() => { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); - }); -} + const link1 = new StaticMockLink(MOCKS, true); -const link2 = new StaticMockLink(MOCKS_ERROR_ORGANIZATIONS_FUNDS, true); -const link3 = new StaticMockLink(MOCKS_ERROR_CREATE_FUND, true); -const link4 = new StaticMockLink(MOCKS_ERROR_UPDATE_FUND, true); -const link5 = new StaticMockLink(MOCKS_ERROR_REMOVE_FUND, true); -const link6 = new StaticMockLink(NO_FUNDS, true); +const link2 = new StaticMockLink(MOCKS_ERROR, true); +const link3 = new StaticMockLink(NO_FUNDS, true); const translations = JSON.parse( JSON.stringify(i18nForTest.getDataByLanguage('en')?.translation.funds), ); -describe('Testing OrganizationFunds screen', () => { - const formData = { - fundName: 'Test Fund', - fundRef: '1', - }; - it("loads the OrganizationFunds screen and it's components", async () => { - const { getByText } = render( - + +const renderOrganizationFunds = (link: ApolloLink): RenderResult => { + return render( + + - + - {} + + } + /> + } + /> + } + /> + - + - , - ); - await wait(); - await waitFor(() => { - expect(getByText(translations.createFund)).toBeInTheDocument(); - }); + + , + ); +}; + +describe('OrganizationFunds Screen =>', () => { + beforeEach(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId' }), + })); }); - it("renders the OrganizationFunds screen and it's components with error", async () => { - const { queryByText } = render( - - - - - {} - - - - , - ); - await wait(); - await waitFor(() => { - expect(queryByText(translations.createFund)).not.toBeInTheDocument(); - }); + + afterEach(() => { + jest.clearAllMocks(); }); - it('renders the Error component', async () => { - render( - - - - - {} - - - - , - ); - await wait(); - await waitFor(() => { - expect(screen.getByTestId('errorMsg')).toBeInTheDocument(); - }); + + afterEach(() => { + cleanup(); }); - it('renders the funds component based on fund type', async () => { - render( - - - - - {} - - - - , - ); - await wait(); - await waitFor(() => { - expect(screen.getAllByTestId('fundtype')[0]).toBeInTheDocument(); - }); + + it('should render the Campaign Pledge screen', async () => { + renderOrganizationFunds(link1); await waitFor(() => { - expect(screen.getAllByTestId('fundtype')[0]).toHaveTextContent( - translations.nonArchive, - ); + expect(screen.getByTestId('searchByName')).toBeInTheDocument(); }); - expect(screen.getAllByTestId('fundtype')[1]).toHaveTextContent( - translations.archived, - ); }); - it("opens and closes the 'Create Fund' modal", async () => { + + it('should redirect to fallback URL if URL params are undefined', async () => { render( - - + + - {} + + } /> + } + /> + - - + + , ); - await wait(); - await waitFor(() => { - expect(screen.getByTestId('createFundBtn')).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('createFundBtn')); await waitFor(() => { - return expect( - screen.findByTestId('createFundModalCloseBtn'), - ).resolves.toBeInTheDocument(); + expect(screen.getByTestId('paramsError')).toBeInTheDocument(); }); - userEvent.click(screen.getByTestId('setTaxDeductibleSwitch')); - userEvent.click(screen.getByTestId('setDefaultSwitch')); - userEvent.click(screen.getByTestId('createFundModalCloseBtn')); - await waitForElementToBeRemoved(() => - screen.queryByTestId('createFundModalCloseBtn'), - ); }); - it('noFunds to be in the document', async () => { - render( - - - - - {} - - - - , + + it('open and close Create Fund modal', async () => { + renderOrganizationFunds(link1); + + const createFundBtn = await screen.findByTestId('createFundBtn'); + expect(createFundBtn).toBeInTheDocument(); + userEvent.click(createFundBtn); + + await waitFor(() => + expect(screen.getAllByText(translations.fundCreate)).toHaveLength(3), ); - await wait(); - await waitFor(() => { - expect(screen.getByText(translations.noFundsFound)).toBeInTheDocument(); - }); - }); - it('creates a new fund', async () => { - render( - - - - - {} - - - - , + userEvent.click(screen.getByTestId('fundModalCloseBtn')); + await waitFor(() => + expect(screen.queryByTestId('fundModalCloseBtn')).toBeNull(), ); - await wait(); - await waitFor(() => { - expect(screen.getByTestId('createFundBtn')).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('createFundBtn')); + }); + + it('open and close update fund modal', async () => { + renderOrganizationFunds(link1); + await waitFor(() => { - return expect( - screen.findByTestId('createFundModalCloseBtn'), - ).resolves.toBeInTheDocument(); + expect(screen.getByTestId('searchByName')).toBeInTheDocument(); }); - userEvent.type( - screen.getByPlaceholderText(translations.enterfundName), - formData.fundName, + + const editFundBtn = await screen.findAllByTestId('editFundBtn'); + await waitFor(() => expect(editFundBtn[0]).toBeInTheDocument()); + userEvent.click(editFundBtn[0]); + + await waitFor(() => + expect( + screen.getAllByText(translations.fundUpdate)[0], + ).toBeInTheDocument(), ); - userEvent.type( - screen.getByPlaceholderText(translations.enterfundId), - formData.fundRef, + userEvent.click(screen.getByTestId('fundModalCloseBtn')); + await waitFor(() => + expect(screen.queryByTestId('fundModalCloseBtn')).toBeNull(), ); - userEvent.click(screen.getByTestId('setTaxDeductibleSwitch')); - userEvent.click(screen.getByTestId('setDefaultSwitch')); - userEvent.click(screen.getByTestId('setTaxDeductibleSwitch')); - userEvent.click(screen.getByTestId('setDefaultSwitch')); - await wait(); - userEvent.click(screen.getByTestId('createFundFormSubmitBtn')); - - await waitFor(() => { - expect(toast.success).toBeCalledWith(translations.fundCreated); - }); }); - it('updates fund successfully', async () => { - render( - - - - - {} - - - - , + + it('open and closes delete fund modal', async () => { + renderOrganizationFunds(link1); + + const deleteFundBtn = await screen.findAllByTestId('deleteFundBtn'); + await waitFor(() => expect(deleteFundBtn[0]).toBeInTheDocument()); + userEvent.click(deleteFundBtn[0]); + + await waitFor(() => + expect(screen.getByText(translations.fundDelete)).toBeInTheDocument(), ); - await wait(); - userEvent.click(screen.getAllByTestId('editFundBtn')[0]); - await wait(); - userEvent.clear(screen.getByTestId('fundNameInput')); - userEvent.clear(screen.getByTestId('fundIdInput')); - userEvent.type(screen.getByTestId('fundNameInput'), 'Test Fund'); - userEvent.type(screen.getByTestId('fundIdInput'), '1'); - expect(screen.getByTestId('taxDeductibleSwitch')).toBeInTheDocument(); - expect(screen.getByTestId('defaultSwitch')).toBeInTheDocument(); - expect(screen.getByTestId('archivedSwitch')).toBeInTheDocument(); - expect(screen.getByTestId('updateFormBtn')).toBeInTheDocument(); - userEvent.click(screen.getByTestId('taxDeductibleSwitch')); - userEvent.click(screen.getByTestId('defaultSwitch')); - userEvent.click(screen.getByTestId('archivedSwitch')); - await wait(); - userEvent.click(screen.getByTestId('updateFormBtn')); - await wait(); - await waitFor(() => { - expect(toast.success).toBeCalledWith(translations.fundUpdated); - }); - }); - it('toast error on unsuccessful fund creation', async () => { - render( - - - - - {} - - - - , + userEvent.click(screen.getByTestId('deleteFundCloseBtn')); + await waitFor(() => + expect(screen.queryByTestId('deleteFundCloseBtn')).toBeNull(), ); - await wait(); - await waitFor(() => { - expect(screen.getByTestId('createFundBtn')).toBeInTheDocument(); + }); + + it('Search the Funds list by name', async () => { + renderOrganizationFunds(link1); + const searchField = await screen.findByTestId('searchByName'); + fireEvent.change(searchField, { + target: { value: '2' }, }); - userEvent.click(screen.getByTestId('createFundBtn')); + await waitFor(() => { - return expect( - screen.findByTestId('createFundModalCloseBtn'), - ).resolves.toBeInTheDocument(); + expect(screen.getByText('Fund 2')).toBeInTheDocument(); + expect(screen.queryByText('Fund 1')).toBeNull(); }); - userEvent.type( - screen.getByPlaceholderText(translations.enterfundName), - formData.fundName, - ); - userEvent.type( - screen.getByPlaceholderText(translations.enterfundId), - formData.fundRef, - ); - userEvent.click(screen.getByTestId('createFundFormSubmitBtn')); + }); + it('should render the Fund screen with error', async () => { + renderOrganizationFunds(link2); await waitFor(() => { - expect(toast.error).toHaveBeenCalled(); + expect(screen.getByTestId('errorMsg')).toBeInTheDocument(); }); }); - it('toast error on unsuccessful fund update', async () => { - render( - - - - - {} - - - - , + + it('renders the empty fund component', async () => { + renderOrganizationFunds(link3); + await waitFor(() => + expect(screen.getByText(translations.noFundsFound)).toBeInTheDocument(), ); - await wait(); - await waitFor(() => { - expect(screen.getAllByTestId('editFundBtn')[0]).toBeInTheDocument(); - }); - userEvent.click(screen.getAllByTestId('editFundBtn')[0]); + }); + + it('Sort the Pledges list by Latest created Date', async () => { + renderOrganizationFunds(link1); + + const sortBtn = await screen.findByTestId('filter'); + expect(sortBtn).toBeInTheDocument(); + + fireEvent.click(sortBtn); + fireEvent.click(screen.getByTestId('createdAt_DESC')); + await waitFor(() => { - return expect( - screen.findByTestId('editFundModalCloseBtn'), - ).resolves.toBeInTheDocument(); + expect(screen.getByText('Fund 1')).toBeInTheDocument(); + expect(screen.queryByText('Fund 2')).toBeInTheDocument(); }); - userEvent.type( - screen.getByPlaceholderText(translations.enterfundName), - 'Test Fund Updated', - ); - userEvent.click(screen.getByTestId('updateFormBtn')); await waitFor(() => { - expect(toast.error).toHaveBeenCalled(); + expect(screen.getAllByTestId('createdOn')[0]).toHaveTextContent( + '22/06/2024', + ); }); }); - it('redirects to campaign screen when clicked on fund name', async () => { - render( - - - - - {} - - - - , - ); - await wait(); + + it('Sort the Pledges list by Earliest created Date', async () => { + renderOrganizationFunds(link1); + + const sortBtn = await screen.findByTestId('filter'); + expect(sortBtn).toBeInTheDocument(); + + fireEvent.click(sortBtn); + fireEvent.click(screen.getByTestId('createdAt_ASC')); + await waitFor(() => { - expect(screen.getAllByTestId('fundName')[0]).toBeInTheDocument(); + expect(screen.getByText('Fund 1')).toBeInTheDocument(); + expect(screen.queryByText('Fund 2')).toBeInTheDocument(); }); - userEvent.click(screen.getAllByTestId('fundName')[0]); + await waitFor(() => { - expect(mockNavigate).toBeCalledWith('/orgfundcampaign/undefined/1'); + expect(screen.getAllByTestId('createdOn')[0]).toHaveTextContent( + '21/06/2024', + ); }); }); - it('delete fund succesfully', async () => { - render( - - - - - {} - - - - , - ); - await wait(); - userEvent.click(screen.getAllByTestId('editFundBtn')[0]); - await wait(); - userEvent.click(screen.getByTestId('fundDeleteModalDeleteBtn')); + + it('Click on Fund Name', async () => { + renderOrganizationFunds(link1); + + const fundName = await screen.findAllByTestId('fundName'); + expect(fundName[0]).toBeInTheDocument(); + fireEvent.click(fundName[0]); + await waitFor(() => { - expect(toast.success).toBeCalledWith(translations.fundDeleted); + expect(screen.getByTestId('campaignScreen')).toBeInTheDocument(); }); }); - it('throws error on unsuccessful fund deletion', async () => { - render( - - - - - {} - - - - , - ); - await wait(); - userEvent.click(screen.getAllByTestId('editFundBtn')[0]); - await wait(); - userEvent.click(screen.getByTestId('fundDeleteModalDeleteBtn')); + + it('Click on View Campaign', async () => { + renderOrganizationFunds(link1); + + const viewBtn = await screen.findAllByTestId('viewBtn'); + expect(viewBtn[0]).toBeInTheDocument(); + fireEvent.click(viewBtn[0]); + await waitFor(() => { - expect(toast.error).toBeCalled(); + expect(screen.getByTestId('campaignScreen')).toBeInTheDocument(); }); }); - it('search funds by name', async () => { - render( - - - - - {} - - - - , - ); - await wait(); - userEvent.click(screen.getAllByTestId('editFundBtn')[0]); - await wait(); - userEvent.click(screen.getByTestId('editFundModalCloseBtn')); - await wait(); - userEvent.type(screen.getByTestId('searchFullName'), 'Funndds'); - await wait(); - userEvent.click(screen.getByTestId('searchBtn')); - }); }); diff --git a/src/screens/OrganizationFunds/OrganizationFunds.tsx b/src/screens/OrganizationFunds/OrganizationFunds.tsx index cecedff2f1..4357877105 100644 --- a/src/screens/OrganizationFunds/OrganizationFunds.tsx +++ b/src/screens/OrganizationFunds/OrganizationFunds.tsx @@ -1,55 +1,48 @@ -/*eslint-disable*/ -import { useMutation, useQuery } from '@apollo/client'; -import { Search, WarningAmberRounded } from '@mui/icons-material'; +import { useQuery } from '@apollo/client'; +import { Search, Sort, WarningAmberRounded } from '@mui/icons-material'; +import { Stack } from '@mui/material'; import { - CREATE_FUND_MUTATION, - REMOVE_FUND_MUTATION, - UPDATE_FUND_MUTATION, -} from 'GraphQl/Mutations/FundMutation'; -import Loader from 'components/Loader/Loader'; -import { useState, type ChangeEvent } from 'react'; -import { Button, Col, Dropdown, Form, Row } from 'react-bootstrap'; + DataGrid, + type GridCellParams, + type GridColDef, +} from '@mui/x-data-grid'; +import { Button, Dropdown, Form } from 'react-bootstrap'; import { useTranslation } from 'react-i18next'; -import { useNavigate, useParams } from 'react-router-dom'; -import { toast } from 'react-toastify'; -import type { - InterfaceCreateFund, - InterfaceFundInfo, - InterfaceQueryOrganizationFunds, -} from 'utils/interfaces'; -import FundCreateModal from './FundCreateModal'; -import FundUpdateModal from './FundUpdateModal'; -import FilterAltOutlinedIcon from '@mui/icons-material/FilterAltOutlined'; -import styles from './OrganizationFunds.module.css'; -import { - Paper, - Table, - TableBody, - TableCell, - TableContainer, - TableHead, - TableRow, - styled, - tableCellClasses, -} from '@mui/material'; +import { Navigate, useNavigate, useParams } from 'react-router-dom'; +import React, { useCallback, useMemo, useState } from 'react'; import dayjs from 'dayjs'; +import Loader from 'components/Loader/Loader'; +import FundModal from './FundModal'; +import FundDeleteModal from './FundDeleteModal'; import { FUND_LIST } from 'GraphQl/Queries/fundQueries'; +import styles from './OrganizationFunds.module.css'; +import type { InterfaceFundInfo } from 'utils/interfaces'; -const StyledTableCell = styled(TableCell)(({ theme }) => ({ - [`&.${tableCellClasses.head}`]: { - backgroundColor: ['#31bb6b', '!important'], - color: theme.palette.common.white, +const dataGridStyle = { + '&.MuiDataGrid-root .MuiDataGrid-cell:focus-within': { + outline: 'none !important', }, - [`&.${tableCellClasses.body}`]: { - fontSize: 14, + '&.MuiDataGrid-root .MuiDataGrid-columnHeader:focus-within': { + outline: 'none', }, -})); - -const StyledTableRow = styled(TableRow)(() => ({ - '&:last-child td, &:last-child th': { - border: 0, + '& .MuiDataGrid-row:hover': { + backgroundColor: 'transparent', + }, + '& .MuiDataGrid-row.Mui-hovered': { + backgroundColor: 'transparent', }, -})); + '& .MuiDataGrid-root': { + borderRadius: '0.5rem', + }, + '& .MuiDataGrid-main': { + borderRadius: '0.5rem', + }, +}; + +enum ModalState { + SAME = 'same', + DELETE = 'delete', +} const organizationFunds = (): JSX.Element => { const { t } = useTranslation('translation', { @@ -57,21 +50,43 @@ const organizationFunds = (): JSX.Element => { }); const { t: tCommon } = useTranslation('common'); - const { orgId: currentUrl } = useParams(); + const { orgId } = useParams(); const navigate = useNavigate(); - const [fundCreateModalIsOpen, setFundCreateModalIsOpen] = - useState(false); - const [fundUpdateModalIsOpen, setFundUpdateModalIsOpen] = - useState(false); - const [taxDeductible, setTaxDeductible] = useState(true); - const [isArchived, setIsArchived] = useState(false); - const [isDefault, setIsDefault] = useState(false); + if (!orgId) { + return ; + } + const [fund, setFund] = useState(null); - const [formState, setFormState] = useState({ - fundName: '', - fundRef: '', + const [searchTerm, setSearchTerm] = useState(''); + const [sortBy, setSortBy] = useState<'createdAt_ASC' | 'createdAt_DESC'>( + 'createdAt_DESC', + ); + + const [modalState, setModalState] = useState<{ + [key in ModalState]: boolean; + }>({ + [ModalState.SAME]: false, + [ModalState.DELETE]: false, }); + const [fundModalMode, setFundModalMode] = useState<'edit' | 'create'>( + 'create', + ); + + const openModal = (modal: ModalState): void => + setModalState((prevState) => ({ ...prevState, [modal]: true })); + + const closeModal = (modal: ModalState): void => + setModalState((prevState) => ({ ...prevState, [modal]: false })); + + const handleOpenModal = useCallback( + (fund: InterfaceFundInfo | null, mode: 'edit' | 'create'): void => { + setFund(fund); + setFundModalMode(mode); + openModal(ModalState.SAME); + }, + [openModal], + ); const { data: fundData, @@ -80,144 +95,31 @@ const organizationFunds = (): JSX.Element => { refetch: refetchFunds, }: { data?: { - fundsByOrganization: InterfaceQueryOrganizationFunds[]; + fundsByOrganization: InterfaceFundInfo[]; }; loading: boolean; error?: Error | undefined; - refetch: any; + refetch: () => void; } = useQuery(FUND_LIST, { variables: { - organizationId: currentUrl, + organizationId: orgId, + filter: searchTerm, + orderBy: sortBy, }, }); - const [fullName, setFullName] = useState(''); - const handleSearch = (): void => { - refetchFunds({ organizationId: currentUrl, filter: fullName }); - }; - - const [createFund] = useMutation(CREATE_FUND_MUTATION); - const [updateFund] = useMutation(UPDATE_FUND_MUTATION); - const [deleteFund] = useMutation(REMOVE_FUND_MUTATION); - - const showCreateModal = (): void => { - setFundCreateModalIsOpen(!fundCreateModalIsOpen); - }; - const hideCreateModal = (): void => { - setFundCreateModalIsOpen(!fundCreateModalIsOpen); - }; - const showUpdateModal = (): void => { - setFundUpdateModalIsOpen(!fundUpdateModalIsOpen); - }; - const hideUpdateModal = (): void => { - setFundUpdateModalIsOpen(!fundUpdateModalIsOpen); - }; - const toggleDeleteModal = (): void => { - setFundUpdateModalIsOpen(!fundUpdateModalIsOpen); - }; - const handleEditClick = (fund: InterfaceFundInfo): void => { - setFormState({ - fundName: fund.name, - fundRef: fund.refrenceNumber, - }); - setTaxDeductible(fund.taxDeductible); - setIsArchived(fund.isArchived); - setIsDefault(fund.isDefault); - setFund(fund); - showUpdateModal(); - }; - const createFundHandler = async ( - e: ChangeEvent, - ): Promise => { - e.preventDefault(); - try { - await createFund({ - variables: { - name: formState.fundName, - refrenceNumber: formState.fundRef, - organizationId: currentUrl, - taxDeductible: taxDeductible, - isArchived: isArchived, - isDefault: isDefault, - }, - }); + const handleDeleteClick = useCallback( + (fund: InterfaceFundInfo): void => { + setFund(fund); + openModal(ModalState.DELETE); + }, + [openModal], + ); - setFormState({ - fundName: '', - fundRef: '', - }); - toast.success(t('fundCreated')); - refetchFunds(); - hideCreateModal(); - } catch (error: unknown) { - if (error instanceof Error) { - toast.error(error.message); - console.log(error.message); - } - } - }; - const updateFundHandler = async ( - e: ChangeEvent, - ): Promise => { - e.preventDefault(); - try { - const updatedFields: { [key: string]: any } = {}; - if (formState.fundName != fund?.name) { - updatedFields.name = formState.fundName; - } - if (formState.fundRef != fund?.refrenceNumber) { - updatedFields.refrenceNumber = formState.fundRef; - } - if (taxDeductible != fund?.taxDeductible) { - updatedFields.taxDeductible = taxDeductible; - } - if (isArchived != fund?.isArchived) { - updatedFields.isArchived = isArchived; - } - if (isDefault != fund?.isDefault) { - updatedFields.isDefault = isDefault; - } + const funds = useMemo(() => fundData?.fundsByOrganization ?? [], [fundData]); - await updateFund({ - variables: { - id: fund?._id, - ...updatedFields, - }, - }); - setFormState({ - fundName: '', - fundRef: '', - }); - refetchFunds(); - hideUpdateModal(); - toast.success(t('fundUpdated')); - } catch (error: unknown) { - if (error instanceof Error) { - toast.error(error.message); - console.log(error.message); - } - } - }; - const deleteFundHandler = async (): Promise => { - try { - await deleteFund({ - variables: { - id: fund?._id, - }, - }); - refetchFunds(); - toggleDeleteModal(); - toast.success(t('fundDeleted')); - } catch (error: unknown) { - if (error instanceof Error) { - toast.error(error.message); - console.log(error.message); - } - } - }; - - const handleClick = (fundId: String) => { - navigate(`/orgfundcampaign/${currentUrl}/${fundId}`); + const handleClick = (fundId: string): void => { + navigate(`/orgfundcampaign/${orgId}/${fundId}`); }; if (fundLoading) { @@ -238,187 +140,250 @@ const organizationFunds = (): JSX.Element => { ); } + const columns: GridColDef[] = [ + { + field: 'id', + headerName: 'Sr. No.', + flex: 1, + minWidth: 100, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return
    {params.row.id}
    ; + }, + }, + { + field: 'fundName', + headerName: 'Fund Name', + flex: 2, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( +
    handleClick(params.row._id as string)} + > + {params.row.name} +
    + ); + }, + }, + { + field: 'createdBy', + headerName: 'Created By', + flex: 2, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return params.row.creator.firstName + ' ' + params.row.creator.lastName; + }, + }, + { + field: 'createdOn', + headerName: 'Created On', + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + flex: 2, + renderCell: (params: GridCellParams) => { + return ( +
    + {dayjs(params.row.createdAt).format('DD/MM/YYYY')} +
    + ); + }, + }, + { + field: 'status', + headerName: 'Status', + flex: 2, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return params.row.isArchived ? 'Archived' : 'Active'; + }, + }, + { + field: 'action', + headerName: 'Action', + flex: 2, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( + <> + + + + ); + }, + }, + { + field: 'assocCampaigns', + headerName: 'Associated Campaigns', + flex: 2, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( + + ); + }, + }, + ]; + return ( - <> - -
    -
    -
    - ) => { - setFullName(e.target.value); - }} - data-testid="searchFullName" - /> - +
    +
    +
    + + - - -
    -
    -
    - - - - {tCommon('filter')} - - -
    -
    - -
    -
    + {t('createdLatest')} + + setSortBy('createdAt_ASC')} + data-testid="createdAt_ASC" + > + {t('createdEarliest')} + + + +
    +
    +
    - -
    -
    - {fundData?.fundsByOrganization && - fundData.fundsByOrganization.length > 0 ? ( -
    - - - - - # - - {t('fundName')} - - - {t('createdBy')} - - - {t('createdOn')} - - - {t('status')} - - - {t('manageFund')} - - - - - {fundData.fundsByOrganization.map( - (fund: any, index: number) => ( - - - {index + 1} - - handleClick(fund._id)} - > - - {fund.name} - - - - {fund.creator.firstName} {fund.creator.lastName} - - - {dayjs(fund.createdAt).format('DD/MM/YYYY')} - - - - - - - - - ), - )} - -
    -
    -
    - ) : ( -
    -
    {t('noFundsFound')}
    -
    - )} -
    - {/* - - {/*
    - + + row._id} + slots={{ + noRowsOverlay: () => ( + + {t('noFundsFound')} + + ), + }} + sx={dataGridStyle} + getRowClassName={() => `${styles.rowBackground}`} + autoHeight + rowHeight={65} + rows={funds.map((fund, index) => ({ + id: index + 1, + ...fund, + }))} + columns={columns} + isRowSelectable={() => false} + /> + closeModal(ModalState.SAME)} + refetchFunds={refetchFunds} + fund={fund} + orgId={orgId} + mode={fundModalMode} + /> + + closeModal(ModalState.DELETE)} + fund={fund} + refetchFunds={refetchFunds} + /> +
    ); }; diff --git a/src/screens/OrganizationFunds/OrganizationFundsMocks.ts b/src/screens/OrganizationFunds/OrganizationFundsMocks.ts index cb1e07d78f..cd03dc7f31 100644 --- a/src/screens/OrganizationFunds/OrganizationFundsMocks.ts +++ b/src/screens/OrganizationFunds/OrganizationFundsMocks.ts @@ -10,21 +10,23 @@ export const MOCKS = [ request: { query: FUND_LIST, variables: { - id: undefined, + organizationId: 'orgId', + orderBy: 'createdAt_DESC', + filter: '', }, }, result: { data: { fundsByOrganization: [ { - _id: '1', + _id: 'fundId', name: 'Fund 1', - refrenceNumber: '123', + refrenceNumber: '1111', taxDeductible: true, isArchived: false, isDefault: false, - createdAt: '2021-07-01T00:00:00.000Z', - organizationId: 'organizationId1', + createdAt: '2024-06-22', + organizationId: 'orgId', creator: { _id: 'creatorId1', firstName: 'John', @@ -32,14 +34,14 @@ export const MOCKS = [ }, }, { - _id: '99', - name: 'Funndds', - refrenceNumber: '1234', + _id: 'fundId2', + name: 'Fund 2', + refrenceNumber: '2222', taxDeductible: true, isArchived: true, isDefault: false, - createdAt: '2021-07-01T00:00:00.000Z', - organizationId: 'organizationId1', + createdAt: '2024-06-21', + organizationId: 'orgId', creator: { _id: 'creatorId1', firstName: 'John', @@ -50,108 +52,27 @@ export const MOCKS = [ }, }, }, - { - request: { - query: CREATE_FUND_MUTATION, - variables: { - name: 'Test Fund', - refrenceNumber: '1', - taxDeductible: true, - isArchived: false, - isDefault: false, - organizationId: undefined, - }, - }, - result: { - data: { - createFund: { - _id: '3', - }, - }, - }, - }, - { - request: { - query: UPDATE_FUND_MUTATION, - variables: { - id: '1', - name: 'Test Fund', - refrenceNumber: '1', - taxDeductible: false, - isArchived: true, - isDefault: true, - }, - }, - result: { - data: { - updateFund: { - _id: '1', - }, - }, - }, - }, - { - request: { - query: REMOVE_FUND_MUTATION, - variables: { - id: '1', - }, - }, - result: { - data: { - removeFund: { - _id: '1', - }, - }, - }, - }, -]; -export const NO_FUNDS = [ - { - request: { - query: FUND_LIST, - variables: { - id: undefined, - }, - }, - result: { - data: { - fundsByOrganization: [], - }, - }, - }, -]; -export const MOCKS_ERROR_ORGANIZATIONS_FUNDS = [ - { - request: { - query: FUND_LIST, - variables: { - organizationId: '1', - }, - }, - error: new Error('Mock graphql error'), - }, -]; -export const MOCKS_ERROR_CREATE_FUND = [ { request: { query: FUND_LIST, variables: { - id: undefined, + organizationId: 'orgId', + orderBy: 'createdAt_ASC', + filter: '', }, }, result: { data: { fundsByOrganization: [ { - _id: '1', - name: 'Fund 1', - refrenceNumber: '123', + _id: 'fundId', + name: 'Fund 2', + refrenceNumber: '2222', taxDeductible: true, - isArchived: false, + isArchived: true, isDefault: false, - createdAt: '2021-07-01T00:00:00.000Z', - organizationId: 'organizationId1', + createdAt: '2024-06-21', + organizationId: 'orgId', creator: { _id: 'creatorId1', firstName: 'John', @@ -159,17 +80,17 @@ export const MOCKS_ERROR_CREATE_FUND = [ }, }, { - _id: '2', - name: 'Fund 2', - refrenceNumber: '456', - taxDeductible: false, + _id: 'fundId2', + name: 'Fund 1', + refrenceNumber: '1111', + taxDeductible: true, isArchived: false, isDefault: false, - createdAt: '2021-07-01T00:00:00.000Z', - organizationId: 'organizationId2', + createdAt: '2024-06-22', + organizationId: 'orgId', creator: { - _id: 'creatorId2', - firstName: 'Jane', + _id: 'creatorId1', + firstName: 'John', lastName: 'Doe', }, }, @@ -177,62 +98,33 @@ export const MOCKS_ERROR_CREATE_FUND = [ }, }, }, - { - request: { - query: CREATE_FUND_MUTATION, - variables: { - name: 'Fund 3', - refrenceNumber: '789', - taxDeductible: true, - isArchived: false, - isDefault: false, - organizationId: undefined, - }, - }, - error: new Error('Mock graphql error'), - }, -]; -export const MOCKS_ERROR_UPDATE_FUND = [ { request: { query: FUND_LIST, variables: { - id: undefined, + organizationId: 'orgId', + orderBy: 'createdAt_DESC', + filter: '2', }, }, result: { data: { fundsByOrganization: [ { - _id: '1', - name: 'Fund 1', - refrenceNumber: '123', + _id: 'fundId', + name: 'Fund 2', + refrenceNumber: '2222', taxDeductible: true, - isArchived: false, + isArchived: true, isDefault: false, - createdAt: '2021-07-01T00:00:00.000Z', - organizationId: 'organizationId1', + createdAt: '2024-06-21', + organizationId: 'orgId', creator: { _id: 'creatorId1', firstName: 'John', lastName: 'Doe', }, }, - { - _id: '2', - name: 'Fund 2', - refrenceNumber: '456', - taxDeductible: false, - isArchived: false, - isDefault: false, - createdAt: '2021-07-01T00:00:00.000Z', - organizationId: 'organizationId2', - creator: { - _id: 'creatorId2', - firstName: 'Jane', - lastName: 'Doe', - }, - }, ], }, }, @@ -241,18 +133,18 @@ export const MOCKS_ERROR_UPDATE_FUND = [ request: { query: CREATE_FUND_MUTATION, variables: { - name: 'Fund 3', - refrenceNumber: '789', - taxDeductible: true, + name: 'Fund 2', + refrenceNumber: '2222', + taxDeductible: false, isArchived: false, - isDefault: false, - organizationId: undefined, + isDefault: true, + organizationId: 'orgId', }, }, result: { data: { createFund: { - _id: '3', + _id: '2222', }, }, }, @@ -261,106 +153,102 @@ export const MOCKS_ERROR_UPDATE_FUND = [ request: { query: UPDATE_FUND_MUTATION, variables: { - id: undefined, - name: 'Fund 1', - refrenceNumber: '789', - taxDeductible: true, - isArchived: false, - isDefault: false, + id: 'fundId', + name: 'Fund 2', + refrenceNumber: '2222', + taxDeductible: false, + isArchived: true, + isDefault: true, + }, + }, + result: { + data: { + updateFund: { + _id: 'fundId', + }, }, }, - error: new Error('Mock graphql error'), }, -]; -export const MOCKS_ERROR_REMOVE_FUND = [ { request: { - query: FUND_LIST, + query: REMOVE_FUND_MUTATION, variables: { - id: undefined, + id: 'fundId', }, }, result: { data: { - fundsByOrganization: [ - { - _id: '3', - name: 'Fund 1', - refrenceNumber: '123', - taxDeductible: true, - isArchived: false, - isDefault: false, - createdAt: '2021-07-01T00:00:00.000Z', - organizationId: 'organizationId1', - creator: { - _id: 'creatorId1', - firstName: 'John', - lastName: 'Doe', - }, - }, - { - _id: '2', - name: 'Fund 2', - refrenceNumber: '456', - taxDeductible: false, - isArchived: false, - isDefault: false, - createdAt: '2021-07-01T00:00:00.000Z', - organizationId: 'organizationId2', - creator: { - _id: 'creatorId2', - firstName: 'Jane', - lastName: 'Doe', - }, - }, - ], + removeFund: { + _id: 'fundId', + }, }, }, }, +]; + +export const NO_FUNDS = [ { request: { - query: CREATE_FUND_MUTATION, + query: FUND_LIST, variables: { - name: 'Fund 3', - refrenceNumber: '789', - taxDeductible: true, - isArchived: false, - isDefault: false, - organizationId: undefined, + organizationId: 'orgId', + orderBy: 'createdAt_DESC', + filter: '', }, }, result: { data: { - createFund: { - _id: '3', - }, + fundsByOrganization: [], }, }, }, +]; + +export const MOCKS_ERROR = [ { request: { - query: UPDATE_FUND_MUTATION, + query: FUND_LIST, variables: { - id: undefined, - name: 'Fund 1', - taxDeductible: true, - isArchived: false, - isDefault: false, + organizationId: 'orgId', + orderBy: 'createdAt_DESC', + filter: '', }, }, - result: { - data: { - updateFund: { - _id: '1', - }, + error: new Error('Mock graphql error'), + }, + { + request: { + query: CREATE_FUND_MUTATION, + variables: { + name: 'Fund 2', + refrenceNumber: '2222', + taxDeductible: false, + isArchived: false, + isDefault: true, + organizationId: 'orgId', }, }, + error: new Error('Mock graphql error'), }, { request: { query: REMOVE_FUND_MUTATION, variables: { - id: undefined, + id: 'fundId', + }, + }, + error: new Error('Mock graphql error'), + }, + { + request: { + query: UPDATE_FUND_MUTATION, + variables: { + id: 'fundId', + name: 'Fund 2', + refrenceNumber: '2222', + taxDeductible: false, + isArchived: true, + isDefault: true, }, }, error: new Error('Mock graphql error'), diff --git a/src/screens/OrganizationPeople/AddMember.tsx b/src/screens/OrganizationPeople/AddMember.tsx index 696436c2bc..9737ef5c50 100644 --- a/src/screens/OrganizationPeople/AddMember.tsx +++ b/src/screens/OrganizationPeople/AddMember.tsx @@ -57,6 +57,8 @@ function AddMember(): JSX.Element { keyPrefix: 'addMember', }); + const { t: tCommon } = useTranslation('common'); + document.title = translateOrgPeople('title'); const [addUserModalisOpen, setAddUserModalIsOpen] = useState(false); @@ -90,7 +92,7 @@ function AddMember(): JSX.Element { orgid: currentUrl, }, }); - toast.success('Member added to the organization.'); + toast.success(tCommon('addedSuccessfully', { item: 'Member' })); memberRefetch({ orgId: currentUrl, }); @@ -382,7 +384,7 @@ function AddMember(): JSX.Element { {userDetails.user.firstName + diff --git a/src/screens/OrganizationPeople/OrganizationPeople.tsx b/src/screens/OrganizationPeople/OrganizationPeople.tsx index 227a645292..24b8f0a2ad 100644 --- a/src/screens/OrganizationPeople/OrganizationPeople.tsx +++ b/src/screens/OrganizationPeople/OrganizationPeople.tsx @@ -172,7 +172,7 @@ function organizationPeople(): JSX.Element { const columns: GridColDef[] = [ { field: 'profile', - headerName: 'Profile', + headerName: tCommon('profile'), flex: 1, minWidth: 50, align: 'center', @@ -196,7 +196,7 @@ function organizationPeople(): JSX.Element { }, { field: 'name', - headerName: 'Name', + headerName: tCommon('name'), flex: 2, minWidth: 150, align: 'center', @@ -217,7 +217,7 @@ function organizationPeople(): JSX.Element { }, { field: 'email', - headerName: 'Email', + headerName: tCommon('email'), minWidth: 150, align: 'center', headerAlign: 'center', @@ -227,7 +227,7 @@ function organizationPeople(): JSX.Element { }, { field: 'joined', - headerName: 'Joined', + headerName: tCommon('joined'), flex: 2, minWidth: 100, align: 'center', @@ -240,7 +240,7 @@ function organizationPeople(): JSX.Element { }, { field: 'action', - headerName: 'Action', + headerName: tCommon('action'), flex: 1, minWidth: 100, align: 'center', @@ -253,14 +253,14 @@ function organizationPeople(): JSX.Element { onClick={() => toggleRemoveAdminModal(params.row._id)} data-testid="removeAdminModalBtn" > - Remove + {tCommon('remove')} ) : ( ); }, @@ -362,12 +362,12 @@ function organizationPeople(): JSX.Element {
    } + /> + + + + + , + ); + + await waitFor(() => { + expect(screen.getByTestId('paramsError')).toBeInTheDocument(); + }); + }); + + it('should render Upcoming Events screen', async () => { + renderUpcomingEvents(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + }); + + it('Search by event title', async () => { + renderUpcomingEvents(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + const searchToggle = await screen.findByTestId('searchByToggle'); + expect(searchToggle).toBeInTheDocument(); + userEvent.click(searchToggle); + + const searchByTitle = await screen.findByTestId('title'); + expect(searchByTitle).toBeInTheDocument(); + userEvent.click(searchByTitle); + + userEvent.type(searchInput, '1'); + await debounceWait(); + + const eventTitle = await screen.findAllByTestId('eventTitle'); + expect(eventTitle[0]).toHaveTextContent('Event 1'); + }); + + it('Search by event location on click of search button', async () => { + renderUpcomingEvents(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + const searchToggle = await screen.findByTestId('searchByToggle'); + expect(searchToggle).toBeInTheDocument(); + userEvent.click(searchToggle); + + const searchByLocation = await screen.findByTestId('location'); + expect(searchByLocation).toBeInTheDocument(); + userEvent.click(searchByLocation); + + // Search by name on press of ENTER + userEvent.type(searchInput, 'M'); + await debounceWait(); + + const eventTitle = await screen.findAllByTestId('eventTitle'); + expect(eventTitle[0]).toHaveTextContent('Event 1'); + }); + + it('should render screen with No Events', async () => { + renderUpcomingEvents(link3); + + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + expect(screen.getByText(t.noEvents)).toBeInTheDocument(); + }); + }); + + it('Error while fetching Events data', async () => { + renderUpcomingEvents(link2); + + await waitFor(() => { + expect(screen.getByTestId('errorMsg')).toBeInTheDocument(); + }); + }); + + it('Click on Individual volunteer button', async () => { + renderUpcomingEvents(link1); + + const volunteerBtn = await screen.findAllByTestId('volunteerBtn'); + userEvent.click(volunteerBtn[0]); + + await waitFor(() => { + expect(toast.success).toHaveBeenCalledWith(t.volunteerSuccess); + }); + }); + + it('Join Volunteer Group', async () => { + renderUpcomingEvents(link1); + + const eventTitle = await screen.findAllByTestId('eventTitle'); + expect(eventTitle[0]).toHaveTextContent('Event 1'); + userEvent.click(eventTitle[0]); + + const joinGroupBtn = await screen.findAllByTestId('joinBtn'); + expect(joinGroupBtn).toHaveLength(3); + userEvent.click(joinGroupBtn[0]); + + await waitFor(() => { + expect(toast.success).toHaveBeenCalledWith(t.volunteerSuccess); + }); + }); + + it('Error on Create Volunteer Membership', async () => { + renderUpcomingEvents(link4); + + const volunteerBtn = await screen.findAllByTestId('volunteerBtn'); + userEvent.click(volunteerBtn[0]); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.tsx b/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.tsx new file mode 100644 index 0000000000..bd61ca97e0 --- /dev/null +++ b/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.tsx @@ -0,0 +1,377 @@ +import React, { useMemo, useState } from 'react'; +import { Dropdown, Form, Button } from 'react-bootstrap'; +import styles from '../VolunteerManagement.module.css'; +import { useTranslation } from 'react-i18next'; +import { Navigate, useParams } from 'react-router-dom'; +import { IoLocationOutline } from 'react-icons/io5'; +import { + Paper, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + Accordion, + AccordionDetails, + AccordionSummary, + Chip, + Stack, + debounce, +} from '@mui/material'; +import { Circle, Search, Sort, WarningAmberRounded } from '@mui/icons-material'; + +import { GridExpandMoreIcon } from '@mui/x-data-grid'; +import useLocalStorage from 'utils/useLocalstorage'; +import { useMutation, useQuery } from '@apollo/client'; +import type { InterfaceUserEvents } from 'utils/interfaces'; +import { IoIosHand } from 'react-icons/io'; +import Loader from 'components/Loader/Loader'; +import { USER_EVENTS_VOLUNTEER } from 'GraphQl/Queries/PlugInQueries'; +import { CREATE_VOLUNTEER_MEMBERSHIP } from 'GraphQl/Mutations/EventVolunteerMutation'; +import { toast } from 'react-toastify'; +import { FaCheck } from 'react-icons/fa'; + +/** + * The `UpcomingEvents` component displays list of upcoming events for the user to volunteer. + * It allows the user to search, sort, and volunteer for events/volunteer groups. + * + * @returns The rendered component displaying the upcoming events. + */ +const UpcomingEvents = (): JSX.Element => { + // Retrieves translation functions for various namespaces + const { t } = useTranslation('translation', { + keyPrefix: 'userVolunteer', + }); + const { t: tCommon } = useTranslation('common'); + const { t: tErrors } = useTranslation('errors'); + + // Retrieves stored user ID from local storage + const { getItem } = useLocalStorage(); + const userId = getItem('userId'); + + // Extracts organization ID from the URL parameters + const { orgId } = useParams(); + if (!orgId || !userId) { + // Redirects to the homepage if orgId or userId is missing + return ; + } + const [searchValue, setSearchValue] = useState(''); + const [searchTerm, setSearchTerm] = useState(''); + const [searchBy, setSearchBy] = useState<'title' | 'location'>('title'); + + const [createVolunteerMembership] = useMutation(CREATE_VOLUNTEER_MEMBERSHIP); + + const debouncedSearch = useMemo( + () => debounce((value: string) => setSearchTerm(value), 300), + [], + ); + + const handleVolunteer = async ( + eventId: string, + group: string | null, + status: string, + ): Promise => { + try { + await createVolunteerMembership({ + variables: { + data: { + event: eventId, + group, + status, + userId, + }, + }, + }); + toast.success(t('volunteerSuccess')); + refetchEvents(); + } catch (error) { + toast.error((error as Error).message); + } + }; + + // Fetches upcomin events based on the organization ID, search term, and sorting order + const { + data: eventsData, + loading: eventsLoading, + error: eventsError, + refetch: refetchEvents, + }: { + data?: { + eventsByOrganizationConnection: InterfaceUserEvents[]; + }; + loading: boolean; + error?: Error | undefined; + refetch: () => void; + } = useQuery(USER_EVENTS_VOLUNTEER, { + variables: { + organization_id: orgId, + title_contains: searchBy === 'title' ? searchTerm : '', + location_contains: searchBy === 'location' ? searchTerm : '', + upcomingOnly: true, + first: null, + skip: null, + }, + }); + + // Extracts the list of upcoming events from the fetched data + const events = useMemo(() => { + if (eventsData) { + return eventsData.eventsByOrganizationConnection; + } + return []; + }, [eventsData]); + + // Renders a loader while events are being fetched + if (eventsLoading) return ; + if (eventsError) { + // Displays an error message if there is an issue loading the events + return ( +
    +
    + +
    + {tErrors('errorLoading', { entity: 'Events' })} +
    +
    +
    + ); + } + + // Renders the upcoming events list and UI elements for searching, sorting, and adding pledges + return ( + <> +
    + {/* Search input field and button */} +
    + { + setSearchValue(e.target.value); + debouncedSearch(e.target.value); + }} + data-testid="searchBy" + /> + +
    +
    +
    + + + + {tCommon('searchBy', { item: '' })} + + + setSearchBy('title')} + data-testid="title" + > + {t('name')} + + setSearchBy('location')} + data-testid="location" + > + {tCommon('location')} + + + +
    +
    +
    + {events.length < 1 ? ( + + {/* Displayed if no events are found */} + {t('noEvents')} + + ) : ( + events.map((event: InterfaceUserEvents, index: number) => { + const { + title, + description, + startDate, + endDate, + location, + volunteerGroups, + recurring, + _id, + volunteers, + } = event; + const isVolunteered = volunteers.some( + (volunteer) => volunteer.user._id === userId, + ); + return ( + + }> +
    +
    +
    +

    {title}

    + {recurring && ( + } + label={t('recurring')} + variant="outlined" + color="primary" + className={`${styles.chip} ${styles.active}`} + /> + )} +
    + +
    + + {' '} + + location: {location} + + Start Date: {startDate as unknown as string} + End Date: {endDate as unknown as string} +
    +
    +
    + +
    +
    +
    + + { + /*istanbul ignore next*/ + description && ( +
    + Description: + {description} +
    + ) + } + {volunteerGroups && volunteerGroups.length > 0 && ( + + + Volunteer Groups: + + + + + + + Sr. No. + + Group Name + + + No. of Members + + + Options + + + + + {volunteerGroups.map((group, index) => { + const { _id: gId, name, volunteers } = group; + const hasJoined = volunteers.some( + (volunteer) => volunteer._id === userId, + ); + return ( + + + {index + 1} + + + {name} + + + {volunteers.length} + + + + + + ); + })} + +
    +
    +
    + )} +
    +
    + ); + }) + )} + + ); +}; + +export default UpcomingEvents; diff --git a/src/screens/UserPortal/Volunteer/VolunteerManagement.module.css b/src/screens/UserPortal/Volunteer/VolunteerManagement.module.css new file mode 100644 index 0000000000..d3b2bbaa54 --- /dev/null +++ b/src/screens/UserPortal/Volunteer/VolunteerManagement.module.css @@ -0,0 +1,138 @@ +/* Upcoming Events Styles */ +.btnsContainer { + display: flex; + margin: 1.5rem 0; +} + +.btnsContainer .input { + flex: 1; + min-width: 18rem; + position: relative; +} + +.btnsContainer input { + outline: 1px solid var(--bs-gray-400); + background-color: white; +} + +.btnsContainer .input button { + width: 52px; +} + +.accordionSummary { + width: 100% !important; + padding-right: 0.75rem; + display: flex; + justify-content: space-between !important; + align-items: center; +} + +.accordionSummary button { + height: 2.25rem; + padding-top: 0.35rem; +} + +.accordionSummary button:hover { + background-color: #31bb6a50 !important; + color: #31bb6b !important; +} + +.titleContainer { + display: flex; + flex-direction: column; + gap: 0.1rem; +} + +.titleContainer h3 { + font-size: 1.25rem; + font-weight: 750; + color: #5e5e5e; + margin-top: 0.2rem; +} + +.subContainer span { + font-size: 0.9rem; + margin-left: 0.5rem; + font-weight: lighter; + color: #707070; +} + +.chipIcon { + height: 0.9rem !important; +} + +.chip { + height: 1.5rem !important; + margin: 0.15rem 0 0 1.25rem; +} + +.active { + background-color: #31bb6a50 !important; +} + +.pending { + background-color: #ffd76950 !important; + color: #bb952bd0 !important; + border-color: #bb952bd0 !important; +} + +.progress { + display: flex; + width: 45rem; +} + +.progressBar { + margin: 0rem 0.75rem; + width: 100%; + font-size: 0.9rem; + height: 1.25rem; +} + +/* Pledge Modal */ + +.pledgeModal { + max-width: 80vw; + margin-top: 2vh; + margin-left: 13vw; +} + +.titlemodal { + color: #707070; + font-weight: 600; + font-size: 32px; + width: 65%; + margin-bottom: 0px; +} + +.modalCloseBtn { + width: 40px; + height: 40px; + padding: 1rem; + display: flex; + justify-content: center; + align-items: center; +} + +.noOutline input { + outline: none; +} + +.greenregbtn { + margin: 1rem 0 0; + margin-top: 15px; + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + padding: 10px 10px; + border-radius: 5px; + background-color: #31bb6b; + width: 100%; + font-size: 16px; + color: white; + outline: none; + font-weight: 600; + cursor: pointer; + transition: + transform 0.2s, + box-shadow 0.2s; + width: 100%; +} diff --git a/src/screens/UserPortal/Volunteer/VolunteerManagement.test.tsx b/src/screens/UserPortal/Volunteer/VolunteerManagement.test.tsx new file mode 100644 index 0000000000..65d2d082a7 --- /dev/null +++ b/src/screens/UserPortal/Volunteer/VolunteerManagement.test.tsx @@ -0,0 +1,128 @@ +import React from 'react'; +import type { RenderResult } from '@testing-library/react'; +import { render, screen, waitFor } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider } from 'react-i18next'; +import i18n from 'utils/i18nForTest'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import VolunteerManagement from './VolunteerManagement'; +import userEvent from '@testing-library/user-event'; +import { MOCKS } from './UpcomingEvents/UpcomingEvents.mocks'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import useLocalStorage from 'utils/useLocalstorage'; +const { setItem } = useLocalStorage(); + +const link1 = new StaticMockLink(MOCKS); + +const renderVolunteerManagement = (): RenderResult => { + return render( + + + + + + } + /> + } /> + } + /> + + + + + , + ); +}; + +describe('Volunteer Management', () => { + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId' }), + })); + }); + + beforeEach(() => { + setItem('userId', 'userId'); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('should redirect to fallback URL if URL params are undefined', async () => { + render( + + + + + + } + /> + } + /> + + + + + , + ); + + await waitFor(() => { + expect(screen.getByTestId('paramsError')).toBeInTheDocument(); + }); + }); + + test('Render Volunteer Management Screen', async () => { + renderVolunteerManagement(); + + const upcomingEventsTab = await screen.findByTestId('upcomingEventsTab'); + expect(upcomingEventsTab).toBeInTheDocument(); + expect(screen.getByTestId('invitationsBtn')).toBeInTheDocument(); + expect(screen.getByTestId('actionsBtn')).toBeInTheDocument(); + expect(screen.getByTestId('groupsBtn')).toBeInTheDocument(); + }); + + test('Testing back button navigation', async () => { + renderVolunteerManagement(); + + const backButton = await screen.findByTestId('backBtn'); + userEvent.click(backButton); + await waitFor(() => { + const orgHome = screen.getByTestId('orgHome'); + expect(orgHome).toBeInTheDocument(); + }); + }); + + test('Testing volunteer management tab switching', async () => { + renderVolunteerManagement(); + + const invitationsBtn = screen.getByTestId('invitationsBtn'); + userEvent.click(invitationsBtn); + + const invitationsTab = screen.getByTestId('invitationsTab'); + expect(invitationsTab).toBeInTheDocument(); + + const actionsBtn = screen.getByTestId('actionsBtn'); + userEvent.click(actionsBtn); + + const actionsTab = screen.getByTestId('actionsTab'); + expect(actionsTab).toBeInTheDocument(); + + const groupsBtn = screen.getByTestId('groupsBtn'); + userEvent.click(groupsBtn); + + const groupsTab = screen.getByTestId('groupsTab'); + expect(groupsTab).toBeInTheDocument(); + }); +}); diff --git a/src/screens/UserPortal/Volunteer/VolunteerManagement.tsx b/src/screens/UserPortal/Volunteer/VolunteerManagement.tsx new file mode 100644 index 0000000000..87be9d7adc --- /dev/null +++ b/src/screens/UserPortal/Volunteer/VolunteerManagement.tsx @@ -0,0 +1,211 @@ +import React, { useState } from 'react'; +import Row from 'react-bootstrap/Row'; +import Col from 'react-bootstrap/Col'; +import { Navigate, useNavigate, useParams } from 'react-router-dom'; +import { FaChevronLeft, FaTasks } from 'react-icons/fa'; +import { useTranslation } from 'react-i18next'; +import { Button, Dropdown } from 'react-bootstrap'; +import { TbCalendarEvent } from 'react-icons/tb'; +import { FaRegEnvelopeOpen, FaUserGroup } from 'react-icons/fa6'; +import UpcomingEvents from './UpcomingEvents/UpcomingEvents'; +import Invitations from './Invitations/Invitations'; +import Actions from './Actions/Actions'; +import Groups from './Groups/Groups'; + +/** + * List of tabs for the volunteer dashboard. + * + * Each tab is associated with an icon and value. + */ +const volunteerDashboardTabs: { + value: TabOptions; + icon: JSX.Element; +}[] = [ + { + value: 'upcomingEvents', + icon: , + }, + { + value: 'invitations', + icon: , + }, + { + value: 'actions', + icon: , + }, + { + value: 'groups', + icon: , + }, +]; + +/** + * Tab options for the volunteer management component. + */ +type TabOptions = 'upcomingEvents' | 'invitations' | 'actions' | 'groups'; + +/** + * `VolunteerManagement` component handles the display and navigation of different event management sections. + * + * It provides a tabbed interface for: + * - Viewing upcoming events to volunteer + * - Managing volunteer requests + * - Managing volunteer invitations + * - Managing volunteer groups + * + * @returns JSX.Element - The `VolunteerManagement` component. + */ +const VolunteerManagement = (): JSX.Element => { + // Translation hook for internationalization + const { t } = useTranslation('translation', { + keyPrefix: 'userVolunteer', + }); + + // Extract organization ID from URL parameters + const { orgId } = useParams(); + + if (!orgId) { + return ; + } + + // Hook for navigation + const navigate = useNavigate(); + + // State hook for managing the currently selected tab + const [tab, setTab] = useState('upcomingEvents'); + + /** + * Renders a button for each tab with the appropriate icon and label. + * + * @param value - The tab value + * @param icon - The icon to display for the tab + * @returns JSX.Element - The rendered button component + */ + const renderButton = ({ + value, + icon, + }: { + value: TabOptions; + icon: React.ReactNode; + }): JSX.Element => { + const selected = tab === value; + const variant = selected ? 'success' : 'light'; + const translatedText = t(value); + + const className = selected + ? 'px-4 d-flex align-items-center rounded-3 shadow-sm' + : 'text-secondary bg-white px-4 d-flex align-items-center rounded-3 shadow-sm'; + const props = { + variant, + className, + style: { height: '2.5rem' }, + onClick: () => setTab(value), + 'data-testid': `${value}Btn`, + }; + + return ( + + ); + }; + + const handleBack = (): void => { + navigate(`/user/organization/${orgId}`); + }; + + return ( +
    + + +
    + + {volunteerDashboardTabs.map(renderButton)} +
    + + + + {t(tab)} + + + {/* Render dropdown items for each settings category */} + {volunteerDashboardTabs.map(({ value, icon }, index) => ( + setTab(value) + } + className={`d-flex gap-2 ${tab === value && 'text-secondary'}`} + > + {icon} {t(value)} + + ))} + + + + + +
    +
    +
    + + {/* Render content based on the selected settings category */} + {(() => { + switch (tab) { + case 'upcomingEvents': + return ( +
    + +
    + ); + case 'invitations': + return ( +
    + +
    + ); + case 'actions': + return ( +
    + +
    + ); + case 'groups': + return ( +
    + +
    + ); + } + })()} +
    + ); +}; + +export default VolunteerManagement; diff --git a/src/setup/askForTalawaApiUrl/setupTalawaWebSocketUrl.test.ts b/src/setup/askForTalawaApiUrl/setupTalawaWebSocketUrl.test.ts new file mode 100644 index 0000000000..3fa612bd25 --- /dev/null +++ b/src/setup/askForTalawaApiUrl/setupTalawaWebSocketUrl.test.ts @@ -0,0 +1,38 @@ +import fs from 'fs'; +import inquirer from 'inquirer'; +import { askForTalawaApiUrl } from './askForTalawaApiUrl'; + +jest.mock('fs'); +jest.mock('inquirer', () => ({ + prompt: jest.fn(), +})); + +describe('WebSocket URL Configuration', () => { + beforeEach(() => { + jest.resetAllMocks(); + }); + + test('should convert http URL to ws WebSocket URL', async () => { + const endpoint = 'http://example.com/graphql'; + const websocketUrl = endpoint.replace(/^http(s)?:\/\//, 'ws$1://'); + + expect(websocketUrl).toBe('ws://example.com/graphql'); + }); + + test('should convert https URL to wss WebSocket URL', async () => { + const endpoint = 'https://example.com/graphql'; + const websocketUrl = endpoint.replace(/^http(s)?:\/\//, 'ws$1://'); + + expect(websocketUrl).toBe('wss://example.com/graphql'); + }); + + test('should retain default WebSocket URL if no new endpoint is provided', async () => { + jest + .spyOn(inquirer, 'prompt') + .mockResolvedValueOnce({ endpoint: 'http://localhost:4000/graphql/' }); + await askForTalawaApiUrl(); + + const writeFileSyncSpy = jest.spyOn(fs, 'writeFileSync'); + expect(writeFileSyncSpy).not.toHaveBeenCalled(); + }); +}); diff --git a/src/state/reducers/userRoutersReducer.test.ts b/src/state/reducers/userRoutersReducer.test.ts index 98c4a78464..e2987dcd38 100644 --- a/src/state/reducers/userRoutersReducer.test.ts +++ b/src/state/reducers/userRoutersReducer.test.ts @@ -14,6 +14,7 @@ describe('Testing Routes reducer', () => { { name: 'Posts', url: 'user/organization/undefined' }, { name: 'People', url: 'user/people/undefined' }, { name: 'Events', url: 'user/events/undefined' }, + { name: 'Volunteer', url: 'user/volunteer/undefined' }, { name: 'Donate', url: 'user/donate/undefined' }, { name: 'Campaigns', url: 'user/campaigns/undefined' }, { name: 'My Pledges', url: 'user/pledges/undefined' }, @@ -31,6 +32,11 @@ describe('Testing Routes reducer', () => { }, { name: 'People', comp_id: 'people', component: 'People' }, { name: 'Events', comp_id: 'events', component: 'Events' }, + { + name: 'Volunteer', + comp_id: 'volunteer', + component: 'VolunteerManagement', + }, { name: 'Donate', comp_id: 'donate', component: 'Donate' }, { name: 'Campaigns', @@ -54,6 +60,7 @@ describe('Testing Routes reducer', () => { { name: 'Posts', url: 'user/organization/orgId' }, { name: 'People', url: 'user/people/orgId' }, { name: 'Events', url: 'user/events/orgId' }, + { name: 'Volunteer', url: 'user/volunteer/orgId' }, { name: 'Donate', url: 'user/donate/orgId' }, { name: 'Campaigns', url: 'user/campaigns/orgId' }, { name: 'My Pledges', url: 'user/pledges/orgId' }, @@ -71,6 +78,11 @@ describe('Testing Routes reducer', () => { }, { name: 'People', comp_id: 'people', component: 'People' }, { name: 'Events', comp_id: 'events', component: 'Events' }, + { + name: 'Volunteer', + comp_id: 'volunteer', + component: 'VolunteerManagement', + }, { name: 'Donate', comp_id: 'donate', component: 'Donate' }, { name: 'Campaigns', diff --git a/src/state/reducers/userRoutesReducer.ts b/src/state/reducers/userRoutesReducer.ts index 44bc91fabb..e1bf5de0dc 100644 --- a/src/state/reducers/userRoutesReducer.ts +++ b/src/state/reducers/userRoutesReducer.ts @@ -55,6 +55,7 @@ const components: ComponentType[] = [ }, { name: 'People', comp_id: 'people', component: 'People' }, { name: 'Events', comp_id: 'events', component: 'Events' }, + { name: 'Volunteer', comp_id: 'volunteer', component: 'VolunteerManagement' }, { name: 'Donate', comp_id: 'donate', component: 'Donate' }, { name: 'Campaigns', diff --git a/src/style/app.module.css b/src/style/app.module.css new file mode 100644 index 0000000000..45449b7bf1 --- /dev/null +++ b/src/style/app.module.css @@ -0,0 +1,507 @@ +:root { + --dropdown-border-color: #555555; + --dropdown-text-color: #555555; + --dropdown-hover-color: #eff1f7; + --grey-bg-color: #eaebef; + --subtle-blue-grey: #7c9beb; + --subtle-blue-grey-hover: #5f7e91; + --modal-width: 670px; + --modal-max-width: 680px; + --input-shadow-color: #dddddd; + --delete-button-bg: #f8d6dc; + --delete-button-color: #ff4d4f; + --search-button-bg: #a8c7fa; + --search-button-border: #555555; + --table-image-size: 50px; + --table-head-bg: var( + --bs-primary, + blue + ); /* Assuming var(--bs-primary) is defined elsewhere */ + --table-head-color: white; + --table-header-color: var(--bs-greyish-black, black); + --table-head-radius: 20px; + --table-bg-color: #eaebef; + --tablerow-bg-color: #eff1f7; + --row-background: var(--bs-white, white); + --font-size-header: 16px; +} + +.noOutline input { + outline: none; +} + +.noOutline:is(:hover, :focus, :active, :focus-visible, .show) { + outline: none !important; +} + +.closeButton { + color: var(--delete-button-color); + margin-right: 5px; + background-color: var(--delete-button-bg); + border: white; +} + +.closeButton:hover { + color: var(--delete-button-bg) !important; + background-color: var(--delete-button-color) !important; + border: white; +} + +.modalContent { + width: var(--modal-width); + max-width: var(--modal-max-width); +} + +.subtleBlueGrey { + color: var(--subtle-blue-grey); + text-decoration: none; +} + +.subtleBlueGrey:hover { + color: var(--subtle-blue-grey-hover); + text-decoration: underline; +} + +.dropdown { + background-color: white; + border: 1px solid var(--dropdown-border-color); + color: var(--dropdown-text-color); + position: relative; + display: inline-block; + margin-top: 10px; + margin-bottom: 10px; +} + +.dropdown:is(:hover, :focus, :active, :focus-visible, .show) { + background-color: transparent !important; + border: 1px solid var(--dropdown-border-color); + color: var(--dropdown-text-color) !important; +} + +.dropdownItem { + background-color: white !important; + color: var(--dropdown-text-color) !important; + border: none !important; +} + +.dropdownItem:hover, +.dropdownItem:focus, +.dropdownItem:active { + background-color: var(--dropdown-hover-color) !important; + color: var(--dropdown-text-color) !important; + outline: none !important; + box-shadow: none !important; +} + +.input { + flex: 1; + + position: relative; +} + +.btnsContainer { + display: flex; + margin: 2.5rem 0; +} + +.btnsContainer .btnsBlock { + display: flex; +} + +.btnsContainer .btnsBlock button { + margin-left: 1rem; + display: flex; + justify-content: center; + align-items: center; +} + +.btnsContainer .input { + flex: 1; + position: relative; +} + +.btnsContainer .input button { + width: 52px; +} + +.deleteButton { + background-color: var(--delete-button-bg); + color: var(--delete-button-color); + border: none; + padding: 5px 20px; + display: flex; + align-items: center; + margin-top: 20px; + margin-right: auto; + margin-left: auto; + gap: 8px; +} + +.actionItemDeleteButton { + background-color: var(--delete-button-bg); + color: var(--delete-button-color); + border: none; +} + +.createButton { + background-color: var(--grey-bg-color) !important; + color: black !important; + margin-top: 10px; + margin-left: 5px; + border: 1px solid var(--dropdown-border-color); +} + +.createButton:hover { + background-color: var(--grey-bg-color) !important; + color: black !important; + border: 1px solid var(--dropdown-border-color) !important; +} + +.visuallyHidden { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} + +.inputField { + margin-top: 10px; + margin-bottom: 10px; + background-color: white; + box-shadow: 0 1px 1px var(--input-shadow-color); +} + +.inputFieldModal { + margin-bottom: 10px; + background-color: white; + box-shadow: 0 1px 1px var(--input-shadow-color); +} + +.inputField > button { + padding-top: 10px; + padding-bottom: 10px; +} + +.searchButton { + margin-bottom: 10px; + background-color: var(--search-button-bg); + border-color: var(--search-button-border); + position: absolute; + z-index: 10; + bottom: 0; + right: 0; + display: flex; + justify-content: center; + align-items: center; +} + +.addButton { + margin-bottom: 10px; + background-color: var(--search-button-bg); + border-color: var(--grey-bg-color); + color: #555555; +} + +.addButton:hover { + background-color: #286fe0; + border-color: var(--search-button-border); +} + +.yesButton { + background-color: var(--search-button-bg); + border-color: var(--search-button-border); +} + +.searchIcon { + color: var(--dropdown-text-color); +} + +.infoButton { + background-color: var(--search-button-bg); + border-color: var(--search-button-border); + color: var(--dropdown-text-color); + margin-right: 0.5rem; + border-radius: 0.25rem; +} + +.infoButton:hover { + background-color: #286fe0; + border-color: var(--search-button-border); +} + +.TableImage { + object-fit: cover; + /* margin-top: px !important; */ + margin-right: 5px; + width: var(--table-image-size) !important; + height: var(--table-image-size) !important; + border-radius: 100% !important; +} + +.tableHead { + color: var(--table-head-color); + border-radius: var(--table-head-radius) !important; + padding: 20px; + margin-top: 20px; +} + +.mainpageright > hr { + margin-top: 10px; + width: 100%; + margin-left: -15px; + margin-right: -15px; + margin-bottom: 20px; +} + +.rowBackground { + background-color: var(--row-background); +} + +.tableHeader { + background-color: var(--table-head-bg); + color: var(--table-header-color); + font-size: var(--font-size-header); +} + +.orgUserTagsScrollableDiv { + scrollbar-width: auto; + scrollbar-color: var(--bs-gray-400) var(--bs-white); + + max-height: calc(100vh - 18rem); + overflow: auto; + position: sticky; +} + +.errorContainer { + min-height: 100vh; +} + +.errorMessage { + margin-top: 25%; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; +} + +.errorIcon { + transform: scale(1.5); + color: var(--bs-danger); + margin-bottom: 1rem; +} + +.subTagsLink { + color: var(--subtle-blue-grey); + font-weight: 500; + cursor: pointer; +} + +.subTagsLink i { + visibility: hidden; +} + +.subTagsLink:hover { + color: var(--subtle-blue-grey-hover); + font-weight: 600; + text-decoration: underline; +} + +.subTagsLink:hover i { + visibility: visible; +} + +.tagsBreadCrumbs { + color: var(--bs-gray); + cursor: pointer; +} + +.orgUserTagsScrollableDiv { + scrollbar-width: auto; + scrollbar-color: var(--bs-gray-400) var(--bs-white); + + max-height: calc(100vh - 18rem); + overflow: auto; + position: sticky; +} + +/* .checkboxButton{ + background-color: transparent; +} + +.checkboxButton:checked{ + background-color: var(--subtle-blue-grey); + color:white +} */ + +input[type='checkbox']:checked + label { + background-color: var(--subtle-blue-grey) !important; +} + +input[type='radio']:checked + label:hover { + color: black !important; +} + +.actionItemsContainer { + height: 90vh; +} + +.actionItemModal { + max-width: 80vw; + margin-top: 2vh; + margin-left: 13vw; +} + +.datediv { + display: flex; + flex-direction: row; +} + +.datebox { + width: 90%; + border-radius: 7px; + outline: none; + box-shadow: none; + padding-top: 2px; + padding-bottom: 2px; + padding-right: 5px; + padding-left: 5px; + margin-right: 5px; + margin-left: 5px; +} + +hr { + border: none; + height: 1px; + background-color: var(--bs-gray-500); + margin: 1rem; +} + +.iconContainer { + display: flex; + justify-content: flex-end; +} +.icon { + margin: 1px; +} + +.message { + margin-top: 25%; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; +} + +.preview { + display: flex; + flex-direction: row; + font-weight: 900; + font-size: 16px; + color: rgb(80, 80, 80); +} + +.rankings { + aspect-ratio: 1; + border-radius: 50%; + width: 50px; +} + +.toggleGroup { + width: 50%; + min-width: 20rem; + margin: 0.5rem 0rem; +} + +.toggleBtn { + padding: 0rem; + height: 2rem; + display: flex; + justify-content: center; + align-items: center; +} + +.toggleBtn:hover { + color: var(--bs-primary) !important; +} + +@media (max-width: 520px) { + .btnsContainer { + margin-bottom: 0; + } + + .btnsContainer .btnsBlock { + display: block; + margin-top: 1rem; + margin-right: 0; + } + + .btnsContainer .btnsBlock div { + flex: 1; + } + + .btnsContainer .btnsBlock div[title='Sort organizations'] { + margin-right: 0.5rem; + } + + .btnsContainer .btnsBlock button { + margin-bottom: 1rem; + margin-right: 0; + width: 100%; + } +} + +@media (max-width: 1120px) { + .contract { + padding-left: calc(250px + 2rem + 1.5rem); + } + + .listBox .itemCard { + width: 100%; + } +} + +@media (max-width: 1020px) { + .btnsContainer { + flex-direction: column; + margin: 1.5rem 0; + } + + .btnsContainer .btnsBlock { + margin: 1.5rem 0 0 0; + justify-content: space-between; + } + + .btnsContainer .btnsBlock button { + margin: 0; + } + + .btnsContainer .btnsBlock div button { + margin-right: 1.5rem; + } +} + +@-webkit-keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} diff --git a/src/utils/chartToPdf.test.ts b/src/utils/chartToPdf.test.ts new file mode 100644 index 0000000000..b3094fff02 --- /dev/null +++ b/src/utils/chartToPdf.test.ts @@ -0,0 +1,168 @@ +import { + exportToCSV, + exportTrendsToCSV, + exportDemographicsToCSV, +} from './chartToPdf'; + +describe('CSV Export Functions', () => { + let mockCreateElement: jest.SpyInstance; + let mockClick: jest.SpyInstance; + let mockSetAttribute: jest.SpyInstance; + + beforeEach(() => { + // Mock URL methods + global.URL.createObjectURL = jest.fn(() => 'mock-url'); + global.URL.revokeObjectURL = jest.fn(); + + // Mock DOM methods + mockSetAttribute = jest.fn(); + mockClick = jest.fn(); + const mockLink = { + setAttribute: mockSetAttribute, + click: mockClick, + } as unknown as HTMLAnchorElement; + + mockCreateElement = jest + .spyOn(document, 'createElement') + .mockReturnValue(mockLink as HTMLAnchorElement); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + describe('CSV Export Functions', () => { + let mockCreateElement: jest.SpyInstance; + let mockAppendChild: jest.SpyInstance; + let mockRemoveChild: jest.SpyInstance; + let mockClick: jest.SpyInstance; + let mockSetAttribute: jest.SpyInstance; + + beforeEach(() => { + // Mock URL methods + global.URL.createObjectURL = jest.fn(() => 'mock-url'); + global.URL.revokeObjectURL = jest.fn(); + + // Mock DOM methods + mockSetAttribute = jest.fn(); + mockClick = jest.fn(); + const mockLink = { + setAttribute: mockSetAttribute, + click: mockClick, + parentNode: document.body, // Add this to trigger removeChild + } as unknown as HTMLAnchorElement; + + mockCreateElement = jest + .spyOn(document, 'createElement') + .mockReturnValue(mockLink as HTMLAnchorElement); + mockAppendChild = jest + .spyOn(document.body, 'appendChild') + .mockImplementation(() => mockLink as HTMLAnchorElement); + mockRemoveChild = jest + .spyOn(document.body, 'removeChild') + .mockImplementation(() => mockLink as HTMLAnchorElement); + }); + + test('exports data to CSV with proper formatting', () => { + const data = [ + ['Header1', 'Header2'], + ['Value1', 'Value2'], + ['Value with, comma', 'Value with "quotes"'], + ]; + + exportToCSV(data, 'test.csv'); + + expect(mockCreateElement).toHaveBeenCalledWith('a'); + expect(mockSetAttribute).toHaveBeenCalledWith('href', 'mock-url'); + expect(mockSetAttribute).toHaveBeenCalledWith('download', 'test.csv'); + expect(mockAppendChild).toHaveBeenCalled(); + expect(mockClick).toHaveBeenCalled(); + expect(mockRemoveChild).toHaveBeenCalled(); + expect(URL.revokeObjectURL).toHaveBeenCalledWith('mock-url'); + }); + test('throws error if data is empty', () => { + expect(() => exportToCSV([], 'test.csv')).toThrow('Data cannot be empty'); + }); + + test('throws error if filename is empty', () => { + expect(() => exportToCSV([['data']], '')).toThrow('Filename is required'); + }); + + test('adds .csv extension if missing', () => { + const data = [['test']]; + exportToCSV(data, 'filename'); + expect(mockSetAttribute).toHaveBeenCalledWith('download', 'filename.csv'); + }); + }); + + describe('exportTrendsToCSV', () => { + test('exports attendance trends data correctly', () => { + const eventLabels = ['Event1', 'Event2']; + const attendeeCounts = [10, 20]; + const maleCounts = [5, 10]; + const femaleCounts = [4, 8]; + const otherCounts = [1, 2]; + + exportTrendsToCSV( + eventLabels, + attendeeCounts, + maleCounts, + femaleCounts, + otherCounts, + ); + + expect(mockCreateElement).toHaveBeenCalledWith('a'); + expect(mockSetAttribute).toHaveBeenCalledWith( + 'download', + 'attendance_trends.csv', + ); + expect(mockClick).toHaveBeenCalled(); + }); + }); + + describe('exportDemographicsToCSV', () => { + test('exports demographics data correctly', () => { + const selectedCategory = 'Age Groups'; + const categoryLabels = ['0-18', '19-30', '31+']; + const categoryData = [10, 20, 15]; + + exportDemographicsToCSV(selectedCategory, categoryLabels, categoryData); + + expect(mockCreateElement).toHaveBeenCalledWith('a'); + expect(mockClick).toHaveBeenCalled(); + expect(mockSetAttribute).toHaveBeenCalledWith('href', 'mock-url'); + }); + + test('throws error if selected category is empty', () => { + expect(() => exportDemographicsToCSV('', ['label'], [1])).toThrow( + 'Selected category is required', + ); + }); + + test('throws error if labels and data arrays have different lengths', () => { + expect(() => + exportDemographicsToCSV('Category', ['label1', 'label2'], [1]), + ).toThrow('Labels and data arrays must have the same length'); + }); + + test('creates safe filename with timestamp', () => { + jest.useFakeTimers(); + const mockDate = new Date('2023-01-01T00:00:00.000Z'); + jest.setSystemTime(mockDate); + + const selectedCategory = 'Age & Demographics!'; + const categoryLabels = ['Group1']; + const categoryData = [10]; + + exportDemographicsToCSV(selectedCategory, categoryLabels, categoryData); + + const expectedFilename = + 'age___demographics__demographics_2023-01-01T00-00-00.000Z.csv'; + const downloadCalls = mockSetAttribute.mock.calls.filter( + (call) => call[0] === 'download', + ); + expect(downloadCalls[0][1]).toBe(expectedFilename); + jest.useRealTimers(); + }); + }); +}); diff --git a/src/utils/chartToPdf.ts b/src/utils/chartToPdf.ts new file mode 100644 index 0000000000..d724f077cc --- /dev/null +++ b/src/utils/chartToPdf.ts @@ -0,0 +1,106 @@ +type CSVData = (string | number)[][]; + +export const exportToCSV = (data: CSVData, filename: string): void => { + if (!data?.length) { + throw new Error('Data cannot be empty'); + } + + if (!filename) { + throw new Error('Filename is required'); + } + + // Ensure .csv extension + const finalFilename = filename.endsWith('.csv') + ? filename + : `${filename}.csv`; + const csvContent = + // Properly escape and quote CSV content + 'data:text/csv;charset=utf-8,' + + data + .map((row) => + row + .map((cell) => { + const cellStr = String(cell); + // Escape double quotes by doubling them + const escapedCell = cellStr.replace(/"/g, '""'); + // Enclose cell in double quotes if it contains commas, newlines, or double quotes + return /[",\n]/.test(escapedCell) + ? `"${escapedCell}"` + : escapedCell; + }) + .join(','), + ) + .join('\n'); + const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }); + const url = URL.createObjectURL(blob); + const link = document.createElement('a'); + try { + link.setAttribute('href', url); + link.setAttribute('download', finalFilename); + document.body.appendChild(link); + link.click(); + } finally { + if (link.parentNode === document.body) { + document.body.removeChild(link); + } + URL.revokeObjectURL(url); // Clean up the URL object + } +}; + +export const exportTrendsToCSV = ( + eventLabels: string[], + attendeeCounts: number[], + maleCounts: number[], + femaleCounts: number[], + otherCounts: number[], +): void => { + const heading = 'Attendance Trends'; + const headers = [ + 'Date', + 'Attendee Count', + 'Male Attendees', + 'Female Attendees', + 'Other Attendees', + ]; + const data: CSVData = [ + [heading], + [], + headers, + ...eventLabels.map((label, index) => [ + label, + attendeeCounts[index], + maleCounts[index], + femaleCounts[index], + otherCounts[index], + ]), + ]; + exportToCSV(data, 'attendance_trends.csv'); +}; + +export const exportDemographicsToCSV = ( + selectedCategory: string, + categoryLabels: string[], + categoryData: number[], +): void => { + if (!selectedCategory?.trim()) { + throw new Error('Selected category is required'); + } + + if (categoryLabels.length !== categoryData.length) { + throw new Error('Labels and data arrays must have the same length'); + } + + const heading = `${selectedCategory} Demographics`; + const headers = [selectedCategory, 'Count']; + const data: CSVData = [ + [heading], + [], + headers, + ...categoryLabels.map((label, index) => [label, categoryData[index]]), + ]; + const safeCategory = selectedCategory + .replace(/[^a-z0-9]/gi, '_') + .toLowerCase(); + const timestamp = new Date().toISOString().replace(/[:]/g, '-'); + exportToCSV(data, `${safeCategory}_demographics_${timestamp}.csv`); +}; diff --git a/src/utils/dateFormatter.test.ts b/src/utils/dateFormatter.test.ts new file mode 100644 index 0000000000..a8e2b4b096 --- /dev/null +++ b/src/utils/dateFormatter.test.ts @@ -0,0 +1,37 @@ +import { formatDate } from './dateFormatter'; + +describe('formatDate', () => { + test('formats date with st suffix', () => { + expect(formatDate('2023-01-01')).toBe('1st Jan 2023'); + expect(formatDate('2023-05-21')).toBe('21st May 2023'); + expect(formatDate('2023-10-31')).toBe('31st Oct 2023'); + }); + + test('formats date with nd suffix', () => { + expect(formatDate('2023-06-02')).toBe('2nd Jun 2023'); + expect(formatDate('2023-09-22')).toBe('22nd Sep 2023'); + }); + + test('formats date with rd suffix', () => { + expect(formatDate('2023-07-03')).toBe('3rd Jul 2023'); + expect(formatDate('2023-08-23')).toBe('23rd Aug 2023'); + }); + + test('formats date with th suffix', () => { + expect(formatDate('2023-02-04')).toBe('4th Feb 2023'); + expect(formatDate('2023-03-11')).toBe('11th Mar 2023'); + expect(formatDate('2023-04-12')).toBe('12th Apr 2023'); + expect(formatDate('2023-05-13')).toBe('13th May 2023'); + expect(formatDate('2023-06-24')).toBe('24th Jun 2023'); + }); + + test('throws error for empty date string', () => { + expect(() => formatDate('')).toThrow('Date string is required'); + }); + + test('throws error for invalid date string', () => { + expect(() => formatDate('invalid-date')).toThrow( + 'Invalid date string provided', + ); + }); +}); diff --git a/src/utils/dateFormatter.ts b/src/utils/dateFormatter.ts new file mode 100644 index 0000000000..92f4abc051 --- /dev/null +++ b/src/utils/dateFormatter.ts @@ -0,0 +1,33 @@ +export function formatDate(dateString: string): string { + if (!dateString) { + throw new Error('Date string is required'); + } + const date = new Date(dateString); + if (isNaN(date.getTime())) { + throw new Error('Invalid date string provided'); + } + const day = date.getDate(); + const year = date.getFullYear(); + + const getSuffix = (day: number): string => { + if (day >= 11 && day <= 13) return 'th'; + const lastDigit = day % 10; + switch (lastDigit) { + case 1: + return 'st'; + case 2: + return 'nd'; + case 3: + return 'rd'; + default: + return 'th'; + } + }; + const suffix = getSuffix(day); + + const monthName = new Intl.DateTimeFormat('en', { month: 'short' }).format( + date, + ); + + return `${day}${suffix} ${monthName} ${year}`; +} diff --git a/src/utils/formEnumFields.ts b/src/utils/formEnumFields.ts index 928537aaab..03b033f185 100644 --- a/src/utils/formEnumFields.ts +++ b/src/utils/formEnumFields.ts @@ -202,124 +202,124 @@ const countryOptions = [ const educationGradeEnum = [ { value: 'NO_GRADE', - label: 'noGrade', + label: 'No-Grade', }, { value: 'PRE_KG', - label: 'preKg', + label: 'Pre-Kg', }, { value: 'KG', - label: 'kg', + label: 'Kg', }, { value: 'GRADE_1', - label: 'grade1', + label: 'Grade-1', }, { value: 'GRADE_2', - label: 'grade2', + label: 'Grade-2', }, { value: 'GRADE_3', - label: 'grade3', + label: 'Grade-3', }, { value: 'GRADE_4', - label: 'grade4', + label: 'Grade-4', }, { value: 'GRADE_5', - label: 'grade5', + label: 'Grade-5', }, { value: 'GRADE_6', - label: 'grade6', + label: 'Grade-6', }, { value: 'GRADE_7', - label: 'grade7', + label: 'Grade-7', }, { value: 'GRADE_8', - label: 'grade8', + label: 'Grade-8', }, { value: 'GRADE_9', - label: 'grade9', + label: 'Grade-9', }, { value: 'GRADE_10', - label: 'grade10', + label: 'Grade-10', }, { value: 'GRADE_11', - label: 'grade11', + label: 'Grade-11', }, { value: 'GRADE_12', - label: 'grade12', + label: 'Grade-12', }, { value: 'GRADUATE', - label: 'graduate', + label: 'Graduate', }, ]; const maritalStatusEnum = [ { value: 'SINGLE', - label: 'single', + label: 'Single', }, { value: 'ENGAGED', - label: 'engaged', + label: 'Engaged', }, { value: 'MARRIED', - label: 'married', + label: 'Married', }, { value: 'DIVORCED', - label: 'divorced', + label: 'Divorced', }, { value: 'WIDOWED', - label: 'widowed', + label: 'Widowed', }, { value: 'SEPARATED', - label: 'separated', + label: 'Separated', }, ]; const genderEnum = [ { value: 'MALE', - label: 'male', + label: 'Male', }, { value: 'FEMALE', - label: 'female', + label: 'Female', }, { value: 'OTHER', - label: 'other', + label: 'Other', }, ]; const employmentStatusEnum = [ { value: 'FULL_TIME', - label: 'fullTime', + label: 'Full-Time', }, { value: 'PART_TIME', - label: 'partTime', + label: 'Part-Time', }, { value: 'UNEMPLOYED', - label: 'unemployed', + label: 'Unemployed', }, ]; diff --git a/src/utils/interfaces.ts b/src/utils/interfaces.ts index 495234a5a1..7ab84a61c1 100644 --- a/src/utils/interfaces.ts +++ b/src/utils/interfaces.ts @@ -7,6 +7,27 @@ export interface InterfaceUserType { }; } +export interface InterfaceUserInfo { + _id: string; + firstName: string; + lastName: string; + image?: string | null; +} + +// Base interface for common event properties +export interface InterfaceBaseEvent { + _id: string; + title: string; + description: string; + startDate: string; + endDate: string; + location: string; + startTime: string; + endTime: string; + allDay: boolean; + recurring: boolean; +} + export interface InterfaceActionItemCategoryInfo { _id: string; name: string; @@ -21,18 +42,11 @@ export interface InterfaceActionItemCategoryList { export interface InterfaceActionItemInfo { _id: string; - assignee: { - _id: string; - firstName: string; - lastName: string; - image: string | null; - }; - assigner: { - _id: string; - firstName: string; - lastName: string; - image: string | null; - }; + assigneeType: 'EventVolunteer' | 'EventVolunteerGroup' | 'User'; + assignee: InterfaceEventVolunteerInfo | null; + assigneeGroup: InterfaceVolunteerGroupInfo | null; + assigneeUser: InterfaceUserInfo | null; + assigner: InterfaceUserInfo; actionItemCategory: { _id: string; name: string; @@ -41,18 +55,14 @@ export interface InterfaceActionItemInfo { postCompletionNotes: string | null; assignmentDate: Date; dueDate: Date; - completionDate: Date; + completionDate: Date | null; isCompleted: boolean; event: { _id: string; title: string; } | null; - creator: { - _id: string; - firstName: string; - lastName: string; - }; - allotedHours: number | null; + creator: InterfaceUserInfo; + allottedHours: number | null; } export interface InterfaceActionItemList { @@ -209,19 +219,43 @@ export interface InterfaceQueryOrganizationPostListItem { }; } -interface InterfaceTagData { +export interface InterfaceTagData { + _id: string; + name: string; + parentTag: { _id: string }; + usersAssignedTo: { + totalCount: number; + }; + childTags: { + totalCount: number; + }; + ancestorTags: { + _id: string; + name: string; + }[]; +} + +interface InterfaceTagNodeData { + edges: { + node: InterfaceTagData; + cursor: string; + }[]; + pageInfo: { + startCursor: string; + endCursor: string; + hasNextPage: boolean; + hasPreviousPage: boolean; + }; + totalCount: number; +} + +interface InterfaceTagMembersData { edges: { node: { _id: string; - name: string; - usersAssignedTo: { - totalCount: number; - }; - childTags: { - totalCount: number; - }; + firstName: string; + lastName: string; }; - cursor: string; }[]; pageInfo: { startCursor: string; @@ -233,32 +267,30 @@ interface InterfaceTagData { } export interface InterfaceQueryOrganizationUserTags { - userTags: InterfaceTagData; + userTags: InterfaceTagNodeData; +} + +export interface InterfaceQueryUserTagChildTags { + name: string; + childTags: InterfaceTagNodeData; + ancestorTags: { + _id: string; + name: string; + }[]; } export interface InterfaceQueryUserTagsAssignedMembers { name: string; - usersAssignedTo: { - edges: { - node: { - _id: string; - firstName: string; - lastName: string; - }; - }[]; - pageInfo: { - startCursor: string; - endCursor: string; - hasNextPage: boolean; - hasPreviousPage: boolean; - }; - totalCount: number; - }; + usersAssignedTo: InterfaceTagMembersData; + ancestorTags: { + _id: string; + name: string; + }[]; } -export interface InterfaceQueryUserTagChildTags { +export interface InterfaceQueryUserTagsMembersToAssignTo { name: string; - childTags: InterfaceTagData; + usersToAssignTo: InterfaceTagMembersData; } export interface InterfaceQueryOrganizationAdvertisementListItem { @@ -343,19 +375,10 @@ export interface InterfacePledgeInfo { currency: string; endDate: string; startDate: string; - users: InterfacePledger[]; + users: InterfaceUserInfo[]; } -export interface InterfaceQueryOrganizationEventListItem { - _id: string; - title: string; - description: string; - startDate: string; - endDate: string; - location: string; - startTime: string; - endTime: string; - allDay: boolean; - recurring: boolean; +export interface InterfaceQueryOrganizationEventListItem + extends InterfaceBaseEvent { isPublic: boolean; isRegisterable: boolean; } @@ -483,7 +506,7 @@ export interface InterfacePostCard { } export interface InterfaceCreatePledge { - pledgeUsers: InterfacePledger[]; + pledgeUsers: InterfaceUserInfo[]; pledgeAmount: number; pledgeCurrency: string; pledgeStartDate: Date; @@ -505,13 +528,6 @@ export interface InterfaceQueryMembershipRequestsListItem { }[]; } -export interface InterfacePledger { - _id: string; - firstName: string; - lastName: string; - image: string | null; -} - export interface InterfaceAgendaItemCategoryInfo { _id: string; name: string; @@ -527,6 +543,20 @@ export interface InterfaceAgendaItemCategoryList { agendaItemCategoriesByOrganization: InterfaceAgendaItemCategoryInfo[]; } +export interface InterfaceAddOnSpotAttendeeProps { + show: boolean; + handleClose: () => void; + reloadMembers: () => void; +} + +export interface InterfaceFormData { + firstName: string; + lastName: string; + email: string; + phoneNo: string; + gender: string; +} + export interface InterfaceAgendaItemInfo { _id: string; title: string; @@ -571,3 +601,101 @@ export interface InterfaceCustomFieldData { type: string; name: string; } + +export interface InterfaceEventVolunteerInfo { + _id: string; + hasAccepted: boolean; + hoursVolunteered: number | null; + user: InterfaceUserInfo; + assignments: { + _id: string; + }[]; + groups: { + _id: string; + name: string; + volunteers: { + _id: string; + }[]; + }[]; +} + +export interface InterfaceVolunteerGroupInfo { + _id: string; + name: string; + description: string | null; + event: { + _id: string; + }; + volunteersRequired: number | null; + createdAt: string; + creator: InterfaceUserInfo; + leader: InterfaceUserInfo; + volunteers: { + _id: string; + user: InterfaceUserInfo; + }[]; + assignments: { + _id: string; + actionItemCategory: { + _id: string; + name: string; + }; + allottedHours: number; + isCompleted: boolean; + }[]; +} + +export interface InterfaceCreateVolunteerGroup { + name: string; + description: string | null; + leader: InterfaceUserInfo | null; + volunteersRequired: number | null; + volunteerUsers: InterfaceUserInfo[]; +} + +export interface InterfaceUserEvents extends InterfaceBaseEvent { + volunteerGroups: { + _id: string; + name: string; + volunteersRequired: number; + description: string; + volunteers: { _id: string }[]; + }[]; + volunteers: { + _id: string; + user: { + _id: string; + }; + }[]; +} + +export interface InterfaceVolunteerMembership { + _id: string; + status: string; + createdAt: string; + event: { + _id: string; + title: string; + startDate: string; + }; + volunteer: { + _id: string; + user: InterfaceUserInfo; + }; + group: { + _id: string; + name: string; + }; +} + +export interface InterfaceVolunteerRank { + rank: number; + hoursVolunteered: number; + user: { + _id: string; + firstName: string; + lastName: string; + email: string; + image: string | null; + }; +} diff --git a/src/utils/organizationTagsUtils.ts b/src/utils/organizationTagsUtils.ts index 5f81497c65..56654a3abb 100644 --- a/src/utils/organizationTagsUtils.ts +++ b/src/utils/organizationTagsUtils.ts @@ -1,5 +1,13 @@ // This file will contain the utililities for organization tags +import type { ApolloError } from '@apollo/client'; +import type { + InterfaceQueryOrganizationUserTags, + InterfaceQueryUserTagChildTags, + InterfaceQueryUserTagsAssignedMembers, + InterfaceQueryUserTagsMembersToAssignTo, +} from './interfaces'; + // This is the style object for mui's data grid used to list the data (tags and member data) export const dataGridStyle = { '&.MuiDataGrid-root .MuiDataGrid-cell:focus-within': { @@ -20,4 +28,90 @@ export const dataGridStyle = { '& .MuiDataGrid-main': { borderRadius: '0.1rem', }, + '& .MuiDataGrid-topContainer': { + position: 'fixed', + top: 290, + zIndex: 1, + }, + '& .MuiDataGrid-virtualScrollerContent': { + marginTop: 6.5, + }, }; + +// the data chunk size for tag related queries +export const TAGS_QUERY_DATA_CHUNK_SIZE = 10; + +// the tag action type +export type TagActionType = 'assignToTags' | 'removeFromTags'; + +// the sortedByType +export type SortedByType = 'ASCENDING' | 'DESCENDING'; + +// Interfaces for tag queries: +// 1. Base interface for Apollo query results +interface InterfaceBaseQueryResult { + loading: boolean; + error?: ApolloError; + refetch?: () => void; +} + +// 2. Generic pagination options +interface InterfacePaginationVariables { + after?: string | null; + first?: number | null; +} + +// 3. Generic fetch more options +interface InterfaceBaseFetchMoreOptions { + variables: InterfacePaginationVariables; + updateQuery?: (prev: T, options: { fetchMoreResult: T }) => T; +} + +// 4. Query interfaces +export interface InterfaceOrganizationTagsQuery + extends InterfaceBaseQueryResult { + data?: { + organizations: InterfaceQueryOrganizationUserTags[]; + }; + fetchMore: ( + options: InterfaceBaseFetchMoreOptions<{ + organizations: InterfaceQueryOrganizationUserTags[]; + }>, + ) => void; +} + +export interface InterfaceOrganizationSubTagsQuery + extends InterfaceBaseQueryResult { + data?: { + getChildTags: InterfaceQueryUserTagChildTags; + }; + fetchMore: ( + options: InterfaceBaseFetchMoreOptions<{ + getChildTags: InterfaceQueryUserTagChildTags; + }>, + ) => void; +} + +export interface InterfaceTagAssignedMembersQuery + extends InterfaceBaseQueryResult { + data?: { + getAssignedUsers: InterfaceQueryUserTagsAssignedMembers; + }; + fetchMore: ( + options: InterfaceBaseFetchMoreOptions<{ + getAssignedUsers: InterfaceQueryUserTagsAssignedMembers; + }>, + ) => void; +} + +export interface InterfaceTagUsersToAssignToQuery + extends InterfaceBaseQueryResult { + data?: { + getUsersToAssignTo: InterfaceQueryUserTagsMembersToAssignTo; + }; + fetchMore: ( + options: InterfaceBaseFetchMoreOptions<{ + getUsersToAssignTo: InterfaceQueryUserTagsMembersToAssignTo; + }>, + ) => void; +} diff --git a/src/utils/useSession.test.tsx b/src/utils/useSession.test.tsx new file mode 100644 index 0000000000..32287ccbb0 --- /dev/null +++ b/src/utils/useSession.test.tsx @@ -0,0 +1,544 @@ +import type { ReactNode } from 'react'; +import React from 'react'; +import { renderHook, act, waitFor } from '@testing-library/react'; +import { MockedProvider } from '@apollo/client/testing'; +import { toast } from 'react-toastify'; +import useSession from './useSession'; +import { GET_COMMUNITY_SESSION_TIMEOUT_DATA } from 'GraphQl/Queries/Queries'; +import { REVOKE_REFRESH_TOKEN } from 'GraphQl/Mutations/mutations'; +import { errorHandler } from 'utils/errorHandler'; +import { BrowserRouter } from 'react-router-dom'; + +jest.mock('react-toastify', () => ({ + toast: { + info: jest.fn(), + warning: jest.fn(), + error: jest.fn(), + }, +})); + +jest.mock('utils/errorHandler', () => ({ + errorHandler: jest.fn(), +})); + +jest.mock('react-i18next', () => ({ + useTranslation: () => ({ + t: (key: string) => key, + }), +})); + +const MOCKS = [ + { + request: { + query: GET_COMMUNITY_SESSION_TIMEOUT_DATA, + }, + result: { + data: { + getCommunityData: { + timeout: 30, + }, + }, + }, + delay: 100, + }, + { + request: { + query: REVOKE_REFRESH_TOKEN, + }, + result: { + data: { + revokeRefreshTokenForUser: true, + }, + }, + }, +]; + +const wait = (ms: number): Promise => + new Promise((resolve) => setTimeout(resolve, ms)); + +describe('useSession Hook', () => { + beforeEach(() => { + jest.clearAllMocks(); + jest.spyOn(window, 'addEventListener').mockImplementation(jest.fn()); + jest.spyOn(window, 'removeEventListener').mockImplementation(jest.fn()); + Object.defineProperty(global, 'localStorage', { + value: { + clear: jest.fn(), + }, + writable: true, + }); + }); + + afterEach(() => { + jest.clearAllMocks(); + jest.useRealTimers(); + jest.restoreAllMocks(); + }); + + test('should handle visibility change to visible', async () => { + jest.useFakeTimers(); + + const { result } = renderHook(() => useSession(), { + wrapper: ({ children }: { children?: ReactNode }) => ( + + {children} + + ), + }); + + Object.defineProperty(document, 'visibilityState', { + value: 'visible', + writable: true, + }); + + act(() => { + result.current.startSession(); + }); + + // Simulate visibility change + act(() => { + document.dispatchEvent(new Event('visibilitychange')); + }); + + act(() => { + jest.advanceTimersByTime(15 * 60 * 1000); + }); + + await waitFor(() => { + expect(window.addEventListener).toHaveBeenCalledWith( + 'mousemove', + expect.any(Function), + ); + expect(window.addEventListener).toHaveBeenCalledWith( + 'keydown', + expect.any(Function), + ); + expect(toast.warning).toHaveBeenCalledWith('sessionWarning'); + }); + + jest.useRealTimers(); + }); + + test('should handle visibility change to hidden and ensure no warning appears in 15 minutes', async () => { + jest.useFakeTimers(); + + const { result } = renderHook(() => useSession(), { + wrapper: ({ children }: { children?: ReactNode }) => ( + + {children} + + ), + }); + + Object.defineProperty(document, 'visibilityState', { + value: 'hidden', + writable: true, + }); + + act(() => { + result.current.startSession(); + }); + + act(() => { + document.dispatchEvent(new Event('visibilitychange')); + }); + + act(() => { + jest.advanceTimersByTime(15 * 60 * 1000); + }); + + await waitFor(() => { + expect(window.removeEventListener).toHaveBeenCalledWith( + 'mousemove', + expect.any(Function), + ); + expect(window.removeEventListener).toHaveBeenCalledWith( + 'keydown', + expect.any(Function), + ); + expect(toast.warning).not.toHaveBeenCalled(); + }); + + jest.useRealTimers(); + }); + + test('should register event listeners on startSession', async () => { + const addEventListenerMock = jest.fn(); + const originalWindowAddEventListener = window.addEventListener; + const originalDocumentAddEventListener = document.addEventListener; + + window.addEventListener = addEventListenerMock; + document.addEventListener = addEventListenerMock; + + const { result } = renderHook(() => useSession(), { + wrapper: ({ children }: { children?: ReactNode }) => ( + + {children} + + ), + }); + + act(() => { + result.current.startSession(); + }); + + expect(addEventListenerMock).toHaveBeenCalledWith( + 'mousemove', + expect.any(Function), + ); + expect(addEventListenerMock).toHaveBeenCalledWith( + 'keydown', + expect.any(Function), + ); + expect(addEventListenerMock).toHaveBeenCalledWith( + 'visibilitychange', + expect.any(Function), + ); + + window.addEventListener = originalWindowAddEventListener; + document.addEventListener = originalDocumentAddEventListener; + }); + + test('should call handleLogout after session timeout', async () => { + jest.useFakeTimers(); + + const { result } = renderHook(() => useSession(), { + wrapper: ({ children }: { children?: ReactNode }) => ( + + {children} + + ), + }); + + act(() => { + result.current.startSession(); + }); + + act(() => { + jest.advanceTimersByTime(31 * 60 * 1000); + }); + + await waitFor(() => { + expect(global.localStorage.clear).toHaveBeenCalled(); + expect(toast.warning).toHaveBeenCalledTimes(2); + expect(toast.warning).toHaveBeenNthCalledWith(1, 'sessionWarning'); + expect(toast.warning).toHaveBeenNthCalledWith(2, 'sessionLogout', { + autoClose: false, + }); + }); + }); + + test('should show a warning toast before session expiration', async () => { + jest.useFakeTimers(); + + const { result } = renderHook(() => useSession(), { + wrapper: ({ children }: { children?: ReactNode }) => ( + + {children} + + ), + }); + + act(() => { + result.current.startSession(); + }); + + act(() => { + jest.advanceTimersByTime(15 * 60 * 1000); + }); + + await waitFor(() => + expect(toast.warning).toHaveBeenCalledWith('sessionWarning'), + ); + + jest.useRealTimers(); + }); + + test('should handle error when revoking token fails', async () => { + const consoleErrorMock = jest.spyOn(console, 'error').mockImplementation(); + + const errorMocks = [ + { + request: { + query: GET_COMMUNITY_SESSION_TIMEOUT_DATA, + }, + result: { + data: { + getCommunityData: { + timeout: 30, + }, + }, + }, + delay: 1000, + }, + { + request: { + query: REVOKE_REFRESH_TOKEN, + }, + error: new Error('Failed to revoke refresh token'), + }, + ]; + + const { result } = renderHook(() => useSession(), { + wrapper: ({ children }: { children?: ReactNode }) => ( + + {children} + + ), + }); + + act(() => { + result.current.startSession(); + result.current.handleLogout(); + }); + + await waitFor(() => + expect(consoleErrorMock).toHaveBeenCalledWith( + 'Error revoking refresh token:', + expect.any(Error), + ), + ); + + consoleErrorMock.mockRestore(); + }); + + test('should set session timeout based on fetched data', async () => { + jest.spyOn(global, 'setTimeout'); + + const { result } = renderHook(() => useSession(), { + wrapper: ({ children }: { children?: ReactNode }) => ( + + {children} + + ), + }); + + act(() => { + result.current.startSession(); + }); + + expect(global.setTimeout).toHaveBeenCalled(); + }); + + test('should call errorHandler on query error', async () => { + const errorMocks = [ + { + request: { + query: GET_COMMUNITY_SESSION_TIMEOUT_DATA, + }, + error: new Error('An error occurred'), + }, + ]; + + const { result } = renderHook(() => useSession(), { + wrapper: ({ children }: { children?: ReactNode }) => ( + + {children} + + ), + }); + + act(() => { + result.current.startSession(); + }); + + await waitFor(() => expect(errorHandler).toHaveBeenCalled()); + }); + //dfghjkjhgfds + + test('should remove event listeners on endSession', async () => { + const { result } = renderHook(() => useSession(), { + wrapper: ({ children }: { children?: ReactNode }) => ( + + {children} + + ), + }); + + // Mock the removeEventListener functions for both window and document + const removeEventListenerMock = jest.fn(); + + // Temporarily replace the real methods with the mock + const originalWindowRemoveEventListener = window.removeEventListener; + const originalDocumentRemoveEventListener = document.removeEventListener; + + window.removeEventListener = removeEventListenerMock; + document.removeEventListener = removeEventListenerMock; + + // await waitForNextUpdate(); + + act(() => { + result.current.startSession(); + }); + + act(() => { + result.current.endSession(); + }); + + // Test that event listeners were removed + expect(removeEventListenerMock).toHaveBeenCalledWith( + 'mousemove', + expect.any(Function), + ); + expect(removeEventListenerMock).toHaveBeenCalledWith( + 'keydown', + expect.any(Function), + ); + expect(removeEventListenerMock).toHaveBeenCalledWith( + 'visibilitychange', + expect.any(Function), + ); + + // Restore the original removeEventListener functions + window.removeEventListener = originalWindowRemoveEventListener; + document.removeEventListener = originalDocumentRemoveEventListener; + }); + + test('should call initialize timers when session is still active when the user returns to the tab', async () => { + jest.useFakeTimers(); + jest.spyOn(global, 'setTimeout').mockImplementation(jest.fn()); + + const { result } = renderHook(() => useSession(), { + wrapper: ({ children }) => ( + + {children} + + ), + }); + + jest.advanceTimersByTime(1000); + + // Set initial visibility state to visible + Object.defineProperty(document, 'visibilityState', { + value: 'visible', + writable: true, + }); + + // Start the session + act(() => { + result.current.startSession(); + jest.advanceTimersByTime(10 * 60 * 1000); // Fast-forward + }); + + // Simulate the user leaving the tab (set visibility to hidden) + Object.defineProperty(document, 'visibilityState', { + value: 'hidden', + writable: true, + }); + + act(() => { + document.dispatchEvent(new Event('visibilitychange')); + }); + + // Fast-forward time by more than the session timeout + act(() => { + jest.advanceTimersByTime(5 * 60 * 1000); // Fast-forward + }); + + // Simulate the user returning to the tab + Object.defineProperty(document, 'visibilityState', { + value: 'visible', + writable: true, + }); + + act(() => { + document.dispatchEvent(new Event('visibilitychange')); + }); + + jest.advanceTimersByTime(1000); + + expect(global.setTimeout).toHaveBeenCalled(); + + // Restore real timers + jest.useRealTimers(); + }); + + test('should call handleLogout when session expires due to inactivity away from tab', async () => { + jest.useFakeTimers(); // Use fake timers to control time + + const { result } = renderHook(() => useSession(), { + wrapper: ({ children }) => ( + + {children} + + ), + }); + + jest.advanceTimersByTime(1000); + + // Set initial visibility state to visible + Object.defineProperty(document, 'visibilityState', { + value: 'visible', + writable: true, + }); + + // Start the session + act(() => { + result.current.startSession(); + jest.advanceTimersByTime(10 * 60 * 1000); // Fast-forward + }); + + // Simulate the user leaving the tab (set visibility to hidden) + Object.defineProperty(document, 'visibilityState', { + value: 'hidden', + writable: true, + }); + + act(() => { + document.dispatchEvent(new Event('visibilitychange')); + }); + + // Fast-forward time by more than the session timeout + act(() => { + jest.advanceTimersByTime(32 * 60 * 1000); // Fast-forward by 32 minutes + }); + + // Simulate the user returning to the tab + Object.defineProperty(document, 'visibilityState', { + value: 'visible', + writable: true, + }); + + act(() => { + document.dispatchEvent(new Event('visibilitychange')); + }); + + jest.advanceTimersByTime(250); + + await waitFor(() => { + expect(global.localStorage.clear).toHaveBeenCalled(); + expect(toast.warning).toHaveBeenCalledWith('sessionLogout', { + autoClose: false, + }); + }); + + // Restore real timers + jest.useRealTimers(); + }); + + test('should handle logout and revoke token', async () => { + jest.useFakeTimers(); + + const { result } = renderHook(() => useSession(), { + wrapper: ({ children }: { children?: ReactNode }) => ( + + {children} + + ), + }); + + act(() => { + result.current.startSession(); + result.current.handleLogout(); + }); + + await waitFor(() => { + expect(global.localStorage.clear).toHaveBeenCalled(); + expect(toast.warning).toHaveBeenCalledWith('sessionLogout', { + autoClose: false, + }); + }); + + jest.useRealTimers(); + }); +}); diff --git a/src/utils/useSession.tsx b/src/utils/useSession.tsx new file mode 100644 index 0000000000..4279e7c850 --- /dev/null +++ b/src/utils/useSession.tsx @@ -0,0 +1,164 @@ +import { useMutation, useQuery } from '@apollo/client'; +import { REVOKE_REFRESH_TOKEN } from 'GraphQl/Mutations/mutations'; +import { GET_COMMUNITY_SESSION_TIMEOUT_DATA } from 'GraphQl/Queries/Queries'; +import { t } from 'i18next'; +import { useEffect, useState, useRef } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useNavigate } from 'react-router-dom'; +import { toast } from 'react-toastify'; +import { errorHandler } from 'utils/errorHandler'; + +type UseSessionReturnType = { + startSession: () => void; + endSession: () => void; + handleLogout: () => void; + extendSession: () => void; //for when logged in already, simply extend session +}; + +/** + * Custom hook for managing user session timeouts in a React application. + * + * This hook handles: + * - Starting and ending the user session. + * - Displaying a warning toast at half of the session timeout duration. + * - Logging the user out and displaying a session expiration toast when the session times out. + * - Automatically resetting the timers when user activity is detected. + * - Pausing session timers when the tab is inactive and resuming them when it becomes active again. + * + * @returns UseSessionReturnType - An object with methods to start and end the session, and to handle logout. + */ +const useSession = (): UseSessionReturnType => { + const { t: tCommon } = useTranslation('common'); + + let startTime: number; + let timeoutDuration: number; + const [sessionTimeout, setSessionTimeout] = useState(30); + // const sessionTimeout = 30; + const sessionTimerRef = useRef(null); + const warningTimerRef = useRef(null); + const navigate = useNavigate(); + + const [revokeRefreshToken] = useMutation(REVOKE_REFRESH_TOKEN); + const { data, error: queryError } = useQuery( + GET_COMMUNITY_SESSION_TIMEOUT_DATA, + ); + + useEffect(() => { + if (queryError) { + errorHandler(t, queryError as Error); + } else { + const sessionTimeoutData = data?.getCommunityData; + if (sessionTimeoutData) { + setSessionTimeout(sessionTimeoutData.timeout); + } + } + }, [data, queryError]); + + const resetTimers = (): void => { + if (sessionTimerRef.current) clearTimeout(sessionTimerRef.current); + if (warningTimerRef.current) clearTimeout(warningTimerRef.current); + }; + + const endSession = (): void => { + resetTimers(); + window.removeEventListener('mousemove', extendSession); + window.removeEventListener('keydown', extendSession); + document.removeEventListener('visibilitychange', handleVisibilityChange); + }; + + const handleLogout = async (): Promise => { + try { + await revokeRefreshToken(); + } catch (error) { + console.error('Error revoking refresh token:', error); + // toast.error('Failed to revoke session. Please try again.'); + } + localStorage.clear(); + endSession(); + navigate('/'); + toast.warning(tCommon('sessionLogout'), { autoClose: false }); + }; + + const initializeTimers = ( + timeLeft?: number, + warningTimeLeft?: number, + ): void => { + const warningTime = warningTimeLeft ?? sessionTimeout / 2; + const sessionTimeoutInMilliseconds = + (timeLeft || sessionTimeout) * 60 * 1000; + const warningTimeInMilliseconds = warningTime * 60 * 1000; + + timeoutDuration = sessionTimeoutInMilliseconds; + startTime = Date.now(); + + warningTimerRef.current = setTimeout(() => { + toast.warning(tCommon('sessionWarning')); + }, warningTimeInMilliseconds); + + sessionTimerRef.current = setTimeout(async () => { + await handleLogout(); + }, sessionTimeoutInMilliseconds); + }; + + const extendSession = (): void => { + resetTimers(); + initializeTimers(); + }; + + const startSession = (): void => { + resetTimers(); + initializeTimers(); + window.removeEventListener('mousemove', extendSession); + window.removeEventListener('keydown', extendSession); + document.removeEventListener('visibilitychange', handleVisibilityChange); + window.addEventListener('mousemove', extendSession); + window.addEventListener('keydown', extendSession); + document.addEventListener('visibilitychange', handleVisibilityChange); + }; + + const handleVisibilityChange = async (): Promise => { + if (document.visibilityState === 'hidden') { + window.removeEventListener('mousemove', extendSession); + window.removeEventListener('keydown', extendSession); + resetTimers(); // Optionally reset timers to prevent them from running in the background + } else if (document.visibilityState === 'visible') { + window.removeEventListener('mousemove', extendSession); + window.removeEventListener('keydown', extendSession); // Ensure no duplicates + window.addEventListener('mousemove', extendSession); + window.addEventListener('keydown', extendSession); + + // Calculate remaining time now that the tab is active again + const elapsedTime = Date.now() - startTime; + const remainingTime = timeoutDuration - elapsedTime; + + const remainingSessionTime = Math.max(remainingTime, 0); // Ensures the remaining time is non-negative and measured in ms; + + if (remainingSessionTime > 0) { + // Calculate remaining warning time only if session time is positive + const remainingWarningTime = Math.max(remainingSessionTime / 2, 0); + initializeTimers( + remainingSessionTime / 60 / 1000, + remainingWarningTime / 60 / 1000, + ); + } else { + // Handle session expiration immediately if time has run out + await handleLogout(); + } + } + }; + + useEffect(() => { + return () => { + endSession(); + }; + }, []); + + return { + startSession, + endSession, + handleLogout, + extendSession, + }; +}; + +export default useSession; From 1fe19c143323072107c20b36ef5c4ca743f9bf9b Mon Sep 17 00:00:00 2001 From: Peter Harrison <16875803+palisadoes@users.noreply.github.com> Date: Sat, 16 Nov 2024 15:03:23 -0800 Subject: [PATCH 31/34] Update dependabot.yaml --- .github/dependabot.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml index 9a3e9a54e9..81d68df4bd 100644 --- a/.github/dependabot.yaml +++ b/.github/dependabot.yaml @@ -12,7 +12,7 @@ updates: labels: - "dependencies" # Specify the target branch for PRs - target-branch: "develop" + target-branch: "develop-postgres" # Customize commit message prefix commit-message: prefix: "chore(deps):" From d2a4d735951581838ce7b8827c6fd7cc441d30d6 Mon Sep 17 00:00:00 2001 From: Peter Harrison <16875803+palisadoes@users.noreply.github.com> Date: Sun, 24 Nov 2024 22:30:04 -0500 Subject: [PATCH 32/34] Update pull-request-target.yml --- .github/workflows/pull-request-target.yml | 26 +++++++++++++---------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/.github/workflows/pull-request-target.yml b/.github/workflows/pull-request-target.yml index 2560a0dac9..51e9bf8919 100644 --- a/.github/workflows/pull-request-target.yml +++ b/.github/workflows/pull-request-target.yml @@ -24,18 +24,22 @@ jobs: comment_tag: pr_review_policy message: | ## Our Pull Request Approval Process - - We have these basic policies to make the approval process smoother for our volunteer team. - + + Thanks for contributing! + ### Testing Your Code - - Please make sure your code passes all tests. Our test code coverage system will fail if these conditions occur: - - 1. The overall code coverage drops below the target threshold of the repository - 2. Any file in the pull request has code coverage levels below the repository threshold - 3. Merge conflicts - - The process helps maintain the overall reliability of the code base and is a prerequisite for getting your PR approved. Assigned reviewers regularly review the PR queue and tend to focus on PRs that are passing. + + Remember, your PRs won't be reviewed until these criteria are met: + + 1. We don't merge PRs with poor code quality. + 1. Follow coding best practices such that CodeRabbit.ai approves your PR. + 1. We don't merge PRs with failed tests. + 1. When tests fail, click on the `Details` link to learn more. + 1. Write sufficient tests for your changes (CodeCov Patch Test). Your testing level must be better than the target threshold of the repository + 1. Tests may fail if you edit sensitive files. Ask to add the `sensitive-files-ignore-pr` label if the edits are necessary. + 1. We cannot merge PRs with conflicting files. These must be fixed. + + These policies make our code better. ### Reviewers From 3d1f1f0f1482211f4ec2b3757a71550777a15df8 Mon Sep 17 00:00:00 2001 From: Peter Harrison <16875803+palisadoes@users.noreply.github.com> Date: Sun, 24 Nov 2024 22:32:43 -0500 Subject: [PATCH 33/34] Update pull-request-target.yml --- .github/workflows/pull-request-target.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pull-request-target.yml b/.github/workflows/pull-request-target.yml index 51e9bf8919..af75effc13 100644 --- a/.github/workflows/pull-request-target.yml +++ b/.github/workflows/pull-request-target.yml @@ -36,10 +36,10 @@ jobs: 1. We don't merge PRs with failed tests. 1. When tests fail, click on the `Details` link to learn more. 1. Write sufficient tests for your changes (CodeCov Patch Test). Your testing level must be better than the target threshold of the repository - 1. Tests may fail if you edit sensitive files. Ask to add the `sensitive-files-ignore-pr` label if the edits are necessary. + 1. Tests may fail if you edit sensitive files. Ask to add the `ignore-sensitive-files-pr` label if the edits are necessary. 1. We cannot merge PRs with conflicting files. These must be fixed. - These policies make our code better. + Our policies make our code better. ### Reviewers From dda3b82c0a9557cb9801b76747144f0e87f69ad5 Mon Sep 17 00:00:00 2001 From: Ramneet04 Date: Thu, 12 Dec 2024 15:25:05 +0530 Subject: [PATCH 34/34] migrated jest to vitest --- .../AgendaItemsCreateModal.spec.tsx | 370 ++++++++++++++++++ 1 file changed, 370 insertions(+) create mode 100644 src/components/AgendaItems/AgendaItemsCreateModal.spec.tsx diff --git a/src/components/AgendaItems/AgendaItemsCreateModal.spec.tsx b/src/components/AgendaItems/AgendaItemsCreateModal.spec.tsx new file mode 100644 index 0000000000..62b046674f --- /dev/null +++ b/src/components/AgendaItems/AgendaItemsCreateModal.spec.tsx @@ -0,0 +1,370 @@ +import React from 'react'; +import { + render, + screen, + fireEvent, + waitFor, + within, +} from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; + +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; + +import AgendaItemsCreateModal from './AgendaItemsCreateModal'; +import { toast } from 'react-toastify'; +import convertToBase64 from 'utils/convertToBase64'; +import '@testing-library/jest-dom/vitest'; +import { describe, test, expect, vi } from 'vitest'; + +const mockFormState = { + title: 'Test Title', + description: 'Test Description', + duration: '20', + attachments: ['Test Attachment'], + urls: ['https://example.com'], + agendaItemCategoryIds: ['category'], +}; +const mockHideCreateModal = vi.fn(); +const mockSetFormState = vi.fn(); +const mockCreateAgendaItemHandler = vi.fn(); +const mockT = (key: string): string => key; +const mockAgendaItemCategories = [ + { + _id: '1', + name: 'Test Name', + description: 'Test Description', + createdBy: { + _id: '1', + firstName: 'Test', + lastName: 'User', + }, + }, + { + _id: '2', + name: 'Another Category', + description: 'Another Description', + createdBy: { + _id: '2', + firstName: 'Another', + lastName: 'Creator', + }, + }, + { + _id: '3', + name: 'Third Category', + description: 'Third Description', + createdBy: { + _id: '3', + firstName: 'Third', + lastName: 'User', + }, + }, +]; +vi.mock('react-toastify', () => ({ + toast: { + success: vi.fn(), + error: vi.fn(), + }, +})); +vi.mock('utils/convertToBase64'); +const mockedConvertToBase64 = convertToBase64 as vi.MockedFunction< + typeof convertToBase64 +>; + +describe('AgendaItemsCreateModal', () => { + test('renders modal correctly', () => { + render( + + + + + + + + + + + , + ); + + expect(screen.getByText('agendaItemDetails')).toBeInTheDocument(); + expect(screen.getByTestId('createAgendaItemFormBtn')).toBeInTheDocument(); + expect( + screen.getByTestId('createAgendaItemModalCloseBtn'), + ).toBeInTheDocument(); + }); + + test('tests the condition for formState', async () => { + const mockFormState = { + title: 'Test Title', + description: 'Test Description', + duration: '20', + attachments: ['Test Attachment'], + urls: ['https://example.com'], + agendaItemCategoryIds: ['1'], + }; + render( + + + + + + + + + + + , + ); + + fireEvent.change(screen.getByLabelText('title'), { + target: { value: 'New title' }, + }); + + fireEvent.change(screen.getByLabelText('description'), { + target: { value: 'New description' }, + }); + + fireEvent.change(screen.getByLabelText('duration'), { + target: { value: '30' }, + }); + + fireEvent.click(screen.getByTestId('deleteUrl')); + fireEvent.click(screen.getByTestId('deleteAttachment')); + + expect(mockSetFormState).toHaveBeenCalledWith({ + ...mockFormState, + title: 'New title', + }); + expect(mockSetFormState).toHaveBeenCalledWith({ + ...mockFormState, + description: 'New description', + }); + + expect(mockSetFormState).toHaveBeenCalledWith({ + ...mockFormState, + duration: '30', + }); + + await waitFor(() => { + expect(mockSetFormState).toHaveBeenCalledWith({ + ...mockFormState, + urls: [], + }); + }); + + await waitFor(() => { + expect(mockSetFormState).toHaveBeenCalledWith({ + ...mockFormState, + attachments: [], + }); + }); + }); + test('handleAddUrl correctly adds valid URL', async () => { + render( + + + + + + + + + , + ); + + const urlInput = screen.getByTestId('urlInput'); + const linkBtn = screen.getByTestId('linkBtn'); + + fireEvent.change(urlInput, { target: { value: 'https://example.com' } }); + fireEvent.click(linkBtn); + + await waitFor(() => { + expect(mockSetFormState).toHaveBeenCalledWith({ + ...mockFormState, + urls: [...mockFormState.urls, 'https://example.com'], + }); + }); + }); + + test('shows error toast for invalid URL', async () => { + render( + + + + + + + + + + + , + ); + + const urlInput = screen.getByTestId('urlInput'); + const linkBtn = screen.getByTestId('linkBtn'); + + fireEvent.change(urlInput, { target: { value: 'invalid-url' } }); + fireEvent.click(linkBtn); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalledWith('invalidUrl'); + }); + }); + + test('shows error toast for file size exceeding limit', async () => { + render( + + + + + + + + + + + , + ); + + const fileInput = screen.getByTestId('attachment'); + const largeFile = new File( + ['a'.repeat(11 * 1024 * 1024)], + 'large-file.jpg', + ); // 11 MB file + + Object.defineProperty(fileInput, 'files', { + value: [largeFile], + }); + + fireEvent.change(fileInput); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalledWith('fileSizeExceedsLimit'); + }); + }); + + test('adds files correctly when within size limit', async () => { + mockedConvertToBase64.mockResolvedValue('base64-file'); + + render( + + + + + + + + + + + , + ); + + const fileInput = screen.getByTestId('attachment'); + const smallFile = new File(['small-file-content'], 'small-file.jpg'); // Small file + + Object.defineProperty(fileInput, 'files', { + value: [smallFile], + }); + + fireEvent.change(fileInput); + + await waitFor(() => { + expect(mockSetFormState).toHaveBeenCalledWith({ + ...mockFormState, + attachments: [...mockFormState.attachments, 'base64-file'], + }); + }); + }); + test('renders autocomplete and selects categories correctly', async () => { + render( + + + + + + + + + + + , + ); + + const autocomplete = screen.getByTestId('categorySelect'); + expect(autocomplete).toBeInTheDocument(); + + const input = within(autocomplete).getByRole('combobox'); + fireEvent.mouseDown(input); + + const options = await screen.getAllByRole('option'); + expect(options).toHaveLength(mockAgendaItemCategories.length); + + fireEvent.click(options[0]); + fireEvent.click(options[1]); + }); +});
    row._id} - components={{ - NoRowsOverlay: () => ( + slots={{ + noRowsOverlay: () => ( button { + padding-bottom: 0; +} + +.createChat { + background-color: white; + border: none; +} + +.opendrawer { + position: fixed; + display: flex; + align-items: center; + justify-content: center; + top: 0; + left: 0; + width: 40px; + height: 100vh; + z-index: 9999; + background-color: rgba(245, 245, 245); + border: none; + border-radius: 0px; + margin-right: 20px; + color: black; +} + +.opendrawer:hover { + transition: background-color 0.5s ease; + background-color: var(--bs-primary); +} +.collapseSidebarButton:hover { + transition: background-color 0.5s ease; + background-color: var(--bs-primary); +} + +.customToggle { + padding: 0; + background: none; + border: none; + margin-right: 1rem; + --bs-btn-active-bg: none; +} +.customToggle svg { + color: black; +} + +.customToggle::after { + content: none; +} +.customToggle:hover, +.customToggle:focus, +.customToggle:active { + background: none; + border: none; +} +.customToggle svg { + color: black; +} + +@media (max-width: 1120px) { + .collapseSidebarButton { + width: calc(250px); + } +} + +@media (max-height: 650px) { + .collapseSidebarButton { + width: 250px; + height: 20px; + } + .opendrawer { + width: 30px; + } +} + +/* For tablets */ +@media (max-width: 820px) { + .containerHeight { + height: 100vh; + padding: 2rem; + } + + .contract, + .expand { + animation: none; + } + + .opendrawer { + width: 25px; + } + + .collapseSidebarButton { + width: 100%; + left: 0; + right: 0; + } +} + +.accordionBody { + height: calc(100vh / 2 - 2rem - 60px) !important; + overflow-y: scroll; } -.colorPrimary { - background: #31bb6b; +.accordionBody::-webkit-scrollbar { + display: none; } diff --git a/src/screens/UserPortal/Chat/Chat.test.tsx b/src/screens/UserPortal/Chat/Chat.test.tsx index b090266acf..bf41dcbe9b 100644 --- a/src/screens/UserPortal/Chat/Chat.test.tsx +++ b/src/screens/UserPortal/Chat/Chat.test.tsx @@ -1,71 +1,1724 @@ import React from 'react'; -import { act, render, screen } from '@testing-library/react'; +import { act, fireEvent, render, screen } from '@testing-library/react'; import { MockedProvider } from '@apollo/react-testing'; -import { I18nextProvider } from 'react-i18next'; +import { I18nextProvider, useTranslation } from 'react-i18next'; -import { ORGANIZATIONS_MEMBER_CONNECTION_LIST } from 'GraphQl/Queries/Queries'; +import { + DIRECT_CHATS_LIST, + USERS_CONNECTION_LIST, + USER_JOINED_ORGANIZATIONS, +} from 'GraphQl/Queries/Queries'; import { BrowserRouter } from 'react-router-dom'; import { Provider } from 'react-redux'; import { store } from 'state/store'; import i18nForTest from 'utils/i18nForTest'; -import { StaticMockLink } from 'utils/StaticMockLink'; import Chat from './Chat'; -import * as getOrganizationId from 'utils/getOrganizationId'; -import userEvent from '@testing-library/user-event'; +import { + MESSAGE_SENT_TO_DIRECT_CHAT, + MESSAGE_SENT_TO_GROUP_CHAT, +} from 'GraphQl/Mutations/OrganizationMutations'; +import { + DIRECT_CHAT_BY_ID, + GROUP_CHAT_BY_ID, + GROUP_CHAT_LIST, +} from 'GraphQl/Queries/PlugInQueries'; +import useLocalStorage from 'utils/useLocalstorage'; + +const { setItem } = useLocalStorage(); const MOCKS = [ { request: { - query: ORGANIZATIONS_MEMBER_CONNECTION_LIST, + query: GROUP_CHAT_LIST, + variables: { + id: null, + }, + }, + result: { + data: { + groupChatsByUserId: [ + { + _id: '1', + creator: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + }, + messages: { + _id: '1', + createdAt: '', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@email.com', + }, + }, + title: 'Test GroupChat', + organization: { + _id: '1', + name: 'Test Org', + }, + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@email.com', + image: 'img', + }, + ], + }, + { + _id: '2', + creator: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + }, + messages: { + _id: '1', + createdAt: '', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@email.com', + }, + }, + title: 'Test GroupChat', + organization: { + _id: '1', + name: 'Test Org', + }, + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@email.com', + image: 'img', + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: GROUP_CHAT_LIST, + variables: { + id: '1', + }, + }, + result: { + data: { + groupChatsByUserId: [ + { + _id: '1', + creator: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + }, + messages: { + _id: '1', + createdAt: '', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@email.com', + }, + }, + title: 'Test GroupChat', + organization: { + _id: '1', + name: 'Test Org', + }, + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@email.com', + image: 'img', + }, + ], + }, + { + _id: '2', + creator: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + }, + messages: { + _id: '1', + createdAt: '', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@email.com', + }, + }, + title: 'Test GroupChat', + organization: { + _id: '1', + name: 'Test Org', + }, + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@email.com', + image: 'img', + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: GROUP_CHAT_LIST, + variables: { + id: null, + }, + }, + result: { + data: { + groupChatsByUserId: [ + { + _id: '1', + creator: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + }, + messages: { + _id: '1', + createdAt: '', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@email.com', + }, + }, + title: 'Test GroupChat', + organization: { + _id: '1', + name: 'Test Org', + }, + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@email.com', + image: 'img', + }, + ], + }, + { + _id: '1', + creator: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + }, + messages: { + _id: '1', + createdAt: '', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@email.com', + }, + }, + title: 'Test GroupChat', + organization: { + _id: '1', + name: 'Test Org', + }, + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@email.com', + image: 'img', + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: DIRECT_CHATS_LIST, + variables: { + id: null, + }, + }, + result: { + data: { + directChatsByUserID: [ + { + _id: '666c88dd92e995354d98527c', + creator: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + __typename: 'User', + }, + messages: [ + { + _id: '668930bae43ce54e6e302cf1', + createdAt: '2024-07-06T11:55:38.933Z', + messageContent: 'hJnkank', + receiver: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + __typename: 'User', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + __typename: 'User', + }, + __typename: 'DirectChatMessage', + }, + ], + organization: { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + __typename: 'Organization', + }, + users: [ + { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + image: null, + __typename: 'User', + }, + { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + image: null, + __typename: 'User', + }, + ], + __typename: 'DirectChat', + }, + { + _id: '666f09c892e995354d98a5ee', + creator: { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + __typename: 'User', + }, + messages: [ + { + _id: '6676932692e995354d98ab7f', + createdAt: '2024-06-22T09:02:30.776Z', + messageContent: 'hii', + receiver: { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + __typename: 'User', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + __typename: 'User', + }, + __typename: 'DirectChatMessage', + }, + ], + organization: { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + __typename: 'Organization', + }, + users: [ + { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + image: null, + __typename: 'User', + }, + { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + image: null, + __typename: 'User', + }, + ], + __typename: 'DirectChat', + }, + ], + }, + }, + }, + { + request: { + query: DIRECT_CHATS_LIST, + variables: { + id: '1', + }, + }, + result: { + data: { + directChatsByUserID: [ + { + _id: '666c88dd92e995354d98527c', + creator: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + __typename: 'User', + }, + messages: [ + { + _id: '668930bae43ce54e6e302cf1', + createdAt: '2024-07-06T11:55:38.933Z', + messageContent: 'hJnkank', + receiver: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + __typename: 'User', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + __typename: 'User', + }, + __typename: 'DirectChatMessage', + }, + ], + organization: { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + __typename: 'Organization', + }, + users: [ + { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + image: null, + __typename: 'User', + }, + { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + image: null, + __typename: 'User', + }, + ], + __typename: 'DirectChat', + }, + { + _id: '666f09c892e995354d98a5ee', + creator: { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + __typename: 'User', + }, + messages: [ + { + _id: '6676932692e995354d98ab7f', + createdAt: '2024-06-22T09:02:30.776Z', + messageContent: 'hii', + receiver: { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + __typename: 'User', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + __typename: 'User', + }, + __typename: 'DirectChatMessage', + }, + ], + organization: { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + __typename: 'Organization', + }, + users: [ + { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + image: null, + __typename: 'User', + }, + { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + image: null, + __typename: 'User', + }, + ], + __typename: 'DirectChat', + }, + ], + }, + }, + }, + { + request: { + query: DIRECT_CHATS_LIST, + variables: { + id: '', + }, + }, + result: { + data: { + directChatsByUserID: [ + { + _id: '666c88dd92e995354d98527c', + creator: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + __typename: 'User', + }, + messages: [ + { + _id: '668930bae43ce54e6e302cf1', + createdAt: '2024-07-06T11:55:38.933Z', + messageContent: 'hJnkank', + receiver: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + __typename: 'User', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + __typename: 'User', + }, + __typename: 'DirectChatMessage', + }, + ], + organization: { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + __typename: 'Organization', + }, + users: [ + { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + image: null, + __typename: 'User', + }, + { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + email: 'testadmin1@example.com', + image: null, + __typename: 'User', + }, + ], + __typename: 'DirectChat', + }, + { + _id: '666f09c892e995354d98a5ee', + creator: { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + __typename: 'User', + }, + messages: [ + { + _id: '6676932692e995354d98ab7f', + createdAt: '2024-06-22T09:02:30.776Z', + messageContent: 'hii', + receiver: { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + __typename: 'User', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + __typename: 'User', + }, + __typename: 'DirectChatMessage', + }, + ], + organization: { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + __typename: 'Organization', + }, + users: [ + { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'testsuperadmin@example.com', + image: null, + __typename: 'User', + }, + { + _id: '67378abd85008f171cf2990d', + firstName: 'Darcy', + lastName: 'Wilf', + email: 'testadmin3@example.com', + image: null, + __typename: 'User', + }, + ], + __typename: 'DirectChat', + }, + ], + }, + }, + }, +]; + +const USER_JOINED_ORG_MOCK = [ + { + request: { + query: USER_JOINED_ORGANIZATIONS, + variables: { + id: '1', + }, + }, + result: { + data: { + users: [ + { + user: { + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + name: 'Any Organization', + image: '', + description: 'New Desc', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + createdAt: '1234567890', + userRegistrationRequired: true, + creator: { + __typename: 'User', + firstName: 'John', + lastName: 'Doe', + }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + }, + ], + }, + }, + ], + }, + }, + }, + { + request: { + query: USER_JOINED_ORGANIZATIONS, + variables: { + id: '1', + }, + }, + result: { + data: { + users: [ + { + user: { + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + name: 'Any Organization', + image: '', + description: 'New Desc', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + createdAt: '1234567890', + userRegistrationRequired: true, + creator: { + __typename: 'User', + firstName: 'John', + lastName: 'Doe', + }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + }, + ], + }, + }, + ], + }, + }, + }, + { + request: { + query: USER_JOINED_ORGANIZATIONS, + variables: { + id: '1', + }, + }, + result: { + data: { + users: [ + { + user: { + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + name: 'Any Organization', + image: '', + description: 'New Desc', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + createdAt: '1234567890', + userRegistrationRequired: true, + creator: { + __typename: 'User', + firstName: 'John', + lastName: 'Doe', + }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + }, + ], + }, + }, + ], + }, + }, + }, + { + request: { + query: USER_JOINED_ORGANIZATIONS, + variables: { + id: null, + }, + }, + result: { + data: { + users: [ + { + user: { + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + name: 'Any Organization', + image: '', + description: 'New Desc', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + createdAt: '1234567890', + userRegistrationRequired: true, + creator: { + __typename: 'User', + firstName: 'John', + lastName: 'Doe', + }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + }, + ], + }, + }, + ], + }, + }, + }, + { + request: { + query: USER_JOINED_ORGANIZATIONS, + variables: { + id: null, + }, + }, + result: { + data: { + users: [ + { + user: { + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + name: 'Any Organization', + image: '', + description: 'New Desc', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + createdAt: '1234567890', + userRegistrationRequired: true, + creator: { + __typename: 'User', + firstName: 'John', + lastName: 'Doe', + }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + }, + ], + }, + }, + ], + }, + }, + }, + { + request: { + query: USER_JOINED_ORGANIZATIONS, + variables: { + id: null, + }, + }, + result: { + data: { + users: [ + { + user: { + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + name: 'Any Organization', + image: '', + description: 'New Desc', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + createdAt: '1234567890', + userRegistrationRequired: true, + creator: { + __typename: 'User', + firstName: 'John', + lastName: 'Doe', + }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + }, + ], + }, + }, + ], + }, + }, + }, +]; + +const UserConnectionListMock = [ + { + request: { + query: USERS_CONNECTION_LIST, variables: { - orgId: '', firstName_contains: '', + lastName_contains: '', }, }, result: { data: { - organizationsMemberConnection: { - edges: [ - { - _id: '64001660a711c62d5b4076a2', - firstName: 'Noble', - lastName: 'Mittal', + users: [ + { + user: { + firstName: 'Deanne', + lastName: 'Marks', image: null, - email: 'noble1@gmail.com', - createdAt: '2023-03-02T03:22:08.101Z', + _id: '6589389d2caa9d8d69087487', + email: 'testuser8@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + organizationsBlockedBy: [], + joinedOrganizations: [ + { + _id: '6537904485008f171cf29924', + name: 'Unity Foundation', + image: null, + address: { + city: 'Queens', + countryCode: 'US', + dependentLocality: 'Some Dependent Locality', + line1: '123 Coffee Street', + line2: 'Apartment 501', + postalCode: '11427', + sortingCode: 'ABC-133', + state: 'NYC', + __typename: 'Address', + }, + createdAt: '2023-04-13T05:16:52.827Z', + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + __typename: 'Organization', + }, + { + _id: '6637904485008f171cf29924', + name: 'Unity Foundation', + image: null, + address: { + city: 'Staten Island', + countryCode: 'US', + dependentLocality: 'Some Dependent Locality', + line1: '123 church Street', + line2: 'Apartment 499', + postalCode: '10301', + sortingCode: 'ABC-122', + state: 'NYC', + __typename: 'Address', + }, + createdAt: '2023-04-13T05:16:52.827Z', + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + __typename: 'Organization', + }, + { + _id: '6737904485008f171cf29924', + name: 'Unity Foundation', + image: null, + address: { + city: 'Brooklyn', + countryCode: 'US', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Main Street', + line2: 'Apt 456', + postalCode: '10004', + sortingCode: 'ABC-789', + state: 'NY', + __typename: 'Address', + }, + createdAt: '2023-04-13T05:16:52.827Z', + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + __typename: 'Organization', + }, + { + _id: '6437904485008f171cf29924', + name: 'Unity Foundation', + image: null, + address: { + city: 'Bronx', + countryCode: 'US', + dependentLocality: 'Some Dependent Locality', + line1: '123 Random Street', + line2: 'Apartment 456', + postalCode: '10451', + sortingCode: 'ABC-123', + state: 'NYC', + __typename: 'Address', + }, + createdAt: '2023-04-13T05:16:52.827Z', + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + __typename: 'Organization', + }, + ], + __typename: 'User', + }, + appUserProfile: { + _id: '64378abd85308f171cf2993d', + adminFor: [], + isSuperAdmin: false, + createdOrganizations: [], + createdEvents: [], + eventAdmin: [], + __typename: 'AppUserProfile', + }, + __typename: 'UserData', + }, + ], + }, + }, + }, + { + request: { + query: USERS_CONNECTION_LIST, + variables: { + firstName_contains: '', + lastName_contains: '', + }, + }, + result: { + data: { + users: { + user: [ + { + firstName: 'Disha', + lastName: 'Talreja', + image: 'img', + _id: '1', + email: 'disha@email.com', + createdAt: '', + appUserProfile: { + _id: '12', + isSuperAdmin: 'false', + createdOrganizations: { + _id: '345678', + }, + createdEvents: { + _id: '34567890', + }, + }, + organizationsBlockedBy: [], + joinedOrganizations: [], + }, + { + firstName: 'Disha', + lastName: 'Talreja', + image: 'img', + _id: '1', + email: 'disha@email.com', + createdAt: '', + appUserProfile: { + _id: '12', + isSuperAdmin: 'false', + createdOrganizations: { + _id: '345678', + }, + createdEvents: { + _id: '34567890', + }, + }, + organizationsBlockedBy: [], + joinedOrganizations: [], }, { - _id: '64001660a711c62d5b4076a3', - firstName: 'Noble', - lastName: 'Mittal', - image: 'mockImage', - email: 'noble@gmail.com', - createdAt: '2023-03-02T03:22:08.101Z', + firstName: 'Disha', + lastName: 'Talreja', + image: 'img', + _id: '1', + email: 'disha@email.com', + createdAt: '', + appUserProfile: { + _id: '12', + isSuperAdmin: 'false', + createdOrganizations: { + _id: '345678', + }, + createdEvents: { + _id: '34567890', + }, + }, + organizationsBlockedBy: [], + joinedOrganizations: [], }, ], }, }, }, }, +]; + +const MESSAGE_SENT_TO_GROUP_CHAT_MOCK = [ + { + request: { + query: MESSAGE_SENT_TO_GROUP_CHAT, + variables: { + userId: null, + }, + }, + result: { + data: { + messageSentToGroupChat: { + _id: '668ec1f1364e03ac47a151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, + { + request: { + query: MESSAGE_SENT_TO_GROUP_CHAT, + variables: { + userId: '2', + }, + }, + result: { + data: { + messageSentToGroupChat: { + _id: '668ec1f1df364e03ac47a151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, + { + request: { + query: MESSAGE_SENT_TO_GROUP_CHAT, + variables: { + userId: '1', + }, + }, + result: { + data: { + messageSentToGroupChat: { + _id: '668ec1f13603ac4697a151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, +]; + +const MESSAGE_SENT_TO_DIRECT_CHAT_MOCK = [ + { + request: { + query: MESSAGE_SENT_TO_DIRECT_CHAT, + variables: { + userId: '1', + }, + }, + result: { + data: { + messageSentToDirectChat: { + _id: '668ec1f1364e03ac4697a151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + receiver: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + image: '', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, + { + request: { + query: MESSAGE_SENT_TO_DIRECT_CHAT, + variables: { + userId: '2', + }, + }, + result: { + data: { + messageSentToDirectChat: { + _id: '668ec1f1364e03ac4697vgfa151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + receiver: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + image: '', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, + { + request: { + query: MESSAGE_SENT_TO_DIRECT_CHAT, + variables: { + userId: null, + }, + }, + result: { + data: { + messageSentToDirectChat: { + _id: '6ec1f1364e03ac4697a151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + receiver: { + _id: '65378abd85008f171cf2990d', + firstName: 'Vyvyan', + lastName: 'Kerry', + image: '', + }, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, +]; + +const DIRECT_CHAT_BY_ID_QUERY_MOCK = [ { request: { - query: ORGANIZATIONS_MEMBER_CONNECTION_LIST, + query: DIRECT_CHAT_BY_ID, variables: { - orgId: '', - firstName_contains: 'j', + id: '1', }, }, result: { data: { - organizationsMemberConnection: { - edges: [ + directChatById: { + _id: '1', + createdAt: '2345678903456', + messages: [ { - _id: '64001660a711c62d5b4076a2', - firstName: 'John', - lastName: 'Cena', - image: null, - email: 'john@gmail.com', - createdAt: '2023-03-02T03:22:08.101Z', + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + receiver: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: DIRECT_CHAT_BY_ID, + variables: { + id: '1', + }, + }, + result: { + data: { + directChatById: { + _id: '1', + createdAt: '2345678903456', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + receiver: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: DIRECT_CHAT_BY_ID, + variables: { + id: '', + }, + }, + result: { + data: { + directChatById: { + _id: '1', + createdAt: '2345678903456', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + receiver: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: DIRECT_CHAT_BY_ID, + variables: { + id: '2', + }, + }, + result: { + data: { + directChatById: { + _id: '65844efc814dd4003db811c4', + createdAt: '2345678903456', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + receiver: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: DIRECT_CHAT_BY_ID, + variables: { + id: null, + }, + }, + result: { + data: { + directChatById: { + _id: '65844efc814dd4003db811c4', + createdAt: '2345678903456', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + receiver: { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', }, ], }, @@ -74,7 +1727,353 @@ const MOCKS = [ }, ]; -const link = new StaticMockLink(MOCKS, true); +const GROUP_CHAT_BY_ID_QUERY_MOCK = [ + { + request: { + query: GROUP_CHAT_BY_ID, + variables: { + id: '1', + }, + }, + result: { + data: { + groupChatById: { + _id: '65844efc814dd4003db811c4', + createdAt: '2345678903456', + title: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: GROUP_CHAT_BY_ID, + variables: { + id: '1', + }, + }, + result: { + data: { + groupChatById: { + _id: '65844efc814dd4003db811c4', + createdAt: '2345678903456', + title: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: GROUP_CHAT_BY_ID, + variables: { + id: '', + }, + }, + result: { + data: { + groupChatById: { + _id: '1', + createdAt: '2345678903456', + title: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: GROUP_CHAT_BY_ID, + variables: { + id: '2', + }, + }, + result: { + data: { + groupChatById: { + _id: '65844efc814dd4003db811c4', + createdAt: '2345678903456', + title: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + }, + }, + }, + { + request: { + query: GROUP_CHAT_BY_ID, + variables: { + id: null, + }, + }, + result: { + data: { + groupChatById: { + _id: '65844efc814dd4003db811c4', + createdAt: '2345678903456', + title: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + }, + }, + }, +]; + +const resizeWindow = (width: number): void => { + window.innerWidth = width; + fireEvent(window, new Event('resize')); +}; async function wait(ms = 100): Promise { await act(() => { @@ -84,8 +2083,8 @@ async function wait(ms = 100): Promise { }); } -describe('Testing People Screen [User Portal]', () => { - jest.mock('utils/getOrganizationId'); +describe('Testing Chat Screen [User Portal]', () => { + window.HTMLElement.prototype.scrollIntoView = jest.fn(); Object.defineProperty(window, 'matchMedia', { writable: true, @@ -101,15 +2100,19 @@ describe('Testing People Screen [User Portal]', () => { })), }); - const getOrganizationIdSpy = jest - .spyOn(getOrganizationId, 'default') - .mockImplementation(() => { - return ''; - }); - test('Screen should be rendered properly', async () => { + const mock = [ + ...USER_JOINED_ORG_MOCK, + ...GROUP_CHAT_BY_ID_QUERY_MOCK, + ...DIRECT_CHAT_BY_ID_QUERY_MOCK, + ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, + ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ...UserConnectionListMock, + ...MOCKS, + ]; + render( - + @@ -119,16 +2122,22 @@ describe('Testing People Screen [User Portal]', () => { , ); - await wait(); - - expect(getOrganizationIdSpy).toHaveBeenCalled(); - expect(screen.queryAllByText('Noble Mittal')).not.toBe([]); }); test('User is able to select a contact', async () => { + const mock = [ + ...USER_JOINED_ORG_MOCK, + ...GROUP_CHAT_BY_ID_QUERY_MOCK, + ...DIRECT_CHAT_BY_ID_QUERY_MOCK, + ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, + ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ...UserConnectionListMock, + ...MOCKS, + ]; + render( - + @@ -141,16 +2150,67 @@ describe('Testing People Screen [User Portal]', () => { await wait(); - userEvent.click(screen.getByText('noble1@gmail.com')); + expect(await screen.findByText('Messages')).toBeInTheDocument(); + const contactCards = await screen.findAllByTestId('chatContact'); + console.log(contactCards); + expect(contactCards[0]).toBeInTheDocument(); + act(() => { + fireEvent.click(contactCards[0]); + }); + }); + + test('Test create new direct chat', async () => { + const mock = [ + ...USER_JOINED_ORG_MOCK, + ...GROUP_CHAT_BY_ID_QUERY_MOCK, + ...DIRECT_CHAT_BY_ID_QUERY_MOCK, + ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, + ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ...UserConnectionListMock, + ...MOCKS, + ]; + render( + + + + + + + + + , + ); + await wait(); - expect(getOrganizationIdSpy).toHaveBeenCalled(); - expect(screen.queryAllByText('Noble Mittal')).not.toBe([]); + const dropdown = await screen.findByTestId('dropdown'); + expect(dropdown).toBeInTheDocument(); + fireEvent.click(dropdown); + const newDirectChatBtn = await screen.findByTestId('newDirectChat'); + expect(newDirectChatBtn).toBeInTheDocument(); + fireEvent.click(newDirectChatBtn); + + const closeButton = screen.getByRole('button', { name: /close/i }); + expect(closeButton).toBeInTheDocument(); + + const submitBtn = await screen.findByTestId('submitBtn'); + expect(submitBtn).toBeInTheDocument(); + + fireEvent.click(closeButton); }); - test('Search functionality works as expected by pressing enter key', async () => { + test('Test create new group chat', async () => { + const mock = [ + ...USER_JOINED_ORG_MOCK, + ...GROUP_CHAT_BY_ID_QUERY_MOCK, + ...DIRECT_CHAT_BY_ID_QUERY_MOCK, + ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, + ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ...UserConnectionListMock, + ...MOCKS, + ]; render( - + @@ -163,17 +2223,33 @@ describe('Testing People Screen [User Portal]', () => { await wait(); - userEvent.type(screen.getByTestId('searchInput'), 'j{enter}'); - await wait(); + const dropdown = await screen.findByTestId('dropdown'); + expect(dropdown).toBeInTheDocument(); + fireEvent.click(dropdown); + + const newGroupChatBtn = await screen.findByTestId('newGroupChat'); + expect(newGroupChatBtn).toBeInTheDocument(); - expect(getOrganizationIdSpy).toHaveBeenCalled(); - expect(screen.queryByText('John Cena')).toBeInTheDocument(); - expect(screen.queryByText('Noble Mittal')).not.toBeInTheDocument(); + fireEvent.click(newGroupChatBtn); + const closeButton = screen.getByRole('button', { name: /close/i }); + expect(closeButton).toBeInTheDocument(); + fireEvent.click(closeButton); }); - test('Search functionality works as expected by clicking search Btn', async () => { + test('sidebar', async () => { + const mock = [ + ...USER_JOINED_ORG_MOCK, + ...GROUP_CHAT_BY_ID_QUERY_MOCK, + ...DIRECT_CHAT_BY_ID_QUERY_MOCK, + ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, + ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ...UserConnectionListMock, + ...MOCKS, + ]; + setItem('userId', '1'); + render( - + @@ -185,13 +2261,44 @@ describe('Testing People Screen [User Portal]', () => { ); await wait(); - const searchBtn = screen.getByTestId('searchBtn'); - userEvent.type(screen.getByTestId('searchInput'), 'j'); - userEvent.click(searchBtn); + + const closeMenubtn = screen.getByTestId('closeMenu'); + expect(closeMenubtn).toBeInTheDocument(); + closeMenubtn.click(); + const openMenuBtn = screen.getByTestId('openMenu'); + expect(openMenuBtn).toBeInTheDocument(); + openMenuBtn.click(); + }); + + test('Testing sidebar when the screen size is less than or equal to 820px', async () => { + setItem('userId', '1'); + const mock = [ + ...USER_JOINED_ORG_MOCK, + ...GROUP_CHAT_BY_ID_QUERY_MOCK, + ...DIRECT_CHAT_BY_ID_QUERY_MOCK, + ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, + ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ...UserConnectionListMock, + ...MOCKS, + ]; + resizeWindow(800); + render( + + + + + + + + + , + ); await wait(); + expect(screen.getByText('My Organizations')).toBeInTheDocument(); + expect(screen.getByText('Talawa User Portal')).toBeInTheDocument(); + + const chatBtn = screen.getByTestId('chatBtn'); - expect(getOrganizationIdSpy).toHaveBeenCalled(); - expect(screen.queryByText('John Cena')).toBeInTheDocument(); - expect(screen.queryByText('Noble Mittal')).not.toBeInTheDocument(); + chatBtn.click(); }); }); diff --git a/src/screens/UserPortal/Chat/Chat.tsx b/src/screens/UserPortal/Chat/Chat.tsx index ee6a6c04f1..2cc14eab58 100644 --- a/src/screens/UserPortal/Chat/Chat.tsx +++ b/src/screens/UserPortal/Chat/Chat.tsx @@ -1,150 +1,288 @@ -import React from 'react'; -// import OrganizationNavbar from 'components/UserPortal/OrganizationNavbar/OrganizationNavbar'; -import { ORGANIZATIONS_MEMBER_CONNECTION_LIST } from 'GraphQl/Queries/Queries'; +import React, { useEffect, useState } from 'react'; +import { DIRECT_CHATS_LIST } from 'GraphQl/Queries/Queries'; import { useQuery } from '@apollo/client'; -import styles from './Chat.module.css'; -import getOrganizationId from 'utils/getOrganizationId'; import { useTranslation } from 'react-i18next'; -import { Form, InputGroup } from 'react-bootstrap'; -import { SearchOutlined } from '@mui/icons-material'; +import { Button, Dropdown } from 'react-bootstrap'; +import { SearchOutlined, Search } from '@mui/icons-material'; import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; import ContactCard from 'components/UserPortal/ContactCard/ContactCard'; import ChatRoom from 'components/UserPortal/ChatRoom/ChatRoom'; +import useLocalStorage from 'utils/useLocalstorage'; +import { ReactComponent as NewChat } from 'assets/svgs/newChat.svg'; +import Accordion from 'react-bootstrap/Accordion'; +import styles from './Chat.module.css'; +import UserSidebar from 'components/UserPortal/UserSidebar/UserSidebar'; +import { GROUP_CHAT_LIST } from 'GraphQl/Queries/PlugInQueries'; +import CreateGroupChat from '../../../components/UserPortal/CreateGroupChat/CreateGroupChat'; +import CreateDirectChat from 'components/UserPortal/CreateDirectChat/CreateDirectChat'; interface InterfaceContactCardProps { id: string; - firstName: string; - lastName: string; - email: string; + title: string; + subtitle: string; image: string; selectedContact: string; setSelectedContact: React.Dispatch>; - setSelectedContactName: React.Dispatch>; -} - -interface InterfaceChatRoomProps { - selectedContact: string; + type: string; + setSelectedChatType: React.Dispatch>; } export default function chat(): JSX.Element { const { t } = useTranslation('translation', { - keyPrefix: 'userChat', + keyPrefix: 'chat', }); const { t: tCommon } = useTranslation('common'); - const organizationId = getOrganizationId(location.href); - const [selectedContact, setSelectedContact] = React.useState(''); - const [selectedContactName, setSelectedContactName] = React.useState(''); - const [contacts, setContacts] = React.useState([]); - const [filterName, setFilterName] = React.useState(''); + const [hideDrawer, setHideDrawer] = useState(null); + + const handleResize = (): void => { + if (window.innerWidth <= 820) { + setHideDrawer(!hideDrawer); + } + }; + + useEffect(() => { + handleResize(); + window.addEventListener('resize', handleResize); + return () => { + window.removeEventListener('resize', handleResize); + }; + }, []); + + const [selectedContact, setSelectedContact] = useState(''); + const [contacts, setContacts] = useState([]); + const [groupChats, setGroupChats] = useState([]); + const [selectChatType, setSelectedChatType] = useState(''); + const { getItem } = useLocalStorage(); + const userId = getItem('userId'); + + const [createDirectChatModalisOpen, setCreateDirectChatModalisOpen] = + useState(false); + + function openCreateDirectChatModal(): void { + setCreateDirectChatModalisOpen(true); + } - const chatRoomProps: InterfaceChatRoomProps = { - selectedContact, + const toggleCreateDirectChatModal = /* istanbul ignore next */ (): void => + setCreateDirectChatModalisOpen(!createDirectChatModalisOpen); + + const [createGroupChatModalisOpen, setCreateGroupChatModalisOpen] = + useState(false); + + function openCreateGroupChatModal(): void { + setCreateGroupChatModalisOpen(true); + } + + const toggleCreateGroupChatModal = /* istanbul ignore next */ (): void => { + setCreateGroupChatModalisOpen(!createGroupChatModalisOpen); }; const { data: contactData, loading: contactLoading, refetch: contactRefetch, - } = useQuery(ORGANIZATIONS_MEMBER_CONNECTION_LIST, { + } = useQuery(DIRECT_CHATS_LIST, { variables: { - orgId: organizationId, - firstName_contains: filterName, + id: userId, }, }); - const handleSearch = (value: string): void => { - setFilterName(value); + const { + data: groupChatList, + loading: groupChatListLoading, + refetch: groupChatListRefetch, + } = useQuery(GROUP_CHAT_LIST, { + variables: { + id: userId, + }, + }); - contactRefetch({ - firstName_contains: value, - }); - }; - const handleSearchByEnter = ( - e: React.KeyboardEvent, - ): void => { - if (e.key === 'Enter') { - const { value } = e.currentTarget; - handleSearch(value); - } - }; - const handleSearchByBtnClick = (): void => { - const value = - (document.getElementById('searchChats') as HTMLInputElement)?.value || ''; - handleSearch(value); - }; + // const handleSearch = (value: string): void => { + // setFilterName(value); + + // contactRefetch(); + // }; + // const handleSearchByEnter = (e: any): void => { + // if (e.key === 'Enter') { + // const { value } = e.target; + // handleSearch(value); + // } + // }; + // const handleSearchByBtnClick = (): void => { + // const value = + // (document.getElementById('searchChats') as HTMLInputElement)?.value || ''; + // handleSearch(value); + // }; React.useEffect(() => { if (contactData) { - setContacts(contactData.organizationsMemberConnection.edges); + setContacts(contactData.directChatsByUserID); } }, [contactData]); + React.useEffect(() => { + if (groupChatList) { + setGroupChats(groupChatList.groupChatsByUserId); + } + }, [groupChatList]); + return ( <> - {/* */} + {hideDrawer ? ( + + ) : ( + + )} +
    -
    +
    -

    - {t('contacts')} -

    - - - Messages + + - - - + + + + + New Chat + + + New Group Chat + + + Starred Messages + + +
    - {contactLoading ? ( + {contactLoading || groupChatListLoading ? (
    Loading...
    ) : ( - contacts.map( - (contact: InterfaceContactCardProps, index: number) => { - const cardProps: InterfaceContactCardProps = { - id: contact.id, - firstName: contact.firstName, - lastName: contact.lastName, - email: contact.email, - image: contact.image, - setSelectedContactName, - selectedContact, - setSelectedContact, - }; - return ; - }, - ) +
    + + {!!contacts.length && ( + + + DIRECT CHATS + + + {contacts.map((contact: any) => { + const cardProps: InterfaceContactCardProps = { + id: contact._id, + title: + contact.users[0]?._id === userId + ? `${contact.users[1]?.firstName} ${contact.users[1]?.lastName}` + : `${contact.users[0]?.firstName} ${contact.users[0]?.lastName}`, + subtitle: userId + ? contact.users[1]?.email + : contact.users[0]?.email, + image: userId + ? contact.users[1]?.image + : contact.users[0]?.image, + setSelectedContact, + selectedContact, + type: 'direct', + setSelectedChatType, + }; + return ( + + ); + })} + + + )} + {!!groupChats.length && ( + + + GROUP CHATS + + + {groupChats.map((chat: any) => { + const cardProps: InterfaceContactCardProps = { + id: chat._id, + title: chat.title, + subtitle: `${chat.users.length} ${chat.users.length > 1 ? 'members' : 'member'}`, + image: '', + setSelectedContact, + selectedContact, + type: 'group', + setSelectedChatType, + }; + return ( + + ); + })} + + + )} + +
    )}
    -
    -
    - {selectedContact ? selectedContactName : t('chat')} -
    - +
    +
    + {createGroupChatModalisOpen && ( + + )} + {createDirectChatModalisOpen && ( + + )} ); } diff --git a/src/screens/UserPortal/Organizations/Organizations.module.css b/src/screens/UserPortal/Organizations/Organizations.module.css index 4cd9bbbddc..27262932d5 100644 --- a/src/screens/UserPortal/Organizations/Organizations.module.css +++ b/src/screens/UserPortal/Organizations/Organizations.module.css @@ -11,7 +11,6 @@ } .mainContainer { - padding: 20px; max-height: 100%; overflow: auto; } @@ -63,7 +62,7 @@ height: 40px; bottom: 0; z-index: 9999; - width: calc(300px + 2rem); + width: calc(300px); background-color: rgba(245, 245, 245, 0.7); color: black; border: none; diff --git a/src/screens/UserPortal/Posts/Posts.test.tsx b/src/screens/UserPortal/Posts/Posts.test.tsx index 4c49b7ba04..da499403ea 100644 --- a/src/screens/UserPortal/Posts/Posts.test.tsx +++ b/src/screens/UserPortal/Posts/Posts.test.tsx @@ -5,7 +5,7 @@ import { act, render, screen, waitFor, within } from '@testing-library/react'; import { I18nextProvider } from 'react-i18next'; import userEvent from '@testing-library/user-event'; import { - ADVERTISEMENTS_GET, + ORGANIZATION_ADVERTISEMENT_LIST, ORGANIZATION_POST_LIST, } from 'GraphQl/Queries/Queries'; import { Provider } from 'react-redux'; @@ -137,67 +137,83 @@ const MOCKS = [ }, { request: { - query: ADVERTISEMENTS_GET, - variables: {}, + query: ORGANIZATION_ADVERTISEMENT_LIST, + variables: { id: 'orgId', first: 6 }, }, result: { data: { - advertisementsConnection: { - edges: [ - { - node: { - _id: '1234', - name: 'Ad 1', - type: 'Type 1', - organization: { - _id: 'orgId', + organizations: [ + { + _id: 'orgId', + advertisements: { + edges: [ + { + node: { + _id: '1234', + name: 'Ad 1', + type: 'Type 1', + organization: { + _id: 'orgId', + }, + mediaUrl: 'Link 1', + endDate: '2024-12-31', + startDate: '2022-01-01', + }, + cursor: '1234', }, - mediaUrl: 'Link 1', - endDate: '2024-12-31', - startDate: '2022-01-01', - }, - }, - { - node: { - _id: '2345', - name: 'Ad 2', - type: 'Type 1', - organization: { - _id: 'orgId', + { + node: { + _id: '2345', + name: 'Ad 2', + type: 'Type 1', + organization: { + _id: 'orgId', + }, + mediaUrl: 'Link 2', + endDate: '2024-09-31', + startDate: '2023-04-01', + }, + cursor: '1234', }, - mediaUrl: 'Link 2', - endDate: '2024-09-31', - startDate: '2023-04-01', - }, - }, - { - node: { - _id: '3456', - name: 'name3', - type: 'Type 2', - organization: { - _id: 'orgId', + { + node: { + _id: '3456', + name: 'name3', + type: 'Type 2', + organization: { + _id: 'orgId', + }, + mediaUrl: 'link3', + startDate: '2023-01-30', + endDate: '2023-12-31', + }, + cursor: '1234', }, - mediaUrl: 'link3', - startDate: '2023-01-30', - endDate: '2023-12-31', - }, - }, - { - node: { - _id: '4567', - name: 'name4', - type: 'Type 2', - organization: { - _id: 'orgId1', + { + node: { + _id: '4567', + name: 'name4', + type: 'Type 2', + organization: { + _id: 'orgId1', + }, + mediaUrl: 'link4', + startDate: '2023-01-30', + endDate: '2023-12-01', + }, + cursor: '1234', }, - mediaUrl: 'link4', - startDate: '2023-01-30', - endDate: '2023-12-01', + ], + pageInfo: { + startCursor: '6411e53835d7ba2344a78e21', + endCursor: '6411e54835d7ba2344a78e31', + hasNextPage: false, + hasPreviousPage: false, }, + totalCount: 2, }, - ], - }, + }, + ], }, }, }, diff --git a/src/screens/UserPortal/Posts/Posts.tsx b/src/screens/UserPortal/Posts/Posts.tsx index aaa5345f1c..e3d3d8556c 100644 --- a/src/screens/UserPortal/Posts/Posts.tsx +++ b/src/screens/UserPortal/Posts/Posts.tsx @@ -1,16 +1,15 @@ import { useQuery } from '@apollo/client'; import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; import SendIcon from '@mui/icons-material/Send'; -import ChevronRightIcon from '@mui/icons-material/ChevronRight'; -import ChevronLeftIcon from '@mui/icons-material/ChevronLeft'; import { - ADVERTISEMENTS_GET, + ORGANIZATION_ADVERTISEMENT_LIST, ORGANIZATION_POST_LIST, USER_DETAILS, } from 'GraphQl/Queries/Queries'; import PostCard from 'components/UserPortal/PostCard/PostCard'; import type { InterfacePostCard, + InterfaceQueryOrganizationAdvertisementListItem, InterfaceQueryUserListItem, } from 'utils/interfaces'; import PromotedPost from 'components/UserPortal/PromotedPost/PromotedPost'; @@ -23,7 +22,36 @@ import { Navigate, useParams } from 'react-router-dom'; import useLocalStorage from 'utils/useLocalstorage'; import styles from './Posts.module.css'; import convertToBase64 from 'utils/convertToBase64'; +import Carousel from 'react-multi-carousel'; +import 'react-multi-carousel/lib/styles.css'; + +const responsive = { + superLargeDesktop: { + breakpoint: { max: 4000, min: 3000 }, + items: 5, + }, + desktop: { + breakpoint: { max: 3000, min: 1024 }, + items: 3, + }, + tablet: { + breakpoint: { max: 1024, min: 600 }, + items: 2, + }, + mobile: { + breakpoint: { max: 600, min: 0 }, + items: 1, + }, +}; +type Ad = { + _id: string; + name: string; + type: 'BANNER' | 'MENU' | 'POPUP'; + mediaUrl: string; + endDate: string; // Assuming it's a string in the format 'yyyy-MM-dd' + startDate: string; // Assuming it's a string in the format 'yyyy-MM-dd' +}; interface InterfaceAdContent { _id: string; name: string; @@ -45,10 +73,6 @@ type AdvertisementsConnection = { }[]; }; -interface InterfaceAdConnection { - advertisementsConnection?: AdvertisementsConnection; -} - type InterfacePostComments = { creator: { _id: string; @@ -101,8 +125,7 @@ export default function home(): JSX.Element { const { getItem } = useLocalStorage(); const [posts, setPosts] = useState([]); const [pinnedPosts, setPinnedPosts] = useState([]); - const [adContent, setAdContent] = useState({}); - const [filteredAd, setFilteredAd] = useState([]); + const [showModal, setShowModal] = useState(false); const [postImg, setPostImg] = useState(''); const { orgId } = useParams(); @@ -111,10 +134,19 @@ export default function home(): JSX.Element { return ; } - const navbarProps = { - currentPage: 'home', - }; - const { data: promotedPostsData } = useQuery(ADVERTISEMENTS_GET); + const { + data: promotedPostsData, + }: { + data?: { + organizations: InterfaceQueryOrganizationAdvertisementListItem[]; + }; + refetch: () => void; + } = useQuery(ORGANIZATION_ADVERTISEMENT_LIST, { + variables: { + id: orgId, + first: 6, + }, + }); const { data, refetch, @@ -122,6 +154,8 @@ export default function home(): JSX.Element { } = useQuery(ORGANIZATION_POST_LIST, { variables: { id: orgId, first: 10 }, }); + + const [adContent, setAdContent] = useState([]); const userId: string | null = getItem('userId'); const { data: userData } = useQuery(USER_DETAILS, { @@ -137,15 +171,16 @@ export default function home(): JSX.Element { }, [data]); useEffect(() => { - if (promotedPostsData) { - setAdContent(promotedPostsData); + if (promotedPostsData && promotedPostsData.organizations) { + const ads: Ad[] = + promotedPostsData.organizations[0].advertisements?.edges.map( + (edge) => edge.node, + ) || []; + + setAdContent(ads); } }, [promotedPostsData]); - useEffect(() => { - setFilteredAd(filterAdContent(adContent, orgId)); - }, [adContent]); - useEffect(() => { setPinnedPosts( posts.filter(({ node }: { node: InterfacePostNode }) => { @@ -154,34 +189,6 @@ export default function home(): JSX.Element { ); }, [posts]); - const filterAdContent = ( - data: { - advertisementsConnection?: { - edges: { - node: InterfaceAdContent; - }[]; - }; - }, - currentOrgId: string, - currentDate: Date = new Date(), - ): InterfaceAdContent[] => { - const { advertisementsConnection } = data; - - if (advertisementsConnection && advertisementsConnection.edges) { - const { edges } = advertisementsConnection; - - return edges - .map((edge) => edge.node) - .filter( - (ad: InterfaceAdContent) => - ad.organization._id === currentOrgId && - new Date(ad.endDate) > currentDate, - ); - } - - return []; - }; - const getCardProps = (node: InterfacePostNode): InterfacePostCard => { const { creator, @@ -321,21 +328,18 @@ export default function home(): JSX.Element { >

    {t('feed')}

    {pinnedPosts.length > 0 && ( -
    -

    {t(`pinnedPosts`)}

    -
    - {pinnedPosts.map(({ node }: { node: InterfacePostNode }) => { - const cardProps = getCardProps(node); - return ; - })} -
    -
    + + {pinnedPosts.map(({ node }: { node: InterfacePostNode }) => { + const cardProps = getCardProps(node); + return ; + })} + )}
    - {filteredAd.length > 0 && ( + {adContent.length > 0 && (
    - {filteredAd.map((post: InterfaceAdContent) => ( + {adContent.map((post: Ad) => ( { userEvent.click(screen.getByTestId('updateUserBtn')); await wait(); }); + + test('Marital Status dropdown value verification', async () => { + render( + + + + + + + + + , + ); + + await wait(); + + // SINGLE + expect( + screen.queryByRole('option', { name: mockMaritalStatusEnum[0].label }), + ).toBeInTheDocument(); + + userEvent.selectOptions( + // Find the select element + screen.getByTestId('inputMaritalStatus'), + // Find and select the Single option + screen.getByRole('option', { name: mockMaritalStatusEnum[0].label }), + ); + + expect(screen.getByTestId('inputMaritalStatus')).toHaveValue( + mockMaritalStatusEnum[0].value, + ); + + // ENGAGED + expect( + screen.queryByRole('option', { name: mockMaritalStatusEnum[1].label }), + ).toBeInTheDocument(); + + userEvent.selectOptions( + // Find the select element + screen.getByTestId('inputMaritalStatus'), + // Find and select the Engaged option + screen.getByRole('option', { name: mockMaritalStatusEnum[1].label }), + ); + + expect(screen.getByTestId('inputMaritalStatus')).toHaveValue( + mockMaritalStatusEnum[1].value, + ); + + // MARRIED + expect( + screen.queryByRole('option', { name: mockMaritalStatusEnum[2].label }), + ).toBeInTheDocument(); + + userEvent.selectOptions( + // Find the select element + screen.getByTestId('inputMaritalStatus'), + // Find and select the Married option + screen.getByRole('option', { name: mockMaritalStatusEnum[2].label }), + ); + + expect(screen.getByTestId('inputMaritalStatus')).toHaveValue( + mockMaritalStatusEnum[2].value, + ); + + // DIVORCED + expect( + screen.queryByRole('option', { name: mockMaritalStatusEnum[3].label }), + ).toBeInTheDocument(); + + userEvent.selectOptions( + // Find the select element + screen.getByTestId('inputMaritalStatus'), + // Find and select the Divorced option + screen.getByRole('option', { name: mockMaritalStatusEnum[3].label }), + ); + + expect(screen.getByTestId('inputMaritalStatus')).toHaveValue( + mockMaritalStatusEnum[3].value, + ); + + // WIDOWED + expect( + screen.queryByRole('option', { name: mockMaritalStatusEnum[4].label }), + ).toBeInTheDocument(); + + userEvent.selectOptions( + // Find the select element + screen.getByTestId('inputMaritalStatus'), + // Find and select the Widowed option + screen.getByRole('option', { name: mockMaritalStatusEnum[4].label }), + ); + + expect(screen.getByTestId('inputMaritalStatus')).toHaveValue( + mockMaritalStatusEnum[4].value, + ); + + // SEPARATED + expect( + screen.queryByRole('option', { name: mockMaritalStatusEnum[5].label }), + ).toBeInTheDocument(); + + userEvent.selectOptions( + // Find the select element + screen.getByTestId('inputMaritalStatus'), + // Find and select the Separated option + screen.getByRole('option', { name: mockMaritalStatusEnum[5].label }), + ); + + expect(screen.getByTestId('inputMaritalStatus')).toHaveValue( + mockMaritalStatusEnum[5].value, + ); + }, 60000); }); diff --git a/src/screens/UserPortal/Settings/Settings.tsx b/src/screens/UserPortal/Settings/Settings.tsx index b1b4a0d0c6..9fb63cd8e1 100644 --- a/src/screens/UserPortal/Settings/Settings.tsx +++ b/src/screens/UserPortal/Settings/Settings.tsx @@ -21,6 +21,7 @@ import DeleteUser from 'components/UserProfileSettings/DeleteUser'; import OtherSettings from 'components/UserProfileSettings/OtherSettings'; import UserSidebar from 'components/UserPortal/UserSidebar/UserSidebar'; import ProfileDropdown from 'components/ProfileDropdown/ProfileDropdown'; +import { create } from 'domain'; export default function settings(): JSX.Element { const { t } = useTranslation('translation', { @@ -52,6 +53,7 @@ export default function settings(): JSX.Element { const [userDetails, setUserDetails] = React.useState({ firstName: '', lastName: '', + createdAt: '', gender: '', email: '', phoneNumber: '', @@ -78,7 +80,7 @@ export default function settings(): JSX.Element { }); /* istanbul ignore next */ if (data) { - toast.success('Your details have been updated.'); + toast.success(tCommon('updatedSuccessfully', { item: 'Profile' })); setTimeout(() => { window.location.reload(); }, 500); @@ -110,6 +112,7 @@ export default function settings(): JSX.Element { const { firstName, lastName, + createdAt, gender, phone, birthDate, @@ -123,6 +126,7 @@ export default function settings(): JSX.Element { ...userDetails, firstName: firstName || '', lastName: lastName || '', + createdAt: createdAt || '', gender: gender || '', phoneNumber: phone?.mobile || '', birthDate: birthDate || '', @@ -142,6 +146,7 @@ export default function settings(): JSX.Element { const { firstName, lastName, + createdAt, gender, email, phone, @@ -156,6 +161,7 @@ export default function settings(): JSX.Element { setUserDetails({ firstName, lastName, + createdAt, gender, email, phoneNumber: phone?.mobile || '', @@ -215,6 +221,7 @@ export default function settings(): JSX.Element { @@ -579,6 +586,7 @@ export default function settings(): JSX.Element { diff --git a/src/screens/Users/Users.test.tsx b/src/screens/Users/Users.test.tsx index 59e16a7878..f130ed1df9 100644 --- a/src/screens/Users/Users.test.tsx +++ b/src/screens/Users/Users.test.tsx @@ -15,13 +15,276 @@ import Users from './Users'; import { EMPTY_MOCKS, MOCKS, MOCKS2 } from './UsersMocks'; import useLocalStorage from 'utils/useLocalstorage'; +import { + USER_LIST, + ORGANIZATION_CONNECTION_LIST, +} from 'GraphQl/Queries/Queries'; + const { setItem, removeItem } = useLocalStorage(); +const MOCK_USERS = [ + { + user: { + _id: 'user1', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + createdAt: '20/06/2022', + registeredEvents: [], + membershipRequests: [], + organizationsBlockedBy: [ + { + _id: 'xyz', + name: 'ABC', + image: null, + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '20/06/2022', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + createdAt: '20/06/2022', + }, + }, + ], + joinedOrganizations: [ + { + _id: 'abc', + name: 'Joined Organization 1', + image: null, + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '20/06/2022', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + createdAt: '20/06/2022', + }, + }, + ], + }, + appUserProfile: { + _id: 'user1', + adminFor: [ + { + _id: '123', + }, + ], + isSuperAdmin: true, + createdOrganizations: [], + createdEvents: [], + eventAdmin: [], + }, + }, + { + user: { + _id: 'user2', + firstName: 'Jane', + lastName: 'Doe', + image: null, + email: 'john@example.com', + createdAt: '21/06/2022', + registeredEvents: [], + membershipRequests: [], + organizationsBlockedBy: [ + { + _id: '456', + name: 'ABC', + image: null, + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '21/06/2022', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + createdAt: '21/06/2022', + }, + }, + ], + joinedOrganizations: [ + { + _id: '123', + name: 'Palisadoes', + image: null, + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '21/06/2022', + creator: { + _id: '123', + firstName: 'John', + lastName: 'Doe', + image: null, + email: 'john@example.com', + createdAt: '21/06/2022', + }, + }, + ], + }, + appUserProfile: { + _id: 'user2', + adminFor: [ + { + _id: '123', + }, + ], + isSuperAdmin: false, + createdOrganizations: [], + createdEvents: [], + eventAdmin: [], + }, + }, + { + user: { + _id: 'user3', + firstName: 'Jack', + lastName: 'Smith', + image: null, + email: 'jack@example.com', + createdAt: '19/06/2022', + registeredEvents: [], + membershipRequests: [], + organizationsBlockedBy: [ + { + _id: 'xyz', + name: 'ABC', + image: null, + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '19/06/2022', + creator: { + _id: '123', + firstName: 'Jack', + lastName: 'Smith', + image: null, + email: 'jack@example.com', + createdAt: '19/06/2022', + }, + }, + ], + joinedOrganizations: [ + { + _id: 'abc', + name: 'Joined Organization 1', + image: null, + address: { + city: 'Kingston', + countryCode: 'JM', + dependentLocality: 'Sample Dependent Locality', + line1: '123 Jamaica Street', + line2: 'Apartment 456', + postalCode: 'JM12345', + sortingCode: 'ABC-123', + state: 'Kingston Parish', + }, + createdAt: '19/06/2022', + creator: { + _id: '123', + firstName: 'Jack', + lastName: 'Smith', + image: null, + email: 'jack@example.com', + createdAt: '19/06/2022', + }, + }, + ], + }, + appUserProfile: { + _id: 'user3', + adminFor: [], + isSuperAdmin: false, + createdOrganizations: [], + createdEvents: [], + eventAdmin: [], + }, + }, +]; + +const MOCKS_NEW = [ + { + request: { + query: USER_LIST, + variables: { + first: 12, + skip: 0, + firstName_contains: '', + lastName_contains: '', + order: 'createdAt_DESC', + }, + }, + result: { + data: { + users: MOCK_USERS, + }, + }, + }, + { + request: { + query: ORGANIZATION_CONNECTION_LIST, + }, + result: { + data: { + organizationsConnection: [], + }, + }, + }, +]; + const link = new StaticMockLink(MOCKS, true); const link2 = new StaticMockLink(EMPTY_MOCKS, true); const link3 = new StaticMockLink(MOCKS2, true); +const link5 = new StaticMockLink(MOCKS_NEW, true); -async function wait(ms = 100): Promise { +async function wait(ms = 1000): Promise { await act(() => { return new Promise((resolve) => { setTimeout(resolve, ms); @@ -132,6 +395,7 @@ describe('Testing Users screen', () => { userEvent.type(screen.getByTestId(/searchByName/i), search1); userEvent.click(searchBtn); await wait(); + expect(screen.queryByText(/not found/i)).not.toBeInTheDocument(); const search2 = 'Pete{backspace}{backspace}{backspace}{backspace}'; userEvent.type(screen.getByTestId(/searchByName/i), search2); @@ -152,24 +416,34 @@ describe('Testing Users screen', () => { }); test('testing search not found', async () => { - render( - - - - - - - - - , - ); + await act(async () => { + render( + + + + + + + + + , + ); - await wait(); + await wait(); - const search = 'hello{enter}'; - await act(() => - userEvent.type(screen.getByTestId(/searchByName/i), search), - ); + const searchBtn = screen.getByTestId('searchButton'); + + const searchInput = screen.getByTestId(/searchByName/i); + + // Clear the search input + userEvent.clear(searchInput); + + // Search for a name that doesn't exist + userEvent.type(screen.getByTestId(/searchByName/i), 'NonexistentName'); + userEvent.click(searchBtn); + + expect(screen.queryByText(/No User Found/i)).toBeInTheDocument(); + }); }); test('Testing User data is not present', async () => { @@ -230,42 +504,6 @@ describe('Testing Users screen', () => { ); }); - test('Testing sorting functionality', async () => { - await act(async () => { - render( - - - - - - - - - - , - ); - - await wait(); - - const searchInput = screen.getByTestId('sort'); - expect(searchInput).toBeInTheDocument(); - - const inputText = screen.getByTestId('sortUsers'); - - fireEvent.click(inputText); - const toggleText = screen.getByTestId('oldest'); - fireEvent.click(toggleText); - - expect(searchInput).toBeInTheDocument(); - - fireEvent.click(inputText); - const toggleTite = screen.getByTestId('newest'); - fireEvent.click(toggleTite); - - expect(searchInput).toBeInTheDocument(); - }); - }); - test('Testing filter functionality', async () => { await act(async () => { render( @@ -345,4 +583,132 @@ describe('Testing Users screen', () => { ); await wait(); }); + + test('should set hasMore to false if users length is less than perPageResult', async () => { + const link = new StaticMockLink(EMPTY_MOCKS, true); + + render( + + + + + + + + + + , + ); + + await wait(200); + + // Check if "No User Found" is displayed + expect(screen.getByText(/No User Found/i)).toBeInTheDocument(); + }); + + test('should filter users correctly', async () => { + await act(async () => { + render( + + + + + + + + + + , + ); + + await wait(); + + const filterButton = screen.getByTestId('filterUsers'); + fireEvent.click(filterButton); + + const filterAdmin = screen.getByTestId('admin'); + fireEvent.click(filterAdmin); + await wait(); + expect(screen.getByText('Jane Doe')).toBeInTheDocument(); + + fireEvent.click(filterButton); + const filterSuperAdmin = screen.getByTestId('superAdmin'); + fireEvent.click(filterSuperAdmin); + await wait(); + expect(screen.getByText('John Doe')).toBeInTheDocument(); + + fireEvent.click(filterButton); + const filterUser = screen.getByTestId('user'); + fireEvent.click(filterUser); + await wait(); + expect(screen.getByText('Jack Smith')).toBeInTheDocument(); + + fireEvent.click(filterButton); + const filterCancel = screen.getByTestId('cancel'); + fireEvent.click(filterCancel); + await wait(); + expect(screen.getByText('John Doe')).toBeInTheDocument(); + expect(screen.getByText('Jane Doe')).toBeInTheDocument(); + expect(screen.getByText('Jack Smith')).toBeInTheDocument(); + }); + }); + + test('Users should be sorted and filtered correctly', async () => { + await act(async () => { + render( + + + + + + + + + + , + ); + + await wait(); + + // Check if the sorting and filtering logic was applied correctly + const rows = screen.getAllByRole('row'); + + const firstRow = rows[1]; + const secondRow = rows[2]; + + expect(firstRow).toHaveTextContent('John Doe'); + expect(secondRow).toHaveTextContent('Jane Doe'); + + await wait(); + + const inputText = screen.getByTestId('sortUsers'); + + fireEvent.click(inputText); + const toggleText = screen.getByTestId('oldest'); + fireEvent.click(toggleText); + + fireEvent.click(inputText); + const toggleTite = screen.getByTestId('newest'); + fireEvent.click(toggleTite); + + // Verify the users are sorted by oldest + await wait(); + + const displayedUsers = screen.getAllByRole('row'); + expect(displayedUsers[1]).toHaveTextContent('John Doe'); // assuming User1 is the oldest + expect(displayedUsers[displayedUsers.length - 1]).toHaveTextContent( + 'Jack Smith', + ); // assuming UserN is the newest + + await wait(); + + fireEvent.click(inputText); + const toggleOld = screen.getByTestId('oldest'); + fireEvent.click(toggleOld); + + fireEvent.click(inputText); + const toggleNewest = screen.getByTestId('newest'); + fireEvent.click(toggleNewest); + }); + }); }); diff --git a/src/screens/Users/Users.tsx b/src/screens/Users/Users.tsx index c03842069f..3dae6ec17e 100644 --- a/src/screens/Users/Users.tsx +++ b/src/screens/Users/Users.tsx @@ -18,6 +18,7 @@ import InfiniteScroll from 'react-infinite-scroll-component'; import type { InterfaceQueryUserListItem } from 'utils/interfaces'; import styles from './Users.module.css'; import useLocalStorage from 'utils/useLocalstorage'; +import type { ApolloError } from '@apollo/client'; const Users = (): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'users' }); @@ -34,43 +35,52 @@ const Users = (): JSX.Element => { const [searchByName, setSearchByName] = useState(''); const [sortingOption, setSortingOption] = useState('newest'); const [filteringOption, setFilteringOption] = useState('cancel'); - const superAdmin = getItem('SuperAdmin'); - const adminFor = getItem('AdminFor'); - const userRole = superAdmin + const userType = getItem('SuperAdmin') ? 'SUPERADMIN' - : adminFor?.length > 0 + : getItem('AdminFor') ? 'ADMIN' : 'USER'; - const loggedInUserId = getItem('id'); - const { data, loading, fetchMore, refetch } = useQuery(USER_LIST, { + const { + data: usersData, + loading: loading, + fetchMore, + refetch: refetchUsers, + }: { + data?: { users: InterfaceQueryUserListItem[] }; + loading: boolean; + fetchMore: any; + refetch: any; + error?: ApolloError; + } = useQuery(USER_LIST, { variables: { first: perPageResult, skip: 0, firstName_contains: '', lastName_contains: '', + order: sortingOption === 'newest' ? 'createdAt_DESC' : 'createdAt_ASC', }, notifyOnNetworkStatusChange: true, }); const { data: dataOrgs } = useQuery(ORGANIZATION_CONNECTION_LIST); - const [displayedUsers, setDisplayedUsers] = useState(data?.users || []); + const [displayedUsers, setDisplayedUsers] = useState(usersData?.users || []); // Manage loading more state useEffect(() => { - if (!data) { + if (!usersData) { return; } - if (data.users.length < perPageResult) { + if (usersData.users.length < perPageResult) { setHasMore(false); } - if (data && data.users) { - let newDisplayedUsers = sortUsers(data.users, sortingOption); + if (usersData && usersData.users) { + let newDisplayedUsers = sortUsers(usersData.users, sortingOption); newDisplayedUsers = filterUsers(newDisplayedUsers, filteringOption); setDisplayedUsers(newDisplayedUsers); } - }, [data, sortingOption, filteringOption]); + }, [usersData, sortingOption, filteringOption]); // To clear the search when the component is unmounted useEffect(() => { @@ -92,7 +102,7 @@ const Users = (): JSX.Element => { // Send to orgList page if user is not superadmin useEffect(() => { - if (userRole != 'SUPERADMIN') { + if (userType != 'SUPERADMIN') { window.location.assign('/orglist'); } }, []); @@ -112,18 +122,17 @@ const Users = (): JSX.Element => { resetAndRefetch(); return; } - refetch({ + refetchUsers({ firstName_contains: value, lastName_contains: '', // Later on we can add several search and filter options }); + setHasMore(true); }; - const handleSearchByEnter = ( - e: React.KeyboardEvent, - ): void => { + const handleSearchByEnter = (e: any): void => { if (e.key === 'Enter') { - const { value } = e.currentTarget; + const { value } = e.target; handleSearch(value); } }; @@ -137,11 +146,12 @@ const Users = (): JSX.Element => { }; /* istanbul ignore next */ const resetAndRefetch = (): void => { - refetch({ + refetchUsers({ first: perPageResult, skip: 0, firstName_contains: '', lastName_contains: '', + order: sortingOption === 'newest' ? 'createdAt_DESC' : 'createdAt_ASC', }); setHasMore(true); }; @@ -150,8 +160,10 @@ const Users = (): JSX.Element => { setIsLoadingMore(true); fetchMore({ variables: { - skip: data?.users.length || 0, + skip: usersData?.users.length || 0, + userType: 'ADMIN', filter: searchByName, + order: sortingOption === 'newest' ? 'createdAt_DESC' : 'createdAt_ASC', }, updateQuery: ( prev: { users: InterfaceQueryUserListItem[] } | undefined, @@ -174,6 +186,8 @@ const Users = (): JSX.Element => { }; const handleSorting = (option: string): void => { + setDisplayedUsers([]); + setHasMore(true); setSortingOption(option); }; @@ -201,6 +215,7 @@ const Users = (): JSX.Element => { }; const handleFiltering = (option: string): void => { + setDisplayedUsers([]); setFilteringOption(option); }; @@ -249,7 +264,7 @@ const Users = (): JSX.Element => {
    {
    {isLoading == false && - data && + usersData && displayedUsers.length === 0 && searchByName.length > 0 ? (
    @@ -350,7 +365,9 @@ const Users = (): JSX.Element => { {tCommon('noResultsFoundFor')} "{searchByName}"
    - ) : isLoading == false && data && displayedUsers.length === 0 ? ( + ) : isLoading == false && + usersData === undefined && + displayedUsers.length === 0 ? (

    {t('noUserFound')}

    @@ -393,7 +410,7 @@ const Users = (): JSX.Element => { - {data && + {usersData && displayedUsers.map( (user: InterfaceQueryUserListItem, index: number) => { return ( diff --git a/src/state/reducers/routesReducer.test.ts b/src/state/reducers/routesReducer.test.ts index 0a474df0c3..84427ee4d0 100644 --- a/src/state/reducers/routesReducer.test.ts +++ b/src/state/reducers/routesReducer.test.ts @@ -16,6 +16,7 @@ describe('Testing Routes reducer', () => { { name: 'Events', url: '/orgevents/undefined' }, { name: 'Venues', url: '/orgvenues/undefined' }, { name: 'Action Items', url: '/orgactionitems/undefined' }, + { name: 'Agenda Items Category', url: '/orgagendacategory/undefined' }, { name: 'Posts', url: '/orgpost/undefined' }, { name: 'Block/Unblock', @@ -63,6 +64,11 @@ describe('Testing Routes reducer', () => { comp_id: 'orgactionitems', component: 'OrganizationActionItems', }, + { + name: 'Agenda Items Category', + comp_id: 'orgagendacategory', + component: 'OrganizationAgendaCategory', + }, { name: 'Posts', comp_id: 'orgpost', component: 'OrgPost' }, { name: 'Block/Unblock', comp_id: 'blockuser', component: 'BlockUser' }, { @@ -113,6 +119,7 @@ describe('Testing Routes reducer', () => { { name: 'Events', url: '/orgevents/orgId' }, { name: 'Venues', url: '/orgvenues/orgId' }, { name: 'Action Items', url: '/orgactionitems/orgId' }, + { name: 'Agenda Items Category', url: '/orgagendacategory/orgId' }, { name: 'Posts', url: '/orgpost/orgId' }, { name: 'Block/Unblock', url: '/blockuser/orgId' }, { name: 'Advertisement', url: '/orgads/orgId' }, @@ -157,6 +164,11 @@ describe('Testing Routes reducer', () => { comp_id: 'orgactionitems', component: 'OrganizationActionItems', }, + { + name: 'Agenda Items Category', + comp_id: 'orgagendacategory', + component: 'OrganizationAgendaCategory', + }, { name: 'Posts', comp_id: 'orgpost', component: 'OrgPost' }, { name: 'Block/Unblock', comp_id: 'blockuser', component: 'BlockUser' }, { @@ -203,6 +215,7 @@ describe('Testing Routes reducer', () => { { name: 'Events', url: '/orgevents/undefined' }, { name: 'Venues', url: '/orgvenues/undefined' }, { name: 'Action Items', url: '/orgactionitems/undefined' }, + { name: 'Agenda Items Category', url: '/orgagendacategory/undefined' }, { name: 'Posts', url: '/orgpost/undefined' }, { name: 'Block/Unblock', @@ -253,6 +266,11 @@ describe('Testing Routes reducer', () => { comp_id: 'orgactionitems', component: 'OrganizationActionItems', }, + { + name: 'Agenda Items Category', + comp_id: 'orgagendacategory', + component: 'OrganizationAgendaCategory', + }, { name: 'Posts', comp_id: 'orgpost', component: 'OrgPost' }, { name: 'Block/Unblock', comp_id: 'blockuser', component: 'BlockUser' }, { diff --git a/src/state/reducers/routesReducer.ts b/src/state/reducers/routesReducer.ts index 34cfdbbcca..bcda9f02d8 100644 --- a/src/state/reducers/routesReducer.ts +++ b/src/state/reducers/routesReducer.ts @@ -76,6 +76,11 @@ const components: ComponentType[] = [ comp_id: 'orgactionitems', component: 'OrganizationActionItems', }, + { + name: 'Agenda Items Category', + comp_id: 'orgagendacategory', + component: 'OrganizationAgendaCategory', + }, { name: 'Posts', comp_id: 'orgpost', component: 'OrgPost' }, { name: 'Block/Unblock', comp_id: 'blockuser', component: 'BlockUser' }, { name: 'Advertisement', comp_id: 'orgads', component: 'Advertisements' }, diff --git a/src/utils/currency.ts b/src/utils/currency.ts index d096177dc5..c7db3002f2 100644 --- a/src/utils/currency.ts +++ b/src/utils/currency.ts @@ -163,7 +163,7 @@ export const currencyOptions = [ { value: 'ZMW', label: 'ZMW' }, // Zambian Kwacha { value: 'ZWD', label: 'ZWD' }, // Zimbabwean Dollar ]; -export const currencySymbols = { +export const currencySymbols: { [key: string]: string } = { AED: 'د.إ', // United Arab Emirates Dirham AFN: '؋', // Afghan Afghani ALL: 'L', // Albanian Lek diff --git a/src/utils/interfaces.ts b/src/utils/interfaces.ts index abaac2efcc..c4e15d0718 100644 --- a/src/utils/interfaces.ts +++ b/src/utils/interfaces.ts @@ -226,19 +226,7 @@ export interface InterfaceQueryOrganizationAdvertisementListItem { totalCount: number; }; } -export interface InterfaceQueryOrganizationFunds { - fundsByOrganization: { - _id: string; - name: string; - refrenceNumber: string; - taxDeductible: boolean; - isArchived: boolean; - isDefault: boolean; - createdAt: string; - organizationId: string; - creator: { _id: string; firstName: string; lastName: string }; - }[]; -} + export interface InterfaceQueryOrganizationFundCampaigns { campaigns: { _id: string; @@ -251,6 +239,9 @@ export interface InterfaceQueryOrganizationFundCampaigns { }[]; } export interface InterfaceQueryFundCampaignsPledges { + name: string; + fundingGoal: number; + currency: string; startDate: Date; endDate: Date; pledges: { @@ -259,10 +250,7 @@ export interface InterfaceQueryFundCampaignsPledges { currency: string; endDate: string; startDate: string; - users: { - _id: string; - firstName: string; - }[]; + users: InterfacePledger[]; }[]; } export interface InterfaceFundInfo { @@ -273,6 +261,8 @@ export interface InterfaceFundInfo { isArchived: boolean; isDefault: boolean; createdAt: string; + organizationId: string; + creator: { _id: string; firstName: string; lastName: string }; } export interface InterfaceCampaignInfo { _id: string; @@ -289,10 +279,7 @@ export interface InterfacePledgeInfo { currency: string; endDate: string; startDate: string; - users: { - _id: string; - firstName: string; - }[]; + users: InterfacePledger[]; } export interface InterfaceQueryOrganizationEventListItem { _id: string; @@ -389,6 +376,9 @@ export interface InterfaceAddress { export interface InterfaceCreateFund { fundName: string; fundRef: string; + isDefault: boolean; + isArchived: boolean; + taxDeductible: boolean; } export interface InterfacePostCard { @@ -409,7 +399,7 @@ export interface InterfacePostCard { comments: { id: string; creator: { - _id: string; + id: string; firstName: string; lastName: string; email: string; @@ -427,15 +417,9 @@ export interface InterfacePostCard { }[]; fetchPosts: () => void; } -export interface InterfaceCreateCampaign { - campaignName: string; - campaignCurrency: string; - campaignGoal: number; - campaignStartDate: Date; - campaignEndDate: Date; -} export interface InterfaceCreatePledge { + pledgeUsers: InterfacePledger[]; pledgeAmount: number; pledgeCurrency: string; pledgeStartDate: Date; @@ -456,3 +440,60 @@ export interface InterfaceQueryMembershipRequestsListItem { }[]; }[]; } + +export interface InterfacePledger { + _id: string; + firstName: string; + lastName: string; + image: string | null; +} +export interface InterfaceAgendaItemCategoryInfo { + _id: string; + name: string; + description: string; + createdBy: { + _id: string; + firstName: string; + lastName: string; + }; +} + +export interface InterfaceAgendaItemCategoryList { + agendaItemCategoriesByOrganization: InterfaceAgendaItemCategoryInfo[]; +} + +export interface InterfaceAgendaItemInfo { + _id: string; + title: string; + description: string; + duration: string; + attachments: string[]; + createdBy: { + _id: string; + firstName: string; + lastName: string; + }; + urls: string[]; + users: { + _id: string; + firstName: string; + lastName: string; + }[]; + sequence: number; + categories: { + _id: string; + name: string; + }[]; + organization: { + _id: string; + name: string; + }; + relatedEvent: { + _id: string; + title: string; + }; +} + +export interface InterfaceAgendaItemList { + agendaItemByEvent: InterfaceAgendaItemInfo[]; +} From b991d548f95b583612e8feb087a7b48ad6dcdfce Mon Sep 17 00:00:00 2001 From: Peter Harrison <16875803+palisadoes@users.noreply.github.com> Date: Sun, 11 Aug 2024 14:44:01 -0700 Subject: [PATCH 24/34] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 21692075fc..26e5eb3557 100644 --- a/README.md +++ b/README.md @@ -53,4 +53,4 @@ Core features include: # Videos 1. Visit our [YouTube Channel playlists](https://www.youtube.com/@PalisadoesOrganization/playlists) for more insights - 1. The "Getting Started - Developers" videos are extremely helpful for new open source contributors. + 1. The "[Getting Started - Developers](https://www.youtube.com/watch?v=YpBUoHxEeyg&list=PLv50qHwThlJUIzscg9a80a9-HmAlmUdCF&index=1)" videos are extremely helpful for new open source contributors. From f358420aac5f069d6bd59d7b2c9b23a36defe77c Mon Sep 17 00:00:00 2001 From: Peter Harrison <16875803+palisadoes@users.noreply.github.com> Date: Sun, 11 Aug 2024 14:44:28 -0700 Subject: [PATCH 25/34] Update CONTRIBUTING.md --- CONTRIBUTING.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 47fa8d6e69..b0d014f1c6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -21,6 +21,11 @@ If you are new to contributing to open source, please read the Open Source Guide +## Videos + +1. Visit our [YouTube Channel playlists](https://www.youtube.com/@PalisadoesOrganization/playlists) for more insights + 1. The "[Getting Started - Developers](https://www.youtube.com/watch?v=YpBUoHxEeyg&list=PLv50qHwThlJUIzscg9a80a9-HmAlmUdCF&index=1)" videos are extremely helpful for new open source contributors. + ## Code of Conduct A safe environment is required for everyone to contribute. Read our [Code of Conduct Guide](CODE_OF_CONDUCT.md) to understand what this means. Let us know immediately if you have unacceptable experiences in this area. From 15c875302c9b3862683b6541377e6a1903d516cc Mon Sep 17 00:00:00 2001 From: Peter Harrison <16875803+palisadoes@users.noreply.github.com> Date: Sun, 11 Aug 2024 14:45:37 -0700 Subject: [PATCH 26/34] Update CONTRIBUTING.md --- CONTRIBUTING.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b0d014f1c6..668c5d8707 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -21,17 +21,16 @@ If you are new to contributing to open source, please read the Open Source Guide -## Videos - -1. Visit our [YouTube Channel playlists](https://www.youtube.com/@PalisadoesOrganization/playlists) for more insights - 1. The "[Getting Started - Developers](https://www.youtube.com/watch?v=YpBUoHxEeyg&list=PLv50qHwThlJUIzscg9a80a9-HmAlmUdCF&index=1)" videos are extremely helpful for new open source contributors. - ## Code of Conduct A safe environment is required for everyone to contribute. Read our [Code of Conduct Guide](CODE_OF_CONDUCT.md) to understand what this means. Let us know immediately if you have unacceptable experiences in this area. No one should fear voicing their opinion. Respones must be respectful. +## Videos + +1. Visit our [YouTube Channel playlists](https://www.youtube.com/@PalisadoesOrganization/playlists) for more insights + 1. The "[Getting Started - Developers](https://www.youtube.com/watch?v=YpBUoHxEeyg&list=PLv50qHwThlJUIzscg9a80a9-HmAlmUdCF&index=1)" videos are extremely helpful for new open source contributors. ## Ways to Contribute If you are ready to start contributing code right away, get ready! From 30c1d18b88fa502e68d92f846aeab4df5f06189e Mon Sep 17 00:00:00 2001 From: Peter Harrison <16875803+palisadoes@users.noreply.github.com> Date: Sun, 29 Sep 2024 11:19:17 -0700 Subject: [PATCH 27/34] Merge with Develop 20240924 (#2306) * 20240929102850 Deleted all files in the main branch in anticipation of merging develop into main cleanly * 20240929103238 Merge develop into main --- .coderabbit.yaml | 3 +- .github/ISSUE_TEMPLATE/bug-report.md | 4 +- .github/ISSUE_TEMPLATE/feature-request.md | 4 +- .github/workflows/check-tsdoc.js | 68 + .github/workflows/compare_translations.py | 30 +- .github/workflows/pull-request.yml | 9 +- .github/workflows/push.yml | 127 +- .node-version | 2 +- CONTRIBUTING.md | 2 + config/babel.config.cjs | 8 + config/vite.config.ts | 30 + public/index.html => index.html | 15 +- jest.config.js | 21 +- package-lock.json | 30782 +++++----------- package.json | 105 +- public/locales/en/common.json | 13 +- public/locales/en/errors.json | 3 +- public/locales/en/translation.json | 440 +- public/locales/fr/common.json | 11 +- public/locales/fr/errors.json | 3 +- public/locales/fr/translation.json | 441 +- public/locales/hi/common.json | 11 +- public/locales/hi/errors.json | 3 +- public/locales/hi/translation.json | 649 +- public/locales/sp/common.json | 11 +- public/locales/sp/errors.json | 3 +- public/locales/sp/translation.json | 166 +- public/locales/zh/common.json | 11 +- public/locales/zh/errors.json | 3 +- public/locales/zh/translation.json | 445 +- scripts/__mocks__/fileMock.js | 2 + scripts/config-overrides/custom_build.js | 17 - scripts/config-overrides/custom_start.js | 19 - scripts/config-overrides/index.js | 29 - scripts/config-overrides/package.json | 5 - scripts/test.js | 52 - src/App.test.tsx | 4 +- src/App.tsx | 40 +- .../Mutations/ActionItemCategoryMutations.ts | 13 +- src/GraphQl/Mutations/ActionItemMutations.ts | 5 + src/GraphQl/Mutations/CampaignMutation.ts | 16 +- src/GraphQl/Mutations/FundMutation.ts | 14 - src/GraphQl/Mutations/TagMutations.ts | 74 + .../Queries/ActionItemCategoryQueries.ts | 18 +- src/GraphQl/Queries/ActionItemQueries.ts | 16 +- src/GraphQl/Queries/OrganizationQueries.ts | 46 + src/GraphQl/Queries/Queries.ts | 2 +- src/GraphQl/Queries/fundQueries.ts | 55 +- src/GraphQl/Queries/userTagQueries.ts | 101 + src/assets/images/talawa-logo-200x200.png | Bin 5468 -> 0 bytes src/assets/images/talawa-logo-600x600.png | Bin 0 -> 17667 bytes src/assets/svgs/angleLeft.svg | 5 - src/assets/svgs/eventDashboard.svg | 7 - src/assets/svgs/eventStats.svg | 12 - .../{Twitter-Logo.svg => X-Logo.svg} | 0 src/assets/svgs/social-icons/index.tsx | 4 +- src/assets/svgs/tag.svg | 4 + .../ActionItemsContainer.module.css | 25 - .../ActionItems/ActionItemsContainer.test.tsx | 777 - .../ActionItems/ActionItemsContainer.tsx | 499 - .../ActionItems/ActionItemsContainerMocks.ts | 112 - .../ActionItems/ActionItemsContainerProps.ts | 131 - .../ActionItems/ActionItemsModal.test.tsx | 294 - .../ActionItems/ActionItemsModal.tsx | 42 - .../ActionItems/ActionItemsModalBody.tsx | 218 - .../ActionItems/ActionItemsWrapper.module.css | 53 - .../ActionItems/ActionItemsWrapper.test.tsx | 73 - .../ActionItems/ActionItemsWrapper.tsx | 45 - src/components/AddOn/AddOn.test.tsx | 8 + src/components/AddOn/AddOn.tsx | 46 +- .../AddOn/core/AddOnEntry/AddOnEntry.test.tsx | 29 +- .../AddOn/core/AddOnEntry/AddOnEntry.tsx | 75 +- .../core/AddOnRegister/AddOnRegister.test.tsx | 104 +- .../core/AddOnRegister/AddOnRegister.tsx | 55 +- .../AddOn/core/AddOnStore/AddOnStore.test.tsx | 4 +- .../AddOn/core/AddOnStore/AddOnStore.tsx | 48 +- .../support/components/Action/Action.tsx | 23 +- .../components/MainContent/MainContent.tsx | 21 +- .../components/SidePanel/SidePanel.tsx | 24 +- .../AddOn/support/services/Plugin.helper.ts | 20 + .../Advertisements/Advertisements.test.tsx | 4 +- .../Advertisements/Advertisements.tsx | 50 +- .../AdvertisementEntry.test.tsx | 57 + .../AdvertisementEntry/AdvertisementEntry.tsx | 68 +- .../AdvertisementRegister.module.css | 1 + .../AdvertisementRegister.test.tsx | 387 +- .../AdvertisementRegister.tsx | 110 +- .../AgendaCategoryContainer.tsx | 68 +- .../AgendaItems/AgendaItemsContainer.test.tsx | 12 +- .../AgendaItems/AgendaItemsContainer.tsx | 55 +- .../AgendaItems/AgendaItemsCreateModal.tsx | 41 +- .../AgendaItems/AgendaItemsDeleteModal.tsx | 10 + .../AgendaItems/AgendaItemsPreviewModal.tsx | 22 + .../AgendaItems/AgendaItemsUpdateModal.tsx | 42 +- src/components/Avatar/Avatar.tsx | 18 +- .../ChangeLanguageDropDown.tsx | 17 + .../ChangeLanguageDropdown.test.tsx | 8 +- src/components/CheckIn/CheckInModal.tsx | 48 +- src/components/CheckIn/CheckInWrapper.tsx | 11 +- src/components/CheckIn/TableRow.test.tsx | 64 +- src/components/CheckIn/TableRow.tsx | 50 +- src/components/CheckIn/tagTemplate.ts | 2 +- .../CollapsibleDropdown.test.tsx | 20 +- .../CollapsibleDropdown.tsx | 10 + .../ContriStats/ContriStats.test.tsx | 1 - src/components/ContriStats/ContriStats.tsx | 12 +- .../CurrentHourIndicator.tsx | 5 + src/components/DeleteOrg/DeleteOrg.test.tsx | 248 - .../DynamicDropDown/DynamicDropDown.tsx | 59 +- .../EditCustomFieldDropDown.test.tsx | 6 +- .../EditCustomFieldDropDown.tsx | 19 +- .../EventCalendar/EventCalendar.tsx | 13 + .../EventCalendar/EventHeader.test.tsx | 3 +- src/components/EventCalendar/EventHeader.tsx | 17 + .../EventCalendar/YearlyEventCalender.tsx | 52 + .../EventDashboardScreen.tsx | 29 +- .../EventListCard/EventListCard.test.tsx | 22 +- .../EventListCard/EventListCard.tsx | 17 + .../EventListCard/EventListCardMocks.ts | 4 +- .../EventListCard/EventListCardModals.tsx | 27 +- .../Dashboard/EventDashboard.tsx | 48 +- .../EventActionItems.module.css | 206 - .../EventActionItems.test.tsx | 1179 - .../EventActionItems/EventActionItems.tsx | 599 - .../useEventActionColumnConfig.tsx | 200 - .../EventAgendaItems.test.tsx | 15 +- .../EventAgendaItems/EventAgendaItems.tsx | 43 +- .../EventRegistrantsModal.tsx | 36 +- .../EventRegistrantsWrapper.tsx | 24 +- src/components/EventStats/EventStats.tsx | 17 +- .../EventStats/EventStatsWrapper.tsx | 21 +- .../EventStats/Statistics/AverageRating.tsx | 13 +- .../EventStats/Statistics/Feedback.tsx | 12 + .../EventStats/Statistics/Review.tsx | 10 + src/components/HolidayCards/HolidayCard.tsx | 8 + .../IconComponent/IconComponent.test.tsx | 49 +- .../IconComponent/IconComponent.tsx | 81 +- src/components/LeftDrawer/LeftDrawer.test.tsx | 149 +- src/components/LeftDrawer/LeftDrawer.tsx | 22 +- .../LeftDrawerOrg/LeftDrawerOrg.module.css | 20 +- .../LeftDrawerOrg/LeftDrawerOrg.test.tsx | 9 +- .../LeftDrawerOrg/LeftDrawerOrg.tsx | 34 +- src/components/Loader/Loader.tsx | 11 +- .../LoginPortalToggle.test.tsx | 4 +- .../LoginPortalToggle/LoginPortalToggle.tsx | 23 +- .../MemberRequestCard.test.tsx | 14 +- .../MemberRequestCard/MemberRequestCard.tsx | 36 +- src/components/NotFound/NotFound.tsx | 11 +- .../OrgActionItemCategories.module.css | 33 - .../OrgActionItemCategories.test.tsx | 372 - .../OrgActionItemCategories.tsx | 292 - .../OrgActionItemCategoryMocks.ts | 174 - .../OrgAdminListCard.test.tsx | 4 +- .../OrgAdminListCard/OrgAdminListCard.tsx | 14 +- .../OrgContriCards/OrgContriCards.tsx | 13 + src/components/OrgDelete/OrgDelete.tsx | 8 + .../OrgListCard/OrgListCard.test.tsx | 4 +- src/components/OrgListCard/OrgListCard.tsx | 29 +- .../OrgPeopleListCard.test.tsx | 4 +- .../OrgPeopleListCard/OrgPeopleListCard.tsx | 27 +- .../OrgPostCard/OrgPostCard.test.tsx | 221 +- src/components/OrgPostCard/OrgPostCard.tsx | 34 +- .../CategoryModal.test.tsx | 208 + .../ActionItemCategories/CategoryModal.tsx | 208 + .../OrgActionItemCategories.module.css | 138 + .../OrgActionItemCategories.test.tsx | 241 + .../OrgActionItemCategories.tsx | 418 + .../OrgActionItemCategoryMocks.ts | 288 + .../AgendaCategoryCreateModal.test.tsx | 0 .../AgendaCategoryCreateModal.tsx | 16 + .../AgendaCategoryDeleteModal.tsx | 12 + .../AgendaCategoryPreviewModal.tsx | 16 + .../AgendaCategoryUpdateModal.test.tsx | 0 .../AgendaCategoryUpdateModal.tsx | 16 + .../OrganizationAgendaCategory.module.css | 0 .../OrganizationAgendaCategory.test.tsx | 8 +- .../OrganizationAgendaCategory.tsx | 50 +- .../OrganizationAgendaCategoryErrorMocks.ts | 0 .../OrganizationAgendaCategoryMocks.ts | 0 .../General}/DeleteOrg/DeleteOrg.module.css | 0 .../General/DeleteOrg/DeleteOrg.test.tsx | 307 + .../General}/DeleteOrg/DeleteOrg.tsx | 32 +- .../OrgSettings/General/GeneralSettings.tsx | 73 + .../OrgProfileFieldSettings.module.css | 0 .../OrgProfileFieldSettings.test.tsx | 4 +- .../OrgProfileFieldSettings.tsx | 31 +- .../General}/OrgUpdate/OrgUpdate.module.css | 0 .../General}/OrgUpdate/OrgUpdate.test.tsx | 4 +- .../General}/OrgUpdate/OrgUpdate.tsx | 17 +- .../General}/OrgUpdate/OrgUpdateMocks.ts | 0 .../OrganizationCard.test.tsx | 2 - .../OrganizationCard/OrganizationCard.tsx | 67 +- .../OrganizationCardStart.test.tsx | 6 +- .../OrganizationCardStart.tsx | 9 +- .../OrganizationDashCards/CardItem.tsx | 19 +- .../OrganizationDashCards/CardItemLoading.tsx | 4 + .../OrganizationDashCards/DashboardCard.tsx | 7 + .../DashboardCardLoading.tsx | 4 + .../OrganizationScreen/OrganizationScreen.tsx | 35 +- src/components/Pagination/Pagination.tsx | 45 +- .../PaginationList/PaginationList.tsx | 39 +- .../ProfileDropdown/ProfileDropdown.test.tsx | 4 +- .../ProfileDropdown/ProfileDropdown.tsx | 12 + .../CustomRecurrenceModal.tsx | 30 + .../RecurrenceOptions/RecurrenceOptions.tsx | 26 +- .../RequestsTableItem.test.tsx | 4 +- .../RequestsTableItem/RequestsTableItem.tsx | 41 +- src/components/SecuredRoute/SecuredRoute.tsx | 14 + .../SuperAdminScreen/SuperAdminScreen.tsx | 12 + src/components/TableLoader/TableLoader.tsx | 12 + .../UserListCard/UserListCard.test.tsx | 13 +- src/components/UserListCard/UserListCard.tsx | 18 +- .../UserPasswordUpdate.test.tsx | 19 +- .../UserPasswordUpdate/UserPasswordUpdate.tsx | 25 +- .../UserPortal/ChatRoom/ChatRoom.test.tsx | 4 +- .../UserPortal/ChatRoom/ChatRoom.tsx | 20 + .../CommentCard/CommentCard.test.tsx | 4 +- .../UserPortal/CommentCard/CommentCard.tsx | 44 +- .../ContactCard/ContactCard.test.tsx | 4 +- .../UserPortal/ContactCard/ContactCard.tsx | 27 + .../CreateDirectChat.test.tsx | 4 +- .../CreateDirectChat/CreateDirectChat.tsx | 33 + .../CreateGroupChat/CreateGroupChat.test.tsx | 6 +- .../CreateGroupChat/CreateGroupChat.tsx | 7 + .../DonationCard/DonationCard.test.tsx | 4 +- .../UserPortal/DonationCard/DonationCard.tsx | 16 + .../UserPortal/EventCard/EventCard.tsx | 40 +- .../OrganizationCard.test.tsx | 6 +- .../OrganizationCard/OrganizationCard.tsx | 36 +- .../OrganizationNavbar.test.tsx | 4 +- .../OrganizationNavbar/OrganizationNavbar.tsx | 32 +- .../OrganizationSidebar.test.tsx | 4 +- .../OrganizationSidebar.tsx | 44 +- .../UserPortal/PeopleCard/PeopleCard.test.tsx | 4 +- .../UserPortal/PeopleCard/PeopleCard.tsx | 23 + .../UserPortal/PostCard/PostCard.test.tsx | 4 +- .../UserPortal/PostCard/PostCard.tsx | 43 +- .../PromotedPost/PromotedPost.test.tsx | 4 +- .../UserPortal/PromotedPost/PromotedPost.tsx | 17 + .../UserPortal/Register/Register.test.tsx | 4 +- .../UserPortal/Register/Register.tsx | 43 +- .../SecuredRouteForUser.tsx | 13 + .../StartPostModal/StartPostModal.test.tsx | 4 +- .../StartPostModal/StartPostModal.tsx | 35 +- .../UserPortal/UserNavbar/UserNavbar.test.tsx | 4 +- .../UserPortal/UserNavbar/UserNavbar.tsx | 32 +- .../UserSidebar/UserSidebar.test.tsx | 87 +- .../UserPortal/UserSidebar/UserSidebar.tsx | 29 +- .../UserSidebarOrg/UserSidebarOrg.test.tsx | 5 +- .../UserSidebarOrg/UserSidebarOrg.tsx | 33 +- .../UserProfileSettings/DeleteUser.tsx | 6 + .../UserProfileSettings/OtherSettings.tsx | 6 + .../UserProfileSettings/UserProfile.tsx | 12 + .../UsersTableItem/UserTableItem.test.tsx | 4 +- .../UsersTableItem/UsersTableItem.tsx | 6 +- src/components/Venues/VenueCard.tsx | 33 +- src/components/Venues/VenueModal.test.tsx | 4 +- src/components/Venues/VenueModal.tsx | 42 +- .../plugins/DummyPlugin/DummyPlugin.test.jsx | 7 +- .../plugins/DummyPlugin/DummyPlugin.tsx | 17 +- .../DummyPlugin2/DummyPlugin2.test.jsx | 6 +- .../plugins/DummyPlugin2/DummyPlugin2.tsx | 16 +- src/constants.ts | 8 +- src/index.tsx | 17 +- src/react-app-env.d.ts | 1 - src/screens/BlockUser/BlockUser.test.tsx | 4 +- src/screens/BlockUser/BlockUser.tsx | 175 +- .../CommunityProfile.test.tsx | 104 +- .../CommunityProfile/CommunityProfile.tsx | 70 +- .../EventManagement.module.css | 8 - .../EventManagement/EventManagement.tsx | 227 +- .../ForgotPassword/ForgotPassword.test.tsx | 45 +- src/screens/ForgotPassword/ForgotPassword.tsx | 61 +- .../FundCampaignPledge.module.css | 14 + .../FundCampaignPledge.test.tsx | 31 +- .../FundCampaignPledge/FundCampaignPledge.tsx | 42 +- .../FundCampaignPledge/PledgeDeleteModal.tsx | 28 +- .../FundCampaignPledge/PledgeModal.tsx | 38 +- .../FundCampaignPledge/PledgesMocks.ts | 730 +- src/screens/LoginPage/LoginPage.test.tsx | 6 +- src/screens/LoginPage/LoginPage.tsx | 60 +- src/screens/ManageTag/ManageTag.module.css | 119 + src/screens/ManageTag/ManageTag.test.tsx | 296 + src/screens/ManageTag/ManageTag.tsx | 511 + src/screens/ManageTag/ManageTagMocks.ts | 290 + .../MemberDetail/MemberDetail.test.tsx | 4 +- src/screens/MemberDetail/MemberDetail.tsx | 11 +- .../OrgContribution/OrgContribution.test.tsx | 4 +- .../OrgContribution/OrgContribution.tsx | 12 + src/screens/OrgList/OrgList.test.tsx | 25 +- src/screens/OrgList/OrgList.tsx | 4 +- src/screens/OrgPost/OrgPost.test.tsx | 93 +- src/screens/OrgPost/OrgPost.tsx | 29 +- src/screens/OrgSettings/OrgSettings.mocks.ts | 143 + .../OrgSettings/OrgSettings.module.css | 3 + src/screens/OrgSettings/OrgSettings.test.tsx | 208 +- src/screens/OrgSettings/OrgSettings.tsx | 222 +- .../ActionItemCreateModal.tsx | 155 - .../ActionItemDeleteModal.tsx | 61 - .../ActionItemPreviewModal.tsx | 133 - .../ActionItemUpdateModal.test.tsx | 235 - .../ActionItemUpdateModal.tsx | 154 - .../ItemDeleteModal.test.tsx | 120 + .../ItemDeleteModal.tsx | 92 + .../ItemModal.test.tsx | 373 + .../OrganizationActionItems/ItemModal.tsx | 440 + .../ItemUpdateStatusModal.test.tsx | 173 + .../ItemUpdateStatusModal.tsx | 129 + .../ItemViewModal.test.tsx | 147 + .../OrganizationActionItems/ItemViewModal.tsx | 233 + .../OrganizationActionItem.mocks.ts | 482 + .../OrganizationActionItemMocks.ts | 417 - .../OrganizationActionItems.module.css | 175 +- .../OrganizationActionItems.test.tsx | 708 +- .../OrganizationActionItems.tsx | 797 +- .../OrganizationActionItemsErrorMocks.ts | 266 - .../OrganizationDashboard.test.tsx | 4 +- .../OrganizationDashboard.tsx | 33 +- .../OrganizationEvents/OrganizationEvents.tsx | 19 +- .../OrganizationEventsMocks.ts | 12 +- .../CampaignDeleteModal.test.tsx | 95 - .../CampaignDeleteModal.tsx | 75 - .../CampaignModal.test.tsx | 2 + .../CampaignModal.tsx | 30 +- .../OrganizationFundCampagins.tsx | 129 +- .../OrganizationFundCampaign.test.tsx | 16 - .../OrganizationFundCampaignMocks.ts | 41 +- .../FundDeleteModal.test.tsx | 100 - .../OrganizationFunds/FundDeleteModal.tsx | 79 - src/screens/OrganizationFunds/FundModal.tsx | 34 +- .../OrganizationFunds.test.tsx | 16 - .../OrganizationFunds/OrganizationFunds.tsx | 85 +- .../OrganizationFundsMocks.ts | 25 - src/screens/OrganizationPeople/AddMember.tsx | 45 +- .../OrganizationPeople.test.tsx | 88 +- .../OrganizationPeople/OrganizationPeople.tsx | 24 +- .../OrganizationTags.module.css | 141 + .../OrganizationTags.test.tsx | 246 + .../OrganizationTags/OrganizationTags.tsx | 515 + .../OrganizationTags/OrganizationTagsMocks.ts | 291 + .../OrganizationVenues/OrganizationVenues.tsx | 36 + src/screens/PageNotFound/PageNotFound.tsx | 15 +- src/screens/Requests/Requests.test.tsx | 4 +- src/screens/Requests/Requests.tsx | 40 +- src/screens/SubTags/SubTags.module.css | 137 + src/screens/SubTags/SubTags.test.tsx | 325 + src/screens/SubTags/SubTags.tsx | 572 + src/screens/SubTags/SubTagsMocks.ts | 415 + .../UserPortal/Campaigns/Campaigns.module.css | 137 + .../UserPortal/Campaigns/Campaigns.test.tsx | 324 + .../UserPortal/Campaigns/Campaigns.tsx | 305 + .../UserPortal/Campaigns/CampaignsMocks.ts | 272 + .../UserPortal/Campaigns/PledgeModal.test.tsx | 310 + .../UserPortal/Campaigns/PledgeModal.tsx | 373 + src/screens/UserPortal/Chat/Chat.test.tsx | 53 +- src/screens/UserPortal/Chat/Chat.tsx | 29 +- .../UserPortal/Donate/Donate.module.css | 9 - src/screens/UserPortal/Donate/Donate.test.tsx | 111 +- src/screens/UserPortal/Donate/Donate.tsx | 103 +- .../UserPortal/Events/Events.module.css | 10 +- src/screens/UserPortal/Events/Events.test.tsx | 12 +- src/screens/UserPortal/Events/Events.tsx | 72 +- .../Organizations/Organizations.test.tsx | 81 +- .../Organizations/Organizations.tsx | 60 +- .../UserPortal/People/People.module.css | 11 - src/screens/UserPortal/People/People.test.tsx | 4 +- src/screens/UserPortal/People/People.tsx | 60 +- .../UserPortal/Pledges/Pledge.test.tsx | 355 + .../UserPortal/Pledges/Pledges.module.css | 202 + src/screens/UserPortal/Pledges/Pledges.tsx | 557 + .../UserPortal/Pledges/PledgesMocks.ts | 596 + src/screens/UserPortal/Posts/Posts.test.tsx | 33 +- src/screens/UserPortal/Posts/Posts.tsx | 29 + .../UserPortal/Settings/Settings.test.tsx | 355 +- src/screens/UserPortal/Settings/Settings.tsx | 65 +- .../UserPortal/UserScreen/UserScreen.test.tsx | 41 +- .../UserPortal/UserScreen/UserScreen.tsx | 62 +- src/screens/Users/Users.test.tsx | 190 +- src/screens/Users/Users.tsx | 45 +- src/state/hooks.ts | 5 + src/state/reducers/routesReducer.test.ts | 36 +- src/state/reducers/routesReducer.ts | 6 +- src/state/reducers/userRoutersReducer.test.ts | 16 + src/state/reducers/userRoutesReducer.ts | 6 + src/state/store.ts | 9 +- src/utils/StaticMockLink.ts | 6 +- src/utils/errorHandler.test.tsx | 8 +- src/utils/errorHandler.tsx | 11 +- src/utils/interfaces.ts | 94 +- src/utils/organizationTagsUtils.ts | 23 + src/utils/timezoneUtils/dateTimeConfig.ts | 28 + .../timezoneUtils/dateTimeMiddleware.test.ts | 226 + src/utils/timezoneUtils/dateTimeMiddleware.ts | 99 + src/utils/timezoneUtils/index.ts | 2 + src/vite-env.d.ts | 1 + tsconfig.json | 1 + 396 files changed, 31389 insertions(+), 32653 deletions(-) create mode 100644 .github/workflows/check-tsdoc.js create mode 100644 config/babel.config.cjs create mode 100644 config/vite.config.ts rename public/index.html => index.html (64%) create mode 100644 scripts/__mocks__/fileMock.js delete mode 100644 scripts/config-overrides/custom_build.js delete mode 100644 scripts/config-overrides/custom_start.js delete mode 100644 scripts/config-overrides/index.js delete mode 100644 scripts/config-overrides/package.json delete mode 100644 scripts/test.js create mode 100644 src/GraphQl/Mutations/TagMutations.ts create mode 100644 src/GraphQl/Queries/userTagQueries.ts delete mode 100644 src/assets/images/talawa-logo-200x200.png create mode 100644 src/assets/images/talawa-logo-600x600.png delete mode 100644 src/assets/svgs/angleLeft.svg delete mode 100644 src/assets/svgs/eventDashboard.svg delete mode 100644 src/assets/svgs/eventStats.svg rename src/assets/svgs/social-icons/{Twitter-Logo.svg => X-Logo.svg} (100%) create mode 100644 src/assets/svgs/tag.svg delete mode 100644 src/components/ActionItems/ActionItemsContainer.module.css delete mode 100644 src/components/ActionItems/ActionItemsContainer.test.tsx delete mode 100644 src/components/ActionItems/ActionItemsContainer.tsx delete mode 100644 src/components/ActionItems/ActionItemsContainerMocks.ts delete mode 100644 src/components/ActionItems/ActionItemsContainerProps.ts delete mode 100644 src/components/ActionItems/ActionItemsModal.test.tsx delete mode 100644 src/components/ActionItems/ActionItemsModal.tsx delete mode 100644 src/components/ActionItems/ActionItemsModalBody.tsx delete mode 100644 src/components/ActionItems/ActionItemsWrapper.module.css delete mode 100644 src/components/ActionItems/ActionItemsWrapper.test.tsx delete mode 100644 src/components/ActionItems/ActionItemsWrapper.tsx delete mode 100644 src/components/DeleteOrg/DeleteOrg.test.tsx delete mode 100644 src/components/EventManagement/EventActionItems/EventActionItems.module.css delete mode 100644 src/components/EventManagement/EventActionItems/EventActionItems.test.tsx delete mode 100644 src/components/EventManagement/EventActionItems/EventActionItems.tsx delete mode 100644 src/components/EventManagement/EventActionItems/useEventActionColumnConfig.tsx delete mode 100644 src/components/OrgActionItemCategories/OrgActionItemCategories.module.css delete mode 100644 src/components/OrgActionItemCategories/OrgActionItemCategories.test.tsx delete mode 100644 src/components/OrgActionItemCategories/OrgActionItemCategories.tsx delete mode 100644 src/components/OrgActionItemCategories/OrgActionItemCategoryMocks.ts create mode 100644 src/components/OrgSettings/ActionItemCategories/CategoryModal.test.tsx create mode 100644 src/components/OrgSettings/ActionItemCategories/CategoryModal.tsx create mode 100644 src/components/OrgSettings/ActionItemCategories/OrgActionItemCategories.module.css create mode 100644 src/components/OrgSettings/ActionItemCategories/OrgActionItemCategories.test.tsx create mode 100644 src/components/OrgSettings/ActionItemCategories/OrgActionItemCategories.tsx create mode 100644 src/components/OrgSettings/ActionItemCategories/OrgActionItemCategoryMocks.ts rename src/{screens/OrganizationAgendaCategory => components/OrgSettings/AgendaItemCategories}/AgendaCategoryCreateModal.test.tsx (100%) rename src/{screens/OrganizationAgendaCategory => components/OrgSettings/AgendaItemCategories}/AgendaCategoryCreateModal.tsx (77%) rename src/{screens/OrganizationAgendaCategory => components/OrgSettings/AgendaItemCategories}/AgendaCategoryDeleteModal.tsx (73%) rename src/{screens/OrganizationAgendaCategory => components/OrgSettings/AgendaItemCategories}/AgendaCategoryPreviewModal.tsx (76%) rename src/{screens/OrganizationAgendaCategory => components/OrgSettings/AgendaItemCategories}/AgendaCategoryUpdateModal.test.tsx (100%) rename src/{screens/OrganizationAgendaCategory => components/OrgSettings/AgendaItemCategories}/AgendaCategoryUpdateModal.tsx (76%) rename src/{screens/OrganizationAgendaCategory => components/OrgSettings/AgendaItemCategories}/OrganizationAgendaCategory.module.css (100%) rename src/{screens/OrganizationAgendaCategory => components/OrgSettings/AgendaItemCategories}/OrganizationAgendaCategory.test.tsx (96%) rename src/{screens/OrganizationAgendaCategory => components/OrgSettings/AgendaItemCategories}/OrganizationAgendaCategory.tsx (78%) rename src/{screens/OrganizationAgendaCategory => components/OrgSettings/AgendaItemCategories}/OrganizationAgendaCategoryErrorMocks.ts (100%) rename src/{screens/OrganizationAgendaCategory => components/OrgSettings/AgendaItemCategories}/OrganizationAgendaCategoryMocks.ts (100%) rename src/components/{ => OrgSettings/General}/DeleteOrg/DeleteOrg.module.css (100%) create mode 100644 src/components/OrgSettings/General/DeleteOrg/DeleteOrg.test.tsx rename src/components/{ => OrgSettings/General}/DeleteOrg/DeleteOrg.tsx (76%) create mode 100644 src/components/OrgSettings/General/GeneralSettings.tsx rename src/components/{ => OrgSettings/General}/OrgProfileFieldSettings/OrgProfileFieldSettings.module.css (100%) rename src/components/{ => OrgSettings/General}/OrgProfileFieldSettings/OrgProfileFieldSettings.test.tsx (98%) rename src/components/{ => OrgSettings/General}/OrgProfileFieldSettings/OrgProfileFieldSettings.tsx (82%) rename src/components/{ => OrgSettings/General}/OrgUpdate/OrgUpdate.module.css (100%) rename src/components/{ => OrgSettings/General}/OrgUpdate/OrgUpdate.test.tsx (98%) rename src/components/{ => OrgSettings/General}/OrgUpdate/OrgUpdate.tsx (95%) rename src/components/{ => OrgSettings/General}/OrgUpdate/OrgUpdateMocks.ts (100%) delete mode 100644 src/react-app-env.d.ts delete mode 100644 src/screens/EventManagement/EventManagement.module.css create mode 100644 src/screens/ManageTag/ManageTag.module.css create mode 100644 src/screens/ManageTag/ManageTag.test.tsx create mode 100644 src/screens/ManageTag/ManageTag.tsx create mode 100644 src/screens/ManageTag/ManageTagMocks.ts create mode 100644 src/screens/OrgSettings/OrgSettings.mocks.ts delete mode 100644 src/screens/OrganizationActionItems/ActionItemCreateModal.tsx delete mode 100644 src/screens/OrganizationActionItems/ActionItemDeleteModal.tsx delete mode 100644 src/screens/OrganizationActionItems/ActionItemPreviewModal.tsx delete mode 100644 src/screens/OrganizationActionItems/ActionItemUpdateModal.test.tsx delete mode 100644 src/screens/OrganizationActionItems/ActionItemUpdateModal.tsx create mode 100644 src/screens/OrganizationActionItems/ItemDeleteModal.test.tsx create mode 100644 src/screens/OrganizationActionItems/ItemDeleteModal.tsx create mode 100644 src/screens/OrganizationActionItems/ItemModal.test.tsx create mode 100644 src/screens/OrganizationActionItems/ItemModal.tsx create mode 100644 src/screens/OrganizationActionItems/ItemUpdateStatusModal.test.tsx create mode 100644 src/screens/OrganizationActionItems/ItemUpdateStatusModal.tsx create mode 100644 src/screens/OrganizationActionItems/ItemViewModal.test.tsx create mode 100644 src/screens/OrganizationActionItems/ItemViewModal.tsx create mode 100644 src/screens/OrganizationActionItems/OrganizationActionItem.mocks.ts delete mode 100644 src/screens/OrganizationActionItems/OrganizationActionItemMocks.ts delete mode 100644 src/screens/OrganizationActionItems/OrganizationActionItemsErrorMocks.ts delete mode 100644 src/screens/OrganizationFundCampaign/CampaignDeleteModal.test.tsx delete mode 100644 src/screens/OrganizationFundCampaign/CampaignDeleteModal.tsx delete mode 100644 src/screens/OrganizationFunds/FundDeleteModal.test.tsx delete mode 100644 src/screens/OrganizationFunds/FundDeleteModal.tsx create mode 100644 src/screens/OrganizationTags/OrganizationTags.module.css create mode 100644 src/screens/OrganizationTags/OrganizationTags.test.tsx create mode 100644 src/screens/OrganizationTags/OrganizationTags.tsx create mode 100644 src/screens/OrganizationTags/OrganizationTagsMocks.ts create mode 100644 src/screens/SubTags/SubTags.module.css create mode 100644 src/screens/SubTags/SubTags.test.tsx create mode 100644 src/screens/SubTags/SubTags.tsx create mode 100644 src/screens/SubTags/SubTagsMocks.ts create mode 100644 src/screens/UserPortal/Campaigns/Campaigns.module.css create mode 100644 src/screens/UserPortal/Campaigns/Campaigns.test.tsx create mode 100644 src/screens/UserPortal/Campaigns/Campaigns.tsx create mode 100644 src/screens/UserPortal/Campaigns/CampaignsMocks.ts create mode 100644 src/screens/UserPortal/Campaigns/PledgeModal.test.tsx create mode 100644 src/screens/UserPortal/Campaigns/PledgeModal.tsx create mode 100644 src/screens/UserPortal/Pledges/Pledge.test.tsx create mode 100644 src/screens/UserPortal/Pledges/Pledges.module.css create mode 100644 src/screens/UserPortal/Pledges/Pledges.tsx create mode 100644 src/screens/UserPortal/Pledges/PledgesMocks.ts create mode 100644 src/state/hooks.ts create mode 100644 src/utils/organizationTagsUtils.ts create mode 100644 src/utils/timezoneUtils/dateTimeConfig.ts create mode 100644 src/utils/timezoneUtils/dateTimeMiddleware.test.ts create mode 100644 src/utils/timezoneUtils/dateTimeMiddleware.ts create mode 100644 src/utils/timezoneUtils/index.ts create mode 100644 src/vite-env.d.ts diff --git a/.coderabbit.yaml b/.coderabbit.yaml index 46e2d25b8c..08e1985ae7 100644 --- a/.coderabbit.yaml +++ b/.coderabbit.yaml @@ -13,5 +13,6 @@ reviews: drafts: false base_branches: - develop + - main chat: - auto_reply: true \ No newline at end of file + auto_reply: true diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md index 493322305f..d9f95c0d65 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.md +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -31,4 +31,6 @@ If applicable, add screenshots to help explain your problem. Add any other context or screenshots about the feature request here. **Potential internship candidates** -Please read this if you are planning to apply for a Palisadoes Foundation internship https://github.com/PalisadoesFoundation/talawa/issues/359 + +Please read this if you are planning to apply for a Palisadoes Foundation internship +- https://github.com/PalisadoesFoundation/talawa/issues/359 diff --git a/.github/ISSUE_TEMPLATE/feature-request.md b/.github/ISSUE_TEMPLATE/feature-request.md index 60d6401dcf..51aea0e9d9 100644 --- a/.github/ISSUE_TEMPLATE/feature-request.md +++ b/.github/ISSUE_TEMPLATE/feature-request.md @@ -23,4 +23,6 @@ A clear and concise description of approach to be followed. Add any other context or screenshots about the feature request here. **Potential internship candidates** -Please read this if you are planning to apply for a Palisadoes Foundation internship https://github.com/PalisadoesFoundation/talawa/issues/359 + +Please read this if you are planning to apply for a Palisadoes Foundation internship +- https://github.com/PalisadoesFoundation/talawa/issues/359 diff --git a/.github/workflows/check-tsdoc.js b/.github/workflows/check-tsdoc.js new file mode 100644 index 0000000000..d5c3b33b90 --- /dev/null +++ b/.github/workflows/check-tsdoc.js @@ -0,0 +1,68 @@ +import fs from 'fs/promises'; // Import fs.promises for async operations +import path from 'path'; + +// List of files to skip +const filesToSkip = [ + 'index.tsx', + 'EventActionItems.tsx', + 'OrgPostCard.tsx', + 'UsersTableItem.tsx', + 'FundCampaignPledge.tsx' +]; + +// Recursively find all .tsx files, excluding files listed in filesToSkip +async function findTsxFiles(dir) { + let results = []; + try { + const list = await fs.readdir(dir); + for (const file of list) { + const filePath = path.join(dir, file); + const stat = await fs.stat(filePath); + if (stat.isDirectory()) { + results = results.concat(await findTsxFiles(filePath)); + } else if ( + filePath.endsWith('.tsx') && + !filePath.endsWith('.test.tsx') && + !filesToSkip.includes(path.relative(dir, filePath)) + ) { + results.push(filePath); + } + } + } catch (err) { + console.error(`Error reading directory ${dir}: ${err.message}`); + } + return results; +} + +// Check if a file contains at least one TSDoc comment +async function containsTsDocComment(filePath) { + try { + const content = await fs.readFile(filePath, 'utf8'); + return /\/\*\*[\s\S]*?\*\//.test(content); + } catch (err) { + console.error(`Error reading file ${filePath}: ${err.message}`); + return false; + } +} + +// Main function to run the validation +async function run() { + const dir = process.argv[2] || './src'; // Allow directory path as a command-line argument + const files = await findTsxFiles(dir); + const filesWithoutTsDoc = []; + + for (const file of files) { + if (!await containsTsDocComment(file)) { + filesWithoutTsDoc.push(file); + } + } + + if (filesWithoutTsDoc.length > 0) { + filesWithoutTsDoc.forEach(file => { + console.error(`No TSDoc comment found in file: ${file}`); + }); + process.exit(1); + } +} + +run(); \ No newline at end of file diff --git a/.github/workflows/compare_translations.py b/.github/workflows/compare_translations.py index fd4f772605..ef65b6c52b 100644 --- a/.github/workflows/compare_translations.py +++ b/.github/workflows/compare_translations.py @@ -88,6 +88,31 @@ def compare_translations(default_translation, errors.append(error_msg) return errors +def flatten_json(nested_json, parent_key=""): + """ + Flattens a nested JSON, concatenating keys to represent the hierarchy. + + Args: + nested_json (dict): The JSON object to flatten. + parent_key (str): The base key for recursion (used to track key hierarchy). + + Returns: + dict: A flattened dictionary with concatenated keys. + """ + flat_dict = {} + + for key, value in nested_json.items(): + # Create the new key by concatenating parent and current key + new_key = f"{parent_key}.{key}" if parent_key else key + + if isinstance(value, dict): + # Recursively flatten the nested dictionary + flat_dict.update(flatten_json(value, new_key)) + else: + # Assign the value to the flattened key + flat_dict[new_key] = value + + return flat_dict def load_translation(filepath): """Load translation from a file. @@ -104,7 +129,8 @@ def load_translation(filepath): if not content.strip(): raise ValueError(f"File {filepath} is empty.") translation = json.loads(content) - return translation + flattened_translation = flatten_json(translation) + return flattened_translation except json.JSONDecodeError as e: raise ValueError(f"Error decoding JSON from file {filepath}: {e}") @@ -170,7 +196,7 @@ def main(): "--directory", type=str, nargs="?", - default=os.path.join(os.getcwd(), "locales"), + default=os.path.join(os.getcwd(), "public/locales"), help="Directory containing translation files(relative to the root directory).", ) args = parser.parse_args() diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 1ec7380c6c..3846371ed5 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -30,7 +30,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v4 with: - node-version: '20.x' + node-version: '22.x' - name: Install Dependencies run: npm install @@ -58,6 +58,9 @@ jobs: CHANGED_FILES: ${{ steps.changed_files.outputs.all_changed_files }} run: npx eslint ${CHANGED_FILES} + - name: Check for TSDoc comments + run: npm run check-tsdoc # Run the TSDoc check script + - name: Check for localStorage Usage run: | chmod +x scripts/githooks/check-localstorage-usage.js @@ -173,7 +176,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v4 with: - node-version: '20.x' + node-version: '22.x' - name: Install Dependencies run: npm install @@ -218,7 +221,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v4 with: - node-version: '20.x' + node-version: '22.x' - name: resolve dependency run: npm install -g @graphql-inspector/cli diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 0542490787..67e49556b4 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -24,7 +24,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [20.x] + node-version: [22.x] steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -58,128 +58,3 @@ jobs: fail_ci_if_error: false name: '${{env.CODECOV_UNIQUE_NAME}}' - Generate-Documentation: - runs-on: ubuntu-latest - if: github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/automated-docs' - steps: - - name: Checkout the Repository - uses: actions/checkout@v4 - # with: - # ref: develop - - # - name: Pull latest changes from develop - # run: git pull origin develop - - - name: Node.js Version - uses: actions/setup-node@v4 - with: - node-version: '20' - - - name: Restore node_modules from cache - id: cache-npm - uses: actions/cache@v4 - env: - cache-name: cache-node-modules - with: - path: | - ~/.npm - node_modules - key: ${{ runner.os }}-generate-docs-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-generate-docs-${{ env.cache-name }}- - ${{ runner.os }}-generate-docs- - ${{ runner.os }}- - - - name: Install dependencies - run: npm install - - - name: Install TypeScript Globally and add GraphQL tag - run: yarn global add typescript - - run: yarn add graphql-tag - - - name: Update Dependencies - run: yarn upgrade - - - name: Generate Documentation of Markdown pages - run: | - npm install --global typedoc - npm install typedoc-plugin-markdown - npm install --save-dev @types/node - npx typedoc --entryPoints src/components src/screens --out talawa-admin-docs --plugin typedoc-plugin-markdown --theme markdown --entryPointStrategy expand --exclude "**/*.test.ts" --exclude "**/*.css" - - - name: Make Markdown Files MDX Compatible - run: python ./.github/workflows/md_mdx_format_adjuster.py --directory talawa-admin-docs - - - - name: Checking doc updated - id: DocUpdated - run: | - if [ -n "$(git status --porcelain)" ]; then - echo "updateDoc=true" >> $GITHUB_OUTPUT - echo -e "Documentation has been updated!!" - else - Green='0;32' - NoColor='\033[0m' - echo -e "${Green}No documentation updated${NoColor}" - fi - - - name: Set env variables - if: steps.DocUpdated.outputs.updateDoc - run: | - echo "commit_id=$(echo $(git rev-parse HEAD))" >> $GITHUB_ENV - echo "email=$(echo $(git log --pretty=format:"%ae" $commit_id))" >> $GITHUB_ENV - - - name: Update Doc - if: steps.DocUpdated.outputs.updateDoc - run: | - Green='0;32' - NoColor='\033[0m' - git config --global user.name "${{github.actor}}" - git config --global user.email "${{env.email}}" - git add . - git commit -m "Update documentation" - git push origin develop:automated-docs --force - echo -e "🚀${Green} Hurrah! doc updated${NoColor}" - - - name: Create Documentation Artifact - uses: actions/upload-artifact@v2 - with: - name: documentation-admin - path: talawa-admin-docs - - Empty-Commit: - name: Create Empty Commit - runs-on: ubuntu-latest - if: github.ref == 'refs/heads/develop' - needs: Generate-Documentation - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - persist-credentials: false - token: ${{ secrets.TALAWA_DOCS_SYNC }} - - name: Empty Commit - run: | - git config --global user.name "${{github.actor}}" - git config --global user.email "${{env.email}}" - git config --global url.https://${{ secrets.TALAWA_DOCS_SYNC }}@github.com/.insteadOf https://github.com/ - git commit --allow-empty -m "Trigger Documentation Workflow" - git push origin develop:automated-docs --force - - Copy-docs-to-talawa-docs: - if: github.ref == 'refs/heads/automated-docs' - needs: Generate-Documentation - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: dmnemec/copy_file_to_another_repo_action@v1.1.1 - env: - API_TOKEN_GITHUB: ${{secrets.TALAWA_DOCS_SYNC}} - with: - source_file: 'talawa-admin-docs/' - destination_repo: 'PalisadoesFoundation/talawa-docs' - destination_branch: 'develop' - destination_folder: 'docs/' - user_email: '${{env.email}}' - user_name: '${{github.actor}}' - commit_message: 'Talawa Admin docs updated' diff --git a/.node-version b/.node-version index 790e1105f2..751f4c9f38 100644 --- a/.node-version +++ b/.node-version @@ -1 +1 @@ -v20.10.0 +v22.7.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 668c5d8707..dbe448c807 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,6 +9,7 @@ If you are new to contributing to open source, please read the Open Source Guide - [Code of Conduct](#code-of-conduct) +- [Videos](#videos) - [Ways to Contribute](#ways-to-contribute) - [Our Development Process](#our-development-process) - [Issues](#issues) @@ -31,6 +32,7 @@ No one should fear voicing their opinion. Respones must be respectful. 1. Visit our [YouTube Channel playlists](https://www.youtube.com/@PalisadoesOrganization/playlists) for more insights 1. The "[Getting Started - Developers](https://www.youtube.com/watch?v=YpBUoHxEeyg&list=PLv50qHwThlJUIzscg9a80a9-HmAlmUdCF&index=1)" videos are extremely helpful for new open source contributors. + ## Ways to Contribute If you are ready to start contributing code right away, get ready! diff --git a/config/babel.config.cjs b/config/babel.config.cjs new file mode 100644 index 0000000000..10cfe1914a --- /dev/null +++ b/config/babel.config.cjs @@ -0,0 +1,8 @@ +module.exports = { + presets: [ + '@babel/preset-env', // Transforms modern JavaScript + '@babel/preset-typescript', // Transforms TypeScript + '@babel/preset-react', // Transforms JSX + ], + plugins: ['babel-plugin-transform-import-meta'], +}; diff --git a/config/vite.config.ts b/config/vite.config.ts new file mode 100644 index 0000000000..71ce6c6f47 --- /dev/null +++ b/config/vite.config.ts @@ -0,0 +1,30 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; +import viteTsconfigPaths from 'vite-tsconfig-paths'; +import svgrPlugin from 'vite-plugin-svgr'; +import EnvironmentPlugin from 'vite-plugin-environment'; + +export default defineConfig({ + // depending on your application, base can also be "/" + build: { + outDir: 'build', + }, + base: '', + plugins: [ + react(), + viteTsconfigPaths(), + EnvironmentPlugin('all'), + svgrPlugin({ + svgrOptions: { + icon: true, + // ...svgr options (https://react-svgr.com/docs/options/) + }, + }), + ], + server: { + // this ensures that the browser opens upon server start + open: true, + // this sets a default port to 3000 + port: 4321, + }, +}); diff --git a/public/index.html b/index.html similarity index 64% rename from public/index.html rename to index.html index 3bd6e258e7..4375f88592 100644 --- a/public/index.html +++ b/index.html @@ -1,12 +1,12 @@ - + - + - - + + - + Talawa Admin
    + diff --git a/jest.config.js b/jest.config.js index 34f219ba06..4346984c74 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,7 +1,8 @@ export default { roots: ['/src'], collectCoverageFrom: ['src/**/*.{ts,tsx}', '!src/index.tsx'], - setupFiles: ['react-app-polyfill/jsdom'], + // setupFiles: ['react-app-polyfill/jsdom'], + setupFiles: ['whatwg-fetch'], setupFilesAfterEnv: ['/src/setupTests.ts'], testMatch: [ '/src/**/__tests__/**/*.{js,jsx,ts,tsx}', @@ -9,11 +10,9 @@ export default { ], testEnvironment: 'jsdom', transform: { - '^.+\\.(js|jsx|mjs|cjs|ts|tsx)$': - 'react-scripts/config/jest/babelTransform.js', - '^.+\\.(css|scss|sass|less)$': 'jest-preview/transforms/css', - '^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)': - 'jest-preview/transforms/file', + '^.+\\.(js|jsx|ts|tsx)$': ['babel-jest', { configFile: "./config/babel.config.cjs" }], // Use babel-jest for JavaScript and TypeScript files + '^.+\\.(css|scss|sass|less)$': 'jest-preview/transforms/css', // CSS transformations + '^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': 'jest-preview/transforms/file', // File transformations }, transformIgnorePatterns: [ '[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs|cjs|ts|tsx)$', @@ -28,6 +27,8 @@ export default { '^@dicebear/core$': '/scripts/__mocks__/@dicebear/core.ts', '^@dicebear/collection$': '/scripts/__mocks__/@dicebear/collection.ts', + '\\.svg\\?react$': '/scripts/__mocks__/fileMock.js', + '\\.svg$': '/scripts/__mocks__/fileMock.js', }, moduleFileExtensions: [ 'web.js', @@ -41,10 +42,10 @@ export default { 'jsx', 'node', ], - watchPlugins: [ - 'jest-watch-typeahead/filename', - 'jest-watch-typeahead/testname', - ], + // watchPlugins: [ + // 'jest-watch-typeahead/filename', + // 'jest-watch-typeahead/testname', + // ], resetMocks: false, coveragePathIgnorePatterns: [ 'src/state/index.ts', diff --git a/package-lock.json b/package-lock.json index d44e07627c..276be70955 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,96 +8,107 @@ "name": "talawa-admin", "version": "3.0.0", "dependencies": { - "@apollo/client": "^3.4.0-beta.19", + "@apollo/client": "^3.11.4", "@apollo/link-error": "^2.0.0-beta.3", "@apollo/react-testing": "^4.0.0", "@dicebear/collection": "^8.0.1", - "@dicebear/core": "^8.0.1", - "@emotion/react": "^11.11.4", - "@emotion/styled": "^11.11.5", - "@mui/icons-material": "^5.16.1", - "@mui/material": "^5.16.4", + "@dicebear/core": "^8.0.2", + "@emotion/react": "^11.13.3", + "@emotion/styled": "^11.13.0", + "@mui/icons-material": "^5.16.7", + "@mui/material": "^5.16.7", "@mui/private-theming": "^5.15.12", "@mui/system": "^5.14.12", - "@mui/x-charts": "^7.8.0", - "@mui/x-data-grid": "^7.11.0", - "@mui/x-date-pickers": "^7.6.1", - "@pdfme/generator": "^1.2.6", + "@mui/x-charts": "^7.17.0", + "@mui/x-data-grid": "^7.16.0", + "@mui/x-date-pickers": "^7.11.1", + "@pdfme/generator": "^4.5.2", + "@reduxjs/toolkit": "^2.2.7", + "@vitejs/plugin-react": "^4.3.1", + "babel-plugin-transform-import-meta": "^2.2.1", "bootstrap": "^5.3.3", "customize-cra": "^1.0.0", - "dayjs": "^1.11.11", + "dayjs": "^1.11.12", + "dotenv": "^16.4.5", "flag-icons": "^6.6.6", "graphql": "^16.9.0", "graphql-tag": "^2.12.6", "graphql-ws": "^5.16.0", "history": "^5.3.0", - "i18next": "^21.8.14", + "i18next": "^23.15.1", "i18next-browser-languagedetector": "^8.0.0", - "i18next-http-backend": "^2.5.2", + "i18next-http-backend": "^2.6.1", "inquirer": "^8.0.0", "js-cookie": "^3.0.1", "markdown-toc": "^1.2.0", "prettier": "^3.3.2", - "react": "^17.0.2", - "react-app-rewired": "^2.2.1", + "react": "^18.3.1", "react-beautiful-dnd": "^13.1.1", - "react-bootstrap": "^2.7.4", + "react-bootstrap": "^2.10.4", "react-datepicker": "^7.3.0", - "react-dom": "^17.0.2", + "react-dom": "^18.3.1", "react-google-recaptcha": "^3.1.0", - "react-i18next": "^11.18.1", + "react-i18next": "^12.3.1", "react-icons": "^5.2.1", "react-infinite-scroll-component": "^6.1.0", "react-multi-carousel": "^2.8.5", - "react-redux": "^7.2.5", - "react-router-dom": "^6.25.1", - "react-scripts": "5.0.1", - "react-toastify": "^9.0.3", + "react-redux": "^9.1.2", + "react-router-dom": "^6.26.0", + "react-toastify": "^10.0.5", "react-tooltip": "^5.27.1", - "redux": "^4.1.1", - "redux-thunk": "^2.3.0", + "redux": "^5.0.1", "sanitize-html": "^2.13.0", + "typedoc": "^0.26.7", "typedoc-plugin-markdown": "^4.2.1", - "typescript": "^4.3.5", - "web-vitals": "^4.2.2" + "typescript": "^5.6.2", + "vite": "^5.4.7", + "vite-plugin-environment": "^1.1.3", + "vite-tsconfig-paths": "^5.0.1", + "web-vitals": "^4.2.3" }, "devDependencies": { "@babel/plugin-proposal-private-property-in-object": "^7.21.11", - "@testing-library/jest-dom": "^5.14.1", - "@testing-library/react": "^11.1.0", + "@babel/preset-env": "^7.25.4", + "@babel/preset-react": "^7.24.7", + "@babel/preset-typescript": "^7.24.7", + "@testing-library/jest-dom": "^6.5.0", + "@testing-library/react": "^16.0.0", "@testing-library/user-event": "^12.1.10", "@types/inquirer": "^9.0.7", "@types/jest": "^26.0.24", "@types/js-cookie": "^3.0.6", - "@types/node": "^20.12.12", + "@types/node": "^22.5.4", "@types/node-fetch": "^2.6.10", - "@types/react": "^17.0.14", + "@types/react": "^18.3.3", "@types/react-beautiful-dnd": "^13.1.8", "@types/react-bootstrap": "^0.32.32", - "@types/react-datepicker": "^4.1.4", - "@types/react-dom": "^17.0.9", + "@types/react-datepicker": "^7.0.0", + "@types/react-dom": "^18.3.0", "@types/react-google-recaptcha": "^2.1.5", "@types/react-router-dom": "^5.1.8", - "@types/sanitize-html": "^2.11.0", - "@typescript-eslint/eslint-plugin": "^5.9.0", - "@typescript-eslint/parser": "^5.9.0", + "@types/sanitize-html": "^2.13.0", + "@typescript-eslint/eslint-plugin": "^8.5.0", + "@typescript-eslint/parser": "^8.5.0", + "babel-jest": "^29.7.0", "cross-env": "^7.0.3", "eslint-config-prettier": "^9.1.0", "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jest": "^25.3.4", - "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-react": "^7.34.1", - "eslint-plugin-tsdoc": "^0.2.17", - "husky": "^8.0.3", + "eslint-plugin-jest": "^28.8.0", + "eslint-plugin-prettier": "^5.2.1", + "eslint-plugin-react": "^7.35.0", + "eslint-plugin-tsdoc": "^0.3.0", + "husky": "^9.1.6", "identity-obj-proxy": "^3.0.0", "jest": "^27.4.5", "jest-localstorage-mock": "^2.4.19", "jest-location-mock": "^2.0.0", "jest-preview": "^0.3.1", - "lint-staged": "^15.2.7", + "lint-staged": "^15.2.8", "postcss-modules": "^6.0.0", - "sass": "^1.77.4", - "tsx": "^4.16.2" + "sass": "^1.77.8", + "tsx": "^4.19.1", + "vite-plugin-svgr": "^4.2.0", + "whatwg-fetch": "^3.6.20" }, "engines": { "node": ">=20.x" @@ -107,26 +118,18 @@ "version": "1.2.6", "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "peer": true, "engines": { "node": ">=0.10.0" } }, "node_modules/@adobe/css-tools": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.3.tgz", - "integrity": "sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==", - "dev": true - }, - "node_modules/@alloc/quick-lru": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", - "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.0.tgz", + "integrity": "sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==", + "dev": true, + "license": "MIT" }, "node_modules/@ampproject/remapping": { "version": "2.2.1", @@ -140,35 +143,20 @@ "node": ">=6.0.0" } }, - "node_modules/@apideck/better-ajv-errors": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.6.tgz", - "integrity": "sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==", - "dependencies": { - "json-schema": "^0.4.0", - "jsonpointer": "^5.0.0", - "leven": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "ajv": ">=8" - } - }, "node_modules/@apollo/client": { - "version": "3.7.17", - "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.7.17.tgz", - "integrity": "sha512-0EErSHEtKPNl5wgWikHJbKFAzJ/k11O0WO2QyqZSHpdxdAnw7UWHY4YiLbHCFG7lhrD+NTQ3Z/H9Jn4rcikoJA==", + "version": "3.11.4", + "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.11.4.tgz", + "integrity": "sha512-bmgYKkULpym8wt8aXlAZ1heaYo0skLJ5ru0qJ+JCRoo03Pe+yIDbBCnqlDw6Mjj76hFkDw3HwFMgZC2Hxp30Mg==", "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", - "@wry/context": "^0.7.0", - "@wry/equality": "^0.5.0", - "@wry/trie": "^0.4.0", + "@wry/caches": "^1.0.0", + "@wry/equality": "^0.5.6", + "@wry/trie": "^0.5.0", "graphql-tag": "^2.12.6", "hoist-non-react-statics": "^3.3.2", - "optimism": "^0.16.2", + "optimism": "^0.18.0", "prop-types": "^15.7.2", + "rehackt": "^0.1.0", "response-iterator": "^0.2.6", "symbol-observable": "^4.0.0", "ts-invariant": "^0.10.3", @@ -176,10 +164,10 @@ "zen-observable-ts": "^1.2.5" }, "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0", + "graphql": "^15.0.0 || ^16.0.0", "graphql-ws": "^5.5.5", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0", "subscriptions-transport-ws": "^0.9.0 || ^0.11.0" }, "peerDependenciesMeta": { @@ -220,108 +208,44 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/code-frame/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/code-frame/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/code-frame/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/compat-data": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", - "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz", + "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.9.tgz", - "integrity": "sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", + "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.9", - "@babel/helper-compilation-targets": "^7.22.9", - "@babel/helper-module-transforms": "^7.22.9", - "@babel/helpers": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.8", - "@babel/types": "^7.22.5", - "convert-source-map": "^1.7.0", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.0", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-module-transforms": "^7.25.2", + "@babel/helpers": "^7.25.0", + "@babel/parser": "^7.25.0", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.2", + "@babel/types": "^7.25.2", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", + "json5": "^2.2.3", "semver": "^6.3.1" }, "engines": { @@ -332,40 +256,12 @@ "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/eslint-parser": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.22.9.tgz", - "integrity": "sha512-xdMkt39/nviO/4vpVdrEYPwXCsYIXSSAr6mC7WQsNIlGnuxKyKE7GZjalcnbSWiC4OXGNNN3UQPeHfjSC6sTDA==", - "dependencies": { - "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", - "eslint-visitor-keys": "^2.1.0", - "semver": "^6.3.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || >=14.0.0" - }, - "peerDependencies": { - "@babel/core": ">=7.11.0", - "eslint": "^7.5.0 || ^8.0.0" - } - }, - "node_modules/@babel/eslint-parser/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "engines": { - "node": ">=10" - } + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, - "node_modules/@babel/eslint-parser/node_modules/semver": { + "node_modules/@babel/core/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", @@ -374,13 +270,13 @@ } }, "node_modules/@babel/generator": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", - "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz", + "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==", "dependencies": { - "@babel/types": "^7.23.6", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", + "@babel/types": "^7.25.6", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" }, "engines": { @@ -388,35 +284,38 @@ } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", - "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", + "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "dev": true, "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", - "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", + "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", + "dev": true, "dependencies": { - "@babel/types": "^7.22.15" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", - "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", + "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", "dependencies": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-validator-option": "^7.23.5", - "browserslist": "^4.22.2", + "@babel/compat-data": "^7.25.2", + "@babel/helper-validator-option": "^7.24.8", + "browserslist": "^4.23.1", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -433,18 +332,17 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.23.10", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.10.tgz", - "integrity": "sha512-2XpP2XhkXzgxecPNEEK8Vz8Asj9aRxt08oKOqtiZoqV2UGZ5T+EkyP9sXQ9nwMxBIG34a7jmasVqoMop7VdPUw==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-member-expression-to-functions": "^7.23.0", - "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.4.tgz", + "integrity": "sha512-ro/bFs3/84MDgDmMwbcHgDa8/E6J3QKNTk4xJJnVeFtGE+tL0K26E3pNxhYz2b67fJpt7Aphw5XcploKXuCvCQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/helper-replace-supers": "^7.25.0", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/traverse": "^7.25.4", "semver": "^6.3.1" }, "engines": { @@ -458,16 +356,18 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", - "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.2.tgz", + "integrity": "sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g==", + "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-annotate-as-pure": "^7.24.7", "regexpu-core": "^5.3.1", "semver": "^6.3.1" }, @@ -482,14 +382,16 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.1.tgz", - "integrity": "sha512-kX4oXixDxG197yhX+J3Wp+NpL2wuCFjWQAr6yX2jtCnflK9ulMI51ULFGIrWiX1jGfvAxdHp+XQCcP2bZGPs9A==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", "@babel/helper-plugin-utils": "^7.22.5", @@ -498,72 +400,43 @@ "resolve": "^1.14.2" }, "peerDependencies": { - "@babel/core": "^7.4.0-0" - } - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", - "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", + "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", + "dev": true, "dependencies": { - "@babel/types": "^7.23.0" + "@babel/traverse": "^7.24.8", + "@babel/types": "^7.24.8" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", "dependencies": { - "@babel/types": "^7.22.15" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", - "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", + "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.2" }, "engines": { "node": ">=6.9.0" @@ -573,32 +446,34 @@ } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", - "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", + "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", + "dev": true, "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", + "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", - "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz", + "integrity": "sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw==", + "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-wrap-function": "^7.22.20" + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-wrap-function": "^7.25.0", + "@babel/traverse": "^7.25.0" }, "engines": { "node": ">=6.9.0" @@ -608,13 +483,14 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", - "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz", + "integrity": "sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==", + "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-member-expression-to-functions": "^7.22.15", - "@babel/helper-optimise-call-expression": "^7.22.5" + "@babel/helper-member-expression-to-functions": "^7.24.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/traverse": "^7.25.0" }, "engines": { "node": ">=6.9.0" @@ -624,96 +500,89 @@ } }, "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", - "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", + "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", + "dev": true, "dependencies": { - "@babel/types": "^7.22.5" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", - "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", + "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", - "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.0.tgz", + "integrity": "sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ==", + "dev": true, "dependencies": { - "@babel/helper-function-name": "^7.22.5", - "@babel/template": "^7.22.15", - "@babel/types": "^7.22.19" + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.0", + "@babel/types": "^7.25.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz", - "integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.6.tgz", + "integrity": "sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==", "dependencies": { - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.6", - "@babel/types": "^7.22.5" + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-validator-identifier": "^7.24.7", "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" @@ -784,9 +653,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.0.tgz", - "integrity": "sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", + "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", + "dependencies": { + "@babel/types": "^7.25.6" + }, "bin": { "parser": "bin/babel-parser.js" }, @@ -794,12 +666,14 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz", - "integrity": "sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==", + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.3.tgz", + "integrity": "sha512-wUrcsxZg6rqBXG05HG1FPYgsP6EvwF4WpBbxIpWIIYnH8wG0gzx3yZY3dtEHas4sTAOGkbTsc9EGPxwff8lRoA==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.3" }, "engines": { "node": ">=6.9.0" @@ -808,29 +682,13 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz", - "integrity": "sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-transform-optional-chaining": "^7.23.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.13.0" - } - }, - "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz", - "integrity": "sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw==", + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.0.tgz", + "integrity": "sha512-Bm4bH2qsX880b/3ziJ8KD711LT7z4u8CFudmjqle65AZj/HNUFhEf90dqYv6O86buWvSBmeQDjv0Tn2aF/bIBA==", + "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -839,98 +697,52 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", - "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-decorators": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.22.7.tgz", - "integrity": "sha512-omXqPF7Onq4Bb7wHxXjM3jSMSJvUUbvDvmmds7KI5n9Cq6Ln5I05I1W2nRlRof1rGdiUxJrxwe285WF96XlBXQ==", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/plugin-syntax-decorators": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", - "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-numeric-separator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", - "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.0.tgz", + "integrity": "sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", - "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", + "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.13.0" } }, - "node_modules/@babel/plugin-proposal-private-methods": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", - "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.0.tgz", + "integrity": "sha512-tggFrk1AIShG/RUQbEwt2Tr/E+ObkfwrPjR6BjbRvsx24+PSjK8zrq0GWPNCjo8qpRx4DuJzlcvWJqlm+0h3kw==", + "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.0" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, "node_modules/@babel/plugin-proposal-private-property-in-object": { @@ -955,6 +767,7 @@ "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -966,6 +779,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -977,6 +791,7 @@ "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" }, @@ -988,6 +803,7 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -998,24 +814,11 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-decorators": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.22.5.tgz", - "integrity": "sha512-avpUOBS7IU6al8MmF1XpAyj9QYeLPuSDJI5D4pVMSMdL7xQokKqJPYQC67RCT0aCTashUXPiGwMJ0DEXXCEmMA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-syntax-dynamic-import": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1027,6 +830,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" }, @@ -1034,26 +838,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-flow": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.22.5.tgz", - "integrity": "sha512-9RdCl0i+q0QExayk2nOS7853w08yLucnnPML6EN9S8fgMPVtdLDCdx/cOQ/i44Lb9UeQX9A35yaqBBOMMZxPxQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz", - "integrity": "sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.6.tgz", + "integrity": "sha512-aABl0jHw9bZ2karQ/uUD6XP4u0SG22SJrOHFoL6XB1R7dTovOP4TzTlsxOYC5yQ1pdscVK2JTUnF6QL3ARoAiQ==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -1063,11 +854,12 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz", - "integrity": "sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.6.tgz", + "integrity": "sha512-sXaDXaJN9SNLymBdlWFA+bjzBhFD617ZaFiY13dGt7TVslVvVgA6fkZOP7Ki3IGElC45lwHdOTrCtKZGVAWeLQ==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -1080,6 +872,7 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -1091,6 +884,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1099,11 +893,12 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", - "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", + "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1116,6 +911,7 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -1127,6 +923,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1138,6 +935,7 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -1149,6 +947,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1160,6 +959,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1171,6 +971,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1182,6 +983,7 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -1196,6 +998,7 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -1207,11 +1010,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", - "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.4.tgz", + "integrity": "sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -1224,6 +1028,7 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -1236,11 +1041,12 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz", - "integrity": "sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", + "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1250,14 +1056,15 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.9.tgz", - "integrity": "sha512-8Q3veQEDGe14dTYuwagbRtwxQDnytyg1JFu4/HwEMETeofocrB0U0ejBJIXoeG/t2oXZ8kzCyI0ZZfbT80VFNQ==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.4.tgz", + "integrity": "sha512-jz8cV2XDDTqjKPwVPJBIjORVEmSGYhdRa8e5k5+vN+uwcjSrSxUaebBRa4ko1jqNF2uxyg8G6XYk30Jv285xzg==", + "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-remap-async-to-generator": "^7.22.20", - "@babel/plugin-syntax-async-generators": "^7.8.4" + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-remap-async-to-generator": "^7.25.0", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/traverse": "^7.25.4" }, "engines": { "node": ">=6.9.0" @@ -1267,13 +1074,14 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz", - "integrity": "sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", + "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", + "dev": true, "dependencies": { - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-remap-async-to-generator": "^7.22.20" + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1283,11 +1091,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz", - "integrity": "sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", + "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1297,11 +1106,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz", - "integrity": "sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.0.tgz", + "integrity": "sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -1311,12 +1121,13 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz", - "integrity": "sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.4.tgz", + "integrity": "sha512-nZeZHyCWPfjkdU5pA/uHiTaDAFUEqkpzf1YoQT2NeSynCGYq9rxfyI3XpQbfx/a0hSnFH6TGlEXvae5Vi7GD8g==", + "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-class-features-plugin": "^7.25.4", + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -1326,12 +1137,13 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz", - "integrity": "sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", + "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", + "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-class-static-block": "^7.14.5" }, "engines": { @@ -1342,17 +1154,16 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.23.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.8.tgz", - "integrity": "sha512-yAYslGsY1bX6Knmg46RjiCiNSwJKv2IUC8qOdYKqMMr0491SXFhcHqOdRDeCRohOOIzwN/90C6mQ9qAKgrP7dg==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20", - "@babel/helper-split-export-declaration": "^7.22.6", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.4.tgz", + "integrity": "sha512-oexUfaQle2pF/b6E0dwsxQtAol9TLSO88kQvym6HHBWFliV2lGdrPieX+WgMRLSJDVzdYywk7jXbLPuO2KLTLg==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-replace-supers": "^7.25.0", + "@babel/traverse": "^7.25.4", "globals": "^11.1.0" }, "engines": { @@ -1363,12 +1174,13 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz", - "integrity": "sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", + "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/template": "^7.22.15" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/template": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1378,11 +1190,12 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz", - "integrity": "sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", + "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -1392,12 +1205,13 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz", - "integrity": "sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", + "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", + "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1407,11 +1221,12 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz", - "integrity": "sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", + "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1420,28 +1235,30 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz", - "integrity": "sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==", + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.0.tgz", + "integrity": "sha512-YLpb4LlYSc3sCUa35un84poXoraOiQucUTTu8X1j18JV+gNa8E0nyUf/CjZ171IRGr4jEguF+vzJU66QZhn29g==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" + "@babel/helper-create-regexp-features-plugin": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz", - "integrity": "sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==", + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", + "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", + "dev": true, "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" }, "engines": { "node": ">=6.9.0" @@ -1450,13 +1267,14 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz", - "integrity": "sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ==", + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", + "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1465,13 +1283,14 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-flow-strip-types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.22.5.tgz", - "integrity": "sha512-tujNbZdxdG0/54g/oua8ISToaXTFBf8EnSb5PgQSciIXWOWKX3S4+JR7ZE9ol8FZwf9kxitzkGQ+QWeov/mCiA==", + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", + "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-flow": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" }, "engines": { "node": ">=6.9.0" @@ -1481,12 +1300,13 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz", - "integrity": "sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", + "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1496,13 +1316,14 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz", - "integrity": "sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==", + "version": "7.25.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.1.tgz", + "integrity": "sha512-TVVJVdW9RKMNgJJlLtHsKDTydjZAbwIsn6ySBPQaEAUU5+gVvlJt/9nRmqVbsV/IBanRjzWoaAQKLoamWVOUuA==", + "dev": true, "dependencies": { - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.1" }, "engines": { "node": ">=6.9.0" @@ -1512,11 +1333,12 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz", - "integrity": "sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", + "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-json-strings": "^7.8.3" }, "engines": { @@ -1527,11 +1349,12 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz", - "integrity": "sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.2.tgz", + "integrity": "sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -1541,11 +1364,12 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz", - "integrity": "sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", + "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" }, "engines": { @@ -1556,11 +1380,12 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz", - "integrity": "sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", + "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1570,12 +1395,13 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz", - "integrity": "sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", + "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", + "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1585,13 +1411,14 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", - "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", + "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", + "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-simple-access": "^7.22.5" + "@babel/helper-module-transforms": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-simple-access": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1601,14 +1428,15 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.9.tgz", - "integrity": "sha512-KDlPRM6sLo4o1FkiSlXoAa8edLXFsKKIda779fbLrvmeuc3itnjCtaO6RrtoaANsIJANj+Vk1zqbZIMhkCAHVw==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.0.tgz", + "integrity": "sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw==", + "dev": true, "dependencies": { - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20" + "@babel/helper-module-transforms": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.0" }, "engines": { "node": ">=6.9.0" @@ -1618,12 +1446,13 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz", - "integrity": "sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", + "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", + "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1633,12 +1462,13 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", - "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", + "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", + "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1648,11 +1478,12 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz", - "integrity": "sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", + "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1662,11 +1493,12 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz", - "integrity": "sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", + "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" }, "engines": { @@ -1677,11 +1509,12 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz", - "integrity": "sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", + "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-numeric-separator": "^7.10.4" }, "engines": { @@ -1692,15 +1525,15 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.4.tgz", - "integrity": "sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", + "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", + "dev": true, "dependencies": { - "@babel/compat-data": "^7.23.3", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.23.3" + "@babel/plugin-transform-parameters": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1710,12 +1543,13 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz", - "integrity": "sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", + "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1725,11 +1559,12 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz", - "integrity": "sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", + "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" }, "engines": { @@ -1740,12 +1575,13 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz", - "integrity": "sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", + "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", "@babel/plugin-syntax-optional-chaining": "^7.8.3" }, "engines": { @@ -1756,11 +1592,12 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz", - "integrity": "sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", + "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1770,12 +1607,13 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz", - "integrity": "sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.4.tgz", + "integrity": "sha512-ao8BG7E2b/URaUQGqN3Tlsg+M3KlHY6rJ1O1gXAEUnZoyNQnvKyH87Kfg+FoxSeyWUB8ISZZsC91C44ZuBFytw==", + "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-class-features-plugin": "^7.25.4", + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -1785,13 +1623,14 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz", - "integrity": "sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", + "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", + "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, "engines": { @@ -1802,11 +1641,12 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz", - "integrity": "sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", + "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1815,12 +1655,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-react-constant-elements": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.22.5.tgz", - "integrity": "sha512-BF5SXoO+nX3h5OhlN78XbbDrBOffv+AxPP2ENaJOVqjWCgBDeOY3WcaUcddutGSfoap+5NEQ/q/4I3WZIvgkXA==", + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz", + "integrity": "sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1829,12 +1670,17 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.22.5.tgz", - "integrity": "sha512-PVk3WPYudRF5z4GKMEYUrLjPl38fJSKNaEOkFuoprioowGuWN6w2RKznuFNSlJx7pzzXXStPUnNSOEO0jL5EVw==", + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.2.tgz", + "integrity": "sha512-KQsqEAVBpU82NM/B/N9j9WOdphom1SZH3R+2V7INrQUH+V9EBFwZsEJl8eBIVeQE62FxJCc70jzEZwqU7RcVqA==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/types": "^7.25.2" }, "engines": { "node": ">=6.9.0" @@ -1843,16 +1689,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.5.tgz", - "integrity": "sha512-rog5gZaVbUip5iWDMTYbVM15XQq+RkUKhET/IHR6oizR+JEoN6CAfTTuHcK4vwUyzca30qqHqEpzBOnaRMWYMA==", + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.7.tgz", + "integrity": "sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ==", + "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-module-imports": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-jsx": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/plugin-transform-react-jsx": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1861,12 +1704,12 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-react-jsx-development": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz", - "integrity": "sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==", + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.7.tgz", + "integrity": "sha512-fOPQYbGSgH0HUp4UJO4sMBFjY6DuWq+2i8rixyUMb3CdGixs/gccURvYOAhajBdKDoGajFr3mUq5rH3phtkGzw==", "dependencies": { - "@babel/plugin-transform-react-jsx": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1875,13 +1718,12 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-react-pure-annotations": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.22.5.tgz", - "integrity": "sha512-gP4k85wx09q+brArVinTXhWiyzLl9UpmGva0+mWyKxk6JZequ05x3eUcIUE+FyttPKJFRRVtAvQaJ6YF9h1ZpA==", + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.7.tgz", + "integrity": "sha512-J2z+MWzZHVOemyLweMqngXrgGC42jQ//R0KdxqkIz/OrbVIIlhFI3WigZ5fO+nwFvBlncr4MGapd8vTyc7RPNQ==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1890,13 +1732,14 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz", - "integrity": "sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==", + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.7.tgz", + "integrity": "sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "regenerator-transform": "^0.15.2" + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1905,12 +1748,14 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz", - "integrity": "sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==", + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", + "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7", + "regenerator-transform": "^0.15.2" }, "engines": { "node": ">=6.9.0" @@ -1919,17 +1764,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-runtime": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.22.9.tgz", - "integrity": "sha512-9KjBH61AGJetCPYp/IEyLEp47SyybZb0nDRpBvmtEkm+rUIwxdlKpyNHI1TmsGkeuLclJdleQHRZ8XLBnnh8CQ==", + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", + "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", + "dev": true, "dependencies": { - "@babel/helper-module-imports": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5", - "babel-plugin-polyfill-corejs2": "^0.4.4", - "babel-plugin-polyfill-corejs3": "^0.8.2", - "babel-plugin-polyfill-regenerator": "^0.5.1", - "semver": "^6.3.1" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1938,20 +1779,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz", - "integrity": "sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", + "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1961,12 +1795,13 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz", - "integrity": "sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", + "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1976,11 +1811,12 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz", - "integrity": "sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", + "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1990,11 +1826,12 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz", - "integrity": "sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", + "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -2004,11 +1841,12 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz", - "integrity": "sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", + "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -2018,14 +1856,16 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.23.6.tgz", - "integrity": "sha512-6cBG5mBvUu4VUD04OHKnYzbuHNP8huDsD3EDqqpIpsswTDoqHCjLoHb6+QgsV1WsT2nipRqCPgxD3LXnEO7XfA==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.2.tgz", + "integrity": "sha512-lBwRvjSmqiMYe/pS0+1gggjJleUJi7NzjvQ1Fkqtt69hBa/0t1YuW/MLQMAPixfwaQOHUXsd6jeU3Z+vdGv3+A==", + "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.23.6", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-typescript": "^7.23.3" + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-syntax-typescript": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -2035,11 +1875,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz", - "integrity": "sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", + "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -2049,12 +1890,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz", - "integrity": "sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", + "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", + "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -2064,12 +1906,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz", - "integrity": "sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", + "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", + "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -2079,12 +1922,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz", - "integrity": "sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.4.tgz", + "integrity": "sha512-qesBxiWkgN1Q+31xUE9RcMk79eOXXDCv6tfyGMRSs4RGlioSg2WVyQAm07k726cSE56pa+Kb0y9epX2qaXzTvA==", + "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.25.2", + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -2094,25 +1938,28 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.9.tgz", - "integrity": "sha512-3kBGTNBBk9DQiPoXYS0g0BYlwTQYUTifqgKTjxUwEUkduRT2QOa0FPGBJ+NROQhGyYO5BuTJwGvBnqKDykac6A==", - "dependencies": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.23.5", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.23.3", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.23.3", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.23.7", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.4.tgz", + "integrity": "sha512-W9Gyo+KmcxjGahtt3t9fb14vFRWvPpu5pT6GBlovAK6BTBcxgjfVMSQCfJl4oi35ODrxP6xx2Wr8LNST57Mraw==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.25.4", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-validator-option": "^7.24.8", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.3", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.0", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.0", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.0", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", "@babel/plugin-syntax-class-static-block": "^7.14.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.23.3", - "@babel/plugin-syntax-import-attributes": "^7.23.3", + "@babel/plugin-syntax-import-assertions": "^7.24.7", + "@babel/plugin-syntax-import-attributes": "^7.24.7", "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", @@ -2124,59 +1971,60 @@ "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.23.3", - "@babel/plugin-transform-async-generator-functions": "^7.23.9", - "@babel/plugin-transform-async-to-generator": "^7.23.3", - "@babel/plugin-transform-block-scoped-functions": "^7.23.3", - "@babel/plugin-transform-block-scoping": "^7.23.4", - "@babel/plugin-transform-class-properties": "^7.23.3", - "@babel/plugin-transform-class-static-block": "^7.23.4", - "@babel/plugin-transform-classes": "^7.23.8", - "@babel/plugin-transform-computed-properties": "^7.23.3", - "@babel/plugin-transform-destructuring": "^7.23.3", - "@babel/plugin-transform-dotall-regex": "^7.23.3", - "@babel/plugin-transform-duplicate-keys": "^7.23.3", - "@babel/plugin-transform-dynamic-import": "^7.23.4", - "@babel/plugin-transform-exponentiation-operator": "^7.23.3", - "@babel/plugin-transform-export-namespace-from": "^7.23.4", - "@babel/plugin-transform-for-of": "^7.23.6", - "@babel/plugin-transform-function-name": "^7.23.3", - "@babel/plugin-transform-json-strings": "^7.23.4", - "@babel/plugin-transform-literals": "^7.23.3", - "@babel/plugin-transform-logical-assignment-operators": "^7.23.4", - "@babel/plugin-transform-member-expression-literals": "^7.23.3", - "@babel/plugin-transform-modules-amd": "^7.23.3", - "@babel/plugin-transform-modules-commonjs": "^7.23.3", - "@babel/plugin-transform-modules-systemjs": "^7.23.9", - "@babel/plugin-transform-modules-umd": "^7.23.3", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", - "@babel/plugin-transform-new-target": "^7.23.3", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.23.4", - "@babel/plugin-transform-numeric-separator": "^7.23.4", - "@babel/plugin-transform-object-rest-spread": "^7.23.4", - "@babel/plugin-transform-object-super": "^7.23.3", - "@babel/plugin-transform-optional-catch-binding": "^7.23.4", - "@babel/plugin-transform-optional-chaining": "^7.23.4", - "@babel/plugin-transform-parameters": "^7.23.3", - "@babel/plugin-transform-private-methods": "^7.23.3", - "@babel/plugin-transform-private-property-in-object": "^7.23.4", - "@babel/plugin-transform-property-literals": "^7.23.3", - "@babel/plugin-transform-regenerator": "^7.23.3", - "@babel/plugin-transform-reserved-words": "^7.23.3", - "@babel/plugin-transform-shorthand-properties": "^7.23.3", - "@babel/plugin-transform-spread": "^7.23.3", - "@babel/plugin-transform-sticky-regex": "^7.23.3", - "@babel/plugin-transform-template-literals": "^7.23.3", - "@babel/plugin-transform-typeof-symbol": "^7.23.3", - "@babel/plugin-transform-unicode-escapes": "^7.23.3", - "@babel/plugin-transform-unicode-property-regex": "^7.23.3", - "@babel/plugin-transform-unicode-regex": "^7.23.3", - "@babel/plugin-transform-unicode-sets-regex": "^7.23.3", + "@babel/plugin-transform-arrow-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.25.4", + "@babel/plugin-transform-async-to-generator": "^7.24.7", + "@babel/plugin-transform-block-scoped-functions": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.25.0", + "@babel/plugin-transform-class-properties": "^7.25.4", + "@babel/plugin-transform-class-static-block": "^7.24.7", + "@babel/plugin-transform-classes": "^7.25.4", + "@babel/plugin-transform-computed-properties": "^7.24.7", + "@babel/plugin-transform-destructuring": "^7.24.8", + "@babel/plugin-transform-dotall-regex": "^7.24.7", + "@babel/plugin-transform-duplicate-keys": "^7.24.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.0", + "@babel/plugin-transform-dynamic-import": "^7.24.7", + "@babel/plugin-transform-exponentiation-operator": "^7.24.7", + "@babel/plugin-transform-export-namespace-from": "^7.24.7", + "@babel/plugin-transform-for-of": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.25.1", + "@babel/plugin-transform-json-strings": "^7.24.7", + "@babel/plugin-transform-literals": "^7.25.2", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", + "@babel/plugin-transform-member-expression-literals": "^7.24.7", + "@babel/plugin-transform-modules-amd": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.8", + "@babel/plugin-transform-modules-systemjs": "^7.25.0", + "@babel/plugin-transform-modules-umd": "^7.24.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", + "@babel/plugin-transform-new-target": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-numeric-separator": "^7.24.7", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-object-super": "^7.24.7", + "@babel/plugin-transform-optional-catch-binding": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.8", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.25.4", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-property-literals": "^7.24.7", + "@babel/plugin-transform-regenerator": "^7.24.7", + "@babel/plugin-transform-reserved-words": "^7.24.7", + "@babel/plugin-transform-shorthand-properties": "^7.24.7", + "@babel/plugin-transform-spread": "^7.24.7", + "@babel/plugin-transform-sticky-regex": "^7.24.7", + "@babel/plugin-transform-template-literals": "^7.24.7", + "@babel/plugin-transform-typeof-symbol": "^7.24.8", + "@babel/plugin-transform-unicode-escapes": "^7.24.7", + "@babel/plugin-transform-unicode-property-regex": "^7.24.7", + "@babel/plugin-transform-unicode-regex": "^7.24.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.25.4", "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.8", - "babel-plugin-polyfill-corejs3": "^0.9.0", - "babel-plugin-polyfill-regenerator": "^0.5.5", - "core-js-compat": "^3.31.0", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.37.1", "semver": "^6.3.1" }, "engines": { @@ -2186,25 +2034,11 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/preset-env/node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", - "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", - "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, "node_modules/@babel/preset-env/node_modules/@babel/plugin-proposal-private-property-in-object": { "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, "engines": { "node": ">=6.9.0" }, @@ -2212,22 +2046,11 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.9.0.tgz", - "integrity": "sha512-7nZPG1uzK2Ymhy/NbaOWTg3uibM2BmGASS4vHS4szRZAIR8R6GwA/xAujpdrXU5iyklrimWnLWU+BLF9suPTqg==", - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.5.0", - "core-js-compat": "^3.34.0" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, "node_modules/@babel/preset-env/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, "bin": { "semver": "bin/semver.js" } @@ -2236,6 +2059,7 @@ "version": "0.1.6-no-external-plugins", "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/types": "^7.4.4", @@ -2246,16 +2070,17 @@ } }, "node_modules/@babel/preset-react": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.22.5.tgz", - "integrity": "sha512-M+Is3WikOpEJHgR385HbuCITPTaPRaNkibTEa9oiofmJvIsrceb4yp9RL9Kb+TE8LznmeyZqpP+Lopwcx59xPQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.7.tgz", + "integrity": "sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.22.5", - "@babel/plugin-transform-react-display-name": "^7.22.5", - "@babel/plugin-transform-react-jsx": "^7.22.5", - "@babel/plugin-transform-react-jsx-development": "^7.22.5", - "@babel/plugin-transform-react-pure-annotations": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-transform-react-display-name": "^7.24.7", + "@babel/plugin-transform-react-jsx": "^7.24.7", + "@babel/plugin-transform-react-jsx-development": "^7.24.7", + "@babel/plugin-transform-react-pure-annotations": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -2265,15 +2090,16 @@ } }, "node_modules/@babel/preset-typescript": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.23.3.tgz", - "integrity": "sha512-17oIGVlqz6CchO9RFYn5U6ZpWRZIngayYCtrPRSgANSwC2V1Jb+iP74nVxzzXJte8b8BYxrL1yY96xfhTBrNNQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz", + "integrity": "sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.22.15", - "@babel/plugin-syntax-jsx": "^7.23.3", - "@babel/plugin-transform-modules-commonjs": "^7.23.3", - "@babel/plugin-transform-typescript": "^7.23.3" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.7", + "@babel/plugin-transform-typescript": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -2285,12 +2111,13 @@ "node_modules/@babel/regjsgen": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true }, "node_modules/@babel/runtime": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.8.tgz", - "integrity": "sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz", + "integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -2298,50 +2125,34 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/runtime-corejs3": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.22.6.tgz", - "integrity": "sha512-M+37LLIRBTEVjktoJjbw4KVhupF0U/3PYUCbBwgAd9k17hoKhRu1n935QiG7Tuxv0LJOMrb2vuKEeYUlv0iyiw==", - "dev": true, - "dependencies": { - "core-js-pure": "^3.30.2", - "regenerator-runtime": "^0.13.11" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/runtime/node_modules/regenerator-runtime": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" }, "node_modules/@babel/template": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", - "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", + "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9" + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.25.0", + "@babel/types": "^7.25.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.0.tgz", - "integrity": "sha512-HfuJlI8qq3dEDmNU5ChzzpZRWq+oxCZQyMzIMEqLho+AQnhMnKQUzH6ydo3RBl/YjPCuk68Y6s0Gx0AeyULiWw==", - "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.24.0", - "@babel/types": "^7.24.0", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz", + "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.6", + "@babel/parser": "^7.25.6", + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.6", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -2350,12 +2161,12 @@ } }, "node_modules/@babel/types": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", - "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", + "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", "to-fast-properties": "^2.0.0" }, "engines": { @@ -2365,370 +2176,101 @@ "node_modules/@bcoe/v8-coverage": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" - }, - "node_modules/@csstools/normalize.css": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-12.0.0.tgz", - "integrity": "sha512-M0qqxAcwCsIVfpFQSlGN5XjXWu8l5JDZN+fPt1LeW5SZexQTgnaEvgXAY+CeygRw0EeppWHi12JxESWiWrB0Sg==" + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true }, - "node_modules/@csstools/postcss-cascade-layers": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-1.1.1.tgz", - "integrity": "sha512-+KdYrpKC5TgomQr2DlZF4lDEpHcoxnj5IGddYYfBWJAKfj1JtuHUIqMa+E1pJJ+z3kvDViWMqyqPlG4Ja7amQA==", - "dependencies": { - "@csstools/selector-specificity": "^2.0.2", - "postcss-selector-parser": "^6.0.10" - }, + "node_modules/@dicebear/adventurer": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/adventurer/-/adventurer-8.0.1.tgz", + "integrity": "sha512-dlEycOH+yETbNo3EtswFJCnG02OEgpyPpOFmSgUuRhcRKsqbMlcsiYV4wKeRvq6VvudJXp8UiHwWszLjCHTvKA==", "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" + "node": ">=16.0.0" }, "peerDependencies": { - "postcss": "^8.2" + "@dicebear/core": "^8.0.0" } }, - "node_modules/@csstools/postcss-color-function": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-1.1.1.tgz", - "integrity": "sha512-Bc0f62WmHdtRDjf5f3e2STwRAl89N2CLb+9iAwzrv4L2hncrbDwnQD9PCq0gtAt7pOI2leIV08HIBUd4jxD8cw==", - "dependencies": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" - }, + "node_modules/@dicebear/adventurer-neutral": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/adventurer-neutral/-/adventurer-neutral-8.0.1.tgz", + "integrity": "sha512-NgSz01T/K6MJn93Lk8rKPGKTx6cJe4/lNKMKjRM+4mez8S56WNdGDGUn/QY5GL3P1p01QAOMFF3hygJk3WAr3g==", "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" + "node": ">=16.0.0" }, "peerDependencies": { - "postcss": "^8.2" + "@dicebear/core": "^8.0.0" } }, - "node_modules/@csstools/postcss-font-format-keywords": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-1.0.1.tgz", - "integrity": "sha512-ZgrlzuUAjXIOc2JueK0X5sZDjCtgimVp/O5CEqTcs5ShWBa6smhWYbS0x5cVc/+rycTDbjjzoP0KTDnUneZGOg==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, + "node_modules/@dicebear/avataaars": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/avataaars/-/avataaars-8.0.1.tgz", + "integrity": "sha512-TYXqP9mq3yHOdLlJr8saXnvxj14eY2YAmoVVbT15Rp5+kPzGDyfblNsM838sP5K6JyCNeojZsGE/sPJKk/G+mA==", "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" + "node": ">=16.0.0" }, "peerDependencies": { - "postcss": "^8.2" + "@dicebear/core": "^8.0.0" } }, - "node_modules/@csstools/postcss-hwb-function": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-1.0.2.tgz", - "integrity": "sha512-YHdEru4o3Rsbjmu6vHy4UKOXZD+Rn2zmkAmLRfPet6+Jz4Ojw8cbWxe1n42VaXQhD3CQUXXTooIy8OkVbUcL+w==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, + "node_modules/@dicebear/avataaars-neutral": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/avataaars-neutral/-/avataaars-neutral-8.0.1.tgz", + "integrity": "sha512-vMV1Htaqpnz+qAVyn2tJWbRQIa6mpO/bu7dD0dumuIb45+LIpNwdUuCvkIQw2qf5ODhn1WAfYX3HEJaxRZc4lA==", "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" + "node": ">=16.0.0" }, "peerDependencies": { - "postcss": "^8.2" + "@dicebear/core": "^8.0.0" } }, - "node_modules/@csstools/postcss-ic-unit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-1.0.1.tgz", - "integrity": "sha512-Ot1rcwRAaRHNKC9tAqoqNZhjdYBzKk1POgWfhN4uCOE47ebGcLRqXjKkApVDpjifL6u2/55ekkpnFcp+s/OZUw==", - "dependencies": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" - }, + "node_modules/@dicebear/big-ears": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/big-ears/-/big-ears-8.0.1.tgz", + "integrity": "sha512-lnPRFbXsHv2EXJR2OLqJdoUIrSVUpf1z4GkCOfAi01sYNYVpfnzg3kNF77QUhkXUhaONF7d4Wz8rUduBHRtjaA==", "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" + "node": ">=16.0.0" }, "peerDependencies": { - "postcss": "^8.2" + "@dicebear/core": "^8.0.0" } }, - "node_modules/@csstools/postcss-is-pseudo-class": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-2.0.7.tgz", - "integrity": "sha512-7JPeVVZHd+jxYdULl87lvjgvWldYu+Bc62s9vD/ED6/QTGjy0jy0US/f6BG53sVMTBJ1lzKZFpYmofBN9eaRiA==", - "dependencies": { - "@csstools/selector-specificity": "^2.0.0", - "postcss-selector-parser": "^6.0.10" - }, + "node_modules/@dicebear/big-ears-neutral": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/big-ears-neutral/-/big-ears-neutral-8.0.1.tgz", + "integrity": "sha512-2FPvNpLI/ald3P8iWhX7SR986B8/DQlvrTNK/v+V0HRJvG1t6/7f9qfUL7OLf6plL7EgSUmKfMKacdiR5skZkA==", "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" + "node": ">=16.0.0" }, "peerDependencies": { - "postcss": "^8.2" + "@dicebear/core": "^8.0.0" } }, - "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" - }, + "node_modules/@dicebear/big-smile": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/big-smile/-/big-smile-8.0.1.tgz", + "integrity": "sha512-uh7FP0RgX8Qtr5zpeKUSNq028IQ3srF5LHJfQGjf4wA8R+ln/Sq0gPRJk6qMCCvPFV42b7A6f7rO7mHGnQ+qDA==", "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" + "node": ">=16.0.0" }, "peerDependencies": { - "postcss": "^8.2" + "@dicebear/core": "^8.0.0" } }, - "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", - "integrity": "sha512-jcOanIbv55OFKQ3sYeFD/T0Ti7AMXc9nM1hZWu8m/2722gOTxFg7xYu4RDLJLeZmPUVQlGzo4jhzvTUq3x4ZUw==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, + "node_modules/@dicebear/bottts": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/bottts/-/bottts-8.0.1.tgz", + "integrity": "sha512-WmaGZnKAT90EP/pzfUox22RshCk3GLB/p+6SsjD0ZIBNjcMXhaJroSoGVcHmPgQVzZBDIdW9C0qDKhkCNVVizg==", "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" + "node": ">=16.0.0" }, "peerDependencies": { - "postcss": "^8.2" + "@dicebear/core": "^8.0.0" } }, - "node_modules/@csstools/postcss-oklab-function": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-1.1.1.tgz", - "integrity": "sha512-nJpJgsdA3dA9y5pgyb/UfEzE7W5Ka7u0CX0/HIMVBNWzWemdcTH3XwANECU6anWv/ao4vVNLTMxhiPNZsTK6iA==", - "dependencies": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "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-progressive-custom-properties": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-1.3.0.tgz", - "integrity": "sha512-ASA9W1aIy5ygskZYuWams4BzafD12ULvSypmaLJT2jvQ8G0M3I8PRQhC0h7mG0Z3LI05+agZjqSR9+K9yaQQjA==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "peerDependencies": { - "postcss": "^8.3" - } - }, - "node_modules/@csstools/postcss-stepped-value-functions": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-1.0.1.tgz", - "integrity": "sha512-dz0LNoo3ijpTOQqEJLY8nyaapl6umbmDcgj4AD0lgVQ572b2eqA1iGZYTTWhrcrHztWDDRAX2DGYyw2VBjvCvQ==", - "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-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", - "integrity": "sha512-woKaLO///4bb+zZC2s80l+7cm07M7268MsyG3M0ActXXEFi6SuhvriQYcb58iiKGbjwwIU7n45iRLEHypB47Og==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/@csstools/postcss-unset-value": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-1.0.2.tgz", - "integrity": "sha512-c8J4roPBILnelAsdLr4XOAR/GsTm0GJi4XpcfvoWk3U6KiTCqiFYc63KhRMQQX35jYMp4Ao8Ij9+IZRgMfJp1g==", - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/@csstools/selector-specificity": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz", - "integrity": "sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==", - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss-selector-parser": "^6.0.10" - } - }, - "node_modules/@dicebear/adventurer": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@dicebear/adventurer/-/adventurer-8.0.1.tgz", - "integrity": "sha512-dlEycOH+yETbNo3EtswFJCnG02OEgpyPpOFmSgUuRhcRKsqbMlcsiYV4wKeRvq6VvudJXp8UiHwWszLjCHTvKA==", - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "@dicebear/core": "^8.0.0" - } - }, - "node_modules/@dicebear/adventurer-neutral": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@dicebear/adventurer-neutral/-/adventurer-neutral-8.0.1.tgz", - "integrity": "sha512-NgSz01T/K6MJn93Lk8rKPGKTx6cJe4/lNKMKjRM+4mez8S56WNdGDGUn/QY5GL3P1p01QAOMFF3hygJk3WAr3g==", - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "@dicebear/core": "^8.0.0" - } - }, - "node_modules/@dicebear/avataaars": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@dicebear/avataaars/-/avataaars-8.0.1.tgz", - "integrity": "sha512-TYXqP9mq3yHOdLlJr8saXnvxj14eY2YAmoVVbT15Rp5+kPzGDyfblNsM838sP5K6JyCNeojZsGE/sPJKk/G+mA==", - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "@dicebear/core": "^8.0.0" - } - }, - "node_modules/@dicebear/avataaars-neutral": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@dicebear/avataaars-neutral/-/avataaars-neutral-8.0.1.tgz", - "integrity": "sha512-vMV1Htaqpnz+qAVyn2tJWbRQIa6mpO/bu7dD0dumuIb45+LIpNwdUuCvkIQw2qf5ODhn1WAfYX3HEJaxRZc4lA==", - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "@dicebear/core": "^8.0.0" - } - }, - "node_modules/@dicebear/big-ears": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@dicebear/big-ears/-/big-ears-8.0.1.tgz", - "integrity": "sha512-lnPRFbXsHv2EXJR2OLqJdoUIrSVUpf1z4GkCOfAi01sYNYVpfnzg3kNF77QUhkXUhaONF7d4Wz8rUduBHRtjaA==", - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "@dicebear/core": "^8.0.0" - } - }, - "node_modules/@dicebear/big-ears-neutral": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@dicebear/big-ears-neutral/-/big-ears-neutral-8.0.1.tgz", - "integrity": "sha512-2FPvNpLI/ald3P8iWhX7SR986B8/DQlvrTNK/v+V0HRJvG1t6/7f9qfUL7OLf6plL7EgSUmKfMKacdiR5skZkA==", - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "@dicebear/core": "^8.0.0" - } - }, - "node_modules/@dicebear/big-smile": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@dicebear/big-smile/-/big-smile-8.0.1.tgz", - "integrity": "sha512-uh7FP0RgX8Qtr5zpeKUSNq028IQ3srF5LHJfQGjf4wA8R+ln/Sq0gPRJk6qMCCvPFV42b7A6f7rO7mHGnQ+qDA==", - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "@dicebear/core": "^8.0.0" - } - }, - "node_modules/@dicebear/bottts": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@dicebear/bottts/-/bottts-8.0.1.tgz", - "integrity": "sha512-WmaGZnKAT90EP/pzfUox22RshCk3GLB/p+6SsjD0ZIBNjcMXhaJroSoGVcHmPgQVzZBDIdW9C0qDKhkCNVVizg==", - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "@dicebear/core": "^8.0.0" - } - }, - "node_modules/@dicebear/bottts-neutral": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@dicebear/bottts-neutral/-/bottts-neutral-8.0.1.tgz", - "integrity": "sha512-krbD3U+UvzlY+kfQDpg9Hql1xJmmu3y9ensiU+XZXiuNw/ZavgGqpJtzpbYeF3J5GsggQlbBh/ZAK9AIKz7S3Q==", + "node_modules/@dicebear/bottts-neutral": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@dicebear/bottts-neutral/-/bottts-neutral-8.0.1.tgz", + "integrity": "sha512-krbD3U+UvzlY+kfQDpg9Hql1xJmmu3y9ensiU+XZXiuNw/ZavgGqpJtzpbYeF3J5GsggQlbBh/ZAK9AIKz7S3Q==", "engines": { "node": ">=16.0.0" }, @@ -2778,9 +2320,9 @@ } }, "node_modules/@dicebear/converter": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@dicebear/converter/-/converter-8.0.1.tgz", - "integrity": "sha512-65L04fN4V07WcUnwQuDYDH+zrP8WA6/UeIuqqH/Pv7VWoJtIk9qHlaA+XGpPr4qgRtkmY7uXVkrED/RMlqvUDA==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@dicebear/converter/-/converter-8.0.2.tgz", + "integrity": "sha512-mREmyQLIfHnt30Xzjc9ZHgDgIzbF7BXApBCYolnB2kO2Kpb14OdmsyLRsYe/Tt+Vt6sLgiigWoZFcRvbStRhLA==", "dependencies": { "@types/json-schema": "^7.0.11", "tmp-promise": "^3.0.3" @@ -2806,11 +2348,11 @@ } }, "node_modules/@dicebear/core": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@dicebear/core/-/core-8.0.1.tgz", - "integrity": "sha512-HWqvQRpVjkboQXinCOjU3poZIMd5p+32wPvc9N5fYiXe3KQLhJNw5T5XiRttDUm3XpoTvhQ4DVTPDsXT8CqrTg==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@dicebear/core/-/core-8.0.2.tgz", + "integrity": "sha512-Zr3dBAH+6BBYc2kjz7KvJCMYasQlsY9CZ7D3abgZhk/XRT4B3qxo8kP+FL8YjJvrOJyV2P7h08BAKZlTWuKXPA==", "dependencies": { - "@dicebear/converter": "8.0.1", + "@dicebear/converter": "8.0.2", "@types/json-schema": "^7.0.11" }, "engines": { @@ -3027,15 +2569,16 @@ } }, "node_modules/@emotion/babel-plugin": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", - "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz", + "integrity": "sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==", + "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.16.7", "@babel/runtime": "^7.18.3", - "@emotion/hash": "^0.9.1", - "@emotion/memoize": "^0.8.1", - "@emotion/serialize": "^1.1.2", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.2.0", "babel-plugin-macros": "^3.1.0", "convert-source-map": "^1.5.0", "escape-string-regexp": "^4.0.0", @@ -3045,47 +2588,49 @@ } }, "node_modules/@emotion/cache": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", - "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", - "dependencies": { - "@emotion/memoize": "^0.8.1", - "@emotion/sheet": "^1.2.2", - "@emotion/utils": "^1.2.1", - "@emotion/weak-memoize": "^0.3.1", + "version": "11.13.1", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.1.tgz", + "integrity": "sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.0", + "@emotion/weak-memoize": "^0.4.0", "stylis": "4.2.0" } }, "node_modules/@emotion/hash": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", - "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", + "license": "MIT" }, "node_modules/@emotion/is-prop-valid": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz", - "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.0.tgz", + "integrity": "sha512-SHetuSLvJDzuNbOdtPVbq6yMMMlLoW5Q94uDqJZqy50gcmAjxFkVqmzqSGEFq9gT2iMuIeKV1PXVWmvUhuZLlQ==", "dependencies": { - "@emotion/memoize": "^0.8.1" + "@emotion/memoize": "^0.9.0" } }, "node_modules/@emotion/memoize": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", - "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==" }, "node_modules/@emotion/react": { - "version": "11.11.4", - "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz", - "integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==", + "version": "11.13.3", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.13.3.tgz", + "integrity": "sha512-lIsdU6JNrmYfJ5EbUCf4xW1ovy5wKQ2CkPRM4xogziOxH1nXxBSjpC9YqbFAP7circxMfYp+6x676BqWcEiixg==", "dependencies": { "@babel/runtime": "^7.18.3", - "@emotion/babel-plugin": "^11.11.0", - "@emotion/cache": "^11.11.0", - "@emotion/serialize": "^1.1.3", - "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", - "@emotion/utils": "^1.2.1", - "@emotion/weak-memoize": "^0.3.1", + "@emotion/babel-plugin": "^11.12.0", + "@emotion/cache": "^11.13.0", + "@emotion/serialize": "^1.3.1", + "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0", + "@emotion/utils": "^1.4.0", + "@emotion/weak-memoize": "^0.4.0", "hoist-non-react-statics": "^3.3.1" }, "peerDependencies": { @@ -3098,33 +2643,34 @@ } }, "node_modules/@emotion/serialize": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.4.tgz", - "integrity": "sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.1.tgz", + "integrity": "sha512-dEPNKzBPU+vFPGa+z3axPRn8XVDetYORmDC0wAiej+TNcOZE70ZMJa0X7JdeoM6q/nWTMZeLpN/fTnD9o8MQBA==", "dependencies": { - "@emotion/hash": "^0.9.1", - "@emotion/memoize": "^0.8.1", - "@emotion/unitless": "^0.8.1", - "@emotion/utils": "^1.2.1", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.10.0", + "@emotion/utils": "^1.4.0", "csstype": "^3.0.2" } }, "node_modules/@emotion/sheet": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", - "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", + "license": "MIT" }, "node_modules/@emotion/styled": { - "version": "11.11.5", - "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.5.tgz", - "integrity": "sha512-/ZjjnaNKvuMPxcIiUkf/9SHoG4Q196DRl1w82hQ3WCsjo1IUR8uaGWrC6a87CrYAW0Kb/pK7hk8BnLgLRi9KoQ==", + "version": "11.13.0", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.13.0.tgz", + "integrity": "sha512-tkzkY7nQhW/zC4hztlwucpT8QEZ6eUzpXDRhww/Eej4tFfO0FxQYWRyg/c5CCXa4d/f174kqeXYjuQRnhzf6dA==", "dependencies": { "@babel/runtime": "^7.18.3", - "@emotion/babel-plugin": "^11.11.0", - "@emotion/is-prop-valid": "^1.2.2", - "@emotion/serialize": "^1.1.4", - "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", - "@emotion/utils": "^1.2.1" + "@emotion/babel-plugin": "^11.12.0", + "@emotion/is-prop-valid": "^1.3.0", + "@emotion/serialize": "^1.3.0", + "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0", + "@emotion/utils": "^1.4.0" }, "peerDependencies": { "@emotion/react": "^11.0.0-rc.0", @@ -3137,27 +2683,30 @@ } }, "node_modules/@emotion/unitless": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", - "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", + "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==" }, "node_modules/@emotion/use-insertion-effect-with-fallbacks": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", - "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz", + "integrity": "sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==", + "license": "MIT", "peerDependencies": { "react": ">=16.8.0" } }, "node_modules/@emotion/utils": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", - "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.0.tgz", + "integrity": "sha512-spEnrA1b6hDR/C68lC2M7m6ALPUHZC0lIY7jAS/B/9DuuO1ZP04eov8SMv/6fwRd8pzmsn2AuJEznRREWlQrlQ==", + "license": "MIT" }, "node_modules/@emotion/weak-memoize": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", - "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", + "license": "MIT" }, "node_modules/@esbuild/aix-ppc64": { "version": "0.21.5", @@ -3166,7 +2715,6 @@ "cpu": [ "ppc64" ], - "dev": true, "optional": true, "os": [ "aix" @@ -3182,7 +2730,6 @@ "cpu": [ "arm" ], - "dev": true, "optional": true, "os": [ "android" @@ -3198,7 +2745,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "android" @@ -3214,7 +2760,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "android" @@ -3230,7 +2775,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -3246,7 +2790,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -3262,7 +2805,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "freebsd" @@ -3278,7 +2820,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "freebsd" @@ -3294,7 +2835,6 @@ "cpu": [ "arm" ], - "dev": true, "optional": true, "os": [ "linux" @@ -3310,7 +2850,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -3326,7 +2865,6 @@ "cpu": [ "ia32" ], - "dev": true, "optional": true, "os": [ "linux" @@ -3342,7 +2880,6 @@ "cpu": [ "loong64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -3358,7 +2895,6 @@ "cpu": [ "mips64el" ], - "dev": true, "optional": true, "os": [ "linux" @@ -3374,7 +2910,6 @@ "cpu": [ "ppc64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -3390,7 +2925,6 @@ "cpu": [ "riscv64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -3406,7 +2940,6 @@ "cpu": [ "s390x" ], - "dev": true, "optional": true, "os": [ "linux" @@ -3422,7 +2955,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -3438,7 +2970,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "netbsd" @@ -3447,6 +2978,22 @@ "node": ">=12" } }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", + "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/openbsd-x64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", @@ -3454,7 +3001,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "openbsd" @@ -3470,7 +3016,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "sunos" @@ -3486,7 +3031,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -3502,7 +3046,6 @@ "cpu": [ "ia32" ], - "dev": true, "optional": true, "os": [ "win32" @@ -3518,7 +3061,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -3531,6 +3073,7 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, "dependencies": { "eslint-visitor-keys": "^3.3.0" }, @@ -3542,17 +3085,22 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", - "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "dev": true, + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz", - "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "peer": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -3575,6 +3123,9 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -3589,12 +3140,18 @@ "node_modules/@eslint/eslintrc/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0", + "peer": true }, "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "peer": true, "dependencies": { "type-fest": "^0.20.2" }, @@ -3609,6 +3166,9 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "peer": true, "dependencies": { "argparse": "^2.0.1" }, @@ -3619,12 +3179,18 @@ "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT", + "peer": true }, "node_modules/@eslint/eslintrc/node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "peer": true, "engines": { "node": ">=10" }, @@ -3633,9 +3199,12 @@ } }, "node_modules/@eslint/js": { - "version": "8.44.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz", - "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "dev": true, + "license": "MIT", + "peer": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } @@ -3658,12 +3227,12 @@ } }, "node_modules/@floating-ui/react": { - "version": "0.26.19", - "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.19.tgz", - "integrity": "sha512-Jk6zITdjjIvjO/VdQFvpRaD3qPwOHH6AoDHxjhpy+oK4KFgaSP871HYWUAPdnLmx1gQ+w/pB312co3tVml+BXA==", + "version": "0.26.22", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.22.tgz", + "integrity": "sha512-LNv4azPt8SpT4WW7Kku5JNVjLk2GcS0bGGjFTAgqOONRFo9r/aaGHHPpdiIuQbB1t8shmWyWqTTUDmZ9fcNshg==", "dependencies": { "@floating-ui/react-dom": "^2.1.1", - "@floating-ui/utils": "^0.2.4", + "@floating-ui/utils": "^0.2.7", "tabbable": "^6.0.0" }, "peerDependencies": { @@ -3684,16 +3253,9 @@ } }, "node_modules/@floating-ui/utils": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.4.tgz", - "integrity": "sha512-dWO2pw8hhi+WrXq1YJy2yCuWoL20PddgGaqTgVe4cOS9Q6qklXCiA1tJEqX6BEwRNSCP84/afac9hd4MS+zEUA==" - }, - "node_modules/@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "optional": true, - "peer": true + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.7.tgz", + "integrity": "sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA==" }, "node_modules/@graphql-typed-document-node/core": { "version": "3.2.0", @@ -3704,12 +3266,16 @@ } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", - "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "peer": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", "minimatch": "^3.0.5" }, "engines": { @@ -3720,6 +3286,8 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "peer": true, "engines": { "node": ">=12.22" }, @@ -3729,14 +3297,19 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause", + "peer": true }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", @@ -3752,6 +3325,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, "engines": { "node": ">=8" } @@ -3760,6 +3334,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, "engines": { "node": ">=8" } @@ -3774,6 +3349,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "dev": true, "dependencies": { "@jest/types": "^27.5.1", "@types/node": "*", @@ -3790,6 +3366,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -3805,6 +3382,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", + "dev": true, "dependencies": { "@jest/console": "^27.5.1", "@jest/reporters": "^27.5.1", @@ -3851,6 +3429,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -3866,6 +3445,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "dev": true, "dependencies": { "@jest/fake-timers": "^27.5.1", "@jest/types": "^27.5.1", @@ -3880,6 +3460,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "dev": true, "dependencies": { "@jest/types": "^27.5.1", "@sinonjs/fake-timers": "^8.0.1", @@ -3896,6 +3477,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", + "dev": true, "dependencies": { "@jest/environment": "^27.5.1", "@jest/types": "^27.5.1", @@ -3909,6 +3491,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", + "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", "@jest/console": "^27.5.1", @@ -3952,6 +3535,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -3967,25 +3551,16 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/@jest/schemas": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", - "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", - "dependencies": { - "@sinclair/typebox": "^0.24.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, "node_modules/@jest/source-map": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", + "dev": true, "dependencies": { "callsites": "^3.0.0", "graceful-fs": "^4.2.9", @@ -3999,6 +3574,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -4007,6 +3583,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", + "dev": true, "dependencies": { "@jest/console": "^27.5.1", "@jest/types": "^27.5.1", @@ -4021,6 +3598,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", + "dev": true, "dependencies": { "@jest/test-result": "^27.5.1", "graceful-fs": "^4.2.9", @@ -4035,6 +3613,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "dev": true, "dependencies": { "@babel/core": "^7.1.0", "@jest/types": "^27.5.1", @@ -4060,6 +3639,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -4075,6 +3655,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -4083,6 +3664,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, "dependencies": { "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", @@ -4098,6 +3680,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -4110,13 +3693,13 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" @@ -4131,9 +3714,9 @@ } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "engines": { "node": ">=6.0.0" } @@ -4142,6 +3725,8 @@ "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "optional": true, + "peer": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -4153,75 +3738,30 @@ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" - }, - "node_modules/@leichtgewicht/ip-codec": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", - "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" - }, "node_modules/@microsoft/tsdoc": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz", - "integrity": "sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==", + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.15.0.tgz", + "integrity": "sha512-HZpPoABogPvjeJOdzCOSJsXeL/SMCBgBZMVC3X3d7YYp2gf31MfxhUoYUNwf1ERPJOnQc0wkFn9trqI6ZEdZuA==", "dev": true }, "node_modules/@microsoft/tsdoc-config": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.16.2.tgz", - "integrity": "sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.17.0.tgz", + "integrity": "sha512-v/EYRXnCAIHxOHW+Plb6OWuUoMotxTN0GLatnpOb1xq0KuTNw/WI3pamJx/UbsoJP5k9MCw1QxvvhPcF9pH3Zg==", "dev": true, "dependencies": { - "@microsoft/tsdoc": "0.14.2", - "ajv": "~6.12.6", + "@microsoft/tsdoc": "0.15.0", + "ajv": "~8.12.0", "jju": "~1.4.0", - "resolve": "~1.19.0" - } - }, - "node_modules/@microsoft/tsdoc-config/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@microsoft/tsdoc-config/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/@microsoft/tsdoc-config/node_modules/resolve": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", - "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", - "dev": true, - "dependencies": { - "is-core-module": "^2.1.0", - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "resolve": "~1.22.2" } }, "node_modules/@mui/base": { @@ -4255,27 +3795,19 @@ } } }, - "node_modules/@mui/base/node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "engines": { - "node": ">=6" - } - }, "node_modules/@mui/core-downloads-tracker": { - "version": "5.16.4", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.4.tgz", - "integrity": "sha512-rNdHXhclwjEZnK+//3SR43YRx0VtjdHnUFhMSGYmAMJve+KiwEja/41EYh8V3pZKqF2geKyfcFUenTfDTYUR4w==", + "version": "5.16.7", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.7.tgz", + "integrity": "sha512-RtsCt4Geed2/v74sbihWzzRs+HsIQCfclHeORh5Ynu2fS4icIKozcSubwuG7vtzq2uW3fOR1zITSP84TNt2GoQ==", "funding": { "type": "opencollective", "url": "https://opencollective.com/mui-org" } }, "node_modules/@mui/icons-material": { - "version": "5.16.1", - "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.16.1.tgz", - "integrity": "sha512-ogQPweYba4+5XZykilwxn2/oS78uwoQ0BVBpOhhCJo0ooZsqTTsalhzP2qD/RdGqMQ8xyXPz1sYM2djTruVVVA==", + "version": "5.16.7", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.16.7.tgz", + "integrity": "sha512-UrGwDJCXEszbDI7yV047BYU5A28eGJ79keTCP4cc74WyncuVrnurlmIRxaHL8YK+LI1Kzq+/JM52IAkNnv4u+Q==", "dependencies": { "@babel/runtime": "^7.23.9" }, @@ -4298,15 +3830,15 @@ } }, "node_modules/@mui/material": { - "version": "5.16.4", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.16.4.tgz", - "integrity": "sha512-dBnh3/zRYgEVIS3OE4oTbujse3gifA0qLMmuUk13ywsDCbngJsdgwW5LuYeiT5pfA8PGPGSqM7mxNytYXgiMCw==", + "version": "5.16.7", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.16.7.tgz", + "integrity": "sha512-cwwVQxBhK60OIOqZOVLFt55t01zmarKJiJUWbk0+8s/Ix5IaUzAShqlJchxsIQ4mSrWqgcKCCXKtIlG5H+/Jmg==", "dependencies": { "@babel/runtime": "^7.23.9", - "@mui/core-downloads-tracker": "^5.16.4", - "@mui/system": "^5.16.4", + "@mui/core-downloads-tracker": "^5.16.7", + "@mui/system": "^5.16.7", "@mui/types": "^7.2.15", - "@mui/utils": "^5.16.4", + "@mui/utils": "^5.16.6", "@popperjs/core": "^2.11.8", "@types/react-transition-group": "^4.4.10", "clsx": "^2.1.0", @@ -4341,21 +3873,13 @@ } } }, - "node_modules/@mui/material/node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "engines": { - "node": ">=6" - } - }, "node_modules/@mui/private-theming": { - "version": "5.16.4", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.16.4.tgz", - "integrity": "sha512-ZsAm8cq31SJ37SVWLRlu02v9SRthxnfQofaiv14L5Bht51B0dz6yQEoVU/V8UduZDCCIrWkBHuReVfKhE/UuXA==", + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.16.6.tgz", + "integrity": "sha512-rAk+Rh8Clg7Cd7shZhyt2HGTTE5wYKNSJ5sspf28Fqm/PZ69Er9o6KX25g03/FG2dfpg5GCwZh/xOojiTfm3hw==", "dependencies": { "@babel/runtime": "^7.23.9", - "@mui/utils": "^5.16.4", + "@mui/utils": "^5.16.6", "prop-types": "^15.8.1" }, "engines": { @@ -4376,9 +3900,9 @@ } }, "node_modules/@mui/styled-engine": { - "version": "5.16.4", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.16.4.tgz", - "integrity": "sha512-0+mnkf+UiAmTVB8PZFqOhqf729Yh0Cxq29/5cA3VAyDVTRIUUQ8FXQhiAhUIbijFmM72rY80ahFPXIm4WDbzcA==", + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.16.6.tgz", + "integrity": "sha512-zaThmS67ZmtHSWToTiHslbI8jwrmITcN93LQaR2lKArbvS7Z3iLkwRoiikNWutx9MBs8Q6okKvbZq1RQYB3v7g==", "dependencies": { "@babel/runtime": "^7.23.9", "@emotion/cache": "^11.11.0", @@ -4407,9 +3931,9 @@ } }, "node_modules/@mui/system": { - "version": "5.16.4", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.16.4.tgz", - "integrity": "sha512-ET1Ujl2/8hbsD611/mqUuNArMCGv/fIWO/f8B3ZqF5iyPHM2aS74vhTNyjytncc4i6dYwGxNk+tLa7GwjNS0/w==", + "version": "5.16.7", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.16.7.tgz", + "integrity": "sha512-Jncvs/r/d/itkxh7O7opOunTqbbSSzMTHzZkNLM+FjAOg+cYAZHrPDlYe1ZGKUYORwwb2XexlWnpZp0kZ4AHuA==", "dependencies": { "@babel/runtime": "^7.23.9", "@mui/private-theming": "^5.16.4", @@ -4445,14 +3969,6 @@ } } }, - "node_modules/@mui/system/node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "engines": { - "node": ">=6" - } - }, "node_modules/@mui/types": { "version": "7.2.15", "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.15.tgz", @@ -4467,11 +3983,12 @@ } }, "node_modules/@mui/utils": { - "version": "5.16.4", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.16.4.tgz", - "integrity": "sha512-nlppYwq10TBIFqp7qxY0SvbACOXeOjeVL3pOcDsK0FT8XjrEXh9/+lkg8AEIzD16z7YfiJDQjaJG2OLkE7BxNg==", + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.16.6.tgz", + "integrity": "sha512-tWiQqlhxAt3KENNiSRL+DIn9H5xNVK6Jjf70x3PnfQPz1MPBdh7yyIcAyVBT9xiw7hP3SomRhPR7hzBMBCjqEA==", "dependencies": { "@babel/runtime": "^7.23.9", + "@mui/types": "^7.2.15", "@types/prop-types": "^15.7.12", "clsx": "^2.1.1", "prop-types": "^15.8.1", @@ -4494,31 +4011,18 @@ } } }, - "node_modules/@mui/utils/node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "engines": { - "node": ">=6" - } - }, "node_modules/@mui/x-charts": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@mui/x-charts/-/x-charts-7.8.0.tgz", - "integrity": "sha512-SosaVtx4Ig1nu/loH6Mq4peH5Pq5UvVEnsMfe4G2IEVrMxfwrktWJo+86t9LxiHTERt4wxPKnsqlhkgBIf9ePQ==", - "dependencies": { - "@babel/runtime": "^7.24.7", - "@mui/base": "^5.0.0-beta.40", - "@mui/system": "^5.15.20", - "@mui/utils": "^5.15.20", - "@react-spring/rafz": "^9.7.3", - "@react-spring/web": "^9.7.3", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@mui/x-charts/-/x-charts-7.17.0.tgz", + "integrity": "sha512-xDH/lOnb57+VBIA7q+1KlC0Ht1O46d/N2MEl1tUq1JYIXhA2Owi5cp+bcaof8Rvw5ApCmkoBxyUIjqT0guNIwA==", + "dependencies": { + "@babel/runtime": "^7.25.6", + "@mui/utils": "^5.16.6", + "@mui/x-charts-vendor": "7.16.0", + "@mui/x-internals": "7.17.0", + "@react-spring/rafz": "^9.7.4", + "@react-spring/web": "^9.7.4", "clsx": "^2.1.1", - "d3-color": "^3.1.0", - "d3-delaunay": "^6.0.4", - "d3-interpolate": "^3.0.1", - "d3-scale": "^4.0.2", - "d3-shape": "^3.2.0", "prop-types": "^15.8.1" }, "engines": { @@ -4527,7 +4031,8 @@ "peerDependencies": { "@emotion/react": "^11.9.0", "@emotion/styled": "^11.8.1", - "@mui/material": "^5.15.14", + "@mui/material": "^5.15.14 || ^6.0.0", + "@mui/system": "^5.15.14 || ^6.0.0", "react": "^17.0.0 || ^18.0.0", "react-dom": "^17.0.0 || ^18.0.0" }, @@ -4540,26 +4045,58 @@ } } }, - "node_modules/@mui/x-charts/node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "node_modules/@mui/x-charts-vendor": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@mui/x-charts-vendor/-/x-charts-vendor-7.16.0.tgz", + "integrity": "sha512-MyMCCl7eAM53rLbjqP4zbMy5hYtdeqCjAYCH2jpvBKdgugm2eaPLKOPM8bUVfen0wHA8BXleQrIrNceytFPyZA==", + "dependencies": { + "@babel/runtime": "^7.25.6", + "@types/d3-color": "^3.1.3", + "@types/d3-delaunay": "^6.0.4", + "@types/d3-interpolate": "^3.0.4", + "@types/d3-scale": "^4.0.8", + "@types/d3-shape": "^3.1.6", + "@types/d3-time": "^3.0.3", + "d3-color": "^3.1.0", + "d3-delaunay": "^6.0.4", + "d3-interpolate": "^3.0.1", + "d3-scale": "^4.0.2", + "d3-shape": "^3.2.0", + "d3-time": "^3.1.0", + "delaunator": "^5.0.1", + "robust-predicates": "^3.0.2" + } + }, + "node_modules/@mui/x-charts/node_modules/@mui/x-internals": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-7.17.0.tgz", + "integrity": "sha512-FLlAGSJl/vsuaA/8hPGazXFppyzIzxApJJDZMoTS0geUmHd0hyooISV2ltllLmrZ/DGtHhI08m8GGnHL6/vVeg==", + "dependencies": { + "@babel/runtime": "^7.25.6", + "@mui/utils": "^5.16.6" + }, "engines": { - "node": ">=6" + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0" } }, "node_modules/@mui/x-data-grid": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-7.11.0.tgz", - "integrity": "sha512-dXaIw3Noxc4d6xenS7J+zMPORG9ptkTW7B81P6QFovILSEuI/qebQhijy/IkqRvcCsuZYLL3nA89bp+EDI503Q==", - "dependencies": { - "@babel/runtime": "^7.24.8", - "@mui/system": "^5.16.2", - "@mui/utils": "^5.16.2", - "@mui/x-internals": "7.11.0", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-7.16.0.tgz", + "integrity": "sha512-71ZyffTeF8RPa399UkMlUbQ8T70kOrUK3fBXfinnal4mwgISlKwBN8EHNZZhyxSQ4vpWs3wHrHZ6MGQeXNUhJQ==", + "dependencies": { + "@babel/runtime": "^7.25.6", + "@mui/utils": "^5.16.6", + "@mui/x-internals": "7.16.0", "clsx": "^2.1.1", "prop-types": "^15.8.1", - "reselect": "^4.1.8" + "reselect": "^5.1.1" }, "engines": { "node": ">=14.0.0" @@ -4569,23 +4106,26 @@ "url": "https://opencollective.com/mui-org" }, "peerDependencies": { - "@mui/material": "^5.15.14", + "@emotion/react": "^11.9.0", + "@emotion/styled": "^11.8.1", + "@mui/material": "^5.15.14 || ^6.0.0", + "@mui/system": "^5.15.14 || ^6.0.0", "react": "^17.0.0 || ^18.0.0", "react-dom": "^17.0.0 || ^18.0.0" - } - }, - "node_modules/@mui/x-data-grid/node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "engines": { - "node": ">=6" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } } }, "node_modules/@mui/x-date-pickers": { - "version": "7.6.1", - "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-7.6.1.tgz", - "integrity": "sha512-erSq5cnOUyBgBmpHnMxIit5yhT3bl/lOaNZKpObvJtvEJetvNA9xWQ7dz/J/AufLzDuvThjusuRD0y+GmeXtiw==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-7.12.1.tgz", + "integrity": "sha512-Zj8kt3SCQbJp1qhMi+A3I4KqB8i5OY2Q11mdOEathFhqN/SQm1sUjIa1G09cGP1dPDgK1a6KM6qJGNtcw/nuWA==", "dependencies": { "@babel/runtime": "^7.24.6", "@mui/base": "^5.0.0-beta.40", @@ -4647,21 +4187,13 @@ } } }, - "node_modules/@mui/x-date-pickers/node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "engines": { - "node": ">=6" - } - }, "node_modules/@mui/x-internals": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-7.11.0.tgz", - "integrity": "sha512-GqCYylKiB4cLH9tK4JweJlT2JvPjnpXjS3TEIqtHB4BcSsezhdRrMGzHOO5zCJqkasqTirJh2t6X16Qw1llr4Q==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-7.16.0.tgz", + "integrity": "sha512-ijer5XYmWlJqWaTmF6TGH1odG7EAupv8iDWYmDm2yVR9IQ+L2nQSuhiFClI+wmGx40KS2VKOlzDMPpF0t7/HCg==", "dependencies": { - "@babel/runtime": "^7.24.8", - "@mui/utils": "^5.16.2" + "@babel/runtime": "^7.25.6", + "@mui/utils": "^5.16.6" }, "engines": { "node": ">=14.0.0" @@ -4674,18 +4206,11 @@ "react": "^17.0.0 || ^18.0.0" } }, - "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { - "version": "5.1.1-v1", - "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", - "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", - "dependencies": { - "eslint-scope": "5.1.1" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -4698,6 +4223,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, "engines": { "node": ">= 8" } @@ -4706,6 +4232,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -4718,6 +4245,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz", "integrity": "sha512-hU30BK9IUN/su0Mn9VdlVKsWBS6GyhVfqjwl1FjZN4TxP6cCw0jP2w7V3Hf5uX7M0AZJ16vey9yE0ny7Sa59ZA==", + "license": "MIT", "dependencies": { "pako": "^1.0.6" } @@ -4726,6 +4254,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@pdf-lib/upng/-/upng-1.0.1.tgz", "integrity": "sha512-dQK2FUMQtowVP00mtIksrlZhdFXQZPC+taih1q4CvPZ5vqdxR/LKBaFg0oAfzd1GlHZXXSPdQfzQnt+ViGvEIQ==", + "license": "MIT", "dependencies": { "pako": "^1.0.10" } @@ -4734,6 +4263,7 @@ "version": "1.2.6", "resolved": "https://registry.npmjs.org/@pdfme/common/-/common-1.2.6.tgz", "integrity": "sha512-ROmQ/iMUdmFS2QXD/kKDdcU5T6H3azDs2b1hE/OXs8531BPZ9ABbu9+1NRZQoNK4U/zP2F+Osb/B8ckr9lAmGg==", + "peer": true, "dependencies": { "buffer": "^6.0.3", "fontkit": "^2.0.2", @@ -4744,35 +4274,47 @@ } }, "node_modules/@pdfme/generator": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@pdfme/generator/-/generator-1.2.6.tgz", - "integrity": "sha512-rAkhr4vYa0OxVubAvLI/UIgD9+sCrcBG1SZpFCBVILgZjpqkUsscXdyukRtmHP6WaNAFGINch6PZVoshyQdGPw==", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/@pdfme/generator/-/generator-4.5.2.tgz", + "integrity": "sha512-lwvNnknTjAlmThkdxNJLcr/1/gYUW1H6xvtdX7t1OSQ/oEJfgcR9oFsUsR+OTnEYDN4zXkAmQbm1K/tnjNQWVA==", "dependencies": { - "@pdfme/common": "latest", - "@pdfme/pdf-lib": "^1.17.3", + "@pdfme/pdf-lib": "^1.18.3", "atob": "^2.1.2", - "bwip-js": "^3.2.2", "fontkit": "^2.0.2" }, - "engines": { - "node": ">=14" + "peerDependencies": { + "@pdfme/common": "latest", + "@pdfme/schemas": "latest" } }, "node_modules/@pdfme/pdf-lib": { - "version": "1.17.3", - "resolved": "https://registry.npmjs.org/@pdfme/pdf-lib/-/pdf-lib-1.17.3.tgz", - "integrity": "sha512-k3cyms42I7jVycwDuzZuLD7A9J/D8Ud1iGJ7BpAfF54QYKxG0mUG6jTDJnc+tHrpNrsoJ4iFqERy5XvMQ6SUsA==", + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/@pdfme/pdf-lib/-/pdf-lib-1.18.3.tgz", + "integrity": "sha512-Zy4lRrxhDo7pbexNCvn+nzO5gLRc1XOXQyFOHC1FJoaHzrZ3GDd4OZwR5AaGIlCwV7ocPP2+iiLFA5wQcx3s9w==", + "license": "MIT", "dependencies": { "@pdf-lib/standard-fonts": "^1.0.0", "@pdf-lib/upng": "^1.0.1", - "pako": "^1.0.11", - "tslib": "^1.11.1" + "color": "^4.2.3", + "node-html-better-parser": "^1.4.0", + "pako": "^1.0.11" } }, - "node_modules/@pdfme/pdf-lib/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "node_modules/@pdfme/schemas": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@pdfme/schemas/-/schemas-4.3.2.tgz", + "integrity": "sha512-hx6xjj9j1VLaPGf+UhA9aBIx8cSRtW3ev71AQwKpBd8QdvhuHpjPSIt5q1XGhGH8FLR8poBh1XsuyeK8yadgMg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@pdfme/pdf-lib": "^1.18.3", + "bwip-js": "^4.1.1", + "fast-xml-parser": "^4.3.2", + "fontkit": "^2.0.2" + }, + "peerDependencies": { + "@pdfme/common": "latest" + } }, "node_modules/@pkgr/core": { "version": "0.1.1", @@ -4786,244 +4328,144 @@ "url": "https://opencollective.com/unts" } }, - "node_modules/@pmmmwh/react-refresh-webpack-plugin": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.10.tgz", - "integrity": "sha512-j0Ya0hCFZPd4x40qLzbhGsh9TMtdb+CJQiso+WxLOPNasohq9cc5SNUcwsZaRH6++Xh91Xkm/xHCkuIiIu0LUA==", + "node_modules/@polka/url": { + "version": "1.0.0-next.21", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz", + "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==", + "dev": true + }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@react-aria/ssr": { + "version": "3.9.5", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.5.tgz", + "integrity": "sha512-xEwGKoysu+oXulibNUSkXf8itW0npHHTa6c4AyYeZIJyRoegeteYuFpZUBPtIDE8RfHdNsSmE1ssOkxRnwbkuQ==", "dependencies": { - "ansi-html-community": "^0.0.8", - "common-path-prefix": "^3.0.0", - "core-js-pure": "^3.23.3", - "error-stack-parser": "^2.0.6", - "find-up": "^5.0.0", - "html-entities": "^2.1.0", - "loader-utils": "^2.0.4", - "schema-utils": "^3.0.0", - "source-map": "^0.7.3" + "@swc/helpers": "^0.5.0" }, "engines": { - "node": ">= 10.13" + "node": ">= 12" }, "peerDependencies": { - "@types/webpack": "4.x || 5.x", - "react-refresh": ">=0.10.0 <1.0.0", - "sockjs-client": "^1.4.0", - "type-fest": ">=0.17.0 <4.0.0", - "webpack": ">=4.43.0 <6.0.0", - "webpack-dev-server": "3.x || 4.x", - "webpack-hot-middleware": "2.x", - "webpack-plugin-serve": "0.x || 1.x" - }, - "peerDependenciesMeta": { - "@types/webpack": { - "optional": true - }, - "sockjs-client": { - "optional": true - }, - "type-fest": { - "optional": true - }, - "webpack-dev-server": { - "optional": true - }, - "webpack-hot-middleware": { - "optional": true - }, - "webpack-plugin-serve": { - "optional": true - } + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0" } }, - "node_modules/@pmmmwh/react-refresh-webpack-plugin/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/@react-aria/ssr/node_modules/@swc/helpers": { + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.12.tgz", + "integrity": "sha512-KMZNXiGibsW9kvZAO1Pam2JPTDBm+KSHMMHWdsyI/1DbIZjT2A6Gy3hblVXUMEDvUAKq+e0vL0X0o54owWji7g==", "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "tslib": "^2.4.0" } }, - "node_modules/@pmmmwh/react-refresh-webpack-plugin/node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "node_modules/@react-spring/animated": { + "version": "9.7.4", + "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.4.tgz", + "integrity": "sha512-7As+8Pty2QlemJ9O5ecsuPKjmO0NKvmVkRR1n6mEotFgWar8FKuQt2xgxz3RTgxcccghpx1YdS1FCdElQNexmQ==", "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" + "@react-spring/shared": "~9.7.4", + "@react-spring/types": "~9.7.4" }, - "engines": { - "node": ">=8.9.0" + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/@pmmmwh/react-refresh-webpack-plugin/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "node_modules/@react-spring/core": { + "version": "9.7.4", + "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.7.4.tgz", + "integrity": "sha512-GzjA44niEJBFUe9jN3zubRDDDP2E4tBlhNlSIkTChiNf9p4ZQlgXBg50qbXfSXHQPHak/ExYxwhipKVsQ/sUTw==", "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" + "@react-spring/animated": "~9.7.4", + "@react-spring/shared": "~9.7.4", + "@react-spring/types": "~9.7.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/react-spring/donate" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/@pmmmwh/react-refresh-webpack-plugin/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "node_modules/@react-spring/rafz": { + "version": "9.7.4", + "resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.7.4.tgz", + "integrity": "sha512-mqDI6rW0Ca8IdryOMiXRhMtVGiEGLIO89vIOyFQXRIwwIMX30HLya24g9z4olDvFyeDW3+kibiKwtZnA4xhldA==" + }, + "node_modules/@react-spring/shared": { + "version": "9.7.4", + "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.7.4.tgz", + "integrity": "sha512-bEPI7cQp94dOtCFSEYpxvLxj0+xQfB5r9Ru1h8OMycsIq7zFZon1G0sHrBLaLQIWeMCllc4tVDYRTLIRv70C8w==", "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@pmmmwh/react-refresh-webpack-plugin/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@pmmmwh/react-refresh-webpack-plugin/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@polka/url": { - "version": "1.0.0-next.21", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz", - "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==", - "dev": true - }, - "node_modules/@popperjs/core": { - "version": "2.11.8", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", - "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" - } - }, - "node_modules/@react-aria/ssr": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.7.0.tgz", - "integrity": "sha512-bfufjg4ESE5giN+Fxj1XIzS5f/YIhqcGc+Ve+vUUKU8xZ8t/Xtjlv8F3kjqDBQdk//n3mluFY7xG1wQVB9rMLQ==", - "dependencies": { - "@swc/helpers": "^0.5.0" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" - } - }, - "node_modules/@react-aria/ssr/node_modules/@swc/helpers": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.1.tgz", - "integrity": "sha512-sJ902EfIzn1Fa+qYmjdQqh8tPsoxyBz+8yBKC2HKUxyezKJFwPGOn7pv4WY6QuQW//ySQi5lJjA/ZT9sNWWNTg==", - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@react-spring/animated": { - "version": "9.7.3", - "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.3.tgz", - "integrity": "sha512-5CWeNJt9pNgyvuSzQH+uy2pvTg8Y4/OisoscZIR8/ZNLIOI+CatFBhGZpDGTF/OzdNFsAoGk3wiUYTwoJ0YIvw==", - "dependencies": { - "@react-spring/shared": "~9.7.3", - "@react-spring/types": "~9.7.3" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@react-spring/core": { - "version": "9.7.3", - "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.7.3.tgz", - "integrity": "sha512-IqFdPVf3ZOC1Cx7+M0cXf4odNLxDC+n7IN3MDcVCTIOSBfqEcBebSv+vlY5AhM0zw05PDbjKrNmBpzv/AqpjnQ==", - "dependencies": { - "@react-spring/animated": "~9.7.3", - "@react-spring/shared": "~9.7.3", - "@react-spring/types": "~9.7.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/react-spring/donate" + "@react-spring/rafz": "~9.7.4", + "@react-spring/types": "~9.7.4" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/@react-spring/rafz": { - "version": "9.7.3", - "resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.7.3.tgz", - "integrity": "sha512-9vzW1zJPcC4nS3aCV+GgcsK/WLaB520Iyvm55ARHfM5AuyBqycjvh1wbmWmgCyJuX4VPoWigzemq1CaaeRSHhQ==" + "node_modules/@react-spring/types": { + "version": "9.7.4", + "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.7.4.tgz", + "integrity": "sha512-iQVztO09ZVfsletMiY+DpT/JRiBntdsdJ4uqk3UJFhrhS8mIC9ZOZbmfGSRs/kdbNPQkVyzucceDicQ/3Mlj9g==" }, - "node_modules/@react-spring/shared": { - "version": "9.7.3", - "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.7.3.tgz", - "integrity": "sha512-NEopD+9S5xYyQ0pGtioacLhL2luflh6HACSSDUZOwLHoxA5eku1UPuqcJqjwSD6luKjjLfiLOspxo43FUHKKSA==", + "node_modules/@react-spring/web": { + "version": "9.7.4", + "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.7.4.tgz", + "integrity": "sha512-UMvCZp7I5HCVIleSa4BwbNxynqvj+mJjG2m20VO2yPoi2pnCYANy58flvz9v/YcXTAvsmL655FV3pm5fbr6akA==", "dependencies": { - "@react-spring/types": "~9.7.3" + "@react-spring/animated": "~9.7.4", + "@react-spring/core": "~9.7.4", + "@react-spring/shared": "~9.7.4", + "@react-spring/types": "~9.7.4" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/@react-spring/types": { - "version": "9.7.3", - "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.7.3.tgz", - "integrity": "sha512-Kpx/fQ/ZFX31OtlqVEFfgaD1ACzul4NksrvIgYfIFq9JpDHFwQkMVZ10tbo0FU/grje4rcL4EIrjekl3kYwgWw==" - }, - "node_modules/@react-spring/web": { - "version": "9.7.3", - "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.7.3.tgz", - "integrity": "sha512-BXt6BpS9aJL/QdVqEIX9YoUy8CE6TJrU0mNCqSoxdXlIeNcEBWOfIyE6B14ENNsyQKS3wOWkiJfco0tCr/9tUg==", + "node_modules/@reduxjs/toolkit": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.2.7.tgz", + "integrity": "sha512-faI3cZbSdFb8yv9dhDTmGwclW0vk0z5o1cia+kf7gCbaCwHI5e+7tP57mJUv22pNcNbeA62GSrPpfrUfdXcQ6g==", "dependencies": { - "@react-spring/animated": "~9.7.3", - "@react-spring/core": "~9.7.3", - "@react-spring/shared": "~9.7.3", - "@react-spring/types": "~9.7.3" + "immer": "^10.0.3", + "redux": "^5.0.1", + "redux-thunk": "^3.1.0", + "reselect": "^5.1.0" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + "react": "^16.9.0 || ^17.0.0 || ^18", + "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } } }, "node_modules/@remix-run/router": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.18.0.tgz", - "integrity": "sha512-L3jkqmqoSVBVKHfpGZmLrex0lxR5SucGA0sUfFzGctehw+S/ggL9L/0NnC5mw6P8HUWpFZ3nQw3cRApjjWx9Sw==", + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.0.tgz", + "integrity": "sha512-zDICCLKEwbVYTS6TjYaWtHXxkdoUvD/QXvyVZjGCsWz5vyH7aFeONlPffPdW+Y/t6KT0MgXb2Mfjun9YpWN1dA==", "engines": { "node": ">=14.0.0" } }, "node_modules/@restart/hooks": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.10.tgz", - "integrity": "sha512-HVZhYHb+9xnN6vDPyiTmw6N4V5wD9tatL3y0zpHFeeatP1ooOD1edzd3MnJCXYlb3OeleDg+Vv16EikGrH57eA==", + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.16.tgz", + "integrity": "sha512-f7aCv7c+nU/3mF7NWLtVVr0Ra80RqsO89hO72r+Y/nvQr5+q0UFGkocElTH6MJApvReVh6JHUFYn2cw1WdHF3w==", "dependencies": { "dequal": "^2.0.3" }, @@ -5032,9 +4474,9 @@ } }, "node_modules/@restart/ui": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.6.6.tgz", - "integrity": "sha512-eC3puKuWE1SRYbojWHXnvCNHGgf3uzHCb6JOhnF4OXPibOIPEkR1sqDSkL643ydigxwh+ruCa1CmYHlzk7ikKA==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.8.0.tgz", + "integrity": "sha512-xJEOXUOTmT4FngTmhdjKFRrVVF0hwCLNPdatLCHkyS4dkiSK12cEu1Y0fjxktjJrdst9jJIc5J6ihMJCoWEN/g==", "dependencies": { "@babel/runtime": "^7.21.0", "@popperjs/core": "^2.11.6", @@ -5052,105 +4494,249 @@ } }, "node_modules/@restart/ui/node_modules/uncontrollable": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-8.0.2.tgz", - "integrity": "sha512-/GDx+K1STGtpgTsj5Dj3J51YaKxZDblbCQHTH1zHLuoBEWodj6MjtRVv3TUijj1JYLRLSFsFzN8NV4M3QV4d9w==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-8.0.4.tgz", + "integrity": "sha512-ulRWYWHvscPFc0QQXvyJjY6LIXU56f0h8pQFvhxiKk5V1fcI8gp9Ht9leVAhrVjzqMw0BgjspBINx9r6oyJUvQ==", "peerDependencies": { "react": ">=16.14.0" } }, - "node_modules/@rollup/plugin-babel": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", - "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", - "dependencies": { - "@babel/helper-module-imports": "^7.10.4", - "@rollup/pluginutils": "^3.1.0" - }, - "engines": { - "node": ">= 10.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0", - "@types/babel__core": "^7.1.9", - "rollup": "^1.20.0||^2.0.0" - }, - "peerDependenciesMeta": { - "@types/babel__core": { - "optional": true - } - } + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.3.tgz", + "integrity": "sha512-MmKSfaB9GX+zXl6E8z4koOr/xU63AMVleLEa64v7R0QF/ZloMs5vcD1sHgM64GXXS1csaJutG+ddtzcueI/BLg==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.3.tgz", + "integrity": "sha512-zrt8ecH07PE3sB4jPOggweBjJMzI1JG5xI2DIsUbkA+7K+Gkjys6eV7i9pOenNSDJH3eOr/jLb/PzqtmdwDq5g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.3.tgz", + "integrity": "sha512-P0UxIOrKNBFTQaXTxOH4RxuEBVCgEA5UTNV6Yz7z9QHnUJ7eLX9reOd/NYMO3+XZO2cco19mXTxDMXxit4R/eQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.3.tgz", + "integrity": "sha512-L1M0vKGO5ASKntqtsFEjTq/fD91vAqnzeaF6sfNAy55aD+Hi2pBI5DKwCO+UNDQHWsDViJLqshxOahXyLSh3EA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.3.tgz", + "integrity": "sha512-btVgIsCjuYFKUjopPoWiDqmoUXQDiW2A4C3Mtmp5vACm7/GnyuprqIDPNczeyR5W8rTXEbkmrJux7cJmD99D2g==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.3.tgz", + "integrity": "sha512-zmjbSphplZlau6ZTkxd3+NMtE4UKVy7U4aVFMmHcgO5CUbw17ZP6QCgyxhzGaU/wFFdTfiojjbLG3/0p9HhAqA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.3.tgz", + "integrity": "sha512-nSZfcZtAnQPRZmUkUQwZq2OjQciR6tEoJaZVFvLHsj0MF6QhNMg0fQ6mUOsiCUpTqxTx0/O6gX0V/nYc7LrgPw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.3.tgz", + "integrity": "sha512-MnvSPGO8KJXIMGlQDYfvYS3IosFN2rKsvxRpPO2l2cum+Z3exiExLwVU+GExL96pn8IP+GdH8Tz70EpBhO0sIQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.3.tgz", + "integrity": "sha512-+W+p/9QNDr2vE2AXU0qIy0qQE75E8RTwTwgqS2G5CRQ11vzq0tbnfBd6brWhS9bCRjAjepJe2fvvkvS3dno+iw==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.3.tgz", + "integrity": "sha512-yXH6K6KfqGXaxHrtr+Uoy+JpNlUlI46BKVyonGiaD74ravdnF9BUNC+vV+SIuB96hUMGShhKV693rF9QDfO6nQ==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.3.tgz", + "integrity": "sha512-R8cwY9wcnApN/KDYWTH4gV/ypvy9yZUHlbJvfaiXSB48JO3KpwSpjOGqO4jnGkLDSk1hgjYkTbTt6Q7uvPf8eg==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.3.tgz", + "integrity": "sha512-kZPbX/NOPh0vhS5sI+dR8L1bU2cSO9FgxwM8r7wHzGydzfSjLRCFAT87GR5U9scj2rhzN3JPYVC7NoBbl4FZ0g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.3.tgz", + "integrity": "sha512-S0Yq+xA1VEH66uiMNhijsWAafffydd2X5b77eLHfRmfLsRSpbiAWiRHV6DEpz6aOToPsgid7TI9rGd6zB1rhbg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.3.tgz", + "integrity": "sha512-9isNzeL34yquCPyerog+IMCNxKR8XYmGd0tHSV+OVx0TmE0aJOo9uw4fZfUuk2qxobP5sug6vNdZR6u7Mw7Q+Q==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.3.tgz", + "integrity": "sha512-nMIdKnfZfzn1Vsk+RuOvl43ONTZXoAPUUxgcU0tXooqg4YrAqzfKzVenqqk2g5efWh46/D28cKFrOzDSW28gTA==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.3.tgz", + "integrity": "sha512-fOvu7PCQjAj4eWDEuD8Xz5gpzFqXzGlxHZozHP4b9Jxv9APtdxL6STqztDzMLuRXEc4UpXGGhx029Xgm91QBeA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/@rollup/plugin-node-resolve": { - "version": "11.2.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", - "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==", + "node_modules/@shikijs/core": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.17.6.tgz", + "integrity": "sha512-9ztslig6/YmCg/XwESAXbKjAjOhaq6HVced9NY6qcbDz1X5g/S90Wco2vMjBNX/6V71ASkzri76JewSGPa7kiQ==", "dependencies": { - "@rollup/pluginutils": "^3.1.0", - "@types/resolve": "1.17.1", - "builtin-modules": "^3.1.0", - "deepmerge": "^4.2.2", - "is-module": "^1.0.0", - "resolve": "^1.19.0" - }, - "engines": { - "node": ">= 10.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0" + "@shikijs/engine-javascript": "1.17.6", + "@shikijs/engine-oniguruma": "1.17.6", + "@shikijs/types": "1.17.6", + "@shikijs/vscode-textmate": "^9.2.2", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.2" } }, - "node_modules/@rollup/plugin-replace": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz", - "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==", + "node_modules/@shikijs/engine-javascript": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.17.6.tgz", + "integrity": "sha512-5EEZj8tVcierNxm4V0UMS2PVoflb0UJPalWWV8l9rRg+oOfnr5VivqBJbkyq5grltVPvByIXvVbY8GSM/356jQ==", "dependencies": { - "@rollup/pluginutils": "^3.1.0", - "magic-string": "^0.25.7" - }, - "peerDependencies": { - "rollup": "^1.20.0 || ^2.0.0" + "@shikijs/types": "1.17.6", + "oniguruma-to-js": "0.4.3" } }, - "node_modules/@rollup/pluginutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", - "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "node_modules/@shikijs/engine-oniguruma": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.17.6.tgz", + "integrity": "sha512-NLfWDMXFYe0nDHFbEoyZdz89aIIey3bTfF3zLYSUNTXks5s4uinZVmuPOFf1HfTeGqIn8uErJSBc3VnpJO7Alw==", "dependencies": { - "@types/estree": "0.0.39", - "estree-walker": "^1.0.1", - "picomatch": "^2.2.2" - }, - "engines": { - "node": ">= 8.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0" + "@shikijs/types": "1.17.6", + "@shikijs/vscode-textmate": "^9.2.2" } }, - "node_modules/@rollup/pluginutils/node_modules/@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==" - }, - "node_modules/@rushstack/eslint-patch": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.3.2.tgz", - "integrity": "sha512-V+MvGwaHH03hYhY+k6Ef/xKd6RYlc4q8WBx+2ANmipHJcKuktNcI/NgEsJgdSUF6Lw32njT6OnrRsKYCdgHjYw==" - }, - "node_modules/@shikijs/core": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.10.3.tgz", - "integrity": "sha512-D45PMaBaeDHxww+EkcDQtDAtzv00Gcsp72ukBtaLSmqRvh0WgGMq3Al0rl1QQBZfuneO75NXMIzEZGFitThWbg==", - "peer": true, + "node_modules/@shikijs/types": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.17.6.tgz", + "integrity": "sha512-ndTFa2TJi2w51ddKQDn3Jy8f6K4E5Q2x3dA3Hmsd3+YmxDQ10UWHjcw7VbVbKzv3VcUvYPLy+z9neqytSzUMUg==", "dependencies": { + "@shikijs/vscode-textmate": "^9.2.2", "@types/hast": "^3.0.4" } }, - "node_modules/@sinclair/typebox": { - "version": "0.24.51", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", - "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==" + "node_modules/@shikijs/vscode-textmate": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-9.2.2.tgz", + "integrity": "sha512-TMp15K+GGYrWlZM8+Lnj9EaHEFmOen0WJBrfa17hF7taDOYthuPPV0GWzfd/9iMij0akS/8Yw2ikquH7uVi/fg==" }, "node_modules/@sindresorhus/is": { "version": "0.14.0", @@ -5165,6 +4751,7 @@ "version": "1.8.6", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "dev": true, "dependencies": { "type-detect": "4.0.8" } @@ -5173,21 +4760,11 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", + "dev": true, "dependencies": { "@sinonjs/commons": "^1.7.0" } }, - "node_modules/@surma/rollup-plugin-off-main-thread": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", - "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==", - "dependencies": { - "ejs": "^3.1.6", - "json5": "^2.2.0", - "magic-string": "^0.25.0", - "string.prototype.matchall": "^4.0.6" - } - }, "node_modules/@svgr/babel-plugin-add-jsx-attribute": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.5.1.tgz", @@ -5413,237 +4990,6 @@ "@svgr/core": "^6.0.0" } }, - "node_modules/@svgr/plugin-svgo": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-5.5.0.tgz", - "integrity": "sha512-r5swKk46GuQl4RrVejVwpeeJaydoxkdwkM1mBKOgJLBUJPGaLci6ylg/IjhrRsREKDkr4kbMWdgOtbXEh0fyLQ==", - "dependencies": { - "cosmiconfig": "^7.0.0", - "deepmerge": "^4.2.2", - "svgo": "^1.2.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/webpack": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-5.5.0.tgz", - "integrity": "sha512-DOBOK255wfQxguUta2INKkzPj6AIS6iafZYiYmHn6W3pHlycSRRlvWKCfLDG10fXfLWqE3DJHgRUOyJYmARa7g==", - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/plugin-transform-react-constant-elements": "^7.12.1", - "@babel/preset-env": "^7.12.1", - "@babel/preset-react": "^7.12.5", - "@svgr/core": "^5.5.0", - "@svgr/plugin-jsx": "^5.5.0", - "@svgr/plugin-svgo": "^5.5.0", - "loader-utils": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/webpack/node_modules/@svgr/babel-plugin-add-jsx-attribute": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz", - "integrity": "sha512-ZFf2gs/8/6B8PnSofI0inYXr2SDNTDScPXhN7k5EqD4aZ3gi6u+rbmZHVB8IM3wDyx8ntKACZbtXSm7oZGRqVg==", - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/webpack/node_modules/@svgr/babel-plugin-remove-jsx-attribute": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-5.4.0.tgz", - "integrity": "sha512-yaS4o2PgUtwLFGTKbsiAy6D0o3ugcUhWK0Z45umJ66EPWunAz9fuFw2gJuje6wqQvQWOTJvIahUwndOXb7QCPg==", - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/webpack/node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-5.0.1.tgz", - "integrity": "sha512-LA72+88A11ND/yFIMzyuLRSMJ+tRKeYKeQ+mR3DcAZ5I4h5CPWN9AHyUzJbWSYp/u2u0xhmgOe0+E41+GjEueA==", - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/webpack/node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-5.0.1.tgz", - "integrity": "sha512-PoiE6ZD2Eiy5mK+fjHqwGOS+IXX0wq/YDtNyIgOrc6ejFnxN4b13pRpiIPbtPwHEc+NT2KCjteAcq33/F1Y9KQ==", - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/webpack/node_modules/@svgr/babel-plugin-svg-dynamic-title": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-5.4.0.tgz", - "integrity": "sha512-zSOZH8PdZOpuG1ZVx/cLVePB2ibo3WPpqo7gFIjLV9a0QsuQAzJiwwqmuEdTaW2pegyBE17Uu15mOgOcgabQZg==", - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/webpack/node_modules/@svgr/babel-plugin-svg-em-dimensions": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-5.4.0.tgz", - "integrity": "sha512-cPzDbDA5oT/sPXDCUYoVXEmm3VIoAWAPT6mSPTJNbQaBNUuEKVKyGH93oDY4e42PYHRW67N5alJx/eEol20abw==", - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/webpack/node_modules/@svgr/babel-plugin-transform-react-native-svg": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-5.4.0.tgz", - "integrity": "sha512-3eYP/SaopZ41GHwXma7Rmxcv9uRslRDTY1estspeB1w1ueZWd/tPlMfEOoccYpEMZU3jD4OU7YitnXcF5hLW2Q==", - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/webpack/node_modules/@svgr/babel-plugin-transform-svg-component": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-5.5.0.tgz", - "integrity": "sha512-q4jSH1UUvbrsOtlo/tKcgSeiCHRSBdXoIoqX1pgcKK/aU3JD27wmMKwGtpB8qRYUYoyXvfGxUVKchLuR5pB3rQ==", - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/webpack/node_modules/@svgr/babel-preset": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-5.5.0.tgz", - "integrity": "sha512-4FiXBjvQ+z2j7yASeGPEi8VD/5rrGQk4Xrq3EdJmoZgz/tpqChpo5hgXDvmEauwtvOc52q8ghhZK4Oy7qph4ig==", - "dependencies": { - "@svgr/babel-plugin-add-jsx-attribute": "^5.4.0", - "@svgr/babel-plugin-remove-jsx-attribute": "^5.4.0", - "@svgr/babel-plugin-remove-jsx-empty-expression": "^5.0.1", - "@svgr/babel-plugin-replace-jsx-attribute-value": "^5.0.1", - "@svgr/babel-plugin-svg-dynamic-title": "^5.4.0", - "@svgr/babel-plugin-svg-em-dimensions": "^5.4.0", - "@svgr/babel-plugin-transform-react-native-svg": "^5.4.0", - "@svgr/babel-plugin-transform-svg-component": "^5.5.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/webpack/node_modules/@svgr/core": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/core/-/core-5.5.0.tgz", - "integrity": "sha512-q52VOcsJPvV3jO1wkPtzTuKlvX7Y3xIcWRpCMtBF3MrteZJtBfQw/+u0B1BHy5ColpQc1/YVTrPEtSYIMNZlrQ==", - "dependencies": { - "@svgr/plugin-jsx": "^5.5.0", - "camelcase": "^6.2.0", - "cosmiconfig": "^7.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/webpack/node_modules/@svgr/hast-util-to-babel-ast": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-5.5.0.tgz", - "integrity": "sha512-cAaR/CAiZRB8GP32N+1jocovUtvlj0+e65TB50/6Lcime+EA49m/8l+P2ko+XPJ4dw3xaPS3jOL4F2X4KWxoeQ==", - "dependencies": { - "@babel/types": "^7.12.6" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/webpack/node_modules/@svgr/plugin-jsx": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-5.5.0.tgz", - "integrity": "sha512-V/wVh33j12hGh05IDg8GpIUXbjAPnTdPTKuP4VNLggnwaHMPNQNae2pRnyTAILWCQdz5GyMqtO488g7CKM8CBA==", - "dependencies": { - "@babel/core": "^7.12.3", - "@svgr/babel-preset": "^5.5.0", - "@svgr/hast-util-to-babel-ast": "^5.5.0", - "svg-parser": "^2.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/webpack/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@svgr/webpack/node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, "node_modules/@swc/helpers": { "version": "0.4.14", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", @@ -5665,35 +5011,23 @@ } }, "node_modules/@testing-library/dom": { - "version": "7.31.2", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.31.2.tgz", - "integrity": "sha512-3UqjCpey6HiTZT92vODYLPxTBWlM8ZOOjr3LX5F37/VRipW2M1kX6I/Cm4VXzteZqfGfagg8yXywpcOgQBlNsQ==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", + "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", "dev": true, + "peer": true, "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", - "@types/aria-query": "^4.2.0", - "aria-query": "^4.2.2", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.6", - "lz-string": "^1.4.4", - "pretty-format": "^26.6.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@testing-library/dom/node_modules/aria-query": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", - "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.10.2", - "@babel/runtime-corejs3": "^7.10.2" + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" }, "engines": { - "node": ">=6.0" + "node": ">=18" } }, "node_modules/@testing-library/dom/node_modules/chalk": { @@ -5701,6 +5035,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "peer": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -5712,43 +5047,93 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/@testing-library/dom/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@testing-library/dom/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true, + "peer": true + }, "node_modules/@testing-library/jest-dom": { - "version": "5.16.5", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz", - "integrity": "sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.5.0.tgz", + "integrity": "sha512-xGGHpBXYSHUUr6XsKBfs85TWlYKpTc37cSBBVrXcib2MkHLboWlkClhWF37JKlDb9KEq3dHs+f2xR7XJEWGBxA==", "dev": true, "dependencies": { - "@adobe/css-tools": "^4.0.1", - "@babel/runtime": "^7.9.2", - "@types/testing-library__jest-dom": "^5.9.1", + "@adobe/css-tools": "^4.4.0", "aria-query": "^5.0.0", "chalk": "^3.0.0", "css.escape": "^1.5.1", - "dom-accessibility-api": "^0.5.6", - "lodash": "^4.17.15", + "dom-accessibility-api": "^0.6.3", + "lodash": "^4.17.21", "redent": "^3.0.0" }, "engines": { - "node": ">=8", + "node": ">=14", "npm": ">=6", "yarn": ">=1" } }, + "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true, + "license": "MIT" + }, "node_modules/@testing-library/react": { - "version": "11.2.7", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-11.2.7.tgz", - "integrity": "sha512-tzRNp7pzd5QmbtXNG/mhdcl7Awfu/Iz1RaVHY75zTdOkmHCuzMhRL83gWHSgOAcjS3CCbyfwUHMZgRJb4kAfpA==", + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.0.0.tgz", + "integrity": "sha512-guuxUKRWQ+FgNX0h0NS0FIq3Q3uLtWVpBzcLOggmfMoUpgBnzBzvLLd4fbm6yS8ydJd94cIfY4yP9qUQjM2KwQ==", "dev": true, "dependencies": { - "@babel/runtime": "^7.12.5", - "@testing-library/dom": "^7.28.1" + "@babel/runtime": "^7.12.5" }, "engines": { - "node": ">=10" + "node": ">=18" }, "peerDependencies": { - "react": "*", - "react-dom": "*" + "@testing-library/dom": "^10.0.0", + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, "node_modules/@testing-library/user-event": { @@ -5771,28 +5156,22 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true, "engines": { "node": ">= 6" } }, - "node_modules/@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/@types/aria-query": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz", - "integrity": "sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==", - "dev": true + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true, + "peer": true }, "node_modules/@types/babel__core": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", - "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", @@ -5826,98 +5205,80 @@ "@babel/types": "^7.20.7" } }, - "node_modules/@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==" }, - "node_modules/@types/bonjour": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz", - "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==", + "node_modules/@types/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", "dependencies": { - "@types/node": "*" + "@types/d3-color": "*" } }, - "node_modules/@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "node_modules/@types/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz", + "integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==", "dependencies": { - "@types/node": "*" + "@types/d3-time": "*" } }, - "node_modules/@types/connect-history-api-fallback": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz", - "integrity": "sha512-4x5FkPpLipqwthjPsF7ZRbOv3uoLUFkTA9G9v583qi4pACvq0uTELrB8OLUzPWUI4IJIyvM85vzkV1nyiI2Lig==", + "node_modules/@types/d3-shape": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.6.tgz", + "integrity": "sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==", "dependencies": { - "@types/express-serve-static-core": "*", - "@types/node": "*" + "@types/d3-path": "*" } }, + "node_modules/@types/d3-time": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.3.tgz", + "integrity": "sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==" + }, "node_modules/@types/eslint": { "version": "8.44.0", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.0.tgz", "integrity": "sha512-gsF+c/0XOguWgaOgvFs+xnnRqt9GwgTvIks36WpE6ueeI4KCEHHd8K/CKHqhOqrJKsYH8m27kRzQEvWXAwXUTw==", + "dev": true, + "optional": true, + "peer": true, "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, - "node_modules/@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", + "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", + "dev": true, "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", - "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==" - }, - "node_modules/@types/express": { - "version": "4.17.17", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", - "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.17.35", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", - "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/graceful-fs": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", - "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", - "dependencies": { - "@types/node": "*" + "@types/node": "*" } }, "node_modules/@types/hast": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "peer": true, "dependencies": { "@types/unist": "*" } @@ -5929,32 +5290,14 @@ "dev": true }, "node_modules/@types/hoist-non-react-statics": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", - "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz", + "integrity": "sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==", "dependencies": { "@types/react": "*", "hoist-non-react-statics": "^3.3.0" } }, - "node_modules/@types/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" - }, - "node_modules/@types/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==" - }, - "node_modules/@types/http-proxy": { - "version": "1.17.11", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.11.tgz", - "integrity": "sha512-HC8G7c1WmaF2ekqpnFq626xd3Zz0uvaqFmBJNRZCGEZCXkvSdJoNFn/8Ygbd9fKNQj8UzLdCETaI0UWPAjK7IA==", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/inquirer": { "version": "9.0.7", "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-9.0.7.tgz", @@ -5968,12 +5311,14 @@ "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==" + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true }, "node_modules/@types/istanbul-lib-report": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, "dependencies": { "@types/istanbul-lib-coverage": "*" } @@ -5982,6 +5327,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, "dependencies": { "@types/istanbul-lib-report": "*" } @@ -6010,26 +5356,24 @@ "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" - }, - "node_modules/@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true }, - "node_modules/@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "optional": true, - "peer": true + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "dependencies": { + "@types/unist": "*" + } }, "node_modules/@types/node": { - "version": "20.12.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz", - "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==", + "version": "22.5.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz", + "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", + "devOptional": true, "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.19.2" } }, "node_modules/@types/node-fetch": { @@ -6056,13 +5400,6 @@ "node": ">= 6" } }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "optional": true, - "peer": true - }, "node_modules/@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", @@ -6071,35 +5408,20 @@ "node_modules/@types/prettier": { "version": "2.7.3", "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", - "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==" + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", + "dev": true }, "node_modules/@types/prop-types": { "version": "15.7.12", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" }, - "node_modules/@types/q": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz", - "integrity": "sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ==" - }, - "node_modules/@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" - }, - "node_modules/@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" - }, "node_modules/@types/react": { - "version": "17.0.62", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.62.tgz", - "integrity": "sha512-eANCyz9DG8p/Vdhr0ZKST8JV12PhH2ACCDYlFw6DIO+D+ca+uP4jtEDEpVqXZrh/uZdXQGwk7whJa3ah5DtyLw==", + "version": "18.3.3", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", + "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", "dependencies": { "@types/prop-types": "*", - "@types/scheduler": "*", "csstype": "^3.0.2" } }, @@ -6122,24 +5444,22 @@ } }, "node_modules/@types/react-datepicker": { - "version": "4.11.2", - "resolved": "https://registry.npmjs.org/@types/react-datepicker/-/react-datepicker-4.11.2.tgz", - "integrity": "sha512-ELYyX3lb3K1WltqdlF1hbnaDGgzlF6PIR5T4W38cSEcfrQDIrPE+Ioq5pwRe/KEJ+ihHMjvTVZQkwJx0pWMNHQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@types/react-datepicker/-/react-datepicker-7.0.0.tgz", + "integrity": "sha512-4tWwOUq589tozyQPBVEqGNng5DaZkomx5IVNuur868yYdgjH6RaL373/HKiVt1IDoNNXYiTGspm1F7kjrarM8Q==", + "deprecated": "This is a stub types definition. react-datepicker provides its own type definitions, so you do not need this installed.", "dev": true, "dependencies": { - "@popperjs/core": "^2.9.2", - "@types/react": "*", - "date-fns": "^2.0.1", - "react-popper": "^2.2.5" + "react-datepicker": "*" } }, "node_modules/@types/react-dom": { - "version": "17.0.20", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.20.tgz", - "integrity": "sha512-4pzIjSxDueZZ90F52mU3aPoogkHIoSIDG+oQ+wQK7Cy2B9S+MvOqY0uEA/qawKz381qrEDkvpwyt8Bm31I8sbA==", + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", "dev": true, "dependencies": { - "@types/react": "^17" + "@types/react": "*" } }, "node_modules/@types/react-google-recaptcha": { @@ -6152,9 +5472,9 @@ } }, "node_modules/@types/react-redux": { - "version": "7.1.25", - "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.25.tgz", - "integrity": "sha512-bAGh4e+w5D8dajd6InASVIyCo4pZLJ66oLb80F9OBLO1gKESbZcRCJpTT6uLXX+HAB57zw1WTdwJdAsewuTweg==", + "version": "7.1.34", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.34.tgz", + "integrity": "sha512-GdFaVjEbYv4Fthm2ZLvj1VSCedV7TqE5y1kNwnjSdBOTXuRSgowux6J8TAct15T3CKBr63UMk+2CO7ilRhyrAQ==", "dependencies": { "@types/hoist-non-react-statics": "^3.3.0", "@types/react": "*", @@ -6162,6 +5482,14 @@ "redux": "^4.0.0" } }, + "node_modules/@types/react-redux/node_modules/redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "dependencies": { + "@babel/runtime": "^7.9.2" + } + }, "node_modules/@types/react-router": { "version": "5.1.20", "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz", @@ -6191,86 +5519,20 @@ "@types/react": "*" } }, - "node_modules/@types/resolve": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", - "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" - }, "node_modules/@types/sanitize-html": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/@types/sanitize-html/-/sanitize-html-2.11.0.tgz", - "integrity": "sha512-7oxPGNQHXLHE48r/r/qjn7q0hlrs3kL7oZnGj0Wf/h9tj/6ibFyRkNbsDxaBBZ4XUZ0Dx5LGCyDJ04ytSofacQ==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/@types/sanitize-html/-/sanitize-html-2.13.0.tgz", + "integrity": "sha512-X31WxbvW9TjIhZZNyNBZ/p5ax4ti7qsNDBDEnH4zAgmEh35YnFD1UiS6z9Cd34kKm0LslFW0KPmTQzu/oGtsqQ==", "dev": true, "dependencies": { "htmlparser2": "^8.0.0" } }, - "node_modules/@types/scheduler": { - "version": "0.16.3", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", - "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==" - }, - "node_modules/@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==" - }, - "node_modules/@types/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", - "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", - "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/serve-static": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", - "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", - "dependencies": { - "@types/http-errors": "*", - "@types/mime": "*", - "@types/node": "*" - } - }, - "node_modules/@types/sockjs": { - "version": "0.3.33", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", - "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" - }, - "node_modules/@types/testing-library__jest-dom": { - "version": "5.14.8", - "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.8.tgz", - "integrity": "sha512-NRfJE9Cgpmu4fx716q9SYmU4jxxhYRU1BQo239Txt/9N3EC745XZX1Yl7h/SBIDlo1ANVOCRB4YDXjaQdoKCHQ==", - "dev": true, - "dependencies": { - "@types/jest": "*" - } + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true }, "node_modules/@types/through": { "version": "0.0.33", @@ -6281,34 +5543,26 @@ "@types/node": "*" } }, - "node_modules/@types/trusted-types": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.3.tgz", - "integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==" - }, "node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "peer": true + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==" }, - "node_modules/@types/warning": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.0.tgz", - "integrity": "sha512-t/Tvs5qR47OLOr+4E9ckN8AmP2Tf16gWq+/qA4iUGS/OOyHVO8wv2vjJuX8SNOUTJyWb+2t7wJm6cXILFnOROA==" + "node_modules/@types/use-sync-external-store": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", + "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" }, - "node_modules/@types/ws": { - "version": "8.5.5", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz", - "integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==", - "dependencies": { - "@types/node": "*" - } + "node_modules/@types/warning": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.3.tgz", + "integrity": "sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q==" }, "node_modules/@types/yargs": { "version": "16.0.5", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.5.tgz", "integrity": "sha512-AxO/ADJOBFJScHbWhq2xAhlWP24rY4aCEG/NFaMvbT3X2MgRsLjhjQwsn0Zi5zn0LG9jUhCCZMeX9Dkuw6k+vQ==", + "dev": true, "dependencies": { "@types/yargs-parser": "*" } @@ -6316,34 +5570,36 @@ "node_modules/@types/yargs-parser": { "version": "21.0.0", "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", - "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", - "dependencies": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/type-utils": "5.62.0", - "@typescript-eslint/utils": "5.62.0", - "debug": "^4.3.4", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.5.0.tgz", + "integrity": "sha512-lHS5hvz33iUFQKuPFGheAB84LwcJ60G8vKnEhnfcK1l8kGVLro2SFYW6K0/tj8FUhRJ0VHyg1oAfg50QGbPPHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.5.0", + "@typescript-eslint/type-utils": "8.5.0", + "@typescript-eslint/utils": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0", "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -6351,85 +5607,156 @@ } } }, - "node_modules/@typescript-eslint/experimental-utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.62.0.tgz", - "integrity": "sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.5.0.tgz", + "integrity": "sha512-06JOQ9Qgj33yvBEx6tpC8ecP9o860rsR22hWMEd12WcTRrfaFgHr2RB/CA/B+7BMhHkXT4chg2MyboGdFGawYg==", + "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "5.62.0" + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.5.0.tgz", + "integrity": "sha512-qjkormnQS5wF9pjSi6q60bKUHH44j2APxfh9TQRXK8wbYVeDYYdYJGIROL87LGZZ2gz3Rbmjc736qyL8deVtdw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/parser": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", - "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.5.0.tgz", + "integrity": "sha512-vEG2Sf9P8BPQ+d0pxdfndw3xIXaoSjliG0/Ejk7UggByZPKXmJmw3GW5jV2gHNQNawBUyfahoSiCFVov0Ruf7Q==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "debug": "^4.3.4" + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, "peerDependenciesMeta": { "typescript": { "optional": true } } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.5.0.tgz", + "integrity": "sha512-6yyGYVL0e+VzGYp60wvkBHiqDWOpT63pdMV2CVG4LVDd5uR6q1qQN/7LafBZtAtNIn/mqXjsSeS5ggv/P0iECw==", + "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.5.0", + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/typescript-estree": "8.5.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" } }, - "node_modules/@typescript-eslint/type-utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", - "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.5.0.tgz", + "integrity": "sha512-yTPqMnbAZJNy2Xq2XU8AdtOW9tJIr+UQb64aXB9f3B1498Zx9JorVgFJcZpEc9UBuCCrdzKID2RGAMkYcDtZOw==", + "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "5.62.0", - "@typescript-eslint/utils": "5.62.0", - "debug": "^4.3.4", - "tsutils": "^3.21.0" + "@typescript-eslint/types": "8.5.0", + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.5.0.tgz", + "integrity": "sha512-gF77eNv0Xz2UJg/NbpWJ0kqAm35UMsvZf1GHj8D9MRFTj/V3tAciIWXfmPLsAAF/vUlpWPvUDyH1jjsr0cMVWw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "8.5.0", + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/typescript-estree": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "*" + "eslint": "^8.57.0 || ^9.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -6437,33 +5764,56 @@ } } }, - "node_modules/@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.5.0.tgz", + "integrity": "sha512-06JOQ9Qgj33yvBEx6tpC8ecP9o860rsR22hWMEd12WcTRrfaFgHr2RB/CA/B+7BMhHkXT4chg2MyboGdFGawYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.5.0.tgz", + "integrity": "sha512-qjkormnQS5wF9pjSi6q60bKUHH44j2APxfh9TQRXK8wbYVeDYYdYJGIROL87LGZZ2gz3Rbmjc736qyL8deVtdw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.5.0.tgz", + "integrity": "sha512-vEG2Sf9P8BPQ+d0pxdfndw3xIXaoSjliG0/Ejk7UggByZPKXmJmw3GW5jV2gHNQNawBUyfahoSiCFVov0Ruf7Q==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0", "debug": "^4.3.4", - "globby": "^11.1.0", + "fast-glob": "^3.3.2", "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -6475,182 +5825,250 @@ } } }, - "node_modules/@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.5.0.tgz", + "integrity": "sha512-yTPqMnbAZJNy2Xq2XU8AdtOW9tJIr+UQb64aXB9f3B1498Zx9JorVgFJcZpEc9UBuCCrdzKID2RGAMkYcDtZOw==", + "dev": true, + "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" + "@typescript-eslint/types": "8.5.0", + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "node_modules/@typescript-eslint/parser/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=16 || 14 >=14.17" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@webassemblyjs/ast": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", - "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "node_modules/@typescript-eslint/type-utils": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.5.0.tgz", + "integrity": "sha512-N1K8Ix+lUM+cIDhL2uekVn/ZD7TZW+9/rwz8DclQpcQ9rk4sIL5CAlBC0CugWKREmDjBzI/kQqU4wkg46jWLYA==", + "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + "@typescript-eslint/typescript-estree": "8.5.0", + "@typescript-eslint/utils": "8.5.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", - "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==" - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.5.0.tgz", + "integrity": "sha512-06JOQ9Qgj33yvBEx6tpC8ecP9o860rsR22hWMEd12WcTRrfaFgHr2RB/CA/B+7BMhHkXT4chg2MyboGdFGawYg==", + "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@xtuc/long": "4.2.2" + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", - "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", - "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6" + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.5.0.tgz", + "integrity": "sha512-qjkormnQS5wF9pjSi6q60bKUHH44j2APxfh9TQRXK8wbYVeDYYdYJGIROL87LGZZ2gz3Rbmjc736qyL8deVtdw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.5.0.tgz", + "integrity": "sha512-vEG2Sf9P8BPQ+d0pxdfndw3xIXaoSjliG0/Ejk7UggByZPKXmJmw3GW5jV2gHNQNawBUyfahoSiCFVov0Ruf7Q==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@xtuc/ieee754": "^1.2.0" + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.5.0.tgz", + "integrity": "sha512-6yyGYVL0e+VzGYp60wvkBHiqDWOpT63pdMV2CVG4LVDd5uR6q1qQN/7LafBZtAtNIn/mqXjsSeS5ggv/P0iECw==", + "dev": true, + "license": "MIT", "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.5.0", + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/typescript-estree": "8.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + } }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", - "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.5.0.tgz", + "integrity": "sha512-yTPqMnbAZJNy2Xq2XU8AdtOW9tJIr+UQb64aXB9f3B1498Zx9JorVgFJcZpEc9UBuCCrdzKID2RGAMkYcDtZOw==", + "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-opt": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6", - "@webassemblyjs/wast-printer": "1.11.6" + "@typescript-eslint/types": "8.5.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", - "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "node_modules/@typescript-eslint/type-utils/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "balanced-match": "^1.0.0" } }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", - "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "node_modules/@typescript-eslint/type-utils/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6" + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", - "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "license": "ISC" + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.1.tgz", + "integrity": "sha512-m/V2syj5CuVnaxcUJOQRel/Wr31FFXRFlnOoq1TVtkCxsY5veGMTEmpWHndrhB2U8ScHtCQB1e+4hWYExQc6Lg==", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@babel/core": "^7.24.5", + "@babel/plugin-transform-react-jsx-self": "^7.24.5", + "@babel/plugin-transform-react-jsx-source": "^7.24.1", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.14.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0" + } + }, + "node_modules/@vitejs/plugin-react/node_modules/react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", - "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "node_modules/@wry/caches": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@wry/caches/-/caches-1.0.1.tgz", + "integrity": "sha512-bXuaUNLVVkD20wcGBWRyo7j9N3TxePEWFZj2Y+r9OoUzfqmavM84+mFykRicNsBqatba5JLay1t48wxaXaWnlA==", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@xtuc/long": "4.2.2" + "tslib": "^2.3.0" + }, + "engines": { + "node": ">=8" } }, "node_modules/@wry/context": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/@wry/context/-/context-0.7.3.tgz", - "integrity": "sha512-Nl8WTesHp89RF803Se9X3IiHjdmLBrIvPMaJkl+rKVJAYyPsz1TEUbu89943HpvujtSJgDUx9W4vZw3K1Mr3sA==", + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@wry/context/-/context-0.7.4.tgz", + "integrity": "sha512-jmT7Sb4ZQWI5iyu3lobQxICu2nC/vbUhP0vIdd6tHC9PTfenmRmuIFqktc6GH9cgi+ZHnsLWPvfSvc4DrYmKiQ==", "dependencies": { "tslib": "^2.3.0" }, @@ -6659,9 +6077,9 @@ } }, "node_modules/@wry/equality": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/@wry/equality/-/equality-0.5.6.tgz", - "integrity": "sha512-D46sfMTngaYlrH+OspKf8mIJETntFnf6Hsjb0V41jAXJ7Bx2kB8Rv8RCUujuVWYttFtHkUNp7g+FwxNQAr6mXA==", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@wry/equality/-/equality-0.5.7.tgz", + "integrity": "sha512-BRFORjsTuQv5gxcXsuDXx6oGRhuVsEGwZy6LOzRRfgu+eSfxbhUQ9L9YtSEIuIjY/o7g3iWFjrc5eSY1GXP2Dw==", "dependencies": { "tslib": "^2.3.0" }, @@ -6670,9 +6088,9 @@ } }, "node_modules/@wry/trie": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@wry/trie/-/trie-0.4.3.tgz", - "integrity": "sha512-I6bHwH0fSf6RqQcnnXLJKhkSXG45MFral3GxPaY4uAl0LYDZM+YDVDAiU9bYwjTuysy1S0IeecWtmq1SZA3M1w==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@wry/trie/-/trie-0.5.0.tgz", + "integrity": "sha512-FNoYzHawTMk/6KMQoEG5O4PuioX19UbwdQKF44yw0nLfOypfQdjtfZzo/UIJWAJ23sNIFbD1Ug9lbaDGMwbqQA==", "dependencies": { "tslib": "^2.3.0" }, @@ -6680,44 +6098,17 @@ "node": ">=8" } }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" - }, "node_modules/abab": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==" - }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "optional": true, - "peer": true - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "dev": true }, "node_modules/acorn": { "version": "8.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "devOptional": true, "bin": { "acorn": "bin/acorn" }, @@ -6729,6 +6120,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "dev": true, "dependencies": { "acorn": "^7.1.1", "acorn-walk": "^7.1.1" @@ -6738,6 +6130,7 @@ "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -6745,18 +6138,13 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "peerDependencies": { - "acorn": "^8" - } - }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peer": true, "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -6765,47 +6153,16 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true, "engines": { "node": ">=0.4.0" } }, - "node_modules/address": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", - "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/adjust-sourcemap-loader": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz", - "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==", - "dependencies": { - "loader-utils": "^2.0.0", - "regex-parser": "^2.2.11" - }, - "engines": { - "node": ">=8.9" - } - }, - "node_modules/adjust-sourcemap-loader/node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, "dependencies": { "debug": "4" }, @@ -6813,39 +6170,11 @@ "node": ">= 6.0.0" } }, - "node_modules/agentkeepalive": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.3.0.tgz", - "integrity": "sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==", - "optional": true, - "peer": true, - "dependencies": { - "debug": "^4.1.0", - "depd": "^2.0.0", - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "optional": true, - "peer": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/ajv": { "version": "8.12.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -6857,22 +6186,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, "node_modules/ansi-align": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", @@ -6896,17 +6209,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "engines": [ - "node >= 0.8.0" - ], - "bin": { - "ansi-html": "bin/ansi-html" - } - }, "node_modules/ansi-red": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", @@ -6948,15 +6250,11 @@ "node": ">=0.10.0" } }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" - }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "devOptional": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -6965,32 +6263,6 @@ "node": ">= 8" } }, - "node_modules/aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "optional": true, - "peer": true - }, - "node_modules/are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "optional": true, - "peer": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "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", @@ -7003,6 +6275,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, "dependencies": { "dequal": "^2.0.3" } @@ -7011,6 +6284,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, "dependencies": { "call-bind": "^1.0.5", "is-array-buffer": "^3.0.4" @@ -7022,20 +6296,17 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array-flatten": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", - "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" - }, "node_modules/array-includes": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", - "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", "is-string": "^1.0.7" }, "engines": { @@ -7045,18 +6316,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "engines": { - "node": ">=8" - } - }, "node_modules/array.prototype.findlast": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -7076,6 +6340,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -7094,6 +6359,7 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -7111,6 +6377,7 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -7124,51 +6391,27 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.reduce": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz", - "integrity": "sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.toreversed": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", - "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - } - }, "node_modules/array.prototype.tosorted": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz", - "integrity": "sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.1.0", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/arraybuffer.prototype.slice": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.5", @@ -7186,73 +6429,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" - }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "optional": true, - "peer": true, - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/ast-types-flow": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==" - }, - "node_modules/async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" - }, - "node_modules/async-foreach": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", - "integrity": "sha512-VUeSMD8nEGBWaZK4lizI1sf3yEC7pnAQ/mrI7pC2fBz2s/tq5jWWEngTwaf0Gruu/OoXRGLGg1XFqpYBiGTYJA==", - "optional": true, - "peer": true, - "engines": { - "node": "*" - } - }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "engines": { - "node": ">= 4.0.0" - } + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true }, "node_modules/atob": { "version": "2.1.2", @@ -7273,42 +6454,11 @@ "gulp-header": "^1.7.1" } }, - "node_modules/autoprefixer": { - "version": "10.4.14", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz", - "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - } - ], - "dependencies": { - "browserslist": "^4.21.5", - "caniuse-lite": "^1.0.30001464", - "fraction.js": "^4.2.0", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, "node_modules/available-typed-arrays": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, "dependencies": { "possible-typed-array-names": "^1.0.0" }, @@ -7319,119 +6469,218 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", - "optional": true, - "peer": true, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, "engines": { - "node": "*" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" } }, - "node_modules/aws4": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", - "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", - "optional": true, - "peer": true + "node_modules/babel-jest/node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/axe-core": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.2.tgz", - "integrity": "sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g==", + "node_modules/babel-jest/node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, "engines": { - "node": ">=4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/axobject-query": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", - "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", + "node_modules/babel-jest/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, "dependencies": { - "dequal": "^2.0.3" + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-jest/node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/babel-jest/node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" } }, - "node_modules/babel-loader": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.3.0.tgz", - "integrity": "sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q==", + "node_modules/babel-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "find-cache-dir": "^3.3.1", - "loader-utils": "^2.0.0", - "make-dir": "^3.1.0", - "schema-utils": "^2.6.5" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 8.9" + "node": ">=10" }, - "peerDependencies": { - "@babel/core": "^7.0.0", - "webpack": ">=2" + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/babel-loader/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/babel-jest/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/babel-jest/node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "node_modules/babel-loader/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "peerDependencies": { - "ajv": "^6.9.1" + "node_modules/babel-jest/node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/babel-loader/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "node_modules/babel-jest/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/babel-loader/node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "node_modules/babel-jest/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, "engines": { - "node": ">=8.9.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/babel-loader/node_modules/schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "node_modules/babel-jest/node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, "dependencies": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 8.9.0" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/babel-jest/node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/babel-plugin-istanbul": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@istanbuljs/load-nyc-config": "^1.0.0", @@ -7443,6 +6692,21 @@ "node": ">=8" } }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/babel-plugin-macros": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", @@ -7457,97 +6721,71 @@ "npm": ">=6" } }, - "node_modules/babel-plugin-named-asset-import": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.8.tgz", - "integrity": "sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q==", - "peerDependencies": { - "@babel/core": "^7.1.0" - } - }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.8", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.8.tgz", - "integrity": "sha512-OtIuQfafSzpo/LhnJaykc0R/MMnuLSSVjVYy9mHArIZ9qTCSZ6TpWCuEKZYVoN//t8HqBNScHrOtCrIK5IaGLg==", + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "dev": true, "dependencies": { "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.5.0", + "@babel/helper-define-polyfill-provider": "^0.6.2", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/babel-plugin-polyfill-corejs2/node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", - "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", - "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, "bin": { "semver": "bin/semver.js" } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.2.tgz", - "integrity": "sha512-Cid+Jv1BrY9ReW9lIfNlNpsI53N+FN7gE+f73zLAUbr9C52W4gKLWSByx47pfDJsEysojKArqOtOKZSVIIUTuQ==", + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", + "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.4.1", - "core-js-compat": "^3.31.0" + "@babel/helper-define-polyfill-provider": "^0.6.2", + "core-js-compat": "^3.38.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.5.tgz", - "integrity": "sha512-OJGYZlhLqBh2DDHeqAxWB1XIvr49CxiJ2gIt61/PU55CQK4Z58OzMqjDe1zwQdQk+rBYsRc+1rJmdajM3gimHg==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.5.0" + "@babel/helper-define-polyfill-provider": "^0.6.2" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/babel-plugin-polyfill-regenerator/node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", - "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", + "node_modules/babel-plugin-transform-import-meta": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-import-meta/-/babel-plugin-transform-import-meta-2.2.1.tgz", + "integrity": "sha512-AxNh27Pcg8Kt112RGa3Vod2QS2YXKKJ6+nSvRtv7qQTJAdx0MZa4UHZ4lnxHUWA2MNbLuZQv5FVab4P1CoLOWw==", "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" + "@babel/template": "^7.4.4", + "tslib": "^2.4.0" }, "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "@babel/core": "^7.10.0" } }, - "node_modules/babel-plugin-transform-react-remove-prop-types": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz", - "integrity": "sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==" - }, "node_modules/babel-preset-current-node-syntax": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, "dependencies": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", @@ -7566,27 +6804,20 @@ "@babel/core": "^7.0.0" } }, - "node_modules/babel-preset-react-app": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-react-app/-/babel-preset-react-app-10.0.1.tgz", - "integrity": "sha512-b0D9IZ1WhhCWkrTXyFuIIgqGzSkRIH5D5AmB0bXbzYAB1OBAwHcUeyWW2LorutLWF5btNo/N7r/cIdmvvKJlYg==", - "dependencies": { - "@babel/core": "^7.16.0", - "@babel/plugin-proposal-class-properties": "^7.16.0", - "@babel/plugin-proposal-decorators": "^7.16.4", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.0", - "@babel/plugin-proposal-numeric-separator": "^7.16.0", - "@babel/plugin-proposal-optional-chaining": "^7.16.0", - "@babel/plugin-proposal-private-methods": "^7.16.0", - "@babel/plugin-transform-flow-strip-types": "^7.16.0", - "@babel/plugin-transform-react-display-name": "^7.16.0", - "@babel/plugin-transform-runtime": "^7.16.4", - "@babel/preset-env": "^7.16.4", - "@babel/preset-react": "^7.16.0", - "@babel/preset-typescript": "^7.16.0", - "@babel/runtime": "^7.16.3", - "babel-plugin-macros": "^3.1.0", - "babel-plugin-transform-react-remove-prop-types": "^0.4.24" + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, "node_modules/balanced-match": { @@ -7613,47 +6844,11 @@ } ] }, - "node_modules/batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" - }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "optional": true, - "peer": true, - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, - "node_modules/bfj": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/bfj/-/bfj-7.0.2.tgz", - "integrity": "sha512-+e/UqUzwmzJamNF50tBV6tZPTORow7gQ96iFow+8b562OdMpEK0BcJEq2OSPEDmAbSMBQ7PKZ87ubFkgxpYWgw==", - "dependencies": { - "bluebird": "^3.5.5", - "check-types": "^11.1.1", - "hoopy": "^0.1.4", - "tryer": "^1.0.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "engines": { - "node": "*" - } - }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "devOptional": true, "engines": { "node": ">=8" } @@ -7691,109 +6886,22 @@ "ieee754": "^1.1.13" } }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, - "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/body-parser/node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/bonjour-service": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.1.1.tgz", - "integrity": "sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg==", - "dependencies": { - "array-flatten": "^2.1.2", - "dns-equal": "^1.0.0", - "fast-deep-equal": "^3.1.3", - "multicast-dns": "^7.2.5" - } - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" - }, - "node_modules/bootstrap": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz", - "integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/twbs" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/bootstrap" - } - ], - "peerDependencies": { - "@popperjs/core": "^2.11.8" + "node_modules/bootstrap": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz", + "integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], + "peerDependencies": { + "@popperjs/core": "^2.11.8" } }, "node_modules/boxen": { @@ -7862,6 +6970,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -7871,6 +6980,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "devOptional": true, "dependencies": { "fill-range": "^7.1.1" }, @@ -7889,12 +6999,13 @@ "node_modules/browser-process-hrtime": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", - "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==" + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", + "dev": true }, "node_modules/browserslist": { - "version": "4.22.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz", - "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", "funding": [ { "type": "opencollective", @@ -7910,10 +7021,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001580", - "electron-to-chromium": "^1.4.648", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" }, "bin": { "browserslist": "cli.js" @@ -7926,6 +7037,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, "dependencies": { "node-int64": "^0.4.0" } @@ -7948,6 +7060,7 @@ "url": "https://feross.org/support" } ], + "peer": true, "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" @@ -7958,33 +7071,16 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, - "node_modules/builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/bwip-js": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/bwip-js/-/bwip-js-3.4.3.tgz", - "integrity": "sha512-x+mQE/bq5V0Nlkn4Jd4cktNlEPH4zeIGSOEQNUtsV/cCJNiBba7u/S9PYR1pmD2WDeeZAIbYTjvGHjBQ21RXvw==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/bwip-js/-/bwip-js-4.5.1.tgz", + "integrity": "sha512-83yQCKiIftz5YonnsTh6wIkFoHHWl+B/XaGWD1UdRw7aB6XP9JtyYP9n8sRy3m5rzL+Ch/RUPnu28UW0RrPZUA==", + "license": "MIT", + "peer": true, "bin": { "bwip-js": "bin/bwip-js.js" } }, - "node_modules/bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/cacheable-request": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", @@ -8040,6 +7136,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -8062,64 +7159,19 @@ "node": ">=6" } }, - "node_modules/camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dependencies": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, "node_modules/camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, "engines": { "node": ">=6" } }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "optional": true, - "peer": true, - "dependencies": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/caniuse-api": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", - "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", - "dependencies": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - } - }, "node_modules/caniuse-lite": { - "version": "1.0.30001587", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001587.tgz", - "integrity": "sha512-HMFNotUmLXn71BQxg8cijvqxnIAofforZOwGsxyXJ0qugTdspUF4sPSJ2vhgprHCB996tIDzEq1ubumPDV8ULA==", + "version": "1.0.30001660", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001660.tgz", + "integrity": "sha512-GacvNTTuATm26qC74pt+ad1fW15mlQ/zuTzzY1ZoIzECTP8HURDfF43kNxPgf7H1jmelCBQTTbBNxdSXOA7Bqg==", "funding": [ { "type": "opencollective", @@ -8135,21 +7187,15 @@ } ] }, - "node_modules/case-sensitive-paths-webpack-plugin": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", - "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", - "engines": { - "node": ">=4" + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", - "optional": true, - "peer": true - }, "node_modules/chalk": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", @@ -8167,24 +7213,39 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, "engines": { "node": ">=10" } }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" }, - "node_modules/check-types": { - "version": "11.2.2", - "resolved": "https://registry.npmjs.org/check-types/-/check-types-11.2.2.tgz", - "integrity": "sha512-HBiYvXvn9Z70Z88XKjz3AEKd4HJhBXsa3j7xFnITAzoS8+q6eIGi8qDB8FKPBAjtuxjI/zFpwuiCb8oDtKOYrA==" - }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "devOptional": true, "funding": [ { "type": "individual", @@ -8207,28 +7268,11 @@ "fsevents": "~2.3.2" } }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "optional": true, - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "engines": { - "node": ">=6.0" - } - }, "node_modules/ci-info": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "dev": true, "funding": [ { "type": "github", @@ -8242,42 +7286,14 @@ "node_modules/cjs-module-lexer": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", - "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==" + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "dev": true }, "node_modules/classnames": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" }, - "node_modules/clean-css": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.2.tgz", - "integrity": "sha512-JVJbM+f3d3Q704rF4bqQ5UUyTtuJ0JRKNbTKVEeujCCBoMdkEi+V+e8oktO9qGQNSvHrFTM6JZRXrUvGR1czww==", - "dependencies": { - "source-map": "~0.6.0" - }, - "engines": { - "node": ">= 10.0" - } - }, - "node_modules/clean-css/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "optional": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, "node_modules/cli-boxes": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", @@ -8291,15 +7307,15 @@ } }, "node_modules/cli-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", - "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", "dev": true, "dependencies": { - "restore-cursor": "^4.0.0" + "restore-cursor": "^5.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -8351,9 +7367,9 @@ "dev": true }, "node_modules/cli-truncate/node_modules/string-width": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", - "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "dependencies": { "emoji-regex": "^10.3.0", @@ -8394,6 +7410,7 @@ "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -8421,9 +7438,9 @@ } }, "node_modules/clsx": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", - "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", "engines": { "node": ">=6" } @@ -8432,88 +7449,12 @@ "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, "engines": { "iojs": ">= 1.0.0", "node": ">= 0.12.0" } }, - "node_modules/coa": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", - "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", - "dependencies": { - "@types/q": "^1.5.1", - "chalk": "^2.4.1", - "q": "^1.1.2" - }, - "engines": { - "node": ">= 4.0" - } - }, - "node_modules/coa/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/coa/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/coa/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/coa/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/coa/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/coa/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/coa/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/coffee-script": { "version": "1.12.7", "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz", @@ -8530,7 +7471,21 @@ "node_modules/collect-v8-coverage": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", - "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==" + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } }, "node_modules/color-convert": { "version": "2.0.1", @@ -8548,30 +7503,27 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "optional": true, - "peer": true, - "bin": { - "color-support": "bin.js" + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" } }, - "node_modules/colord": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", - "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==" - }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -8579,6 +7531,15 @@ "node": ">= 0.8" } }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/commander": { "version": "9.5.0", "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", @@ -8588,74 +7549,11 @@ "node": "^12.20.0 || >=14" } }, - "node_modules/common-path-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", - "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==" - }, - "node_modules/common-tags": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", - "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==" - }, - "node_modules/compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dependencies": { - "mime-db": ">= 1.43.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "dependencies": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/compression/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/compression/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/compression/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true }, "node_modules/concat-stream": { "version": "1.6.2", @@ -8736,11 +7634,6 @@ "node": ">=8" } }, - "node_modules/confusing-browser-globals": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", - "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==" - }, "node_modules/connect": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", @@ -8756,14 +7649,6 @@ "node": ">= 0.10.0" } }, - "node_modules/connect-history-api-fallback": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", - "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", - "engines": { - "node": ">=0.8" - } - }, "node_modules/connect/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -8779,82 +7664,24 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "optional": true, - "peer": true - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/convert-source-map": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" }, - "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" - }, - "node_modules/core-js": { - "version": "3.31.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.31.1.tgz", - "integrity": "sha512-2sKLtfq1eFST7l7v62zaqXacPc7uG8ZAya8ogijLhTtaKNcpzpB4TMoTw2Si+8GYKRwFPMMtUT0263QFWFfqyQ==", - "hasInstallScript": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, "node_modules/core-js-compat": { - "version": "3.36.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.0.tgz", - "integrity": "sha512-iV9Pd/PsgjNWBXeq8XRtWVSgz2tKAfhfvBs7qxYty+RlRd+OCksaWmOnc4JKrTc1cToXL1N0s3l/vwlxPtdElw==", + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", + "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==", + "dev": true, "dependencies": { - "browserslist": "^4.22.3" + "browserslist": "^4.23.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/core-js" } }, - "node_modules/core-js-pure": { - "version": "3.31.1", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.31.1.tgz", - "integrity": "sha512-w+C62kvWti0EPs4KPMCMVv9DriHSXfQOCQ94bGGBiEW5rrbtt/Rz8n5Krhfw9cpFyzXBjf3DB3QnPdEzGDY4Fw==", - "hasInstallScript": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", @@ -8905,6 +7732,7 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -8918,27 +7746,11 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true, "engines": { "node": ">=8" } }, - "node_modules/css-blank-pseudo": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz", - "integrity": "sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ==", - "dependencies": { - "postcss-selector-parser": "^6.0.9" - }, - "bin": { - "css-blank-pseudo": "dist/cli.cjs" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, "node_modules/css-box-model": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz", @@ -8947,500 +7759,142 @@ "tiny-invariant": "^1.0.6" } }, - "node_modules/css-declaration-sorter": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", - "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==", - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.0.9" - } + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true }, - "node_modules/css-has-pseudo": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-3.0.4.tgz", - "integrity": "sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw==", - "dependencies": { - "postcss-selector-parser": "^6.0.9" - }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, "bin": { - "css-has-pseudo": "dist/cli.cjs" + "cssesc": "bin/cssesc" }, "engines": { - "node": "^12 || ^14 || >=16" - }, - "peerDependencies": { - "postcss": "^8.4" + "node": ">=4" } }, - "node_modules/css-loader": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.8.1.tgz", - "integrity": "sha512-xDAXtEVGlD0gJ07iclwWVkLoZOpEvAWaSyf6W18S2pOC//K8+qUDIx8IIT3D+HjnmkJPQeesOPv5aiUaJsCM2g==", - "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.21", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.3", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.3.8" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } + "node_modules/cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", + "dev": true }, - "node_modules/css-minimizer-webpack-plugin": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz", - "integrity": "sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==", + "node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, "dependencies": { - "cssnano": "^5.0.6", - "jest-worker": "^27.0.2", - "postcss": "^8.3.5", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0", - "source-map": "^0.6.1" + "cssom": "~0.3.6" }, "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@parcel/css": { - "optional": true - }, - "clean-css": { - "optional": true - }, - "csso": { - "optional": true - }, - "esbuild": { - "optional": true - } + "node": ">=8" } }, - "node_modules/css-minimizer-webpack-plugin/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/customize-cra": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/customize-cra/-/customize-cra-1.0.0.tgz", + "integrity": "sha512-DbtaLuy59224U+xCiukkxSq8clq++MOtJ1Et7LED1fLszWe88EoblEYFBJ895sB1mC6B4uu3xPT/IjClELhMbA==", "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" + "lodash.flow": "^3.5.0" } }, - "node_modules/css-minimizer-webpack-plugin/node_modules/schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" + "internmap": "1 - 2" }, "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=12" } }, - "node_modules/css-minimizer-webpack-plugin/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/css-prefers-color-scheme": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz", - "integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==", - "bin": { - "css-prefers-color-scheme": "dist/cli.cjs" + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "dependencies": { + "delaunator": "5" }, "engines": { - "node": "^12 || ^14 || >=16" - }, - "peerDependencies": { - "postcss": "^8.4" + "node": ">=12" } }, - "node_modules/css-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", - "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^3.2.1", - "domutils": "^1.7.0", - "nth-check": "^1.0.2" + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "engines": { + "node": ">=12" } }, - "node_modules/css-select-base-adapter": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", - "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==" + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } }, - "node_modules/css-select/node_modules/css-what": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", - "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==", + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" + "node": ">=12" } }, - "node_modules/css-select/node_modules/dom-serializer": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", - "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", "dependencies": { - "domelementtype": "^2.0.1", - "entities": "^2.0.0" + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" } }, - "node_modules/css-select/node_modules/domutils": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", - "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", "dependencies": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "node_modules/css-select/node_modules/domutils/node_modules/domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" - }, - "node_modules/css-select/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/css-select/node_modules/nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", - "dependencies": { - "boolbase": "~1.0.0" - } - }, - "node_modules/css-tree": { - "version": "1.0.0-alpha.37", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", - "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", - "dependencies": { - "mdn-data": "2.0.4", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/css-tree/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css.escape": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", - "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", - "dev": true - }, - "node_modules/cssdb": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.6.0.tgz", - "integrity": "sha512-Nna7rph8V0jC6+JBY4Vk4ndErUmfJfV6NJCaZdurL0omggabiy+QB2HCQtu5c/ACLZ0I7REv7A4QyPIoYzZx0w==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - } - ] - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cssnano": { - "version": "5.1.15", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.15.tgz", - "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==", - "dependencies": { - "cssnano-preset-default": "^5.2.14", - "lilconfig": "^2.0.3", - "yaml": "^1.10.2" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/cssnano" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/cssnano-preset-default": { - "version": "5.2.14", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz", - "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==", - "dependencies": { - "css-declaration-sorter": "^6.3.1", - "cssnano-utils": "^3.1.0", - "postcss-calc": "^8.2.3", - "postcss-colormin": "^5.3.1", - "postcss-convert-values": "^5.1.3", - "postcss-discard-comments": "^5.1.2", - "postcss-discard-duplicates": "^5.1.0", - "postcss-discard-empty": "^5.1.1", - "postcss-discard-overridden": "^5.1.0", - "postcss-merge-longhand": "^5.1.7", - "postcss-merge-rules": "^5.1.4", - "postcss-minify-font-values": "^5.1.0", - "postcss-minify-gradients": "^5.1.1", - "postcss-minify-params": "^5.1.4", - "postcss-minify-selectors": "^5.2.1", - "postcss-normalize-charset": "^5.1.0", - "postcss-normalize-display-values": "^5.1.0", - "postcss-normalize-positions": "^5.1.1", - "postcss-normalize-repeat-style": "^5.1.1", - "postcss-normalize-string": "^5.1.0", - "postcss-normalize-timing-functions": "^5.1.0", - "postcss-normalize-unicode": "^5.1.1", - "postcss-normalize-url": "^5.1.0", - "postcss-normalize-whitespace": "^5.1.1", - "postcss-ordered-values": "^5.1.3", - "postcss-reduce-initial": "^5.1.2", - "postcss-reduce-transforms": "^5.1.0", - "postcss-svgo": "^5.1.0", - "postcss-unique-selectors": "^5.1.1" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/cssnano-utils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", - "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/csso": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", - "dependencies": { - "css-tree": "^1.1.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/csso/node_modules/css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", - "dependencies": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/csso/node_modules/mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" - }, - "node_modules/csso/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cssom": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", - "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==" - }, - "node_modules/cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dependencies": { - "cssom": "~0.3.6" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cssstyle/node_modules/cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" - }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" - }, - "node_modules/customize-cra": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/customize-cra/-/customize-cra-1.0.0.tgz", - "integrity": "sha512-DbtaLuy59224U+xCiukkxSq8clq++MOtJ1Et7LED1fLszWe88EoblEYFBJ895sB1mC6B4uu3xPT/IjClELhMbA==", - "dependencies": { - "lodash.flow": "^3.5.0" - } - }, - "node_modules/d3-array": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", - "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", - "dependencies": { - "internmap": "1 - 2" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-color": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", - "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-delaunay": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", - "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", - "dependencies": { - "delaunator": "5" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-format": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", - "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-interpolate": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", - "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", - "dependencies": { - "d3-color": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-path": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", - "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-scale": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", - "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", - "dependencies": { - "d3-array": "2.10.0 - 3", - "d3-format": "1 - 3", - "d3-interpolate": "1.2.0 - 3", - "d3-time": "2.1.1 - 3", - "d3-time-format": "2 - 4" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-shape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", - "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", - "dependencies": { - "d3-path": "^3.1.0" - }, - "engines": { - "node": ">=12" + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" } }, "node_modules/d3-time": { @@ -9465,28 +7919,11 @@ "node": ">=12" } }, - "node_modules/damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==" - }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", - "optional": true, - "peer": true, - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/data-urls": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "dev": true, "dependencies": { "abab": "^2.0.3", "whatwg-mimetype": "^2.3.0", @@ -9500,6 +7937,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -9516,6 +7954,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -9532,6 +7971,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -9548,7 +7988,8 @@ "version": "2.30.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", - "devOptional": true, + "optional": true, + "peer": true, "dependencies": { "@babel/runtime": "^7.21.0" }, @@ -9561,14 +8002,14 @@ } }, "node_modules/dayjs": { - "version": "1.11.11", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz", - "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==" + "version": "1.11.12", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.12.tgz", + "integrity": "sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg==" }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "dependencies": { "ms": "2.1.2" }, @@ -9581,47 +8022,11 @@ } } }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decamelize-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", - "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", - "optional": true, - "peer": true, - "dependencies": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decamelize-keys/node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/decimal.js": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", - "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "dev": true }, "node_modules/decompress-response": { "version": "3.3.0", @@ -9638,7 +8043,8 @@ "node_modules/dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==" + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", + "dev": true }, "node_modules/deep-extend": { "version": "0.6.0", @@ -9652,7 +8058,9 @@ "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "peer": true }, "node_modules/deepmerge": { "version": "4.3.1", @@ -9662,17 +8070,6 @@ "node": ">=0.10.0" } }, - "node_modules/default-gateway": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", - "dependencies": { - "execa": "^5.0.0" - }, - "engines": { - "node": ">= 10" - } - }, "node_modules/defaults": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", @@ -9702,6 +8099,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -9718,6 +8116,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, "engines": { "node": ">=8" } @@ -9726,6 +8125,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", @@ -9750,25 +8150,11 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, "engines": { "node": ">=0.4.0" } }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "optional": true, - "peer": true - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -9777,15 +8163,6 @@ "node": ">=6" } }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, "node_modules/detect-file": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", @@ -9795,40 +8172,18 @@ "node": ">=0.10.0" } }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" - }, - "node_modules/detect-port-alt": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", - "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", "dependencies": { - "address": "^1.0.1", - "debug": "^2.6.0" - }, - "bin": { - "detect": "bin/detect-port", - "detect-port": "bin/detect-port" + "dequal": "^2.0.0" }, - "engines": { - "node": ">= 4.2.1" - } - }, - "node_modules/detect-port-alt/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/detect-port-alt/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, "node_modules/dfa": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz", @@ -9842,11 +8197,6 @@ "node": ">=0.8.0" } }, - "node_modules/didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" - }, "node_modules/diff-sequences": { "version": "26.6.2", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.6.2.tgz", @@ -9856,42 +8206,12 @@ "node": ">= 10.14.2" } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" - }, - "node_modules/dns-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==" - }, - "node_modules/dns-packet": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.0.tgz", - "integrity": "sha512-rza3UH1LwdHh9qyPXp8lkwpjSNk/AMD3dPytUoRoqnypDUhY0xvbdmVhWOfxO68frEfV9BU8V12Ez7ZsHGZpCQ==", - "dependencies": { - "@leichtgewicht/ip-codec": "^2.0.1" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "peer": true, "dependencies": { "esutils": "^2.0.2" }, @@ -9903,15 +8223,8 @@ "version": "0.5.16", "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", - "dev": true - }, - "node_modules/dom-converter": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", - "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", - "dependencies": { - "utila": "~0.4" - } + "dev": true, + "peer": true }, "node_modules/dom-helpers": { "version": "5.2.1", @@ -9950,6 +8263,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "dev": true, "dependencies": { "webidl-conversions": "^5.0.0" }, @@ -9961,6 +8275,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "dev": true, "engines": { "node": ">=8" } @@ -9996,6 +8311,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3" @@ -10014,68 +8330,38 @@ } }, "node_modules/dotenv": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", - "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", "engines": { - "node": ">=10" + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" } }, - "node_modules/dotenv-expand": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", - "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==" - }, - "node_modules/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" - }, "node_modules/duplexer3": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==", "dev": true }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "optional": true, - "peer": true, - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "node_modules/ejs": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz", - "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==", - "dependencies": { - "jake": "^10.8.5" - }, - "bin": { - "ejs": "bin/cli.js" - }, - "engines": { - "node": ">=0.10.0" - } + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.668", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.668.tgz", - "integrity": "sha512-ZOBocMYCehr9W31+GpMclR+KBaDZOoAEabLdhpZ8oU1JFDwIaFY0UDbpXVEUFc0BIP2O2Qn3rkfCjQmMR4T/bQ==" + "version": "1.5.19", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.19.tgz", + "integrity": "sha512-kpLJJi3zxTR1U828P+LIUDZ5ohixyo68/IcYOHLqnbTPr/wdgn4i1ECvmALN9E16JPA6cvCG5UG79gVwVdEK5w==" }, "node_modules/emittery": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", + "dev": true, "engines": { "node": ">=10" }, @@ -10083,23 +8369,11 @@ "url": "https://github.com/sindresorhus/emittery?sponsor=1" } }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" - }, - "node_modules/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "engines": { - "node": ">= 4" - } - }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, "engines": { "node": ">= 0.8" } @@ -10123,18 +8397,6 @@ "once": "^1.4.0" } }, - "node_modules/enhanced-resolve": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", - "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -10146,23 +8408,18 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "optional": true, - "peer": true, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, "engines": { - "node": ">=6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "optional": true, - "peer": true - }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -10171,18 +8428,11 @@ "is-arrayish": "^0.2.1" } }, - "node_modules/error-stack-parser": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", - "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", - "dependencies": { - "stackframe": "^1.3.4" - } - }, "node_modules/es-abstract": { - "version": "1.23.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.2.tgz", - "integrity": "sha512-60s3Xv2T2p1ICykc7c+DNDPLDMm9t4QxCOUU0K9JxiLjM3C1zB9YVdN7tjxrFd4+AkZ8CdX1ovUga4P2+1e+/w==", + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.1", "arraybuffer.prototype.slice": "^1.0.3", @@ -10223,11 +8473,11 @@ "safe-regex-test": "^1.0.3", "string.prototype.trim": "^1.2.9", "string.prototype.trimend": "^1.0.8", - "string.prototype.trimstart": "^1.0.7", + "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.2", "typed-array-byte-length": "^1.0.1", "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.5", + "typed-array-length": "^1.0.6", "unbox-primitive": "^1.0.2", "which-typed-array": "^1.1.15" }, @@ -10238,15 +8488,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" - }, "node_modules/es-define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, "dependencies": { "get-intrinsic": "^1.2.4" }, @@ -10258,18 +8504,20 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, "engines": { "node": ">= 0.4" } }, "node_modules/es-iterator-helpers": { - "version": "1.0.18", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.18.tgz", - "integrity": "sha512-scxAJaewsahbqTYrGKJihhViaM6DDZDDoucfvzNbK0pOren1g/daDQ3IAhzn+1G14rBG7w+i5N+qul60++zlKA==", + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", + "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", + "es-abstract": "^1.23.3", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", @@ -10286,15 +8534,11 @@ "node": ">= 0.4" } }, - "node_modules/es-module-lexer": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.0.tgz", - "integrity": "sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==" - }, "node_modules/es-object-atoms": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, "dependencies": { "es-errors": "^1.3.0" }, @@ -10306,6 +8550,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, "dependencies": { "get-intrinsic": "^1.2.4", "has-tostringtag": "^1.0.2", @@ -10319,6 +8564,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, "dependencies": { "hasown": "^2.0.0" } @@ -10327,6 +8573,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, "dependencies": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -10343,7 +8590,6 @@ "version": "0.21.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" @@ -10378,9 +8624,9 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "engines": { "node": ">=6" } @@ -10397,7 +8643,8 @@ "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true }, "node_modules/escape-string-regexp": { "version": "4.0.0", @@ -10414,6 +8661,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", @@ -10434,6 +8682,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, "engines": { "node": ">=4.0" } @@ -10442,32 +8691,37 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, "optional": true, "engines": { "node": ">=0.10.0" } }, "node_modules/eslint": { - "version": "8.45.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.45.0.tgz", - "integrity": "sha512-pd8KSxiQpdYRfYa9Wufvdoct3ZPQQuVuU5O6scNgMuOMYuxvH0IGaYK0wUFjo4UYYQQCUndlXiMbnxopwvvTiw==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "dev": true, + "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.1.0", - "@eslint/js": "8.44.0", - "@humanwhocodes/config-array": "^0.11.10", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.1", - "espree": "^9.6.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -10512,37 +8766,11 @@ "eslint": ">=7.0.0" } }, - "node_modules/eslint-config-react-app": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-7.0.1.tgz", - "integrity": "sha512-K6rNzvkIeHaTd8m/QEh1Zko0KI7BACWkkneSs6s9cKZC/J27X3eZR6Upt1jkmZ/4FK+XUOPPxMEN7+lbUXfSlA==", - "dependencies": { - "@babel/core": "^7.16.0", - "@babel/eslint-parser": "^7.16.3", - "@rushstack/eslint-patch": "^1.1.0", - "@typescript-eslint/eslint-plugin": "^5.5.0", - "@typescript-eslint/parser": "^5.5.0", - "babel-preset-react-app": "^10.0.1", - "confusing-browser-globals": "^1.0.11", - "eslint-plugin-flowtype": "^8.0.3", - "eslint-plugin-import": "^2.25.3", - "eslint-plugin-jest": "^25.3.0", - "eslint-plugin-jsx-a11y": "^6.5.1", - "eslint-plugin-react": "^7.27.1", - "eslint-plugin-react-hooks": "^4.3.0", - "eslint-plugin-testing-library": "^5.0.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "eslint": "^8.0.0" - } - }, "node_modules/eslint-import-resolver-node": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", @@ -10553,6 +8781,7 @@ "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, "dependencies": { "ms": "^2.1.1" } @@ -10561,6 +8790,7 @@ "version": "2.8.0", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "dev": true, "dependencies": { "debug": "^3.2.7" }, @@ -10577,31 +8807,16 @@ "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, "dependencies": { "ms": "^2.1.1" } }, - "node_modules/eslint-plugin-flowtype": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-8.0.3.tgz", - "integrity": "sha512-dX8l6qUL6O+fYPtpNRideCFSpmWOUVx5QcaGLVqe/vlDiBSe4vYljDWDETwnyFzpl7By/WVIu6rcrniCgH9BqQ==", - "dependencies": { - "lodash": "^4.17.21", - "string-natural-compare": "^3.0.1" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@babel/plugin-syntax-flow": "^7.14.5", - "@babel/plugin-transform-react-jsx": "^7.14.9", - "eslint": "^8.1.0" - } - }, "node_modules/eslint-plugin-import": { "version": "2.29.1", "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "dev": true, "dependencies": { "array-includes": "^3.1.7", "array.prototype.findlastindex": "^1.2.3", @@ -10632,6 +8847,7 @@ "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, "dependencies": { "ms": "^2.1.1" } @@ -10640,6 +8856,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, "dependencies": { "esutils": "^2.0.2" }, @@ -10651,23 +8868,27 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, "bin": { "semver": "bin/semver.js" } }, "node_modules/eslint-plugin-jest": { - "version": "25.7.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-25.7.0.tgz", - "integrity": "sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==", + "version": "28.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.0.tgz", + "integrity": "sha512-Tubj1hooFxCl52G4qQu0edzV/+EZzPUeN8p2NnW5uu4fbDs+Yo7+qDVDc4/oG3FbCqEBmu/OC3LSsyiU22oghw==", + "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/experimental-utils": "^5.0.0" + "@typescript-eslint/utils": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^16.10.0 || ^18.12.0 || >=20.0.0" }, "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^4.0.0 || ^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "@typescript-eslint/eslint-plugin": "^6.0.0 || ^7.0.0 || ^8.0.0", + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0", + "jest": "*" }, "peerDependenciesMeta": { "@typescript-eslint/eslint-plugin": { @@ -10678,289 +8899,272 @@ } } }, - "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz", - "integrity": "sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==", + "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/scope-manager": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.5.0.tgz", + "integrity": "sha512-06JOQ9Qgj33yvBEx6tpC8ecP9o860rsR22hWMEd12WcTRrfaFgHr2RB/CA/B+7BMhHkXT4chg2MyboGdFGawYg==", + "dev": true, + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.20.7", - "aria-query": "^5.1.3", - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "ast-types-flow": "^0.0.7", - "axe-core": "^4.6.2", - "axobject-query": "^3.1.1", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "has": "^1.0.3", - "jsx-ast-utils": "^3.3.3", - "language-tags": "=1.0.5", - "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "semver": "^6.3.0" + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0" }, "engines": { - "node": ">=4.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" + "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/types": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.5.0.tgz", + "integrity": "sha512-qjkormnQS5wF9pjSi6q60bKUHH44j2APxfh9TQRXK8wbYVeDYYdYJGIROL87LGZZ2gz3Rbmjc736qyL8deVtdw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/eslint-plugin-prettier": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", - "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", + "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.5.0.tgz", + "integrity": "sha512-vEG2Sf9P8BPQ+d0pxdfndw3xIXaoSjliG0/Ejk7UggByZPKXmJmw3GW5jV2gHNQNawBUyfahoSiCFVov0Ruf7Q==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.8.6" + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint-plugin-prettier" - }, - "peerDependencies": { - "@types/eslint": ">=8.0.0", - "eslint": ">=8.0.0", - "eslint-config-prettier": "*", - "prettier": ">=3.0.0" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependenciesMeta": { - "@types/eslint": { - "optional": true - }, - "eslint-config-prettier": { + "typescript": { "optional": true } } }, - "node_modules/eslint-plugin-react": { - "version": "7.34.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz", - "integrity": "sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==", + "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/utils": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.5.0.tgz", + "integrity": "sha512-6yyGYVL0e+VzGYp60wvkBHiqDWOpT63pdMV2CVG4LVDd5uR6q1qQN/7LafBZtAtNIn/mqXjsSeS5ggv/P0iECw==", + "dev": true, + "license": "MIT", "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlast": "^1.2.4", - "array.prototype.flatmap": "^1.3.2", - "array.prototype.toreversed": "^1.1.2", - "array.prototype.tosorted": "^1.1.3", - "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.17", - "estraverse": "^5.3.0", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.7", - "object.fromentries": "^2.0.7", - "object.hasown": "^1.1.3", - "object.values": "^1.1.7", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.5", - "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.10" + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.5.0", + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/typescript-estree": "8.5.0" }, "engines": { - "node": ">=4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, - "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", - "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", - "engines": { - "node": ">=10" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + "eslint": "^8.57.0 || ^9.0.0" } }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.5.0.tgz", + "integrity": "sha512-yTPqMnbAZJNy2Xq2XU8AdtOW9tJIr+UQb64aXB9f3B1498Zx9JorVgFJcZpEc9UBuCCrdzKID2RGAMkYcDtZOw==", + "dev": true, + "license": "MIT", "dependencies": { - "esutils": "^2.0.2" + "@typescript-eslint/types": "8.5.0", + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-testing-library": { - "version": "5.11.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.11.0.tgz", - "integrity": "sha512-ELY7Gefo+61OfXKlQeXNIDVVLPcvKTeiQOoMZG9TeuWa7Ln4dUNRv8JdRWBQI9Mbb427XGlVB1aa1QPZxBJM8Q==", - "dependencies": { - "@typescript-eslint/utils": "^5.58.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0", - "npm": ">=6" - }, - "peerDependencies": { - "eslint": "^7.5.0 || ^8.0.0" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/eslint-plugin-tsdoc": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.17.tgz", - "integrity": "sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA==", + "node_modules/eslint-plugin-jest/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { - "@microsoft/tsdoc": "0.14.2", - "@microsoft/tsdoc-config": "0.16.2" + "balanced-match": "^1.0.0" } }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "node_modules/eslint-plugin-jest/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/eslint-webpack-plugin": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-3.2.0.tgz", - "integrity": "sha512-avrKcGncpPbPSUHX6B3stNGzkKFto3eL+DKM4+VyMrVnhPc3vRczVlCq3uhuFOdRvDHTVXuzwk1ZKUrqDQHQ9w==", + "node_modules/eslint-plugin-prettier": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", + "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", + "dev": true, "dependencies": { - "@types/eslint": "^7.29.0 || ^8.4.1", - "jest-worker": "^28.0.2", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "schema-utils": "^4.0.0" + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.9.1" }, "engines": { - "node": ">= 12.13.0" + "node": "^14.18.0 || >=16.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "url": "https://opencollective.com/eslint-plugin-prettier" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0", - "webpack": "^5.0.0" + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } } }, - "node_modules/eslint-webpack-plugin/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "node_modules/eslint-plugin-react": { + "version": "7.35.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.0.tgz", + "integrity": "sha512-v501SSMOWv8gerHkk+IIQBkcGRGrO2nfybfj5pLxuJNFTPxxA3PSryhXTK+9pNbtkggheDdsC0E9Q8CuPk6JKA==", + "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.3" + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.19", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.0", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.11", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" }, "peerDependencies": { - "ajv": "^8.8.2" + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, - "node_modules/eslint-webpack-plugin/node_modules/jest-worker": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.1.3.tgz", - "integrity": "sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g==", + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "esutils": "^2.0.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": ">=0.10.0" } }, - "node_modules/eslint-webpack-plugin/node_modules/schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "node_modules/eslint-plugin-react/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" }, - "engines": { - "node": ">= 12.13.0" + "bin": { + "resolve": "bin/resolve" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-webpack-plugin/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-tsdoc": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.3.0.tgz", + "integrity": "sha512-0MuFdBrrJVBjT/gyhkP2BqpD0np1NxNLfQ38xXDlSs/KVVpKI2A6vN7jx2Rve/CyUsvOsMGwp9KKrinv7q9g3A==", + "dev": true, "dependencies": { - "has-flag": "^4.0.0" - }, + "@microsoft/tsdoc": "0.15.0", + "@microsoft/tsdoc-config": "0.17.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -10975,12 +9179,16 @@ "node_modules/eslint/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "peer": true }, "node_modules/eslint/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -10993,9 +9201,12 @@ } }, "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.1.tgz", - "integrity": "sha512-CvefSOsDdaYYvxChovdrPo/ZGt8d5lrJWleAc1diXRKhHGiTYEI26cvo8Kle/wGnsizoCJjK73FMg1/IkIwiNA==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -11011,6 +9222,9 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, "engines": { "node": ">=4.0" } @@ -11019,6 +9233,8 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "peer": true, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -11034,6 +9250,8 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "peer": true, "dependencies": { "is-glob": "^4.0.3" }, @@ -11045,6 +9263,8 @@ "version": "13.20.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, + "peer": true, "dependencies": { "type-fest": "^0.20.2" }, @@ -11059,6 +9279,8 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "peer": true, "dependencies": { "argparse": "^2.0.1" }, @@ -11069,12 +9291,16 @@ "node_modules/eslint/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "peer": true }, "node_modules/eslint/node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "peer": true, "dependencies": { "p-locate": "^5.0.0" }, @@ -11089,6 +9315,8 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "peer": true, "dependencies": { "yocto-queue": "^0.1.0" }, @@ -11103,6 +9331,8 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "peer": true, "dependencies": { "p-limit": "^3.0.2" }, @@ -11117,6 +9347,8 @@ "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "peer": true, "engines": { "node": ">=10" }, @@ -11128,6 +9360,9 @@ "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", @@ -11156,6 +9391,8 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "peer": true, "dependencies": { "estraverse": "^5.1.0" }, @@ -11167,6 +9404,8 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "peer": true, "engines": { "node": ">=4.0" } @@ -11175,6 +9414,8 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "peer": true, "dependencies": { "estraverse": "^5.2.0" }, @@ -11186,56 +9427,26 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "peer": true, "engines": { "node": ">=4.0" } }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-walker": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", - "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==" - }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "engines": { - "node": ">=0.8.x" - } - }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -11258,6 +9469,7 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, "engines": { "node": ">= 0.8.0" } @@ -11342,6 +9554,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "dev": true, "dependencies": { "@jest/types": "^27.5.1", "jest-get-type": "^27.5.1", @@ -11352,147 +9565,30 @@ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.1", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" }, "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/express/node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" - }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" + "node": ">=4" } }, - "node_modules/express/node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "node_modules/external-editor/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" + "safer-buffer": ">= 2.1.2 < 3" }, "engines": { - "node": ">= 0.8" + "node": ">=0.10.0" } }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/express/node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/express/node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" - }, - "node_modules/express/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "optional": true, - "peer": true - }, - "node_modules/external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/external-editor/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "engines": [ - "node >=0.6.0" - ], - "optional": true, - "peer": true - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -11505,9 +9601,11 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", - "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -11522,36 +9620,53 @@ "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "peer": true + }, + "node_modules/fast-xml-parser": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } }, "node_modules/fastq": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, "dependencies": { "reusify": "^1.0.4" } }, - "node_modules/faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", - "dependencies": { - "websocket-driver": ">=0.5.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/fb-watchman": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, "dependencies": { "bser": "2.1.1" } @@ -11582,6 +9697,8 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "peer": true, "dependencies": { "flat-cache": "^3.0.4" }, @@ -11589,77 +9706,11 @@ "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/file-loader": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", - "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", - "dependencies": { - "loader-utils": "^2.0.0", - "schema-utils": "^3.0.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/file-loader/node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/filelist": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", - "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", - "dependencies": { - "minimatch": "^5.0.1" - } - }, - "node_modules/filelist/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/filelist/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/filesize": { - "version": "8.0.7", - "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", - "integrity": "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==", - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "devOptional": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -11700,22 +9751,6 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, - "node_modules/find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, "node_modules/find-node-modules": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/find-node-modules/-/find-node-modules-2.1.3.tgz", @@ -11735,6 +9770,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -11767,6 +9803,8 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "peer": true, "dependencies": { "flatted": "^3.1.0", "rimraf": "^3.0.2" @@ -11778,26 +9816,9 @@ "node_modules/flatted": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" - }, - "node_modules/follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true, + "peer": true }, "node_modules/fontkit": { "version": "2.0.2", @@ -11819,6 +9840,7 @@ "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, "dependencies": { "is-callable": "^1.1.3" } @@ -11831,314 +9853,81 @@ "node": ">=0.10.0" } }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", - "optional": true, - "peer": true, - "engines": { - "node": "*" - } - }, - "node_modules/fork-ts-checker-webpack-plugin": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz", - "integrity": "sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==", + "node_modules/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, "dependencies": { - "@babel/code-frame": "^7.8.3", - "@types/json-schema": "^7.0.5", - "chalk": "^4.1.0", - "chokidar": "^3.4.2", - "cosmiconfig": "^6.0.0", - "deepmerge": "^4.2.2", - "fs-extra": "^9.0.0", - "glob": "^7.1.6", - "memfs": "^3.1.2", - "minimatch": "^3.0.4", - "schema-utils": "2.7.0", - "semver": "^7.3.2", - "tapable": "^1.0.0" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" }, "engines": { - "node": ">=10", - "yarn": ">=1.0.0" - }, - "peerDependencies": { - "eslint": ">= 6", - "typescript": ">= 2.7", - "vue-template-compiler": "*", - "webpack": ">= 4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - }, - "vue-template-compiler": { - "optional": true - } + "node": ">= 6" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "peerDependencies": { - "ajv": "^6.9.1" + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.7.2" - }, - "engines": { - "node": ">=8" + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "node_modules/generic-names": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/generic-names/-/generic-names-4.0.0.tgz", + "integrity": "sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A==", + "dev": true, "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", - "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", - "dependencies": { - "@types/json-schema": "^7.0.4", - "ajv": "^6.12.2", - "ajv-keywords": "^3.4.1" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fraction.js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", - "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", - "engines": { - "node": "*" - }, - "funding": { - "type": "patreon", - "url": "https://www.patreon.com/infusion" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-monkey": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.4.tgz", - "integrity": "sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ==" - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "optional": true, - "peer": true, - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/gaze": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", - "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", - "optional": true, - "peer": true, - "dependencies": { - "globule": "^1.0.0" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/generic-names": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/generic-names/-/generic-names-4.0.0.tgz", - "integrity": "sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A==", - "dev": true, - "dependencies": { - "loader-utils": "^3.2.0" + "loader-utils": "^3.2.0" } }, "node_modules/gensync": { @@ -12153,6 +9942,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -12173,6 +9963,7 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2", @@ -12187,33 +9978,20 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-own-enumerable-property-symbols": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", - "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" - }, "node_modules/get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, "engines": { "node": ">=8.0.0" } }, - "node_modules/get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw==", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, "engines": { "node": ">=10" }, @@ -12225,6 +10003,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, "dependencies": { "call-bind": "^1.0.5", "es-errors": "^1.3.0", @@ -12249,20 +10028,11 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "optional": true, - "peer": true, - "dependencies": { - "assert-plus": "^1.0.0" - } - }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -12282,6 +10052,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "devOptional": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -12289,11 +10060,6 @@ "node": ">= 6" } }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" - }, "node_modules/global-dirs": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", @@ -12318,41 +10084,6 @@ "node": ">=10" } }, - "node_modules/global-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", - "dependencies": { - "global-prefix": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", - "dependencies": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-prefix/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, "node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -12365,6 +10096,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, "dependencies": { "define-properties": "^1.1.3" }, @@ -12375,78 +10107,16 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globule": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.4.tgz", - "integrity": "sha512-OPTIfhMBh7JbBYDpa5b+Q5ptmMWKwcNcFSR/0c6t8V4f3ZAVBEsKNY37QdVqmLRYSMhOUGYrY0QhSoEpzGr/Eg==", - "optional": true, - "peer": true, - "dependencies": { - "glob": "~7.1.1", - "lodash": "^4.17.21", - "minimatch": "~3.0.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/globule/node_modules/glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "optional": true, - "peer": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/globule/node_modules/minimatch": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", - "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", - "optional": true, - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } + "node_modules/globrex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", + "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==" }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -12491,12 +10161,14 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true }, "node_modules/graphql": { "version": "16.9.0", @@ -12576,106 +10248,19 @@ "through2": "^2.0.0" } }, - "node_modules/gzip-size": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", - "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", - "dependencies": { - "duplexer": "^0.1.2" - }, - "engines": { - "node": ">=10" - }, + "node_modules/harmony-reflect": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", + "integrity": "sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==", + "dev": true + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" - }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", - "optional": true, - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", - "optional": true, - "peer": true, - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/har-validator/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "optional": true, - "peer": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/har-validator/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "optional": true, - "peer": true - }, - "node_modules/hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "optional": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/harmony-reflect": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", - "integrity": "sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==" - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-flag": { @@ -12690,6 +10275,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, "dependencies": { "es-define-property": "^1.0.0" }, @@ -12701,6 +10287,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -12712,6 +10299,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -12723,6 +10311,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, "dependencies": { "has-symbols": "^1.0.3" }, @@ -12733,13 +10322,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "optional": true, - "peer": true - }, "node_modules/has-yarn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", @@ -12760,12 +10342,38 @@ "node": ">= 0.4" } }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "bin": { - "he": "bin/he" + "node_modules/hast-util-to-html": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.2.tgz", + "integrity": "sha512-RP5wNpj5nm1Z8cloDv4Sl4RS8jH5HYa0v93YB6Wb4poEzgMo/dAAL0KcT4974dCjcNG5pkLqTImeFHHCwwfY3g==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, "node_modules/history": { @@ -12801,94 +10409,11 @@ "node": ">=0.10.0" } }, - "node_modules/hoopy": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", - "integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==", - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "optional": true, - "peer": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/hosted-git-info/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "optional": true, - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/hosted-git-info/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "optional": true, - "peer": true - }, - "node_modules/hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", - "dependencies": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - } - }, - "node_modules/hpack.js/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "node_modules/hpack.js/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/hpack.js/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/hpack.js/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/html-encoding-sniffer": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "dev": true, "dependencies": { "whatwg-encoding": "^1.0.5" }, @@ -12897,9 +10422,9 @@ } }, "node_modules/html-entities": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz", - "integrity": "sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", + "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", "funding": [ { "type": "github", @@ -12914,35 +10439,8 @@ "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==" - }, - "node_modules/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", - "dependencies": { - "camel-case": "^4.1.2", - "clean-css": "^5.2.2", - "commander": "^8.3.0", - "he": "^1.2.0", - "param-case": "^3.0.4", - "relateurl": "^0.2.7", - "terser": "^5.10.0" - }, - "bin": { - "html-minifier-terser": "cli.js" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/html-minifier-terser/node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "engines": { - "node": ">= 12" - } + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true }, "node_modules/html-parse-stringify": { "version": "3.0.1", @@ -12952,26 +10450,13 @@ "void-elements": "3.1.0" } }, - "node_modules/html-webpack-plugin": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.3.tgz", - "integrity": "sha512-6YrDKTuqaP/TquFH7h4srYWsZx+x6k6+FbsTm0ziCwGHDP78Unr1r9F/H4+sGmMbX08GQcJ+K64x55b+7VM/jg==", - "dependencies": { - "@types/html-minifier-terser": "^6.0.0", - "html-minifier-terser": "^6.0.2", - "lodash": "^4.17.21", - "pretty-error": "^4.0.0", - "tapable": "^2.0.0" - }, - "engines": { - "node": ">=10.13.0" - }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", "funding": { - "type": "opencollective", - "url": "https://opencollective.com/html-webpack-plugin" - }, - "peerDependencies": { - "webpack": "^5.20.0" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, "node_modules/htmlparser2": { @@ -12996,58 +10481,13 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "devOptional": true - }, - "node_modules/http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==" - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-errors/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-parser-js": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", - "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" - }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } + "dev": true }, "node_modules/http-proxy-agent": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, "dependencies": { "@tootallnate/once": "1", "agent-base": "6", @@ -13057,60 +10497,11 @@ "node": ">= 6" } }, - "node_modules/http-proxy-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", - "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", - "dependencies": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@types/express": "^4.17.13" - }, - "peerDependenciesMeta": { - "@types/express": { - "optional": true - } - } - }, - "node_modules/http-proxy-middleware/node_modules/is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", - "optional": true, - "peer": true, - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, "dependencies": { "agent-base": "6", "debug": "4" @@ -13123,39 +10514,30 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, "engines": { "node": ">=10.17.0" } }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "optional": true, - "peer": true, - "dependencies": { - "ms": "^2.0.0" - } - }, "node_modules/husky": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", - "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", + "version": "9.1.6", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.6.tgz", + "integrity": "sha512-sqbjZKK7kf44hfdE94EoX8MZNk0n7HeW37O4YrVGCF4wzgQjp+akPAkfUK5LZ6KuR/6sqeAVuXHji+RzQgOn5A==", "dev": true, "bin": { - "husky": "lib/bin.js" + "husky": "bin.js" }, "engines": { - "node": ">=14" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/typicode" } }, "node_modules/i18next": { - "version": "21.10.0", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-21.10.0.tgz", - "integrity": "sha512-YeuIBmFsGjUfO3qBmMOc0rQaun4mIpGKET5WDwvu8lU7gvwpcariZLNtL0Fzj+zazcHUrlXHiptcFhBMFaxzfg==", + "version": "23.15.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.15.1.tgz", + "integrity": "sha512-wB4abZ3uK7EWodYisHl/asf8UYEhrI/vj/8aoSsrj/ZDxj4/UXPOa1KvFt1Fq5hkUHquNqwFlDprmjZ8iySgYA==", "funding": [ { "type": "individual", @@ -13171,7 +10553,7 @@ } ], "dependencies": { - "@babel/runtime": "^7.17.2" + "@babel/runtime": "^7.23.2" } }, "node_modules/i18next-browser-languagedetector": { @@ -13183,9 +10565,9 @@ } }, "node_modules/i18next-http-backend": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-2.5.2.tgz", - "integrity": "sha512-+K8HbDfrvc1/2X8jpb7RLhI9ZxBDpx3xogYkQwGKlWAUXLSEGXzgdt3EcUjLlBCdMwdQY+K+EUF6oh8oB6rwHw==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-2.6.1.tgz", + "integrity": "sha512-rCilMAnlEQNeKOZY1+x8wLM5IpYOj10guGvEpeC59tNjj6MMreLIjIW8D1RclhD3ifLwn6d/Y9HEM1RUE6DSog==", "dependencies": { "cross-fetch": "4.0.0" } @@ -13194,6 +10576,8 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "optional": true, + "peer": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -13205,6 +10589,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, "engines": { "node": "^10 || ^12 || >= 14" }, @@ -13212,15 +10597,11 @@ "postcss": "^8.1.0" } }, - "node_modules/idb": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", - "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==" - }, "node_modules/identity-obj-proxy": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz", "integrity": "sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA==", + "dev": true, "dependencies": { "harmony-reflect": "^1.4.6" }, @@ -13248,17 +10629,19 @@ ] }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/immer": { - "version": "9.0.21", - "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", - "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz", + "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==", "funding": { "type": "opencollective", "url": "https://opencollective.com/immer" @@ -13298,6 +10681,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, "dependencies": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" @@ -13316,6 +10700,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, "engines": { "node": ">=0.8.19" } @@ -13324,22 +10709,16 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "devOptional": true, + "dev": true, "engines": { "node": ">=8" } }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "optional": true, - "peer": true - }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -13353,7 +10732,8 @@ "node_modules/ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true }, "node_modules/inquirer": { "version": "8.2.6", @@ -13435,6 +10815,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.0", @@ -13460,25 +10841,11 @@ "loose-envify": "^1.0.0" } }, - "node_modules/ip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", - "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==", - "optional": true, - "peer": true - }, - "node_modules/ipaddr.js": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", - "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==", - "engines": { - "node": ">= 10" - } - }, "node_modules/is-array-buffer": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.2.1" @@ -13499,6 +10866,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -13513,6 +10881,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, "dependencies": { "has-bigints": "^1.0.1" }, @@ -13524,6 +10893,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "devOptional": true, "dependencies": { "binary-extensions": "^2.0.0" }, @@ -13535,6 +10905,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -13555,6 +10926,7 @@ "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -13595,6 +10967,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, "dependencies": { "is-typed-array": "^1.1.13" }, @@ -13609,6 +10982,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -13623,6 +10997,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, "bin": { "is-docker": "cli.js" }, @@ -13648,6 +11023,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -13656,6 +11032,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dev": true, "dependencies": { "call-bind": "^1.0.2" }, @@ -13675,6 +11052,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, "engines": { "node": ">=6" } @@ -13683,6 +11061,7 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -13697,6 +11076,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "devOptional": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -13728,17 +11108,11 @@ "node": ">=8" } }, - "node_modules/is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "optional": true, - "peer": true - }, "node_modules/is-map": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -13746,15 +11120,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==" - }, "node_modules/is-negative-zero": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -13778,6 +11148,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "devOptional": true, "engines": { "node": ">=0.12.0" } @@ -13786,6 +11157,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -13809,20 +11181,11 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, "engines": { "node": ">=8" } }, - "node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -13837,12 +11200,14 @@ "node_modules/is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true }, "node_modules/is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -13854,26 +11219,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", - "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-root": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", - "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==", - "engines": { - "node": ">=6" - } - }, "node_modules/is-set": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -13885,6 +11235,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, "dependencies": { "call-bind": "^1.0.7" }, @@ -13899,6 +11250,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, "engines": { "node": ">=8" }, @@ -13910,6 +11262,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -13924,6 +11277,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, "dependencies": { "has-symbols": "^1.0.2" }, @@ -13938,6 +11292,7 @@ "version": "1.1.13", "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, "dependencies": { "which-typed-array": "^1.1.14" }, @@ -13951,7 +11306,8 @@ "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true }, "node_modules/is-unicode-supported": { "version": "0.1.0", @@ -13968,6 +11324,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -13979,6 +11336,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, "dependencies": { "call-bind": "^1.0.2" }, @@ -13990,6 +11348,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "get-intrinsic": "^1.2.4" @@ -14014,6 +11373,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, "dependencies": { "is-docker": "^2.0.0" }, @@ -14030,12 +11390,14 @@ "node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true }, "node_modules/isobject": { "version": "3.0.1", @@ -14045,17 +11407,11 @@ "node": ">=0.10.0" } }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", - "optional": true, - "peer": true - }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true, "engines": { "node": ">=8" } @@ -14064,6 +11420,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, "dependencies": { "@babel/core": "^7.12.3", "@babel/parser": "^7.14.7", @@ -14079,6 +11436,7 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, "bin": { "semver": "bin/semver.js" } @@ -14087,6 +11445,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^3.0.0", @@ -14100,6 +11459,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, "dependencies": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", @@ -14113,6 +11473,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -14121,6 +11482,7 @@ "version": "3.1.5", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", + "dev": true, "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" @@ -14133,6 +11495,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "dev": true, "dependencies": { "define-properties": "^1.2.1", "get-intrinsic": "^1.2.1", @@ -14141,42 +11504,11 @@ "set-function-name": "^2.0.1" } }, - "node_modules/jake": { - "version": "10.8.7", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", - "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==", - "dependencies": { - "async": "^3.2.3", - "chalk": "^4.0.2", - "filelist": "^1.0.4", - "minimatch": "^3.1.2" - }, - "bin": { - "jake": "bin/cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jake/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": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", + "dev": true, "dependencies": { "@jest/core": "^27.5.1", "import-local": "^3.0.2", @@ -14201,6 +11533,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", + "dev": true, "dependencies": { "@jest/types": "^27.5.1", "execa": "^5.0.0", @@ -14214,6 +11547,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", + "dev": true, "dependencies": { "@jest/environment": "^27.5.1", "@jest/test-result": "^27.5.1", @@ -14243,6 +11577,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -14258,6 +11593,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -14271,6 +11607,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, "engines": { "node": ">=10" }, @@ -14281,12 +11618,14 @@ "node_modules/jest-circus/node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true }, "node_modules/jest-cli": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", + "dev": true, "dependencies": { "@jest/core": "^27.5.1", "@jest/test-result": "^27.5.1", @@ -14320,6 +11659,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -14335,6 +11675,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", + "dev": true, "dependencies": { "@babel/core": "^7.8.0", "@jest/test-sequencer": "^27.5.1", @@ -14377,6 +11718,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", + "dev": true, "dependencies": { "@jest/transform": "^27.5.1", "@jest/types": "^27.5.1", @@ -14398,6 +11740,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", + "dev": true, "dependencies": { "@babel/template": "^7.3.3", "@babel/types": "^7.3.3", @@ -14412,6 +11755,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", + "dev": true, "dependencies": { "babel-plugin-jest-hoist": "^27.5.1", "babel-preset-current-node-syntax": "^1.0.0" @@ -14427,6 +11771,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -14442,6 +11787,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", + "dev": true, "dependencies": { "@jest/environment": "^27.5.1", "@jest/fake-timers": "^27.5.1", @@ -14458,6 +11804,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -14471,6 +11818,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, "engines": { "node": ">=10" }, @@ -14481,7 +11829,8 @@ "node_modules/jest-config/node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true }, "node_modules/jest-diff": { "version": "26.6.2", @@ -14527,6 +11876,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", + "dev": true, "dependencies": { "detect-newline": "^3.0.0" }, @@ -14538,6 +11888,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, "engines": { "node": ">=8" } @@ -14546,6 +11897,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", + "dev": true, "dependencies": { "@jest/types": "^27.5.1", "chalk": "^4.0.0", @@ -14561,6 +11913,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -14576,6 +11929,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -14589,6 +11943,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, "engines": { "node": ">=10" }, @@ -14599,12 +11954,14 @@ "node_modules/jest-each/node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true }, "node_modules/jest-environment-jsdom": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", + "dev": true, "dependencies": { "@jest/environment": "^27.5.1", "@jest/fake-timers": "^27.5.1", @@ -14622,6 +11979,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "dev": true, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } @@ -14630,6 +11988,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "dev": true, "dependencies": { "@jest/types": "^27.5.1", "@types/graceful-fs": "^4.1.2", @@ -14655,6 +12014,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", + "dev": true, "dependencies": { "@jest/environment": "^27.5.1", "@jest/source-map": "^27.5.1", @@ -14682,6 +12042,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -14697,6 +12058,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -14710,6 +12072,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, "engines": { "node": ">=10" }, @@ -14720,12 +12083,14 @@ "node_modules/jest-jasmine2/node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true }, "node_modules/jest-leak-detector": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", + "dev": true, "dependencies": { "jest-get-type": "^27.5.1", "pretty-format": "^27.5.1" @@ -14738,6 +12103,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, "engines": { "node": ">=10" }, @@ -14749,6 +12115,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -14761,7 +12128,8 @@ "node_modules/jest-leak-detector/node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true }, "node_modules/jest-localstorage-mock": { "version": "2.4.26", @@ -14882,6 +12250,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "dev": true, "dependencies": { "chalk": "^4.0.0", "jest-diff": "^27.5.1", @@ -14896,6 +12265,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -14911,6 +12281,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "dev": true, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } @@ -14919,6 +12290,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "dev": true, "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^27.5.1", @@ -14933,6 +12305,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -14946,6 +12319,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, "engines": { "node": ">=10" }, @@ -14956,12 +12330,14 @@ "node_modules/jest-matcher-utils/node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true }, "node_modules/jest-message-util": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", "@jest/types": "^27.5.1", @@ -14981,6 +12357,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -14996,6 +12373,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -15009,6 +12387,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, "engines": { "node": ">=10" }, @@ -15019,12 +12398,14 @@ "node_modules/jest-message-util/node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true }, "node_modules/jest-mock": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "dev": true, "dependencies": { "@jest/types": "^27.5.1", "@types/node": "*" @@ -15037,6 +12418,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, "engines": { "node": ">=6" }, @@ -15112,6 +12494,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } @@ -15120,6 +12503,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", + "dev": true, "dependencies": { "@jest/types": "^27.5.1", "chalk": "^4.0.0", @@ -15140,6 +12524,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", + "dev": true, "dependencies": { "@jest/types": "^27.5.1", "jest-regex-util": "^27.5.1", @@ -15153,6 +12538,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -15168,6 +12554,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", + "dev": true, "dependencies": { "@jest/console": "^27.5.1", "@jest/environment": "^27.5.1", @@ -15199,6 +12586,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -15214,6 +12602,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", + "dev": true, "dependencies": { "@jest/environment": "^27.5.1", "@jest/fake-timers": "^27.5.1", @@ -15230,6 +12619,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", + "dev": true, "dependencies": { "@jest/environment": "^27.5.1", "@jest/fake-timers": "^27.5.1", @@ -15262,6 +12652,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -15277,6 +12668,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dev": true, "dependencies": { "@types/node": "*", "graceful-fs": "^4.2.9" @@ -15289,6 +12681,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", + "dev": true, "dependencies": { "@babel/core": "^7.7.2", "@babel/generator": "^7.7.2", @@ -15321,6 +12714,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -15336,6 +12730,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "dev": true, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } @@ -15344,6 +12739,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "dev": true, "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^27.5.1", @@ -15358,6 +12754,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -15371,6 +12768,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, "engines": { "node": ">=10" }, @@ -15381,12 +12779,14 @@ "node_modules/jest-snapshot/node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true }, "node_modules/jest-util": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, "dependencies": { "@jest/types": "^27.5.1", "@types/node": "*", @@ -15403,6 +12803,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -15418,6 +12819,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", + "dev": true, "dependencies": { "@jest/types": "^27.5.1", "camelcase": "^6.2.0", @@ -15434,6 +12836,7 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, "engines": { "node": ">=10" }, @@ -15445,6 +12848,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -15460,6 +12864,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -15473,6 +12878,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, "engines": { "node": ">=10" }, @@ -15483,94 +12889,32 @@ "node_modules/jest-validate/node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" - }, - "node_modules/jest-watch-typeahead": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-1.1.0.tgz", - "integrity": "sha512-Va5nLSJTN7YFtC2jd+7wsoe1pNe5K4ShLux/E5iHEwlB9AxaxmggY7to9KUqKojhaJw3aXqt5WAb4jGPOolpEw==", - "dependencies": { - "ansi-escapes": "^4.3.1", - "chalk": "^4.0.0", - "jest-regex-util": "^28.0.0", - "jest-watcher": "^28.0.0", - "slash": "^4.0.0", - "string-length": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "jest": "^27.0.0 || ^28.0.0" - } + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true }, - "node_modules/jest-watch-typeahead/node_modules/@jest/console": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.3.tgz", - "integrity": "sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==", + "node_modules/jest-watcher": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", + "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", + "dev": true, "dependencies": { - "@jest/types": "^28.1.3", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", "@types/node": "*", + "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "jest-message-util": "^28.1.3", - "jest-util": "^28.1.3", - "slash": "^3.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-watch-typeahead/node_modules/@jest/console/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-watch-typeahead/node_modules/@jest/test-result": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-28.1.3.tgz", - "integrity": "sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg==", - "dependencies": { - "@jest/console": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-watch-typeahead/node_modules/@jest/types": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", - "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", - "dependencies": { - "@jest/schemas": "^28.1.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "jest-util": "^27.5.1", + "string-length": "^4.0.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-watch-typeahead/node_modules/@types/yargs": { - "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", - "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", - "dependencies": { - "@types/yargs-parser": "*" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-watch-typeahead/node_modules/chalk": { + "node_modules/jest-watcher/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -15582,229 +12926,11 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-watch-typeahead/node_modules/emittery": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", - "integrity": "sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, - "node_modules/jest-watch-typeahead/node_modules/jest-message-util": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", - "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^28.1.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^28.1.3", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-watch-typeahead/node_modules/jest-message-util/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-watch-typeahead/node_modules/jest-regex-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", - "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-watch-typeahead/node_modules/jest-util": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", - "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", - "dependencies": { - "@jest/types": "^28.1.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-watch-typeahead/node_modules/jest-watcher": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-28.1.3.tgz", - "integrity": "sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g==", - "dependencies": { - "@jest/test-result": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.10.2", - "jest-util": "^28.1.3", - "string-length": "^4.0.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-watch-typeahead/node_modules/jest-watcher/node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jest-watch-typeahead/node_modules/jest-watcher/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-watch-typeahead/node_modules/pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", - "dependencies": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-watch-typeahead/node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-watch-typeahead/node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-watch-typeahead/node_modules/string-length": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-5.0.1.tgz", - "integrity": "sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==", - "dependencies": { - "char-regex": "^2.0.0", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-watch-typeahead/node_modules/string-length/node_modules/char-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-2.0.1.tgz", - "integrity": "sha512-oSvEeo6ZUD7NepqAat3RqoucZ5SeqLJgOvVIwkafu6IP3V0pO38s/ypdVUmDDK6qIIHNlYHJAKX9E7R7HoKElw==", - "engines": { - "node": ">=12.20" - } - }, - "node_modules/jest-watch-typeahead/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/jest-watch-typeahead/node_modules/strip-ansi/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/jest-watcher": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", - "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", - "dependencies": { - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "jest-util": "^27.5.1", - "string-length": "^4.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-watcher/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-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -15818,6 +12944,7 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -15828,27 +12955,12 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/jiti": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.1.tgz", - "integrity": "sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg==", - "bin": { - "jiti": "bin/jiti.js" - } - }, "node_modules/jju": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", "dev": true }, - "node_modules/js-base64": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", - "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==", - "optional": true, - "peer": true - }, "node_modules/js-cookie": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", @@ -15874,17 +12986,11 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", - "optional": true, - "peer": true - }, "node_modules/jsdom": { "version": "16.7.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "dev": true, "dependencies": { "abab": "^2.0.5", "acorn": "^8.2.4", @@ -15929,12 +13035,14 @@ "node_modules/jsdom/node_modules/parse5": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true }, "node_modules/jsdom/node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "dev": true, "engines": { "node": ">=8.3.0" }, @@ -15973,26 +13081,17 @@ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "optional": true, + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, "peer": true }, "node_modules/json5": { @@ -16006,45 +13105,11 @@ "node": ">=6" } }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonpointer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", - "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "optional": true, - "peer": true, - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, "node_modules/jsx-ast-utils": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.4.tgz", - "integrity": "sha512-fX2TVdCViod6HwKEtSWGHs57oFhVfCMwieb9PuRDgjDPh5XeqJiHFFFJCHxU5cnTc3Bu/GRL+kPiFmw8XWOfKw==", + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", @@ -16076,31 +13141,11 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, "engines": { "node": ">=6" } }, - "node_modules/klona": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", - "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/language-subtag-registry": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", - "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==" - }, - "node_modules/language-tags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", - "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", - "dependencies": { - "language-subtag-registry": "~0.3.2" - } - }, "node_modules/latest-version": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", @@ -16113,15 +13158,6 @@ "node": ">=8" } }, - "node_modules/launch-editor": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz", - "integrity": "sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==", - "dependencies": { - "picocolors": "^1.0.0", - "shell-quote": "^1.7.3" - } - }, "node_modules/lazy-cache": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz", @@ -16137,6 +13173,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, "engines": { "node": ">=6" } @@ -16145,6 +13182,8 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "peer": true, "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -16157,6 +13196,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true, "engines": { "node": ">=10" } @@ -16170,27 +13210,26 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", - "peer": true, "dependencies": { "uc.micro": "^2.0.0" } }, "node_modules/lint-staged": { - "version": "15.2.7", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.7.tgz", - "integrity": "sha512-+FdVbbCZ+yoh7E/RosSdqKJyUM2OEjTciH0TFNkawKgvFp1zbGlEC39RADg+xKBG1R4mhoH2j85myBQZ5wR+lw==", + "version": "15.2.8", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.8.tgz", + "integrity": "sha512-PUWFf2zQzsd9EFU+kM1d7UP+AZDbKFKuj+9JNVTBkhUFhbg4MAt6WfyMMwBfM4lYqd4D2Jwac5iuTu9rVj4zCQ==", "dev": true, "dependencies": { "chalk": "~5.3.0", "commander": "~12.1.0", - "debug": "~4.3.4", + "debug": "~4.3.6", "execa": "~8.0.1", - "lilconfig": "~3.1.1", - "listr2": "~8.2.1", + "lilconfig": "~3.1.2", + "listr2": "~8.2.4", "micromatch": "~4.0.7", "pidtree": "~0.6.0", "string-argv": "~0.3.2", - "yaml": "~2.4.2" + "yaml": "~2.5.0" }, "bin": { "lint-staged": "bin/lint-staged.js" @@ -16370,9 +13409,9 @@ } }, "node_modules/lint-staged/node_modules/yaml": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", - "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz", + "integrity": "sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==", "dev": true, "bin": { "yaml": "bin.mjs" @@ -16437,16 +13476,16 @@ } }, "node_modules/listr2": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.1.tgz", - "integrity": "sha512-irTfvpib/rNiD637xeevjO2l3Z5loZmuaRi0L0YE5LfijwVY96oyVn0DFD3o/teAok7nfobMG1THvvcHh/BP6g==", + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.4.tgz", + "integrity": "sha512-opevsywziHd3zHCVQGAj8zu+Z3yHNkkoYhWIGnq54RrCVwLz0MozotJEDnKsIBLvkfLGN6BLOyAeRrYI0pKA4g==", "dev": true, "dependencies": { "cli-truncate": "^4.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", - "log-update": "^6.0.0", - "rfdc": "^1.3.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", "wrap-ansi": "^9.0.0" }, "engines": { @@ -16490,9 +13529,9 @@ "dev": true }, "node_modules/listr2/node_modules/string-width": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", - "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "dependencies": { "emoji-regex": "^10.3.0", @@ -16538,18 +13577,11 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "engines": { - "node": ">=6.11.5" - } - }, "node_modules/loader-utils": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==", + "dev": true, "engines": { "node": ">= 12.13.0" } @@ -16558,6 +13590,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, "dependencies": { "p-locate": "^4.1.0" }, @@ -16584,27 +13617,20 @@ "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true }, "node_modules/lodash.flow": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz", "integrity": "sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw==" }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" - }, - "node_modules/lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "peer": true }, "node_modules/lodash.template": { "version": "4.5.0", @@ -16623,11 +13649,6 @@ "lodash._reinterpolate": "^3.0.0" } }, - "node_modules/lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" - }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -16659,14 +13680,14 @@ } }, "node_modules/log-update": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", - "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", "dev": true, "dependencies": { - "ansi-escapes": "^6.2.0", - "cli-cursor": "^4.0.0", - "slice-ansi": "^7.0.0", + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" }, @@ -16678,12 +13699,15 @@ } }, "node_modules/log-update/node_modules/ansi-escapes": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", - "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", "dev": true, + "dependencies": { + "environment": "^1.0.0" + }, "engines": { - "node": ">=14.16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -16751,9 +13775,9 @@ } }, "node_modules/log-update/node_modules/string-width": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", - "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "dependencies": { "emoji-regex": "^10.3.0", @@ -16814,6 +13838,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, "dependencies": { "tslib": "^2.0.3" } @@ -16838,30 +13863,23 @@ "node_modules/lunr": { "version": "2.3.9", "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", - "peer": true + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==" }, "node_modules/lz-string": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", "dev": true, + "peer": true, "bin": { "lz-string": "bin/bin.js" } }, - "node_modules/magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", - "dependencies": { - "sourcemap-codec": "^1.4.8" - } - }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, "dependencies": { "semver": "^6.0.0" }, @@ -16876,6 +13894,7 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, "bin": { "semver": "bin/semver.js" } @@ -16884,28 +13903,15 @@ "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, "dependencies": { "tmpl": "1.0.5" } }, - "node_modules/map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "optional": true, - "peer": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/markdown-it": { "version": "14.1.0", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", - "peer": true, "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", @@ -16921,8 +13927,7 @@ "node_modules/markdown-it/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "peer": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/markdown-link": { "version": "0.1.1", @@ -16962,117 +13967,146 @@ "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==" }, - "node_modules/mdn-data": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", - "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==" + "node_modules/mdast-util-to-hast": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", + "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } }, "node_modules/mdurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", - "peer": true - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memfs": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", - "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", - "dependencies": { - "fs-monkey": "^1.0.4" - }, - "engines": { - "node": ">= 4.0.0" - } + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==" }, "node_modules/memoize-one": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==" }, - "node_modules/meow": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", - "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", - "optional": true, - "peer": true, - "dependencies": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize": "^1.2.0", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "optional": true, - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/merge": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/merge/-/merge-2.1.1.tgz", "integrity": "sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==", "dev": true }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" - }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, "engines": { "node": ">= 8" } }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "engines": { - "node": ">= 0.6" + "node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", + "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", + "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" } }, + "node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz", + "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -17081,21 +14115,11 @@ "node": ">=8.6" } }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, "engines": { "node": ">= 0.6" } @@ -17104,6 +14128,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -17119,6 +14144,18 @@ "node": ">=6" } }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mimic-response": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", @@ -17132,67 +14169,16 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "devOptional": true, + "dev": true, "engines": { "node": ">=4" } }, - "node_modules/mini-css-extract-plugin": { - "version": "2.7.6", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.6.tgz", - "integrity": "sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw==", - "dependencies": { - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, - "node_modules/mini-css-extract-plugin/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/mini-css-extract-plugin/node_modules/schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" - }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -17208,114 +14194,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "optional": true, - "peer": true, - "dependencies": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "optional": true, - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "optional": true, - "peer": true - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "optional": true, - "peer": true - }, "node_modules/mixin-deep": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", @@ -17328,19 +14206,6 @@ "node": ">=0.10.0" } }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "optional": true, - "peer": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/mrmime": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", @@ -17355,40 +14220,11 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, - "node_modules/multicast-dns": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", - "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", - "dependencies": { - "dns-packet": "^5.2.2", - "thunky": "^1.0.2" - }, - "bin": { - "multicast-dns": "cli.js" - } - }, "node_modules/mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "node_modules/nan": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", - "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", - "optional": true, - "peer": true - }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -17409,30 +14245,14 @@ "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" - }, - "node_modules/natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==" - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true }, "node_modules/no-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, "dependencies": { "lower-case": "^2.0.2", "tslib": "^2.0.3" @@ -17476,378 +14296,40 @@ "webidl-conversions": "^3.0.0" } }, - "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "engines": { - "node": ">= 6.13.0" - } - }, - "node_modules/node-gyp": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", - "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", - "optional": true, - "peer": true, - "dependencies": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^9.1.0", - "nopt": "^5.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": ">= 10.12.0" - } - }, - "node_modules/node-gyp/node_modules/@npmcli/fs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", - "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", - "optional": true, - "peer": true, - "dependencies": { - "@gar/promisify": "^1.0.1", - "semver": "^7.3.5" - } - }, - "node_modules/node-gyp/node_modules/@npmcli/move-file": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", - "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", - "deprecated": "This functionality has been moved to @npmcli/fs", - "optional": true, - "peer": true, - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-gyp/node_modules/cacache": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", - "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", - "optional": true, - "peer": true, - "dependencies": { - "@npmcli/fs": "^1.0.0", - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.1", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/node-gyp/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "optional": true, - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-gyp/node_modules/make-fetch-happen": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", - "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", - "optional": true, - "peer": true, - "dependencies": { - "agentkeepalive": "^4.1.3", - "cacache": "^15.2.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^6.0.0", - "minipass": "^3.1.3", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^1.3.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.2", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^6.0.0", - "ssri": "^8.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/node-gyp/node_modules/minipass-fetch": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", - "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.1.0", - "minipass-sized": "^1.0.3", - "minizlib": "^2.0.0" - }, - "engines": { - "node": ">=8" - }, - "optionalDependencies": { - "encoding": "^0.1.12" - } - }, - "node_modules/node-gyp/node_modules/socks-proxy-agent": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", - "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", - "optional": true, - "peer": true, - "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/node-gyp/node_modules/ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/node-gyp/node_modules/unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "optional": true, - "peer": true, - "dependencies": { - "unique-slug": "^2.0.0" - } - }, - "node_modules/node-gyp/node_modules/unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "optional": true, - "peer": true, + "node_modules/node-html-better-parser": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/node-html-better-parser/-/node-html-better-parser-1.4.4.tgz", + "integrity": "sha512-uvlqL1uMU7m/aIY9WsGM0jDW7gVFIuFSWS6f2rlJeL7K1ZzKnA3B8cNbUGw9ywwYm9W7W2ooi0iQ7aI29aQmPw==", + "license": "MIT", "dependencies": { - "imurmurhash": "^0.1.4" + "html-entities": "^2.3.2" } }, - "node_modules/node-gyp/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "optional": true, - "peer": true - }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true }, "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" - }, - "node_modules/node-sass": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-7.0.3.tgz", - "integrity": "sha512-8MIlsY/4dXUkJDYht9pIWBhMil3uHmE8b/AdJPjmFn1nBx9X9BASzfzmsCy0uCCb8eqI3SYYzVPDswWqSx7gjw==", - "hasInstallScript": true, - "optional": true, - "peer": true, - "dependencies": { - "async-foreach": "^0.1.3", - "chalk": "^4.1.2", - "cross-spawn": "^7.0.3", - "gaze": "^1.0.0", - "get-stdin": "^4.0.1", - "glob": "^7.0.3", - "lodash": "^4.17.15", - "meow": "^9.0.0", - "nan": "^2.13.2", - "node-gyp": "^8.4.1", - "npmlog": "^5.0.0", - "request": "^2.88.0", - "sass-graph": "^4.0.1", - "stdout-stream": "^1.4.0", - "true-case-path": "^1.0.2" - }, - "bin": { - "node-sass": "bin/node-sass" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/node-sass/node_modules/are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "optional": true, - "peer": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-sass/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "optional": true, - "peer": true, - "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/node-sass/node_modules/gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "optional": true, - "peer": true, - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-sass/node_modules/npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "optional": true, - "peer": true, - "dependencies": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } - }, - "node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "optional": true, - "peer": true, - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "optional": true, - "peer": true, - "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, - "engines": { - "node": ">=10" - } + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "devOptional": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, "dependencies": { "path-key": "^3.0.0" }, @@ -17855,47 +14337,11 @@ "node": ">=8" } }, - "node_modules/npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "optional": true, - "peer": true, - "dependencies": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, "node_modules/nwsapi": { "version": "2.2.7", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", - "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==" - }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "optional": true, - "peer": true, - "engines": { - "node": "*" - } + "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==", + "dev": true }, "node_modules/object-assign": { "version": "4.1.1", @@ -17905,18 +14351,11 @@ "node": ">=0.10.0" } }, - "node_modules/object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "engines": { - "node": ">= 6" - } - }, "node_modules/object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -17925,6 +14364,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, "engines": { "node": ">= 0.4" } @@ -17933,6 +14373,7 @@ "version": "4.1.5", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, "dependencies": { "call-bind": "^1.0.5", "define-properties": "^1.2.1", @@ -17950,6 +14391,7 @@ "version": "1.1.8", "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -17960,13 +14402,15 @@ } }, "node_modules/object.fromentries": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", - "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -17975,28 +14419,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object.getownpropertydescriptors": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.6.tgz", - "integrity": "sha512-lq+61g26E/BgHv0ZTFgRvi7NMEPuAxLkFU7rukXjc/AlwH4Am5xXVnIXy3un1bg/JPbXHrixRkK1itUzzPiIjQ==", - "dependencies": { - "array.prototype.reduce": "^1.0.5", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.21.2", - "safe-array-concat": "^1.0.0" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/object.groupby": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -18004,41 +14431,26 @@ "get-intrinsic": "^1.2.1" } }, - "node_modules/object.hasown": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.4.tgz", - "integrity": "sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==", + "node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", "dependencies": { - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", - "dependencies": { - "isobject": "^3.0.1" + "isobject": "^3.0.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/object.values": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", - "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -18047,11 +14459,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" - }, "node_modules/on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -18064,18 +14471,11 @@ "node": ">= 0.8" } }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, "dependencies": { "wrappy": "1" } @@ -18094,10 +14494,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/oniguruma-to-js": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/oniguruma-to-js/-/oniguruma-to-js-0.4.3.tgz", + "integrity": "sha512-X0jWUcAlxORhOqqBREgPMgnshB7ZGYszBNspP+tS9hPD3l13CdaXcHbgImoHUHlrvGx/7AvFEkTRhAGYh+jzjQ==", + "dependencies": { + "regex": "^4.3.2" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/open": { "version": "8.4.2", "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", @@ -18111,18 +14523,20 @@ } }, "node_modules/optimism": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.16.2.tgz", - "integrity": "sha512-zWNbgWj+3vLEjZNIh/okkY2EUfX+vB9TJopzIZwT1xxaMqC5hRLLraePod4c5n4He08xuXNH+zhKFFCu390wiQ==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.18.0.tgz", + "integrity": "sha512-tGn8+REwLRNFnb9WmcY5IfpOqeX2kpaYJ1s6Ae3mn12AeydLkR3j+jSCmVQFoXqU8D41PAJ1RG1rCRNWmNZVmQ==", "dependencies": { + "@wry/caches": "^1.0.0", "@wry/context": "^0.7.0", - "@wry/trie": "^0.3.0" + "@wry/trie": "^0.4.3", + "tslib": "^2.3.0" } }, "node_modules/optimism/node_modules/@wry/trie": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@wry/trie/-/trie-0.3.2.tgz", - "integrity": "sha512-yRTyhWSls2OY/pYLfwff867r8ekooZ4UI+/gxot5Wj8EFwSf2rG+n+Mo/6LoLQm1TKA4GRj2+LCpbfS937dClQ==", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@wry/trie/-/trie-0.4.3.tgz", + "integrity": "sha512-I6bHwH0fSf6RqQcnnXLJKhkSXG45MFral3GxPaY4uAl0LYDZM+YDVDAiU9bYwjTuysy1S0IeecWtmq1SZA3M1w==", "dependencies": { "tslib": "^2.3.0" }, @@ -18134,6 +14548,8 @@ "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "peer": true, "dependencies": { "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", @@ -18227,6 +14643,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, "dependencies": { "p-try": "^2.0.0" }, @@ -18241,6 +14658,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, "dependencies": { "p-limit": "^2.2.0" }, @@ -18248,46 +14666,11 @@ "node": ">=8" } }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "optional": true, - "peer": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-retry": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", - "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", - "dependencies": { - "@types/retry": "0.12.0", - "retry": "^0.13.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-retry/node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "engines": { - "node": ">= 4" - } - }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, "engines": { "node": ">=6" } @@ -18321,15 +14704,6 @@ "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" }, - "node_modules/param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -18376,23 +14750,16 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, "engines": { "node": ">= 0.8" } }, - "node_modules/pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, "engines": { "node": ">=8" } @@ -18401,6 +14768,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -18409,6 +14777,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, "engines": { "node": ">=8" } @@ -18426,20 +14795,16 @@ "node": ">=8" } }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" - }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "devOptional": true, "engines": { "node": ">=8.6" }, @@ -18463,6 +14828,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -18471,6 +14837,7 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, "engines": { "node": ">= 6" } @@ -18479,6 +14846,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, "dependencies": { "find-up": "^4.0.0" }, @@ -18486,71 +14854,19 @@ "node": ">=8" } }, - "node_modules/pkg-up": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", - "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", - "dependencies": { - "find-up": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-up/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-up/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-up/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-up/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/possible-typed-array-names": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, "engines": { "node": ">= 0.4" } }, "node_modules/postcss": { - "version": "8.4.35", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", - "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", + "version": "8.4.45", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.45.tgz", + "integrity": "sha512-7KTLTdzdZZYscUc65XmjFiB73vBhBfbPztCYdUNvlaso9PrzjzcmjqBPR0lNGkcVlcO4BjiO5rK/qNz+XAen1Q==", "funding": [ { "type": "opencollective", @@ -18567,1547 +14883,1307 @@ ], "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "picocolors": "^1.0.1", + "source-map-js": "^1.2.0" }, "engines": { "node": "^10 || ^12 || >=14" } }, - "node_modules/postcss-attribute-case-insensitive": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.2.tgz", - "integrity": "sha512-XIidXV8fDr0kKt28vqki84fRK8VW8eTuIa4PChv2MqKuT6C9UjmSKzen6KaWhWEoYvwxFCa7n/tC1SZ3tyq4SQ==", - "dependencies": { - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-browser-comments": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-browser-comments/-/postcss-browser-comments-4.0.0.tgz", - "integrity": "sha512-X9X9/WN3KIvY9+hNERUqX9gncsgBA25XaeR+jshHz2j8+sYyHktHw1JdKuMjeLpGktXidqDhA7b/qm1mrBDmgg==", - "engines": { - "node": ">=8" - }, - "peerDependencies": { - "browserslist": ">=4", - "postcss": ">=8" - } - }, - "node_modules/postcss-calc": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", - "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", - "dependencies": { - "postcss-selector-parser": "^6.0.9", - "postcss-value-parser": "^4.2.0" - }, - "peerDependencies": { - "postcss": "^8.2.2" - } - }, - "node_modules/postcss-clamp": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz", - "integrity": "sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==", + "node_modules/postcss-import": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz", + "integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==", + "dev": true, "dependencies": { - "postcss-value-parser": "^4.2.0" + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" }, "engines": { - "node": ">=7.6.0" + "node": ">=10.0.0" }, "peerDependencies": { - "postcss": "^8.4.6" + "postcss": "^8.0.0" } }, - "node_modules/postcss-color-functional-notation": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-4.2.4.tgz", - "integrity": "sha512-2yrTAUZUab9s6CpxkxC4rVgFEVaR6/2Pipvi6qcgvnYiVqZcbDHEoBDhrXzyb7Efh2CCfHQNtcqWcIruDTIUeg==", + "node_modules/postcss-load-config": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.1.tgz", + "integrity": "sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==", + "dev": true, "dependencies": { - "postcss-value-parser": "^4.2.0" + "lilconfig": "^2.0.5", + "yaml": "^2.1.1" }, "engines": { - "node": "^12 || ^14 || >=16" + "node": ">= 14" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/csstools" + "url": "https://opencollective.com/postcss/" }, "peerDependencies": { - "postcss": "^8.2" + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } } }, - "node_modules/postcss-color-hex-alpha": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-8.0.4.tgz", - "integrity": "sha512-nLo2DCRC9eE4w2JmuKgVA3fGL3d01kGq752pVALF68qpGLmx2Qrk91QTKkdUqqp45T1K1XV8IhQpcu1hoAQflQ==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, + "node_modules/postcss-load-config/node_modules/yaml": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", + "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", + "dev": true, "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" + "node": ">= 14" } }, - "node_modules/postcss-color-rebeccapurple": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-7.1.1.tgz", - "integrity": "sha512-pGxkuVEInwLHgkNxUc4sdg4g3py7zUeCQ9sMfwyHAT+Ezk8a4OaaVZ8lIY5+oNqA/BXXgLyXv0+5wHP68R79hg==", + "node_modules/postcss-modules": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules/-/postcss-modules-6.0.0.tgz", + "integrity": "sha512-7DGfnlyi/ju82BRzTIjWS5C4Tafmzl3R79YP/PASiocj+aa6yYphHhhKUOEoXQToId5rgyFgJ88+ccOUydjBXQ==", + "dev": true, "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" + "generic-names": "^4.0.0", + "icss-utils": "^5.1.0", + "lodash.camelcase": "^4.3.0", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "string-hash": "^1.1.1" }, "peerDependencies": { - "postcss": "^8.2" + "postcss": "^8.0.0" } }, - "node_modules/postcss-colormin": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.1.tgz", - "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==", - "dependencies": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0", - "colord": "^2.9.1", - "postcss-value-parser": "^4.2.0" - }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "dev": true, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^10 || ^12 || >= 14" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.1.0" } }, - "node_modules/postcss-convert-values": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", - "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", + "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", + "dev": true, "dependencies": { - "browserslist": "^4.21.4", - "postcss-value-parser": "^4.2.0" + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^10 || ^12 || >= 14" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.1.0" } }, - "node_modules/postcss-custom-media": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-8.0.2.tgz", - "integrity": "sha512-7yi25vDAoHAkbhAzX9dHx2yc6ntS4jQvejrNcC+csQJAXjj15e7VcWfMgLqBNAbOvqi5uIa9huOVwdHbf+sKqg==", + "node_modules/postcss-modules-scope": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", + "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", + "dev": true, "dependencies": { - "postcss-value-parser": "^4.2.0" + "postcss-selector-parser": "^6.0.4" }, "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" + "node": "^10 || ^12 || >= 14" }, "peerDependencies": { - "postcss": "^8.3" + "postcss": "^8.1.0" } }, - "node_modules/postcss-custom-properties": { - "version": "12.1.11", - "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-12.1.11.tgz", - "integrity": "sha512-0IDJYhgU8xDv1KY6+VgUwuQkVtmYzRwu+dMjnmdMafXYv86SWqfxkc7qdDvWS38vsjaEtv8e0vGOUQrAiMBLpQ==", + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, "dependencies": { - "postcss-value-parser": "^4.2.0" + "icss-utils": "^5.0.0" }, "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" + "node": "^10 || ^12 || >= 14" }, "peerDependencies": { - "postcss": "^8.2" + "postcss": "^8.1.0" } }, - "node_modules/postcss-custom-selectors": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-6.0.3.tgz", - "integrity": "sha512-fgVkmyiWDwmD3JbpCmB45SvvlCD6z9CG6Ie6Iere22W5aHea6oWa7EM2bpnv2Fj3I94L3VbtvX9KqwSi5aFzSg==", + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, "dependencies": { - "postcss-selector-parser": "^6.0.4" + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" }, "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.3" + "node": ">=4" } }, - "node_modules/postcss-dir-pseudo-class": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-6.0.5.tgz", - "integrity": "sha512-eqn4m70P031PF7ZQIvSgy9RSJ5uI2171O/OO/zcRNYpJbvaeKFUlar1aJ7rmgiQtbm0FSPsRewjpdS0Oew7MPA==", - "dependencies": { - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true }, - "node_modules/postcss-discard-comments": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", - "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "peer": true, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">= 0.8.0" } }, - "node_modules/postcss-discard-duplicates": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", - "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", + "node_modules/prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", + "dev": true, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=4" } }, - "node_modules/postcss-discard-empty": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", - "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", + "node_modules/prettier": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", + "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", + "bin": { + "prettier": "bin/prettier.cjs" + }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">=14" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/postcss-discard-overridden": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", - "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", - "engines": { - "node": "^10 || ^12 || >=14.0" + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" }, - "peerDependencies": { - "postcss": "^8.2.15" + "engines": { + "node": ">=6.0.0" } }, - "node_modules/postcss-double-position-gradients": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-3.1.2.tgz", - "integrity": "sha512-GX+FuE/uBR6eskOK+4vkXgT6pDkexLokPaz/AbJna9s5Kzp/yl488pKPjhy0obB475ovfT1Wv8ho7U/cHNaRgQ==", + "node_modules/pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "dev": true, "dependencies": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" }, "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" + "node": ">= 10" } }, - "node_modules/postcss-env-function": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-4.0.6.tgz", - "integrity": "sha512-kpA6FsLra+NqcFnL81TnsU+Z7orGtDTxcOhl6pwXeEq1yFPpRMkCDpHhrz8CFQDr/Wfm0jLiNQ1OsGGPjlqPwA==", + "node_modules/pretty-format/node_modules/@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "dev": true, "dependencies": { - "postcss-value-parser": "^4.2.0" + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" }, "engines": { - "node": "^12 || ^14 || >=16" - }, - "peerDependencies": { - "postcss": "^8.4" + "node": ">= 10.14.2" } }, - "node_modules/postcss-flexbugs-fixes": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz", - "integrity": "sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==", - "peerDependencies": { - "postcss": "^8.1.4" + "node_modules/pretty-format/node_modules/@types/yargs": { + "version": "15.0.15", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.15.tgz", + "integrity": "sha512-IziEYMU9XoVj8hWg7k+UJrXALkGFjWJhn5QFEv9q4p+v40oZhSuC135M38st8XPjICL7Ey4TV64ferBGUoJhBg==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" } }, - "node_modules/postcss-focus-visible": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-6.0.4.tgz", - "integrity": "sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw==", + "node_modules/pretty-format/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "postcss-selector-parser": "^6.0.9" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "^12 || ^14 || >=16" + "node": ">=10" }, - "peerDependencies": { - "postcss": "^8.4" + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/postcss-focus-within": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz", - "integrity": "sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ==", + "node_modules/pretty-format/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, "dependencies": { - "postcss-selector-parser": "^6.0.9" + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" }, "engines": { - "node": "^12 || ^14 || >=16" - }, - "peerDependencies": { - "postcss": "^8.4" + "node": ">= 6" } }, - "node_modules/postcss-font-variant": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", - "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", - "peerDependencies": { - "postcss": "^8.1.0" + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" } }, - "node_modules/postcss-gap-properties": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-3.0.5.tgz", - "integrity": "sha512-IuE6gKSdoUNcvkGIqdtjtcMtZIFyXZhmFd5RUlg97iVEvp1BZKV5ngsAjCjrVy+14uhGBQl9tzmi1Qwq4kqVOg==", - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" + "node_modules/prop-types-extra": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz", + "integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==", + "dependencies": { + "react-is": "^16.3.2", + "warning": "^4.0.0" }, "peerDependencies": { - "postcss": "^8.2" + "react": ">=0.14.0" } }, - "node_modules/postcss-image-set-function": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-4.0.7.tgz", - "integrity": "sha512-9T2r9rsvYzm5ndsBE8WgtrMlIT7VbtTfE7b3BQnudUqnBcBo7L758oc+o+pdj/dUV0l5wjwSdjeOH2DZtfv8qw==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, + "node_modules/prop-types-extra/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/property-information": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", + "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/postcss-import": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz", - "integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==", + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, "dependencies": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "postcss": "^8.0.0" + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } }, - "node_modules/postcss-initial": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz", - "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==", - "peerDependencies": { - "postcss": "^8.0.0" + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true, + "engines": { + "node": ">=6" } }, - "node_modules/postcss-js": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", - "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", - "dependencies": { - "camelcase-css": "^2.0.1" - }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", "engines": { - "node": "^12 || ^14 || >= 16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.4.21" + "node": ">=6" } }, - "node_modules/postcss-lab-function": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-4.2.1.tgz", - "integrity": "sha512-xuXll4isR03CrQsmxyz92LJB2xX9n+pZJ5jE9JgcnmsCammLyKdlzrBin+25dy6wIjfhJpKBAN80gsTlCgRk2w==", + "node_modules/pupa": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "dev": true, "dependencies": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" + "escape-goat": "^2.0.0" }, "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" + "node": ">=8" } }, - "node_modules/postcss-load-config": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.1.tgz", - "integrity": "sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==", - "dependencies": { - "lilconfig": "^2.0.5", - "yaml": "^2.1.1" - }, - "engines": { - "node": ">= 14" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" }, - "ts-node": { - "optional": true + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" } - } + ] }, - "node_modules/postcss-load-config/node_modules/yaml": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", - "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", - "engines": { - "node": ">= 14" - } + "node_modules/raf-schd": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz", + "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==" }, - "node_modules/postcss-loader": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", - "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", + "node_modules/randomatic": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", "dependencies": { - "cosmiconfig": "^7.0.0", - "klona": "^2.0.5", - "semver": "^7.3.5" + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" }, "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "postcss": "^7.0.0 || ^8.0.1", - "webpack": "^5.0.0" + "node": ">= 0.10.0" } }, - "node_modules/postcss-logical": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-5.0.4.tgz", - "integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==", + "node_modules/randomatic/node_modules/is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", "engines": { - "node": "^12 || ^14 || >=16" + "node": ">=0.10.0" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" }, - "peerDependencies": { - "postcss": "^8.4" + "bin": { + "rc": "cli.js" } }, - "node_modules/postcss-media-minmax": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz", - "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==", + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "postcss": "^8.1.0" + "node": ">=0.10.0" } }, - "node_modules/postcss-merge-longhand": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", - "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "dependencies": { - "postcss-value-parser": "^4.2.0", - "stylehacks": "^5.1.1" + "loose-envify": "^1.1.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=0.10.0" } }, - "node_modules/postcss-merge-rules": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz", - "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==", + "node_modules/react-async-script": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/react-async-script/-/react-async-script-1.2.0.tgz", + "integrity": "sha512-bCpkbm9JiAuMGhkqoAiC0lLkb40DJ0HOEJIku+9JDjxX3Rcs+ztEOG13wbrOskt3n2DTrjshhaQ/iay+SnGg5Q==", "dependencies": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0", - "cssnano-utils": "^3.1.0", - "postcss-selector-parser": "^6.0.5" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" + "hoist-non-react-statics": "^3.3.0", + "prop-types": "^15.5.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "react": ">=16.4.1" } }, - "node_modules/postcss-minify-font-values": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", - "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", + "node_modules/react-beautiful-dnd": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.1.tgz", + "integrity": "sha512-0Lvs4tq2VcrEjEgDXHjT98r+63drkKEgqyxdA7qD3mvKwga6a5SscbdLPO2IExotU1jW8L0Ksdl0Cj2AF67nPQ==", "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" + "@babel/runtime": "^7.9.2", + "css-box-model": "^1.2.0", + "memoize-one": "^5.1.1", + "raf-schd": "^4.0.2", + "react-redux": "^7.2.0", + "redux": "^4.0.4", + "use-memo-one": "^1.1.1" }, "peerDependencies": { - "postcss": "^8.2.15" + "react": "^16.8.5 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.5 || ^17.0.0 || ^18.0.0" } }, - "node_modules/postcss-minify-gradients": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", - "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", + "node_modules/react-beautiful-dnd/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "node_modules/react-beautiful-dnd/node_modules/react-redux": { + "version": "7.2.9", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz", + "integrity": "sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==", "dependencies": { - "colord": "^2.9.1", - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" + "@babel/runtime": "^7.15.4", + "@types/react-redux": "^7.1.20", + "hoist-non-react-statics": "^3.3.2", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^17.0.2" }, "peerDependencies": { - "postcss": "^8.2.15" + "react": "^16.8.3 || ^17 || ^18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } } }, - "node_modules/postcss-minify-params": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", - "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", + "node_modules/react-beautiful-dnd/node_modules/redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", "dependencies": { - "browserslist": "^4.21.4", - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "@babel/runtime": "^7.9.2" } }, - "node_modules/postcss-minify-selectors": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", - "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", + "node_modules/react-bootstrap": { + "version": "2.10.4", + "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.10.4.tgz", + "integrity": "sha512-W3398nBM2CBfmGP2evneEO3ZZwEMPtHs72q++eNw60uDGDAdiGn0f9yNys91eo7/y8CTF5Ke1C0QO8JFVPU40Q==", "dependencies": { - "postcss-selector-parser": "^6.0.5" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" + "@babel/runtime": "^7.24.7", + "@restart/hooks": "^0.4.9", + "@restart/ui": "^1.6.9", + "@types/react-transition-group": "^4.4.6", + "classnames": "^2.3.2", + "dom-helpers": "^5.2.1", + "invariant": "^2.2.4", + "prop-types": "^15.8.1", + "prop-types-extra": "^1.1.0", + "react-transition-group": "^4.4.5", + "uncontrollable": "^7.2.1", + "warning": "^4.0.3" }, "peerDependencies": { - "postcss": "^8.2.15" + "@types/react": ">=16.14.8", + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/postcss-modules": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules/-/postcss-modules-6.0.0.tgz", - "integrity": "sha512-7DGfnlyi/ju82BRzTIjWS5C4Tafmzl3R79YP/PASiocj+aa6yYphHhhKUOEoXQToId5rgyFgJ88+ccOUydjBXQ==", - "dev": true, + "node_modules/react-datepicker": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-7.3.0.tgz", + "integrity": "sha512-EqRKLAtLZUTztiq6a+tjSjQX9ES0Xd229JPckAtyZZ4GoY3rtvNWAzkYZnQUf6zTWT50Ki0+t+W9VRQIkSJLfg==", "dependencies": { - "generic-names": "^4.0.0", - "icss-utils": "^5.1.0", - "lodash.camelcase": "^4.3.0", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.0", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "string-hash": "^1.1.1" + "@floating-ui/react": "^0.26.2", + "clsx": "^2.1.0", + "date-fns": "^3.3.1", + "prop-types": "^15.7.2", + "react-onclickoutside": "^6.13.0" }, "peerDependencies": { - "postcss": "^8.0.0" + "react": "^16.9.0 || ^17 || ^18", + "react-dom": "^16.9.0 || ^17 || ^18" } }, - "node_modules/postcss-modules-extract-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" + "node_modules/react-datepicker/node_modules/date-fns": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" } }, - "node_modules/postcss-modules-local-by-default": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz", - "integrity": "sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==", + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "dependencies": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" }, "peerDependencies": { - "postcss": "^8.1.0" + "react": "^18.3.1" } }, - "node_modules/postcss-modules-scope": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", - "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "node_modules/react-google-recaptcha": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/react-google-recaptcha/-/react-google-recaptcha-3.1.0.tgz", + "integrity": "sha512-cYW2/DWas8nEKZGD7SCu9BSuVz8iOcOLHChHyi7upUuVhkpkhYG/6N3KDiTQ3XAiZ2UAZkfvYKMfAHOzBOcGEg==", "dependencies": { - "postcss-selector-parser": "^6.0.4" - }, - "engines": { - "node": "^10 || ^12 || >= 14" + "prop-types": "^15.5.0", + "react-async-script": "^1.2.0" }, "peerDependencies": { - "postcss": "^8.1.0" + "react": ">=16.4.1" } }, - "node_modules/postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "node_modules/react-i18next": { + "version": "12.3.1", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-12.3.1.tgz", + "integrity": "sha512-5v8E2XjZDFzK7K87eSwC7AJcAkcLt5xYZ4+yTPDAW1i7C93oOY1dnr4BaQM7un4Hm+GmghuiPvevWwlca5PwDA==", "dependencies": { - "icss-utils": "^5.0.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" + "@babel/runtime": "^7.20.6", + "html-parse-stringify": "^3.0.1" }, "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-nested": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", - "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", - "dependencies": { - "postcss-selector-parser": "^6.0.11" + "i18next": ">= 19.0.0", + "react": ">= 16.8.0" }, - "engines": { - "node": ">=12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.2.14" + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } } }, - "node_modules/postcss-nesting": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-10.2.0.tgz", - "integrity": "sha512-EwMkYchxiDiKUhlJGzWsD9b2zvq/r2SSubcRrgP+jujMXFzqvANLt16lJANC+5uZ6hjI7lpRmI6O8JIl+8l1KA==", - "dependencies": { - "@csstools/selector-specificity": "^2.0.0", - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, + "node_modules/react-icons": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.2.1.tgz", + "integrity": "sha512-zdbW5GstTzXaVKvGSyTaBalt7HSfuK5ovrzlpyiWHAFXndXTdd/1hdDHI4xBM1Mn7YriT6aqESucFl9kEXzrdw==", "peerDependencies": { - "postcss": "^8.2" + "react": "*" } }, - "node_modules/postcss-normalize": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize/-/postcss-normalize-10.0.1.tgz", - "integrity": "sha512-+5w18/rDev5mqERcG3W5GZNMJa1eoYYNGo8gB7tEwaos0ajk3ZXAI4mHGcNT47NE+ZnZD1pEpUOFLvltIwmeJA==", + "node_modules/react-infinite-scroll-component": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/react-infinite-scroll-component/-/react-infinite-scroll-component-6.1.0.tgz", + "integrity": "sha512-SQu5nCqy8DxQWpnUVLx7V7b7LcA37aM7tvoWjTLZp1dk6EJibM5/4EJKzOnl07/BsM1Y40sKLuqjCwwH/xV0TQ==", "dependencies": { - "@csstools/normalize.css": "*", - "postcss-browser-comments": "^4", - "sanitize.css": "*" - }, - "engines": { - "node": ">= 12" + "throttle-debounce": "^2.1.0" }, "peerDependencies": { - "browserslist": ">= 4", - "postcss": ">= 8" + "react": ">=16.0.0" } }, - "node_modules/postcss-normalize-charset": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", - "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" + }, + "node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, + "node_modules/react-multi-carousel": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/react-multi-carousel/-/react-multi-carousel-2.8.5.tgz", + "integrity": "sha512-C5DAvJkfzR2JK9YixZ3oyF9x6R4LW6nzTpIXrl9Oujxi4uqP9SzVVCjl+JLM3tSdqdjAx/oWZK3dTVBSR73Q+w==", "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">=8" + } + }, + "node_modules/react-onclickoutside": { + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.13.1.tgz", + "integrity": "sha512-LdrrxK/Yh9zbBQdFbMTXPp3dTSN9B+9YJQucdDu3JNKRrbdU+H+/TVONJoWtOwy4II8Sqf1y/DTI6w/vGPYW0w==", + "funding": { + "type": "individual", + "url": "https://github.com/Pomax/react-onclickoutside/blob/master/FUNDING.md" }, "peerDependencies": { - "postcss": "^8.2.15" + "react": "^15.5.x || ^16.x || ^17.x || ^18.x", + "react-dom": "^15.5.x || ^16.x || ^17.x || ^18.x" } }, - "node_modules/postcss-normalize-display-values": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", - "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", + "node_modules/react-redux": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.1.2.tgz", + "integrity": "sha512-0OA4dhM1W48l3uzmv6B7TXPCGmokUU4p1M44DGN2/D9a1FjVPukVjER1PcPX97jIg6aUeLq1XJo1IpfbgULn0w==", "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" + "@types/use-sync-external-store": "^0.0.3", + "use-sync-external-store": "^1.0.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "@types/react": "^18.2.25", + "react": "^18.0", + "redux": "^5.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "redux": { + "optional": true + } } }, - "node_modules/postcss-normalize-positions": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", - "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", + "node_modules/react-router": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.26.0.tgz", + "integrity": "sha512-wVQq0/iFYd3iZ9H2l3N3k4PL8EEHcb0XlU2Na8nEwmiXgIUElEH6gaJDtUQxJ+JFzmIXaQjfdpcGWaM6IoQGxg==", "dependencies": { - "postcss-value-parser": "^4.2.0" + "@remix-run/router": "1.19.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">=14.0.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "react": ">=16.8" } }, - "node_modules/postcss-normalize-repeat-style": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", - "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", + "node_modules/react-router-dom": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.26.0.tgz", + "integrity": "sha512-RRGUIiDtLrkX3uYcFiCIxKFWMcWQGMojpYZfcstc63A1+sSnVgILGIm9gNUA6na3Fm1QuPGSBQH2EMbAZOnMsQ==", "dependencies": { - "postcss-value-parser": "^4.2.0" + "@remix-run/router": "1.19.0", + "react-router": "6.26.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">=14.0.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "react": ">=16.8", + "react-dom": ">=16.8" } }, - "node_modules/postcss-normalize-string": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", - "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", + "node_modules/react-toastify": { + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-10.0.5.tgz", + "integrity": "sha512-mNKt2jBXJg4O7pSdbNUfDdTsK9FIdikfsIE/yUCxbAEXl4HMyJaivrVFcn3Elvt5xvCQYhUZm+hqTIu1UXM3Pw==", "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" + "clsx": "^2.1.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "react": ">=18", + "react-dom": ">=18" } }, - "node_modules/postcss-normalize-timing-functions": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", - "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", + "node_modules/react-tooltip": { + "version": "5.27.1", + "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.27.1.tgz", + "integrity": "sha512-a+micPXcMOMt11CYlwJD4XShcqGziasHco4NPe1OFw298WBTILMyzUgNC1LAFViAe791JdHNVSJIpzhZm2MvDA==", "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" + "@floating-ui/dom": "^1.6.1", + "classnames": "^2.3.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "react": ">=16.14.0", + "react-dom": ">=16.14.0" } }, - "node_modules/postcss-normalize-unicode": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", - "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", "dependencies": { - "browserslist": "^4.21.4", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" }, "peerDependencies": { - "postcss": "^8.2.15" + "react": ">=16.6.0", + "react-dom": ">=16.6.0" } }, - "node_modules/postcss-normalize-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", - "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, "dependencies": { - "normalize-url": "^6.0.1", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "pify": "^2.3.0" } }, - "node_modules/postcss-normalize-whitespace": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", - "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dependencies": { - "postcss-value-parser": "^4.2.0" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" }, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">= 6" } }, - "node_modules/postcss-opacity-percentage": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.3.tgz", - "integrity": "sha512-An6Ba4pHBiDtyVpSLymUUERMo2cU7s+Obz6BTrS+gxkbnSBNKSuD0AVUc+CpBMrpVPKKfoVz0WQCX+Tnst0i4A==", - "funding": [ - { - "type": "kofi", - "url": "https://ko-fi.com/mrcgrtz" - }, - { - "type": "liberapay", - "url": "https://liberapay.com/mrcgrtz" - } - ], - "engines": { - "node": "^12 || ^14 || >=16" + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "devOptional": true, + "dependencies": { + "picomatch": "^2.2.1" }, - "peerDependencies": { - "postcss": "^8.2" + "engines": { + "node": ">=8.10.0" } }, - "node_modules/postcss-ordered-values": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", - "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, "dependencies": { - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" - }, + "node": ">=8" + } + }, + "node_modules/redux": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==" + }, + "node_modules/redux-thunk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", + "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", "peerDependencies": { - "postcss": "^8.2.15" + "redux": "^5.0.0" } }, - "node_modules/postcss-overflow-shorthand": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.4.tgz", - "integrity": "sha512-otYl/ylHK8Y9bcBnPLo3foYFLL6a6Ak+3EQBPOTR7luMYCOsiVTUk1iLvNf6tVPNGXcoL9Hoz37kpfriRIFb4A==", + "node_modules/reflect.getprototypeof": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "dev": true, "dependencies": { - "postcss-value-parser": "^4.2.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" }, "engines": { - "node": "^12 || ^14 || >=16" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/postcss-page-break": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", - "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", - "peerDependencies": { - "postcss": "^8" - } + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true }, - "node_modules/postcss-place": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-7.0.5.tgz", - "integrity": "sha512-wR8igaZROA6Z4pv0d+bvVrvGY4GVHihBCBQieXFY3kuSuMyOmEnnfFzHl/tQuqHZkfkIVBEbDvYcFfHmpSet9g==", + "node_modules/regenerate-unicode-properties": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz", + "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==", + "dev": true, "dependencies": { - "postcss-value-parser": "^4.2.0" + "regenerate": "^1.4.2" }, "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" + "node": ">=4" } }, - "node_modules/postcss-preset-env": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-7.8.3.tgz", - "integrity": "sha512-T1LgRm5uEVFSEF83vHZJV2z19lHg4yJuZ6gXZZkqVsqv63nlr6zabMH3l4Pc01FQCyfWVrh2GaUeCVy9Po+Aag==", - "dependencies": { - "@csstools/postcss-cascade-layers": "^1.1.1", - "@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.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.13", - "browserslist": "^4.21.4", - "css-blank-pseudo": "^3.0.3", - "css-has-pseudo": "^3.0.4", - "css-prefers-color-scheme": "^6.0.3", - "cssdb": "^7.1.0", - "postcss-attribute-case-insensitive": "^5.0.2", - "postcss-clamp": "^4.1.0", - "postcss-color-functional-notation": "^4.2.4", - "postcss-color-hex-alpha": "^8.0.4", - "postcss-color-rebeccapurple": "^7.1.1", - "postcss-custom-media": "^8.0.2", - "postcss-custom-properties": "^12.1.10", - "postcss-custom-selectors": "^6.0.3", - "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.5", - "postcss-image-set-function": "^4.0.7", - "postcss-initial": "^4.0.1", - "postcss-lab-function": "^4.2.1", - "postcss-logical": "^5.0.4", - "postcss-media-minmax": "^5.0.0", - "postcss-nesting": "^10.2.0", - "postcss-opacity-percentage": "^1.1.2", - "postcss-overflow-shorthand": "^3.0.4", - "postcss-page-break": "^3.0.4", - "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.1", - "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/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.8.4" } }, - "node_modules/postcss-pseudo-class-any-link": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.6.tgz", - "integrity": "sha512-9sCtZkO6f/5ML9WcTLcIyV1yz9D1rf0tWc+ulKcvV30s0iZKS/ONyETvoWsr6vnrmW+X+KmuK3gV/w5EWnT37w==", + "node_modules/regex": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/regex/-/regex-4.3.2.tgz", + "integrity": "sha512-kK/AA3A9K6q2js89+VMymcboLOlF5lZRCYJv3gzszXFHBr6kO6qLGzbm+UIugBEV8SMMKCTR59txoY6ctRHYVw==" + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "dev": true, "dependencies": { - "postcss-selector-parser": "^6.0.10" + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" }, "engines": { - "node": "^12 || ^14 || >=16" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/postcss-reduce-initial": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz", - "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==", + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dev": true, "dependencies": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0" + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=4" } }, - "node_modules/postcss-reduce-transforms": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", - "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", + "node_modules/registry-auth-token": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz", + "integrity": "sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==", + "dev": true, "dependencies": { - "postcss-value-parser": "^4.2.0" + "rc": "1.2.8" }, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=6.0.0" } }, - "node_modules/postcss-replace-overflow-wrap": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", - "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", - "peerDependencies": { - "postcss": "^8.0.3" - } - }, - "node_modules/postcss-selector-not": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-6.0.1.tgz", - "integrity": "sha512-1i9affjAe9xu/y9uqWH+tD4r6/hDaXJruk8xn2x1vzxC2U3J3LKO3zJW4CyxlNhA56pADJ/djpEwpH1RClI2rQ==", - "dependencies": { - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.0.13", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", - "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "node_modules/registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dev": true, "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" + "rc": "^1.2.8" }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/postcss-svgo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", - "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dev": true, "dependencies": { - "postcss-value-parser": "^4.2.0", - "svgo": "^2.7.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" + "jsesc": "~0.5.0" }, - "peerDependencies": { - "postcss": "^8.2.15" + "bin": { + "regjsparser": "bin/parser" } }, - "node_modules/postcss-svgo/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "engines": { - "node": ">= 10" + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" } }, - "node_modules/postcss-svgo/node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" + "node_modules/rehackt": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/rehackt/-/rehackt-0.1.0.tgz", + "integrity": "sha512-7kRDOuLHB87D/JESKxQoRwv4DzbIdwkAGQ7p6QKGdVlY1IZheUnVhlk/4UZlNUVxdAXpyxikE3URsG067ybVzw==", + "peerDependencies": { + "@types/react": "*", + "react": "*" }, - "funding": { - "url": "https://github.com/sponsors/fb55" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + } } }, - "node_modules/postcss-svgo/node_modules/css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "node_modules/remarkable": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/remarkable/-/remarkable-1.7.4.tgz", + "integrity": "sha512-e6NKUXgX95whv7IgddywbeN/ItCkWbISmc2DiqHJb0wTrqZIexqdco5b8Z3XZoo/48IdNVKM9ZCvTPJ4F5uvhg==", "dependencies": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" + "argparse": "^1.0.10", + "autolinker": "~0.28.0" }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/postcss-svgo/node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" + "bin": { + "remarkable": "bin/remarkable.js" }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + "engines": { + "node": ">= 0.10.0" } }, - "node_modules/postcss-svgo/node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dependencies": { - "domelementtype": "^2.2.0" - }, + "node_modules/repeat-element": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", + "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/postcss-svgo/node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "engines": { + "node": ">=0.10" } }, - "node_modules/postcss-svgo/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/postcss-svgo/node_modules/mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" - }, - "node_modules/postcss-svgo/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/postcss-svgo/node_modules/svgo": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", - "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, + "node_modules/reselect": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==" + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dependencies": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^4.1.3", - "css-tree": "^1.1.3", - "csso": "^4.2.0", - "picocolors": "^1.0.0", - "stable": "^0.1.8" + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { - "svgo": "bin/svgo" + "resolve": "bin/resolve" }, - "engines": { - "node": ">=10.13.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/postcss-unique-selectors": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", - "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, "dependencies": { - "postcss-selector-parser": "^6.0.5" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" + "resolve-from": "^5.0.0" }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "engines": { - "node": ">= 0.8.0" + "node": ">=8" } }, - "node_modules/prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/prettier": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", - "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", - "bin": { - "prettier": "bin/prettier.cjs" + "node_modules/resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/prettier-linter-helpers": { + "node_modules/resolve-dir/node_modules/global-modules": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", "dev": true, "dependencies": { - "fast-diff": "^1.1.2" + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" }, "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/pretty-bytes": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", - "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pretty-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", - "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", - "dependencies": { - "lodash": "^4.17.20", - "renderkid": "^3.0.0" + "node": ">=0.10.0" } }, - "node_modules/pretty-format": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", - "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "node_modules/resolve-dir/node_modules/global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", "dev": true, "dependencies": { - "@jest/types": "^26.6.2", - "ansi-regex": "^5.0.0", - "ansi-styles": "^4.0.0", - "react-is": "^17.0.1" + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" }, "engines": { - "node": ">= 10" + "node": ">=0.10.0" } }, - "node_modules/pretty-format/node_modules/@jest/types": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", - "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "node_modules/resolve-dir/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^15.0.0", - "chalk": "^4.0.0" + "isexe": "^2.0.0" }, - "engines": { - "node": ">= 10.14.2" + "bin": { + "which": "bin/which" } }, - "node_modules/pretty-format/node_modules/@types/yargs": { - "version": "15.0.15", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.15.tgz", - "integrity": "sha512-IziEYMU9XoVj8hWg7k+UJrXALkGFjWJhn5QFEv9q4p+v40oZhSuC135M38st8XPjICL7Ey4TV64ferBGUoJhBg==", - "dev": true, - "dependencies": { - "@types/yargs-parser": "*" + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" } }, - "node_modules/pretty-format/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", "dev": true, - "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/pretty-format/node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "node_modules/promise": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", - "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", - "dependencies": { - "asap": "~2.0.6" + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", - "optional": true, - "peer": true - }, - "node_modules/promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "optional": true, - "peer": true, - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, + "node_modules/resolve.exports": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.1.tgz", + "integrity": "sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==", + "dev": true, "engines": { "node": ">=10" } }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, + "node_modules/response-iterator": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/response-iterator/-/response-iterator-0.2.6.tgz", + "integrity": "sha512-pVzEEzrsg23Sh053rmDUvLSkGXluZio0qu8VT6ukrYuvtjVfCbDZH9d6PGXb8HZfzdNZt8feXv/jvUzlhRgLnw==", "engines": { - "node": ">= 6" + "node": ">=0.8" } }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "node_modules/responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", + "dev": true, "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" + "lowercase-keys": "^1.0.0" } }, - "node_modules/prop-types-extra": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz", - "integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==", + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, "dependencies": { - "react-is": "^16.3.2", - "warning": "^4.0.0" + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" }, - "peerDependencies": { - "react": ">=0.14.0" + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/prop-types-extra/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/prop-types/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "node_modules/restore-cursor/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" + "mimic-function": "^5.0.0" }, "engines": { - "node": ">= 0.10" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/proxy-addr/node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, "engines": { - "node": ">= 0.10" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" - }, - "node_modules/pump": { + "node_modules/restructure": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } + "resolved": "https://registry.npmjs.org/restructure/-/restructure-3.0.0.tgz", + "integrity": "sha512-Xj8/MEIhhfj9X2rmD9iJ4Gga9EFqVlpMj3vfLnV2r/Mh5jRMryNV+6lWh9GdJtDBcBSPIqzRdfBQ3wDtNFv/uw==" }, - "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, "engines": { - "node": ">=6" + "iojs": ">=1.0.0", + "node": ">=0.10.0" } }, - "node_modules/punycode.js": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", - "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", - "peer": true, - "engines": { - "node": ">=6" - } + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true }, - "node_modules/pupa": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", - "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "dependencies": { - "escape-goat": "^2.0.0" + "glob": "^7.1.3" }, - "engines": { - "node": ">=8" + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", - "engines": { - "node": ">=0.6.0", - "teleport": ">=0.2.0" - } + "node_modules/robust-predicates": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" }, - "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "node_modules/rollup": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.3.tgz", + "integrity": "sha512-7sqRtBNnEbcBtMeRVc6VRsJMmpI+JU1z9VTvW8D4gXIYQFz0aLcsE6rRkyghZkLfEgUZgVvOG7A5CVz/VW5GIA==", "dependencies": { - "side-channel": "^1.0.4" + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" }, "engines": { - "node": ">=0.6" + "node": ">=18.0.0", + "npm": ">=8.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.21.3", + "@rollup/rollup-android-arm64": "4.21.3", + "@rollup/rollup-darwin-arm64": "4.21.3", + "@rollup/rollup-darwin-x64": "4.21.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.21.3", + "@rollup/rollup-linux-arm-musleabihf": "4.21.3", + "@rollup/rollup-linux-arm64-gnu": "4.21.3", + "@rollup/rollup-linux-arm64-musl": "4.21.3", + "@rollup/rollup-linux-powerpc64le-gnu": "4.21.3", + "@rollup/rollup-linux-riscv64-gnu": "4.21.3", + "@rollup/rollup-linux-s390x-gnu": "4.21.3", + "@rollup/rollup-linux-x64-gnu": "4.21.3", + "@rollup/rollup-linux-x64-musl": "4.21.3", + "@rollup/rollup-win32-arm64-msvc": "4.21.3", + "@rollup/rollup-win32-ia32-msvc": "4.21.3", + "@rollup/rollup-win32-x64-msvc": "4.21.3", + "fsevents": "~2.3.2" } }, - "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/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "engines": { + "node": ">=0.12.0" + } }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, "funding": [ { "type": "github", @@ -20121,919 +16197,696 @@ "type": "consulting", "url": "https://feross.org/support" } - ] - }, - "node_modules/quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "optional": true, - "peer": true, - "engines": { - "node": ">=8" + ], + "dependencies": { + "queue-microtask": "^1.2.2" } }, - "node_modules/raf": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", - "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", "dependencies": { - "performance-now": "^2.1.0" + "tslib": "^2.1.0" } }, - "node_modules/raf-schd": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz", - "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==" - }, - "node_modules/randomatic": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", - "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, "dependencies": { - "is-number": "^4.0.0", - "kind-of": "^6.0.0", - "math-random": "^1.0.1" + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" }, "engines": { - "node": ">= 0.10.0" + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/randomatic/node_modules/is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "engines": { - "node": ">=0.10.0" - } + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, "engines": { - "node": ">= 0.6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sanitize-html": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.13.0.tgz", + "integrity": "sha512-Xff91Z+4Mz5QiNSLdLWwjgBDm5b1RU6xBT0+12rapjiaR7SwfRdjw8f+6Rir2MXKLrDicRFHdb51hGOAxmsUIA==", "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" + "deepmerge": "^4.2.2", + "escape-string-regexp": "^4.0.0", + "htmlparser2": "^8.0.0", + "is-plain-object": "^5.0.0", + "parse-srcset": "^1.0.2", + "postcss": "^8.3.11" } }, - "node_modules/raw-body/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "node_modules/sanitize-html/node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", "engines": { - "node": ">= 0.8" + "node": ">=0.10.0" } }, - "node_modules/raw-body/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "node_modules/sass": { + "version": "1.77.8", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.8.tgz", + "integrity": "sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ==", + "devOptional": true, "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" }, "engines": { - "node": ">=0.10.0" + "node": ">=14.0.0" } }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "node_modules/saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", "dev": true, "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" + "xmlchars": "^2.2.0" }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/react": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", - "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - }, - "engines": { - "node": ">=0.10.0" + "loose-envify": "^1.1.0" } }, - "node_modules/react-app-polyfill": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-3.0.0.tgz", - "integrity": "sha512-sZ41cxiU5llIB003yxxQBYrARBqe0repqPTTYBTmMqTz9szeBbE37BehCE891NZsmdZqqP+xWKdT3eo3vOzN8w==", - "dependencies": { - "core-js": "^3.19.2", - "object-assign": "^4.1.1", - "promise": "^8.1.0", - "raf": "^3.4.1", - "regenerator-runtime": "^0.13.9", - "whatwg-fetch": "^3.6.2" + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=14" + "node": ">=10" } }, - "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==", + "node_modules/semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "dev": true, "dependencies": { - "semver": "^5.6.0" - }, - "bin": { - "react-app-rewired": "bin/index.js" + "semver": "^6.3.0" }, - "peerDependencies": { - "react-scripts": ">=2.1.3" + "engines": { + "node": ">=8" } }, - "node_modules/react-app-rewired/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "node_modules/semver-diff/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, "bin": { - "semver": "bin/semver" + "semver": "bin/semver.js" } }, - "node_modules/react-async-script": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/react-async-script/-/react-async-script-1.2.0.tgz", - "integrity": "sha512-bCpkbm9JiAuMGhkqoAiC0lLkb40DJ0HOEJIku+9JDjxX3Rcs+ztEOG13wbrOskt3n2DTrjshhaQ/iay+SnGg5Q==", + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, "dependencies": { - "hoist-non-react-statics": "^3.3.0", - "prop-types": "^15.5.0" + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" }, - "peerDependencies": { - "react": ">=16.4.1" + "engines": { + "node": ">= 0.4" } }, - "node_modules/react-beautiful-dnd": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.1.tgz", - "integrity": "sha512-0Lvs4tq2VcrEjEgDXHjT98r+63drkKEgqyxdA7qD3mvKwga6a5SscbdLPO2IExotU1jW8L0Ksdl0Cj2AF67nPQ==", + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.9.2", - "css-box-model": "^1.2.0", - "memoize-one": "^5.1.1", - "raf-schd": "^4.0.2", - "react-redux": "^7.2.0", - "redux": "^4.0.4", - "use-memo-one": "^1.1.1" + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" }, - "peerDependencies": { - "react": "^16.8.5 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.5 || ^17.0.0 || ^18.0.0" + "engines": { + "node": ">= 0.4" } }, - "node_modules/react-bootstrap": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.8.0.tgz", - "integrity": "sha512-e/aNtxl0Z2ozrIaR82jr6Zz7ss9GSoaXpQaxmvtDUsTZIq/XalkduR/ZXP6vbQHz2T4syvjA+4FbtwELxxmpww==", + "node_modules/set-getter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.1.tgz", + "integrity": "sha512-9sVWOy+gthr+0G9DzqqLaYNA7+5OKkSmcqjL9cBpDEaZrr3ShQlyX2cZ/O/ozE41oxn/Tt0LGEM/w4Rub3A3gw==", "dependencies": { - "@babel/runtime": "^7.21.0", - "@restart/hooks": "^0.4.9", - "@restart/ui": "^1.6.3", - "@types/react-transition-group": "^4.4.5", - "classnames": "^2.3.2", - "dom-helpers": "^5.2.1", - "invariant": "^2.2.4", - "prop-types": "^15.8.1", - "prop-types-extra": "^1.1.0", - "react-transition-group": "^4.4.5", - "uncontrollable": "^7.2.1", - "warning": "^4.0.3" - }, - "peerDependencies": { - "@types/react": ">=16.14.8", - "react": ">=16.14.0", - "react-dom": ">=16.14.0" + "to-object-path": "^0.3.0" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=0.10.0" } }, - "node_modules/react-datepicker": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-7.3.0.tgz", - "integrity": "sha512-EqRKLAtLZUTztiq6a+tjSjQX9ES0Xd229JPckAtyZZ4GoY3rtvNWAzkYZnQUf6zTWT50Ki0+t+W9VRQIkSJLfg==", + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "dependencies": { - "@floating-ui/react": "^0.26.2", - "clsx": "^2.1.0", - "date-fns": "^3.3.1", - "prop-types": "^15.7.2", - "react-onclickoutside": "^6.13.0" + "shebang-regex": "^3.0.0" }, - "peerDependencies": { - "react": "^16.9.0 || ^17 || ^18", - "react-dom": "^16.9.0 || ^17 || ^18" + "engines": { + "node": ">=8" } }, - "node_modules/react-datepicker/node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/react-datepicker/node_modules/date-fns": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", - "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/kossnocorp" + "node_modules/shiki": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.17.6.tgz", + "integrity": "sha512-RejGugKpDM75vh6YtF9R771acxHRDikC/01kxsUGW+Pnaz3pTY+c8aZB5CnD7p0vuFPs1HaoAIU/4E+NCfS+mQ==", + "dependencies": { + "@shikijs/core": "1.17.6", + "@shikijs/engine-javascript": "1.17.6", + "@shikijs/engine-oniguruma": "1.17.6", + "@shikijs/types": "1.17.6", + "@shikijs/vscode-textmate": "^9.2.2", + "@types/hast": "^3.0.4" } }, - "node_modules/react-dev-utils": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", - "integrity": "sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==", - "dependencies": { - "@babel/code-frame": "^7.16.0", - "address": "^1.1.2", - "browserslist": "^4.18.1", - "chalk": "^4.1.2", - "cross-spawn": "^7.0.3", - "detect-port-alt": "^1.1.6", - "escape-string-regexp": "^4.0.0", - "filesize": "^8.0.6", - "find-up": "^5.0.0", - "fork-ts-checker-webpack-plugin": "^6.5.0", - "global-modules": "^2.0.0", - "globby": "^11.0.4", - "gzip-size": "^6.0.0", - "immer": "^9.0.7", - "is-root": "^2.1.0", - "loader-utils": "^3.2.0", - "open": "^8.4.0", - "pkg-up": "^3.1.0", - "prompts": "^2.4.2", - "react-error-overlay": "^6.0.11", - "recursive-readdir": "^2.2.2", - "shell-quote": "^1.7.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/react-dev-utils/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/react-dev-utils/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "license": "MIT", "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "license": "MIT" + }, + "node_modules/sirv": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.3.tgz", + "integrity": "sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA==", + "dev": true, + "dependencies": { + "@polka/url": "^1.0.0-next.20", + "mrmime": "^1.0.0", + "totalist": "^3.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 10" } }, - "node_modules/react-dev-utils/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, "dependencies": { - "p-locate": "^5.0.0" + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" }, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/react-dev-utils/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dependencies": { - "yocto-queue": "^0.1.0" - }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/react-dev-utils/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dependencies": { - "p-limit": "^3.0.2" - }, + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/react-dom": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", - "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dev": true, "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "scheduler": "^0.20.2" - }, - "peerDependencies": { - "react": "17.0.2" + "dot-case": "^3.0.4", + "tslib": "^2.0.3" } }, - "node_modules/react-error-overlay": { - "version": "6.0.11", - "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", - "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/react-fast-compare": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", - "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==", - "dev": true + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/react-google-recaptcha": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/react-google-recaptcha/-/react-google-recaptcha-3.1.0.tgz", - "integrity": "sha512-cYW2/DWas8nEKZGD7SCu9BSuVz8iOcOLHChHyi7upUuVhkpkhYG/6N3KDiTQ3XAiZ2UAZkfvYKMfAHOzBOcGEg==", + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "devOptional": true, "dependencies": { - "prop-types": "^15.5.0", - "react-async-script": "^1.2.0" - }, - "peerDependencies": { - "react": ">=16.4.1" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, - "node_modules/react-i18next": { - "version": "11.18.6", - "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.18.6.tgz", - "integrity": "sha512-yHb2F9BiT0lqoQDt8loZ5gWP331GwctHz9tYQ8A2EIEUu+CcEdjBLQWli1USG3RdWQt3W+jqQLg/d4rrQR96LA==", - "dependencies": { - "@babel/runtime": "^7.14.5", - "html-parse-stringify": "^3.0.1" - }, - "peerDependencies": { - "i18next": ">= 19.0.0", - "react": ">= 16.8.0" - }, - "peerDependenciesMeta": { - "react-dom": { - "optional": true - }, - "react-native": { - "optional": true - } + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "devOptional": true, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/react-icons": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.2.1.tgz", - "integrity": "sha512-zdbW5GstTzXaVKvGSyTaBalt7HSfuK5ovrzlpyiWHAFXndXTdd/1hdDHI4xBM1Mn7YriT6aqESucFl9kEXzrdw==", - "peerDependencies": { - "react": "*" + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/react-infinite-scroll-component": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/react-infinite-scroll-component/-/react-infinite-scroll-component-6.1.0.tgz", - "integrity": "sha512-SQu5nCqy8DxQWpnUVLx7V7b7LcA37aM7tvoWjTLZp1dk6EJibM5/4EJKzOnl07/BsM1Y40sKLuqjCwwH/xV0TQ==", + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, "dependencies": { - "throttle-debounce": "^2.1.0" + "escape-string-regexp": "^2.0.0" }, - "peerDependencies": { - "react": ">=16.0.0" + "engines": { + "node": ">=10" } }, - "node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" - }, - "node_modules/react-lifecycles-compat": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", - "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" - }, - "node_modules/react-multi-carousel": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/react-multi-carousel/-/react-multi-carousel-2.8.5.tgz", - "integrity": "sha512-C5DAvJkfzR2JK9YixZ3oyF9x6R4LW6nzTpIXrl9Oujxi4uqP9SzVVCjl+JLM3tSdqdjAx/oWZK3dTVBSR73Q+w==", + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, "engines": { "node": ">=8" } }, - "node_modules/react-onclickoutside": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.13.0.tgz", - "integrity": "sha512-ty8So6tcUpIb+ZE+1HAhbLROvAIJYyJe/1vRrrcmW+jLsaM+/powDRqxzo6hSh9CuRZGSL1Q8mvcF5WRD93a0A==", - "funding": { - "type": "individual", - "url": "https://github.com/Pomax/react-onclickoutside/blob/master/FUNDING.md" - }, - "peerDependencies": { - "react": "^15.5.x || ^16.x || ^17.x || ^18.x", - "react-dom": "^15.5.x || ^16.x || ^17.x || ^18.x" + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true, + "engines": { + "node": ">= 0.6" } }, - "node_modules/react-popper": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz", - "integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==", - "dev": true, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dependencies": { - "react-fast-compare": "^3.0.1", - "warning": "^4.0.2" - }, - "peerDependencies": { - "@popperjs/core": "^2.0.0", - "react": "^16.8.0 || ^17 || ^18", - "react-dom": "^16.8.0 || ^17 || ^18" + "safe-buffer": "~5.2.0" } }, - "node_modules/react-redux": { - "version": "7.2.9", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz", - "integrity": "sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==", - "dependencies": { - "@babel/runtime": "^7.15.4", - "@types/react-redux": "^7.1.20", - "hoist-non-react-statics": "^3.3.2", - "loose-envify": "^1.4.0", - "prop-types": "^15.7.2", - "react-is": "^17.0.2" - }, - "peerDependencies": { - "react": "^16.8.3 || ^17 || ^18" - }, - "peerDependenciesMeta": { - "react-dom": { - "optional": true - }, - "react-native": { - "optional": true - } - } - }, - "node_modules/react-redux/node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" - }, - "node_modules/react-refresh": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", - "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==", + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=0.6.19" } }, - "node_modules/react-router": { - "version": "6.25.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.25.1.tgz", - "integrity": "sha512-u8ELFr5Z6g02nUtpPAggP73Jigj1mRePSwhS/2nkTrlPU5yEkH1vYzWNyvSnSzeeE2DNqWdH+P8OhIh9wuXhTw==", + "node_modules/string-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", + "integrity": "sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==", + "dev": true + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, "dependencies": { - "@remix-run/router": "1.18.0" + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "react": ">=16.8" + "node": ">=10" } }, - "node_modules/react-router-dom": { - "version": "6.25.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.25.1.tgz", - "integrity": "sha512-0tUDpbFvk35iv+N89dWNrJp+afLgd+y4VtorJZuOCXK0kkCWjEvb3vTJM++SYvMEpbVwXKf3FjeVveVEb6JpDQ==", + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dependencies": { - "@remix-run/router": "1.18.0", - "react-router": "6.25.1" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "react": ">=16.8", - "react-dom": ">=16.8" + "node": ">=8" } }, - "node_modules/react-scripts": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", - "integrity": "sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==", - "dependencies": { - "@babel/core": "^7.16.0", - "@pmmmwh/react-refresh-webpack-plugin": "^0.5.3", - "@svgr/webpack": "^5.5.0", - "babel-jest": "^27.4.2", - "babel-loader": "^8.2.3", - "babel-plugin-named-asset-import": "^0.3.8", - "babel-preset-react-app": "^10.0.1", - "bfj": "^7.0.2", - "browserslist": "^4.18.1", - "camelcase": "^6.2.1", - "case-sensitive-paths-webpack-plugin": "^2.4.0", - "css-loader": "^6.5.1", - "css-minimizer-webpack-plugin": "^3.2.0", - "dotenv": "^10.0.0", - "dotenv-expand": "^5.1.0", - "eslint": "^8.3.0", - "eslint-config-react-app": "^7.0.1", - "eslint-webpack-plugin": "^3.1.1", - "file-loader": "^6.2.0", - "fs-extra": "^10.0.0", - "html-webpack-plugin": "^5.5.0", - "identity-obj-proxy": "^3.0.0", - "jest": "^27.4.3", - "jest-resolve": "^27.4.2", - "jest-watch-typeahead": "^1.0.0", - "mini-css-extract-plugin": "^2.4.5", - "postcss": "^8.4.4", - "postcss-flexbugs-fixes": "^5.0.2", - "postcss-loader": "^6.2.1", - "postcss-normalize": "^10.0.1", - "postcss-preset-env": "^7.0.1", - "prompts": "^2.4.2", - "react-app-polyfill": "^3.0.0", - "react-dev-utils": "^12.0.1", - "react-refresh": "^0.11.0", - "resolve": "^1.20.0", - "resolve-url-loader": "^4.0.0", - "sass-loader": "^12.3.0", - "semver": "^7.3.5", - "source-map-loader": "^3.0.0", - "style-loader": "^3.3.1", - "tailwindcss": "^3.0.2", - "terser-webpack-plugin": "^5.2.5", - "webpack": "^5.64.4", - "webpack-dev-server": "^4.6.0", - "webpack-manifest-plugin": "^4.0.2", - "workbox-webpack-plugin": "^6.4.1" - }, - "bin": { - "react-scripts": "bin/react-scripts.js" - }, - "engines": { - "node": ">=14.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" - }, - "peerDependencies": { - "react": ">= 16", - "typescript": "^3.2.1 || ^4" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } + "node_modules/string-width/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, - "node_modules/react-scripts/node_modules/babel-jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", - "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", + "node_modules/string.prototype.matchall": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "dev": true, "dependencies": { - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^27.5.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.8.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/react-scripts/node_modules/babel-plugin-jest-hoist": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", - "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.0.0", - "@types/babel__traverse": "^7.0.6" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" } }, - "node_modules/react-scripts/node_modules/babel-preset-jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", - "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, "dependencies": { - "babel-plugin-jest-hoist": "^27.5.1", - "babel-preset-current-node-syntax": "^1.0.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/react-scripts/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "engines": { - "node": ">=10" + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/react-scripts/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/react-toastify": { - "version": "9.1.3", - "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.1.3.tgz", - "integrity": "sha512-fPfb8ghtn/XMxw3LkxQBk3IyagNpF/LIKjOBflbexr2AWxAH1MJgvnESwEwBn9liLFXgTKWgBSdZpw9m4OTHTg==", + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", "dependencies": { - "clsx": "^1.1.1" + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" }, - "peerDependencies": { - "react": ">=16", - "react-dom": ">=16" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/react-tooltip": { - "version": "5.27.1", - "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.27.1.tgz", - "integrity": "sha512-a+micPXcMOMt11CYlwJD4XShcqGziasHco4NPe1OFw298WBTILMyzUgNC1LAFViAe791JdHNVSJIpzhZm2MvDA==", + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dependencies": { - "@floating-ui/dom": "^1.6.1", - "classnames": "^2.3.0" + "ansi-regex": "^5.0.1" }, - "peerDependencies": { - "react": ">=16.14.0", - "react-dom": ">=16.14.0" + "engines": { + "node": ">=8" } }, - "node_modules/react-transition-group": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", - "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", - "dependencies": { - "@babel/runtime": "^7.5.5", - "dom-helpers": "^5.0.1", - "loose-envify": "^1.4.0", - "prop-types": "^15.6.2" - }, - "peerDependencies": { - "react": ">=16.6.0", - "react-dom": ">=16.6.0" + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dependencies": { - "pify": "^2.3.0" + "node_modules/strip-color": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/strip-color/-/strip-color-0.1.0.tgz", + "integrity": "sha512-p9LsUieSjWNNAxVCXLeilaDlmuUOrDS5/dF9znM1nZc7EGX5+zEFC0bEevsNIaldjlks+2jns5Siz6F9iK6jwA==", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "optional": true, - "peer": true, - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "optional": true, - "peer": true, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" + "min-indent": "^1.0.0" }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-pkg-up/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "optional": true, - "peer": true, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-pkg/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "optional": true, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "license": "MIT", "peer": true }, - "node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "optional": true, - "peer": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/read-pkg/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "optional": true, - "peer": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "optional": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" }, - "node_modules/recursive-readdir": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", - "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", + "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": { - "minimatch": "^3.0.5" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=6.0.0" + "node": ">=8" } }, - "node_modules/redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "devOptional": true, + "node_modules/supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "dev": true, "dependencies": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/redux": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", - "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", - "dependencies": { - "@babel/runtime": "^7.9.2" - } - }, - "node_modules/redux-thunk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz", - "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==", - "peerDependencies": { - "redux": "^4" - } - }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", - "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.1", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", - "which-builtin-type": "^1.1.3" - }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "engines": { "node": ">= 0.4" }, @@ -21041,2744 +16894,817 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", + "dev": true }, - "node_modules/regenerate-unicode-properties": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz", - "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==", - "dependencies": { - "regenerate": "^1.4.2" - }, + "node_modules/symbol-observable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", + "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", "engines": { - "node": ">=4" + "node": ">=0.10" } }, - "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true }, - "node_modules/regenerator-transform": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", - "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "node_modules/synckit": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", + "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.8.4" + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" } }, - "node_modules/regex-parser": { - "version": "2.2.11", - "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.11.tgz", - "integrity": "sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q==" + "node_modules/tabbable": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==" }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", - "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "node_modules/terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "dev": true, "dependencies": { - "call-bind": "^1.0.6", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "set-function-name": "^2.0.1" + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/regexpu-core": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", - "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "node_modules/terser": { + "version": "5.32.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.32.0.tgz", + "integrity": "sha512-v3Gtw3IzpBJ0ugkxEX8U0W6+TnPKRRCWGh1jC/iM/e3Ki5+qvO1L1EAZ56bZasc64aXHwRHNIQEzm6//i5cemQ==", + "optional": true, + "peer": true, "dependencies": { - "@babel/regjsgen": "^0.8.0", - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsparser": "^0.9.1", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" }, "engines": { - "node": ">=4" + "node": ">=10" } }, - "node_modules/registry-auth-token": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz", - "integrity": "sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==", + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "optional": true, + "peer": true + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, "dependencies": { - "rc": "1.2.8" + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" }, "engines": { - "node": ">=6.0.0" + "node": ">=8" } }, - "node_modules/registry-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", - "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true, - "dependencies": { - "rc": "^1.2.8" - }, + "peer": true + }, + "node_modules/throat": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz", + "integrity": "sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==", + "dev": true + }, + "node_modules/throttle-debounce": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-2.3.0.tgz", + "integrity": "sha512-H7oLPV0P7+jgvrk+6mwwwBDmxTaxnu9HMXmloNLXwnNO0ZxZ31Orah2n8lU1eMPvsaowP2CX+USCgyovXfdOFQ==", "engines": { "node": ">=8" } }, - "node_modules/regjsparser": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", - "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", - "dependencies": { - "jsesc": "~0.5.0" - }, - "bin": { - "regjsparser": "bin/parser" - } + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "bin": { - "jsesc": "bin/jsesc" + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" } }, - "node_modules/relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", - "engines": { - "node": ">= 0.10" - } + "node_modules/through2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" }, - "node_modules/remarkable": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/remarkable/-/remarkable-1.7.4.tgz", - "integrity": "sha512-e6NKUXgX95whv7IgddywbeN/ItCkWbISmc2DiqHJb0wTrqZIexqdco5b8Z3XZoo/48IdNVKM9ZCvTPJ4F5uvhg==", + "node_modules/through2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dependencies": { - "argparse": "^1.0.10", - "autolinker": "~0.28.0" - }, - "bin": { - "remarkable": "bin/remarkable.js" - }, - "engines": { - "node": ">= 0.10.0" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/renderkid": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", - "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", - "dependencies": { - "css-select": "^4.1.3", - "dom-converter": "^0.2.0", - "htmlparser2": "^6.1.0", - "lodash": "^4.17.21", - "strip-ansi": "^6.0.1" - } + "node_modules/through2/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, - "node_modules/renderkid/node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "node_modules/through2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" + "safe-buffer": "~5.1.0" } }, - "node_modules/renderkid/node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } + "node_modules/tiny-inflate": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==" }, - "node_modules/renderkid/node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" }, - "node_modules/renderkid/node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" + "os-tmpdir": "~1.0.2" }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/renderkid/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "engines": { + "node": ">=0.6.0" } }, - "node_modules/renderkid/node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], + "node_modules/tmp-promise": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", + "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" + "tmp": "^0.2.0" } }, - "node_modules/repeat-element": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", - "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", + "node_modules/tmp-promise/node_modules/tmp": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", "engines": { - "node": ">=0.10.0" + "node": ">=14.14" } }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "engines": { - "node": ">=0.10" + "node": ">=4" } }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "optional": true, - "peer": true, + "node_modules/to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==", "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" + "kind-of": "^3.0.2" }, "engines": { - "node": ">= 6" + "node": ">=0.10.0" } }, - "node_modules/request/node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "optional": true, - "peer": true, + "node_modules/to-object-path/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" + "is-buffer": "^1.1.5" }, "engines": { - "node": ">= 0.12" + "node": ">=0.10.0" } }, - "node_modules/request/node_modules/qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "optional": true, - "peer": true, + "node_modules/to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true, "engines": { - "node": ">=0.6" + "node": ">=6" } }, - "node_modules/request/node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "optional": true, - "peer": true, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "devOptional": true, "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" + "is-number": "^7.0.0" }, "engines": { - "node": ">=0.8" + "node": ">=8.0" } }, - "node_modules/request/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "optional": true, - "peer": true, - "bin": { - "uuid": "bin/uuid" - } + "node_modules/toml": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/toml/-/toml-2.3.6.tgz", + "integrity": "sha512-gVweAectJU3ebq//Ferr2JUY4WKSDe5N+z0FvjDncLGyHmIDoxgY/2Ie4qfEIDm4IS7OA6Rmdm7pdEEdMcV/xQ==" }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "node_modules/tough-cookie": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", + "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", + "dev": true, + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" - }, - "node_modules/reselect": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", - "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==" - }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/tough-cookie/node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" } }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "node_modules/tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "dev": true, "dependencies": { - "resolve-from": "^5.0.0" + "punycode": "^2.1.1" }, "engines": { "node": ">=8" } }, - "node_modules/resolve-cwd/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "engines": { - "node": ">=8" + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, - "dependencies": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - }, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" } }, - "node_modules/resolve-dir/node_modules/global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, + "node_modules/ts-invariant": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.10.3.tgz", + "integrity": "sha512-uivwYcQaxAucv1CzRp2n/QdYPo4ILf9VXgH19zEIjFx2EJufV16P0JtJVpYHy89DItG6Kwj2oIUjrcK5au+4tQ==", "dependencies": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" + "tslib": "^2.1.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/resolve-dir/node_modules/global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, "dependencies": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - }, - "engines": { - "node": ">=0.10.0" + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" } }, - "node_modules/resolve-dir/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, "dependencies": { - "isexe": "^2.0.0" + "minimist": "^1.2.0" }, "bin": { - "which": "bin/which" + "json5": "lib/cli.js" } }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, "engines": { "node": ">=4" } }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true, - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, - "node_modules/resolve-url-loader": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-4.0.0.tgz", - "integrity": "sha512-05VEMczVREcbtT7Bz+C+96eUO5HDNvdthIiMB34t7FcF8ehcu4wC0sSgPUubs3XW2Q3CNLJk/BJrCU9wVRymiA==", + "node_modules/tsx": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.1.tgz", + "integrity": "sha512-0flMz1lh74BR4wOvBjuh9olbnwqCPc35OOlfyzHba0Dc+QNUeWX/Gq2YTbnwcWPO3BMd8fkzRVrHcsR+a7z7rA==", + "dev": true, "dependencies": { - "adjust-sourcemap-loader": "^4.0.0", - "convert-source-map": "^1.7.0", - "loader-utils": "^2.0.0", - "postcss": "^7.0.35", - "source-map": "0.6.1" + "esbuild": "~0.23.0", + "get-tsconfig": "^4.7.5" }, - "engines": { - "node": ">=8.9" + "bin": { + "tsx": "dist/cli.mjs" }, - "peerDependencies": { - "rework": "1.0.1", - "rework-visit": "1.0.0" + "engines": { + "node": ">=18.0.0" }, - "peerDependenciesMeta": { - "rework": { - "optional": true - }, - "rework-visit": { - "optional": true - } + "optionalDependencies": { + "fsevents": "~2.3.3" } }, - "node_modules/resolve-url-loader/node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, + "node_modules/tsx/node_modules/@esbuild/aix-ppc64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", + "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": ">=8.9.0" + "node": ">=18" } }, - "node_modules/resolve-url-loader/node_modules/picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + "node_modules/tsx/node_modules/@esbuild/android-arm": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz", + "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/resolve-url-loader/node_modules/postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dependencies": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - }, + "node_modules/tsx/node_modules/@esbuild/android-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", + "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" + "node": ">=18" } }, - "node_modules/resolve-url-loader/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/tsx/node_modules/@esbuild/android-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz", + "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=0.10.0" + "node": ">=18" } }, - "node_modules/resolve.exports": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.1.tgz", - "integrity": "sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==", + "node_modules/tsx/node_modules/@esbuild/darwin-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", + "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/response-iterator": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/response-iterator/-/response-iterator-0.2.6.tgz", - "integrity": "sha512-pVzEEzrsg23Sh053rmDUvLSkGXluZio0qu8VT6ukrYuvtjVfCbDZH9d6PGXb8HZfzdNZt8feXv/jvUzlhRgLnw==", + "node_modules/tsx/node_modules/@esbuild/darwin-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", + "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=0.8" + "node": ">=18" } }, - "node_modules/responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", + "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", + "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "lowercase-keys": "^1.0.0" + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" } }, - "node_modules/restore-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "node_modules/tsx/node_modules/@esbuild/freebsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", + "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=18" } }, - "node_modules/restructure": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/restructure/-/restructure-3.0.0.tgz", - "integrity": "sha512-Xj8/MEIhhfj9X2rmD9iJ4Gga9EFqVlpMj3vfLnV2r/Mh5jRMryNV+6lWh9GdJtDBcBSPIqzRdfBQ3wDtNFv/uw==" + "node_modules/tsx/node_modules/@esbuild/linux-arm": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", + "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "node_modules/tsx/node_modules/@esbuild/linux-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", + "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", + "cpu": [ + "arm64" + ], + "dev": true, "optional": true, - "peer": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 4" + "node": ">=18" } }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "node_modules/tsx/node_modules/@esbuild/linux-ia32": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", + "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" + "node": ">=18" } }, - "node_modules/rfdc": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", - "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", - "dev": true - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/robust-predicates": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", - "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" - }, - "node_modules/rollup": { - "version": "2.79.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", - "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=10.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/rollup-plugin-terser": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", - "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", - "deprecated": "This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser", - "dependencies": { - "@babel/code-frame": "^7.10.4", - "jest-worker": "^26.2.1", - "serialize-javascript": "^4.0.0", - "terser": "^5.0.0" - }, - "peerDependencies": { - "rollup": "^2.0.0" - } - }, - "node_modules/rollup-plugin-terser/node_modules/jest-worker": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", - "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/rollup-plugin-terser/node_modules/serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } + "node_modules/tsx/node_modules/@esbuild/linux-loong64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", + "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", + "cpu": [ + "loong64" ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/safe-array-concat": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", - "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", - "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safe-regex-test": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-regex": "^1.1.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/sanitize-html": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.13.0.tgz", - "integrity": "sha512-Xff91Z+4Mz5QiNSLdLWwjgBDm5b1RU6xBT0+12rapjiaR7SwfRdjw8f+6Rir2MXKLrDicRFHdb51hGOAxmsUIA==", - "dependencies": { - "deepmerge": "^4.2.2", - "escape-string-regexp": "^4.0.0", - "htmlparser2": "^8.0.0", - "is-plain-object": "^5.0.0", - "parse-srcset": "^1.0.2", - "postcss": "^8.3.11" - } - }, - "node_modules/sanitize-html/node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sanitize.css": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-13.0.0.tgz", - "integrity": "sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA==" - }, - "node_modules/sass": { - "version": "1.77.4", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.4.tgz", - "integrity": "sha512-vcF3Ckow6g939GMA4PeU7b2K/9FALXk2KF9J87txdHzXbUF9XRQRwSxcAs/fGaTnJeBFd7UoV22j3lzMLdM0Pw==", - "devOptional": true, - "dependencies": { - "chokidar": ">=3.0.0 <4.0.0", - "immutable": "^4.0.0", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-graph": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-4.0.1.tgz", - "integrity": "sha512-5YCfmGBmxoIRYHnKK2AKzrAkCoQ8ozO+iumT8K4tXJXRVCPf+7s1/9KxTSW3Rbvf+7Y7b4FR3mWyLnQr3PHocA==", - "optional": true, - "peer": true, - "dependencies": { - "glob": "^7.0.0", - "lodash": "^4.17.11", - "scss-tokenizer": "^0.4.3", - "yargs": "^17.2.1" - }, - "bin": { - "sassgraph": "bin/sassgraph" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/sass-graph/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "optional": true, - "peer": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/sass-graph/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, "optional": true, - "peer": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, + "os": [ + "linux" + ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/sass-graph/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "node_modules/tsx/node_modules/@esbuild/linux-mips64el": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", + "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", + "cpu": [ + "mips64el" + ], + "dev": true, "optional": true, - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/sass-loader": { - "version": "12.6.0", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.6.0.tgz", - "integrity": "sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA==", - "dependencies": { - "klona": "^2.0.4", - "neo-async": "^2.6.2" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "fibers": ">= 3.1.0", - "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0", - "sass": "^1.3.0", - "sass-embedded": "*", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "fibers": { - "optional": true - }, - "node-sass": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - } - } - }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, - "node_modules/saxes": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", - "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", - "dependencies": { - "xmlchars": "^2.2.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/scheduler": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", - "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, - "node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/schema-utils/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/schema-utils/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/schema-utils/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/scss-tokenizer": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.4.3.tgz", - "integrity": "sha512-raKLgf1LI5QMQnG+RxHz6oK0sL3x3I4FN2UDLqgLOGO8hodECNnNh5BXn7fAyBxrA8zVzdQizQ6XjNJQ+uBwMw==", - "optional": true, - "peer": true, - "dependencies": { - "js-base64": "^2.4.9", - "source-map": "^0.7.3" - } - }, - "node_modules/scss-tokenizer/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "optional": true, - "peer": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==" - }, - "node_modules/selfsigned": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz", - "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==", - "dependencies": { - "node-forge": "^1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver-diff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", - "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", - "dev": true, - "dependencies": { - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/semver-diff/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "node_modules/send/node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/send/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", - "dependencies": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/serve-index/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/serve-index/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-index/node_modules/http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-index/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" - }, - "node_modules/serve-index/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/serve-index/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" - }, - "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "optional": true, - "peer": true - }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-function-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-getter": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.1.tgz", - "integrity": "sha512-9sVWOy+gthr+0G9DzqqLaYNA7+5OKkSmcqjL9cBpDEaZrr3ShQlyX2cZ/O/ozE41oxn/Tt0LGEM/w4Rub3A3gw==", - "dependencies": { - "to-object-path": "^0.3.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "engines": { - "node": ">=8" - } - }, - "node_modules/shell-quote": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", - "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/shiki": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.10.3.tgz", - "integrity": "sha512-eneCLncGuvPdTutJuLyUGS8QNPAVFO5Trvld2wgEq1e002mwctAhJKeMGWtWVXOIEzmlcLRqcgPSorR6AVzOmQ==", - "peer": true, - "dependencies": { - "@shikijs/core": "1.10.3", - "@types/hast": "^3.0.4" - } - }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, - "node_modules/sirv": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.3.tgz", - "integrity": "sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA==", - "dev": true, - "dependencies": { - "@polka/url": "^1.0.0-next.20", - "mrmime": "^1.0.0", - "totalist": "^3.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "optional": true, - "peer": true, - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", - "dependencies": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" - } - }, - "node_modules/socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "optional": true, - "peer": true, - "dependencies": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.13.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" - }, - "node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-loader": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-3.0.2.tgz", - "integrity": "sha512-BokxPoLjyl3iOrgkWaakaxqnelAJSS+0V+De0kKIq6lyWrXuiPgYTGp6z3iHmqljKAaLXwZa+ctD8GccRJeVvg==", - "dependencies": { - "abab": "^2.0.5", - "iconv-lite": "^0.6.3", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "deprecated": "Please use @jridgewell/sourcemap-codec instead" - }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "optional": true, - "peer": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "optional": true, - "peer": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "optional": true, - "peer": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", - "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", - "optional": true, - "peer": true - }, - "node_modules/spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "dependencies": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dependencies": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" - }, - "node_modules/sshpk": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", - "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", - "optional": true, - "peer": true, - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility" - }, - "node_modules/stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/stackframe": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", - "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==" - }, - "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/stdout-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", - "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", - "optional": true, - "peer": true, - "dependencies": { - "readable-stream": "^2.0.1" - } - }, - "node_modules/stdout-stream/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "optional": true, - "peer": true - }, - "node_modules/stdout-stream/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "optional": true, - "peer": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/stdout-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "optional": true, - "peer": true - }, - "node_modules/stdout-stream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "optional": true, - "peer": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-argv": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", - "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", - "dev": true, - "engines": { - "node": ">=0.6.19" - } - }, - "node_modules/string-hash": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", - "integrity": "sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==", - "dev": true - }, - "node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/string-natural-compare": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/string-natural-compare/-/string-natural-compare-3.0.1.tgz", - "integrity": "sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==" - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/string.prototype.matchall": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", - "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "regexp.prototype.flags": "^1.5.2", - "set-function-name": "^2.0.2", - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", - "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", - "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", - "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/stringify-object": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", - "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", - "dependencies": { - "get-own-enumerable-property-symbols": "^3.0.0", - "is-obj": "^1.0.1", - "is-regexp": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/stringify-object/node_modules/is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-color": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/strip-color/-/strip-color-0.1.0.tgz", - "integrity": "sha512-p9LsUieSjWNNAxVCXLeilaDlmuUOrDS5/dF9znM1nZc7EGX5+zEFC0bEevsNIaldjlks+2jns5Siz6F9iK6jwA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", - "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==", - "engines": { - "node": ">=10" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "devOptional": true, - "dependencies": { - "min-indent": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/style-loader": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.3.tgz", - "integrity": "sha512-53BiGLXAcll9maCYtZi2RCQZKa8NQQai5C4horqKyRmHj9H7QmcUyucrH+4KW/gBQbXM2AsB0axoEcFZPlfPcw==", - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, - "node_modules/stylehacks": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", - "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", - "dependencies": { - "browserslist": "^4.21.4", - "postcss-selector-parser": "^6.0.4" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/stylis": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", - "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" - }, - "node_modules/sucrase": { - "version": "3.33.0", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.33.0.tgz", - "integrity": "sha512-ARGC7vbufOHfpvyGcZZXFaXCMZ9A4fffOGC5ucOW7+WHDGlAe8LJdf3Jts1sWhDeiI1RSWrKy5Hodl+JWGdW2A==", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.2", - "commander": "^4.0.0", - "glob": "7.1.6", - "lines-and-columns": "^1.1.6", - "mz": "^2.7.0", - "pirates": "^4.0.1", - "ts-interface-checker": "^0.1.9" - }, - "bin": { - "sucrase": "bin/sucrase", - "sucrase-node": "bin/sucrase-node" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/sucrase/node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/sucrase/node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "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/supports-hyperlinks": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", - "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", - "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/svg-parser": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", - "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" - }, - "node_modules/svgo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", - "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", - "deprecated": "This SVGO version is no longer supported. Upgrade to v2.x.x.", - "dependencies": { - "chalk": "^2.4.1", - "coa": "^2.0.2", - "css-select": "^2.0.0", - "css-select-base-adapter": "^0.1.1", - "css-tree": "1.0.0-alpha.37", - "csso": "^4.0.2", - "js-yaml": "^3.13.1", - "mkdirp": "~0.5.1", - "object.values": "^1.1.0", - "sax": "~1.2.4", - "stable": "^0.1.8", - "unquote": "~1.1.1", - "util.promisify": "~1.0.0" - }, - "bin": { - "svgo": "bin/svgo" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/svgo/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/svgo/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/svgo/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/svgo/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/svgo/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/svgo/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/svgo/node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/svgo/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/symbol-observable": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", - "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" - }, - "node_modules/synckit": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", - "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", - "dev": true, - "dependencies": { - "@pkgr/core": "^0.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, - "node_modules/tabbable": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", - "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==" - }, - "node_modules/tailwindcss": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz", - "integrity": "sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==", - "dependencies": { - "@alloc/quick-lru": "^5.2.0", - "arg": "^5.0.2", - "chokidar": "^3.5.3", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.2.12", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "jiti": "^1.18.2", - "lilconfig": "^2.1.0", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.23", - "postcss-import": "^15.1.0", - "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.1", - "postcss-nested": "^6.0.1", - "postcss-selector-parser": "^6.0.11", - "resolve": "^1.22.2", - "sucrase": "^3.32.0" - }, - "bin": { - "tailwind": "lib/cli.js", - "tailwindcss": "lib/cli.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tailwindcss/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/tailwindcss/node_modules/postcss-import": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", - "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", - "dependencies": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/tar": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", - "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", - "optional": true, - "peer": true, - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "optional": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/tar/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "optional": true, - "peer": true - }, - "node_modules/temp-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", - "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/tempy": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz", - "integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==", - "dependencies": { - "is-stream": "^2.0.0", - "temp-dir": "^2.0.0", - "type-fest": "^0.16.0", - "unique-string": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/tempy/node_modules/type-fest": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", - "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/terminal-link": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", - "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", - "dependencies": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/terser": { - "version": "5.19.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.19.0.tgz", - "integrity": "sha512-JpcpGOQLOXm2jsomozdMDpd5f8ZHh1rR48OFgWUH3QsyZcfPgv2qDCYbcDEAYNd4OZRj2bWYKpwdll/udZCk/Q==", - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.9", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", - "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.8" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" - }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/throat": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz", - "integrity": "sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==" - }, - "node_modules/throttle-debounce": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-2.3.0.tgz", - "integrity": "sha512-H7oLPV0P7+jgvrk+6mwwwBDmxTaxnu9HMXmloNLXwnNO0ZxZ31Orah2n8lU1eMPvsaowP2CX+USCgyovXfdOFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" - }, - "node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/through2/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "node_modules/through2/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/through2/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/through2/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" - }, - "node_modules/tiny-inflate": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", - "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==" - }, - "node_modules/tiny-invariant": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", - "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" - }, - "node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/tmp-promise": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", - "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", - "dependencies": { - "tmp": "^0.2.0" - } - }, - "node_modules/tmp-promise/node_modules/tmp": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", - "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", - "engines": { - "node": ">=14.14" - } - }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==" - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "engines": { - "node": ">=4" - } - }, - "node_modules/to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==", - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-object-path/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "os": [ + "linux" + ], "engines": { - "node": ">=0.6" + "node": ">=18" } }, - "node_modules/toml": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/toml/-/toml-2.3.6.tgz", - "integrity": "sha512-gVweAectJU3ebq//Ferr2JUY4WKSDe5N+z0FvjDncLGyHmIDoxgY/2Ie4qfEIDm4IS7OA6Rmdm7pdEEdMcV/xQ==" - }, - "node_modules/totalist": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", - "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "node_modules/tsx/node_modules/@esbuild/linux-ppc64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", + "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", + "cpu": [ + "ppc64" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6" + "node": ">=18" } }, - "node_modules/tough-cookie": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", - "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", - "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - }, + "node_modules/tsx/node_modules/@esbuild/linux-riscv64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", + "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6" + "node": ">=18" } }, - "node_modules/tough-cookie/node_modules/universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "node_modules/tsx/node_modules/@esbuild/linux-s390x": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", + "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 4.0.0" + "node": ">=18" } }, - "node_modules/tr46": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", - "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", - "dependencies": { - "punycode": "^2.1.1" - }, + "node_modules/tsx/node_modules/@esbuild/linux-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", + "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/trim-newlines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "node_modules/tsx/node_modules/@esbuild/netbsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", + "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", + "cpu": [ + "x64" + ], + "dev": true, "optional": true, - "peer": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/true-case-path": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", - "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", + "node_modules/tsx/node_modules/@esbuild/openbsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", + "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", + "cpu": [ + "x64" + ], + "dev": true, "optional": true, - "peer": true, - "dependencies": { - "glob": "^7.1.2" - } - }, - "node_modules/tryer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", - "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==" - }, - "node_modules/ts-interface-checker": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" - }, - "node_modules/ts-invariant": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.10.3.tgz", - "integrity": "sha512-uivwYcQaxAucv1CzRp2n/QdYPo4ILf9VXgH19zEIjFx2EJufV16P0JtJVpYHy89DItG6Kwj2oIUjrcK5au+4tQ==", - "dependencies": { - "tslib": "^2.1.0" - }, + "os": [ + "openbsd" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" + "node_modules/tsx/node_modules/@esbuild/sunos-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", + "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" } }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" + "node_modules/tsx/node_modules/@esbuild/win32-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", + "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" } }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "node_modules/tsx/node_modules/@esbuild/win32-ia32": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", + "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=4" + "node": ">=18" } }, - "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dependencies": { - "tslib": "^1.8.1" - }, + "node_modules/tsx/node_modules/@esbuild/win32-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", + "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + "node": ">=18" } }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/tsx": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.16.2.tgz", - "integrity": "sha512-C1uWweJDgdtX2x600HjaFaucXTilT7tgUZHbOE4+ypskZ1OP8CRCSDkCxG6Vya9EwaFIVagWwpaVAn5wzypaqQ==", + "node_modules/tsx/node_modules/esbuild": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", + "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", "dev": true, - "dependencies": { - "esbuild": "~0.21.5", - "get-tsconfig": "^4.7.5" - }, + "hasInstallScript": true, "bin": { - "tsx": "dist/cli.mjs" + "esbuild": "bin/esbuild" }, "engines": { - "node": ">=18.0.0" + "node": ">=18" }, "optionalDependencies": { - "fsevents": "~2.3.3" - } - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "optional": true, - "peer": true, - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" + "@esbuild/aix-ppc64": "0.23.1", + "@esbuild/android-arm": "0.23.1", + "@esbuild/android-arm64": "0.23.1", + "@esbuild/android-x64": "0.23.1", + "@esbuild/darwin-arm64": "0.23.1", + "@esbuild/darwin-x64": "0.23.1", + "@esbuild/freebsd-arm64": "0.23.1", + "@esbuild/freebsd-x64": "0.23.1", + "@esbuild/linux-arm": "0.23.1", + "@esbuild/linux-arm64": "0.23.1", + "@esbuild/linux-ia32": "0.23.1", + "@esbuild/linux-loong64": "0.23.1", + "@esbuild/linux-mips64el": "0.23.1", + "@esbuild/linux-ppc64": "0.23.1", + "@esbuild/linux-riscv64": "0.23.1", + "@esbuild/linux-s390x": "0.23.1", + "@esbuild/linux-x64": "0.23.1", + "@esbuild/netbsd-x64": "0.23.1", + "@esbuild/openbsd-arm64": "0.23.1", + "@esbuild/openbsd-x64": "0.23.1", + "@esbuild/sunos-x64": "0.23.1", + "@esbuild/win32-arm64": "0.23.1", + "@esbuild/win32-ia32": "0.23.1", + "@esbuild/win32-x64": "0.23.1" } }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", - "optional": true, - "peer": true - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "peer": true, "dependencies": { "prelude-ls": "^1.2.1" }, @@ -23790,6 +17716,7 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, "engines": { "node": ">=4" } @@ -23805,22 +17732,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/typed-array-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -23834,6 +17750,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", @@ -23852,6 +17769,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", @@ -23871,6 +17789,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", @@ -23895,21 +17814,21 @@ "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, "dependencies": { "is-typedarray": "^1.0.0" } }, "node_modules/typedoc": { - "version": "0.26.3", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.3.tgz", - "integrity": "sha512-6d2Sw9disvvpdk4K7VNjKr5/3hzijtfQVHRthhDqJgnhMHy1wQz4yPMJVKXElvnZhFr0nkzo+GzjXDTRV5yLpg==", - "peer": true, + "version": "0.26.7", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.7.tgz", + "integrity": "sha512-gUeI/Wk99vjXXMi8kanwzyhmeFEGv1LTdTQsiyIsmSYsBebvFxhbcyAx7Zjo4cMbpLGxM4Uz3jVIjksu/I2v6Q==", "dependencies": { "lunr": "^2.3.9", "markdown-it": "^14.1.0", "minimatch": "^9.0.5", - "shiki": "^1.9.1", - "yaml": "^2.4.5" + "shiki": "^1.16.2", + "yaml": "^2.5.1" }, "bin": { "typedoc": "bin/typedoc" @@ -23918,7 +17837,7 @@ "node": ">= 18" }, "peerDependencies": { - "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x" + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x" } }, "node_modules/typedoc-plugin-markdown": { @@ -23936,7 +17855,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "peer": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -23945,7 +17863,6 @@ "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "peer": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -23957,10 +17874,9 @@ } }, "node_modules/typedoc/node_modules/yaml": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", - "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", - "peer": true, + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", "bin": { "yaml": "bin.mjs" }, @@ -23969,27 +17885,27 @@ } }, "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", + "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, "node_modules/uc.micro": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", - "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", - "peer": true + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==" }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "has-bigints": "^1.0.2", @@ -24015,14 +17931,16 @@ } }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "devOptional": true }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true, "engines": { "node": ">=4" } @@ -24031,6 +17949,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, "dependencies": { "unicode-canonical-property-names-ecmascript": "^2.0.0", "unicode-property-aliases-ecmascript": "^2.0.0" @@ -24043,6 +17962,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "dev": true, "engines": { "node": ">=4" } @@ -24060,6 +17980,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true, "engines": { "node": ">=4" } @@ -24082,6 +18003,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, "dependencies": { "crypto-random-string": "^2.0.0" }, @@ -24089,40 +18011,82 @@ "node": ">=8" } }, - "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "engines": { - "node": ">= 10.0.0" + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, "engines": { "node": ">= 0.8" } }, - "node_modules/unquote": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", - "integrity": "sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg==" - }, - "node_modules/upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "engines": { - "node": ">=4", - "yarn": "*" - } - }, "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", "funding": [ { "type": "opencollective", @@ -24138,8 +18102,8 @@ } ], "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.1.2", + "picocolors": "^1.0.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -24196,6 +18160,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -24204,6 +18169,7 @@ "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dev": true, "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" @@ -24229,107 +18195,458 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/util.promisify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", - "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "node_modules/use-sync-external-store": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", + "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/v8-to-istanbul": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", + "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0", + "source-map": "^0.7.3" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vite": { + "version": "5.4.7", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.7.tgz", + "integrity": "sha512-5l2zxqMEPVENgvzTuBpHer2awaetimj2BGkhBPdnwKbPNOlHsODU+oiazEZzLK7KhAnOrO+XGYJYn4ZlUhDtDQ==", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-plugin-environment": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/vite-plugin-environment/-/vite-plugin-environment-1.1.3.tgz", + "integrity": "sha512-9LBhB0lx+2lXVBEWxFZC+WO7PKEyE/ykJ7EPWCq95NEcCpblxamTbs5Dm3DLBGzwODpJMEnzQywJU8fw6XGGGA==", + "peerDependencies": { + "vite": ">= 2.7" + } + }, + "node_modules/vite-plugin-svgr": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/vite-plugin-svgr/-/vite-plugin-svgr-4.2.0.tgz", + "integrity": "sha512-SC7+FfVtNQk7So0XMjrrtLAbEC8qjFPifyD7+fs/E6aaNdVde6umlVVh0QuwDLdOMu7vp5RiGFsB70nj5yo0XA==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^5.0.5", + "@svgr/core": "^8.1.0", + "@svgr/plugin-jsx": "^8.1.0" + }, + "peerDependencies": { + "vite": "^2.6.0 || 3 || 4 || 5" + } + }, + "node_modules/vite-plugin-svgr/node_modules/@rollup/pluginutils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", + "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/vite-plugin-svgr/node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/vite-plugin-svgr/node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", + "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/vite-plugin-svgr/node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", + "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/vite-plugin-svgr/node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", + "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/vite-plugin-svgr/node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", + "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/vite-plugin-svgr/node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", + "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/vite-plugin-svgr/node_modules/@svgr/babel-preset": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", + "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", + "dev": true, + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", + "@svgr/babel-plugin-transform-svg-component": "8.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/vite-plugin-svgr/node_modules/@svgr/core": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", + "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^8.1.3", + "snake-case": "^3.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/vite-plugin-svgr/node_modules/@svgr/hast-util-to-babel-ast": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", + "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.21.3", + "entities": "^4.4.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/vite-plugin-svgr/node_modules/@svgr/plugin-jsx": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", + "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", + "dev": true, "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.2", - "has-symbols": "^1.0.1", - "object.getownpropertydescriptors": "^2.1.0" + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "@svgr/hast-util-to-babel-ast": "8.0.0", + "svg-parser": "^2.0.4" + }, + "engines": { + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" } }, - "node_modules/utila": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==" + "node_modules/vite-plugin-svgr/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "node_modules/vite-plugin-svgr/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/v8-to-istanbul": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", - "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", + "node_modules/vite-plugin-svgr/node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0", - "source-map": "^0.7.3" + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" }, "engines": { - "node": ">=10.12.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/v8-to-istanbul/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "engines": { - "node": ">= 8" - } + "node_modules/vite-plugin-svgr/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "optional": true, - "peer": true, + "node_modules/vite-plugin-svgr/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "engines": { - "node": ">= 0.8" + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "engines": [ - "node >=0.6.0" - ], - "optional": true, - "peer": true, + "node_modules/vite-tsconfig-paths": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-5.0.1.tgz", + "integrity": "sha512-yqwv+LstU7NwPeNqajZzLEBVpUFU6Dugtb2P84FXuvaoYA+/70l9MHE+GYfYAycVyPSDYZ7mjOFuYBRqlEpTig==", "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" + "debug": "^4.1.1", + "globrex": "^0.1.2", + "tsconfck": "^3.0.3" + }, + "peerDependencies": { + "vite": "*" + }, + "peerDependenciesMeta": { + "vite": { + "optional": true + } } }, - "node_modules/verror/node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", - "optional": true, - "peer": true + "node_modules/vite-tsconfig-paths/node_modules/tsconfck": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.3.tgz", + "integrity": "sha512-ulNZP1SVpRDesxeMLON/LtWM8HIgAJEIVpVVhBM6gsmvQ8+Rh+ZG7FWGvHh7Ah3pRABwVJWklWCr/BTZSv0xnQ==", + "bin": { + "tsconfck": "bin/tsconfck.js" + }, + "engines": { + "node": "^18 || >=20" + }, + "peerDependencies": { + "typescript": "^5.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } }, "node_modules/void-elements": { "version": "3.1.0", @@ -24344,6 +18661,7 @@ "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", "deprecated": "Use your platform's native performance.now() and performance.timeOrigin.", + "dev": true, "dependencies": { "browser-process-hrtime": "^1.0.0" } @@ -24352,6 +18670,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "dev": true, "dependencies": { "xml-name-validator": "^3.0.0" }, @@ -24363,6 +18682,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, "dependencies": { "makeerror": "1.0.12" } @@ -24375,26 +18695,6 @@ "loose-envify": "^1.0.0" } }, - "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dependencies": { - "minimalistic-assert": "^1.0.0" - } - }, "node_modules/wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", @@ -24404,270 +18704,24 @@ } }, "node_modules/web-vitals": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.2.tgz", - "integrity": "sha512-nYfoOqb4EmElljyXU2qdeE76KsvoHdftQKY4DzA9Aw8DervCg2bG634pHLrJ/d6+B4mE3nWTSJv8Mo7B2mbZkw==" + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.3.tgz", + "integrity": "sha512-/CFAm1mNxSmOj6i0Co+iGFJ58OS4NRGVP+AWS/l509uIK5a1bSoIVaHz/ZumpHTfHSZBpgrJ+wjfpAOrTHok5Q==" }, "node_modules/webidl-conversions": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "dev": true, "engines": { "node": ">=10.4" } }, - "node_modules/webpack": { - "version": "5.88.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.1.tgz", - "integrity": "sha512-FROX3TxQnC/ox4N+3xQoWZzvGXSuscxR32rbzjpXgEzWudJFEJBpdlkkob2ylrv5yzzufD1zph1OoFsLtm6stQ==", - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.15.0", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-dev-middleware": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", - "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", - "dependencies": { - "colorette": "^2.0.10", - "memfs": "^3.4.3", - "mime-types": "^2.1.31", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/webpack-dev-middleware/node_modules/schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/webpack-dev-server": { - "version": "4.15.1", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz", - "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==", - "dependencies": { - "@types/bonjour": "^3.5.9", - "@types/connect-history-api-fallback": "^1.3.5", - "@types/express": "^4.17.13", - "@types/serve-index": "^1.9.1", - "@types/serve-static": "^1.13.10", - "@types/sockjs": "^0.3.33", - "@types/ws": "^8.5.5", - "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.0.11", - "chokidar": "^3.5.3", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^2.0.0", - "default-gateway": "^6.0.3", - "express": "^4.17.3", - "graceful-fs": "^4.2.6", - "html-entities": "^2.3.2", - "http-proxy-middleware": "^2.0.3", - "ipaddr.js": "^2.0.1", - "launch-editor": "^2.6.0", - "open": "^8.0.9", - "p-retry": "^4.5.0", - "rimraf": "^3.0.2", - "schema-utils": "^4.0.0", - "selfsigned": "^2.1.1", - "serve-index": "^1.9.1", - "sockjs": "^0.3.24", - "spdy": "^4.0.2", - "webpack-dev-middleware": "^5.3.1", - "ws": "^8.13.0" - }, - "bin": { - "webpack-dev-server": "bin/webpack-dev-server.js" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.37.0 || ^5.0.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - }, - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-dev-server/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/webpack-dev-server/node_modules/schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/webpack-manifest-plugin": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/webpack-manifest-plugin/-/webpack-manifest-plugin-4.1.1.tgz", - "integrity": "sha512-YXUAwxtfKIJIKkhg03MKuiFAD72PlrqCiwdwO4VEXdRO5V0ORCNwaOwAZawPZalCbmH9kBDmXnNeQOw+BIEiow==", - "dependencies": { - "tapable": "^2.0.0", - "webpack-sources": "^2.2.0" - }, - "engines": { - "node": ">=12.22.0" - }, - "peerDependencies": { - "webpack": "^4.44.2 || ^5.47.0" - } - }, - "node_modules/webpack-manifest-plugin/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack-manifest-plugin/node_modules/webpack-sources": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", - "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", - "dependencies": { - "source-list-map": "^2.0.1", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", - "dependencies": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/whatwg-encoding": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, "dependencies": { "iconv-lite": "0.4.24" } @@ -24676,6 +18730,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -24684,19 +18739,22 @@ } }, "node_modules/whatwg-fetch": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", - "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==" + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==", + "dev": true }, "node_modules/whatwg-mimetype": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==" + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true }, "node_modules/whatwg-url": { "version": "8.7.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "dev": true, "dependencies": { "lodash": "^4.7.0", "tr46": "^2.1.0", @@ -24710,6 +18768,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -24724,6 +18783,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, "dependencies": { "is-bigint": "^1.0.1", "is-boolean-object": "^1.1.0", @@ -24736,12 +18796,13 @@ } }, "node_modules/which-builtin-type": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", - "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.4.tgz", + "integrity": "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==", + "dev": true, "dependencies": { - "function.prototype.name": "^1.1.5", - "has-tostringtag": "^1.0.0", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", "is-date-object": "^1.0.5", "is-finalizationregistry": "^1.0.2", @@ -24750,8 +18811,8 @@ "is-weakref": "^1.0.2", "isarray": "^2.0.5", "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.15" }, "engines": { "node": ">= 0.4" @@ -24764,6 +18825,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", @@ -24781,6 +18843,7 @@ "version": "1.1.15", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", @@ -24795,16 +18858,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "optional": true, - "peer": true, - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, "node_modules/widest-line": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", @@ -24817,269 +18870,11 @@ "node": ">=8" } }, - "node_modules/workbox-background-sync": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-6.6.0.tgz", - "integrity": "sha512-jkf4ZdgOJxC9u2vztxLuPT/UjlH7m/nWRQ/MgGL0v8BJHoZdVGJd18Kck+a0e55wGXdqyHO+4IQTk0685g4MUw==", - "dependencies": { - "idb": "^7.0.1", - "workbox-core": "6.6.0" - } - }, - "node_modules/workbox-broadcast-update": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-6.6.0.tgz", - "integrity": "sha512-nm+v6QmrIFaB/yokJmQ/93qIJ7n72NICxIwQwe5xsZiV2aI93MGGyEyzOzDPVz5THEr5rC3FJSsO3346cId64Q==", - "dependencies": { - "workbox-core": "6.6.0" - } - }, - "node_modules/workbox-build": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-6.6.0.tgz", - "integrity": "sha512-Tjf+gBwOTuGyZwMz2Nk/B13Fuyeo0Q84W++bebbVsfr9iLkDSo6j6PST8tET9HYA58mlRXwlMGpyWO8ETJiXdQ==", - "dependencies": { - "@apideck/better-ajv-errors": "^0.3.1", - "@babel/core": "^7.11.1", - "@babel/preset-env": "^7.11.0", - "@babel/runtime": "^7.11.2", - "@rollup/plugin-babel": "^5.2.0", - "@rollup/plugin-node-resolve": "^11.2.1", - "@rollup/plugin-replace": "^2.4.1", - "@surma/rollup-plugin-off-main-thread": "^2.2.3", - "ajv": "^8.6.0", - "common-tags": "^1.8.0", - "fast-json-stable-stringify": "^2.1.0", - "fs-extra": "^9.0.1", - "glob": "^7.1.6", - "lodash": "^4.17.20", - "pretty-bytes": "^5.3.0", - "rollup": "^2.43.1", - "rollup-plugin-terser": "^7.0.0", - "source-map": "^0.8.0-beta.0", - "stringify-object": "^3.3.0", - "strip-comments": "^2.0.1", - "tempy": "^0.6.0", - "upath": "^1.2.0", - "workbox-background-sync": "6.6.0", - "workbox-broadcast-update": "6.6.0", - "workbox-cacheable-response": "6.6.0", - "workbox-core": "6.6.0", - "workbox-expiration": "6.6.0", - "workbox-google-analytics": "6.6.0", - "workbox-navigation-preload": "6.6.0", - "workbox-precaching": "6.6.0", - "workbox-range-requests": "6.6.0", - "workbox-recipes": "6.6.0", - "workbox-routing": "6.6.0", - "workbox-strategies": "6.6.0", - "workbox-streams": "6.6.0", - "workbox-sw": "6.6.0", - "workbox-window": "6.6.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/workbox-build/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/workbox-build/node_modules/source-map": { - "version": "0.8.0-beta.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", - "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", - "dependencies": { - "whatwg-url": "^7.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/workbox-build/node_modules/tr46": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", - "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/workbox-build/node_modules/webidl-conversions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" - }, - "node_modules/workbox-build/node_modules/whatwg-url": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", - "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", - "dependencies": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" - } - }, - "node_modules/workbox-cacheable-response": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-6.6.0.tgz", - "integrity": "sha512-JfhJUSQDwsF1Xv3EV1vWzSsCOZn4mQ38bWEBR3LdvOxSPgB65gAM6cS2CX8rkkKHRgiLrN7Wxoyu+TuH67kHrw==", - "deprecated": "workbox-background-sync@6.6.0", - "dependencies": { - "workbox-core": "6.6.0" - } - }, - "node_modules/workbox-core": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.6.0.tgz", - "integrity": "sha512-GDtFRF7Yg3DD859PMbPAYPeJyg5gJYXuBQAC+wyrWuuXgpfoOrIQIvFRZnQ7+czTIQjIr1DhLEGFzZanAT/3bQ==" - }, - "node_modules/workbox-expiration": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.6.0.tgz", - "integrity": "sha512-baplYXcDHbe8vAo7GYvyAmlS4f6998Jff513L4XvlzAOxcl8F620O91guoJ5EOf5qeXG4cGdNZHkkVAPouFCpw==", - "dependencies": { - "idb": "^7.0.1", - "workbox-core": "6.6.0" - } - }, - "node_modules/workbox-google-analytics": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-6.6.0.tgz", - "integrity": "sha512-p4DJa6OldXWd6M9zRl0H6vB9lkrmqYFkRQ2xEiNdBFp9U0LhsGO7hsBscVEyH9H2/3eZZt8c97NB2FD9U2NJ+Q==", - "dependencies": { - "workbox-background-sync": "6.6.0", - "workbox-core": "6.6.0", - "workbox-routing": "6.6.0", - "workbox-strategies": "6.6.0" - } - }, - "node_modules/workbox-navigation-preload": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-6.6.0.tgz", - "integrity": "sha512-utNEWG+uOfXdaZmvhshrh7KzhDu/1iMHyQOV6Aqup8Mm78D286ugu5k9MFD9SzBT5TcwgwSORVvInaXWbvKz9Q==", - "dependencies": { - "workbox-core": "6.6.0" - } - }, - "node_modules/workbox-precaching": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.6.0.tgz", - "integrity": "sha512-eYu/7MqtRZN1IDttl/UQcSZFkHP7dnvr/X3Vn6Iw6OsPMruQHiVjjomDFCNtd8k2RdjLs0xiz9nq+t3YVBcWPw==", - "dependencies": { - "workbox-core": "6.6.0", - "workbox-routing": "6.6.0", - "workbox-strategies": "6.6.0" - } - }, - "node_modules/workbox-range-requests": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-6.6.0.tgz", - "integrity": "sha512-V3aICz5fLGq5DpSYEU8LxeXvsT//mRWzKrfBOIxzIdQnV/Wj7R+LyJVTczi4CQ4NwKhAaBVaSujI1cEjXW+hTw==", - "dependencies": { - "workbox-core": "6.6.0" - } - }, - "node_modules/workbox-recipes": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-6.6.0.tgz", - "integrity": "sha512-TFi3kTgYw73t5tg73yPVqQC8QQjxJSeqjXRO4ouE/CeypmP2O/xqmB/ZFBBQazLTPxILUQ0b8aeh0IuxVn9a6A==", - "dependencies": { - "workbox-cacheable-response": "6.6.0", - "workbox-core": "6.6.0", - "workbox-expiration": "6.6.0", - "workbox-precaching": "6.6.0", - "workbox-routing": "6.6.0", - "workbox-strategies": "6.6.0" - } - }, - "node_modules/workbox-routing": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.6.0.tgz", - "integrity": "sha512-x8gdN7VDBiLC03izAZRfU+WKUXJnbqt6PG9Uh0XuPRzJPpZGLKce/FkOX95dWHRpOHWLEq8RXzjW0O+POSkKvw==", - "dependencies": { - "workbox-core": "6.6.0" - } - }, - "node_modules/workbox-strategies": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.6.0.tgz", - "integrity": "sha512-eC07XGuINAKUWDnZeIPdRdVja4JQtTuc35TZ8SwMb1ztjp7Ddq2CJ4yqLvWzFWGlYI7CG/YGqaETntTxBGdKgQ==", - "dependencies": { - "workbox-core": "6.6.0" - } - }, - "node_modules/workbox-streams": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-6.6.0.tgz", - "integrity": "sha512-rfMJLVvwuED09CnH1RnIep7L9+mj4ufkTyDPVaXPKlhi9+0czCu+SJggWCIFbPpJaAZmp2iyVGLqS3RUmY3fxg==", - "dependencies": { - "workbox-core": "6.6.0", - "workbox-routing": "6.6.0" - } - }, - "node_modules/workbox-sw": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-6.6.0.tgz", - "integrity": "sha512-R2IkwDokbtHUE4Kus8pKO5+VkPHD2oqTgl+XJwh4zbF1HyjAbgNmK/FneZHVU7p03XUt9ICfuGDYISWG9qV/CQ==" - }, - "node_modules/workbox-webpack-plugin": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-webpack-plugin/-/workbox-webpack-plugin-6.6.0.tgz", - "integrity": "sha512-xNZIZHalboZU66Wa7x1YkjIqEy1gTR+zPM+kjrYJzqN7iurYZBctBLISyScjhkJKYuRrZUP0iqViZTh8rS0+3A==", - "dependencies": { - "fast-json-stable-stringify": "^2.1.0", - "pretty-bytes": "^5.4.1", - "upath": "^1.2.0", - "webpack-sources": "^1.4.3", - "workbox-build": "6.6.0" - }, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "webpack": "^4.4.0 || ^5.9.0" - } - }, - "node_modules/workbox-webpack-plugin/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/workbox-webpack-plugin/node_modules/webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dependencies": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - } - }, - "node_modules/workbox-window": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-6.6.0.tgz", - "integrity": "sha512-L4N9+vka17d16geaJXXRjENLFldvkWy7JyGxElRD0JvBxvFEd8LOhr+uXCcar/NzAmIBRv9EZ+M+Qr4mOoBITw==", - "dependencies": { - "@types/trusted-types": "^2.0.2", - "workbox-core": "6.6.0" - } - }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -25095,12 +18890,14 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true }, "node_modules/write-file-atomic": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, "dependencies": { "imurmurhash": "^0.1.4", "is-typedarray": "^1.0.0", @@ -25109,9 +18906,10 @@ } }, "node_modules/ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, "engines": { "node": ">=10.0.0" }, @@ -25140,12 +18938,14 @@ "node_modules/xml-name-validator": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==" + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true }, "node_modules/xmlchars": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true }, "node_modules/xtend": { "version": "4.0.2", @@ -25159,6 +18959,7 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, "engines": { "node": ">=10" } @@ -25180,6 +18981,7 @@ "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -25197,6 +18999,7 @@ "version": "20.2.9", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, "engines": { "node": ">=10" } @@ -25205,6 +19008,8 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "peer": true, "engines": { "node": ">=10" }, @@ -25229,28 +19034,35 @@ "version": "3.22.4", "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } } }, "dependencies": { "@aashutoshrathi/word-wrap": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==" + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "peer": true }, "@adobe/css-tools": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.3.tgz", - "integrity": "sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.0.tgz", + "integrity": "sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==", "dev": true }, - "@alloc/quick-lru": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", - "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==" - }, "@ampproject/remapping": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", @@ -25260,29 +19072,20 @@ "@jridgewell/trace-mapping": "^0.3.9" } }, - "@apideck/better-ajv-errors": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.6.tgz", - "integrity": "sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==", - "requires": { - "json-schema": "^0.4.0", - "jsonpointer": "^5.0.0", - "leven": "^3.1.0" - } - }, "@apollo/client": { - "version": "3.7.17", - "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.7.17.tgz", - "integrity": "sha512-0EErSHEtKPNl5wgWikHJbKFAzJ/k11O0WO2QyqZSHpdxdAnw7UWHY4YiLbHCFG7lhrD+NTQ3Z/H9Jn4rcikoJA==", + "version": "3.11.4", + "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.11.4.tgz", + "integrity": "sha512-bmgYKkULpym8wt8aXlAZ1heaYo0skLJ5ru0qJ+JCRoo03Pe+yIDbBCnqlDw6Mjj76hFkDw3HwFMgZC2Hxp30Mg==", "requires": { "@graphql-typed-document-node/core": "^3.1.1", - "@wry/context": "^0.7.0", - "@wry/equality": "^0.5.0", - "@wry/trie": "^0.4.0", + "@wry/caches": "^1.0.0", + "@wry/equality": "^0.5.6", + "@wry/trie": "^0.5.0", "graphql-tag": "^2.12.6", "hoist-non-react-statics": "^3.3.2", - "optimism": "^0.16.2", + "optimism": "^0.18.0", "prop-types": "^15.7.2", + "rehackt": "^0.1.0", "response-iterator": "^0.2.6", "symbol-observable": "^4.0.0", "ts-invariant": "^0.10.3", @@ -25315,113 +19118,45 @@ } }, "@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", "requires": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" } }, "@babel/compat-data": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", - "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==" + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz", + "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==" }, "@babel/core": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.9.tgz", - "integrity": "sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", + "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", "requires": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.9", - "@babel/helper-compilation-targets": "^7.22.9", - "@babel/helper-module-transforms": "^7.22.9", - "@babel/helpers": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.8", - "@babel/types": "^7.22.5", - "convert-source-map": "^1.7.0", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.0", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-module-transforms": "^7.25.2", + "@babel/helpers": "^7.25.0", + "@babel/parser": "^7.25.0", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.2", + "@babel/types": "^7.25.2", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.1" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" - } - } - }, - "@babel/eslint-parser": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.22.9.tgz", - "integrity": "sha512-xdMkt39/nviO/4vpVdrEYPwXCsYIXSSAr6mC7WQsNIlGnuxKyKE7GZjalcnbSWiC4OXGNNN3UQPeHfjSC6sTDA==", - "requires": { - "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", - "eslint-visitor-keys": "^2.1.0", + "json5": "^2.2.3", "semver": "^6.3.1" }, "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==" + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, "semver": { "version": "6.3.1", @@ -25431,40 +19166,43 @@ } }, "@babel/generator": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", - "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz", + "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==", "requires": { - "@babel/types": "^7.23.6", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", + "@babel/types": "^7.25.6", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" } }, "@babel/helper-annotate-as-pure": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", - "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", + "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "dev": true, "requires": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.7" } }, "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", - "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", + "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", + "dev": true, "requires": { - "@babel/types": "^7.22.15" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" } }, "@babel/helper-compilation-targets": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", - "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", + "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", "requires": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-validator-option": "^7.23.5", - "browserslist": "^4.22.2", + "@babel/compat-data": "^7.25.2", + "@babel/helper-validator-option": "^7.24.8", + "browserslist": "^4.23.1", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -25477,34 +19215,35 @@ } }, "@babel/helper-create-class-features-plugin": { - "version": "7.23.10", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.10.tgz", - "integrity": "sha512-2XpP2XhkXzgxecPNEEK8Vz8Asj9aRxt08oKOqtiZoqV2UGZ5T+EkyP9sXQ9nwMxBIG34a7jmasVqoMop7VdPUw==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-member-expression-to-functions": "^7.23.0", - "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.4.tgz", + "integrity": "sha512-ro/bFs3/84MDgDmMwbcHgDa8/E6J3QKNTk4xJJnVeFtGE+tL0K26E3pNxhYz2b67fJpt7Aphw5XcploKXuCvCQ==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/helper-replace-supers": "^7.25.0", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/traverse": "^7.25.4", "semver": "^6.3.1" }, "dependencies": { "semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true } } }, "@babel/helper-create-regexp-features-plugin": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", - "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.2.tgz", + "integrity": "sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g==", + "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-annotate-as-pure": "^7.24.7", "regexpu-core": "^5.3.1", "semver": "^6.3.1" }, @@ -25512,14 +19251,16 @@ "semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true } } }, "@babel/helper-define-polyfill-provider": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.1.tgz", - "integrity": "sha512-kX4oXixDxG197yhX+J3Wp+NpL2wuCFjWQAr6yX2jtCnflK9ulMI51ULFGIrWiX1jGfvAxdHp+XQCcP2bZGPs9A==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "dev": true, "requires": { "@babel/helper-compilation-targets": "^7.22.6", "@babel/helper-plugin-utils": "^7.22.5", @@ -25528,156 +19269,135 @@ "resolve": "^1.14.2" } }, - "@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==" - }, - "@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "requires": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "requires": { - "@babel/types": "^7.22.5" - } - }, "@babel/helper-member-expression-to-functions": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", - "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", + "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", + "dev": true, "requires": { - "@babel/types": "^7.23.0" + "@babel/traverse": "^7.24.8", + "@babel/types": "^7.24.8" } }, "@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", "requires": { - "@babel/types": "^7.22.15" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" } }, "@babel/helper-module-transforms": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", - "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", + "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", "requires": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.2" } }, "@babel/helper-optimise-call-expression": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", - "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", + "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", + "dev": true, "requires": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.7" } }, "@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==" + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", + "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==" }, "@babel/helper-remap-async-to-generator": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", - "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz", + "integrity": "sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw==", + "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-wrap-function": "^7.22.20" + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-wrap-function": "^7.25.0", + "@babel/traverse": "^7.25.0" } }, "@babel/helper-replace-supers": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", - "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz", + "integrity": "sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==", + "dev": true, "requires": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-member-expression-to-functions": "^7.22.15", - "@babel/helper-optimise-call-expression": "^7.22.5" + "@babel/helper-member-expression-to-functions": "^7.24.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/traverse": "^7.25.0" } }, "@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", "requires": { - "@babel/types": "^7.22.5" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" } }, "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", - "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", + "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", + "dev": true, "requires": { - "@babel/types": "^7.22.5" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" } }, "@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==" + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==" }, "@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==" + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==" }, "@babel/helper-validator-option": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", - "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==" + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", + "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==" }, "@babel/helper-wrap-function": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", - "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.0.tgz", + "integrity": "sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ==", + "dev": true, "requires": { - "@babel/helper-function-name": "^7.22.5", - "@babel/template": "^7.22.15", - "@babel/types": "^7.22.19" + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.0", + "@babel/types": "^7.25.0" } }, "@babel/helpers": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz", - "integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.6.tgz", + "integrity": "sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==", "requires": { - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.6", - "@babel/types": "^7.22.5" + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.6" } }, "@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", "requires": { - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-validator-identifier": "^7.24.7", "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "dependencies": { "ansi-styles": { @@ -25718,107 +19438,74 @@ }, "has-flag": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@babel/parser": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.0.tgz", - "integrity": "sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==" - }, - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz", - "integrity": "sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz", - "integrity": "sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-transform-optional-chaining": "^7.23.3" - } - }, - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz", - "integrity": "sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw==", - "requires": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.22.5" + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } } }, - "@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", - "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "@babel/parser": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", + "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", "requires": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/types": "^7.25.6" } }, - "@babel/plugin-proposal-decorators": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.22.7.tgz", - "integrity": "sha512-omXqPF7Onq4Bb7wHxXjM3jSMSJvUUbvDvmmds7KI5n9Cq6Ln5I05I1W2nRlRof1rGdiUxJrxwe285WF96XlBXQ==", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.3.tgz", + "integrity": "sha512-wUrcsxZg6rqBXG05HG1FPYgsP6EvwF4WpBbxIpWIIYnH8wG0gzx3yZY3dtEHas4sTAOGkbTsc9EGPxwff8lRoA==", + "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/plugin-syntax-decorators": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.3" } }, - "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", - "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.0.tgz", + "integrity": "sha512-Bm4bH2qsX880b/3ziJ8KD711LT7z4u8CFudmjqle65AZj/HNUFhEf90dqYv6O86buWvSBmeQDjv0Tn2aF/bIBA==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + "@babel/helper-plugin-utils": "^7.24.8" } }, - "@babel/plugin-proposal-numeric-separator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", - "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.0.tgz", + "integrity": "sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" + "@babel/helper-plugin-utils": "^7.24.8" } }, - "@babel/plugin-proposal-optional-chaining": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", - "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", + "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7" } }, - "@babel/plugin-proposal-private-methods": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", - "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.0.tgz", + "integrity": "sha512-tggFrk1AIShG/RUQbEwt2Tr/E+ObkfwrPjR6BjbRvsx24+PSjK8zrq0GWPNCjo8qpRx4DuJzlcvWJqlm+0h3kw==", + "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.0" } }, "@babel/plugin-proposal-private-property-in-object": { @@ -25837,6 +19524,7 @@ "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.0" } @@ -25845,6 +19533,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.0" } @@ -25853,6 +19542,7 @@ "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.12.13" } @@ -25861,22 +19551,16 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.14.5" } }, - "@babel/plugin-syntax-decorators": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.22.5.tgz", - "integrity": "sha512-avpUOBS7IU6al8MmF1XpAyj9QYeLPuSDJI5D4pVMSMdL7xQokKqJPYQC67RCT0aCTashUXPiGwMJ0DEXXCEmMA==", - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, "@babel/plugin-syntax-dynamic-import": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.0" } @@ -25885,38 +19569,34 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.3" } }, - "@babel/plugin-syntax-flow": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.22.5.tgz", - "integrity": "sha512-9RdCl0i+q0QExayk2nOS7853w08yLucnnPML6EN9S8fgMPVtdLDCdx/cOQ/i44Lb9UeQX9A35yaqBBOMMZxPxQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, "@babel/plugin-syntax-import-assertions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz", - "integrity": "sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.6.tgz", + "integrity": "sha512-aABl0jHw9bZ2karQ/uUD6XP4u0SG22SJrOHFoL6XB1R7dTovOP4TzTlsxOYC5yQ1pdscVK2JTUnF6QL3ARoAiQ==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.8" } }, "@babel/plugin-syntax-import-attributes": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz", - "integrity": "sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.6.tgz", + "integrity": "sha512-sXaDXaJN9SNLymBdlWFA+bjzBhFD617ZaFiY13dGt7TVslVvVgA6fkZOP7Ki3IGElC45lwHdOTrCtKZGVAWeLQ==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.8" } }, "@babel/plugin-syntax-import-meta": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.10.4" } @@ -25925,22 +19605,25 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.0" } }, "@babel/plugin-syntax-jsx": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", - "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", + "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" } }, "@babel/plugin-syntax-logical-assignment-operators": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.10.4" } @@ -25949,6 +19632,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.0" } @@ -25957,6 +19641,7 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.10.4" } @@ -25965,6 +19650,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.0" } @@ -25973,6 +19659,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.0" } @@ -25981,6 +19668,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.0" } @@ -25989,6 +19677,7 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.14.5" } @@ -25997,568 +19686,614 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-syntax-typescript": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", - "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.4.tgz", + "integrity": "sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.8" } }, "@babel/plugin-syntax-unicode-sets-regex": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, "requires": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-arrow-functions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz", - "integrity": "sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", + "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" } }, "@babel/plugin-transform-async-generator-functions": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.9.tgz", - "integrity": "sha512-8Q3veQEDGe14dTYuwagbRtwxQDnytyg1JFu4/HwEMETeofocrB0U0ejBJIXoeG/t2oXZ8kzCyI0ZZfbT80VFNQ==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.4.tgz", + "integrity": "sha512-jz8cV2XDDTqjKPwVPJBIjORVEmSGYhdRa8e5k5+vN+uwcjSrSxUaebBRa4ko1jqNF2uxyg8G6XYk30Jv285xzg==", + "dev": true, "requires": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-remap-async-to-generator": "^7.22.20", - "@babel/plugin-syntax-async-generators": "^7.8.4" + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-remap-async-to-generator": "^7.25.0", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/traverse": "^7.25.4" } }, "@babel/plugin-transform-async-to-generator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz", - "integrity": "sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", + "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", + "dev": true, "requires": { - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-remap-async-to-generator": "^7.22.20" + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7" } }, "@babel/plugin-transform-block-scoped-functions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz", - "integrity": "sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", + "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" } }, "@babel/plugin-transform-block-scoping": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz", - "integrity": "sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.0.tgz", + "integrity": "sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.8" } }, "@babel/plugin-transform-class-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz", - "integrity": "sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.4.tgz", + "integrity": "sha512-nZeZHyCWPfjkdU5pA/uHiTaDAFUEqkpzf1YoQT2NeSynCGYq9rxfyI3XpQbfx/a0hSnFH6TGlEXvae5Vi7GD8g==", + "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-class-features-plugin": "^7.25.4", + "@babel/helper-plugin-utils": "^7.24.8" } }, "@babel/plugin-transform-class-static-block": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz", - "integrity": "sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", + "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", + "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-class-static-block": "^7.14.5" } }, "@babel/plugin-transform-classes": { - "version": "7.23.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.8.tgz", - "integrity": "sha512-yAYslGsY1bX6Knmg46RjiCiNSwJKv2IUC8qOdYKqMMr0491SXFhcHqOdRDeCRohOOIzwN/90C6mQ9qAKgrP7dg==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20", - "@babel/helper-split-export-declaration": "^7.22.6", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.4.tgz", + "integrity": "sha512-oexUfaQle2pF/b6E0dwsxQtAol9TLSO88kQvym6HHBWFliV2lGdrPieX+WgMRLSJDVzdYywk7jXbLPuO2KLTLg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-replace-supers": "^7.25.0", + "@babel/traverse": "^7.25.4", "globals": "^11.1.0" } }, "@babel/plugin-transform-computed-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz", - "integrity": "sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", + "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/template": "^7.22.15" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/template": "^7.24.7" } }, "@babel/plugin-transform-destructuring": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz", - "integrity": "sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", + "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.8" } }, "@babel/plugin-transform-dotall-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz", - "integrity": "sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", + "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", + "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" } }, "@babel/plugin-transform-duplicate-keys": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz", - "integrity": "sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", + "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.7" + } + }, + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.0.tgz", + "integrity": "sha512-YLpb4LlYSc3sCUa35un84poXoraOiQucUTTu8X1j18JV+gNa8E0nyUf/CjZ171IRGr4jEguF+vzJU66QZhn29g==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8" } }, "@babel/plugin-transform-dynamic-import": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz", - "integrity": "sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", + "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3" } }, "@babel/plugin-transform-exponentiation-operator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz", - "integrity": "sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", + "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", + "dev": true, "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" } }, "@babel/plugin-transform-export-namespace-from": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz", - "integrity": "sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", + "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" } }, - "@babel/plugin-transform-flow-strip-types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.22.5.tgz", - "integrity": "sha512-tujNbZdxdG0/54g/oua8ISToaXTFBf8EnSb5PgQSciIXWOWKX3S4+JR7ZE9ol8FZwf9kxitzkGQ+QWeov/mCiA==", - "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-flow": "^7.22.5" - } - }, "@babel/plugin-transform-for-of": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz", - "integrity": "sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", + "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" } }, "@babel/plugin-transform-function-name": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz", - "integrity": "sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==", + "version": "7.25.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.1.tgz", + "integrity": "sha512-TVVJVdW9RKMNgJJlLtHsKDTydjZAbwIsn6ySBPQaEAUU5+gVvlJt/9nRmqVbsV/IBanRjzWoaAQKLoamWVOUuA==", + "dev": true, "requires": { - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.1" } }, "@babel/plugin-transform-json-strings": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz", - "integrity": "sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", + "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-json-strings": "^7.8.3" } }, "@babel/plugin-transform-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz", - "integrity": "sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.2.tgz", + "integrity": "sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.8" } }, "@babel/plugin-transform-logical-assignment-operators": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz", - "integrity": "sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", + "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" } }, "@babel/plugin-transform-member-expression-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz", - "integrity": "sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", + "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" } }, "@babel/plugin-transform-modules-amd": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz", - "integrity": "sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", + "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", + "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", - "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", + "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", + "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-simple-access": "^7.22.5" + "@babel/helper-module-transforms": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-simple-access": "^7.24.7" } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.9.tgz", - "integrity": "sha512-KDlPRM6sLo4o1FkiSlXoAa8edLXFsKKIda779fbLrvmeuc3itnjCtaO6RrtoaANsIJANj+Vk1zqbZIMhkCAHVw==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.0.tgz", + "integrity": "sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw==", + "dev": true, "requires": { - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20" + "@babel/helper-module-transforms": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.0" } }, "@babel/plugin-transform-modules-umd": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz", - "integrity": "sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", + "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", + "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" } }, "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", - "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", + "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", + "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" } }, "@babel/plugin-transform-new-target": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz", - "integrity": "sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", + "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" } }, "@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz", - "integrity": "sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", + "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" } }, "@babel/plugin-transform-numeric-separator": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz", - "integrity": "sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", + "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-numeric-separator": "^7.10.4" } }, "@babel/plugin-transform-object-rest-spread": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.4.tgz", - "integrity": "sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", + "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", + "dev": true, "requires": { - "@babel/compat-data": "^7.23.3", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.23.3" + "@babel/plugin-transform-parameters": "^7.24.7" } }, "@babel/plugin-transform-object-super": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz", - "integrity": "sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", + "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7" } }, "@babel/plugin-transform-optional-catch-binding": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz", - "integrity": "sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", + "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" } }, "@babel/plugin-transform-optional-chaining": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz", - "integrity": "sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", + "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", "@babel/plugin-syntax-optional-chaining": "^7.8.3" } }, "@babel/plugin-transform-parameters": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz", - "integrity": "sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", + "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" } }, "@babel/plugin-transform-private-methods": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz", - "integrity": "sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.4.tgz", + "integrity": "sha512-ao8BG7E2b/URaUQGqN3Tlsg+M3KlHY6rJ1O1gXAEUnZoyNQnvKyH87Kfg+FoxSeyWUB8ISZZsC91C44ZuBFytw==", + "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-class-features-plugin": "^7.25.4", + "@babel/helper-plugin-utils": "^7.24.8" } }, "@babel/plugin-transform-private-property-in-object": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz", - "integrity": "sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", + "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", + "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" } }, "@babel/plugin-transform-property-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz", - "integrity": "sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==", - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-react-constant-elements": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.22.5.tgz", - "integrity": "sha512-BF5SXoO+nX3h5OhlN78XbbDrBOffv+AxPP2ENaJOVqjWCgBDeOY3WcaUcddutGSfoap+5NEQ/q/4I3WZIvgkXA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", + "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" } }, "@babel/plugin-transform-react-display-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.22.5.tgz", - "integrity": "sha512-PVk3WPYudRF5z4GKMEYUrLjPl38fJSKNaEOkFuoprioowGuWN6w2RKznuFNSlJx7pzzXXStPUnNSOEO0jL5EVw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz", + "integrity": "sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" } }, "@babel/plugin-transform-react-jsx": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.5.tgz", - "integrity": "sha512-rog5gZaVbUip5iWDMTYbVM15XQq+RkUKhET/IHR6oizR+JEoN6CAfTTuHcK4vwUyzca30qqHqEpzBOnaRMWYMA==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.2.tgz", + "integrity": "sha512-KQsqEAVBpU82NM/B/N9j9WOdphom1SZH3R+2V7INrQUH+V9EBFwZsEJl8eBIVeQE62FxJCc70jzEZwqU7RcVqA==", + "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-module-imports": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-jsx": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/types": "^7.25.2" } }, "@babel/plugin-transform-react-jsx-development": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz", - "integrity": "sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.7.tgz", + "integrity": "sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ==", + "dev": true, + "requires": { + "@babel/plugin-transform-react-jsx": "^7.24.7" + } + }, + "@babel/plugin-transform-react-jsx-self": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.7.tgz", + "integrity": "sha512-fOPQYbGSgH0HUp4UJO4sMBFjY6DuWq+2i8rixyUMb3CdGixs/gccURvYOAhajBdKDoGajFr3mUq5rH3phtkGzw==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.7" + } + }, + "@babel/plugin-transform-react-jsx-source": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.7.tgz", + "integrity": "sha512-J2z+MWzZHVOemyLweMqngXrgGC42jQ//R0KdxqkIz/OrbVIIlhFI3WigZ5fO+nwFvBlncr4MGapd8vTyc7RPNQ==", "requires": { - "@babel/plugin-transform-react-jsx": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" } }, "@babel/plugin-transform-react-pure-annotations": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.22.5.tgz", - "integrity": "sha512-gP4k85wx09q+brArVinTXhWiyzLl9UpmGva0+mWyKxk6JZequ05x3eUcIUE+FyttPKJFRRVtAvQaJ6YF9h1ZpA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.7.tgz", + "integrity": "sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA==", + "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" } }, "@babel/plugin-transform-regenerator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz", - "integrity": "sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", + "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", "regenerator-transform": "^0.15.2" } }, "@babel/plugin-transform-reserved-words": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz", - "integrity": "sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==", - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-runtime": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.22.9.tgz", - "integrity": "sha512-9KjBH61AGJetCPYp/IEyLEp47SyybZb0nDRpBvmtEkm+rUIwxdlKpyNHI1TmsGkeuLclJdleQHRZ8XLBnnh8CQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", + "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", + "dev": true, "requires": { - "@babel/helper-module-imports": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5", - "babel-plugin-polyfill-corejs2": "^0.4.4", - "babel-plugin-polyfill-corejs3": "^0.8.2", - "babel-plugin-polyfill-regenerator": "^0.5.1", - "semver": "^6.3.1" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" - } + "@babel/helper-plugin-utils": "^7.24.7" } }, "@babel/plugin-transform-shorthand-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz", - "integrity": "sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", + "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" } }, "@babel/plugin-transform-spread": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz", - "integrity": "sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", + "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" } }, "@babel/plugin-transform-sticky-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz", - "integrity": "sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", + "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" } }, "@babel/plugin-transform-template-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz", - "integrity": "sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", + "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" } }, "@babel/plugin-transform-typeof-symbol": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz", - "integrity": "sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", + "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.8" } }, "@babel/plugin-transform-typescript": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.23.6.tgz", - "integrity": "sha512-6cBG5mBvUu4VUD04OHKnYzbuHNP8huDsD3EDqqpIpsswTDoqHCjLoHb6+QgsV1WsT2nipRqCPgxD3LXnEO7XfA==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.2.tgz", + "integrity": "sha512-lBwRvjSmqiMYe/pS0+1gggjJleUJi7NzjvQ1Fkqtt69hBa/0t1YuW/MLQMAPixfwaQOHUXsd6jeU3Z+vdGv3+A==", + "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.23.6", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-typescript": "^7.23.3" + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-syntax-typescript": "^7.24.7" } }, "@babel/plugin-transform-unicode-escapes": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz", - "integrity": "sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", + "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" } }, "@babel/plugin-transform-unicode-property-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz", - "integrity": "sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", + "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", + "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" } }, "@babel/plugin-transform-unicode-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz", - "integrity": "sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", + "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", + "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" } }, "@babel/plugin-transform-unicode-sets-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz", - "integrity": "sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.4.tgz", + "integrity": "sha512-qesBxiWkgN1Q+31xUE9RcMk79eOXXDCv6tfyGMRSs4RGlioSg2WVyQAm07k726cSE56pa+Kb0y9epX2qaXzTvA==", + "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.25.2", + "@babel/helper-plugin-utils": "^7.24.8" } }, "@babel/preset-env": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.9.tgz", - "integrity": "sha512-3kBGTNBBk9DQiPoXYS0g0BYlwTQYUTifqgKTjxUwEUkduRT2QOa0FPGBJ+NROQhGyYO5BuTJwGvBnqKDykac6A==", - "requires": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.23.5", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.23.3", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.23.3", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.23.7", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.4.tgz", + "integrity": "sha512-W9Gyo+KmcxjGahtt3t9fb14vFRWvPpu5pT6GBlovAK6BTBcxgjfVMSQCfJl4oi35ODrxP6xx2Wr8LNST57Mraw==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.25.4", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-validator-option": "^7.24.8", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.3", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.0", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.0", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.0", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", "@babel/plugin-syntax-class-static-block": "^7.14.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.23.3", - "@babel/plugin-syntax-import-attributes": "^7.23.3", + "@babel/plugin-syntax-import-assertions": "^7.24.7", + "@babel/plugin-syntax-import-attributes": "^7.24.7", "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", @@ -26570,93 +20305,75 @@ "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.23.3", - "@babel/plugin-transform-async-generator-functions": "^7.23.9", - "@babel/plugin-transform-async-to-generator": "^7.23.3", - "@babel/plugin-transform-block-scoped-functions": "^7.23.3", - "@babel/plugin-transform-block-scoping": "^7.23.4", - "@babel/plugin-transform-class-properties": "^7.23.3", - "@babel/plugin-transform-class-static-block": "^7.23.4", - "@babel/plugin-transform-classes": "^7.23.8", - "@babel/plugin-transform-computed-properties": "^7.23.3", - "@babel/plugin-transform-destructuring": "^7.23.3", - "@babel/plugin-transform-dotall-regex": "^7.23.3", - "@babel/plugin-transform-duplicate-keys": "^7.23.3", - "@babel/plugin-transform-dynamic-import": "^7.23.4", - "@babel/plugin-transform-exponentiation-operator": "^7.23.3", - "@babel/plugin-transform-export-namespace-from": "^7.23.4", - "@babel/plugin-transform-for-of": "^7.23.6", - "@babel/plugin-transform-function-name": "^7.23.3", - "@babel/plugin-transform-json-strings": "^7.23.4", - "@babel/plugin-transform-literals": "^7.23.3", - "@babel/plugin-transform-logical-assignment-operators": "^7.23.4", - "@babel/plugin-transform-member-expression-literals": "^7.23.3", - "@babel/plugin-transform-modules-amd": "^7.23.3", - "@babel/plugin-transform-modules-commonjs": "^7.23.3", - "@babel/plugin-transform-modules-systemjs": "^7.23.9", - "@babel/plugin-transform-modules-umd": "^7.23.3", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", - "@babel/plugin-transform-new-target": "^7.23.3", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.23.4", - "@babel/plugin-transform-numeric-separator": "^7.23.4", - "@babel/plugin-transform-object-rest-spread": "^7.23.4", - "@babel/plugin-transform-object-super": "^7.23.3", - "@babel/plugin-transform-optional-catch-binding": "^7.23.4", - "@babel/plugin-transform-optional-chaining": "^7.23.4", - "@babel/plugin-transform-parameters": "^7.23.3", - "@babel/plugin-transform-private-methods": "^7.23.3", - "@babel/plugin-transform-private-property-in-object": "^7.23.4", - "@babel/plugin-transform-property-literals": "^7.23.3", - "@babel/plugin-transform-regenerator": "^7.23.3", - "@babel/plugin-transform-reserved-words": "^7.23.3", - "@babel/plugin-transform-shorthand-properties": "^7.23.3", - "@babel/plugin-transform-spread": "^7.23.3", - "@babel/plugin-transform-sticky-regex": "^7.23.3", - "@babel/plugin-transform-template-literals": "^7.23.3", - "@babel/plugin-transform-typeof-symbol": "^7.23.3", - "@babel/plugin-transform-unicode-escapes": "^7.23.3", - "@babel/plugin-transform-unicode-property-regex": "^7.23.3", - "@babel/plugin-transform-unicode-regex": "^7.23.3", - "@babel/plugin-transform-unicode-sets-regex": "^7.23.3", + "@babel/plugin-transform-arrow-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.25.4", + "@babel/plugin-transform-async-to-generator": "^7.24.7", + "@babel/plugin-transform-block-scoped-functions": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.25.0", + "@babel/plugin-transform-class-properties": "^7.25.4", + "@babel/plugin-transform-class-static-block": "^7.24.7", + "@babel/plugin-transform-classes": "^7.25.4", + "@babel/plugin-transform-computed-properties": "^7.24.7", + "@babel/plugin-transform-destructuring": "^7.24.8", + "@babel/plugin-transform-dotall-regex": "^7.24.7", + "@babel/plugin-transform-duplicate-keys": "^7.24.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.0", + "@babel/plugin-transform-dynamic-import": "^7.24.7", + "@babel/plugin-transform-exponentiation-operator": "^7.24.7", + "@babel/plugin-transform-export-namespace-from": "^7.24.7", + "@babel/plugin-transform-for-of": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.25.1", + "@babel/plugin-transform-json-strings": "^7.24.7", + "@babel/plugin-transform-literals": "^7.25.2", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", + "@babel/plugin-transform-member-expression-literals": "^7.24.7", + "@babel/plugin-transform-modules-amd": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.8", + "@babel/plugin-transform-modules-systemjs": "^7.25.0", + "@babel/plugin-transform-modules-umd": "^7.24.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", + "@babel/plugin-transform-new-target": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-numeric-separator": "^7.24.7", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-object-super": "^7.24.7", + "@babel/plugin-transform-optional-catch-binding": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.8", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.25.4", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-property-literals": "^7.24.7", + "@babel/plugin-transform-regenerator": "^7.24.7", + "@babel/plugin-transform-reserved-words": "^7.24.7", + "@babel/plugin-transform-shorthand-properties": "^7.24.7", + "@babel/plugin-transform-spread": "^7.24.7", + "@babel/plugin-transform-sticky-regex": "^7.24.7", + "@babel/plugin-transform-template-literals": "^7.24.7", + "@babel/plugin-transform-typeof-symbol": "^7.24.8", + "@babel/plugin-transform-unicode-escapes": "^7.24.7", + "@babel/plugin-transform-unicode-property-regex": "^7.24.7", + "@babel/plugin-transform-unicode-regex": "^7.24.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.25.4", "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.8", - "babel-plugin-polyfill-corejs3": "^0.9.0", - "babel-plugin-polyfill-regenerator": "^0.5.5", - "core-js-compat": "^3.31.0", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.37.1", "semver": "^6.3.1" }, "dependencies": { - "@babel/helper-define-polyfill-provider": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", - "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", - "requires": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" - } - }, "@babel/plugin-proposal-private-property-in-object": { "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, "requires": {} }, - "babel-plugin-polyfill-corejs3": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.9.0.tgz", - "integrity": "sha512-7nZPG1uzK2Ymhy/NbaOWTg3uibM2BmGASS4vHS4szRZAIR8R6GwA/xAujpdrXU5iyklrimWnLWU+BLF9suPTqg==", - "requires": { - "@babel/helper-define-polyfill-provider": "^0.5.0", - "core-js-compat": "^3.34.0" - } - }, "semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true } } }, @@ -26664,234 +20381,100 @@ "version": "0.1.6-no-external-plugins", "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/types": "^7.4.4", "esutils": "^2.0.2" } }, - "@babel/preset-react": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.22.5.tgz", - "integrity": "sha512-M+Is3WikOpEJHgR385HbuCITPTaPRaNkibTEa9oiofmJvIsrceb4yp9RL9Kb+TE8LznmeyZqpP+Lopwcx59xPQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.22.5", - "@babel/plugin-transform-react-display-name": "^7.22.5", - "@babel/plugin-transform-react-jsx": "^7.22.5", - "@babel/plugin-transform-react-jsx-development": "^7.22.5", - "@babel/plugin-transform-react-pure-annotations": "^7.22.5" - } - }, - "@babel/preset-typescript": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.23.3.tgz", - "integrity": "sha512-17oIGVlqz6CchO9RFYn5U6ZpWRZIngayYCtrPRSgANSwC2V1Jb+iP74nVxzzXJte8b8BYxrL1yY96xfhTBrNNQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.22.15", - "@babel/plugin-syntax-jsx": "^7.23.3", - "@babel/plugin-transform-modules-commonjs": "^7.23.3", - "@babel/plugin-transform-typescript": "^7.23.3" - } - }, - "@babel/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" - }, - "@babel/runtime": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.8.tgz", - "integrity": "sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==", - "requires": { - "regenerator-runtime": "^0.14.0" - }, - "dependencies": { - "regenerator-runtime": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", - "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" - } - } - }, - "@babel/runtime-corejs3": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.22.6.tgz", - "integrity": "sha512-M+37LLIRBTEVjktoJjbw4KVhupF0U/3PYUCbBwgAd9k17hoKhRu1n935QiG7Tuxv0LJOMrb2vuKEeYUlv0iyiw==", - "dev": true, - "requires": { - "core-js-pure": "^3.30.2", - "regenerator-runtime": "^0.13.11" - } - }, - "@babel/template": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", - "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", - "requires": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9" - } - }, - "@babel/traverse": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.0.tgz", - "integrity": "sha512-HfuJlI8qq3dEDmNU5ChzzpZRWq+oxCZQyMzIMEqLho+AQnhMnKQUzH6ydo3RBl/YjPCuk68Y6s0Gx0AeyULiWw==", - "requires": { - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.24.0", - "@babel/types": "^7.24.0", - "debug": "^4.3.1", - "globals": "^11.1.0" - } - }, - "@babel/types": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", - "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", - "requires": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - } - }, - "@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" - }, - "@csstools/normalize.css": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-12.0.0.tgz", - "integrity": "sha512-M0qqxAcwCsIVfpFQSlGN5XjXWu8l5JDZN+fPt1LeW5SZexQTgnaEvgXAY+CeygRw0EeppWHi12JxESWiWrB0Sg==" - }, - "@csstools/postcss-cascade-layers": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-1.1.1.tgz", - "integrity": "sha512-+KdYrpKC5TgomQr2DlZF4lDEpHcoxnj5IGddYYfBWJAKfj1JtuHUIqMa+E1pJJ+z3kvDViWMqyqPlG4Ja7amQA==", - "requires": { - "@csstools/selector-specificity": "^2.0.2", - "postcss-selector-parser": "^6.0.10" - } - }, - "@csstools/postcss-color-function": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-1.1.1.tgz", - "integrity": "sha512-Bc0f62WmHdtRDjf5f3e2STwRAl89N2CLb+9iAwzrv4L2hncrbDwnQD9PCq0gtAt7pOI2leIV08HIBUd4jxD8cw==", - "requires": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" - } - }, - "@csstools/postcss-font-format-keywords": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-1.0.1.tgz", - "integrity": "sha512-ZgrlzuUAjXIOc2JueK0X5sZDjCtgimVp/O5CEqTcs5ShWBa6smhWYbS0x5cVc/+rycTDbjjzoP0KTDnUneZGOg==", - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "@csstools/postcss-hwb-function": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-1.0.2.tgz", - "integrity": "sha512-YHdEru4o3Rsbjmu6vHy4UKOXZD+Rn2zmkAmLRfPet6+Jz4Ojw8cbWxe1n42VaXQhD3CQUXXTooIy8OkVbUcL+w==", - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "@csstools/postcss-ic-unit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-1.0.1.tgz", - "integrity": "sha512-Ot1rcwRAaRHNKC9tAqoqNZhjdYBzKk1POgWfhN4uCOE47ebGcLRqXjKkApVDpjifL6u2/55ekkpnFcp+s/OZUw==", - "requires": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" - } - }, - "@csstools/postcss-is-pseudo-class": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-2.0.7.tgz", - "integrity": "sha512-7JPeVVZHd+jxYdULl87lvjgvWldYu+Bc62s9vD/ED6/QTGjy0jy0US/f6BG53sVMTBJ1lzKZFpYmofBN9eaRiA==", - "requires": { - "@csstools/selector-specificity": "^2.0.0", - "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==", + "@babel/preset-react": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.7.tgz", + "integrity": "sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==", + "dev": true, "requires": { - "postcss-value-parser": "^4.2.0" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-transform-react-display-name": "^7.24.7", + "@babel/plugin-transform-react-jsx": "^7.24.7", + "@babel/plugin-transform-react-jsx-development": "^7.24.7", + "@babel/plugin-transform-react-pure-annotations": "^7.24.7" } }, - "@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", - "integrity": "sha512-jcOanIbv55OFKQ3sYeFD/T0Ti7AMXc9nM1hZWu8m/2722gOTxFg7xYu4RDLJLeZmPUVQlGzo4jhzvTUq3x4ZUw==", + "@babel/preset-typescript": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz", + "integrity": "sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==", + "dev": true, "requires": { - "postcss-value-parser": "^4.2.0" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.7", + "@babel/plugin-transform-typescript": "^7.24.7" } }, - "@csstools/postcss-oklab-function": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-1.1.1.tgz", - "integrity": "sha512-nJpJgsdA3dA9y5pgyb/UfEzE7W5Ka7u0CX0/HIMVBNWzWemdcTH3XwANECU6anWv/ao4vVNLTMxhiPNZsTK6iA==", - "requires": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" - } + "@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true }, - "@csstools/postcss-progressive-custom-properties": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-1.3.0.tgz", - "integrity": "sha512-ASA9W1aIy5ygskZYuWams4BzafD12ULvSypmaLJT2jvQ8G0M3I8PRQhC0h7mG0Z3LI05+agZjqSR9+K9yaQQjA==", + "@babel/runtime": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz", + "integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==", "requires": { - "postcss-value-parser": "^4.2.0" + "regenerator-runtime": "^0.14.0" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + } } }, - "@csstools/postcss-stepped-value-functions": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-1.0.1.tgz", - "integrity": "sha512-dz0LNoo3ijpTOQqEJLY8nyaapl6umbmDcgj4AD0lgVQ572b2eqA1iGZYTTWhrcrHztWDDRAX2DGYyw2VBjvCvQ==", + "@babel/template": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", + "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", "requires": { - "postcss-value-parser": "^4.2.0" + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.25.0", + "@babel/types": "^7.25.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" + "@babel/traverse": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz", + "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==", + "requires": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.6", + "@babel/parser": "^7.25.6", + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.6", + "debug": "^4.3.1", + "globals": "^11.1.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", - "integrity": "sha512-woKaLO///4bb+zZC2s80l+7cm07M7268MsyG3M0ActXXEFi6SuhvriQYcb58iiKGbjwwIU7n45iRLEHypB47Og==", + "@babel/types": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", + "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", "requires": { - "postcss-value-parser": "^4.2.0" + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" } }, - "@csstools/postcss-unset-value": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-1.0.2.tgz", - "integrity": "sha512-c8J4roPBILnelAsdLr4XOAR/GsTm0GJi4XpcfvoWk3U6KiTCqiFYc63KhRMQQX35jYMp4Ao8Ij9+IZRgMfJp1g==", - "requires": {} - }, - "@csstools/selector-specificity": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz", - "integrity": "sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==", - "requires": {} + "@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true }, "@dicebear/adventurer": { "version": "8.0.1", @@ -26983,20 +20566,20 @@ } }, "@dicebear/converter": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@dicebear/converter/-/converter-8.0.1.tgz", - "integrity": "sha512-65L04fN4V07WcUnwQuDYDH+zrP8WA6/UeIuqqH/Pv7VWoJtIk9qHlaA+XGpPr4qgRtkmY7uXVkrED/RMlqvUDA==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@dicebear/converter/-/converter-8.0.2.tgz", + "integrity": "sha512-mREmyQLIfHnt30Xzjc9ZHgDgIzbF7BXApBCYolnB2kO2Kpb14OdmsyLRsYe/Tt+Vt6sLgiigWoZFcRvbStRhLA==", "requires": { "@types/json-schema": "^7.0.11", "tmp-promise": "^3.0.3" } }, "@dicebear/core": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@dicebear/core/-/core-8.0.1.tgz", - "integrity": "sha512-HWqvQRpVjkboQXinCOjU3poZIMd5p+32wPvc9N5fYiXe3KQLhJNw5T5XiRttDUm3XpoTvhQ4DVTPDsXT8CqrTg==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@dicebear/core/-/core-8.0.2.tgz", + "integrity": "sha512-Zr3dBAH+6BBYc2kjz7KvJCMYasQlsY9CZ7D3abgZhk/XRT4B3qxo8kP+FL8YjJvrOJyV2P7h08BAKZlTWuKXPA==", "requires": { - "@dicebear/converter": "8.0.1", + "@dicebear/converter": "8.0.2", "@types/json-schema": "^7.0.11" } }, @@ -27115,15 +20698,15 @@ "requires": {} }, "@emotion/babel-plugin": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", - "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz", + "integrity": "sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==", "requires": { "@babel/helper-module-imports": "^7.16.7", "@babel/runtime": "^7.18.3", - "@emotion/hash": "^0.9.1", - "@emotion/memoize": "^0.8.1", - "@emotion/serialize": "^1.1.2", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.2.0", "babel-plugin-macros": "^3.1.0", "convert-source-map": "^1.5.0", "escape-string-regexp": "^4.0.0", @@ -27133,224 +20716,213 @@ } }, "@emotion/cache": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", - "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", - "requires": { - "@emotion/memoize": "^0.8.1", - "@emotion/sheet": "^1.2.2", - "@emotion/utils": "^1.2.1", - "@emotion/weak-memoize": "^0.3.1", + "version": "11.13.1", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.1.tgz", + "integrity": "sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==", + "requires": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.0", + "@emotion/weak-memoize": "^0.4.0", "stylis": "4.2.0" } }, "@emotion/hash": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", - "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==" }, "@emotion/is-prop-valid": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz", - "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.0.tgz", + "integrity": "sha512-SHetuSLvJDzuNbOdtPVbq6yMMMlLoW5Q94uDqJZqy50gcmAjxFkVqmzqSGEFq9gT2iMuIeKV1PXVWmvUhuZLlQ==", "requires": { - "@emotion/memoize": "^0.8.1" + "@emotion/memoize": "^0.9.0" } }, "@emotion/memoize": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", - "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==" }, "@emotion/react": { - "version": "11.11.4", - "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz", - "integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==", + "version": "11.13.3", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.13.3.tgz", + "integrity": "sha512-lIsdU6JNrmYfJ5EbUCf4xW1ovy5wKQ2CkPRM4xogziOxH1nXxBSjpC9YqbFAP7circxMfYp+6x676BqWcEiixg==", "requires": { "@babel/runtime": "^7.18.3", - "@emotion/babel-plugin": "^11.11.0", - "@emotion/cache": "^11.11.0", - "@emotion/serialize": "^1.1.3", - "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", - "@emotion/utils": "^1.2.1", - "@emotion/weak-memoize": "^0.3.1", + "@emotion/babel-plugin": "^11.12.0", + "@emotion/cache": "^11.13.0", + "@emotion/serialize": "^1.3.1", + "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0", + "@emotion/utils": "^1.4.0", + "@emotion/weak-memoize": "^0.4.0", "hoist-non-react-statics": "^3.3.1" } }, "@emotion/serialize": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.4.tgz", - "integrity": "sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.1.tgz", + "integrity": "sha512-dEPNKzBPU+vFPGa+z3axPRn8XVDetYORmDC0wAiej+TNcOZE70ZMJa0X7JdeoM6q/nWTMZeLpN/fTnD9o8MQBA==", "requires": { - "@emotion/hash": "^0.9.1", - "@emotion/memoize": "^0.8.1", - "@emotion/unitless": "^0.8.1", - "@emotion/utils": "^1.2.1", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.10.0", + "@emotion/utils": "^1.4.0", "csstype": "^3.0.2" } }, "@emotion/sheet": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", - "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==" }, "@emotion/styled": { - "version": "11.11.5", - "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.5.tgz", - "integrity": "sha512-/ZjjnaNKvuMPxcIiUkf/9SHoG4Q196DRl1w82hQ3WCsjo1IUR8uaGWrC6a87CrYAW0Kb/pK7hk8BnLgLRi9KoQ==", + "version": "11.13.0", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.13.0.tgz", + "integrity": "sha512-tkzkY7nQhW/zC4hztlwucpT8QEZ6eUzpXDRhww/Eej4tFfO0FxQYWRyg/c5CCXa4d/f174kqeXYjuQRnhzf6dA==", "requires": { "@babel/runtime": "^7.18.3", - "@emotion/babel-plugin": "^11.11.0", - "@emotion/is-prop-valid": "^1.2.2", - "@emotion/serialize": "^1.1.4", - "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", - "@emotion/utils": "^1.2.1" + "@emotion/babel-plugin": "^11.12.0", + "@emotion/is-prop-valid": "^1.3.0", + "@emotion/serialize": "^1.3.0", + "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0", + "@emotion/utils": "^1.4.0" } }, "@emotion/unitless": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", - "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", + "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==" }, "@emotion/use-insertion-effect-with-fallbacks": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", - "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz", + "integrity": "sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==", "requires": {} }, "@emotion/utils": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", - "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.0.tgz", + "integrity": "sha512-spEnrA1b6hDR/C68lC2M7m6ALPUHZC0lIY7jAS/B/9DuuO1ZP04eov8SMv/6fwRd8pzmsn2AuJEznRREWlQrlQ==" }, "@emotion/weak-memoize": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", - "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==" }, "@esbuild/aix-ppc64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "dev": true, "optional": true }, "@esbuild/android-arm": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "dev": true, "optional": true }, "@esbuild/android-arm64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "dev": true, "optional": true }, "@esbuild/android-x64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "dev": true, "optional": true }, "@esbuild/darwin-arm64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "dev": true, "optional": true }, "@esbuild/darwin-x64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "dev": true, "optional": true }, "@esbuild/freebsd-arm64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "dev": true, "optional": true }, "@esbuild/freebsd-x64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "dev": true, "optional": true }, "@esbuild/linux-arm": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "dev": true, "optional": true }, "@esbuild/linux-arm64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "dev": true, "optional": true }, "@esbuild/linux-ia32": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "dev": true, "optional": true }, "@esbuild/linux-loong64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "dev": true, "optional": true }, "@esbuild/linux-mips64el": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "dev": true, "optional": true }, "@esbuild/linux-ppc64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "dev": true, "optional": true }, "@esbuild/linux-riscv64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "dev": true, "optional": true }, "@esbuild/linux-s390x": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "dev": true, "optional": true }, "@esbuild/linux-x64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "dev": true, "optional": true }, "@esbuild/netbsd-x64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "optional": true + }, + "@esbuild/openbsd-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", + "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", "dev": true, "optional": true }, @@ -27358,54 +20930,53 @@ "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "dev": true, "optional": true }, "@esbuild/sunos-x64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "dev": true, "optional": true }, "@esbuild/win32-arm64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "dev": true, "optional": true }, "@esbuild/win32-ia32": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "dev": true, "optional": true }, "@esbuild/win32-x64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "dev": true, "optional": true }, "@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, "requires": { "eslint-visitor-keys": "^3.3.0" } }, "@eslint-community/regexpp": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", - "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==" + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "dev": true }, "@eslint/eslintrc": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz", - "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "peer": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -27422,6 +20993,8 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "peer": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -27432,12 +21005,16 @@ "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "peer": true }, "globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "peer": true, "requires": { "type-fest": "^0.20.2" } @@ -27446,6 +21023,8 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "peer": true, "requires": { "argparse": "^2.0.1" } @@ -27453,19 +21032,25 @@ "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "peer": true }, "type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "peer": true } } }, "@eslint/js": { - "version": "8.44.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz", - "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==" + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "dev": true, + "peer": true }, "@floating-ui/core": { "version": "1.6.1", @@ -27485,12 +21070,12 @@ } }, "@floating-ui/react": { - "version": "0.26.19", - "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.19.tgz", - "integrity": "sha512-Jk6zITdjjIvjO/VdQFvpRaD3qPwOHH6AoDHxjhpy+oK4KFgaSP871HYWUAPdnLmx1gQ+w/pB312co3tVml+BXA==", + "version": "0.26.22", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.22.tgz", + "integrity": "sha512-LNv4azPt8SpT4WW7Kku5JNVjLk2GcS0bGGjFTAgqOONRFo9r/aaGHHPpdiIuQbB1t8shmWyWqTTUDmZ9fcNshg==", "requires": { "@floating-ui/react-dom": "^2.1.1", - "@floating-ui/utils": "^0.2.4", + "@floating-ui/utils": "^0.2.7", "tabbable": "^6.0.0" } }, @@ -27503,16 +21088,9 @@ } }, "@floating-ui/utils": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.4.tgz", - "integrity": "sha512-dWO2pw8hhi+WrXq1YJy2yCuWoL20PddgGaqTgVe4cOS9Q6qklXCiA1tJEqX6BEwRNSCP84/afac9hd4MS+zEUA==" - }, - "@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "optional": true, - "peer": true + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.7.tgz", + "integrity": "sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA==" }, "@graphql-typed-document-node/core": { "version": "3.2.0", @@ -27521,29 +21099,36 @@ "requires": {} }, "@humanwhocodes/config-array": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", - "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "dev": true, + "peer": true, "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", "minimatch": "^3.0.5" } }, "@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==" + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "peer": true }, "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "dev": true, + "peer": true }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, "requires": { "camelcase": "^5.3.1", "find-up": "^4.1.0", @@ -27555,14 +21140,16 @@ "resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==" + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true } } }, "@istanbuljs/schema": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==" + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true }, "@jedmao/location": { "version": "3.0.0", @@ -27574,6 +21161,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "dev": true, "requires": { "@jest/types": "^27.5.1", "@types/node": "*", @@ -27587,6 +21175,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -27598,6 +21187,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", + "dev": true, "requires": { "@jest/console": "^27.5.1", "@jest/reporters": "^27.5.1", @@ -27633,6 +21223,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -27644,6 +21235,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "dev": true, "requires": { "@jest/fake-timers": "^27.5.1", "@jest/types": "^27.5.1", @@ -27655,6 +21247,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "dev": true, "requires": { "@jest/types": "^27.5.1", "@sinonjs/fake-timers": "^8.0.1", @@ -27668,6 +21261,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", + "dev": true, "requires": { "@jest/environment": "^27.5.1", "@jest/types": "^27.5.1", @@ -27678,6 +21272,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", + "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", "@jest/console": "^27.5.1", @@ -27710,6 +21305,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -27718,22 +21314,16 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true } } }, - "@jest/schemas": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", - "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", - "requires": { - "@sinclair/typebox": "^0.24.1" - } - }, "@jest/source-map": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", + "dev": true, "requires": { "callsites": "^3.0.0", "graceful-fs": "^4.2.9", @@ -27743,7 +21333,8 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true } } }, @@ -27751,6 +21342,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", + "dev": true, "requires": { "@jest/console": "^27.5.1", "@jest/types": "^27.5.1", @@ -27762,6 +21354,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", + "dev": true, "requires": { "@jest/test-result": "^27.5.1", "graceful-fs": "^4.2.9", @@ -27773,6 +21366,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "dev": true, "requires": { "@babel/core": "^7.1.0", "@jest/types": "^27.5.1", @@ -27795,6 +21389,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -27803,7 +21398,8 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true } } }, @@ -27811,6 +21407,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, "requires": { "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", @@ -27823,6 +21420,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -27831,13 +21429,13 @@ } }, "@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "requires": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" } }, "@jridgewell/resolve-uri": { @@ -27846,14 +21444,16 @@ "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" }, "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==" }, "@jridgewell/source-map": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "optional": true, + "peer": true, "requires": { "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -27865,72 +21465,30 @@ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, "@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - }, - "dependencies": { - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" - } + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "@leichtgewicht/ip-codec": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", - "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" - }, "@microsoft/tsdoc": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz", - "integrity": "sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==", + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.15.0.tgz", + "integrity": "sha512-HZpPoABogPvjeJOdzCOSJsXeL/SMCBgBZMVC3X3d7YYp2gf31MfxhUoYUNwf1ERPJOnQc0wkFn9trqI6ZEdZuA==", "dev": true }, "@microsoft/tsdoc-config": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.16.2.tgz", - "integrity": "sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.17.0.tgz", + "integrity": "sha512-v/EYRXnCAIHxOHW+Plb6OWuUoMotxTN0GLatnpOb1xq0KuTNw/WI3pamJx/UbsoJP5k9MCw1QxvvhPcF9pH3Zg==", "dev": true, "requires": { - "@microsoft/tsdoc": "0.14.2", - "ajv": "~6.12.6", + "@microsoft/tsdoc": "0.15.0", + "ajv": "~8.12.0", "jju": "~1.4.0", - "resolve": "~1.19.0" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "resolve": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", - "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", - "dev": true, - "requires": { - "is-core-module": "^2.1.0", - "path-parse": "^1.0.6" - } - } + "resolve": "~1.22.2" } }, "@mui/base": { @@ -27945,38 +21503,31 @@ "@popperjs/core": "^2.11.8", "clsx": "^2.1.0", "prop-types": "^15.8.1" - }, - "dependencies": { - "clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" - } } }, "@mui/core-downloads-tracker": { - "version": "5.16.4", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.4.tgz", - "integrity": "sha512-rNdHXhclwjEZnK+//3SR43YRx0VtjdHnUFhMSGYmAMJve+KiwEja/41EYh8V3pZKqF2geKyfcFUenTfDTYUR4w==" + "version": "5.16.7", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.7.tgz", + "integrity": "sha512-RtsCt4Geed2/v74sbihWzzRs+HsIQCfclHeORh5Ynu2fS4icIKozcSubwuG7vtzq2uW3fOR1zITSP84TNt2GoQ==" }, "@mui/icons-material": { - "version": "5.16.1", - "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.16.1.tgz", - "integrity": "sha512-ogQPweYba4+5XZykilwxn2/oS78uwoQ0BVBpOhhCJo0ooZsqTTsalhzP2qD/RdGqMQ8xyXPz1sYM2djTruVVVA==", + "version": "5.16.7", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.16.7.tgz", + "integrity": "sha512-UrGwDJCXEszbDI7yV047BYU5A28eGJ79keTCP4cc74WyncuVrnurlmIRxaHL8YK+LI1Kzq+/JM52IAkNnv4u+Q==", "requires": { "@babel/runtime": "^7.23.9" } }, "@mui/material": { - "version": "5.16.4", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.16.4.tgz", - "integrity": "sha512-dBnh3/zRYgEVIS3OE4oTbujse3gifA0qLMmuUk13ywsDCbngJsdgwW5LuYeiT5pfA8PGPGSqM7mxNytYXgiMCw==", + "version": "5.16.7", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.16.7.tgz", + "integrity": "sha512-cwwVQxBhK60OIOqZOVLFt55t01zmarKJiJUWbk0+8s/Ix5IaUzAShqlJchxsIQ4mSrWqgcKCCXKtIlG5H+/Jmg==", "requires": { "@babel/runtime": "^7.23.9", - "@mui/core-downloads-tracker": "^5.16.4", - "@mui/system": "^5.16.4", + "@mui/core-downloads-tracker": "^5.16.7", + "@mui/system": "^5.16.7", "@mui/types": "^7.2.15", - "@mui/utils": "^5.16.4", + "@mui/utils": "^5.16.6", "@popperjs/core": "^2.11.8", "@types/react-transition-group": "^4.4.10", "clsx": "^2.1.0", @@ -27984,29 +21535,22 @@ "prop-types": "^15.8.1", "react-is": "^18.3.1", "react-transition-group": "^4.4.5" - }, - "dependencies": { - "clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" - } } }, "@mui/private-theming": { - "version": "5.16.4", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.16.4.tgz", - "integrity": "sha512-ZsAm8cq31SJ37SVWLRlu02v9SRthxnfQofaiv14L5Bht51B0dz6yQEoVU/V8UduZDCCIrWkBHuReVfKhE/UuXA==", + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.16.6.tgz", + "integrity": "sha512-rAk+Rh8Clg7Cd7shZhyt2HGTTE5wYKNSJ5sspf28Fqm/PZ69Er9o6KX25g03/FG2dfpg5GCwZh/xOojiTfm3hw==", "requires": { "@babel/runtime": "^7.23.9", - "@mui/utils": "^5.16.4", + "@mui/utils": "^5.16.6", "prop-types": "^15.8.1" } }, "@mui/styled-engine": { - "version": "5.16.4", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.16.4.tgz", - "integrity": "sha512-0+mnkf+UiAmTVB8PZFqOhqf729Yh0Cxq29/5cA3VAyDVTRIUUQ8FXQhiAhUIbijFmM72rY80ahFPXIm4WDbzcA==", + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.16.6.tgz", + "integrity": "sha512-zaThmS67ZmtHSWToTiHslbI8jwrmITcN93LQaR2lKArbvS7Z3iLkwRoiikNWutx9MBs8Q6okKvbZq1RQYB3v7g==", "requires": { "@babel/runtime": "^7.23.9", "@emotion/cache": "^11.11.0", @@ -28015,9 +21559,9 @@ } }, "@mui/system": { - "version": "5.16.4", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.16.4.tgz", - "integrity": "sha512-ET1Ujl2/8hbsD611/mqUuNArMCGv/fIWO/f8B3ZqF5iyPHM2aS74vhTNyjytncc4i6dYwGxNk+tLa7GwjNS0/w==", + "version": "5.16.7", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.16.7.tgz", + "integrity": "sha512-Jncvs/r/d/itkxh7O7opOunTqbbSSzMTHzZkNLM+FjAOg+cYAZHrPDlYe1ZGKUYORwwb2XexlWnpZp0kZ4AHuA==", "requires": { "@babel/runtime": "^7.23.9", "@mui/private-theming": "^5.16.4", @@ -28027,13 +21571,6 @@ "clsx": "^2.1.0", "csstype": "^3.1.3", "prop-types": "^15.8.1" - }, - "dependencies": { - "clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" - } } }, "@mui/types": { @@ -28043,76 +21580,83 @@ "requires": {} }, "@mui/utils": { - "version": "5.16.4", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.16.4.tgz", - "integrity": "sha512-nlppYwq10TBIFqp7qxY0SvbACOXeOjeVL3pOcDsK0FT8XjrEXh9/+lkg8AEIzD16z7YfiJDQjaJG2OLkE7BxNg==", + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.16.6.tgz", + "integrity": "sha512-tWiQqlhxAt3KENNiSRL+DIn9H5xNVK6Jjf70x3PnfQPz1MPBdh7yyIcAyVBT9xiw7hP3SomRhPR7hzBMBCjqEA==", "requires": { "@babel/runtime": "^7.23.9", + "@mui/types": "^7.2.15", "@types/prop-types": "^15.7.12", "clsx": "^2.1.1", "prop-types": "^15.8.1", "react-is": "^18.3.1" + } + }, + "@mui/x-charts": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@mui/x-charts/-/x-charts-7.17.0.tgz", + "integrity": "sha512-xDH/lOnb57+VBIA7q+1KlC0Ht1O46d/N2MEl1tUq1JYIXhA2Owi5cp+bcaof8Rvw5ApCmkoBxyUIjqT0guNIwA==", + "requires": { + "@babel/runtime": "^7.25.6", + "@mui/utils": "^5.16.6", + "@mui/x-charts-vendor": "7.16.0", + "@mui/x-internals": "7.17.0", + "@react-spring/rafz": "^9.7.4", + "@react-spring/web": "^9.7.4", + "clsx": "^2.1.1", + "prop-types": "^15.8.1" }, "dependencies": { - "clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" + "@mui/x-internals": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-7.17.0.tgz", + "integrity": "sha512-FLlAGSJl/vsuaA/8hPGazXFppyzIzxApJJDZMoTS0geUmHd0hyooISV2ltllLmrZ/DGtHhI08m8GGnHL6/vVeg==", + "requires": { + "@babel/runtime": "^7.25.6", + "@mui/utils": "^5.16.6" + } } } }, - "@mui/x-charts": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@mui/x-charts/-/x-charts-7.8.0.tgz", - "integrity": "sha512-SosaVtx4Ig1nu/loH6Mq4peH5Pq5UvVEnsMfe4G2IEVrMxfwrktWJo+86t9LxiHTERt4wxPKnsqlhkgBIf9ePQ==", + "@mui/x-charts-vendor": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@mui/x-charts-vendor/-/x-charts-vendor-7.16.0.tgz", + "integrity": "sha512-MyMCCl7eAM53rLbjqP4zbMy5hYtdeqCjAYCH2jpvBKdgugm2eaPLKOPM8bUVfen0wHA8BXleQrIrNceytFPyZA==", "requires": { - "@babel/runtime": "^7.24.7", - "@mui/base": "^5.0.0-beta.40", - "@mui/system": "^5.15.20", - "@mui/utils": "^5.15.20", - "@react-spring/rafz": "^9.7.3", - "@react-spring/web": "^9.7.3", - "clsx": "^2.1.1", + "@babel/runtime": "^7.25.6", + "@types/d3-color": "^3.1.3", + "@types/d3-delaunay": "^6.0.4", + "@types/d3-interpolate": "^3.0.4", + "@types/d3-scale": "^4.0.8", + "@types/d3-shape": "^3.1.6", + "@types/d3-time": "^3.0.3", "d3-color": "^3.1.0", "d3-delaunay": "^6.0.4", "d3-interpolate": "^3.0.1", "d3-scale": "^4.0.2", "d3-shape": "^3.2.0", - "prop-types": "^15.8.1" - }, - "dependencies": { - "clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" - } + "d3-time": "^3.1.0", + "delaunator": "^5.0.1", + "robust-predicates": "^3.0.2" } }, "@mui/x-data-grid": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-7.11.0.tgz", - "integrity": "sha512-dXaIw3Noxc4d6xenS7J+zMPORG9ptkTW7B81P6QFovILSEuI/qebQhijy/IkqRvcCsuZYLL3nA89bp+EDI503Q==", - "requires": { - "@babel/runtime": "^7.24.8", - "@mui/system": "^5.16.2", - "@mui/utils": "^5.16.2", - "@mui/x-internals": "7.11.0", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-7.16.0.tgz", + "integrity": "sha512-71ZyffTeF8RPa399UkMlUbQ8T70kOrUK3fBXfinnal4mwgISlKwBN8EHNZZhyxSQ4vpWs3wHrHZ6MGQeXNUhJQ==", + "requires": { + "@babel/runtime": "^7.25.6", + "@mui/utils": "^5.16.6", + "@mui/x-internals": "7.16.0", "clsx": "^2.1.1", "prop-types": "^15.8.1", - "reselect": "^4.1.8" - }, - "dependencies": { - "clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" - } + "reselect": "^5.1.1" } }, "@mui/x-date-pickers": { - "version": "7.6.1", - "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-7.6.1.tgz", - "integrity": "sha512-erSq5cnOUyBgBmpHnMxIit5yhT3bl/lOaNZKpObvJtvEJetvNA9xWQ7dz/J/AufLzDuvThjusuRD0y+GmeXtiw==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-7.12.1.tgz", + "integrity": "sha512-Zj8kt3SCQbJp1qhMi+A3I4KqB8i5OY2Q11mdOEathFhqN/SQm1sUjIa1G09cGP1dPDgK1a6KM6qJGNtcw/nuWA==", "requires": { "@babel/runtime": "^7.24.6", "@mui/base": "^5.0.0-beta.40", @@ -28122,36 +21666,22 @@ "clsx": "^2.1.1", "prop-types": "^15.8.1", "react-transition-group": "^4.4.5" - }, - "dependencies": { - "clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" - } } }, "@mui/x-internals": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-7.11.0.tgz", - "integrity": "sha512-GqCYylKiB4cLH9tK4JweJlT2JvPjnpXjS3TEIqtHB4BcSsezhdRrMGzHOO5zCJqkasqTirJh2t6X16Qw1llr4Q==", - "requires": { - "@babel/runtime": "^7.24.8", - "@mui/utils": "^5.16.2" - } - }, - "@nicolo-ribaudo/eslint-scope-5-internals": { - "version": "5.1.1-v1", - "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", - "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-7.16.0.tgz", + "integrity": "sha512-ijer5XYmWlJqWaTmF6TGH1odG7EAupv8iDWYmDm2yVR9IQ+L2nQSuhiFClI+wmGx40KS2VKOlzDMPpF0t7/HCg==", "requires": { - "eslint-scope": "5.1.1" + "@babel/runtime": "^7.25.6", + "@mui/utils": "^5.16.6" } }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, "requires": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -28160,12 +21690,14 @@ "@nodelib/fs.stat": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true }, "@nodelib/fs.walk": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, "requires": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -28191,6 +21723,7 @@ "version": "1.2.6", "resolved": "https://registry.npmjs.org/@pdfme/common/-/common-1.2.6.tgz", "integrity": "sha512-ROmQ/iMUdmFS2QXD/kKDdcU5T6H3azDs2b1hE/OXs8531BPZ9ABbu9+1NRZQoNK4U/zP2F+Osb/B8ckr9lAmGg==", + "peer": true, "requires": { "buffer": "^6.0.3", "fontkit": "^2.0.2", @@ -28198,33 +21731,37 @@ } }, "@pdfme/generator": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@pdfme/generator/-/generator-1.2.6.tgz", - "integrity": "sha512-rAkhr4vYa0OxVubAvLI/UIgD9+sCrcBG1SZpFCBVILgZjpqkUsscXdyukRtmHP6WaNAFGINch6PZVoshyQdGPw==", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/@pdfme/generator/-/generator-4.5.2.tgz", + "integrity": "sha512-lwvNnknTjAlmThkdxNJLcr/1/gYUW1H6xvtdX7t1OSQ/oEJfgcR9oFsUsR+OTnEYDN4zXkAmQbm1K/tnjNQWVA==", "requires": { - "@pdfme/common": "latest", - "@pdfme/pdf-lib": "^1.17.3", + "@pdfme/pdf-lib": "^1.18.3", "atob": "^2.1.2", - "bwip-js": "^3.2.2", "fontkit": "^2.0.2" } }, "@pdfme/pdf-lib": { - "version": "1.17.3", - "resolved": "https://registry.npmjs.org/@pdfme/pdf-lib/-/pdf-lib-1.17.3.tgz", - "integrity": "sha512-k3cyms42I7jVycwDuzZuLD7A9J/D8Ud1iGJ7BpAfF54QYKxG0mUG6jTDJnc+tHrpNrsoJ4iFqERy5XvMQ6SUsA==", + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/@pdfme/pdf-lib/-/pdf-lib-1.18.3.tgz", + "integrity": "sha512-Zy4lRrxhDo7pbexNCvn+nzO5gLRc1XOXQyFOHC1FJoaHzrZ3GDd4OZwR5AaGIlCwV7ocPP2+iiLFA5wQcx3s9w==", "requires": { "@pdf-lib/standard-fonts": "^1.0.0", - "@pdf-lib/upng": "^1.0.1", - "pako": "^1.0.11", - "tslib": "^1.11.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } + "@pdf-lib/upng": "^1.0.1", + "color": "^4.2.3", + "node-html-better-parser": "^1.4.0", + "pako": "^1.0.11" + } + }, + "@pdfme/schemas": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@pdfme/schemas/-/schemas-4.3.2.tgz", + "integrity": "sha512-hx6xjj9j1VLaPGf+UhA9aBIx8cSRtW3ev71AQwKpBd8QdvhuHpjPSIt5q1XGhGH8FLR8poBh1XsuyeK8yadgMg==", + "peer": true, + "requires": { + "@pdfme/pdf-lib": "^1.18.3", + "bwip-js": "^4.1.1", + "fast-xml-parser": "^4.3.2", + "fontkit": "^2.0.2" } }, "@pkgr/core": { @@ -28233,72 +21770,6 @@ "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", "dev": true }, - "@pmmmwh/react-refresh-webpack-plugin": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.10.tgz", - "integrity": "sha512-j0Ya0hCFZPd4x40qLzbhGsh9TMtdb+CJQiso+WxLOPNasohq9cc5SNUcwsZaRH6++Xh91Xkm/xHCkuIiIu0LUA==", - "requires": { - "ansi-html-community": "^0.0.8", - "common-path-prefix": "^3.0.0", - "core-js-pure": "^3.23.3", - "error-stack-parser": "^2.0.6", - "find-up": "^5.0.0", - "html-entities": "^2.1.0", - "loader-utils": "^2.0.4", - "schema-utils": "^3.0.0", - "source-map": "^0.7.3" - }, - "dependencies": { - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "requires": { - "p-locate": "^5.0.0" - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "requires": { - "p-limit": "^3.0.2" - } - }, - "source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==" - } - } - }, "@polka/url": { "version": "1.0.0-next.21", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz", @@ -28311,17 +21782,17 @@ "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==" }, "@react-aria/ssr": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.7.0.tgz", - "integrity": "sha512-bfufjg4ESE5giN+Fxj1XIzS5f/YIhqcGc+Ve+vUUKU8xZ8t/Xtjlv8F3kjqDBQdk//n3mluFY7xG1wQVB9rMLQ==", + "version": "3.9.5", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.5.tgz", + "integrity": "sha512-xEwGKoysu+oXulibNUSkXf8itW0npHHTa6c4AyYeZIJyRoegeteYuFpZUBPtIDE8RfHdNsSmE1ssOkxRnwbkuQ==", "requires": { "@swc/helpers": "^0.5.0" }, "dependencies": { "@swc/helpers": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.1.tgz", - "integrity": "sha512-sJ902EfIzn1Fa+qYmjdQqh8tPsoxyBz+8yBKC2HKUxyezKJFwPGOn7pv4WY6QuQW//ySQi5lJjA/ZT9sNWWNTg==", + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.12.tgz", + "integrity": "sha512-KMZNXiGibsW9kvZAO1Pam2JPTDBm+KSHMMHWdsyI/1DbIZjT2A6Gy3hblVXUMEDvUAKq+e0vL0X0o54owWji7g==", "requires": { "tslib": "^2.4.0" } @@ -28329,70 +21800,82 @@ } }, "@react-spring/animated": { - "version": "9.7.3", - "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.3.tgz", - "integrity": "sha512-5CWeNJt9pNgyvuSzQH+uy2pvTg8Y4/OisoscZIR8/ZNLIOI+CatFBhGZpDGTF/OzdNFsAoGk3wiUYTwoJ0YIvw==", + "version": "9.7.4", + "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.4.tgz", + "integrity": "sha512-7As+8Pty2QlemJ9O5ecsuPKjmO0NKvmVkRR1n6mEotFgWar8FKuQt2xgxz3RTgxcccghpx1YdS1FCdElQNexmQ==", "requires": { - "@react-spring/shared": "~9.7.3", - "@react-spring/types": "~9.7.3" + "@react-spring/shared": "~9.7.4", + "@react-spring/types": "~9.7.4" } }, "@react-spring/core": { - "version": "9.7.3", - "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.7.3.tgz", - "integrity": "sha512-IqFdPVf3ZOC1Cx7+M0cXf4odNLxDC+n7IN3MDcVCTIOSBfqEcBebSv+vlY5AhM0zw05PDbjKrNmBpzv/AqpjnQ==", + "version": "9.7.4", + "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.7.4.tgz", + "integrity": "sha512-GzjA44niEJBFUe9jN3zubRDDDP2E4tBlhNlSIkTChiNf9p4ZQlgXBg50qbXfSXHQPHak/ExYxwhipKVsQ/sUTw==", "requires": { - "@react-spring/animated": "~9.7.3", - "@react-spring/shared": "~9.7.3", - "@react-spring/types": "~9.7.3" + "@react-spring/animated": "~9.7.4", + "@react-spring/shared": "~9.7.4", + "@react-spring/types": "~9.7.4" } }, "@react-spring/rafz": { - "version": "9.7.3", - "resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.7.3.tgz", - "integrity": "sha512-9vzW1zJPcC4nS3aCV+GgcsK/WLaB520Iyvm55ARHfM5AuyBqycjvh1wbmWmgCyJuX4VPoWigzemq1CaaeRSHhQ==" + "version": "9.7.4", + "resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.7.4.tgz", + "integrity": "sha512-mqDI6rW0Ca8IdryOMiXRhMtVGiEGLIO89vIOyFQXRIwwIMX30HLya24g9z4olDvFyeDW3+kibiKwtZnA4xhldA==" }, "@react-spring/shared": { - "version": "9.7.3", - "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.7.3.tgz", - "integrity": "sha512-NEopD+9S5xYyQ0pGtioacLhL2luflh6HACSSDUZOwLHoxA5eku1UPuqcJqjwSD6luKjjLfiLOspxo43FUHKKSA==", + "version": "9.7.4", + "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.7.4.tgz", + "integrity": "sha512-bEPI7cQp94dOtCFSEYpxvLxj0+xQfB5r9Ru1h8OMycsIq7zFZon1G0sHrBLaLQIWeMCllc4tVDYRTLIRv70C8w==", "requires": { - "@react-spring/types": "~9.7.3" + "@react-spring/rafz": "~9.7.4", + "@react-spring/types": "~9.7.4" } }, "@react-spring/types": { - "version": "9.7.3", - "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.7.3.tgz", - "integrity": "sha512-Kpx/fQ/ZFX31OtlqVEFfgaD1ACzul4NksrvIgYfIFq9JpDHFwQkMVZ10tbo0FU/grje4rcL4EIrjekl3kYwgWw==" + "version": "9.7.4", + "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.7.4.tgz", + "integrity": "sha512-iQVztO09ZVfsletMiY+DpT/JRiBntdsdJ4uqk3UJFhrhS8mIC9ZOZbmfGSRs/kdbNPQkVyzucceDicQ/3Mlj9g==" }, "@react-spring/web": { - "version": "9.7.3", - "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.7.3.tgz", - "integrity": "sha512-BXt6BpS9aJL/QdVqEIX9YoUy8CE6TJrU0mNCqSoxdXlIeNcEBWOfIyE6B14ENNsyQKS3wOWkiJfco0tCr/9tUg==", + "version": "9.7.4", + "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.7.4.tgz", + "integrity": "sha512-UMvCZp7I5HCVIleSa4BwbNxynqvj+mJjG2m20VO2yPoi2pnCYANy58flvz9v/YcXTAvsmL655FV3pm5fbr6akA==", + "requires": { + "@react-spring/animated": "~9.7.4", + "@react-spring/core": "~9.7.4", + "@react-spring/shared": "~9.7.4", + "@react-spring/types": "~9.7.4" + } + }, + "@reduxjs/toolkit": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.2.7.tgz", + "integrity": "sha512-faI3cZbSdFb8yv9dhDTmGwclW0vk0z5o1cia+kf7gCbaCwHI5e+7tP57mJUv22pNcNbeA62GSrPpfrUfdXcQ6g==", "requires": { - "@react-spring/animated": "~9.7.3", - "@react-spring/core": "~9.7.3", - "@react-spring/shared": "~9.7.3", - "@react-spring/types": "~9.7.3" + "immer": "^10.0.3", + "redux": "^5.0.1", + "redux-thunk": "^3.1.0", + "reselect": "^5.1.0" } }, "@remix-run/router": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.18.0.tgz", - "integrity": "sha512-L3jkqmqoSVBVKHfpGZmLrex0lxR5SucGA0sUfFzGctehw+S/ggL9L/0NnC5mw6P8HUWpFZ3nQw3cRApjjWx9Sw==" + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.0.tgz", + "integrity": "sha512-zDICCLKEwbVYTS6TjYaWtHXxkdoUvD/QXvyVZjGCsWz5vyH7aFeONlPffPdW+Y/t6KT0MgXb2Mfjun9YpWN1dA==" }, "@restart/hooks": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.10.tgz", - "integrity": "sha512-HVZhYHb+9xnN6vDPyiTmw6N4V5wD9tatL3y0zpHFeeatP1ooOD1edzd3MnJCXYlb3OeleDg+Vv16EikGrH57eA==", + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.16.tgz", + "integrity": "sha512-f7aCv7c+nU/3mF7NWLtVVr0Ra80RqsO89hO72r+Y/nvQr5+q0UFGkocElTH6MJApvReVh6JHUFYn2cw1WdHF3w==", "requires": { "dequal": "^2.0.3" } }, "@restart/ui": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.6.6.tgz", - "integrity": "sha512-eC3puKuWE1SRYbojWHXnvCNHGgf3uzHCb6JOhnF4OXPibOIPEkR1sqDSkL643ydigxwh+ruCa1CmYHlzk7ikKA==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.8.0.tgz", + "integrity": "sha512-xJEOXUOTmT4FngTmhdjKFRrVVF0hwCLNPdatLCHkyS4dkiSK12cEu1Y0fjxktjJrdst9jJIc5J6ihMJCoWEN/g==", "requires": { "@babel/runtime": "^7.21.0", "@popperjs/core": "^2.11.6", @@ -28406,79 +21889,153 @@ }, "dependencies": { "uncontrollable": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-8.0.2.tgz", - "integrity": "sha512-/GDx+K1STGtpgTsj5Dj3J51YaKxZDblbCQHTH1zHLuoBEWodj6MjtRVv3TUijj1JYLRLSFsFzN8NV4M3QV4d9w==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-8.0.4.tgz", + "integrity": "sha512-ulRWYWHvscPFc0QQXvyJjY6LIXU56f0h8pQFvhxiKk5V1fcI8gp9Ht9leVAhrVjzqMw0BgjspBINx9r6oyJUvQ==", "requires": {} } } }, - "@rollup/plugin-babel": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", - "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", - "requires": { - "@babel/helper-module-imports": "^7.10.4", - "@rollup/pluginutils": "^3.1.0" - } + "@rollup/rollup-android-arm-eabi": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.3.tgz", + "integrity": "sha512-MmKSfaB9GX+zXl6E8z4koOr/xU63AMVleLEa64v7R0QF/ZloMs5vcD1sHgM64GXXS1csaJutG+ddtzcueI/BLg==", + "optional": true }, - "@rollup/plugin-node-resolve": { - "version": "11.2.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", - "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==", + "@rollup/rollup-android-arm64": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.3.tgz", + "integrity": "sha512-zrt8ecH07PE3sB4jPOggweBjJMzI1JG5xI2DIsUbkA+7K+Gkjys6eV7i9pOenNSDJH3eOr/jLb/PzqtmdwDq5g==", + "optional": true + }, + "@rollup/rollup-darwin-arm64": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.3.tgz", + "integrity": "sha512-P0UxIOrKNBFTQaXTxOH4RxuEBVCgEA5UTNV6Yz7z9QHnUJ7eLX9reOd/NYMO3+XZO2cco19mXTxDMXxit4R/eQ==", + "optional": true + }, + "@rollup/rollup-darwin-x64": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.3.tgz", + "integrity": "sha512-L1M0vKGO5ASKntqtsFEjTq/fD91vAqnzeaF6sfNAy55aD+Hi2pBI5DKwCO+UNDQHWsDViJLqshxOahXyLSh3EA==", + "optional": true + }, + "@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.3.tgz", + "integrity": "sha512-btVgIsCjuYFKUjopPoWiDqmoUXQDiW2A4C3Mtmp5vACm7/GnyuprqIDPNczeyR5W8rTXEbkmrJux7cJmD99D2g==", + "optional": true + }, + "@rollup/rollup-linux-arm-musleabihf": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.3.tgz", + "integrity": "sha512-zmjbSphplZlau6ZTkxd3+NMtE4UKVy7U4aVFMmHcgO5CUbw17ZP6QCgyxhzGaU/wFFdTfiojjbLG3/0p9HhAqA==", + "optional": true + }, + "@rollup/rollup-linux-arm64-gnu": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.3.tgz", + "integrity": "sha512-nSZfcZtAnQPRZmUkUQwZq2OjQciR6tEoJaZVFvLHsj0MF6QhNMg0fQ6mUOsiCUpTqxTx0/O6gX0V/nYc7LrgPw==", + "optional": true + }, + "@rollup/rollup-linux-arm64-musl": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.3.tgz", + "integrity": "sha512-MnvSPGO8KJXIMGlQDYfvYS3IosFN2rKsvxRpPO2l2cum+Z3exiExLwVU+GExL96pn8IP+GdH8Tz70EpBhO0sIQ==", + "optional": true + }, + "@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.3.tgz", + "integrity": "sha512-+W+p/9QNDr2vE2AXU0qIy0qQE75E8RTwTwgqS2G5CRQ11vzq0tbnfBd6brWhS9bCRjAjepJe2fvvkvS3dno+iw==", + "optional": true + }, + "@rollup/rollup-linux-riscv64-gnu": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.3.tgz", + "integrity": "sha512-yXH6K6KfqGXaxHrtr+Uoy+JpNlUlI46BKVyonGiaD74ravdnF9BUNC+vV+SIuB96hUMGShhKV693rF9QDfO6nQ==", + "optional": true + }, + "@rollup/rollup-linux-s390x-gnu": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.3.tgz", + "integrity": "sha512-R8cwY9wcnApN/KDYWTH4gV/ypvy9yZUHlbJvfaiXSB48JO3KpwSpjOGqO4jnGkLDSk1hgjYkTbTt6Q7uvPf8eg==", + "optional": true + }, + "@rollup/rollup-linux-x64-gnu": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.3.tgz", + "integrity": "sha512-kZPbX/NOPh0vhS5sI+dR8L1bU2cSO9FgxwM8r7wHzGydzfSjLRCFAT87GR5U9scj2rhzN3JPYVC7NoBbl4FZ0g==", + "optional": true + }, + "@rollup/rollup-linux-x64-musl": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.3.tgz", + "integrity": "sha512-S0Yq+xA1VEH66uiMNhijsWAafffydd2X5b77eLHfRmfLsRSpbiAWiRHV6DEpz6aOToPsgid7TI9rGd6zB1rhbg==", + "optional": true + }, + "@rollup/rollup-win32-arm64-msvc": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.3.tgz", + "integrity": "sha512-9isNzeL34yquCPyerog+IMCNxKR8XYmGd0tHSV+OVx0TmE0aJOo9uw4fZfUuk2qxobP5sug6vNdZR6u7Mw7Q+Q==", + "optional": true + }, + "@rollup/rollup-win32-ia32-msvc": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.3.tgz", + "integrity": "sha512-nMIdKnfZfzn1Vsk+RuOvl43ONTZXoAPUUxgcU0tXooqg4YrAqzfKzVenqqk2g5efWh46/D28cKFrOzDSW28gTA==", + "optional": true + }, + "@rollup/rollup-win32-x64-msvc": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.3.tgz", + "integrity": "sha512-fOvu7PCQjAj4eWDEuD8Xz5gpzFqXzGlxHZozHP4b9Jxv9APtdxL6STqztDzMLuRXEc4UpXGGhx029Xgm91QBeA==", + "optional": true + }, + "@shikijs/core": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.17.6.tgz", + "integrity": "sha512-9ztslig6/YmCg/XwESAXbKjAjOhaq6HVced9NY6qcbDz1X5g/S90Wco2vMjBNX/6V71ASkzri76JewSGPa7kiQ==", "requires": { - "@rollup/pluginutils": "^3.1.0", - "@types/resolve": "1.17.1", - "builtin-modules": "^3.1.0", - "deepmerge": "^4.2.2", - "is-module": "^1.0.0", - "resolve": "^1.19.0" + "@shikijs/engine-javascript": "1.17.6", + "@shikijs/engine-oniguruma": "1.17.6", + "@shikijs/types": "1.17.6", + "@shikijs/vscode-textmate": "^9.2.2", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.2" } }, - "@rollup/plugin-replace": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz", - "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==", + "@shikijs/engine-javascript": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.17.6.tgz", + "integrity": "sha512-5EEZj8tVcierNxm4V0UMS2PVoflb0UJPalWWV8l9rRg+oOfnr5VivqBJbkyq5grltVPvByIXvVbY8GSM/356jQ==", "requires": { - "@rollup/pluginutils": "^3.1.0", - "magic-string": "^0.25.7" + "@shikijs/types": "1.17.6", + "oniguruma-to-js": "0.4.3" } }, - "@rollup/pluginutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", - "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "@shikijs/engine-oniguruma": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.17.6.tgz", + "integrity": "sha512-NLfWDMXFYe0nDHFbEoyZdz89aIIey3bTfF3zLYSUNTXks5s4uinZVmuPOFf1HfTeGqIn8uErJSBc3VnpJO7Alw==", "requires": { - "@types/estree": "0.0.39", - "estree-walker": "^1.0.1", - "picomatch": "^2.2.2" - }, - "dependencies": { - "@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==" - } + "@shikijs/types": "1.17.6", + "@shikijs/vscode-textmate": "^9.2.2" } }, - "@rushstack/eslint-patch": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.3.2.tgz", - "integrity": "sha512-V+MvGwaHH03hYhY+k6Ef/xKd6RYlc4q8WBx+2ANmipHJcKuktNcI/NgEsJgdSUF6Lw32njT6OnrRsKYCdgHjYw==" - }, - "@shikijs/core": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.10.3.tgz", - "integrity": "sha512-D45PMaBaeDHxww+EkcDQtDAtzv00Gcsp72ukBtaLSmqRvh0WgGMq3Al0rl1QQBZfuneO75NXMIzEZGFitThWbg==", - "peer": true, + "@shikijs/types": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.17.6.tgz", + "integrity": "sha512-ndTFa2TJi2w51ddKQDn3Jy8f6K4E5Q2x3dA3Hmsd3+YmxDQ10UWHjcw7VbVbKzv3VcUvYPLy+z9neqytSzUMUg==", "requires": { + "@shikijs/vscode-textmate": "^9.2.2", "@types/hast": "^3.0.4" } }, - "@sinclair/typebox": { - "version": "0.24.51", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", - "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==" + "@shikijs/vscode-textmate": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-9.2.2.tgz", + "integrity": "sha512-TMp15K+GGYrWlZM8+Lnj9EaHEFmOen0WJBrfa17hF7taDOYthuPPV0GWzfd/9iMij0akS/8Yw2ikquH7uVi/fg==" }, "@sindresorhus/is": { "version": "0.14.0", @@ -28490,6 +22047,7 @@ "version": "1.8.6", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "dev": true, "requires": { "type-detect": "4.0.8" } @@ -28498,21 +22056,11 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", + "dev": true, "requires": { "@sinonjs/commons": "^1.7.0" } }, - "@surma/rollup-plugin-off-main-thread": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", - "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==", - "requires": { - "ejs": "^3.1.6", - "json5": "^2.2.0", - "magic-string": "^0.25.0", - "string.prototype.matchall": "^4.0.6" - } - }, "@svgr/babel-plugin-add-jsx-attribute": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.5.1.tgz", @@ -28628,132 +22176,6 @@ "svg-parser": "^2.0.4" } }, - "@svgr/plugin-svgo": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-5.5.0.tgz", - "integrity": "sha512-r5swKk46GuQl4RrVejVwpeeJaydoxkdwkM1mBKOgJLBUJPGaLci6ylg/IjhrRsREKDkr4kbMWdgOtbXEh0fyLQ==", - "requires": { - "cosmiconfig": "^7.0.0", - "deepmerge": "^4.2.2", - "svgo": "^1.2.2" - } - }, - "@svgr/webpack": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-5.5.0.tgz", - "integrity": "sha512-DOBOK255wfQxguUta2INKkzPj6AIS6iafZYiYmHn6W3pHlycSRRlvWKCfLDG10fXfLWqE3DJHgRUOyJYmARa7g==", - "requires": { - "@babel/core": "^7.12.3", - "@babel/plugin-transform-react-constant-elements": "^7.12.1", - "@babel/preset-env": "^7.12.1", - "@babel/preset-react": "^7.12.5", - "@svgr/core": "^5.5.0", - "@svgr/plugin-jsx": "^5.5.0", - "@svgr/plugin-svgo": "^5.5.0", - "loader-utils": "^2.0.0" - }, - "dependencies": { - "@svgr/babel-plugin-add-jsx-attribute": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz", - "integrity": "sha512-ZFf2gs/8/6B8PnSofI0inYXr2SDNTDScPXhN7k5EqD4aZ3gi6u+rbmZHVB8IM3wDyx8ntKACZbtXSm7oZGRqVg==" - }, - "@svgr/babel-plugin-remove-jsx-attribute": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-5.4.0.tgz", - "integrity": "sha512-yaS4o2PgUtwLFGTKbsiAy6D0o3ugcUhWK0Z45umJ66EPWunAz9fuFw2gJuje6wqQvQWOTJvIahUwndOXb7QCPg==" - }, - "@svgr/babel-plugin-remove-jsx-empty-expression": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-5.0.1.tgz", - "integrity": "sha512-LA72+88A11ND/yFIMzyuLRSMJ+tRKeYKeQ+mR3DcAZ5I4h5CPWN9AHyUzJbWSYp/u2u0xhmgOe0+E41+GjEueA==" - }, - "@svgr/babel-plugin-replace-jsx-attribute-value": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-5.0.1.tgz", - "integrity": "sha512-PoiE6ZD2Eiy5mK+fjHqwGOS+IXX0wq/YDtNyIgOrc6ejFnxN4b13pRpiIPbtPwHEc+NT2KCjteAcq33/F1Y9KQ==" - }, - "@svgr/babel-plugin-svg-dynamic-title": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-5.4.0.tgz", - "integrity": "sha512-zSOZH8PdZOpuG1ZVx/cLVePB2ibo3WPpqo7gFIjLV9a0QsuQAzJiwwqmuEdTaW2pegyBE17Uu15mOgOcgabQZg==" - }, - "@svgr/babel-plugin-svg-em-dimensions": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-5.4.0.tgz", - "integrity": "sha512-cPzDbDA5oT/sPXDCUYoVXEmm3VIoAWAPT6mSPTJNbQaBNUuEKVKyGH93oDY4e42PYHRW67N5alJx/eEol20abw==" - }, - "@svgr/babel-plugin-transform-react-native-svg": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-5.4.0.tgz", - "integrity": "sha512-3eYP/SaopZ41GHwXma7Rmxcv9uRslRDTY1estspeB1w1ueZWd/tPlMfEOoccYpEMZU3jD4OU7YitnXcF5hLW2Q==" - }, - "@svgr/babel-plugin-transform-svg-component": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-5.5.0.tgz", - "integrity": "sha512-q4jSH1UUvbrsOtlo/tKcgSeiCHRSBdXoIoqX1pgcKK/aU3JD27wmMKwGtpB8qRYUYoyXvfGxUVKchLuR5pB3rQ==" - }, - "@svgr/babel-preset": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-5.5.0.tgz", - "integrity": "sha512-4FiXBjvQ+z2j7yASeGPEi8VD/5rrGQk4Xrq3EdJmoZgz/tpqChpo5hgXDvmEauwtvOc52q8ghhZK4Oy7qph4ig==", - "requires": { - "@svgr/babel-plugin-add-jsx-attribute": "^5.4.0", - "@svgr/babel-plugin-remove-jsx-attribute": "^5.4.0", - "@svgr/babel-plugin-remove-jsx-empty-expression": "^5.0.1", - "@svgr/babel-plugin-replace-jsx-attribute-value": "^5.0.1", - "@svgr/babel-plugin-svg-dynamic-title": "^5.4.0", - "@svgr/babel-plugin-svg-em-dimensions": "^5.4.0", - "@svgr/babel-plugin-transform-react-native-svg": "^5.4.0", - "@svgr/babel-plugin-transform-svg-component": "^5.5.0" - } - }, - "@svgr/core": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/core/-/core-5.5.0.tgz", - "integrity": "sha512-q52VOcsJPvV3jO1wkPtzTuKlvX7Y3xIcWRpCMtBF3MrteZJtBfQw/+u0B1BHy5ColpQc1/YVTrPEtSYIMNZlrQ==", - "requires": { - "@svgr/plugin-jsx": "^5.5.0", - "camelcase": "^6.2.0", - "cosmiconfig": "^7.0.0" - } - }, - "@svgr/hast-util-to-babel-ast": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-5.5.0.tgz", - "integrity": "sha512-cAaR/CAiZRB8GP32N+1jocovUtvlj0+e65TB50/6Lcime+EA49m/8l+P2ko+XPJ4dw3xaPS3jOL4F2X4KWxoeQ==", - "requires": { - "@babel/types": "^7.12.6" - } - }, - "@svgr/plugin-jsx": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-5.5.0.tgz", - "integrity": "sha512-V/wVh33j12hGh05IDg8GpIUXbjAPnTdPTKuP4VNLggnwaHMPNQNae2pRnyTAILWCQdz5GyMqtO488g7CKM8CBA==", - "requires": { - "@babel/core": "^7.12.3", - "@svgr/babel-preset": "^5.5.0", - "@svgr/hast-util-to-babel-ast": "^5.5.0", - "svg-parser": "^2.0.2" - } - }, - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" - }, - "loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - } - } - }, "@swc/helpers": { "version": "0.4.14", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", @@ -28772,68 +22194,93 @@ } }, "@testing-library/dom": { - "version": "7.31.2", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.31.2.tgz", - "integrity": "sha512-3UqjCpey6HiTZT92vODYLPxTBWlM8ZOOjr3LX5F37/VRipW2M1kX6I/Cm4VXzteZqfGfagg8yXywpcOgQBlNsQ==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", + "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", "dev": true, + "peer": true, "requires": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", - "@types/aria-query": "^4.2.0", - "aria-query": "^4.2.2", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.6", - "lz-string": "^1.4.4", - "pretty-format": "^26.6.2" + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" }, "dependencies": { - "aria-query": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", - "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", - "dev": true, - "requires": { - "@babel/runtime": "^7.10.2", - "@babel/runtime-corejs3": "^7.10.2" - } - }, "chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "peer": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "peer": true, + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "peer": true + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true, + "peer": true } } }, "@testing-library/jest-dom": { - "version": "5.16.5", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz", - "integrity": "sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.5.0.tgz", + "integrity": "sha512-xGGHpBXYSHUUr6XsKBfs85TWlYKpTc37cSBBVrXcib2MkHLboWlkClhWF37JKlDb9KEq3dHs+f2xR7XJEWGBxA==", "dev": true, "requires": { - "@adobe/css-tools": "^4.0.1", - "@babel/runtime": "^7.9.2", - "@types/testing-library__jest-dom": "^5.9.1", + "@adobe/css-tools": "^4.4.0", "aria-query": "^5.0.0", "chalk": "^3.0.0", "css.escape": "^1.5.1", - "dom-accessibility-api": "^0.5.6", - "lodash": "^4.17.15", + "dom-accessibility-api": "^0.6.3", + "lodash": "^4.17.21", "redent": "^3.0.0" + }, + "dependencies": { + "dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true + } } }, "@testing-library/react": { - "version": "11.2.7", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-11.2.7.tgz", - "integrity": "sha512-tzRNp7pzd5QmbtXNG/mhdcl7Awfu/Iz1RaVHY75zTdOkmHCuzMhRL83gWHSgOAcjS3CCbyfwUHMZgRJb4kAfpA==", + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.0.0.tgz", + "integrity": "sha512-guuxUKRWQ+FgNX0h0NS0FIq3Q3uLtWVpBzcLOggmfMoUpgBnzBzvLLd4fbm6yS8ydJd94cIfY4yP9qUQjM2KwQ==", "dev": true, "requires": { - "@babel/runtime": "^7.12.5", - "@testing-library/dom": "^7.28.1" + "@babel/runtime": "^7.12.5" } }, "@testing-library/user-event": { @@ -28848,23 +22295,20 @@ "@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==" - }, - "@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==" + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true }, "@types/aria-query": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz", - "integrity": "sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==", - "dev": true + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true, + "peer": true }, "@types/babel__core": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", - "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "requires": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", @@ -28898,89 +22342,72 @@ "@babel/types": "^7.20.7" } }, - "@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "requires": { - "@types/connect": "*", - "@types/node": "*" - } + "@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==" + }, + "@types/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==" }, - "@types/bonjour": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz", - "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==", + "@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", "requires": { - "@types/node": "*" + "@types/d3-color": "*" } }, - "@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "@types/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==" + }, + "@types/d3-scale": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz", + "integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==", "requires": { - "@types/node": "*" + "@types/d3-time": "*" } }, - "@types/connect-history-api-fallback": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz", - "integrity": "sha512-4x5FkPpLipqwthjPsF7ZRbOv3uoLUFkTA9G9v583qi4pACvq0uTELrB8OLUzPWUI4IJIyvM85vzkV1nyiI2Lig==", + "@types/d3-shape": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.6.tgz", + "integrity": "sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==", "requires": { - "@types/express-serve-static-core": "*", - "@types/node": "*" + "@types/d3-path": "*" } }, + "@types/d3-time": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.3.tgz", + "integrity": "sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==" + }, "@types/eslint": { "version": "8.44.0", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.0.tgz", "integrity": "sha512-gsF+c/0XOguWgaOgvFs+xnnRqt9GwgTvIks36WpE6ueeI4KCEHHd8K/CKHqhOqrJKsYH8m27kRzQEvWXAwXUTw==", + "dev": true, + "optional": true, + "peer": true, "requires": { "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", - "requires": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "@types/estree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", - "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==" - }, - "@types/express": { - "version": "4.17.17", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", - "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "@types/express-serve-static-core": { - "version": "4.17.35", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", - "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", - "requires": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" + "@types/json-schema": "*" } }, + "@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + }, "@types/graceful-fs": { "version": "4.1.6", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", + "dev": true, "requires": { "@types/node": "*" } @@ -28989,7 +22416,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "peer": true, "requires": { "@types/unist": "*" } @@ -29001,32 +22427,14 @@ "dev": true }, "@types/hoist-non-react-statics": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", - "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz", + "integrity": "sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==", "requires": { "@types/react": "*", "hoist-non-react-statics": "^3.3.0" } }, - "@types/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" - }, - "@types/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==" - }, - "@types/http-proxy": { - "version": "1.17.11", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.11.tgz", - "integrity": "sha512-HC8G7c1WmaF2ekqpnFq626xd3Zz0uvaqFmBJNRZCGEZCXkvSdJoNFn/8Ygbd9fKNQj8UzLdCETaI0UWPAjK7IA==", - "requires": { - "@types/node": "*" - } - }, "@types/inquirer": { "version": "9.0.7", "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-9.0.7.tgz", @@ -29040,12 +22448,14 @@ "@types/istanbul-lib-coverage": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==" + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true }, "@types/istanbul-lib-report": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, "requires": { "@types/istanbul-lib-coverage": "*" } @@ -29054,6 +22464,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, "requires": { "@types/istanbul-lib-report": "*" } @@ -29082,26 +22493,24 @@ "@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" - }, - "@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true }, - "@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "optional": true, - "peer": true + "@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "requires": { + "@types/unist": "*" + } }, "@types/node": { - "version": "20.12.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz", - "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==", + "version": "22.5.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz", + "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", + "devOptional": true, "requires": { - "undici-types": "~5.26.4" + "undici-types": "~6.19.2" } }, "@types/node-fetch": { @@ -29127,13 +22536,6 @@ } } }, - "@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "optional": true, - "peer": true - }, "@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", @@ -29142,35 +22544,20 @@ "@types/prettier": { "version": "2.7.3", "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", - "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==" + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", + "dev": true }, "@types/prop-types": { "version": "15.7.12", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" }, - "@types/q": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz", - "integrity": "sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ==" - }, - "@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" - }, - "@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" - }, "@types/react": { - "version": "17.0.62", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.62.tgz", - "integrity": "sha512-eANCyz9DG8p/Vdhr0ZKST8JV12PhH2ACCDYlFw6DIO+D+ca+uP4jtEDEpVqXZrh/uZdXQGwk7whJa3ah5DtyLw==", + "version": "18.3.3", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", + "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", "requires": { "@types/prop-types": "*", - "@types/scheduler": "*", "csstype": "^3.0.2" } }, @@ -29193,24 +22580,21 @@ } }, "@types/react-datepicker": { - "version": "4.11.2", - "resolved": "https://registry.npmjs.org/@types/react-datepicker/-/react-datepicker-4.11.2.tgz", - "integrity": "sha512-ELYyX3lb3K1WltqdlF1hbnaDGgzlF6PIR5T4W38cSEcfrQDIrPE+Ioq5pwRe/KEJ+ihHMjvTVZQkwJx0pWMNHQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@types/react-datepicker/-/react-datepicker-7.0.0.tgz", + "integrity": "sha512-4tWwOUq589tozyQPBVEqGNng5DaZkomx5IVNuur868yYdgjH6RaL373/HKiVt1IDoNNXYiTGspm1F7kjrarM8Q==", "dev": true, "requires": { - "@popperjs/core": "^2.9.2", - "@types/react": "*", - "date-fns": "^2.0.1", - "react-popper": "^2.2.5" + "react-datepicker": "*" } }, "@types/react-dom": { - "version": "17.0.20", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.20.tgz", - "integrity": "sha512-4pzIjSxDueZZ90F52mU3aPoogkHIoSIDG+oQ+wQK7Cy2B9S+MvOqY0uEA/qawKz381qrEDkvpwyt8Bm31I8sbA==", + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", "dev": true, "requires": { - "@types/react": "^17" + "@types/react": "*" } }, "@types/react-google-recaptcha": { @@ -29223,14 +22607,24 @@ } }, "@types/react-redux": { - "version": "7.1.25", - "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.25.tgz", - "integrity": "sha512-bAGh4e+w5D8dajd6InASVIyCo4pZLJ66oLb80F9OBLO1gKESbZcRCJpTT6uLXX+HAB57zw1WTdwJdAsewuTweg==", + "version": "7.1.34", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.34.tgz", + "integrity": "sha512-GdFaVjEbYv4Fthm2ZLvj1VSCedV7TqE5y1kNwnjSdBOTXuRSgowux6J8TAct15T3CKBr63UMk+2CO7ilRhyrAQ==", "requires": { "@types/hoist-non-react-statics": "^3.3.0", "@types/react": "*", "hoist-non-react-statics": "^3.3.0", "redux": "^4.0.0" + }, + "dependencies": { + "redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "requires": { + "@babel/runtime": "^7.9.2" + } + } } }, "@types/react-router": { @@ -29262,86 +22656,20 @@ "@types/react": "*" } }, - "@types/resolve": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", - "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", - "requires": { - "@types/node": "*" - } - }, - "@types/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" - }, "@types/sanitize-html": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/@types/sanitize-html/-/sanitize-html-2.11.0.tgz", - "integrity": "sha512-7oxPGNQHXLHE48r/r/qjn7q0hlrs3kL7oZnGj0Wf/h9tj/6ibFyRkNbsDxaBBZ4XUZ0Dx5LGCyDJ04ytSofacQ==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/@types/sanitize-html/-/sanitize-html-2.13.0.tgz", + "integrity": "sha512-X31WxbvW9TjIhZZNyNBZ/p5ax4ti7qsNDBDEnH4zAgmEh35YnFD1UiS6z9Cd34kKm0LslFW0KPmTQzu/oGtsqQ==", "dev": true, "requires": { "htmlparser2": "^8.0.0" } }, - "@types/scheduler": { - "version": "0.16.3", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", - "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==" - }, - "@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==" - }, - "@types/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", - "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", - "requires": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "@types/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", - "requires": { - "@types/express": "*" - } - }, - "@types/serve-static": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", - "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", - "requires": { - "@types/http-errors": "*", - "@types/mime": "*", - "@types/node": "*" - } - }, - "@types/sockjs": { - "version": "0.3.33", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", - "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", - "requires": { - "@types/node": "*" - } - }, "@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" - }, - "@types/testing-library__jest-dom": { - "version": "5.14.8", - "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.8.tgz", - "integrity": "sha512-NRfJE9Cgpmu4fx716q9SYmU4jxxhYRU1BQo239Txt/9N3EC745XZX1Yl7h/SBIDlo1ANVOCRB4YDXjaQdoKCHQ==", - "dev": true, - "requires": { - "@types/jest": "*" - } + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true }, "@types/through": { "version": "0.0.33", @@ -29352,34 +22680,26 @@ "@types/node": "*" } }, - "@types/trusted-types": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.3.tgz", - "integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==" - }, "@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "peer": true + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==" }, - "@types/warning": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.0.tgz", - "integrity": "sha512-t/Tvs5qR47OLOr+4E9ckN8AmP2Tf16gWq+/qA4iUGS/OOyHVO8wv2vjJuX8SNOUTJyWb+2t7wJm6cXILFnOROA==" + "@types/use-sync-external-store": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", + "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" }, - "@types/ws": { - "version": "8.5.5", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz", - "integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==", - "requires": { - "@types/node": "*" - } + "@types/warning": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.3.tgz", + "integrity": "sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q==" }, "@types/yargs": { "version": "16.0.5", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.5.tgz", "integrity": "sha512-AxO/ADJOBFJScHbWhq2xAhlWP24rY4aCEG/NFaMvbT3X2MgRsLjhjQwsn0Zi5zn0LG9jUhCCZMeX9Dkuw6k+vQ==", + "dev": true, "requires": { "@types/yargs-parser": "*" } @@ -29387,302 +22707,334 @@ "@types/yargs-parser": { "version": "21.0.0", "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", - "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", - "requires": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/type-utils": "5.62.0", - "@typescript-eslint/utils": "5.62.0", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/experimental-utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.62.0.tgz", - "integrity": "sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.5.0.tgz", + "integrity": "sha512-lHS5hvz33iUFQKuPFGheAB84LwcJ60G8vKnEhnfcK1l8kGVLro2SFYW6K0/tj8FUhRJ0VHyg1oAfg50QGbPPHw==", + "dev": true, "requires": { - "@typescript-eslint/utils": "5.62.0" + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.5.0", + "@typescript-eslint/type-utils": "8.5.0", + "@typescript-eslint/utils": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.5.0.tgz", + "integrity": "sha512-06JOQ9Qgj33yvBEx6tpC8ecP9o860rsR22hWMEd12WcTRrfaFgHr2RB/CA/B+7BMhHkXT4chg2MyboGdFGawYg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0" + } + }, + "@typescript-eslint/types": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.5.0.tgz", + "integrity": "sha512-qjkormnQS5wF9pjSi6q60bKUHH44j2APxfh9TQRXK8wbYVeDYYdYJGIROL87LGZZ2gz3Rbmjc736qyL8deVtdw==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.5.0.tgz", + "integrity": "sha512-vEG2Sf9P8BPQ+d0pxdfndw3xIXaoSjliG0/Ejk7UggByZPKXmJmw3GW5jV2gHNQNawBUyfahoSiCFVov0Ruf7Q==", + "dev": true, + "requires": { + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + } + }, + "@typescript-eslint/utils": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.5.0.tgz", + "integrity": "sha512-6yyGYVL0e+VzGYp60wvkBHiqDWOpT63pdMV2CVG4LVDd5uR6q1qQN/7LafBZtAtNIn/mqXjsSeS5ggv/P0iECw==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.5.0", + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/typescript-estree": "8.5.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.5.0.tgz", + "integrity": "sha512-yTPqMnbAZJNy2Xq2XU8AdtOW9tJIr+UQb64aXB9f3B1498Zx9JorVgFJcZpEc9UBuCCrdzKID2RGAMkYcDtZOw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "8.5.0", + "eslint-visitor-keys": "^3.4.3" + } + }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } } }, "@typescript-eslint/parser": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", - "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.5.0.tgz", + "integrity": "sha512-gF77eNv0Xz2UJg/NbpWJ0kqAm35UMsvZf1GHj8D9MRFTj/V3tAciIWXfmPLsAAF/vUlpWPvUDyH1jjsr0cMVWw==", + "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/scope-manager": "8.5.0", + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/typescript-estree": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0", "debug": "^4.3.4" - } - }, - "@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", - "requires": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.5.0.tgz", + "integrity": "sha512-06JOQ9Qgj33yvBEx6tpC8ecP9o860rsR22hWMEd12WcTRrfaFgHr2RB/CA/B+7BMhHkXT4chg2MyboGdFGawYg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0" + } + }, + "@typescript-eslint/types": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.5.0.tgz", + "integrity": "sha512-qjkormnQS5wF9pjSi6q60bKUHH44j2APxfh9TQRXK8wbYVeDYYdYJGIROL87LGZZ2gz3Rbmjc736qyL8deVtdw==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.5.0.tgz", + "integrity": "sha512-vEG2Sf9P8BPQ+d0pxdfndw3xIXaoSjliG0/Ejk7UggByZPKXmJmw3GW5jV2gHNQNawBUyfahoSiCFVov0Ruf7Q==", + "dev": true, + "requires": { + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.5.0.tgz", + "integrity": "sha512-yTPqMnbAZJNy2Xq2XU8AdtOW9tJIr+UQb64aXB9f3B1498Zx9JorVgFJcZpEc9UBuCCrdzKID2RGAMkYcDtZOw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "8.5.0", + "eslint-visitor-keys": "^3.4.3" + } + }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } } }, "@typescript-eslint/type-utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", - "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", - "requires": { - "@typescript-eslint/typescript-estree": "5.62.0", - "@typescript-eslint/utils": "5.62.0", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==" - }, - "@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.5.0.tgz", + "integrity": "sha512-N1K8Ix+lUM+cIDhL2uekVn/ZD7TZW+9/rwz8DclQpcQ9rk4sIL5CAlBC0CugWKREmDjBzI/kQqU4wkg46jWLYA==", + "dev": true, "requires": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", + "@typescript-eslint/typescript-estree": "8.5.0", + "@typescript-eslint/utils": "8.5.0", "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", - "requires": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" - } - }, - "@webassemblyjs/ast": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", - "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", - "requires": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" - }, - "@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" - }, - "@webassemblyjs/helper-buffer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", - "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==" - }, - "@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", - "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", - "requires": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" - }, - "@webassemblyjs/wasm-edit": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", - "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", - "requires": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-opt": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6", - "@webassemblyjs/wast-printer": "1.11.6" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", - "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", - "requires": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "ts-api-utils": "^1.3.0" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.5.0.tgz", + "integrity": "sha512-06JOQ9Qgj33yvBEx6tpC8ecP9o860rsR22hWMEd12WcTRrfaFgHr2RB/CA/B+7BMhHkXT4chg2MyboGdFGawYg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0" + } + }, + "@typescript-eslint/types": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.5.0.tgz", + "integrity": "sha512-qjkormnQS5wF9pjSi6q60bKUHH44j2APxfh9TQRXK8wbYVeDYYdYJGIROL87LGZZ2gz3Rbmjc736qyL8deVtdw==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.5.0.tgz", + "integrity": "sha512-vEG2Sf9P8BPQ+d0pxdfndw3xIXaoSjliG0/Ejk7UggByZPKXmJmw3GW5jV2gHNQNawBUyfahoSiCFVov0Ruf7Q==", + "dev": true, + "requires": { + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + } + }, + "@typescript-eslint/utils": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.5.0.tgz", + "integrity": "sha512-6yyGYVL0e+VzGYp60wvkBHiqDWOpT63pdMV2CVG4LVDd5uR6q1qQN/7LafBZtAtNIn/mqXjsSeS5ggv/P0iECw==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.5.0", + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/typescript-estree": "8.5.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.5.0.tgz", + "integrity": "sha512-yTPqMnbAZJNy2Xq2XU8AdtOW9tJIr+UQb64aXB9f3B1498Zx9JorVgFJcZpEc9UBuCCrdzKID2RGAMkYcDtZOw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "8.5.0", + "eslint-visitor-keys": "^3.4.3" + } + }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } } }, - "@webassemblyjs/wasm-opt": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", - "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", - "requires": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6" - } + "@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" }, - "@webassemblyjs/wasm-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", - "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "@vitejs/plugin-react": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.1.tgz", + "integrity": "sha512-m/V2syj5CuVnaxcUJOQRel/Wr31FFXRFlnOoq1TVtkCxsY5veGMTEmpWHndrhB2U8ScHtCQB1e+4hWYExQc6Lg==", "requires": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@babel/core": "^7.24.5", + "@babel/plugin-transform-react-jsx-self": "^7.24.5", + "@babel/plugin-transform-react-jsx-source": "^7.24.1", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.14.2" + }, + "dependencies": { + "react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==" + } } }, - "@webassemblyjs/wast-printer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", - "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "@wry/caches": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@wry/caches/-/caches-1.0.1.tgz", + "integrity": "sha512-bXuaUNLVVkD20wcGBWRyo7j9N3TxePEWFZj2Y+r9OoUzfqmavM84+mFykRicNsBqatba5JLay1t48wxaXaWnlA==", "requires": { - "@webassemblyjs/ast": "1.11.6", - "@xtuc/long": "4.2.2" + "tslib": "^2.3.0" } }, "@wry/context": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/@wry/context/-/context-0.7.3.tgz", - "integrity": "sha512-Nl8WTesHp89RF803Se9X3IiHjdmLBrIvPMaJkl+rKVJAYyPsz1TEUbu89943HpvujtSJgDUx9W4vZw3K1Mr3sA==", + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@wry/context/-/context-0.7.4.tgz", + "integrity": "sha512-jmT7Sb4ZQWI5iyu3lobQxICu2nC/vbUhP0vIdd6tHC9PTfenmRmuIFqktc6GH9cgi+ZHnsLWPvfSvc4DrYmKiQ==", "requires": { "tslib": "^2.3.0" } }, "@wry/equality": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/@wry/equality/-/equality-0.5.6.tgz", - "integrity": "sha512-D46sfMTngaYlrH+OspKf8mIJETntFnf6Hsjb0V41jAXJ7Bx2kB8Rv8RCUujuVWYttFtHkUNp7g+FwxNQAr6mXA==", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@wry/equality/-/equality-0.5.7.tgz", + "integrity": "sha512-BRFORjsTuQv5gxcXsuDXx6oGRhuVsEGwZy6LOzRRfgu+eSfxbhUQ9L9YtSEIuIjY/o7g3iWFjrc5eSY1GXP2Dw==", "requires": { "tslib": "^2.3.0" } }, "@wry/trie": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@wry/trie/-/trie-0.4.3.tgz", - "integrity": "sha512-I6bHwH0fSf6RqQcnnXLJKhkSXG45MFral3GxPaY4uAl0LYDZM+YDVDAiU9bYwjTuysy1S0IeecWtmq1SZA3M1w==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@wry/trie/-/trie-0.5.0.tgz", + "integrity": "sha512-FNoYzHawTMk/6KMQoEG5O4PuioX19UbwdQKF44yw0nLfOypfQdjtfZzo/UIJWAJ23sNIFbD1Ug9lbaDGMwbqQA==", "requires": { "tslib": "^2.3.0" } }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" - }, - "@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" - }, "abab": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==" - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "optional": true, - "peer": true - }, - "accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "requires": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - } + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "dev": true }, "acorn": { "version": "8.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==" + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "devOptional": true }, "acorn-globals": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "dev": true, "requires": { "acorn": "^7.1.1", "acorn-walk": "^7.1.1" @@ -29691,88 +23043,39 @@ "acorn": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true } } }, - "acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "requires": {} - }, "acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peer": true, "requires": {} }, "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.2", - "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", - "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==" - }, - "adjust-sourcemap-loader": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz", - "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==", - "requires": { - "loader-utils": "^2.0.0", - "regex-parser": "^2.2.11" - }, - "dependencies": { - "loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - } - } + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true }, "agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, "requires": { "debug": "4" } }, - "agentkeepalive": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.3.0.tgz", - "integrity": "sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==", - "optional": true, - "peer": true, - "requires": { - "debug": "^4.1.0", - "depd": "^2.0.0", - "humanize-ms": "^1.2.1" - } - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "optional": true, - "peer": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, "ajv": { "version": "8.12.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, "requires": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -29780,14 +23083,6 @@ "uri-js": "^4.2.2" } }, - "ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "requires": { - "ajv": "^8.0.0" - } - }, "ansi-align": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", @@ -29805,11 +23100,6 @@ "type-fest": "^0.21.3" } }, - "ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==" - }, "ansi-red": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", @@ -29836,43 +23126,16 @@ "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", "integrity": "sha512-ZyznvL8k/FZeQHr2T6LzcJ/+vBApDnMNZvfVFy3At0knswWd6rJ3/0Hhmpu8oqa6C92npmozs890sX9Dl6q+Qw==" }, - "any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" - }, "anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "devOptional": true, "requires": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, - "aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "optional": true, - "peer": true - }, - "are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "optional": true, - "peer": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - } - }, - "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", @@ -29885,6 +23148,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, "requires": { "dequal": "^2.0.3" } @@ -29893,37 +23157,31 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, "requires": { "call-bind": "^1.0.5", "is-array-buffer": "^3.0.4" } }, - "array-flatten": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", - "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" - }, "array-includes": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", - "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", "is-string": "^1.0.7" } }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" - }, "array.prototype.findlast": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, "requires": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -29937,6 +23195,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", + "dev": true, "requires": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -29949,6 +23208,7 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, "requires": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -29960,29 +23220,7 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - } - }, - "array.prototype.reduce": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz", - "integrity": "sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.7" - } - }, - "array.prototype.toreversed": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", - "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", + "dev": true, "requires": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -29991,14 +23229,15 @@ } }, "array.prototype.tosorted": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz", - "integrity": "sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, "requires": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.1.0", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", "es-shim-unscopables": "^1.0.2" } }, @@ -30006,6 +23245,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, "requires": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.5", @@ -30017,61 +23257,11 @@ "is-shared-array-buffer": "^1.0.2" } }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "optional": true, - "peer": true - }, - "asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" - }, - "asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "optional": true, - "peer": true, - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "optional": true, - "peer": true - }, - "ast-types-flow": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==" - }, - "async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" - }, - "async-foreach": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", - "integrity": "sha512-VUeSMD8nEGBWaZK4lizI1sf3yEC7pnAQ/mrI7pC2fBz2s/tq5jWWEngTwaf0Gruu/OoXRGLGg1XFqpYBiGTYJA==", - "optional": true, - "peer": true - }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true }, "atob": { "version": "2.1.2", @@ -30086,105 +23276,178 @@ "gulp-header": "^1.7.1" } }, - "autoprefixer": { - "version": "10.4.14", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz", - "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==", - "requires": { - "browserslist": "^4.21.5", - "caniuse-lite": "^1.0.30001464", - "fraction.js": "^4.2.0", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", - "postcss-value-parser": "^4.2.0" - } - }, "available-typed-arrays": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, "requires": { "possible-typed-array-names": "^1.0.0" } }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", - "optional": true, - "peer": true - }, - "aws4": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", - "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", - "optional": true, - "peer": true - }, - "axe-core": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.2.tgz", - "integrity": "sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g==" - }, - "axobject-query": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", - "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", - "requires": { - "dequal": "^2.0.3" - } - }, - "babel-loader": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.3.0.tgz", - "integrity": "sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q==", + "babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, "requires": { - "find-cache-dir": "^3.3.1", - "loader-utils": "^2.0.0", - "make-dir": "^3.1.0", - "schema-utils": "^2.6.5" + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" }, "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "@sinclair/typebox": "^0.27.8" + } + }, + "@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "requires": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + } + }, + "@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "requires": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + } + }, + "@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + } + }, + "jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true + }, + "jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" } }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "requires": {} - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, - "schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, "requires": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" } } } @@ -30193,6 +23456,7 @@ "version": "6.1.1", "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", "@istanbuljs/load-nyc-config": "^1.0.0", @@ -30201,6 +23465,18 @@ "test-exclude": "^6.0.0" } }, + "babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "requires": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + } + }, "babel-plugin-macros": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", @@ -30211,81 +23487,58 @@ "resolve": "^1.19.0" } }, - "babel-plugin-named-asset-import": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.8.tgz", - "integrity": "sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q==", - "requires": {} - }, "babel-plugin-polyfill-corejs2": { - "version": "0.4.8", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.8.tgz", - "integrity": "sha512-OtIuQfafSzpo/LhnJaykc0R/MMnuLSSVjVYy9mHArIZ9qTCSZ6TpWCuEKZYVoN//t8HqBNScHrOtCrIK5IaGLg==", + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "dev": true, "requires": { "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.5.0", + "@babel/helper-define-polyfill-provider": "^0.6.2", "semver": "^6.3.1" }, "dependencies": { - "@babel/helper-define-polyfill-provider": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", - "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", - "requires": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" - } - }, "semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true } } }, "babel-plugin-polyfill-corejs3": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.2.tgz", - "integrity": "sha512-Cid+Jv1BrY9ReW9lIfNlNpsI53N+FN7gE+f73zLAUbr9C52W4gKLWSByx47pfDJsEysojKArqOtOKZSVIIUTuQ==", + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", + "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "dev": true, "requires": { - "@babel/helper-define-polyfill-provider": "^0.4.1", - "core-js-compat": "^3.31.0" + "@babel/helper-define-polyfill-provider": "^0.6.2", + "core-js-compat": "^3.38.0" } }, "babel-plugin-polyfill-regenerator": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.5.tgz", - "integrity": "sha512-OJGYZlhLqBh2DDHeqAxWB1XIvr49CxiJ2gIt61/PU55CQK4Z58OzMqjDe1zwQdQk+rBYsRc+1rJmdajM3gimHg==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "dev": true, "requires": { - "@babel/helper-define-polyfill-provider": "^0.5.0" - }, - "dependencies": { - "@babel/helper-define-polyfill-provider": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", - "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", - "requires": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" - } - } + "@babel/helper-define-polyfill-provider": "^0.6.2" } }, - "babel-plugin-transform-react-remove-prop-types": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz", - "integrity": "sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==" + "babel-plugin-transform-import-meta": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-import-meta/-/babel-plugin-transform-import-meta-2.2.1.tgz", + "integrity": "sha512-AxNh27Pcg8Kt112RGa3Vod2QS2YXKKJ6+nSvRtv7qQTJAdx0MZa4UHZ4lnxHUWA2MNbLuZQv5FVab4P1CoLOWw==", + "requires": { + "@babel/template": "^7.4.4", + "tslib": "^2.4.0" + } }, "babel-preset-current-node-syntax": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, "requires": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", @@ -30301,27 +23554,14 @@ "@babel/plugin-syntax-top-level-await": "^7.8.3" } }, - "babel-preset-react-app": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-react-app/-/babel-preset-react-app-10.0.1.tgz", - "integrity": "sha512-b0D9IZ1WhhCWkrTXyFuIIgqGzSkRIH5D5AmB0bXbzYAB1OBAwHcUeyWW2LorutLWF5btNo/N7r/cIdmvvKJlYg==", - "requires": { - "@babel/core": "^7.16.0", - "@babel/plugin-proposal-class-properties": "^7.16.0", - "@babel/plugin-proposal-decorators": "^7.16.4", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.0", - "@babel/plugin-proposal-numeric-separator": "^7.16.0", - "@babel/plugin-proposal-optional-chaining": "^7.16.0", - "@babel/plugin-proposal-private-methods": "^7.16.0", - "@babel/plugin-transform-flow-strip-types": "^7.16.0", - "@babel/plugin-transform-react-display-name": "^7.16.0", - "@babel/plugin-transform-runtime": "^7.16.4", - "@babel/preset-env": "^7.16.4", - "@babel/preset-react": "^7.16.0", - "@babel/preset-typescript": "^7.16.0", - "@babel/runtime": "^7.16.3", - "babel-plugin-macros": "^3.1.0", - "babel-plugin-transform-react-remove-prop-types": "^0.4.24" + "babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "requires": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" } }, "balanced-match": { @@ -30334,41 +23574,11 @@ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, - "batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "optional": true, - "peer": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "bfj": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/bfj/-/bfj-7.0.2.tgz", - "integrity": "sha512-+e/UqUzwmzJamNF50tBV6tZPTORow7gQ96iFow+8b562OdMpEK0BcJEq2OSPEDmAbSMBQ7PKZ87ubFkgxpYWgw==", - "requires": { - "bluebird": "^3.5.5", - "check-types": "^11.1.1", - "hoopy": "^0.1.4", - "tryer": "^1.0.1" - } - }, - "big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" - }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "devOptional": true }, "bl": { "version": "4.1.0", @@ -30391,82 +23601,6 @@ } } }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, - "body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "dependencies": { - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "requires": { - "ee-first": "1.1.1" - } - } - } - }, - "bonjour-service": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.1.1.tgz", - "integrity": "sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg==", - "requires": { - "array-flatten": "^2.1.2", - "dns-equal": "^1.0.0", - "fast-deep-equal": "^3.1.3", - "multicast-dns": "^7.2.5" - } - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" - }, "bootstrap": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz", @@ -30517,6 +23651,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -30526,6 +23661,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "devOptional": true, "requires": { "fill-range": "^7.1.1" } @@ -30541,23 +23677,25 @@ "browser-process-hrtime": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", - "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==" + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", + "dev": true }, "browserslist": { - "version": "4.22.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz", - "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", "requires": { - "caniuse-lite": "^1.0.30001580", - "electron-to-chromium": "^1.4.648", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" } }, "bser": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, "requires": { "node-int64": "^0.4.0" } @@ -30566,6 +23704,7 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "peer": true, "requires": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" @@ -30576,20 +23715,11 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, - "builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==" - }, "bwip-js": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/bwip-js/-/bwip-js-3.4.3.tgz", - "integrity": "sha512-x+mQE/bq5V0Nlkn4Jd4cktNlEPH4zeIGSOEQNUtsV/cCJNiBba7u/S9PYR1pmD2WDeeZAIbYTjvGHjBQ21RXvw==" - }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==" + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/bwip-js/-/bwip-js-4.5.1.tgz", + "integrity": "sha512-83yQCKiIftz5YonnsTh6wIkFoHHWl+B/XaGWD1UdRw7aB6XP9JtyYP9n8sRy3m5rzL+Ch/RUPnu28UW0RrPZUA==", + "peer": true }, "cacheable-request": { "version": "6.1.0", @@ -30633,6 +23763,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, "requires": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -30646,64 +23777,21 @@ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" }, - "camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "requires": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" - }, - "camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==" - }, - "camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "optional": true, - "peer": true, - "requires": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - } - }, - "caniuse-api": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", - "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", - "requires": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - } + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true }, "caniuse-lite": { - "version": "1.0.30001587", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001587.tgz", - "integrity": "sha512-HMFNotUmLXn71BQxg8cijvqxnIAofforZOwGsxyXJ0qugTdspUF4sPSJ2vhgprHCB996tIDzEq1ubumPDV8ULA==" - }, - "case-sensitive-paths-webpack-plugin": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", - "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==" - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", - "optional": true, - "peer": true + "version": "1.0.30001660", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001660.tgz", + "integrity": "sha512-GacvNTTuATm26qC74pt+ad1fW15mlQ/zuTzzY1ZoIzECTP8HURDfF43kNxPgf7H1jmelCBQTTbBNxdSXOA7Bqg==" + }, + "ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==" }, "chalk": { "version": "3.0.0", @@ -30718,22 +23806,29 @@ "char-regex": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==" + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true + }, + "character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==" + }, + "character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==" }, "chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" }, - "check-types": { - "version": "11.2.2", - "resolved": "https://registry.npmjs.org/check-types/-/check-types-11.2.2.tgz", - "integrity": "sha512-HBiYvXvn9Z70Z88XKjz3AEKd4HJhBXsa3j7xFnITAzoS8+q6eIGi8qDB8FKPBAjtuxjI/zFpwuiCb8oDtKOYrA==" - }, "chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "devOptional": true, "requires": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -30745,55 +23840,23 @@ "readdirp": "~3.6.0" } }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "optional": true, - "peer": true - }, - "chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==" - }, "ci-info": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==" + "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "dev": true }, "cjs-module-lexer": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", - "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==" + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "dev": true }, "classnames": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" }, - "clean-css": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.2.tgz", - "integrity": "sha512-JVJbM+f3d3Q704rF4bqQ5UUyTtuJ0JRKNbTKVEeujCCBoMdkEi+V+e8oktO9qGQNSvHrFTM6JZRXrUvGR1czww==", - "requires": { - "source-map": "~0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "optional": true, - "peer": true - }, "cli-boxes": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", @@ -30801,12 +23864,12 @@ "dev": true }, "cli-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", - "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", "dev": true, "requires": { - "restore-cursor": "^4.0.0" + "restore-cursor": "^5.0.0" } }, "cli-spinners": { @@ -30837,9 +23900,9 @@ "dev": true }, "string-width": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", - "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "requires": { "emoji-regex": "^10.3.0", @@ -30867,6 +23930,7 @@ "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, "requires": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -30888,75 +23952,15 @@ } }, "clsx": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", - "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==" - }, - "coa": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", - "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", - "requires": { - "@types/q": "^1.5.1", - "chalk": "^2.4.1", - "q": "^1.1.2" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } - } + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true }, "coffee-script": { "version": "1.12.7", @@ -30966,7 +23970,17 @@ "collect-v8-coverage": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", - "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==" + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "requires": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + } }, "color-convert": { "version": "2.0.1", @@ -30977,102 +23991,50 @@ } }, "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==" - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "optional": true, - "peer": true + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "colord": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", - "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==" + "color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } }, "colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, "requires": { "delayed-stream": "~1.0.0" } }, + "comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==" + }, "commander": { "version": "9.5.0", "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", "dev": true }, - "common-path-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", - "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==" - }, - "common-tags": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", - "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==" - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==" - }, - "compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "requires": { - "mime-db": ">= 1.43.0 < 2" - } - }, - "compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "requires": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true }, "concat-stream": { "version": "1.6.2", @@ -31148,11 +24110,6 @@ "xdg-basedir": "^4.0.0" } }, - "confusing-browser-globals": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", - "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==" - }, "connect": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", @@ -31182,64 +24139,20 @@ } } }, - "connect-history-api-fallback": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", - "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==" - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "optional": true, - "peer": true - }, - "content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "requires": { - "safe-buffer": "5.2.1" - } - }, - "content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" - }, "convert-source-map": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" }, - "cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" - }, - "core-js": { - "version": "3.31.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.31.1.tgz", - "integrity": "sha512-2sKLtfq1eFST7l7v62zaqXacPc7uG8ZAya8ogijLhTtaKNcpzpB4TMoTw2Si+8GYKRwFPMMtUT0263QFWFfqyQ==" - }, "core-js-compat": { - "version": "3.36.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.0.tgz", - "integrity": "sha512-iV9Pd/PsgjNWBXeq8XRtWVSgz2tKAfhfvBs7qxYty+RlRd+OCksaWmOnc4JKrTc1cToXL1N0s3l/vwlxPtdElw==", + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", + "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==", + "dev": true, "requires": { - "browserslist": "^4.22.3" + "browserslist": "^4.23.3" } }, - "core-js-pure": { - "version": "3.31.1", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.31.1.tgz", - "integrity": "sha512-w+C62kvWti0EPs4KPMCMVv9DriHSXfQOCQ94bGGBiEW5rrbtt/Rz8n5Krhfw9cpFyzXBjf3DB3QnPdEzGDY4Fw==" - }, "core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", @@ -31278,6 +24191,7 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -31287,15 +24201,8 @@ "crypto-random-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" - }, - "css-blank-pseudo": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz", - "integrity": "sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ==", - "requires": { - "postcss-selector-parser": "^6.0.9" - } + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true }, "css-box-model": { "version": "1.2.1", @@ -31305,268 +24212,29 @@ "tiny-invariant": "^1.0.6" } }, - "css-declaration-sorter": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", - "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==", - "requires": {} - }, - "css-has-pseudo": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-3.0.4.tgz", - "integrity": "sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw==", - "requires": { - "postcss-selector-parser": "^6.0.9" - } - }, - "css-loader": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.8.1.tgz", - "integrity": "sha512-xDAXtEVGlD0gJ07iclwWVkLoZOpEvAWaSyf6W18S2pOC//K8+qUDIx8IIT3D+HjnmkJPQeesOPv5aiUaJsCM2g==", - "requires": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.21", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.3", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.3.8" - } - }, - "css-minimizer-webpack-plugin": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz", - "integrity": "sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==", - "requires": { - "cssnano": "^5.0.6", - "jest-worker": "^27.0.2", - "postcss": "^8.3.5", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0", - "source-map": "^0.6.1" - }, - "dependencies": { - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, - "css-prefers-color-scheme": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz", - "integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==", - "requires": {} - }, - "css-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", - "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", - "requires": { - "boolbase": "^1.0.0", - "css-what": "^3.2.1", - "domutils": "^1.7.0", - "nth-check": "^1.0.2" - }, - "dependencies": { - "css-what": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", - "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==" - }, - "dom-serializer": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", - "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", - "requires": { - "domelementtype": "^2.0.1", - "entities": "^2.0.0" - } - }, - "domutils": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", - "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", - "requires": { - "dom-serializer": "0", - "domelementtype": "1" - }, - "dependencies": { - "domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" - } - } - }, - "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" - }, - "nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", - "requires": { - "boolbase": "~1.0.0" - } - } - } - }, - "css-select-base-adapter": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", - "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==" - }, - "css-tree": { - "version": "1.0.0-alpha.37", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", - "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", - "requires": { - "mdn-data": "2.0.4", - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, - "css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==" - }, "css.escape": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", "dev": true }, - "cssdb": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.6.0.tgz", - "integrity": "sha512-Nna7rph8V0jC6+JBY4Vk4ndErUmfJfV6NJCaZdurL0omggabiy+QB2HCQtu5c/ACLZ0I7REv7A4QyPIoYzZx0w==" - }, "cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" - }, - "cssnano": { - "version": "5.1.15", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.15.tgz", - "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==", - "requires": { - "cssnano-preset-default": "^5.2.14", - "lilconfig": "^2.0.3", - "yaml": "^1.10.2" - } - }, - "cssnano-preset-default": { - "version": "5.2.14", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz", - "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==", - "requires": { - "css-declaration-sorter": "^6.3.1", - "cssnano-utils": "^3.1.0", - "postcss-calc": "^8.2.3", - "postcss-colormin": "^5.3.1", - "postcss-convert-values": "^5.1.3", - "postcss-discard-comments": "^5.1.2", - "postcss-discard-duplicates": "^5.1.0", - "postcss-discard-empty": "^5.1.1", - "postcss-discard-overridden": "^5.1.0", - "postcss-merge-longhand": "^5.1.7", - "postcss-merge-rules": "^5.1.4", - "postcss-minify-font-values": "^5.1.0", - "postcss-minify-gradients": "^5.1.1", - "postcss-minify-params": "^5.1.4", - "postcss-minify-selectors": "^5.2.1", - "postcss-normalize-charset": "^5.1.0", - "postcss-normalize-display-values": "^5.1.0", - "postcss-normalize-positions": "^5.1.1", - "postcss-normalize-repeat-style": "^5.1.1", - "postcss-normalize-string": "^5.1.0", - "postcss-normalize-timing-functions": "^5.1.0", - "postcss-normalize-unicode": "^5.1.1", - "postcss-normalize-url": "^5.1.0", - "postcss-normalize-whitespace": "^5.1.1", - "postcss-ordered-values": "^5.1.3", - "postcss-reduce-initial": "^5.1.2", - "postcss-reduce-transforms": "^5.1.0", - "postcss-svgo": "^5.1.0", - "postcss-unique-selectors": "^5.1.1" - } - }, - "cssnano-utils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", - "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", - "requires": {} - }, - "csso": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", - "requires": { - "css-tree": "^1.1.2" - }, - "dependencies": { - "css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", - "requires": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" - } - }, - "mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true }, "cssom": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", - "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==" + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", + "dev": true }, "cssstyle": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, "requires": { "cssom": "~0.3.6" }, @@ -31574,7 +24242,8 @@ "cssom": { "version": "0.3.8", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true } } }, @@ -31666,25 +24335,11 @@ "d3-time": "1 - 3" } }, - "damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==" - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", - "optional": true, - "peer": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, "data-urls": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "dev": true, "requires": { "abab": "^2.0.3", "whatwg-mimetype": "^2.3.0", @@ -31695,6 +24350,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, "requires": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -31705,6 +24361,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, "requires": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -31715,6 +24372,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, "requires": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -31725,55 +24383,30 @@ "version": "2.30.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", - "devOptional": true, + "optional": true, + "peer": true, "requires": { "@babel/runtime": "^7.21.0" } }, "dayjs": { - "version": "1.11.11", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz", - "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==" + "version": "1.11.12", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.12.tgz", + "integrity": "sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg==" }, "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "requires": { "ms": "2.1.2" } }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "optional": true, - "peer": true - }, - "decamelize-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", - "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", - "optional": true, - "peer": true, - "requires": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "dependencies": { - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "optional": true, - "peer": true - } - } - }, "decimal.js": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", - "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "dev": true }, "decompress-response": { "version": "3.3.0", @@ -31787,7 +24420,8 @@ "dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==" + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", + "dev": true }, "deep-extend": { "version": "0.6.0", @@ -31798,21 +24432,15 @@ "deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "peer": true }, "deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==" }, - "default-gateway": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", - "requires": { - "execa": "^5.0.0" - } - }, "defaults": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", @@ -31838,6 +24466,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, "requires": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -31847,12 +24476,14 @@ "define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==" + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true }, "define-properties": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, "requires": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", @@ -31870,63 +24501,26 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "optional": true, - "peer": true - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true }, "dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==" }, - "destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" - }, "detect-file": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", "integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==", "dev": true }, - "detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" - }, - "detect-port-alt": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", - "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", + "devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", "requires": { - "address": "^1.0.1", - "debug": "^2.6.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - } + "dequal": "^2.0.0" } }, "dfa": { @@ -31935,51 +24529,22 @@ "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==" }, "diacritics-map": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/diacritics-map/-/diacritics-map-0.1.0.tgz", - "integrity": "sha512-3omnDTYrGigU0i4cJjvaKwD52B8aoqyX/NEIkukFFkogBemsIbhSa1O414fpTp5nuszJG6lvQ5vBvDVNCbSsaQ==" - }, - "didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" - }, - "diff-sequences": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.6.2.tgz", - "integrity": "sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "requires": { - "path-type": "^4.0.0" - } - }, - "dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" - }, - "dns-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==" + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/diacritics-map/-/diacritics-map-0.1.0.tgz", + "integrity": "sha512-3omnDTYrGigU0i4cJjvaKwD52B8aoqyX/NEIkukFFkogBemsIbhSa1O414fpTp5nuszJG6lvQ5vBvDVNCbSsaQ==" }, - "dns-packet": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.0.tgz", - "integrity": "sha512-rza3UH1LwdHh9qyPXp8lkwpjSNk/AMD3dPytUoRoqnypDUhY0xvbdmVhWOfxO68frEfV9BU8V12Ez7ZsHGZpCQ==", - "requires": { - "@leichtgewicht/ip-codec": "^2.0.1" - } + "diff-sequences": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.6.2.tgz", + "integrity": "sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==", + "dev": true }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "peer": true, "requires": { "esutils": "^2.0.2" } @@ -31988,15 +24553,8 @@ "version": "0.5.16", "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", - "dev": true - }, - "dom-converter": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", - "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", - "requires": { - "utila": "~0.4" - } + "dev": true, + "peer": true }, "dom-helpers": { "version": "5.2.1", @@ -32026,6 +24584,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "dev": true, "requires": { "webidl-conversions": "^5.0.0" }, @@ -32033,7 +24592,8 @@ "webidl-conversions": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", - "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==" + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "dev": true } } }, @@ -32059,6 +24619,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, "requires": { "no-case": "^3.0.4", "tslib": "^2.0.3" @@ -32074,19 +24635,9 @@ } }, "dotenv": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", - "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==" - }, - "dotenv-expand": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", - "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==" - }, - "duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==" }, "duplexer3": { "version": "0.1.5", @@ -32094,54 +24645,28 @@ "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==", "dev": true }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "optional": true, - "peer": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "ejs": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz", - "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==", - "requires": { - "jake": "^10.8.5" - } + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true }, "electron-to-chromium": { - "version": "1.4.668", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.668.tgz", - "integrity": "sha512-ZOBocMYCehr9W31+GpMclR+KBaDZOoAEabLdhpZ8oU1JFDwIaFY0UDbpXVEUFc0BIP2O2Qn3rkfCjQmMR4T/bQ==" + "version": "1.5.19", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.19.tgz", + "integrity": "sha512-kpLJJi3zxTR1U828P+LIUDZ5ohixyo68/IcYOHLqnbTPr/wdgn4i1ECvmALN9E16JPA6cvCG5UG79gVwVdEK5w==" }, "emittery": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", - "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==" - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" - }, - "emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" + "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", + "dev": true }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true }, "encoding": { "version": "0.1.13", @@ -32162,33 +24687,16 @@ "once": "^1.4.0" } }, - "enhanced-resolve": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", - "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, "entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==" }, - "env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "optional": true, - "peer": true - }, - "err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "optional": true, - "peer": true + "environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true }, "error-ex": { "version": "1.3.2", @@ -32198,18 +24706,11 @@ "is-arrayish": "^0.2.1" } }, - "error-stack-parser": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", - "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", - "requires": { - "stackframe": "^1.3.4" - } - }, "es-abstract": { - "version": "1.23.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.2.tgz", - "integrity": "sha512-60s3Xv2T2p1ICykc7c+DNDPLDMm9t4QxCOUU0K9JxiLjM3C1zB9YVdN7tjxrFd4+AkZ8CdX1ovUga4P2+1e+/w==", + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, "requires": { "array-buffer-byte-length": "^1.0.1", "arraybuffer.prototype.slice": "^1.0.3", @@ -32250,24 +24751,20 @@ "safe-regex-test": "^1.0.3", "string.prototype.trim": "^1.2.9", "string.prototype.trimend": "^1.0.8", - "string.prototype.trimstart": "^1.0.7", + "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.2", "typed-array-byte-length": "^1.0.1", "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.5", + "typed-array-length": "^1.0.6", "unbox-primitive": "^1.0.2", "which-typed-array": "^1.1.15" } }, - "es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" - }, "es-define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, "requires": { "get-intrinsic": "^1.2.4" } @@ -32275,16 +24772,18 @@ "es-errors": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true }, "es-iterator-helpers": { - "version": "1.0.18", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.18.tgz", - "integrity": "sha512-scxAJaewsahbqTYrGKJihhViaM6DDZDDoucfvzNbK0pOren1g/daDQ3IAhzn+1G14rBG7w+i5N+qul60++zlKA==", + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", + "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", + "dev": true, "requires": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", + "es-abstract": "^1.23.3", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", @@ -32298,15 +24797,11 @@ "safe-array-concat": "^1.1.2" } }, - "es-module-lexer": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.0.tgz", - "integrity": "sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==" - }, "es-object-atoms": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, "requires": { "es-errors": "^1.3.0" } @@ -32315,6 +24810,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, "requires": { "get-intrinsic": "^1.2.4", "has-tostringtag": "^1.0.2", @@ -32325,6 +24821,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, "requires": { "hasown": "^2.0.0" } @@ -32333,6 +24830,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, "requires": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -32343,7 +24841,6 @@ "version": "0.21.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, "requires": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", @@ -32371,9 +24868,9 @@ } }, "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==" }, "escape-goat": { "version": "2.1.1", @@ -32384,7 +24881,8 @@ "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true }, "escape-string-regexp": { "version": "4.0.0", @@ -32395,6 +24893,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, "requires": { "esprima": "^4.0.1", "estraverse": "^5.2.0", @@ -32405,37 +24904,42 @@ "estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, "optional": true } } }, "eslint": { - "version": "8.45.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.45.0.tgz", - "integrity": "sha512-pd8KSxiQpdYRfYa9Wufvdoct3ZPQQuVuU5O6scNgMuOMYuxvH0IGaYK0wUFjo4UYYQQCUndlXiMbnxopwvvTiw==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "dev": true, + "peer": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.1.0", - "@eslint/js": "8.44.0", - "@humanwhocodes/config-array": "^0.11.10", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.1", - "espree": "^9.6.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -32463,6 +24967,8 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "peer": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -32473,21 +24979,27 @@ "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "peer": true }, "chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "eslint-scope": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.1.tgz", - "integrity": "sha512-CvefSOsDdaYYvxChovdrPo/ZGt8d5lrJWleAc1diXRKhHGiTYEI26cvo8Kle/wGnsizoCJjK73FMg1/IkIwiNA==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "peer": true, "requires": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -32496,12 +25008,16 @@ "estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "peer": true }, "find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "peer": true, "requires": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -32511,6 +25027,8 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "peer": true, "requires": { "is-glob": "^4.0.3" } @@ -32519,6 +25037,8 @@ "version": "13.20.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, + "peer": true, "requires": { "type-fest": "^0.20.2" } @@ -32527,6 +25047,8 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "peer": true, "requires": { "argparse": "^2.0.1" } @@ -32534,12 +25056,16 @@ "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "peer": true }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "peer": true, "requires": { "p-locate": "^5.0.0" } @@ -32548,6 +25074,8 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "peer": true, "requires": { "yocto-queue": "^0.1.0" } @@ -32556,6 +25084,8 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "peer": true, "requires": { "p-limit": "^3.0.2" } @@ -32563,7 +25093,9 @@ "type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "peer": true } } }, @@ -32574,31 +25106,11 @@ "dev": true, "requires": {} }, - "eslint-config-react-app": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-7.0.1.tgz", - "integrity": "sha512-K6rNzvkIeHaTd8m/QEh1Zko0KI7BACWkkneSs6s9cKZC/J27X3eZR6Upt1jkmZ/4FK+XUOPPxMEN7+lbUXfSlA==", - "requires": { - "@babel/core": "^7.16.0", - "@babel/eslint-parser": "^7.16.3", - "@rushstack/eslint-patch": "^1.1.0", - "@typescript-eslint/eslint-plugin": "^5.5.0", - "@typescript-eslint/parser": "^5.5.0", - "babel-preset-react-app": "^10.0.1", - "confusing-browser-globals": "^1.0.11", - "eslint-plugin-flowtype": "^8.0.3", - "eslint-plugin-import": "^2.25.3", - "eslint-plugin-jest": "^25.3.0", - "eslint-plugin-jsx-a11y": "^6.5.1", - "eslint-plugin-react": "^7.27.1", - "eslint-plugin-react-hooks": "^4.3.0", - "eslint-plugin-testing-library": "^5.0.1" - } - }, "eslint-import-resolver-node": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, "requires": { "debug": "^3.2.7", "is-core-module": "^2.13.0", @@ -32609,6 +25121,7 @@ "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, "requires": { "ms": "^2.1.1" } @@ -32619,6 +25132,7 @@ "version": "2.8.0", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "dev": true, "requires": { "debug": "^3.2.7" }, @@ -32627,25 +25141,18 @@ "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, "requires": { "ms": "^2.1.1" } } } }, - "eslint-plugin-flowtype": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-8.0.3.tgz", - "integrity": "sha512-dX8l6qUL6O+fYPtpNRideCFSpmWOUVx5QcaGLVqe/vlDiBSe4vYljDWDETwnyFzpl7By/WVIu6rcrniCgH9BqQ==", - "requires": { - "lodash": "^4.17.21", - "string-natural-compare": "^3.0.1" - } - }, "eslint-plugin-import": { "version": "2.29.1", "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "dev": true, "requires": { "array-includes": "^3.1.7", "array.prototype.findlastindex": "^1.2.3", @@ -32670,6 +25177,7 @@ "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, "requires": { "ms": "^2.1.1" } @@ -32678,6 +25186,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, "requires": { "esutils": "^2.0.2" } @@ -32685,87 +25194,135 @@ "semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true } } }, "eslint-plugin-jest": { - "version": "25.7.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-25.7.0.tgz", - "integrity": "sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==", - "requires": { - "@typescript-eslint/experimental-utils": "^5.0.0" - } - }, - "eslint-plugin-jsx-a11y": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz", - "integrity": "sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==", + "version": "28.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.0.tgz", + "integrity": "sha512-Tubj1hooFxCl52G4qQu0edzV/+EZzPUeN8p2NnW5uu4fbDs+Yo7+qDVDc4/oG3FbCqEBmu/OC3LSsyiU22oghw==", + "dev": true, "requires": { - "@babel/runtime": "^7.20.7", - "aria-query": "^5.1.3", - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "ast-types-flow": "^0.0.7", - "axe-core": "^4.6.2", - "axobject-query": "^3.1.1", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "has": "^1.0.3", - "jsx-ast-utils": "^3.3.3", - "language-tags": "=1.0.5", - "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "semver": "^6.3.0" + "@typescript-eslint/utils": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + "@typescript-eslint/scope-manager": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.5.0.tgz", + "integrity": "sha512-06JOQ9Qgj33yvBEx6tpC8ecP9o860rsR22hWMEd12WcTRrfaFgHr2RB/CA/B+7BMhHkXT4chg2MyboGdFGawYg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0" + } + }, + "@typescript-eslint/types": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.5.0.tgz", + "integrity": "sha512-qjkormnQS5wF9pjSi6q60bKUHH44j2APxfh9TQRXK8wbYVeDYYdYJGIROL87LGZZ2gz3Rbmjc736qyL8deVtdw==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.5.0.tgz", + "integrity": "sha512-vEG2Sf9P8BPQ+d0pxdfndw3xIXaoSjliG0/Ejk7UggByZPKXmJmw3GW5jV2gHNQNawBUyfahoSiCFVov0Ruf7Q==", + "dev": true, + "requires": { + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + } + }, + "@typescript-eslint/utils": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.5.0.tgz", + "integrity": "sha512-6yyGYVL0e+VzGYp60wvkBHiqDWOpT63pdMV2CVG4LVDd5uR6q1qQN/7LafBZtAtNIn/mqXjsSeS5ggv/P0iECw==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.5.0", + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/typescript-estree": "8.5.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.5.0.tgz", + "integrity": "sha512-yTPqMnbAZJNy2Xq2XU8AdtOW9tJIr+UQb64aXB9f3B1498Zx9JorVgFJcZpEc9UBuCCrdzKID2RGAMkYcDtZOw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "8.5.0", + "eslint-visitor-keys": "^3.4.3" + } + }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } } } }, "eslint-plugin-prettier": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", - "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", + "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", "dev": true, "requires": { "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.8.6" + "synckit": "^0.9.1" } }, "eslint-plugin-react": { - "version": "7.34.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz", - "integrity": "sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==", + "version": "7.35.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.0.tgz", + "integrity": "sha512-v501SSMOWv8gerHkk+IIQBkcGRGrO2nfybfj5pLxuJNFTPxxA3PSryhXTK+9pNbtkggheDdsC0E9Q8CuPk6JKA==", + "dev": true, "requires": { - "array-includes": "^3.1.7", - "array.prototype.findlast": "^1.2.4", + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.2", - "array.prototype.toreversed": "^1.1.2", - "array.prototype.tosorted": "^1.1.3", + "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.17", + "es-iterator-helpers": "^1.0.19", "estraverse": "^5.3.0", + "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", - "object.entries": "^1.1.7", - "object.fromentries": "^2.0.7", - "object.hasown": "^1.1.3", - "object.values": "^1.1.7", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.0", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.10" + "string.prototype.matchall": "^4.0.11", + "string.prototype.repeat": "^1.0.0" }, "dependencies": { "doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, "requires": { "esutils": "^2.0.2" } @@ -32773,12 +25330,14 @@ "estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true }, "resolve": { "version": "2.0.0-next.5", "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, "requires": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -32788,103 +25347,33 @@ "semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true } } }, - "eslint-plugin-react-hooks": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", - "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", - "requires": {} - }, - "eslint-plugin-testing-library": { - "version": "5.11.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.11.0.tgz", - "integrity": "sha512-ELY7Gefo+61OfXKlQeXNIDVVLPcvKTeiQOoMZG9TeuWa7Ln4dUNRv8JdRWBQI9Mbb427XGlVB1aa1QPZxBJM8Q==", - "requires": { - "@typescript-eslint/utils": "^5.58.0" - } - }, "eslint-plugin-tsdoc": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.17.tgz", - "integrity": "sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.3.0.tgz", + "integrity": "sha512-0MuFdBrrJVBjT/gyhkP2BqpD0np1NxNLfQ38xXDlSs/KVVpKI2A6vN7jx2Rve/CyUsvOsMGwp9KKrinv7q9g3A==", "dev": true, "requires": { - "@microsoft/tsdoc": "0.14.2", - "@microsoft/tsdoc-config": "0.16.2" - } - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "@microsoft/tsdoc": "0.15.0", + "@microsoft/tsdoc-config": "0.17.0" } }, "eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==" - }, - "eslint-webpack-plugin": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-3.2.0.tgz", - "integrity": "sha512-avrKcGncpPbPSUHX6B3stNGzkKFto3eL+DKM4+VyMrVnhPc3vRczVlCq3uhuFOdRvDHTVXuzwk1ZKUrqDQHQ9w==", - "requires": { - "@types/eslint": "^7.29.0 || ^8.4.1", - "jest-worker": "^28.0.2", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "schema-utils": "^4.0.0" - }, - "dependencies": { - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "jest-worker": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.1.3.tgz", - "integrity": "sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g==", - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - } - }, - "schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - } - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "requires": { - "has-flag": "^4.0.0" - } - } - } + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true }, "espree": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "peer": true, "requires": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", @@ -32900,6 +25389,8 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "peer": true, "requires": { "estraverse": "^5.1.0" }, @@ -32907,7 +25398,9 @@ "estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "peer": true } } }, @@ -32915,6 +25408,8 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "peer": true, "requires": { "estraverse": "^5.2.0" }, @@ -32922,44 +25417,23 @@ "estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "peer": true } } }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" - }, - "estree-walker": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", - "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==" - }, "esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" - }, - "eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true }, "execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, "requires": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -32975,7 +25449,8 @@ "exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==" + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true }, "expand-range": { "version": "1.8.2", @@ -33041,6 +25516,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "dev": true, "requires": { "@jest/types": "^27.5.1", "jest-get-type": "^27.5.1", @@ -33048,103 +25524,6 @@ "jest-message-util": "^27.5.1" } }, - "express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", - "requires": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.1", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "requires": { - "ee-first": "1.1.1" - } - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" - }, - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "optional": true, - "peer": true - }, "external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", @@ -33165,13 +25544,6 @@ } } }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "optional": true, - "peer": true - }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -33184,9 +25556,10 @@ "dev": true }, "fast-glob": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", - "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -33198,33 +25571,39 @@ "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true }, "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "peer": true + }, + "fast-xml-parser": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "peer": true, + "requires": { + "strnum": "^1.0.5" + } }, "fastq": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, "requires": { "reusify": "^1.0.4" } }, - "faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", - "requires": { - "websocket-driver": ">=0.5.1" - } - }, "fb-watchman": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, "requires": { "bser": "2.1.1" } @@ -33248,66 +25627,17 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "peer": true, "requires": { "flat-cache": "^3.0.4" } }, - "file-loader": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", - "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", - "requires": { - "loader-utils": "^2.0.0", - "schema-utils": "^3.0.0" - }, - "dependencies": { - "loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - } - } - }, - "filelist": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", - "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", - "requires": { - "minimatch": "^5.0.1" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "filesize": { - "version": "8.0.7", - "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", - "integrity": "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==" - }, "fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "devOptional": true, "requires": { "to-regex-range": "^5.0.1" } @@ -33344,16 +25674,6 @@ } } }, - "find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - } - }, "find-node-modules": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/find-node-modules/-/find-node-modules-2.1.3.tgz", @@ -33373,6 +25693,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, "requires": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -33399,6 +25720,8 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "peer": true, "requires": { "flatted": "^3.1.0", "rimraf": "^3.0.2" @@ -33407,12 +25730,9 @@ "flatted": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" - }, - "follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==" + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true, + "peer": true }, "fontkit": { "version": "2.0.2", @@ -33434,6 +25754,7 @@ "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, "requires": { "is-callable": "^1.1.3" } @@ -33443,158 +25764,22 @@ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==" }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", - "optional": true, - "peer": true - }, - "fork-ts-checker-webpack-plugin": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz", - "integrity": "sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==", - "requires": { - "@babel/code-frame": "^7.8.3", - "@types/json-schema": "^7.0.5", - "chalk": "^4.1.0", - "chokidar": "^3.4.2", - "cosmiconfig": "^6.0.0", - "deepmerge": "^4.2.2", - "fs-extra": "^9.0.0", - "glob": "^7.1.6", - "memfs": "^3.1.2", - "minimatch": "^3.0.4", - "schema-utils": "2.7.0", - "semver": "^7.3.2", - "tapable": "^1.0.0" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "requires": {} - }, - "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" - } - }, - "cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", - "requires": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.7.2" - } - }, - "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "schema-utils": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", - "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", - "requires": { - "@types/json-schema": "^7.0.4", - "ajv": "^6.12.2", - "ajv-keywords": "^3.4.1" - } - }, - "tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" - } - } - }, "form-data": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "mime-types": "^2.1.12" } }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" - }, - "fraction.js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", - "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==" - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" - }, - "fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "optional": true, - "peer": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "fs-monkey": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.4.tgz", - "integrity": "sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ==" - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true }, "fsevents": { "version": "2.3.3", @@ -33611,6 +25796,7 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, "requires": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -33621,34 +25807,8 @@ "functions-have-names": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" - }, - "gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "optional": true, - "peer": true, - "requires": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - } - }, - "gaze": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", - "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", - "optional": true, - "peer": true, - "requires": { - "globule": "^1.0.0" - } + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true }, "generic-names": { "version": "4.0.0", @@ -33667,7 +25827,8 @@ "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true }, "get-east-asian-width": { "version": "1.2.0", @@ -33679,6 +25840,7 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, "requires": { "es-errors": "^1.3.0", "function-bind": "^1.1.2", @@ -33687,32 +25849,23 @@ "hasown": "^2.0.0" } }, - "get-own-enumerable-property-symbols": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", - "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" - }, "get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==" - }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw==", - "optional": true, - "peer": true + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true }, "get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true }, "get-symbol-description": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, "requires": { "call-bind": "^1.0.5", "es-errors": "^1.3.0", @@ -33728,20 +25881,11 @@ "resolve-pkg-maps": "^1.0.0" } }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "optional": true, - "peer": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, "glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -33755,15 +25899,11 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "devOptional": true, "requires": { "is-glob": "^4.0.1" } }, - "glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" - }, "global-dirs": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", @@ -33781,103 +25921,30 @@ } } }, - "global-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", - "requires": { - "global-prefix": "^3.0.0" - } - }, - "global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", - "requires": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - }, - "dependencies": { - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "requires": { - "isexe": "^2.0.0" - } - } - } - }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" - }, - "globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "requires": { - "define-properties": "^1.1.3" - } - }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - } - }, - "globule": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.4.tgz", - "integrity": "sha512-OPTIfhMBh7JbBYDpa5b+Q5ptmMWKwcNcFSR/0c6t8V4f3ZAVBEsKNY37QdVqmLRYSMhOUGYrY0QhSoEpzGr/Eg==", - "optional": true, - "peer": true, - "requires": { - "glob": "~7.1.1", - "lodash": "^4.17.21", - "minimatch": "~3.0.2" - }, - "dependencies": { - "glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "optional": true, - "peer": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "minimatch": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", - "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", - "optional": true, - "peer": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } + }, + "globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3" } }, + "globrex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", + "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==" + }, "gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, "requires": { "get-intrinsic": "^1.1.3" } @@ -33915,12 +25982,14 @@ "graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true }, "graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true }, "graphql": { "version": "16.9.0", @@ -33978,83 +26047,17 @@ "through2": "^2.0.0" } }, - "gzip-size": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", - "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", - "requires": { - "duplexer": "^0.1.2" - } - }, - "handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", - "optional": true, - "peer": true - }, - "har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "optional": true, - "peer": true, - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "optional": true, - "peer": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "optional": true, - "peer": true - } - } - }, - "hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "optional": true, - "peer": true - }, "harmony-reflect": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", - "integrity": "sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==" - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } + "integrity": "sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==", + "dev": true }, "has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==" + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true }, "has-flag": { "version": "4.0.0", @@ -34065,6 +26068,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, "requires": { "es-define-property": "^1.0.0" } @@ -34072,28 +26076,24 @@ "has-proto": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==" + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true }, "has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true }, "has-tostringtag": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, "requires": { "has-symbols": "^1.0.3" } }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "optional": true, - "peer": true - }, "has-yarn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", @@ -34108,10 +26108,31 @@ "function-bind": "^1.1.2" } }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" + "hast-util-to-html": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.2.tgz", + "integrity": "sha512-RP5wNpj5nm1Z8cloDv4Sl4RS8jH5HYa0v93YB6Wb4poEzgMo/dAAL0KcT4974dCjcNG5pkLqTImeFHHCwwfY3g==", + "requires": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + } + }, + "hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "requires": { + "@types/hast": "^3.0.0" + } }, "history": { "version": "5.3.0", @@ -34145,123 +26166,25 @@ "parse-passwd": "^1.0.0" } }, - "hoopy": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", - "integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==" - }, - "hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "optional": true, - "peer": true, - "requires": { - "lru-cache": "^6.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "optional": true, - "peer": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "optional": true, - "peer": true - } - } - }, - "hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", - "requires": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, "html-encoding-sniffer": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "dev": true, "requires": { "whatwg-encoding": "^1.0.5" } }, "html-entities": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz", - "integrity": "sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==" + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", + "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==" }, "html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==" - }, - "html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", - "requires": { - "camel-case": "^4.1.2", - "clean-css": "^5.2.2", - "commander": "^8.3.0", - "he": "^1.2.0", - "param-case": "^3.0.4", - "relateurl": "^0.2.7", - "terser": "^5.10.0" - }, - "dependencies": { - "commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==" - } - } + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true }, "html-parse-stringify": { "version": "3.0.1", @@ -34271,17 +26194,10 @@ "void-elements": "3.1.0" } }, - "html-webpack-plugin": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.3.tgz", - "integrity": "sha512-6YrDKTuqaP/TquFH7h4srYWsZx+x6k6+FbsTm0ziCwGHDP78Unr1r9F/H4+sGmMbX08GQcJ+K64x55b+7VM/jg==", - "requires": { - "@types/html-minifier-terser": "^6.0.0", - "html-minifier-terser": "^6.0.2", - "lodash": "^4.17.21", - "pretty-error": "^4.0.0", - "tapable": "^2.0.0" - } + "html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==" }, "htmlparser2": { "version": "8.0.2", @@ -34298,92 +26214,24 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "devOptional": true - }, - "http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==" - }, - "http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "requires": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "dependencies": { - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" - } - } - }, - "http-parser-js": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", - "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" - }, - "http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "requires": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } + "dev": true }, "http-proxy-agent": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, "requires": { "@tootallnate/once": "1", "agent-base": "6", "debug": "4" } }, - "http-proxy-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", - "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", - "requires": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - }, - "dependencies": { - "is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==" - } - } - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", - "optional": true, - "peer": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, "https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, "requires": { "agent-base": "6", "debug": "4" @@ -34392,30 +26240,21 @@ "human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" - }, - "humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "optional": true, - "peer": true, - "requires": { - "ms": "^2.0.0" - } + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true }, "husky": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", - "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", + "version": "9.1.6", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.6.tgz", + "integrity": "sha512-sqbjZKK7kf44hfdE94EoX8MZNk0n7HeW37O4YrVGCF4wzgQjp+akPAkfUK5LZ6KuR/6sqeAVuXHji+RzQgOn5A==", "dev": true }, "i18next": { - "version": "21.10.0", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-21.10.0.tgz", - "integrity": "sha512-YeuIBmFsGjUfO3qBmMOc0rQaun4mIpGKET5WDwvu8lU7gvwpcariZLNtL0Fzj+zazcHUrlXHiptcFhBMFaxzfg==", + "version": "23.15.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.15.1.tgz", + "integrity": "sha512-wB4abZ3uK7EWodYisHl/asf8UYEhrI/vj/8aoSsrj/ZDxj4/UXPOa1KvFt1Fq5hkUHquNqwFlDprmjZ8iySgYA==", "requires": { - "@babel/runtime": "^7.17.2" + "@babel/runtime": "^7.23.2" } }, "i18next-browser-languagedetector": { @@ -34427,9 +26266,9 @@ } }, "i18next-http-backend": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-2.5.2.tgz", - "integrity": "sha512-+K8HbDfrvc1/2X8jpb7RLhI9ZxBDpx3xogYkQwGKlWAUXLSEGXzgdt3EcUjLlBCdMwdQY+K+EUF6oh8oB6rwHw==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-2.6.1.tgz", + "integrity": "sha512-rCilMAnlEQNeKOZY1+x8wLM5IpYOj10guGvEpeC59tNjj6MMreLIjIW8D1RclhD3ifLwn6d/Y9HEM1RUE6DSog==", "requires": { "cross-fetch": "4.0.0" } @@ -34438,6 +26277,8 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "optional": true, + "peer": true, "requires": { "safer-buffer": ">= 2.1.2 < 3.0.0" } @@ -34446,17 +26287,14 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, "requires": {} }, - "idb": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", - "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==" - }, "identity-obj-proxy": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz", "integrity": "sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA==", + "dev": true, "requires": { "harmony-reflect": "^1.4.6" } @@ -34467,14 +26305,15 @@ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==" + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true }, "immer": { - "version": "9.0.21", - "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", - "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==" + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz", + "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==" }, "immutable": { "version": "4.3.5", @@ -34501,6 +26340,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, "requires": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" @@ -34509,25 +26349,20 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==" + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true }, "indent-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "devOptional": true - }, - "infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "optional": true, - "peer": true + "dev": true }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -34541,7 +26376,8 @@ "ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true }, "inquirer": { "version": "8.2.6", @@ -34607,6 +26443,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, "requires": { "es-errors": "^1.3.0", "hasown": "^2.0.0", @@ -34626,22 +26463,11 @@ "loose-envify": "^1.0.0" } }, - "ip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", - "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==", - "optional": true, - "peer": true - }, - "ipaddr.js": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", - "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==" - }, "is-array-buffer": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, "requires": { "call-bind": "^1.0.2", "get-intrinsic": "^1.2.1" @@ -34656,6 +26482,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, "requires": { "has-tostringtag": "^1.0.0" } @@ -34664,6 +26491,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, "requires": { "has-bigints": "^1.0.1" } @@ -34672,6 +26500,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "devOptional": true, "requires": { "binary-extensions": "^2.0.0" } @@ -34680,6 +26509,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, "requires": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -34693,7 +26523,8 @@ "is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==" + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true }, "is-ci": { "version": "2.0.0", @@ -34724,6 +26555,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, "requires": { "is-typed-array": "^1.1.13" } @@ -34732,6 +26564,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, "requires": { "has-tostringtag": "^1.0.0" } @@ -34739,7 +26572,8 @@ "is-docker": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true }, "is-extendable": { "version": "1.0.1", @@ -34752,12 +26586,14 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "devOptional": true }, "is-finalizationregistry": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dev": true, "requires": { "call-bind": "^1.0.2" } @@ -34770,12 +26606,14 @@ "is-generator-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==" + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true }, "is-generator-function": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, "requires": { "has-tostringtag": "^1.0.0" } @@ -34784,6 +26622,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "devOptional": true, "requires": { "is-extglob": "^2.1.1" } @@ -34803,27 +26642,17 @@ "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==" }, - "is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "optional": true, - "peer": true - }, "is-map": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==" - }, - "is-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==" + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true }, "is-negative-zero": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==" + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true }, "is-npm": { "version": "5.0.0", @@ -34834,12 +26663,14 @@ "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "devOptional": true }, "is-number-object": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, "requires": { "has-tostringtag": "^1.0.0" } @@ -34851,16 +26682,10 @@ "dev": true }, "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==" - }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "optional": true, - "peer": true + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true }, "is-plain-object": { "version": "2.0.4", @@ -34873,36 +26698,30 @@ "is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true }, "is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, "requires": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" } }, - "is-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", - "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==" - }, - "is-root": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", - "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==" - }, "is-set": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==" + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true }, "is-shared-array-buffer": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, "requires": { "call-bind": "^1.0.7" } @@ -34910,12 +26729,14 @@ "is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true }, "is-string": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, "requires": { "has-tostringtag": "^1.0.0" } @@ -34924,6 +26745,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, "requires": { "has-symbols": "^1.0.2" } @@ -34932,6 +26754,7 @@ "version": "1.1.13", "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, "requires": { "which-typed-array": "^1.1.14" } @@ -34939,7 +26762,8 @@ "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true }, "is-unicode-supported": { "version": "0.1.0", @@ -34949,12 +26773,14 @@ "is-weakmap": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==" + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true }, "is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, "requires": { "call-bind": "^1.0.2" } @@ -34963,6 +26789,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", + "dev": true, "requires": { "call-bind": "^1.0.7", "get-intrinsic": "^1.2.4" @@ -34978,6 +26805,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, "requires": { "is-docker": "^2.0.0" } @@ -34991,34 +26819,31 @@ "isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true }, "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==" }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", - "optional": true, - "peer": true - }, "istanbul-lib-coverage": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==" + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true }, "istanbul-lib-instrument": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, "requires": { "@babel/core": "^7.12.3", "@babel/parser": "^7.14.7", @@ -35030,7 +26855,8 @@ "semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true } } }, @@ -35038,6 +26864,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, "requires": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^3.0.0", @@ -35048,6 +26875,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, "requires": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", @@ -35057,7 +26885,8 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true } } }, @@ -35065,6 +26894,7 @@ "version": "3.1.5", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", + "dev": true, "requires": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" @@ -35074,6 +26904,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "dev": true, "requires": { "define-properties": "^1.2.1", "get-intrinsic": "^1.2.1", @@ -35082,32 +26913,11 @@ "set-function-name": "^2.0.1" } }, - "jake": { - "version": "10.8.7", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", - "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==", - "requires": { - "async": "^3.2.3", - "chalk": "^4.0.2", - "filelist": "^1.0.4", - "minimatch": "^3.1.2" - }, - "dependencies": { - "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" - } - } - } - }, "jest": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", + "dev": true, "requires": { "@jest/core": "^27.5.1", "import-local": "^3.0.2", @@ -35118,6 +26928,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", + "dev": true, "requires": { "@jest/types": "^27.5.1", "execa": "^5.0.0", @@ -35128,6 +26939,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", + "dev": true, "requires": { "@jest/environment": "^27.5.1", "@jest/test-result": "^27.5.1", @@ -35154,6 +26966,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -35163,6 +26976,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, "requires": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -35172,14 +26986,16 @@ "ansi-styles": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true } } }, "react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true } } }, @@ -35187,6 +27003,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", + "dev": true, "requires": { "@jest/core": "^27.5.1", "@jest/test-result": "^27.5.1", @@ -35206,6 +27023,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -35217,6 +27035,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", + "dev": true, "requires": { "@babel/core": "^7.8.0", "@jest/test-sequencer": "^27.5.1", @@ -35248,6 +27067,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", + "dev": true, "requires": { "@jest/transform": "^27.5.1", "@jest/types": "^27.5.1", @@ -35263,6 +27083,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", + "dev": true, "requires": { "@babel/template": "^7.3.3", "@babel/types": "^7.3.3", @@ -35274,6 +27095,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", + "dev": true, "requires": { "babel-plugin-jest-hoist": "^27.5.1", "babel-preset-current-node-syntax": "^1.0.0" @@ -35283,6 +27105,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -35292,6 +27115,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", + "dev": true, "requires": { "@jest/environment": "^27.5.1", "@jest/fake-timers": "^27.5.1", @@ -35305,6 +27129,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, "requires": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -35314,14 +27139,16 @@ "ansi-styles": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true } } }, "react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true } } }, @@ -35359,6 +27186,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", + "dev": true, "requires": { "detect-newline": "^3.0.0" }, @@ -35366,7 +27194,8 @@ "detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==" + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true } } }, @@ -35374,6 +27203,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", + "dev": true, "requires": { "@jest/types": "^27.5.1", "chalk": "^4.0.0", @@ -35386,6 +27216,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -35395,6 +27226,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, "requires": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -35404,14 +27236,16 @@ "ansi-styles": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true } } }, "react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true } } }, @@ -35419,6 +27253,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", + "dev": true, "requires": { "@jest/environment": "^27.5.1", "@jest/fake-timers": "^27.5.1", @@ -35432,12 +27267,14 @@ "jest-get-type": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", - "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==" + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "dev": true }, "jest-haste-map": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "dev": true, "requires": { "@jest/types": "^27.5.1", "@types/graceful-fs": "^4.1.2", @@ -35458,6 +27295,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", + "dev": true, "requires": { "@jest/environment": "^27.5.1", "@jest/source-map": "^27.5.1", @@ -35482,6 +27320,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -35491,6 +27330,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, "requires": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -35500,14 +27340,16 @@ "ansi-styles": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true } } }, "react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true } } }, @@ -35515,6 +27357,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", + "dev": true, "requires": { "jest-get-type": "^27.5.1", "pretty-format": "^27.5.1" @@ -35523,12 +27366,14 @@ "ansi-styles": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true }, "pretty-format": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, "requires": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -35538,7 +27383,8 @@ "react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true } } }, @@ -35632,6 +27478,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "dev": true, "requires": { "chalk": "^4.0.0", "jest-diff": "^27.5.1", @@ -35643,6 +27490,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -35651,12 +27499,14 @@ "diff-sequences": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", - "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==" + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "dev": true }, "jest-diff": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "dev": true, "requires": { "chalk": "^4.0.0", "diff-sequences": "^27.5.1", @@ -35668,6 +27518,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, "requires": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -35677,14 +27528,16 @@ "ansi-styles": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true } } }, "react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true } } }, @@ -35692,6 +27545,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "dev": true, "requires": { "@babel/code-frame": "^7.12.13", "@jest/types": "^27.5.1", @@ -35708,6 +27562,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -35717,6 +27572,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, "requires": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -35726,14 +27582,16 @@ "ansi-styles": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true } } }, "react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true } } }, @@ -35741,6 +27599,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "dev": true, "requires": { "@jest/types": "^27.5.1", "@types/node": "*" @@ -35750,6 +27609,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, "requires": {} }, "jest-preview": { @@ -35796,12 +27656,14 @@ "jest-regex-util": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", - "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==" + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true }, "jest-resolve": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", + "dev": true, "requires": { "@jest/types": "^27.5.1", "chalk": "^4.0.0", @@ -35819,6 +27681,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -35830,6 +27693,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", + "dev": true, "requires": { "@jest/types": "^27.5.1", "jest-regex-util": "^27.5.1", @@ -35840,6 +27704,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", + "dev": true, "requires": { "@jest/console": "^27.5.1", "@jest/environment": "^27.5.1", @@ -35868,6 +27733,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -35877,6 +27743,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", + "dev": true, "requires": { "@jest/environment": "^27.5.1", "@jest/fake-timers": "^27.5.1", @@ -35892,6 +27759,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", + "dev": true, "requires": { "@jest/environment": "^27.5.1", "@jest/fake-timers": "^27.5.1", @@ -35921,6 +27789,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -35932,6 +27801,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dev": true, "requires": { "@types/node": "*", "graceful-fs": "^4.2.9" @@ -35941,6 +27811,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", + "dev": true, "requires": { "@babel/core": "^7.7.2", "@babel/generator": "^7.7.2", @@ -35970,6 +27841,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -35978,12 +27850,14 @@ "diff-sequences": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", - "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==" + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "dev": true }, "jest-diff": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "dev": true, "requires": { "chalk": "^4.0.0", "diff-sequences": "^27.5.1", @@ -35995,6 +27869,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, "requires": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -36004,14 +27879,16 @@ "ansi-styles": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true } } }, "react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true } } }, @@ -36019,6 +27896,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, "requires": { "@jest/types": "^27.5.1", "@types/node": "*", @@ -36032,6 +27910,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -36043,6 +27922,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", + "dev": true, "requires": { "@jest/types": "^27.5.1", "camelcase": "^6.2.0", @@ -36055,249 +27935,43 @@ "camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" - }, - "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" - } - }, - "pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", - "requires": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" - } - } - }, - "react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" - } - } - }, - "jest-watch-typeahead": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-1.1.0.tgz", - "integrity": "sha512-Va5nLSJTN7YFtC2jd+7wsoe1pNe5K4ShLux/E5iHEwlB9AxaxmggY7to9KUqKojhaJw3aXqt5WAb4jGPOolpEw==", - "requires": { - "ansi-escapes": "^4.3.1", - "chalk": "^4.0.0", - "jest-regex-util": "^28.0.0", - "jest-watcher": "^28.0.0", - "slash": "^4.0.0", - "string-length": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "dependencies": { - "@jest/console": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.3.tgz", - "integrity": "sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==", - "requires": { - "@jest/types": "^28.1.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^28.1.3", - "jest-util": "^28.1.3", - "slash": "^3.0.0" - }, - "dependencies": { - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" - } - } - }, - "@jest/test-result": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-28.1.3.tgz", - "integrity": "sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg==", - "requires": { - "@jest/console": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - } - }, - "@jest/types": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", - "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", - "requires": { - "@jest/schemas": "^28.1.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@types/yargs": { - "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", - "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", - "requires": { - "@types/yargs-parser": "*" - } + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true }, "chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "emittery": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", - "integrity": "sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==" - }, - "jest-message-util": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", - "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", - "requires": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^28.1.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^28.1.3", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "dependencies": { - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" - } - } - }, - "jest-regex-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", - "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==" - }, - "jest-util": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", - "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", - "requires": { - "@jest/types": "^28.1.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, - "jest-watcher": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-28.1.3.tgz", - "integrity": "sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g==", - "requires": { - "@jest/test-result": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.10.2", - "jest-util": "^28.1.3", - "string-length": "^4.0.1" - }, - "dependencies": { - "string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "requires": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - } + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, "pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, "requires": { - "@jest/schemas": "^28.1.3", "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "react-is": "^17.0.1" }, "dependencies": { "ansi-styles": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" - } - } - }, - "slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==" - }, - "string-length": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-5.0.1.tgz", - "integrity": "sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==", - "requires": { - "char-regex": "^2.0.0", - "strip-ansi": "^7.0.1" - }, - "dependencies": { - "char-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-2.0.1.tgz", - "integrity": "sha512-oSvEeo6ZUD7NepqAat3RqoucZ5SeqLJgOvVIwkafu6IP3V0pO38s/ypdVUmDDK6qIIHNlYHJAKX9E7R7HoKElw==" + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true } } }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "requires": { - "ansi-regex": "^6.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" - } - } + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true } } }, @@ -36305,6 +27979,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", + "dev": true, "requires": { "@jest/test-result": "^27.5.1", "@jest/types": "^27.5.1", @@ -36319,6 +27994,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -36330,6 +28006,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, "requires": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -36340,30 +28017,19 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, "requires": { "has-flag": "^4.0.0" } } } }, - "jiti": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.1.tgz", - "integrity": "sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg==" - }, "jju": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", "dev": true }, - "js-base64": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", - "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==", - "optional": true, - "peer": true - }, "js-cookie": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", @@ -36383,17 +28049,11 @@ "esprima": "^4.0.0" } }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", - "optional": true, - "peer": true - }, "jsdom": { "version": "16.7.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "dev": true, "requires": { "abab": "^2.0.5", "acorn": "^8.2.4", @@ -36427,12 +28087,14 @@ "parse5": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true }, "ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "dev": true, "requires": {} } } @@ -36453,26 +28115,17 @@ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, - "json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, "json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "optional": true, + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, "peer": true }, "json5": { @@ -36480,37 +28133,11 @@ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "jsonpointer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", - "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==" - }, - "jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "optional": true, - "peer": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - } - }, "jsx-ast-utils": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.4.tgz", - "integrity": "sha512-fX2TVdCViod6HwKEtSWGHs57oFhVfCMwieb9PuRDgjDPh5XeqJiHFFFJCHxU5cnTc3Bu/GRL+kPiFmw8XWOfKw==", + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, "requires": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", @@ -36535,25 +28162,8 @@ "kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==" - }, - "klona": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", - "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==" - }, - "language-subtag-registry": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", - "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==" - }, - "language-tags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", - "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", - "requires": { - "language-subtag-registry": "~0.3.2" - } + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true }, "latest-version": { "version": "5.1.0", @@ -36564,15 +28174,6 @@ "package-json": "^6.3.0" } }, - "launch-editor": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz", - "integrity": "sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==", - "requires": { - "picocolors": "^1.0.0", - "shell-quote": "^1.7.3" - } - }, "lazy-cache": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz", @@ -36584,12 +28185,15 @@ "leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "peer": true, "requires": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -36598,7 +28202,8 @@ "lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==" + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true }, "lines-and-columns": { "version": "1.2.4", @@ -36609,27 +28214,26 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", - "peer": true, "requires": { "uc.micro": "^2.0.0" } }, "lint-staged": { - "version": "15.2.7", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.7.tgz", - "integrity": "sha512-+FdVbbCZ+yoh7E/RosSdqKJyUM2OEjTciH0TFNkawKgvFp1zbGlEC39RADg+xKBG1R4mhoH2j85myBQZ5wR+lw==", + "version": "15.2.8", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.8.tgz", + "integrity": "sha512-PUWFf2zQzsd9EFU+kM1d7UP+AZDbKFKuj+9JNVTBkhUFhbg4MAt6WfyMMwBfM4lYqd4D2Jwac5iuTu9rVj4zCQ==", "dev": true, "requires": { "chalk": "~5.3.0", "commander": "~12.1.0", - "debug": "~4.3.4", + "debug": "~4.3.6", "execa": "~8.0.1", - "lilconfig": "~3.1.1", - "listr2": "~8.2.1", + "lilconfig": "~3.1.2", + "listr2": "~8.2.4", "micromatch": "~4.0.7", "pidtree": "~0.6.0", "string-argv": "~0.3.2", - "yaml": "~2.4.2" + "yaml": "~2.5.0" }, "dependencies": { "chalk": { @@ -36728,9 +28332,9 @@ "dev": true }, "yaml": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", - "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz", + "integrity": "sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==", "dev": true } } @@ -36778,16 +28382,16 @@ } }, "listr2": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.1.tgz", - "integrity": "sha512-irTfvpib/rNiD637xeevjO2l3Z5loZmuaRi0L0YE5LfijwVY96oyVn0DFD3o/teAok7nfobMG1THvvcHh/BP6g==", + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.4.tgz", + "integrity": "sha512-opevsywziHd3zHCVQGAj8zu+Z3yHNkkoYhWIGnq54RrCVwLz0MozotJEDnKsIBLvkfLGN6BLOyAeRrYI0pKA4g==", "dev": true, "requires": { "cli-truncate": "^4.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", - "log-update": "^6.0.0", - "rfdc": "^1.3.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", "wrap-ansi": "^9.0.0" }, "dependencies": { @@ -36816,9 +28420,9 @@ "dev": true }, "string-width": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", - "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "requires": { "emoji-regex": "^10.3.0", @@ -36848,20 +28452,17 @@ } } }, - "loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==" - }, "loader-utils": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", - "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==" + "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==", + "dev": true }, "locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, "requires": { "p-locate": "^4.1.0" } @@ -36885,27 +28486,20 @@ "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true }, "lodash.flow": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz", "integrity": "sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw==" }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" - }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" - }, - "lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "peer": true }, "lodash.template": { "version": "4.5.0", @@ -36924,11 +28518,6 @@ "lodash._reinterpolate": "^3.0.0" } }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" - }, "log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -36950,23 +28539,26 @@ } }, "log-update": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", - "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", "dev": true, "requires": { - "ansi-escapes": "^6.2.0", - "cli-cursor": "^4.0.0", - "slice-ansi": "^7.0.0", + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" }, "dependencies": { "ansi-escapes": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", - "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", - "dev": true + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", + "dev": true, + "requires": { + "environment": "^1.0.0" + } }, "ansi-regex": { "version": "6.0.1", @@ -37006,9 +28598,9 @@ } }, "string-width": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", - "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "requires": { "emoji-regex": "^10.3.0", @@ -37050,6 +28642,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, "requires": { "tslib": "^2.0.3" } @@ -37071,27 +28664,20 @@ "lunr": { "version": "2.3.9", "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", - "peer": true + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==" }, "lz-string": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", - "dev": true - }, - "magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", - "requires": { - "sourcemap-codec": "^1.4.8" - } + "dev": true, + "peer": true }, "make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, "requires": { "semver": "^6.0.0" }, @@ -37099,7 +28685,8 @@ "semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true } } }, @@ -37107,22 +28694,15 @@ "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, "requires": { "tmpl": "1.0.5" } }, - "map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "optional": true, - "peer": true - }, "markdown-it": { "version": "14.1.0", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", - "peer": true, "requires": { "argparse": "^2.0.1", "entities": "^4.4.0", @@ -37135,8 +28715,7 @@ "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "peer": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" } } }, @@ -37169,114 +28748,105 @@ "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==" }, - "mdn-data": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", - "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==" + "mdast-util-to-hast": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", + "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "requires": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + } }, "mdurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", - "peer": true - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" - }, - "memfs": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", - "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", - "requires": { - "fs-monkey": "^1.0.4" - } + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==" }, "memoize-one": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==" }, - "meow": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", - "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", - "optional": true, - "peer": true, - "requires": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize": "^1.2.0", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - }, - "dependencies": { - "type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "optional": true, - "peer": true - } - } - }, "merge": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/merge/-/merge-2.1.1.tgz", "integrity": "sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==", "dev": true }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" - }, "merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true }, "merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" + "micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "requires": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "micromark-util-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", + "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==" + }, + "micromark-util-sanitize-uri": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", + "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", + "requires": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==" + }, + "micromark-util-types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz", + "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==" }, "micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, "requires": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true }, "mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, "requires": { "mime-db": "1.52.0" } @@ -37286,6 +28856,12 @@ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" }, + "mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true + }, "mimic-response": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", @@ -37296,46 +28872,13 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "devOptional": true - }, - "mini-css-extract-plugin": { - "version": "2.7.6", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.6.tgz", - "integrity": "sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw==", - "requires": { - "schema-utils": "^4.0.0" - }, - "dependencies": { - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - } - } - } - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + "dev": true }, "minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -37343,98 +28886,7 @@ "minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" - }, - "minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "optional": true, - "peer": true, - "requires": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - } - }, - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "optional": true, - "peer": true, - "requires": { - "yallist": "^4.0.0" - }, - "dependencies": { - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "optional": true, - "peer": true - } - } - }, - "minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "optional": true, - "peer": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "optional": true, - "peer": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "optional": true, - "peer": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "optional": true, - "peer": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "optional": true, - "peer": true, - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "dependencies": { - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "optional": true, - "peer": true - } - } + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" }, "mixin-deep": { "version": "1.3.2", @@ -37445,13 +28897,6 @@ "is-extendable": "^1.0.1" } }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "optional": true, - "peer": true - }, "mrmime": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", @@ -37463,37 +28908,11 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, - "multicast-dns": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", - "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", - "requires": { - "dns-packet": "^5.2.2", - "thunky": "^1.0.2" - } - }, "mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" }, - "mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "requires": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "nan": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", - "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", - "optional": true, - "peer": true - }, "nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -37502,27 +28921,14 @@ "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" - }, - "natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==" - }, - "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true }, "no-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, "requires": { "lower-case": "^2.0.2", "tslib": "^2.0.3" @@ -37557,370 +28963,68 @@ } } }, - "node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==" - }, - "node-gyp": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", - "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", - "optional": true, - "peer": true, + "node-html-better-parser": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/node-html-better-parser/-/node-html-better-parser-1.4.4.tgz", + "integrity": "sha512-uvlqL1uMU7m/aIY9WsGM0jDW7gVFIuFSWS6f2rlJeL7K1ZzKnA3B8cNbUGw9ywwYm9W7W2ooi0iQ7aI29aQmPw==", "requires": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^9.1.0", - "nopt": "^5.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "dependencies": { - "@npmcli/fs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", - "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", - "optional": true, - "peer": true, - "requires": { - "@gar/promisify": "^1.0.1", - "semver": "^7.3.5" - } - }, - "@npmcli/move-file": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", - "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", - "optional": true, - "peer": true, - "requires": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - } - }, - "cacache": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", - "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", - "optional": true, - "peer": true, - "requires": { - "@npmcli/fs": "^1.0.0", - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.1", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "optional": true, - "peer": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "make-fetch-happen": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", - "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", - "optional": true, - "peer": true, - "requires": { - "agentkeepalive": "^4.1.3", - "cacache": "^15.2.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^6.0.0", - "minipass": "^3.1.3", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^1.3.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.2", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^6.0.0", - "ssri": "^8.0.0" - } - }, - "minipass-fetch": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", - "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", - "optional": true, - "peer": true, - "requires": { - "encoding": "^0.1.12", - "minipass": "^3.1.0", - "minipass-sized": "^1.0.3", - "minizlib": "^2.0.0" - } - }, - "socks-proxy-agent": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", - "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", - "optional": true, - "peer": true, - "requires": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - } - }, - "ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "optional": true, - "peer": true, - "requires": { - "minipass": "^3.1.1" - } - }, - "unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "optional": true, - "peer": true, - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "optional": true, - "peer": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "optional": true, - "peer": true - } + "html-entities": "^2.3.2" } }, "node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true }, "node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" - }, - "node-sass": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-7.0.3.tgz", - "integrity": "sha512-8MIlsY/4dXUkJDYht9pIWBhMil3uHmE8b/AdJPjmFn1nBx9X9BASzfzmsCy0uCCb8eqI3SYYzVPDswWqSx7gjw==", - "optional": true, - "peer": true, - "requires": { - "async-foreach": "^0.1.3", - "chalk": "^4.1.2", - "cross-spawn": "^7.0.3", - "gaze": "^1.0.0", - "get-stdin": "^4.0.1", - "glob": "^7.0.3", - "lodash": "^4.17.15", - "meow": "^9.0.0", - "nan": "^2.13.2", - "node-gyp": "^8.4.1", - "npmlog": "^5.0.0", - "request": "^2.88.0", - "sass-graph": "^4.0.1", - "stdout-stream": "^1.4.0", - "true-case-path": "^1.0.2" - }, - "dependencies": { - "are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "optional": true, - "peer": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "optional": true, - "peer": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "optional": true, - "peer": true, - "requires": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - } - }, - "npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "optional": true, - "peer": true, - "requires": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } - } - } - }, - "nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "optional": true, - "peer": true, - "requires": { - "abbrev": "1" - } - }, - "normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "optional": true, - "peer": true, - "requires": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - } + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" - }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==" - }, - "normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==" + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "devOptional": true }, "npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, "requires": { "path-key": "^3.0.0" } }, - "npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "optional": true, - "peer": true, - "requires": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - } - }, - "nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "requires": { - "boolbase": "^1.0.0" - } - }, "nwsapi": { "version": "2.2.7", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", - "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==" - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "optional": true, - "peer": true + "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==", + "dev": true }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" }, - "object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==" - }, "object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==" + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "dev": true }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true }, "object.assign": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, "requires": { "call-bind": "^1.0.5", "define-properties": "^1.2.1", @@ -37932,6 +29036,7 @@ "version": "1.1.8", "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "dev": true, "requires": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -37939,31 +29044,22 @@ } }, "object.fromentries": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", - "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - } - }, - "object.getownpropertydescriptors": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.6.tgz", - "integrity": "sha512-lq+61g26E/BgHv0ZTFgRvi7NMEPuAxLkFU7rukXjc/AlwH4Am5xXVnIXy3un1bg/JPbXHrixRkK1itUzzPiIjQ==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, "requires": { - "array.prototype.reduce": "^1.0.5", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.21.2", - "safe-array-concat": "^1.0.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" } }, "object.groupby": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "dev": true, "requires": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -37971,16 +29067,6 @@ "get-intrinsic": "^1.2.1" } }, - "object.hasown": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.4.tgz", - "integrity": "sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==", - "requires": { - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - } - }, "object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", @@ -37990,20 +29076,16 @@ } }, "object.values": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", - "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" } }, - "obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" - }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -38013,15 +29095,11 @@ "ee-first": "1.1.1" } }, - "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" - }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, "requires": { "wrappy": "1" } @@ -38034,10 +29112,19 @@ "mimic-fn": "^2.1.0" } }, + "oniguruma-to-js": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/oniguruma-to-js/-/oniguruma-to-js-0.4.3.tgz", + "integrity": "sha512-X0jWUcAlxORhOqqBREgPMgnshB7ZGYszBNspP+tS9hPD3l13CdaXcHbgImoHUHlrvGx/7AvFEkTRhAGYh+jzjQ==", + "requires": { + "regex": "^4.3.2" + } + }, "open": { "version": "8.4.2", "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, "requires": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", @@ -38045,18 +29132,20 @@ } }, "optimism": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.16.2.tgz", - "integrity": "sha512-zWNbgWj+3vLEjZNIh/okkY2EUfX+vB9TJopzIZwT1xxaMqC5hRLLraePod4c5n4He08xuXNH+zhKFFCu390wiQ==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.18.0.tgz", + "integrity": "sha512-tGn8+REwLRNFnb9WmcY5IfpOqeX2kpaYJ1s6Ae3mn12AeydLkR3j+jSCmVQFoXqU8D41PAJ1RG1rCRNWmNZVmQ==", "requires": { + "@wry/caches": "^1.0.0", "@wry/context": "^0.7.0", - "@wry/trie": "^0.3.0" + "@wry/trie": "^0.4.3", + "tslib": "^2.3.0" }, "dependencies": { "@wry/trie": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@wry/trie/-/trie-0.3.2.tgz", - "integrity": "sha512-yRTyhWSls2OY/pYLfwff867r8ekooZ4UI+/gxot5Wj8EFwSf2rG+n+Mo/6LoLQm1TKA4GRj2+LCpbfS937dClQ==", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@wry/trie/-/trie-0.4.3.tgz", + "integrity": "sha512-I6bHwH0fSf6RqQcnnXLJKhkSXG45MFral3GxPaY4uAl0LYDZM+YDVDAiU9bYwjTuysy1S0IeecWtmq1SZA3M1w==", "requires": { "tslib": "^2.3.0" } @@ -38067,6 +29156,8 @@ "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "peer": true, "requires": { "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", @@ -38135,6 +29226,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, "requires": { "p-try": "^2.0.0" } @@ -38143,40 +29235,16 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, "requires": { "p-limit": "^2.2.0" } }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "optional": true, - "peer": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "p-retry": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", - "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", - "requires": { - "@types/retry": "0.12.0", - "retry": "^0.13.1" - }, - "dependencies": { - "retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==" - } - } - }, "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true }, "package-json": { "version": "6.5.0", @@ -38203,15 +29271,6 @@ "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" }, - "param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "requires": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -38245,31 +29304,26 @@ "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - }, - "pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true }, "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true }, "path-parse": { "version": "1.0.7", @@ -38281,20 +29335,16 @@ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" - }, "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" }, "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "devOptional": true }, "pidtree": { "version": "0.6.0", @@ -38305,264 +29355,38 @@ "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==" + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true }, "pirates": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==" + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true }, "pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, "requires": { "find-up": "^4.0.0" } }, - "pkg-up": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", - "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", - "requires": { - "find-up": "^3.0.0" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "requires": { - "p-limit": "^2.0.0" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==" - } - } - }, "possible-typed-array-names": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==" + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true }, "postcss": { - "version": "8.4.35", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", - "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", + "version": "8.4.45", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.45.tgz", + "integrity": "sha512-7KTLTdzdZZYscUc65XmjFiB73vBhBfbPztCYdUNvlaso9PrzjzcmjqBPR0lNGkcVlcO4BjiO5rK/qNz+XAen1Q==", "requires": { "nanoid": "^3.3.7", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - } - }, - "postcss-attribute-case-insensitive": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.2.tgz", - "integrity": "sha512-XIidXV8fDr0kKt28vqki84fRK8VW8eTuIa4PChv2MqKuT6C9UjmSKzen6KaWhWEoYvwxFCa7n/tC1SZ3tyq4SQ==", - "requires": { - "postcss-selector-parser": "^6.0.10" - } - }, - "postcss-browser-comments": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-browser-comments/-/postcss-browser-comments-4.0.0.tgz", - "integrity": "sha512-X9X9/WN3KIvY9+hNERUqX9gncsgBA25XaeR+jshHz2j8+sYyHktHw1JdKuMjeLpGktXidqDhA7b/qm1mrBDmgg==", - "requires": {} - }, - "postcss-calc": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", - "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", - "requires": { - "postcss-selector-parser": "^6.0.9", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-clamp": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz", - "integrity": "sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==", - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-color-functional-notation": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-4.2.4.tgz", - "integrity": "sha512-2yrTAUZUab9s6CpxkxC4rVgFEVaR6/2Pipvi6qcgvnYiVqZcbDHEoBDhrXzyb7Efh2CCfHQNtcqWcIruDTIUeg==", - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-color-hex-alpha": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-8.0.4.tgz", - "integrity": "sha512-nLo2DCRC9eE4w2JmuKgVA3fGL3d01kGq752pVALF68qpGLmx2Qrk91QTKkdUqqp45T1K1XV8IhQpcu1hoAQflQ==", - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-color-rebeccapurple": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-7.1.1.tgz", - "integrity": "sha512-pGxkuVEInwLHgkNxUc4sdg4g3py7zUeCQ9sMfwyHAT+Ezk8a4OaaVZ8lIY5+oNqA/BXXgLyXv0+5wHP68R79hg==", - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-colormin": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.1.tgz", - "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==", - "requires": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0", - "colord": "^2.9.1", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-convert-values": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", - "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", - "requires": { - "browserslist": "^4.21.4", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-custom-media": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-8.0.2.tgz", - "integrity": "sha512-7yi25vDAoHAkbhAzX9dHx2yc6ntS4jQvejrNcC+csQJAXjj15e7VcWfMgLqBNAbOvqi5uIa9huOVwdHbf+sKqg==", - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-custom-properties": { - "version": "12.1.11", - "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-12.1.11.tgz", - "integrity": "sha512-0IDJYhgU8xDv1KY6+VgUwuQkVtmYzRwu+dMjnmdMafXYv86SWqfxkc7qdDvWS38vsjaEtv8e0vGOUQrAiMBLpQ==", - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-custom-selectors": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-6.0.3.tgz", - "integrity": "sha512-fgVkmyiWDwmD3JbpCmB45SvvlCD6z9CG6Ie6Iere22W5aHea6oWa7EM2bpnv2Fj3I94L3VbtvX9KqwSi5aFzSg==", - "requires": { - "postcss-selector-parser": "^6.0.4" - } - }, - "postcss-dir-pseudo-class": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-6.0.5.tgz", - "integrity": "sha512-eqn4m70P031PF7ZQIvSgy9RSJ5uI2171O/OO/zcRNYpJbvaeKFUlar1aJ7rmgiQtbm0FSPsRewjpdS0Oew7MPA==", - "requires": { - "postcss-selector-parser": "^6.0.10" - } - }, - "postcss-discard-comments": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", - "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", - "requires": {} - }, - "postcss-discard-duplicates": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", - "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", - "requires": {} - }, - "postcss-discard-empty": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", - "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", - "requires": {} - }, - "postcss-discard-overridden": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", - "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", - "requires": {} - }, - "postcss-double-position-gradients": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-3.1.2.tgz", - "integrity": "sha512-GX+FuE/uBR6eskOK+4vkXgT6pDkexLokPaz/AbJna9s5Kzp/yl488pKPjhy0obB475ovfT1Wv8ho7U/cHNaRgQ==", - "requires": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-env-function": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-4.0.6.tgz", - "integrity": "sha512-kpA6FsLra+NqcFnL81TnsU+Z7orGtDTxcOhl6pwXeEq1yFPpRMkCDpHhrz8CFQDr/Wfm0jLiNQ1OsGGPjlqPwA==", - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-flexbugs-fixes": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz", - "integrity": "sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==", - "requires": {} - }, - "postcss-focus-visible": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-6.0.4.tgz", - "integrity": "sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw==", - "requires": { - "postcss-selector-parser": "^6.0.9" - } - }, - "postcss-focus-within": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz", - "integrity": "sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ==", - "requires": { - "postcss-selector-parser": "^6.0.9" - } - }, - "postcss-font-variant": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", - "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", - "requires": {} - }, - "postcss-gap-properties": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-3.0.5.tgz", - "integrity": "sha512-IuE6gKSdoUNcvkGIqdtjtcMtZIFyXZhmFd5RUlg97iVEvp1BZKV5ngsAjCjrVy+14uhGBQl9tzmi1Qwq4kqVOg==", - "requires": {} - }, - "postcss-image-set-function": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-4.0.7.tgz", - "integrity": "sha512-9T2r9rsvYzm5ndsBE8WgtrMlIT7VbtTfE7b3BQnudUqnBcBo7L758oc+o+pdj/dUV0l5wjwSdjeOH2DZtfv8qw==", - "requires": { - "postcss-value-parser": "^4.2.0" + "picocolors": "^1.0.1", + "source-map-js": "^1.2.0" } }, "postcss-import": { @@ -38576,33 +29400,11 @@ "resolve": "^1.1.7" } }, - "postcss-initial": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz", - "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==", - "requires": {} - }, - "postcss-js": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", - "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", - "requires": { - "camelcase-css": "^2.0.1" - } - }, - "postcss-lab-function": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-4.2.1.tgz", - "integrity": "sha512-xuXll4isR03CrQsmxyz92LJB2xX9n+pZJ5jE9JgcnmsCammLyKdlzrBin+25dy6wIjfhJpKBAN80gsTlCgRk2w==", - "requires": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" - } - }, "postcss-load-config": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.1.tgz", "integrity": "sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==", + "dev": true, "requires": { "lilconfig": "^2.0.5", "yaml": "^2.1.1" @@ -38610,488 +29412,86 @@ "dependencies": { "yaml": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", - "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==" - } - } - }, - "postcss-loader": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", - "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", - "requires": { - "cosmiconfig": "^7.0.0", - "klona": "^2.0.5", - "semver": "^7.3.5" - } - }, - "postcss-logical": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-5.0.4.tgz", - "integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==", - "requires": {} - }, - "postcss-media-minmax": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz", - "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==", - "requires": {} - }, - "postcss-merge-longhand": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", - "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", - "requires": { - "postcss-value-parser": "^4.2.0", - "stylehacks": "^5.1.1" - } - }, - "postcss-merge-rules": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz", - "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==", - "requires": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0", - "cssnano-utils": "^3.1.0", - "postcss-selector-parser": "^6.0.5" - } - }, - "postcss-minify-font-values": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", - "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-minify-gradients": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", - "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", - "requires": { - "colord": "^2.9.1", - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-minify-params": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", - "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", - "requires": { - "browserslist": "^4.21.4", - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-minify-selectors": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", - "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", - "requires": { - "postcss-selector-parser": "^6.0.5" - } - }, - "postcss-modules": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules/-/postcss-modules-6.0.0.tgz", - "integrity": "sha512-7DGfnlyi/ju82BRzTIjWS5C4Tafmzl3R79YP/PASiocj+aa6yYphHhhKUOEoXQToId5rgyFgJ88+ccOUydjBXQ==", - "dev": true, - "requires": { - "generic-names": "^4.0.0", - "icss-utils": "^5.1.0", - "lodash.camelcase": "^4.3.0", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.0", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "string-hash": "^1.1.1" - } - }, - "postcss-modules-extract-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "requires": {} - }, - "postcss-modules-local-by-default": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz", - "integrity": "sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==", - "requires": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - } - }, - "postcss-modules-scope": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", - "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", - "requires": { - "postcss-selector-parser": "^6.0.4" - } - }, - "postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "requires": { - "icss-utils": "^5.0.0" - } - }, - "postcss-nested": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", - "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", - "requires": { - "postcss-selector-parser": "^6.0.11" - } - }, - "postcss-nesting": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-10.2.0.tgz", - "integrity": "sha512-EwMkYchxiDiKUhlJGzWsD9b2zvq/r2SSubcRrgP+jujMXFzqvANLt16lJANC+5uZ6hjI7lpRmI6O8JIl+8l1KA==", - "requires": { - "@csstools/selector-specificity": "^2.0.0", - "postcss-selector-parser": "^6.0.10" - } - }, - "postcss-normalize": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize/-/postcss-normalize-10.0.1.tgz", - "integrity": "sha512-+5w18/rDev5mqERcG3W5GZNMJa1eoYYNGo8gB7tEwaos0ajk3ZXAI4mHGcNT47NE+ZnZD1pEpUOFLvltIwmeJA==", - "requires": { - "@csstools/normalize.css": "*", - "postcss-browser-comments": "^4", - "sanitize.css": "*" - } - }, - "postcss-normalize-charset": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", - "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", - "requires": {} - }, - "postcss-normalize-display-values": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", - "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-positions": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", - "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-repeat-style": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", - "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-string": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", - "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-timing-functions": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", - "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-unicode": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", - "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", - "requires": { - "browserslist": "^4.21.4", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", - "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", - "requires": { - "normalize-url": "^6.0.1", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-whitespace": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", - "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-opacity-percentage": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.3.tgz", - "integrity": "sha512-An6Ba4pHBiDtyVpSLymUUERMo2cU7s+Obz6BTrS+gxkbnSBNKSuD0AVUc+CpBMrpVPKKfoVz0WQCX+Tnst0i4A==", - "requires": {} - }, - "postcss-ordered-values": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", - "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", - "requires": { - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", + "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", + "dev": true + } } }, - "postcss-overflow-shorthand": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.4.tgz", - "integrity": "sha512-otYl/ylHK8Y9bcBnPLo3foYFLL6a6Ak+3EQBPOTR7luMYCOsiVTUk1iLvNf6tVPNGXcoL9Hoz37kpfriRIFb4A==", + "postcss-modules": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules/-/postcss-modules-6.0.0.tgz", + "integrity": "sha512-7DGfnlyi/ju82BRzTIjWS5C4Tafmzl3R79YP/PASiocj+aa6yYphHhhKUOEoXQToId5rgyFgJ88+ccOUydjBXQ==", + "dev": true, "requires": { - "postcss-value-parser": "^4.2.0" + "generic-names": "^4.0.0", + "icss-utils": "^5.1.0", + "lodash.camelcase": "^4.3.0", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "string-hash": "^1.1.1" } }, - "postcss-page-break": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", - "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", + "postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "dev": true, "requires": {} }, - "postcss-place": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-7.0.5.tgz", - "integrity": "sha512-wR8igaZROA6Z4pv0d+bvVrvGY4GVHihBCBQieXFY3kuSuMyOmEnnfFzHl/tQuqHZkfkIVBEbDvYcFfHmpSet9g==", - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-preset-env": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-7.8.3.tgz", - "integrity": "sha512-T1LgRm5uEVFSEF83vHZJV2z19lHg4yJuZ6gXZZkqVsqv63nlr6zabMH3l4Pc01FQCyfWVrh2GaUeCVy9Po+Aag==", - "requires": { - "@csstools/postcss-cascade-layers": "^1.1.1", - "@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.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.13", - "browserslist": "^4.21.4", - "css-blank-pseudo": "^3.0.3", - "css-has-pseudo": "^3.0.4", - "css-prefers-color-scheme": "^6.0.3", - "cssdb": "^7.1.0", - "postcss-attribute-case-insensitive": "^5.0.2", - "postcss-clamp": "^4.1.0", - "postcss-color-functional-notation": "^4.2.4", - "postcss-color-hex-alpha": "^8.0.4", - "postcss-color-rebeccapurple": "^7.1.1", - "postcss-custom-media": "^8.0.2", - "postcss-custom-properties": "^12.1.10", - "postcss-custom-selectors": "^6.0.3", - "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.5", - "postcss-image-set-function": "^4.0.7", - "postcss-initial": "^4.0.1", - "postcss-lab-function": "^4.2.1", - "postcss-logical": "^5.0.4", - "postcss-media-minmax": "^5.0.0", - "postcss-nesting": "^10.2.0", - "postcss-opacity-percentage": "^1.1.2", - "postcss-overflow-shorthand": "^3.0.4", - "postcss-page-break": "^3.0.4", - "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.1", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-pseudo-class-any-link": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.6.tgz", - "integrity": "sha512-9sCtZkO6f/5ML9WcTLcIyV1yz9D1rf0tWc+ulKcvV30s0iZKS/ONyETvoWsr6vnrmW+X+KmuK3gV/w5EWnT37w==", - "requires": { - "postcss-selector-parser": "^6.0.10" - } - }, - "postcss-reduce-initial": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz", - "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==", + "postcss-modules-local-by-default": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", + "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", + "dev": true, "requires": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0" + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" } }, - "postcss-reduce-transforms": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", - "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", + "postcss-modules-scope": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", + "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", + "dev": true, "requires": { - "postcss-value-parser": "^4.2.0" + "postcss-selector-parser": "^6.0.4" } }, - "postcss-replace-overflow-wrap": { + "postcss-modules-values": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", - "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", - "requires": {} - }, - "postcss-selector-not": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-6.0.1.tgz", - "integrity": "sha512-1i9affjAe9xu/y9uqWH+tD4r6/hDaXJruk8xn2x1vzxC2U3J3LKO3zJW4CyxlNhA56pADJ/djpEwpH1RClI2rQ==", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, "requires": { - "postcss-selector-parser": "^6.0.10" + "icss-utils": "^5.0.0" } }, "postcss-selector-parser": { - "version": "6.0.13", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", - "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, "requires": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, - "postcss-svgo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", - "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", - "requires": { - "postcss-value-parser": "^4.2.0", - "svgo": "^2.7.0" - }, - "dependencies": { - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" - }, - "css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "requires": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - } - }, - "css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", - "requires": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" - } - }, - "dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - } - }, - "domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "requires": { - "domelementtype": "^2.2.0" - } - }, - "domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "requires": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - } - }, - "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" - }, - "mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "svgo": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", - "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", - "requires": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^4.1.3", - "css-tree": "^1.1.3", - "csso": "^4.2.0", - "picocolors": "^1.0.0", - "stable": "^0.1.8" - } - } - } - }, - "postcss-unique-selectors": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", - "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", - "requires": { - "postcss-selector-parser": "^6.0.5" - } - }, "postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==" + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "peer": true }, "prepend-http": { "version": "2.0.0", @@ -39113,20 +29513,6 @@ "fast-diff": "^1.1.2" } }, - "pretty-bytes": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", - "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==" - }, - "pretty-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", - "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", - "requires": { - "lodash": "^4.17.20", - "renderkid": "^3.0.0" - } - }, "pretty-format": { "version": "26.6.2", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", @@ -39184,36 +29570,11 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, - "promise": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", - "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", - "requires": { - "asap": "~2.0.6" - } - }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", - "optional": true, - "peer": true - }, - "promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "optional": true, - "peer": true, - "requires": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - } - }, "prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, "requires": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" @@ -39252,26 +29613,16 @@ } } }, - "proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "requires": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "dependencies": { - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" - } - } + "property-information": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", + "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==" }, "psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true }, "pump": { "version": "3.0.0", @@ -39286,13 +29637,13 @@ "punycode": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==" + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true }, "punycode.js": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", - "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", - "peer": true + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==" }, "pupa": { "version": "2.1.1", @@ -39303,43 +29654,17 @@ "escape-goat": "^2.0.0" } }, - "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==" - }, - "qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "requires": { - "side-channel": "^1.0.4" - } - }, "querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" - }, - "quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "optional": true, - "peer": true - }, - "raf": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", - "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", - "requires": { - "performance-now": "^2.1.0" - } + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true }, "raf-schd": { "version": "4.0.3", @@ -39363,45 +29688,6 @@ } } }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" - }, - "raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "requires": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "dependencies": { - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - } - } - }, "rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -39423,40 +29709,11 @@ } }, "react": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", - "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, - "react-app-polyfill": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-3.0.0.tgz", - "integrity": "sha512-sZ41cxiU5llIB003yxxQBYrARBqe0repqPTTYBTmMqTz9szeBbE37BehCE891NZsmdZqqP+xWKdT3eo3vOzN8w==", - "requires": { - "core-js": "^3.19.2", - "object-assign": "^4.1.1", - "promise": "^8.1.0", - "raf": "^3.4.1", - "regenerator-runtime": "^0.13.9", - "whatwg-fetch": "^3.6.2" - } - }, - "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==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "requires": { - "semver": "^5.6.0" - }, - "dependencies": { - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" - } + "loose-envify": "^1.1.0" } }, "react-async-script": { @@ -39480,17 +29737,45 @@ "react-redux": "^7.2.0", "redux": "^4.0.4", "use-memo-one": "^1.1.1" + }, + "dependencies": { + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "react-redux": { + "version": "7.2.9", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz", + "integrity": "sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==", + "requires": { + "@babel/runtime": "^7.15.4", + "@types/react-redux": "^7.1.20", + "hoist-non-react-statics": "^3.3.2", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^17.0.2" + } + }, + "redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "requires": { + "@babel/runtime": "^7.9.2" + } + } } }, "react-bootstrap": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.8.0.tgz", - "integrity": "sha512-e/aNtxl0Z2ozrIaR82jr6Zz7ss9GSoaXpQaxmvtDUsTZIq/XalkduR/ZXP6vbQHz2T4syvjA+4FbtwELxxmpww==", + "version": "2.10.4", + "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.10.4.tgz", + "integrity": "sha512-W3398nBM2CBfmGP2evneEO3ZZwEMPtHs72q++eNw60uDGDAdiGn0f9yNys91eo7/y8CTF5Ke1C0QO8JFVPU40Q==", "requires": { - "@babel/runtime": "^7.21.0", + "@babel/runtime": "^7.24.7", "@restart/hooks": "^0.4.9", - "@restart/ui": "^1.6.3", - "@types/react-transition-group": "^4.4.5", + "@restart/ui": "^1.6.9", + "@types/react-transition-group": "^4.4.6", "classnames": "^2.3.2", "dom-helpers": "^5.2.1", "invariant": "^2.2.4", @@ -39504,123 +29789,31 @@ "react-datepicker": { "version": "7.3.0", "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-7.3.0.tgz", - "integrity": "sha512-EqRKLAtLZUTztiq6a+tjSjQX9ES0Xd229JPckAtyZZ4GoY3rtvNWAzkYZnQUf6zTWT50Ki0+t+W9VRQIkSJLfg==", - "requires": { - "@floating-ui/react": "^0.26.2", - "clsx": "^2.1.0", - "date-fns": "^3.3.1", - "prop-types": "^15.7.2", - "react-onclickoutside": "^6.13.0" - }, - "dependencies": { - "clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" - }, - "date-fns": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", - "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==" - } - } - }, - "react-dev-utils": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", - "integrity": "sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==", - "requires": { - "@babel/code-frame": "^7.16.0", - "address": "^1.1.2", - "browserslist": "^4.18.1", - "chalk": "^4.1.2", - "cross-spawn": "^7.0.3", - "detect-port-alt": "^1.1.6", - "escape-string-regexp": "^4.0.0", - "filesize": "^8.0.6", - "find-up": "^5.0.0", - "fork-ts-checker-webpack-plugin": "^6.5.0", - "global-modules": "^2.0.0", - "globby": "^11.0.4", - "gzip-size": "^6.0.0", - "immer": "^9.0.7", - "is-root": "^2.1.0", - "loader-utils": "^3.2.0", - "open": "^8.4.0", - "pkg-up": "^3.1.0", - "prompts": "^2.4.2", - "react-error-overlay": "^6.0.11", - "recursive-readdir": "^2.2.2", - "shell-quote": "^1.7.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "dependencies": { - "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" - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "requires": { - "p-locate": "^5.0.0" - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "requires": { - "p-limit": "^3.0.2" - } + "integrity": "sha512-EqRKLAtLZUTztiq6a+tjSjQX9ES0Xd229JPckAtyZZ4GoY3rtvNWAzkYZnQUf6zTWT50Ki0+t+W9VRQIkSJLfg==", + "requires": { + "@floating-ui/react": "^0.26.2", + "clsx": "^2.1.0", + "date-fns": "^3.3.1", + "prop-types": "^15.7.2", + "react-onclickoutside": "^6.13.0" + }, + "dependencies": { + "date-fns": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==" } } }, "react-dom": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", - "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "requires": { "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "scheduler": "^0.20.2" + "scheduler": "^0.23.2" } }, - "react-error-overlay": { - "version": "6.0.11", - "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", - "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" - }, - "react-fast-compare": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", - "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==", - "dev": true - }, "react-google-recaptcha": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/react-google-recaptcha/-/react-google-recaptcha-3.1.0.tgz", @@ -39631,11 +29824,11 @@ } }, "react-i18next": { - "version": "11.18.6", - "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.18.6.tgz", - "integrity": "sha512-yHb2F9BiT0lqoQDt8loZ5gWP331GwctHz9tYQ8A2EIEUu+CcEdjBLQWli1USG3RdWQt3W+jqQLg/d4rrQR96LA==", + "version": "12.3.1", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-12.3.1.tgz", + "integrity": "sha512-5v8E2XjZDFzK7K87eSwC7AJcAkcLt5xYZ4+yTPDAW1i7C93oOY1dnr4BaQM7un4Hm+GmghuiPvevWwlca5PwDA==", "requires": { - "@babel/runtime": "^7.14.5", + "@babel/runtime": "^7.20.6", "html-parse-stringify": "^3.0.1" } }, @@ -39669,175 +29862,43 @@ "integrity": "sha512-C5DAvJkfzR2JK9YixZ3oyF9x6R4LW6nzTpIXrl9Oujxi4uqP9SzVVCjl+JLM3tSdqdjAx/oWZK3dTVBSR73Q+w==" }, "react-onclickoutside": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.13.0.tgz", - "integrity": "sha512-ty8So6tcUpIb+ZE+1HAhbLROvAIJYyJe/1vRrrcmW+jLsaM+/powDRqxzo6hSh9CuRZGSL1Q8mvcF5WRD93a0A==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.13.1.tgz", + "integrity": "sha512-LdrrxK/Yh9zbBQdFbMTXPp3dTSN9B+9YJQucdDu3JNKRrbdU+H+/TVONJoWtOwy4II8Sqf1y/DTI6w/vGPYW0w==", "requires": {} }, - "react-popper": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz", - "integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==", - "dev": true, - "requires": { - "react-fast-compare": "^3.0.1", - "warning": "^4.0.2" - } - }, "react-redux": { - "version": "7.2.9", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz", - "integrity": "sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.1.2.tgz", + "integrity": "sha512-0OA4dhM1W48l3uzmv6B7TXPCGmokUU4p1M44DGN2/D9a1FjVPukVjER1PcPX97jIg6aUeLq1XJo1IpfbgULn0w==", "requires": { - "@babel/runtime": "^7.15.4", - "@types/react-redux": "^7.1.20", - "hoist-non-react-statics": "^3.3.2", - "loose-envify": "^1.4.0", - "prop-types": "^15.7.2", - "react-is": "^17.0.2" - }, - "dependencies": { - "react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" - } + "@types/use-sync-external-store": "^0.0.3", + "use-sync-external-store": "^1.0.0" } }, - "react-refresh": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", - "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==" - }, "react-router": { - "version": "6.25.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.25.1.tgz", - "integrity": "sha512-u8ELFr5Z6g02nUtpPAggP73Jigj1mRePSwhS/2nkTrlPU5yEkH1vYzWNyvSnSzeeE2DNqWdH+P8OhIh9wuXhTw==", + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.26.0.tgz", + "integrity": "sha512-wVQq0/iFYd3iZ9H2l3N3k4PL8EEHcb0XlU2Na8nEwmiXgIUElEH6gaJDtUQxJ+JFzmIXaQjfdpcGWaM6IoQGxg==", "requires": { - "@remix-run/router": "1.18.0" + "@remix-run/router": "1.19.0" } }, "react-router-dom": { - "version": "6.25.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.25.1.tgz", - "integrity": "sha512-0tUDpbFvk35iv+N89dWNrJp+afLgd+y4VtorJZuOCXK0kkCWjEvb3vTJM++SYvMEpbVwXKf3FjeVveVEb6JpDQ==", + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.26.0.tgz", + "integrity": "sha512-RRGUIiDtLrkX3uYcFiCIxKFWMcWQGMojpYZfcstc63A1+sSnVgILGIm9gNUA6na3Fm1QuPGSBQH2EMbAZOnMsQ==", "requires": { - "@remix-run/router": "1.18.0", - "react-router": "6.25.1" - } - }, - "react-scripts": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", - "integrity": "sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==", - "requires": { - "@babel/core": "^7.16.0", - "@pmmmwh/react-refresh-webpack-plugin": "^0.5.3", - "@svgr/webpack": "^5.5.0", - "babel-jest": "^27.4.2", - "babel-loader": "^8.2.3", - "babel-plugin-named-asset-import": "^0.3.8", - "babel-preset-react-app": "^10.0.1", - "bfj": "^7.0.2", - "browserslist": "^4.18.1", - "camelcase": "^6.2.1", - "case-sensitive-paths-webpack-plugin": "^2.4.0", - "css-loader": "^6.5.1", - "css-minimizer-webpack-plugin": "^3.2.0", - "dotenv": "^10.0.0", - "dotenv-expand": "^5.1.0", - "eslint": "^8.3.0", - "eslint-config-react-app": "^7.0.1", - "eslint-webpack-plugin": "^3.1.1", - "file-loader": "^6.2.0", - "fs-extra": "^10.0.0", - "fsevents": "^2.3.2", - "html-webpack-plugin": "^5.5.0", - "identity-obj-proxy": "^3.0.0", - "jest": "^27.4.3", - "jest-resolve": "^27.4.2", - "jest-watch-typeahead": "^1.0.0", - "mini-css-extract-plugin": "^2.4.5", - "postcss": "^8.4.4", - "postcss-flexbugs-fixes": "^5.0.2", - "postcss-loader": "^6.2.1", - "postcss-normalize": "^10.0.1", - "postcss-preset-env": "^7.0.1", - "prompts": "^2.4.2", - "react-app-polyfill": "^3.0.0", - "react-dev-utils": "^12.0.1", - "react-refresh": "^0.11.0", - "resolve": "^1.20.0", - "resolve-url-loader": "^4.0.0", - "sass-loader": "^12.3.0", - "semver": "^7.3.5", - "source-map-loader": "^3.0.0", - "style-loader": "^3.3.1", - "tailwindcss": "^3.0.2", - "terser-webpack-plugin": "^5.2.5", - "webpack": "^5.64.4", - "webpack-dev-server": "^4.6.0", - "webpack-manifest-plugin": "^4.0.2", - "workbox-webpack-plugin": "^6.4.1" - }, - "dependencies": { - "babel-jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", - "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", - "requires": { - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^27.5.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - } - }, - "babel-plugin-jest-hoist": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", - "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", - "requires": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.0.0", - "@types/babel__traverse": "^7.0.6" - } - }, - "babel-preset-jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", - "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", - "requires": { - "babel-plugin-jest-hoist": "^27.5.1", - "babel-preset-current-node-syntax": "^1.0.0" - } - }, - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" - }, - "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" - } - } + "@remix-run/router": "1.19.0", + "react-router": "6.26.0" } }, "react-toastify": { - "version": "9.1.3", - "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.1.3.tgz", - "integrity": "sha512-fPfb8ghtn/XMxw3LkxQBk3IyagNpF/LIKjOBflbexr2AWxAH1MJgvnESwEwBn9liLFXgTKWgBSdZpw9m4OTHTg==", + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-10.0.5.tgz", + "integrity": "sha512-mNKt2jBXJg4O7pSdbNUfDdTsK9FIdikfsIE/yUCxbAEXl4HMyJaivrVFcn3Elvt5xvCQYhUZm+hqTIu1UXM3Pw==", "requires": { - "clsx": "^1.1.1" + "clsx": "^2.1.0" } }, "react-tooltip": { @@ -39864,80 +29925,11 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, "requires": { "pify": "^2.3.0" } }, - "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "optional": true, - "peer": true, - "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "dependencies": { - "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "optional": true, - "peer": true - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "optional": true, - "peer": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "optional": true, - "peer": true - }, - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "optional": true, - "peer": true - } - } - }, - "read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "optional": true, - "peer": true, - "requires": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "dependencies": { - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "optional": true, - "peer": true - } - } - }, "readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -39952,46 +29944,37 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "devOptional": true, "requires": { "picomatch": "^2.2.1" } }, - "recursive-readdir": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", - "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", - "requires": { - "minimatch": "^3.0.5" - } - }, "redent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "devOptional": true, + "dev": true, "requires": { "indent-string": "^4.0.0", "strip-indent": "^3.0.0" } }, "redux": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", - "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", - "requires": { - "@babel/runtime": "^7.9.2" - } + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==" }, "redux-thunk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz", - "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", + "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", "requires": {} }, "reflect.getprototypeof": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "dev": true, "requires": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -40005,38 +29988,37 @@ "regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true }, "regenerate-unicode-properties": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz", "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==", + "dev": true, "requires": { "regenerate": "^1.4.2" } }, - "regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" - }, "regenerator-transform": { "version": "0.15.2", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, "requires": { "@babel/runtime": "^7.8.4" } }, - "regex-parser": { - "version": "2.2.11", - "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.11.tgz", - "integrity": "sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q==" + "regex": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/regex/-/regex-4.3.2.tgz", + "integrity": "sha512-kK/AA3A9K6q2js89+VMymcboLOlF5lZRCYJv3gzszXFHBr6kO6qLGzbm+UIugBEV8SMMKCTR59txoY6ctRHYVw==" }, "regexp.prototype.flags": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "dev": true, "requires": { "call-bind": "^1.0.6", "define-properties": "^1.2.1", @@ -40048,6 +30030,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dev": true, "requires": { "@babel/regjsgen": "^0.8.0", "regenerate": "^1.4.2", @@ -40079,6 +30062,7 @@ "version": "0.9.1", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dev": true, "requires": { "jsesc": "~0.5.0" }, @@ -40086,14 +30070,16 @@ "jsesc": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==" + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true } } }, - "relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==" + "rehackt": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/rehackt/-/rehackt-0.1.0.tgz", + "integrity": "sha512-7kRDOuLHB87D/JESKxQoRwv4DzbIdwkAGQ7p6QKGdVlY1IZheUnVhlk/4UZlNUVxdAXpyxikE3URsG067ybVzw==", + "requires": {} }, "remarkable": { "version": "1.7.4", @@ -40104,76 +30090,6 @@ "autolinker": "~0.28.0" } }, - "renderkid": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", - "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", - "requires": { - "css-select": "^4.1.3", - "dom-converter": "^0.2.0", - "htmlparser2": "^6.1.0", - "lodash": "^4.17.21", - "strip-ansi": "^6.0.1" - }, - "dependencies": { - "css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "requires": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - } - }, - "dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - } - }, - "domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "requires": { - "domelementtype": "^2.2.0" - } - }, - "domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "requires": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - } - }, - "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" - }, - "htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - } - } - }, "repeat-element": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", @@ -40184,93 +30100,28 @@ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==" }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "optional": true, - "peer": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "optional": true, - "peer": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "optional": true, - "peer": true - }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "optional": true, - "peer": true, - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "optional": true, - "peer": true - } - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true }, "require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true }, "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true }, "reselect": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", - "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==" + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==" }, "resolve": { "version": "1.22.8", @@ -40286,6 +30137,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, "requires": { "resolve-from": "^5.0.0" }, @@ -40293,7 +30145,8 @@ "resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==" + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true } } }, @@ -40342,64 +30195,22 @@ } } }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" - }, - "resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true - }, - "resolve-url-loader": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-4.0.0.tgz", - "integrity": "sha512-05VEMczVREcbtT7Bz+C+96eUO5HDNvdthIiMB34t7FcF8ehcu4wC0sSgPUubs3XW2Q3CNLJk/BJrCU9wVRymiA==", - "requires": { - "adjust-sourcemap-loader": "^4.0.0", - "convert-source-map": "^1.7.0", - "loader-utils": "^2.0.0", - "postcss": "^7.0.35", - "source-map": "0.6.1" - }, - "dependencies": { - "loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - }, - "picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" - }, - "postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "requires": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" + }, + "resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true + }, "resolve.exports": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.1.tgz", - "integrity": "sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==" + "integrity": "sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==", + "dev": true }, "response-iterator": { "version": "0.2.6", @@ -40416,13 +30227,30 @@ } }, "restore-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "dev": true, "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "dependencies": { + "onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "requires": { + "mimic-function": "^5.0.0" + } + }, + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + } } }, "restructure": { @@ -40430,28 +30258,23 @@ "resolved": "https://registry.npmjs.org/restructure/-/restructure-3.0.0.tgz", "integrity": "sha512-Xj8/MEIhhfj9X2rmD9iJ4Gga9EFqVlpMj3vfLnV2r/Mh5jRMryNV+6lWh9GdJtDBcBSPIqzRdfBQ3wDtNFv/uw==" }, - "retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "optional": true, - "peer": true - }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true }, "rfdc": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", - "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "dev": true }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, "requires": { "glob": "^7.1.3" } @@ -40462,44 +30285,30 @@ "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" }, "rollup": { - "version": "2.79.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", - "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", - "requires": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.3.tgz", + "integrity": "sha512-7sqRtBNnEbcBtMeRVc6VRsJMmpI+JU1z9VTvW8D4gXIYQFz0aLcsE6rRkyghZkLfEgUZgVvOG7A5CVz/VW5GIA==", + "requires": { + "@rollup/rollup-android-arm-eabi": "4.21.3", + "@rollup/rollup-android-arm64": "4.21.3", + "@rollup/rollup-darwin-arm64": "4.21.3", + "@rollup/rollup-darwin-x64": "4.21.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.21.3", + "@rollup/rollup-linux-arm-musleabihf": "4.21.3", + "@rollup/rollup-linux-arm64-gnu": "4.21.3", + "@rollup/rollup-linux-arm64-musl": "4.21.3", + "@rollup/rollup-linux-powerpc64le-gnu": "4.21.3", + "@rollup/rollup-linux-riscv64-gnu": "4.21.3", + "@rollup/rollup-linux-s390x-gnu": "4.21.3", + "@rollup/rollup-linux-x64-gnu": "4.21.3", + "@rollup/rollup-linux-x64-musl": "4.21.3", + "@rollup/rollup-win32-arm64-msvc": "4.21.3", + "@rollup/rollup-win32-ia32-msvc": "4.21.3", + "@rollup/rollup-win32-x64-msvc": "4.21.3", + "@types/estree": "1.0.5", "fsevents": "~2.3.2" } }, - "rollup-plugin-terser": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", - "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", - "requires": { - "@babel/code-frame": "^7.10.4", - "jest-worker": "^26.2.1", - "serialize-javascript": "^4.0.0", - "terser": "^5.0.0" - }, - "dependencies": { - "jest-worker": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", - "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" - } - }, - "serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "requires": { - "randombytes": "^2.1.0" - } - } - } - }, "run-async": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", @@ -40509,6 +30318,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, "requires": { "queue-microtask": "^1.2.2" } @@ -40525,6 +30335,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, "requires": { "call-bind": "^1.0.7", "get-intrinsic": "^1.2.4", @@ -40541,6 +30352,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, "requires": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -40572,15 +30384,10 @@ } } }, - "sanitize.css": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-13.0.0.tgz", - "integrity": "sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA==" - }, "sass": { - "version": "1.77.4", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.4.tgz", - "integrity": "sha512-vcF3Ckow6g939GMA4PeU7b2K/9FALXk2KF9J87txdHzXbUF9XRQRwSxcAs/fGaTnJeBFd7UoV22j3lzMLdM0Pw==", + "version": "1.77.8", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.8.tgz", + "integrity": "sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ==", "devOptional": true, "requires": { "chokidar": ">=3.0.0 <4.0.0", @@ -40588,176 +30395,28 @@ "source-map-js": ">=0.6.2 <2.0.0" } }, - "sass-graph": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-4.0.1.tgz", - "integrity": "sha512-5YCfmGBmxoIRYHnKK2AKzrAkCoQ8ozO+iumT8K4tXJXRVCPf+7s1/9KxTSW3Rbvf+7Y7b4FR3mWyLnQr3PHocA==", - "optional": true, - "peer": true, - "requires": { - "glob": "^7.0.0", - "lodash": "^4.17.11", - "scss-tokenizer": "^0.4.3", - "yargs": "^17.2.1" - }, - "dependencies": { - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "optional": true, - "peer": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "optional": true, - "peer": true, - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "optional": true, - "peer": true - } - } - }, - "sass-loader": { - "version": "12.6.0", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.6.0.tgz", - "integrity": "sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA==", - "requires": { - "klona": "^2.0.4", - "neo-async": "^2.6.2" - } - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, "saxes": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "dev": true, "requires": { "xmlchars": "^2.2.0" } }, "scheduler": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", - "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, - "schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "requires": {} - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - } - } - }, - "scss-tokenizer": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.4.3.tgz", - "integrity": "sha512-raKLgf1LI5QMQnG+RxHz6oK0sL3x3I4FN2UDLqgLOGO8hodECNnNh5BXn7fAyBxrA8zVzdQizQ6XjNJQ+uBwMw==", - "optional": true, - "peer": true, - "requires": { - "js-base64": "^2.4.9", - "source-map": "^0.7.3" - }, - "dependencies": { - "source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "optional": true, - "peer": true - } - } - }, - "select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==" - }, - "selfsigned": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz", - "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==", + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", "requires": { - "node-forge": "^1" + "loose-envify": "^1.1.0" } }, "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "requires": { - "lru-cache": "^6.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true }, "semver-diff": { "version": "3.1.1", @@ -40776,146 +30435,11 @@ } } }, - "send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "requires": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - } - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "requires": { - "ee-first": "1.1.1" - } - }, - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" - } - } - }, - "serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "requires": { - "randombytes": "^2.1.0" - } - }, - "serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", - "requires": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==" - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" - } - } - }, - "serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "optional": true, - "peer": true - }, "set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, "requires": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -40929,6 +30453,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, "requires": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -40944,15 +30469,11 @@ "to-object-path": "^0.3.0" } }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "requires": { "shebang-regex": "^3.0.0" } @@ -40960,20 +30481,19 @@ "shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" - }, - "shell-quote": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", - "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==" + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true }, "shiki": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.10.3.tgz", - "integrity": "sha512-eneCLncGuvPdTutJuLyUGS8QNPAVFO5Trvld2wgEq1e002mwctAhJKeMGWtWVXOIEzmlcLRqcgPSorR6AVzOmQ==", - "peer": true, - "requires": { - "@shikijs/core": "1.10.3", + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.17.6.tgz", + "integrity": "sha512-RejGugKpDM75vh6YtF9R771acxHRDikC/01kxsUGW+Pnaz3pTY+c8aZB5CnD7p0vuFPs1HaoAIU/4E+NCfS+mQ==", + "requires": { + "@shikijs/core": "1.17.6", + "@shikijs/engine-javascript": "1.17.6", + "@shikijs/engine-oniguruma": "1.17.6", + "@shikijs/types": "1.17.6", + "@shikijs/vscode-textmate": "^9.2.2", "@types/hast": "^3.0.4" } }, @@ -40981,6 +30501,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, "requires": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -40993,6 +30514,21 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "requires": { + "is-arrayish": "^0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + } + } + }, "sirv": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.3.tgz", @@ -41007,12 +30543,14 @@ "sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true }, "slice-ansi": { "version": "5.0.0", @@ -41038,63 +30576,31 @@ } } }, - "smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "optional": true, - "peer": true - }, - "sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", - "requires": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" - } - }, - "socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "optional": true, - "peer": true, + "snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dev": true, "requires": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" + "dot-case": "^3.0.4", + "tslib": "^2.0.3" } }, - "source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" - }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" }, "source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" - }, - "source-map-loader": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-3.0.2.tgz", - "integrity": "sha512-BokxPoLjyl3iOrgkWaakaxqnelAJSS+0V+De0kKIq6lyWrXuiPgYTGp6z3iHmqljKAaLXwZa+ctD8GccRJeVvg==", - "requires": { - "abab": "^2.0.5", - "iconv-lite": "^0.6.3", - "source-map-js": "^1.0.1" - } + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==" }, "source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "devOptional": true, "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -41103,108 +30609,26 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "devOptional": true } } }, - "sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" - }, - "spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "optional": true, - "peer": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "optional": true, - "peer": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "optional": true, - "peer": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", - "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", - "optional": true, - "peer": true - }, - "spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "requires": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - } - }, - "spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "requires": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - } + "space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==" }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, - "sshpk": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", - "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", - "optional": true, - "peer": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==" - }, "stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, "requires": { "escape-string-regexp": "^2.0.0" }, @@ -41212,71 +30636,16 @@ "escape-string-regexp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true } } }, - "stackframe": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", - "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==" - }, "statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==" - }, - "stdout-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", - "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", - "optional": true, - "peer": true, - "requires": { - "readable-stream": "^2.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "optional": true, - "peer": true - }, - "readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "optional": true, - "peer": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "optional": true, - "peer": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "optional": true, - "peer": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true }, "string_decoder": { "version": "1.3.0", @@ -41302,16 +30671,12 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, "requires": { "char-regex": "^1.0.2", "strip-ansi": "^6.0.0" } }, - "string-natural-compare": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/string-natural-compare/-/string-natural-compare-3.0.1.tgz", - "integrity": "sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==" - }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -41333,6 +30698,7 @@ "version": "4.0.11", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "dev": true, "requires": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -41348,10 +30714,21 @@ "side-channel": "^1.0.6" } }, + "string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, "string.prototype.trim": { "version": "1.2.9", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, "requires": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -41363,6 +30740,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, "requires": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -41370,30 +30748,23 @@ } }, "string.prototype.trimstart": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", - "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" } }, - "stringify-object": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", - "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", "requires": { - "get-own-enumerable-property-symbols": "^3.0.0", - "is-obj": "^1.0.1", - "is-regexp": "^1.0.0" - }, - "dependencies": { - "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==" - } + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" } }, "strip-ansi": { @@ -41407,28 +30778,25 @@ "strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==" + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true }, "strip-color": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/strip-color/-/strip-color-0.1.0.tgz", "integrity": "sha512-p9LsUieSjWNNAxVCXLeilaDlmuUOrDS5/dF9znM1nZc7EGX5+zEFC0bEevsNIaldjlks+2jns5Siz6F9iK6jwA==" }, - "strip-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", - "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==" - }, "strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==" + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true }, "strip-indent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "devOptional": true, + "dev": true, "requires": { "min-indent": "^1.0.0" } @@ -41436,62 +30804,20 @@ "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" - }, - "style-loader": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.3.tgz", - "integrity": "sha512-53BiGLXAcll9maCYtZi2RCQZKa8NQQai5C4horqKyRmHj9H7QmcUyucrH+4KW/gBQbXM2AsB0axoEcFZPlfPcw==", - "requires": {} + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true }, - "stylehacks": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", - "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", - "requires": { - "browserslist": "^4.21.4", - "postcss-selector-parser": "^6.0.4" - } + "strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "peer": true }, "stylis": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" }, - "sucrase": { - "version": "3.33.0", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.33.0.tgz", - "integrity": "sha512-ARGC7vbufOHfpvyGcZZXFaXCMZ9A4fffOGC5ucOW7+WHDGlAe8LJdf3Jts1sWhDeiI1RSWrKy5Hodl+JWGdW2A==", - "requires": { - "@jridgewell/gen-mapping": "^0.3.2", - "commander": "^4.0.0", - "glob": "7.1.6", - "lines-and-columns": "^1.1.6", - "mz": "^2.7.0", - "pirates": "^4.0.1", - "ts-interface-checker": "^0.1.9" - }, - "dependencies": { - "commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==" - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -41504,6 +30830,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "dev": true, "requires": { "has-flag": "^4.0.0", "supports-color": "^7.0.0" @@ -41517,86 +30844,8 @@ "svg-parser": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", - "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" - }, - "svgo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", - "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", - "requires": { - "chalk": "^2.4.1", - "coa": "^2.0.2", - "css-select": "^2.0.0", - "css-select-base-adapter": "^0.1.1", - "css-tree": "1.0.0-alpha.37", - "csso": "^4.0.2", - "js-yaml": "^3.13.1", - "mkdirp": "~0.5.1", - "object.values": "^1.1.0", - "sax": "~1.2.4", - "stable": "^0.1.8", - "unquote": "~1.1.1", - "util.promisify": "~1.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" - }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "requires": { - "minimist": "^1.2.6" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } - } + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", + "dev": true }, "symbol-observable": { "version": "4.0.0", @@ -41606,12 +30855,13 @@ "symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true }, "synckit": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", - "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", + "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==", "dev": true, "requires": { "@pkgr/core": "^0.1.0", @@ -41623,127 +30873,22 @@ "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==" }, - "tailwindcss": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz", - "integrity": "sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==", - "requires": { - "@alloc/quick-lru": "^5.2.0", - "arg": "^5.0.2", - "chokidar": "^3.5.3", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.2.12", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "jiti": "^1.18.2", - "lilconfig": "^2.1.0", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.23", - "postcss-import": "^15.1.0", - "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.1", - "postcss-nested": "^6.0.1", - "postcss-selector-parser": "^6.0.11", - "resolve": "^1.22.2", - "sucrase": "^3.32.0" - }, - "dependencies": { - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "requires": { - "is-glob": "^4.0.3" - } - }, - "postcss-import": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", - "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", - "requires": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - } - } - } - }, - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" - }, - "tar": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", - "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", - "optional": true, - "peer": true, - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "dependencies": { - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "optional": true, - "peer": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "optional": true, - "peer": true - } - } - }, - "temp-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", - "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==" - }, - "tempy": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz", - "integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==", - "requires": { - "is-stream": "^2.0.0", - "temp-dir": "^2.0.0", - "type-fest": "^0.16.0", - "unique-string": "^2.0.0" - }, - "dependencies": { - "type-fest": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", - "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==" - } - } - }, "terminal-link": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "dev": true, "requires": { "ansi-escapes": "^4.2.1", "supports-hyperlinks": "^2.0.0" } }, "terser": { - "version": "5.19.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.19.0.tgz", - "integrity": "sha512-JpcpGOQLOXm2jsomozdMDpd5f8ZHh1rR48OFgWUH3QsyZcfPgv2qDCYbcDEAYNd4OZRj2bWYKpwdll/udZCk/Q==", + "version": "5.32.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.32.0.tgz", + "integrity": "sha512-v3Gtw3IzpBJ0ugkxEX8U0W6+TnPKRRCWGh1jC/iM/e3Ki5+qvO1L1EAZ56bZasc64aXHwRHNIQEzm6//i5cemQ==", + "optional": true, + "peer": true, "requires": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -41754,26 +30899,17 @@ "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "optional": true, + "peer": true } } }, - "terser-webpack-plugin": { - "version": "5.3.9", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", - "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", - "requires": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.8" - } - }, "test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, "requires": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", @@ -41783,28 +30919,15 @@ "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" - }, - "thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "requires": { - "any-promise": "^1.0.0" - } - }, - "thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "requires": { - "thenify": ">= 3.1.0 < 4" - } + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "peer": true }, "throat": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz", - "integrity": "sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==" + "integrity": "sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==", + "dev": true }, "throttle-debounce": { "version": "2.3.0", @@ -41859,11 +30982,6 @@ } } }, - "thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" - }, "tiny-inflate": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", @@ -41900,7 +31018,8 @@ "tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==" + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true }, "to-fast-properties": { "version": "2.0.0", @@ -41935,15 +31054,11 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "devOptional": true, "requires": { "is-number": "^7.0.0" } }, - "toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" - }, "toml": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/toml/-/toml-2.3.6.tgz", @@ -41959,6 +31074,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", + "dev": true, "requires": { "psl": "^1.1.33", "punycode": "^2.1.1", @@ -41969,7 +31085,8 @@ "universalify": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==" + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true } } }, @@ -41977,36 +31094,22 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "dev": true, "requires": { "punycode": "^2.1.1" } }, - "trim-newlines": { + "trim-lines": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", - "optional": true, - "peer": true - }, - "true-case-path": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", - "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", - "optional": true, - "peer": true, - "requires": { - "glob": "^7.1.2" - } - }, - "tryer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", - "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==" + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==" }, - "ts-interface-checker": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" + "ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "requires": {} }, "ts-invariant": { "version": "0.10.3", @@ -42020,6 +31123,7 @@ "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, "requires": { "@types/json5": "^0.0.29", "json5": "^1.0.2", @@ -42031,6 +31135,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, "requires": { "minimist": "^1.2.0" } @@ -42038,7 +31143,8 @@ "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==" + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true } } }, @@ -42047,53 +31153,218 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "requires": { - "tslib": "^1.8.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } - } - }, "tsx": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.16.2.tgz", - "integrity": "sha512-C1uWweJDgdtX2x600HjaFaucXTilT7tgUZHbOE4+ypskZ1OP8CRCSDkCxG6Vya9EwaFIVagWwpaVAn5wzypaqQ==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.1.tgz", + "integrity": "sha512-0flMz1lh74BR4wOvBjuh9olbnwqCPc35OOlfyzHba0Dc+QNUeWX/Gq2YTbnwcWPO3BMd8fkzRVrHcsR+a7z7rA==", "dev": true, "requires": { - "esbuild": "~0.21.5", + "esbuild": "~0.23.0", "fsevents": "~2.3.3", "get-tsconfig": "^4.7.5" + }, + "dependencies": { + "@esbuild/aix-ppc64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", + "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz", + "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", + "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", + "dev": true, + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz", + "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", + "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", + "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", + "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", + "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", + "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", + "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", + "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", + "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", + "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", + "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", + "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", + "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", + "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", + "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", + "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", + "dev": true, + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", + "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", + "dev": true, + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", + "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", + "dev": true, + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", + "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", + "dev": true, + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", + "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", + "dev": true, + "optional": true + }, + "esbuild": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", + "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", + "dev": true, + "requires": { + "@esbuild/aix-ppc64": "0.23.1", + "@esbuild/android-arm": "0.23.1", + "@esbuild/android-arm64": "0.23.1", + "@esbuild/android-x64": "0.23.1", + "@esbuild/darwin-arm64": "0.23.1", + "@esbuild/darwin-x64": "0.23.1", + "@esbuild/freebsd-arm64": "0.23.1", + "@esbuild/freebsd-x64": "0.23.1", + "@esbuild/linux-arm": "0.23.1", + "@esbuild/linux-arm64": "0.23.1", + "@esbuild/linux-ia32": "0.23.1", + "@esbuild/linux-loong64": "0.23.1", + "@esbuild/linux-mips64el": "0.23.1", + "@esbuild/linux-ppc64": "0.23.1", + "@esbuild/linux-riscv64": "0.23.1", + "@esbuild/linux-s390x": "0.23.1", + "@esbuild/linux-x64": "0.23.1", + "@esbuild/netbsd-x64": "0.23.1", + "@esbuild/openbsd-arm64": "0.23.1", + "@esbuild/openbsd-x64": "0.23.1", + "@esbuild/sunos-x64": "0.23.1", + "@esbuild/win32-arm64": "0.23.1", + "@esbuild/win32-ia32": "0.23.1", + "@esbuild/win32-x64": "0.23.1" + } + } } }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "optional": true, - "peer": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", - "optional": true, - "peer": true - }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "peer": true, "requires": { "prelude-ls": "^1.2.1" } @@ -42101,26 +31372,19 @@ "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true }, "type-fest": { "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==" }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, "typed-array-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, "requires": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -42131,6 +31395,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, "requires": { "call-bind": "^1.0.7", "for-each": "^0.3.3", @@ -42143,6 +31408,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, "requires": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", @@ -42156,6 +31422,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, "requires": { "call-bind": "^1.0.7", "for-each": "^0.3.3", @@ -42174,28 +31441,27 @@ "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, "requires": { "is-typedarray": "^1.0.0" } }, "typedoc": { - "version": "0.26.3", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.3.tgz", - "integrity": "sha512-6d2Sw9disvvpdk4K7VNjKr5/3hzijtfQVHRthhDqJgnhMHy1wQz4yPMJVKXElvnZhFr0nkzo+GzjXDTRV5yLpg==", - "peer": true, + "version": "0.26.7", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.7.tgz", + "integrity": "sha512-gUeI/Wk99vjXXMi8kanwzyhmeFEGv1LTdTQsiyIsmSYsBebvFxhbcyAx7Zjo4cMbpLGxM4Uz3jVIjksu/I2v6Q==", "requires": { "lunr": "^2.3.9", "markdown-it": "^14.1.0", "minimatch": "^9.0.5", - "shiki": "^1.9.1", - "yaml": "^2.4.5" + "shiki": "^1.16.2", + "yaml": "^2.5.1" }, "dependencies": { "brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "peer": true, "requires": { "balanced-match": "^1.0.0" } @@ -42204,16 +31470,14 @@ "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "peer": true, "requires": { "brace-expansion": "^2.0.1" } }, "yaml": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", - "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", - "peer": true + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==" } } }, @@ -42224,20 +31488,20 @@ "requires": {} }, "typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==" + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", + "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==" }, "uc.micro": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", - "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", - "peer": true + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==" }, "unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, "requires": { "call-bind": "^1.0.2", "has-bigints": "^1.0.2", @@ -42257,19 +31521,22 @@ } }, "undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "devOptional": true }, "unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==" + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true }, "unicode-match-property-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, "requires": { "unicode-canonical-property-names-ecmascript": "^2.0.0", "unicode-property-aliases-ecmascript": "^2.0.0" @@ -42278,7 +31545,8 @@ "unicode-match-property-value-ecmascript": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", - "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==" + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "dev": true }, "unicode-properties": { "version": "1.4.1", @@ -42292,7 +31560,8 @@ "unicode-property-aliases-ecmascript": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==" + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true }, "unicode-trie": { "version": "2.0.0", @@ -42314,37 +31583,67 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, "requires": { "crypto-random-string": "^2.0.0" } }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + "unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "requires": { + "@types/unist": "^3.0.0" + } + }, + "unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "requires": { + "@types/unist": "^3.0.0" + } + }, + "unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "requires": { + "@types/unist": "^3.0.0" + } + }, + "unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "requires": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + } + }, + "unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "requires": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + } }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" - }, - "unquote": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", - "integrity": "sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg==" - }, - "upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true }, "update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.1.2", + "picocolors": "^1.0.1" } }, "update-notifier": { @@ -42385,6 +31684,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, "requires": { "punycode": "^2.1.0" } @@ -42393,6 +31693,7 @@ "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dev": true, "requires": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" @@ -42413,41 +31714,28 @@ "integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==", "requires": {} }, + "use-sync-external-store": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", + "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==", + "requires": {} + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, - "util.promisify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", - "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.2", - "has-symbols": "^1.0.1", - "object.getownpropertydescriptors": "^2.1.0" - } - }, - "utila": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==" - }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true }, "v8-to-istanbul": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", + "dev": true, "requires": { "@types/istanbul-lib-coverage": "^2.0.1", "convert-source-map": "^1.6.0", @@ -42457,44 +31745,217 @@ "source-map": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==" + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true + } + } + }, + "vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "requires": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + } + }, + "vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "requires": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + } + }, + "vite": { + "version": "5.4.7", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.7.tgz", + "integrity": "sha512-5l2zxqMEPVENgvzTuBpHer2awaetimj2BGkhBPdnwKbPNOlHsODU+oiazEZzLK7KhAnOrO+XGYJYn4ZlUhDtDQ==", + "requires": { + "esbuild": "^0.21.3", + "fsevents": "~2.3.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + } + }, + "vite-plugin-environment": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/vite-plugin-environment/-/vite-plugin-environment-1.1.3.tgz", + "integrity": "sha512-9LBhB0lx+2lXVBEWxFZC+WO7PKEyE/ykJ7EPWCq95NEcCpblxamTbs5Dm3DLBGzwODpJMEnzQywJU8fw6XGGGA==", + "requires": {} + }, + "vite-plugin-svgr": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/vite-plugin-svgr/-/vite-plugin-svgr-4.2.0.tgz", + "integrity": "sha512-SC7+FfVtNQk7So0XMjrrtLAbEC8qjFPifyD7+fs/E6aaNdVde6umlVVh0QuwDLdOMu7vp5RiGFsB70nj5yo0XA==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^5.0.5", + "@svgr/core": "^8.1.0", + "@svgr/plugin-jsx": "^8.1.0" + }, + "dependencies": { + "@rollup/pluginutils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", + "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", + "dev": true, + "requires": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + } + }, + "@svgr/babel-plugin-add-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "dev": true, + "requires": {} + }, + "@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", + "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "dev": true, + "requires": {} + }, + "@svgr/babel-plugin-svg-dynamic-title": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", + "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "dev": true, + "requires": {} + }, + "@svgr/babel-plugin-svg-em-dimensions": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", + "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "dev": true, + "requires": {} + }, + "@svgr/babel-plugin-transform-react-native-svg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", + "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", + "dev": true, + "requires": {} + }, + "@svgr/babel-plugin-transform-svg-component": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", + "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "dev": true, + "requires": {} + }, + "@svgr/babel-preset": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", + "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", + "dev": true, + "requires": { + "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", + "@svgr/babel-plugin-transform-svg-component": "8.0.0" + } + }, + "@svgr/core": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", + "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "dev": true, + "requires": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^8.1.3", + "snake-case": "^3.0.4" + } + }, + "@svgr/hast-util-to-babel-ast": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", + "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "dev": true, + "requires": { + "@babel/types": "^7.21.3", + "entities": "^4.4.0" + } + }, + "@svgr/plugin-jsx": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", + "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", + "dev": true, + "requires": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "@svgr/hast-util-to-babel-ast": "8.0.0", + "svg-parser": "^2.0.4" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + }, + "cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "requires": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + } + }, + "estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } } } }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "optional": true, - "peer": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "optional": true, - "peer": true, + "vite-tsconfig-paths": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-5.0.1.tgz", + "integrity": "sha512-yqwv+LstU7NwPeNqajZzLEBVpUFU6Dugtb2P84FXuvaoYA+/70l9MHE+GYfYAycVyPSDYZ7mjOFuYBRqlEpTig==", "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" + "debug": "^4.1.1", + "globrex": "^0.1.2", + "tsconfck": "^3.0.3" }, "dependencies": { - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", - "optional": true, - "peer": true + "tsconfck": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.3.tgz", + "integrity": "sha512-ulNZP1SVpRDesxeMLON/LtWM8HIgAJEIVpVVhBM6gsmvQ8+Rh+ZG7FWGvHh7Ah3pRABwVJWklWCr/BTZSv0xnQ==", + "requires": {} } } }, @@ -42507,6 +31968,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "dev": true, "requires": { "browser-process-hrtime": "^1.0.0" } @@ -42515,6 +31977,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "dev": true, "requires": { "xml-name-validator": "^3.0.0" } @@ -42523,6 +31986,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, "requires": { "makeerror": "1.0.12" } @@ -42535,23 +31999,6 @@ "loose-envify": "^1.0.0" } }, - "watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "requires": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - } - }, - "wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "requires": { - "minimalistic-assert": "^1.0.0" - } - }, "wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", @@ -42561,186 +32008,21 @@ } }, "web-vitals": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.2.tgz", - "integrity": "sha512-nYfoOqb4EmElljyXU2qdeE76KsvoHdftQKY4DzA9Aw8DervCg2bG634pHLrJ/d6+B4mE3nWTSJv8Mo7B2mbZkw==" + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.3.tgz", + "integrity": "sha512-/CFAm1mNxSmOj6i0Co+iGFJ58OS4NRGVP+AWS/l509uIK5a1bSoIVaHz/ZumpHTfHSZBpgrJ+wjfpAOrTHok5Q==" }, "webidl-conversions": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==" - }, - "webpack": { - "version": "5.88.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.1.tgz", - "integrity": "sha512-FROX3TxQnC/ox4N+3xQoWZzvGXSuscxR32rbzjpXgEzWudJFEJBpdlkkob2ylrv5yzzufD1zph1OoFsLtm6stQ==", - "requires": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.15.0", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - } - }, - "webpack-dev-middleware": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", - "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", - "requires": { - "colorette": "^2.0.10", - "memfs": "^3.4.3", - "mime-types": "^2.1.31", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - }, - "dependencies": { - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - } - } - } - }, - "webpack-dev-server": { - "version": "4.15.1", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz", - "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==", - "requires": { - "@types/bonjour": "^3.5.9", - "@types/connect-history-api-fallback": "^1.3.5", - "@types/express": "^4.17.13", - "@types/serve-index": "^1.9.1", - "@types/serve-static": "^1.13.10", - "@types/sockjs": "^0.3.33", - "@types/ws": "^8.5.5", - "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.0.11", - "chokidar": "^3.5.3", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^2.0.0", - "default-gateway": "^6.0.3", - "express": "^4.17.3", - "graceful-fs": "^4.2.6", - "html-entities": "^2.3.2", - "http-proxy-middleware": "^2.0.3", - "ipaddr.js": "^2.0.1", - "launch-editor": "^2.6.0", - "open": "^8.0.9", - "p-retry": "^4.5.0", - "rimraf": "^3.0.2", - "schema-utils": "^4.0.0", - "selfsigned": "^2.1.1", - "serve-index": "^1.9.1", - "sockjs": "^0.3.24", - "spdy": "^4.0.2", - "webpack-dev-middleware": "^5.3.1", - "ws": "^8.13.0" - }, - "dependencies": { - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - } - } - } - }, - "webpack-manifest-plugin": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/webpack-manifest-plugin/-/webpack-manifest-plugin-4.1.1.tgz", - "integrity": "sha512-YXUAwxtfKIJIKkhg03MKuiFAD72PlrqCiwdwO4VEXdRO5V0ORCNwaOwAZawPZalCbmH9kBDmXnNeQOw+BIEiow==", - "requires": { - "tapable": "^2.0.0", - "webpack-sources": "^2.2.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "webpack-sources": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", - "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", - "requires": { - "source-list-map": "^2.0.1", - "source-map": "^0.6.1" - } - } - } - }, - "webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==" - }, - "websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", - "requires": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - } - }, - "websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==" + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "dev": true }, "whatwg-encoding": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, "requires": { "iconv-lite": "0.4.24" }, @@ -42749,6 +32031,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3" } @@ -42756,19 +32039,22 @@ } }, "whatwg-fetch": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", - "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==" + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==", + "dev": true }, "whatwg-mimetype": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==" + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true }, "whatwg-url": { "version": "8.7.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "dev": true, "requires": { "lodash": "^4.7.0", "tr46": "^2.1.0", @@ -42779,6 +32065,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "requires": { "isexe": "^2.0.0" } @@ -42787,6 +32074,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, "requires": { "is-bigint": "^1.0.1", "is-boolean-object": "^1.1.0", @@ -42796,12 +32084,13 @@ } }, "which-builtin-type": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", - "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.4.tgz", + "integrity": "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==", + "dev": true, "requires": { - "function.prototype.name": "^1.1.5", - "has-tostringtag": "^1.0.0", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", "is-date-object": "^1.0.5", "is-finalizationregistry": "^1.0.2", @@ -42810,14 +32099,15 @@ "is-weakref": "^1.0.2", "isarray": "^2.0.5", "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.15" } }, "which-collection": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, "requires": { "is-map": "^2.0.3", "is-set": "^2.0.3", @@ -42829,6 +32119,7 @@ "version": "1.1.15", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, "requires": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", @@ -42837,16 +32128,6 @@ "has-tostringtag": "^1.0.2" } }, - "wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "optional": true, - "peer": true, - "requires": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, "widest-line": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", @@ -42856,254 +32137,11 @@ "string-width": "^4.0.0" } }, - "workbox-background-sync": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-6.6.0.tgz", - "integrity": "sha512-jkf4ZdgOJxC9u2vztxLuPT/UjlH7m/nWRQ/MgGL0v8BJHoZdVGJd18Kck+a0e55wGXdqyHO+4IQTk0685g4MUw==", - "requires": { - "idb": "^7.0.1", - "workbox-core": "6.6.0" - } - }, - "workbox-broadcast-update": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-6.6.0.tgz", - "integrity": "sha512-nm+v6QmrIFaB/yokJmQ/93qIJ7n72NICxIwQwe5xsZiV2aI93MGGyEyzOzDPVz5THEr5rC3FJSsO3346cId64Q==", - "requires": { - "workbox-core": "6.6.0" - } - }, - "workbox-build": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-6.6.0.tgz", - "integrity": "sha512-Tjf+gBwOTuGyZwMz2Nk/B13Fuyeo0Q84W++bebbVsfr9iLkDSo6j6PST8tET9HYA58mlRXwlMGpyWO8ETJiXdQ==", - "requires": { - "@apideck/better-ajv-errors": "^0.3.1", - "@babel/core": "^7.11.1", - "@babel/preset-env": "^7.11.0", - "@babel/runtime": "^7.11.2", - "@rollup/plugin-babel": "^5.2.0", - "@rollup/plugin-node-resolve": "^11.2.1", - "@rollup/plugin-replace": "^2.4.1", - "@surma/rollup-plugin-off-main-thread": "^2.2.3", - "ajv": "^8.6.0", - "common-tags": "^1.8.0", - "fast-json-stable-stringify": "^2.1.0", - "fs-extra": "^9.0.1", - "glob": "^7.1.6", - "lodash": "^4.17.20", - "pretty-bytes": "^5.3.0", - "rollup": "^2.43.1", - "rollup-plugin-terser": "^7.0.0", - "source-map": "^0.8.0-beta.0", - "stringify-object": "^3.3.0", - "strip-comments": "^2.0.1", - "tempy": "^0.6.0", - "upath": "^1.2.0", - "workbox-background-sync": "6.6.0", - "workbox-broadcast-update": "6.6.0", - "workbox-cacheable-response": "6.6.0", - "workbox-core": "6.6.0", - "workbox-expiration": "6.6.0", - "workbox-google-analytics": "6.6.0", - "workbox-navigation-preload": "6.6.0", - "workbox-precaching": "6.6.0", - "workbox-range-requests": "6.6.0", - "workbox-recipes": "6.6.0", - "workbox-routing": "6.6.0", - "workbox-strategies": "6.6.0", - "workbox-streams": "6.6.0", - "workbox-sw": "6.6.0", - "workbox-window": "6.6.0" - }, - "dependencies": { - "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "source-map": { - "version": "0.8.0-beta.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", - "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", - "requires": { - "whatwg-url": "^7.0.0" - } - }, - "tr46": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", - "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", - "requires": { - "punycode": "^2.1.0" - } - }, - "webidl-conversions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" - }, - "whatwg-url": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", - "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", - "requires": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" - } - } - } - }, - "workbox-cacheable-response": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-6.6.0.tgz", - "integrity": "sha512-JfhJUSQDwsF1Xv3EV1vWzSsCOZn4mQ38bWEBR3LdvOxSPgB65gAM6cS2CX8rkkKHRgiLrN7Wxoyu+TuH67kHrw==", - "requires": { - "workbox-core": "6.6.0" - } - }, - "workbox-core": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.6.0.tgz", - "integrity": "sha512-GDtFRF7Yg3DD859PMbPAYPeJyg5gJYXuBQAC+wyrWuuXgpfoOrIQIvFRZnQ7+czTIQjIr1DhLEGFzZanAT/3bQ==" - }, - "workbox-expiration": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.6.0.tgz", - "integrity": "sha512-baplYXcDHbe8vAo7GYvyAmlS4f6998Jff513L4XvlzAOxcl8F620O91guoJ5EOf5qeXG4cGdNZHkkVAPouFCpw==", - "requires": { - "idb": "^7.0.1", - "workbox-core": "6.6.0" - } - }, - "workbox-google-analytics": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-6.6.0.tgz", - "integrity": "sha512-p4DJa6OldXWd6M9zRl0H6vB9lkrmqYFkRQ2xEiNdBFp9U0LhsGO7hsBscVEyH9H2/3eZZt8c97NB2FD9U2NJ+Q==", - "requires": { - "workbox-background-sync": "6.6.0", - "workbox-core": "6.6.0", - "workbox-routing": "6.6.0", - "workbox-strategies": "6.6.0" - } - }, - "workbox-navigation-preload": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-6.6.0.tgz", - "integrity": "sha512-utNEWG+uOfXdaZmvhshrh7KzhDu/1iMHyQOV6Aqup8Mm78D286ugu5k9MFD9SzBT5TcwgwSORVvInaXWbvKz9Q==", - "requires": { - "workbox-core": "6.6.0" - } - }, - "workbox-precaching": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.6.0.tgz", - "integrity": "sha512-eYu/7MqtRZN1IDttl/UQcSZFkHP7dnvr/X3Vn6Iw6OsPMruQHiVjjomDFCNtd8k2RdjLs0xiz9nq+t3YVBcWPw==", - "requires": { - "workbox-core": "6.6.0", - "workbox-routing": "6.6.0", - "workbox-strategies": "6.6.0" - } - }, - "workbox-range-requests": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-6.6.0.tgz", - "integrity": "sha512-V3aICz5fLGq5DpSYEU8LxeXvsT//mRWzKrfBOIxzIdQnV/Wj7R+LyJVTczi4CQ4NwKhAaBVaSujI1cEjXW+hTw==", - "requires": { - "workbox-core": "6.6.0" - } - }, - "workbox-recipes": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-6.6.0.tgz", - "integrity": "sha512-TFi3kTgYw73t5tg73yPVqQC8QQjxJSeqjXRO4ouE/CeypmP2O/xqmB/ZFBBQazLTPxILUQ0b8aeh0IuxVn9a6A==", - "requires": { - "workbox-cacheable-response": "6.6.0", - "workbox-core": "6.6.0", - "workbox-expiration": "6.6.0", - "workbox-precaching": "6.6.0", - "workbox-routing": "6.6.0", - "workbox-strategies": "6.6.0" - } - }, - "workbox-routing": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.6.0.tgz", - "integrity": "sha512-x8gdN7VDBiLC03izAZRfU+WKUXJnbqt6PG9Uh0XuPRzJPpZGLKce/FkOX95dWHRpOHWLEq8RXzjW0O+POSkKvw==", - "requires": { - "workbox-core": "6.6.0" - } - }, - "workbox-strategies": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.6.0.tgz", - "integrity": "sha512-eC07XGuINAKUWDnZeIPdRdVja4JQtTuc35TZ8SwMb1ztjp7Ddq2CJ4yqLvWzFWGlYI7CG/YGqaETntTxBGdKgQ==", - "requires": { - "workbox-core": "6.6.0" - } - }, - "workbox-streams": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-6.6.0.tgz", - "integrity": "sha512-rfMJLVvwuED09CnH1RnIep7L9+mj4ufkTyDPVaXPKlhi9+0czCu+SJggWCIFbPpJaAZmp2iyVGLqS3RUmY3fxg==", - "requires": { - "workbox-core": "6.6.0", - "workbox-routing": "6.6.0" - } - }, - "workbox-sw": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-6.6.0.tgz", - "integrity": "sha512-R2IkwDokbtHUE4Kus8pKO5+VkPHD2oqTgl+XJwh4zbF1HyjAbgNmK/FneZHVU7p03XUt9ICfuGDYISWG9qV/CQ==" - }, - "workbox-webpack-plugin": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-webpack-plugin/-/workbox-webpack-plugin-6.6.0.tgz", - "integrity": "sha512-xNZIZHalboZU66Wa7x1YkjIqEy1gTR+zPM+kjrYJzqN7iurYZBctBLISyScjhkJKYuRrZUP0iqViZTh8rS0+3A==", - "requires": { - "fast-json-stable-stringify": "^2.1.0", - "pretty-bytes": "^5.4.1", - "upath": "^1.2.0", - "webpack-sources": "^1.4.3", - "workbox-build": "6.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - } - } - } - }, - "workbox-window": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-6.6.0.tgz", - "integrity": "sha512-L4N9+vka17d16geaJXXRjENLFldvkWy7JyGxElRD0JvBxvFEd8LOhr+uXCcar/NzAmIBRv9EZ+M+Qr4mOoBITw==", - "requires": { - "@types/trusted-types": "^2.0.2", - "workbox-core": "6.6.0" - } - }, "wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, "requires": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -43113,12 +32151,14 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true }, "write-file-atomic": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, "requires": { "imurmurhash": "^0.1.4", "is-typedarray": "^1.0.0", @@ -43127,9 +32167,10 @@ } }, "ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, "requires": {} }, "xdg-basedir": { @@ -43141,12 +32182,14 @@ "xml-name-validator": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==" + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true }, "xmlchars": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true }, "xtend": { "version": "4.0.2", @@ -43156,7 +32199,8 @@ "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true }, "yallist": { "version": "3.1.1", @@ -43172,6 +32216,7 @@ "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, "requires": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -43185,12 +32230,15 @@ "yargs-parser": { "version": "20.2.9", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "peer": true }, "zen-observable": { "version": "0.8.15", @@ -43208,7 +32256,13 @@ "zod": { "version": "3.22.4", "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", - "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==" + "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", + "peer": true + }, + "zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==" } } } diff --git a/package.json b/package.json index 52e08ba7c3..5619390f62 100644 --- a/package.json +++ b/package.json @@ -5,68 +5,75 @@ "type": "module", "config-overrides-path": "scripts/config-overrides", "dependencies": { - "@apollo/client": "^3.4.0-beta.19", + "@apollo/client": "^3.11.4", "@apollo/link-error": "^2.0.0-beta.3", "@apollo/react-testing": "^4.0.0", "@dicebear/collection": "^8.0.1", - "@dicebear/core": "^8.0.1", - "@emotion/react": "^11.11.4", - "@emotion/styled": "^11.11.5", - "@mui/icons-material": "^5.16.1", - "@mui/material": "^5.16.4", + "@dicebear/core": "^8.0.2", + "@emotion/react": "^11.13.3", + "@emotion/styled": "^11.13.0", + "@mui/icons-material": "^5.16.7", + "@mui/material": "^5.16.7", "@mui/private-theming": "^5.15.12", "@mui/system": "^5.14.12", - "@mui/x-charts": "^7.8.0", - "@mui/x-data-grid": "^7.11.0", - "@mui/x-date-pickers": "^7.6.1", - "@pdfme/generator": "^1.2.6", + "@mui/x-charts": "^7.17.0", + "@mui/x-data-grid": "^7.16.0", + "@mui/x-date-pickers": "^7.11.1", + "@pdfme/generator": "^4.5.2", + "@reduxjs/toolkit": "^2.2.7", + "@vitejs/plugin-react": "^4.3.1", + "babel-plugin-transform-import-meta": "^2.2.1", "bootstrap": "^5.3.3", "customize-cra": "^1.0.0", - "dayjs": "^1.11.11", + "dayjs": "^1.11.12", + "dotenv": "^16.4.5", "flag-icons": "^6.6.6", "graphql": "^16.9.0", "graphql-tag": "^2.12.6", "graphql-ws": "^5.16.0", "history": "^5.3.0", - "i18next": "^21.8.14", + "i18next": "^23.15.1", "i18next-browser-languagedetector": "^8.0.0", - "i18next-http-backend": "^2.5.2", + "i18next-http-backend": "^2.6.1", "inquirer": "^8.0.0", "js-cookie": "^3.0.1", "markdown-toc": "^1.2.0", "prettier": "^3.3.2", - "react": "^17.0.2", - "react-app-rewired": "^2.2.1", + "react": "^18.3.1", "react-beautiful-dnd": "^13.1.1", - "react-bootstrap": "^2.7.4", + "react-bootstrap": "^2.10.4", "react-datepicker": "^7.3.0", - "react-dom": "^17.0.2", + "react-dom": "^18.3.1", "react-google-recaptcha": "^3.1.0", - "react-i18next": "^11.18.1", + "react-i18next": "^12.3.1", "react-icons": "^5.2.1", "react-infinite-scroll-component": "^6.1.0", "react-multi-carousel": "^2.8.5", - "react-redux": "^7.2.5", - "react-router-dom": "^6.25.1", - "react-scripts": "5.0.1", - "react-toastify": "^9.0.3", + "react-redux": "^9.1.2", + "react-router-dom": "^6.26.0", + "react-toastify": "^10.0.5", "react-tooltip": "^5.27.1", - "redux": "^4.1.1", - "redux-thunk": "^2.3.0", + "redux": "^5.0.1", "sanitize-html": "^2.13.0", + "typedoc": "^0.26.7", "typedoc-plugin-markdown": "^4.2.1", - "typescript": "^4.3.5", - "web-vitals": "^4.2.2" + "typescript": "^5.6.2", + "vite": "^5.4.7", + "vite-plugin-environment": "^1.1.3", + "vite-tsconfig-paths": "^5.0.1", + "web-vitals": "^4.2.3" }, "scripts": { - "serve": "cross-env ESLINT_NO_DEV_ERRORS=true node ./scripts/config-overrides/custom_start.js", - "build": "node ./scripts/config-overrides/custom_build.js", - "test": "cross-env NODE_ENV=test node scripts/test.js --env=./scripts/custom-test-env.js --watchAll --coverage", + "serve": "cross-env ESLINT_NO_DEV_ERRORS=true vite --config config/vite.config.ts", + "build": "tsc && vite build --config config/vite.config.ts", + "preview": "vite preview --config config/vite.config.ts", + "test": "cross-env NODE_ENV=test jest --env=./scripts/custom-test-env.js --watchAll --coverage", "eject": "react-scripts eject", "lint:check": "eslint \"**/*.{ts,tsx}\" --max-warnings=0", "lint:fix": "eslint --fix \"**/*.{ts,tsx}\"", "format:fix": "prettier --write \"**/*.{ts,tsx,json,scss,css}\"", "format:check": "prettier --check \"**/*.{ts,tsx,json,scss,css}\"", + "check-tsdoc": "node .github/workflows/check-tsdoc.js", "typecheck": "tsc --project tsconfig.json --noEmit", "prepare": "husky install", "jest-preview": "jest-preview", @@ -95,41 +102,47 @@ }, "devDependencies": { "@babel/plugin-proposal-private-property-in-object": "^7.21.11", - "@testing-library/jest-dom": "^5.14.1", - "@testing-library/react": "^11.1.0", + "@babel/preset-env": "^7.25.4", + "@babel/preset-react": "^7.24.7", + "@babel/preset-typescript": "^7.24.7", + "@testing-library/jest-dom": "^6.5.0", + "@testing-library/react": "^16.0.0", "@testing-library/user-event": "^12.1.10", "@types/inquirer": "^9.0.7", "@types/jest": "^26.0.24", "@types/js-cookie": "^3.0.6", - "@types/node": "^20.12.12", + "@types/node": "^22.5.4", "@types/node-fetch": "^2.6.10", - "@types/react": "^17.0.14", + "@types/react": "^18.3.3", "@types/react-beautiful-dnd": "^13.1.8", "@types/react-bootstrap": "^0.32.32", - "@types/react-datepicker": "^4.1.4", - "@types/react-dom": "^17.0.9", + "@types/react-datepicker": "^7.0.0", + "@types/react-dom": "^18.3.0", "@types/react-google-recaptcha": "^2.1.5", "@types/react-router-dom": "^5.1.8", - "@types/sanitize-html": "^2.11.0", - "@typescript-eslint/eslint-plugin": "^5.9.0", - "@typescript-eslint/parser": "^5.9.0", + "@types/sanitize-html": "^2.13.0", + "@typescript-eslint/eslint-plugin": "^8.5.0", + "@typescript-eslint/parser": "^8.5.0", + "babel-jest": "^29.7.0", "cross-env": "^7.0.3", "eslint-config-prettier": "^9.1.0", "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jest": "^25.3.4", - "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-react": "^7.34.1", - "eslint-plugin-tsdoc": "^0.2.17", - "husky": "^8.0.3", + "eslint-plugin-jest": "^28.8.0", + "eslint-plugin-prettier": "^5.2.1", + "eslint-plugin-react": "^7.35.0", + "eslint-plugin-tsdoc": "^0.3.0", + "husky": "^9.1.6", "identity-obj-proxy": "^3.0.0", "jest": "^27.4.5", "jest-localstorage-mock": "^2.4.19", "jest-location-mock": "^2.0.0", "jest-preview": "^0.3.1", - "lint-staged": "^15.2.7", + "lint-staged": "^15.2.8", "postcss-modules": "^6.0.0", - "sass": "^1.77.4", - "tsx": "^4.16.2" + "sass": "^1.77.8", + "tsx": "^4.19.1", + "vite-plugin-svgr": "^4.2.0", + "whatwg-fetch": "^3.6.20" }, "resolutions": { "@apollo/client": "^3.4.0-beta.19", diff --git a/public/locales/en/common.json b/public/locales/en/common.json index d3f108c550..3cf8df2010 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -77,10 +77,19 @@ "manage": "Manage", "searchResultsFor": "Search results for {{text}}", "none": "None", - "sort": "Sort", "Donate": "Donate", "addedSuccessfully": "{{item}} added Successfully", "updatedSuccessfully": "{{item}} updated Successfully", "removedSuccessfully": "{{item}} removed Successfully", - "successfullyUpdated": "Successfully Updated" + "successfullyUpdated": "Successfully Updated", + "sort": "Sort", + "all": "All", + "active": "Active", + "disabled": "Disabled", + "pending": "Pending", + "completed": "Completed", + "late": "Late", + "createdLatest": "Created Latest", + "createdEarliest": "Created Earliest", + "searchBy": "Search by {{item}}" } diff --git a/public/locales/en/errors.json b/public/locales/en/errors.json index 155d747bcf..752c0db750 100644 --- a/public/locales/en/errors.json +++ b/public/locales/en/errors.json @@ -6,5 +6,6 @@ "errorSendingMail": "Error sending mail", "emailNotRegistered": "Email not registered", "notFoundMsg": "Oops! The Page you requested was not found!", - "errorOccurredCouldntCreate": "An error occurred. Couldn't create {{entity}}" + "errorOccurredCouldntCreate": "An error occurred. Couldn't create {{entity}}", + "errorLoading": "Error occured while loading {{entity}} data" } diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 33cdd02286..8a668b03d8 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -22,7 +22,25 @@ "numeric_value_check": "Atleaset one numeric value", "special_char_check": "Atleast one special character", "selectOrg": "Select an organization", - "afterRegister": "Successfully registered. Please wait for admin to approve your request." + "afterRegister": "Successfully registered. Please wait for admin to approve your request.", + "talawa_portal": "talawa_portal", + "login": "login", + "register": "register", + "firstName": "firstName", + "lastName": "lastName", + "email": "email", + "password": "password", + "confirmPassword": "confirmPassword", + "forgotPassword": "forgotPassword", + "enterEmail": "enterEmail", + "enterPassword": "enterPassword", + "talawaApiUnavailable": "talawaApiUnavailable", + "notAuthorised": "notAuthorised", + "notFound": "notFound", + "OR": "OR", + "admin": "admin", + "user": "user", + "loading": "loading" }, "userLoginPage": { "title": "Talawa Admin", @@ -38,7 +56,23 @@ "successfullyRegistered": "Successfully Registered. Please wait until you will be approved.", "userLogin": "User Login", "afterRegister": "Successfully registered. Please wait for admin to approve your request.", - "selectOrg": "Select an organization" + "selectOrg": "Select an organization", + "talawa_portal": "talawa_portal", + "login": "login", + "register": "register", + "firstName": "firstName", + "lastName": "lastName", + "email": "email", + "password": "password", + "confirmPassword": "confirmPassword", + "forgotPassword": "forgotPassword", + "enterEmail": "enterEmail", + "enterPassword": "enterPassword", + "talawaApiUnavailable": "talawaApiUnavailable", + "notAuthorised": "notAuthorised", + "notFound": "notFound", + "OR": "OR", + "loading": "loading" }, "latestEvents": { "eventCardTitle": "Upcoming Events", @@ -51,12 +85,19 @@ "noPostsCreated": "No Posts Created" }, "listNavbar": { - "roles": "Roles" + "roles": "Roles", + "talawa_portal": "talawa_portal", + "requests": "requests", + "logout": "logout" }, "leftDrawer": { "my organizations": "My Organizations", "requests": "Membership Requests", - "communityProfile": "Community Profile" + "communityProfile": "Community Profile", + "talawaAdminPortal": "talawaAdminPortal", + "menu": "menu", + "users": "users", + "logout": "logout" }, "leftDrawerOrg": { "Dashboard": "Dashboard", @@ -75,7 +116,13 @@ "notifications": "Notifications", "spamsThe": "spams the", "group": "group", - "noNotifications": "No Notifications" + "noNotifications": "No Notifications", + "talawaAdminPortal": "talawaAdminPortal", + "menu": "menu", + "talawa_portal": "talawa_portal", + "settings": "settings", + "logout": "logout", + "close": "close" }, "orgList": { "title": "Talawa Organizations", @@ -105,11 +152,25 @@ "manageFeaturesInfo": "Creation Successful ! Please select features that you want to enale for this organization from the plugin store.", "goToStore": "Go to Plugin Store", "enableEverything": "Enable Everything", - "sampleOrgSuccess": "Sample Organization Successfully Created" + "sampleOrgSuccess": "Sample Organization Successfully Created", + "name": "name", + "email": "email", + "searchByName": "searchByName", + "description": "description", + "location": "location", + "address": "address", + "displayImage": "displayImage", + "filter": "filter", + "cancel": "cancel", + "endOfResults": "endOfResults", + "noResultsFoundFor": "noResultsFoundFor", + "OR": "OR" }, "orgListCard": { "manage": "Manage", - "sampleOrganization": "Sample Organization" + "sampleOrganization": "Sample Organization", + "admins": "admins", + "members": "members" }, "paginationList": { "rowsPerPage": "rows per page", @@ -126,7 +187,11 @@ "acceptedSuccessfully": "Request accepted successfully", "rejectedSuccessfully": "Request rejected successfully", "noOrgErrorTitle": "Organizations Not Found", - "noOrgErrorDescription": "Please create an organization through dashboard" + "noOrgErrorDescription": "Please create an organization through dashboard", + "name": "name", + "email": "email", + "endOfResults": "endOfResults", + "noResultsFoundFor": "noResultsFoundFor" }, "users": { "title": "Talawa Roles", @@ -150,7 +215,25 @@ "visit": "Visit", "withdraw": "Widthdraw", "removeUserFrom": "Remove User from {{org}}", - "removeConfirmation": "Are you sure you want to remove '{{name}}' from organization '{{org}}'?" + "removeConfirmation": "Are you sure you want to remove '{{name}}' from organization '{{org}}'?", + "searchByName": "searchByName", + "users": "users", + "name": "name", + "email": "email", + "endOfResults": "endOfResults", + "admin": "admin", + "superAdmin": "superAdmin", + "user": "user", + "filter": "filter", + "noResultsFoundFor": "noResultsFoundFor", + "talawaApiUnavailable": "talawaApiUnavailable", + "cancel": "cancel", + "admins": "admins", + "members": "members", + "orgJoined": "orgJoined", + "MembershipRequestSent": "MembershipRequestSent", + "AlreadyJoined": "AlreadyJoined", + "errorOccured": "errorOccured" }, "communityProfile": { "title": "Community Profile", @@ -178,7 +261,12 @@ "latestPosts": "Latest Posts", "noPostsPresent": "No Posts Present", "membershipRequests": "Membership requests", - "noMembershipRequests": "No Membership requests present" + "noMembershipRequests": "No Membership requests present", + "location": "location", + "members": "members", + "admins": "admins", + "requests": "requests", + "talawaApiUnavailable": "talawaApiUnavailable" }, "organizationPeople": { "title": "Talawa Members", @@ -198,23 +286,79 @@ "enterLastName": "Enter your last name", "enterConfirmPassword": "Enter Password to confirm", "organization": "Organization", - "invalidDetailsMessage": "Please enter valid details." + "invalidDetailsMessage": "Please enter valid details.", + "members": "members", + "admins": "admins", + "users": "users", + "searchFirstName": "searchFirstName", + "searchLastName": "searchLastName", + "firstName": "firstName", + "lastName": "lastName", + "emailAddress": "emailAddress", + "enterEmail": "enterEmail", + "password": "password", + "enterPassword": "enterPassword", + "confirmPassword": "confirmPassword", + "create": "create", + "cancel": "cancel", + "user": "user", + "profile": "profile" + }, + "organizationTags": { + "title": "Organization Tags", + "createTag": "Create a new tag", + "manageTag": "Manage", + "editTag": "Edit", + "removeTag": "Remove", + "tagDetails": "Tag Details", + "tagName": "Name", + "tagType": "Type", + "tagNamePlaceholder": "Write the name of the tag", + "tagCreationSuccess": "New tag created successfully", + "tagUpdationSuccess": "Tag updated successfully", + "tagRemovalSuccess": "Tag deleted successfully", + "noTagsFound": "No tags found", + "removeUserTag": "Delete Tag", + "removeUserTagMessage": "Do you want to delete this tag?", + "addChildTag": "Add a Sub Tag" + }, + "manageTag": { + "title": "Tag Details", + "addPeopleToTag": "Add People to tag", + "viewProfile": "View", + "noAssignedMembersFound": "No one assigned", + "unassignUserTag": "Unassign Tag", + "unassignUserTagMessage": "Do you want to remove the tag from this user?", + "successfullyUnassigned": "Tag unassigned from user", + "addPeople": "Add People", + "add": "Add", + "subTags": "Sub Tags" }, "userListCard": { "addAdmin": "Add Admin", - "addedAsAdmin": "User is added as admin." + "addedAsAdmin": "User is added as admin.", + "joined": "joined", + "talawaApiUnavailable": "talawaApiUnavailable" }, "orgAdminListCard": { "remove": "Remove", "removeAdmin": "Remove Admin", "removeAdminMsg": "Do you want to remove this admin?", - "adminRemoved": "The admin is removed." + "adminRemoved": "The admin is removed.", + "joined": "joined", + "no": "no", + "yes": "yes", + "talawaApiUnavailable": "talawaApiUnavailable" }, "orgPeopleListCard": { "remove": "Remove", "removeMember": "Remove Member", "removeMemberMsg": "Do you want to remove this member?", - "memberRemoved": "The Member is removed" + "memberRemoved": "The Member is removed", + "joined": "joined", + "no": "no", + "yes": "yes", + "talawaApiUnavailable": "talawaApiUnavailable" }, "organizationEvents": { "title": "Events", @@ -242,7 +386,17 @@ "never": "Never", "on": "On", "after": "After", - "occurences": "occurences" + "occurences": "occurences", + "startTime": "startTime", + "endTime": "endTime", + "eventLocation": "eventLocation", + "events": "events", + "description": "description", + "location": "location", + "startDate": "startDate", + "endDate": "endDate", + "talawaApiUnavailable": "talawaApiUnavailable", + "done": "done" }, "organizationActionItems": { "actionItemCategory": "Action Item Category", @@ -253,9 +407,8 @@ "assignmentDate": "Assignment Date", "active": "Active", "clearFilters": "Clear Filters", - "completed": "Completed", "completionDate": "Completion Date", - "createActionItem": "Create Action Items", + "createActionItem": "Create Action Item", "deleteActionItem": "Delete Action Item", "deleteActionItemMsg": "Do you want to remove this action item?", "details": "Details", @@ -278,7 +431,18 @@ "successfulCreation": "Action Item created successfully", "successfulUpdation": "Action Item updated successfully", "successfulDeletion": "Action Item deleted successfully", - "title": "Action Items" + "title": "Action Items", + "category": "Category", + "allotedHours": "Alloted Hours", + "latestDueDate": "Latest Due Date", + "earliestDueDate": "Earliest Due Date", + "updateActionItem": "Update Action Item", + "noneUpdated": "None of the fields were updated", + "updateStatusMsg": "Are you sure you want to mark this action item as pending?", + "close": "close", + "eventActionItems": "eventActionItems", + "no": "no", + "yes": "yes" }, "organizationAgendaCategory": { "agendaCategoryDetails": "Agenda Category Details", @@ -355,7 +519,19 @@ "never": "Never", "on": "On", "after": "After", - "occurences": "occurences" + "occurences": "occurences", + "startTime": "startTime", + "endTime": "endTime", + "location": "location", + "no": "no", + "yes": "yes", + "description": "description", + "startDate": "startDate", + "endDate": "endDate", + "registerEvent": "registerEvent", + "close": "close", + "talawaApiUnavailable": "talawaApiUnavailable", + "done": "done" }, "funds": { "title": "Funds", @@ -378,7 +554,8 @@ "deleteFundMsg": "Are you sure you want to delete this fund?", "createdLatest": "Created Latest", "createdEarliest": "Created Earliest", - "viewCampaigns": "View Campaigns" + "viewCampaigns": "View Campaigns", + "searchByName": "searchByName" }, "fundCampaign": { "title": "Fundraising Campaigns", @@ -430,7 +607,9 @@ "pledges": "Pledges", "endsOn": "Ends on", "raisedAmount": "Raised amount ", - "pledgedAmount": "Pledged amount" + "pledgedAmount": "Pledged amount", + "startDate": "startDate", + "endDate": "endDate" }, "orgPost": { "title": "Posts", @@ -458,7 +637,8 @@ "postCreatedSuccess": "Congratulations! You have Posted Something.", "pinPost": "Pin post", "Next": "Next Page", - "Previous": "Previous Page" + "Previous": "Previous Page", + "cancel": "cancel" }, "postNotFound": { "post": "Post", @@ -473,7 +653,8 @@ "user not found!": "User Not Found!", "member not found!": "Member Not Found!", "admin not found!": "Admin Not Found!", - "roles not found!": "Roles Not Found!" + "roles not found!": "Roles Not Found!", + "user": "user" }, "orgPostCard": { "author": "Author", @@ -492,7 +673,12 @@ "postDeleted": "Post deleted successfully.", "postUpdated": "Post Updated successfully.", "tag": " Your browser does not support the video tag", - "pin": "Pin Post" + "pin": "Pin Post", + "edit": "edit", + "no": "no", + "yes": "yes", + "close": "close", + "talawaApiUnavailable": "talawaApiUnavailable" }, "blockUnblockUser": { "title": "Block/Unblock User", @@ -508,7 +694,12 @@ "blockedUsers": "Blocked Users", "searchByFirstName": "Search By First Name", "searchByLastName": "Search By Last Name", - "noSpammerFound": "No spammer found" + "noSpammerFound": "No spammer found", + "searchByName": "searchByName", + "name": "name", + "email": "email", + "talawaApiUnavailable": "talawaApiUnavailable", + "noResultsFoundFor": "noResultsFoundFor" }, "eventManagement": { "title": "Event Management", @@ -533,7 +724,10 @@ "errorSendingMail": "Error in sending mail.", "passwordMismatches": "Password and Confirm password mismatches.", "passwordChanges": "Password changes successfully.", - "OTPsent": "OTP is sent to your registered email." + "OTPsent": "OTP is sent to your registered email.", + "forgotPassword": "forgotPassword", + "password": "password", + "talawaApiUnavailable": "talawaApiUnavailable" }, "pageNotFound": { "title": "404 Not Found", @@ -571,7 +765,8 @@ "noData": "No data", "otherSettings": "Other Settings", "changeLanguage": "Change Language", - "manageCustomFields": "Manage Custom Fields" + "manageCustomFields": "Manage Custom Fields", + "agendaItemCategories": "Agenda Item Categories" }, "deleteOrg": { "deleteOrganization": "Delete Organization", @@ -579,18 +774,30 @@ "deleteMsg": "Do you want to delete this organization?", "confirmDelete": "Confirm Delete", "longDelOrgMsg": "By clicking on Delete Organization button the organization will be permanently deleted along with its events, tags and all related data.", - "successfullyDeletedSampleOrganization": "Successfully deleted sample Organization" + "successfullyDeletedSampleOrganization": "Successfully deleted sample Organization", + "cancel": "cancel" }, "userUpdate": { "appLanguageCode": "Default Language", - "userType": "User Type" + "userType": "User Type", + "firstName": "firstName", + "lastName": "lastName", + "email": "email", + "password": "password", + "admin": "admin", + "superAdmin": "superAdmin", + "displayImage": "displayImage", + "saveChanges": "saveChanges", + "cancel": "cancel" }, "userPasswordUpdate": { "previousPassword": "Previous Password", "newPassword": "New Password", "confirmNewPassword": "Confirm New Password", "passCantBeEmpty": "Password can't be empty", - "passNoMatch": "New and Confirm password do not match." + "passNoMatch": "New and Confirm password do not match.", + "saveChanges": "saveChanges", + "cancel": "cancel" }, "orgDelete": { "deleteOrg": "Delete Org" @@ -598,7 +805,9 @@ "membershipRequest": { "accept": "Accept", "reject": "Reject", - "memberAdded": "it is accepted" + "memberAdded": "it is accepted", + "joined": "joined", + "talawaApiUnavailable": "talawaApiUnavailable" }, "orgUpdate": { "city": "City", @@ -612,7 +821,15 @@ "userRegistrationRequired": "User Registration Required", "isVisibleInSearch": "Visible in Search", "enterNameOrganization": "Enter Organization Name", - "successfulUpdated": "Organization updated successfully" + "successfulUpdated": "Organization updated successfully", + "name": "name", + "description": "description", + "location": "location", + "address": "address", + "displayImage": "displayImage", + "saveChanges": "saveChanges", + "cancel": "cancel", + "talawaApiUnavailable": "talawaApiUnavailable" }, "addOnRegister": { "addNew": "Add New", @@ -622,7 +839,9 @@ "pluginDesc": "Plugin Description", "pName": "Ex: Donations", "cName": "Ex: john Doe", - "pDesc": "This Plugin enables UI for" + "pDesc": "This Plugin enables UI for", + "close": "close", + "register": "register" }, "addOnStore": { "title": "Add On Store", @@ -676,14 +895,32 @@ "membershipRequests": "Membership requests", "adminForEvents": "Admin for events", "addedAsAdmin": "User is added as admin.", - "userType": "User Type" + "userType": "User Type", + "email": "email", + "displayImage": "displayImage", + "address": "address", + "delete": "delete", + "saveChanges": "saveChanges", + "joined": "joined", + "talawaApiUnavailable": "talawaApiUnavailable" + }, + "people": { + "title": "People", + "searchUsers": "Search users" }, "userLogin": { "login": "Login", "loginIntoYourAccount": "Login into your account", "invalidDetailsMessage": "Please enter a valid email and password.", "notAuthorised": "Sorry! you are not Authorised!", - "invalidCredentials": "Entered credentials are incorrect. Please enter valid credentials." + "invalidCredentials": "Entered credentials are incorrect. Please enter valid credentials.", + "forgotPassword": "forgotPassword", + "emailAddress": "emailAddress", + "enterEmail": "enterEmail", + "password": "password", + "enterPassword": "enterPassword", + "register": "register", + "talawaApiUnavailable": "talawaApiUnavailable" }, "userRegister": { "enterFirstName": "Enter your first name", @@ -693,7 +930,16 @@ "login": "Login", "afterRegister": "Successfully registered. Please wait for admin to approve your request.", "passwordNotMatch": "Password doesn't match. Confirm Password and try again.", - "invalidDetailsMessage": "Please enter valid details." + "invalidDetailsMessage": "Please enter valid details.", + "register": "register", + "firstName": "firstName", + "lastName": "lastName", + "emailAddress": "emailAddress", + "enterEmail": "enterEmail", + "password": "password", + "enterPassword": "enterPassword", + "confirmPassword": "confirmPassword", + "talawaApiUnavailable": "talawaApiUnavailable" }, "userNavbar": { "talawa": "Talawa", @@ -702,7 +948,10 @@ "events": "Events", "chat": "Chat", "donate": "Donate", - "language": "Language" + "language": "Language", + "settings": "settings", + "logout": "logout", + "close": "close" }, "userOrganizations": { "allOrganizations": "All Organizations", @@ -711,7 +960,11 @@ "selectOrganization": "Select an organization", "searchUsers": "Search users", "nothingToShow": "Nothing to show here.", - "organizations": "Organizations" + "organizations": "Organizations", + "search": "search", + "filter": "filter", + "searchByName": "searchByName", + "searchOrganizations": "Search Organization" }, "userSidebarOrg": { "yourOrganizations": "Your Organizations", @@ -724,13 +977,15 @@ "communityProfile": "Community Profile", "logout": "Logout", "settings": "Settings", - "chat": "Chat" + "chat": "Chat", + "menu": "menu" }, "organizationSidebar": { "viewAll": "View all", "events": "Events", "noEvents": "No Events to show", - "noMembers": "No Members to show" + "noMembers": "No Members to show", + "members": "members" }, "postCard": { "likes": "Likes", @@ -742,7 +997,7 @@ "home": { "posts": "Posts", "post": "Post", - "title": "Title", + "title": "Posts", "textArea": "Something on your mind?", "feed": "Feed", "loading": "Loading", @@ -809,9 +1064,18 @@ "fullTime": "Full Time", "partTime": "Part Time", "selectCountry": "Select a country", - "enterState": "Enter City or State" + "enterState": "Enter City or State", + "settings": "settings", + "firstName": "firstName", + "lastName": "lastName", + "emailAddress": "emailAddress", + "displayImage": "displayImage", + "address": "address", + "saveChanges": "saveChanges", + "joined": "joined" }, "donate": { + "title": "Donations", "donations": "Donations", "searchDonations": "Search donations", "donateForThe": "Donate for the", @@ -819,9 +1083,14 @@ "yourPreviousDonations": "Your Previous Donations", "donate": "Donate", "nothingToShow": "Nothing to show here.", - "success": "Donation Successful" + "success": "Donation Successful", + "invalidAmount": "Please enter a numerical value for the donation amount.", + "donationAmountDescription": "Please enter the numerical value for the donation amount.", + "donationOutOfRange": "Donation amount must be between {{min}} and {{max}}.", + "donateTo": "donateTo" }, "userEvents": { + "title": "Events", "nothingToShow": "Nothing to show here.", "createEvent": "Create Event", "recurring": "Recurring Event", @@ -836,13 +1105,25 @@ "publicEvent": "Is Public", "registerable": "Is Registerable", "monthlyCalendarView": "Monthly Calendar", - "yearlyCalendarView": "Yearly Calender" + "yearlyCalendarView": "Yearly Calender", + "startTime": "startTime", + "endTime": "endTime", + "enterLocation": "enterLocation", + "search": "search", + "cancel": "cancel", + "create": "create", + "eventDescription": "eventDescription", + "eventLocation": "eventLocation", + "startDate": "startDate", + "endDate": "endDate" }, "userEventCard": { "starts": "Starts", "ends": "Ends", "creator": "Creator", - "alreadyRegistered": "Already registered" + "alreadyRegistered": "Already registered", + "location": "location", + "register": "register" }, "advertisement": { "title": "Advertisements", @@ -867,7 +1148,15 @@ "editAdvertisement": "Edit Advertisement", "advertisementDeleted": "Advertisement deleted successfully.", "endDateGreaterOrEqual": "End Date should be greater than or equal to Start Date", - "advertisementCreated": "Advertisement created successfully." + "advertisementCreated": "Advertisement created successfully.", + "pHeading": "pHeading", + "delete": "delete", + "close": "close", + "no": "no", + "yes": "yes", + "edit": "edit", + "saveChanges": "saveChanges", + "endOfResults": "endOfResults" }, "userChat": { "chat": "Chat", @@ -891,20 +1180,28 @@ "String": "String", "Boolean": "Boolean", "Date": "Date", - "Number": "Number" + "Number": "Number", + "saveChanges": "saveChanges" }, "orgActionItemCategories": { "enableButton": "Enable", "disableButton": "Disable", "updateActionItemCategory": "Update", "actionItemCategoryName": "Name", - "actionItemCategoryDetails": "Action Item Category Details", + "categoryDetails": "Category Details", "enterName": "Enter Name", "successfulCreation": "Action Item Category created successfully", "successfulUpdation": "Action Item Category updated successfully", "sameNameConflict": "Please change the name to make an update", "categoryEnabled": "Action Item Category Enabled", - "categoryDisabled": "Action Item Category Disabled" + "categoryDisabled": "Action Item Category Disabled", + "noActionItemCategories": "No Action Item Categories", + "status": "Status", + "categoryDeleted": "Action Item Category deleted successfully", + "deleteCategory": "Delete Category", + "deleteCategoryMsg": "Are you sure you want to delete this Action Item Category?", + "createButton": "createButton", + "editButton": "editButton" }, "organizationVenues": { "title": "Venues", @@ -928,7 +1225,12 @@ "view": "View", "venueTitleError": "Venue title cannot be empty!", "venueCapacityError": "Capacity must be a positive number!", - "searchBy": "Search By" + "searchBy": "Search By", + "description": "description", + "edit": "edit", + "delete": "delete", + "name": "name", + "desc": "desc" }, "addMember": { "title": "Add Member", @@ -942,7 +1244,18 @@ "organization": "Organization", "invalidDetailsMessage": "Please provide all required details.", "passwordNotMatch": "Passwords do not match.", - "addMember": "Add Member" + "addMember": "Add Member", + "firstName": "firstName", + "lastName": "lastName", + "emailAddress": "emailAddress", + "enterEmail": "enterEmail", + "password": "password", + "enterPassword": "enterPassword", + "confirmPassword": "confirmPassword", + "cancel": "cancel", + "create": "create", + "user": "user", + "profile": "profile" }, "eventActionItems": { "title": "Action Items", @@ -970,7 +1283,9 @@ "successfulCreation": "Action Item created successfully", "successfulUpdation": "Action Item updated successfully", "notes": "Notes", - "save": "Save" + "save": "Save", + "yes": "yes", + "no": "no" }, "checkIn": { "errorCheckingIn": "Error checking in", @@ -979,5 +1294,26 @@ "eventRegistrantsModal": { "errorAddingAttendee": "Error adding attendee", "errorRemovingAttendee": "Error removing attendee" + }, + "userCampaigns": { + "title": "Fundraising Campaigns", + "searchByName": "Search by Name...", + "searchBy": "Search by", + "pledgers": "Pledgers", + "campaigns": "Campaigns", + "myPledges": "My Pledges", + "lowestAmount": "Lowest Amount", + "highestAmount": "Highest Amount", + "lowestGoal": "Lowest Goal", + "highestGoal": "Highest Goal", + "latestEndDate": "Latest End Date", + "earliestEndDate": "Earliest End Date", + "addPledge": "Add Pledge", + "viewPledges": "View Pledges", + "noPledges": "No Pledges Found", + "noCampaigns": "No Campaigns Found" + }, + "userPledges": { + "title": "My Pledges" } } diff --git a/public/locales/fr/common.json b/public/locales/fr/common.json index 250584da70..6796237d38 100644 --- a/public/locales/fr/common.json +++ b/public/locales/fr/common.json @@ -82,5 +82,14 @@ "addedSuccessfully": "{{item}} ajouté avec succès", "updatedSuccessfully": "{{item}} mis à jour avec succès", "removedSuccessfully": "{{item}} supprimé avec succès", - "successfullyUpdated": "Mis à jour avec succès" + "successfullyUpdated": "Mis à jour avec succès", + "all": "Tous", + "active": "Actif", + "disabled": "Désactivé", + "pending": "En attente", + "completed": "Complété", + "late": "En retard", + "createdLatest": "Créé le plus récemment", + "createdEarliest": "Créé le plus tôt", + "searchBy": "Rechercher par {{item}}" } diff --git a/public/locales/fr/errors.json b/public/locales/fr/errors.json index f5aea03266..e9a7cf4fd9 100644 --- a/public/locales/fr/errors.json +++ b/public/locales/fr/errors.json @@ -6,5 +6,6 @@ "errorSendingMail": "Erreur lors de l'envoi du courrier", "emailNotRegistered": "Email non enregistré", "notFoundMsg": "Oops! ", - "errorOccurredCouldntCreate": "Une erreur s'est produite. Impossible de créer {{entity}}" + "errorOccurredCouldntCreate": "Une erreur s'est produite. Impossible de créer {{entity}}", + "errorLoading": "Une erreur s'est produite lors du chargement des données {{entity}}" } diff --git a/public/locales/fr/translation.json b/public/locales/fr/translation.json index d5c084fcfe..6f7332057b 100644 --- a/public/locales/fr/translation.json +++ b/public/locales/fr/translation.json @@ -22,7 +22,25 @@ "numeric_value_check": "Au moins une valeur numérique", "special_char_check": "Au moins un caractère spécial", "selectOrg": "Sélectionnez une organisation", - "afterRegister": "Enregistré avec succès. " + "afterRegister": "Enregistré avec succès. ", + "talawa_portal": "Portail Talawa", + "login": "Connexion", + "register": "S'inscrire", + "firstName": "Prénom", + "lastName": "Nom de famille", + "email": "E-mail", + "password": "Mot de passe", + "confirmPassword": "Confirmer le mot de passe", + "forgotPassword": "Mot de passe oublié", + "enterEmail": "Entrer l'e-mail", + "enterPassword": "Entrer le mot de passe", + "talawaApiUnavailable": "API Talawa indisponible", + "notAuthorised": "Non autorisé", + "notFound": "Non trouvé", + "OR": "OU", + "admin": "Administrateur", + "user": "Utilisateur", + "loading": "Chargement" }, "userLoginPage": { "title": "Administrateur Talawa", @@ -38,7 +56,23 @@ "successfullyRegistered": "Enregistré avec succès. ", "userLogin": "Utilisateur en ligne", "afterRegister": "Enregistré avec succès. ", - "selectOrg": "Sélectionnez une organisation" + "selectOrg": "Sélectionnez une organisation", + "talawa_portal": "Portail Talawa", + "login": "Connexion", + "register": "S'inscrire", + "firstName": "Prénom", + "lastName": "Nom de famille", + "email": "E-mail", + "password": "Mot de passe", + "confirmPassword": "Confirmer le mot de passe", + "forgotPassword": "Mot de passe oublié", + "enterEmail": "Entrer l'e-mail", + "enterPassword": "Entrer le mot de passe", + "talawaApiUnavailable": "API Talawa indisponible", + "notAuthorised": "Non autorisé", + "notFound": "Non trouvé", + "OR": "OU", + "loading": "Chargement" }, "latestEvents": { "eventCardTitle": "évènements à venir", @@ -51,12 +85,19 @@ "noPostsCreated": "Aucun message créé" }, "listNavbar": { - "roles": "Les rôles" + "roles": "Les rôles", + "talawa_portal": "Portail Talawa", + "requests": "Demandes", + "logout": "Déconnexion" }, "leftDrawer": { "my organizations": "Mes organisations", "requests": "Demandes d'adhésion", - "communityProfile": "Profil de la communauté" + "communityProfile": "Profil de la communauté", + "talawaAdminPortal": "Portail Administrateur Talawa", + "menu": "Menu", + "users": "Utilisateurs", + "logout": "Déconnexion" }, "leftDrawerOrg": { "Dashboard": "Tableau de bord", @@ -75,7 +116,13 @@ "notifications": "Notifications", "spamsThe": "spamme le", "group": "groupe", - "noNotifications": "Aucune notification" + "noNotifications": "Aucune notification", + "talawaAdminPortal": "Portail Administrateur Talawa", + "menu": "Menu", + "talawa_portal": "Portail Talawa", + "settings": "Paramètres", + "logout": "Déconnexion", + "close": "Fermer" }, "orgList": { "title": "Organisations Talawa", @@ -105,11 +152,25 @@ "manageFeaturesInfo": "Création réussie ! ", "goToStore": "Accédez à la boutique de plugins", "enableEverything": "Activer tout", - "sampleOrgSuccess": "Exemple d'organisation créée avec succès" + "sampleOrgSuccess": "Exemple d'organisation créée avec succès", + "name": "Nom", + "email": "E-mail", + "searchByName": "Rechercher par nom", + "description": "Description", + "location": "Emplacement", + "address": "Adresse", + "displayImage": "Image d'affichage", + "filter": "Filtrer", + "cancel": "Annuler", + "endOfResults": "Fin des résultats", + "noResultsFoundFor": "Aucun résultat trouvé pour", + "OR": "OU" }, "orgListCard": { "manage": "Gérer", - "sampleOrganization": "Exemple d'organisation" + "sampleOrganization": "Exemple d'organisation", + "admins": "Administrateurs", + "members": "Membres" }, "paginationList": { "rowsPerPage": "lignes par page", @@ -126,7 +187,11 @@ "acceptedSuccessfully": "Demande acceptée avec succès", "rejectedSuccessfully": "Demande rejetée avec succès", "noOrgErrorTitle": "Organisations introuvables", - "noOrgErrorDescription": "Veuillez créer une organisation via le tableau de bord" + "noOrgErrorDescription": "Veuillez créer une organisation via le tableau de bord", + "name": "Nom", + "email": "E-mail", + "endOfResults": "Fin des résultats", + "noResultsFoundFor": "Aucun résultat trouvé pour" }, "users": { "title": "Rôles Talawa", @@ -150,7 +215,25 @@ "visit": "Visite", "withdraw": "Largeur de tirage", "removeUserFrom": "Supprimer l'Utilisateur de {{org}}", - "removeConfirmation": "Êtes-vous sûr de vouloir supprimer '{{name}}' de l'organisation '{{org}}' ?" + "removeConfirmation": "Êtes-vous sûr de vouloir supprimer '{{name}}' de l'organisation '{{org}}' ?", + "searchByName": "Rechercher par nom", + "users": "Utilisateurs", + "name": "Nom", + "email": "E-mail", + "endOfResults": "Fin des résultats", + "admin": "Administrateur", + "superAdmin": "Super Administrateur", + "user": "Utilisateur", + "filter": "Filtrer", + "noResultsFoundFor": "Aucun résultat trouvé pour", + "talawaApiUnavailable": "API Talawa indisponible", + "cancel": "Annuler", + "admins": "Administrateurs", + "members": "Membres", + "orgJoined": "Organisation Rejointe", + "MembershipRequestSent": "Demande d'adhésion envoyée", + "AlreadyJoined": "Déjà rejoint", + "errorOccured": "Une erreur s'est produite" }, "communityProfile": { "title": "Profil de la communauté", @@ -178,7 +261,12 @@ "latestPosts": "Derniers messages", "noPostsPresent": "Aucun message présent", "membershipRequests": "Demandes d'adhésion", - "noMembershipRequests": "Aucune demande d'adhésion présente" + "noMembershipRequests": "Aucune demande d'adhésion présente", + "location": "Emplacement", + "members": "Membres", + "admins": "Administrateurs", + "requests": "Demandes", + "talawaApiUnavailable": "API Talawa indisponible" }, "organizationPeople": { "title": "Membres Talawa", @@ -198,23 +286,79 @@ "enterLastName": "Entrez votre nom de famille", "enterConfirmPassword": "Entrez votre mot de passe pour confirmer", "organization": "Organisation", - "invalidDetailsMessage": "Veuillez saisir des informations valides." + "user": "Utilisateur", + "profile": "Profil", + "invalidDetailsMessage": "Veuillez saisir des informations valides.", + "members": "Membres", + "admins": "Administrateurs", + "users": "Utilisateurs", + "searchFirstName": "Rechercher par prénom", + "searchLastName": "Rechercher par nom de famille", + "firstName": "Prénom", + "lastName": "Nom de famille", + "emailAddress": "Adresse e-mail", + "enterEmail": "Entrer l'e-mail", + "password": "Mot de passe", + "enterPassword": "Entrer le mot de passe", + "confirmPassword": "Confirmer le mot de passe", + "create": "Créer", + "cancel": "Annuler" + }, + "organizationTags": { + "title": "Étiquettes d'Organisation", + "createTag": "Créer une nouvelle étiquette", + "manageTag": "Gérer", + "editTag": "Modifier", + "removeTag": "Supprimer", + "tagDetails": "Détails de l'Étiquette", + "tagName": "Nom", + "tagType": "Type", + "tagNamePlaceholder": "Écrire le nom de l'étiquette", + "tagCreationSuccess": "Nouvelle étiquette créée avec succès", + "tagUpdationSuccess": "Étiquette mise à jour avec succès", + "tagRemovalSuccess": "Étiquette supprimée avec succès", + "noTagsFound": "Aucune étiquette trouvée", + "removeUserTag": "Supprimer l'Étiquette", + "removeUserTagMessage": "Voulez-vous supprimer cette étiquette ?", + "addChildTag": "Ajouter une Sous-Étiquette" + }, + "manageTag": { + "title": "Détails de l'étiquette", + "addPeopleToTag": "Ajouter des personnes à l'étiquette", + "viewProfile": "Voir", + "noAssignedMembersFound": "Aucun membre assigné", + "unassignUserTag": "Désassigner l'étiquette", + "unassignUserTagMessage": "Voulez-vous retirer l'étiquette de cet utilisateur?", + "successfullyUnassigned": "Étiquette retirée de l'utilisateur", + "addPeople": "Ajouter des personnes", + "add": "Ajouter", + "subTags": "Sous-étiquettes" }, "userListCard": { "addAdmin": "Ajouter un administrateur", - "addedAsAdmin": "L'utilisateur est ajouté en tant qu'administrateur." + "addedAsAdmin": "L'utilisateur est ajouté en tant qu'administrateur.", + "joined": "Rejoint", + "talawaApiUnavailable": "API Talawa indisponible" }, "orgAdminListCard": { "remove": "Retirer", "removeAdmin": "Supprimer l'administrateur", "removeAdminMsg": "Voulez-vous supprimer cet administrateur ?", - "adminRemoved": "L'administrateur est supprimé." + "adminRemoved": "L'administrateur est supprimé.", + "joined": "Rejoint", + "no": "Non", + "yes": "Oui", + "talawaApiUnavailable": "API Talawa indisponible" }, "orgPeopleListCard": { "remove": "Retirer", "removeMember": "Supprimer un membre", "removeMemberMsg": "Voulez-vous supprimer ce membre ?", - "memberRemoved": "Le membre est supprimé" + "memberRemoved": "Le membre est supprimé", + "joined": "Rejoint", + "no": "Non", + "yes": "Oui", + "talawaApiUnavailable": "API Talawa indisponible" }, "organizationEvents": { "title": "Événements", @@ -245,7 +389,14 @@ "never": "Jamais", "on": "Sur", "after": "Après", - "occurences": "événements" + "occurences": "événements", + "events": "Événements", + "description": "Description", + "location": "Emplacement", + "startDate": "Date de début", + "endDate": "Date de fin", + "talawaApiUnavailable": "API Talawa indisponible", + "done": "Fait" }, "organizationActionItems": { "actionItemCategory": "Catégorie d'élément d'action", @@ -256,7 +407,6 @@ "assignmentDate": "Date d'affectation", "active": "Actif", "clearFilters": "Effacer les filtres", - "completed": "Complété", "completionDate": "Date d'achèvement", "createActionItem": "Créer un élément d'action", "deleteActionItem": "Supprimer l'élément d'action", @@ -281,7 +431,18 @@ "successfulCreation": "Élément d'action créé avec succès", "successfulUpdation": "Élément d'action mis à jour avec succès", "successfulDeletion": "Élément d'action supprimé avec succès", - "title": "Éléments d'action" + "title": "Éléments d'action", + "category": "Catégorie", + "allotedHours": "Heures allouées", + "latestDueDate": "Date d'échéance la plus récente", + "earliestDueDate": "Date d'échéance la plus ancienne", + "updateActionItem": "Mettre à jour l'élément d'action", + "noneUpdated": "Aucun des champs n'a été mis à jour", + "updateStatusMsg": "Êtes-vous sûr de vouloir marquer cet élément d'action comme en attente?", + "close": "Fermer", + "eventActionItems": "Éléments d'action d'événement", + "no": "Non", + "yes": "Oui" }, "organizationAgendaCategory": { "agendaCategoryDetails": "Détails de la catégorie d'ordre du jour", @@ -360,7 +521,17 @@ "never": "Jamais", "on": "Sur", "after": "Après", - "occurences": "événements" + "occurences": "événements", + "location": "Lieu", + "no": "Non", + "yes": "Oui", + "description": "Description", + "startDate": "Date de début", + "endDate": "Date de fin", + "registerEvent": "Inscrire à l'événement", + "close": "Fermer", + "talawaApiUnavailable": "API Talawa non disponible", + "done": "Terminé" }, "funds": { "title": "Fonds", @@ -436,7 +607,9 @@ "pledges": "Promesses de dons", "endsOn": "Se termine le", "raisedAmount": "Montant collecté", - "pledgedAmount": "Montant promis" + "pledgedAmount": "Montant promis", + "startDate": "Date de début", + "endDate": "Date de fin" }, "orgPost": { "title": "Des postes", @@ -464,7 +637,8 @@ "postCreatedSuccess": "Toutes nos félicitations! ", "pinPost": "Épingler le message", "Next": "Page suivante", - "Previous": "Page précédente" + "Previous": "Page précédente", + "cancel": "Annuler" }, "postNotFound": { "post": "Poste", @@ -479,7 +653,8 @@ "user not found!": "Utilisateur non trouvé!", "member not found!": "Membre introuvable!", "admin not found!": "Administrateur introuvable !", - "roles not found!": "Rôles introuvables !" + "roles not found!": "Rôles introuvables !", + "user": "Utilisateur" }, "orgPostCard": { "author": "Auteur", @@ -498,7 +673,12 @@ "postDeleted": "Message supprimé avec succès.", "postUpdated": "Post mis à jour avec succès.", "tag": " Votre navigateur ne prend pas en charge la balise vidéo", - "pin": "Épingler le message" + "pin": "Épingler le message", + "edit": "Modifier", + "no": "Non", + "yes": "Oui", + "close": "Fermer", + "talawaApiUnavailable": "API Talawa non disponible" }, "blockUnblockUser": { "title": "Bloquer/débloquer un utilisateur", @@ -514,7 +694,12 @@ "blockedUsers": "Utilisateurs bloqués", "searchByFirstName": "Recherche par prénom", "searchByLastName": "Rechercher par nom de famille", - "noSpammerFound": "Aucun spammeur trouvé" + "noSpammerFound": "Aucun spammeur trouvé", + "searchByName": "Rechercher par nom", + "name": "Nom", + "email": "Email", + "talawaApiUnavailable": "API Talawa non disponible", + "noResultsFoundFor": "Aucun résultat trouvé pour" }, "eventManagement": { "title": "Gestion d'événements", @@ -539,7 +724,10 @@ "errorSendingMail": "Erreur lors de l'envoi du courrier.", "passwordMismatches": "Mot de passe et Confirmer les incompatibilités de mot de passe.", "passwordChanges": "Le mot de passe a été modifié avec succès.", - "OTPsent": "OTP est envoyé à votre adresse e-mail enregistrée." + "OTPsent": "OTP est envoyé à votre adresse e-mail enregistrée.", + "forgotPassword": "Mot de passe oublié", + "password": "Mot de passe", + "talawaApiUnavailable": "API Talawa non disponible" }, "pageNotFound": { "404": "404", @@ -574,10 +762,11 @@ "actionItemCategories": "Catégories d'éléments d'action", "updateOrganization": "Mettre à jour l'organisation", "seeRequest": "Voir la demande", - "noData": "Pas de données", - "otherSettings": "Autres réglages", + "noData": "Aucune donnée", + "otherSettings": "Autres paramètres", "changeLanguage": "Changer de langue", - "manageCustomFields": "Gérer les champs personnalisés" + "manageCustomFields": "Gérer les champs personnalisés", + "agendaItemCategories": "Catégories d'éléments d'agenda" }, "deleteOrg": { "deleteOrganization": "Supprimer l'organisation", @@ -585,18 +774,30 @@ "deleteMsg": "Voulez-vous supprimer cette organisation ?", "confirmDelete": "Confirmation de la suppression", "longDelOrgMsg": "En cliquant sur le bouton Supprimer l'organisation, l'organisation sera définitivement supprimée ainsi que ses événements, balises et toutes les données associées.", - "successfullyDeletedSampleOrganization": "Exemple d'organisation supprimé avec succès" + "successfullyDeletedSampleOrganization": "Exemple d'organisation supprimé avec succès", + "cancel": "Annuler" }, "userUpdate": { "appLanguageCode": "Langage par défaut", - "userType": "Type d'utilisateur" + "userType": "Type d'utilisateur", + "firstName": "Prénom", + "lastName": "Nom de famille", + "email": "Email", + "password": "Mot de passe", + "admin": "Admin", + "superAdmin": "Super Admin", + "displayImage": "Image d'affichage", + "saveChanges": "Enregistrer les modifications", + "cancel": "Annuler" }, "userPasswordUpdate": { "previousPassword": "Mot de passe précédent", "newPassword": "nouveau mot de passe", "confirmNewPassword": "Confirmer le nouveau mot de passe", "passCantBeEmpty": "Le mot de passe ne peut pas être vide", - "passNoMatch": "Le nouveau mot de passe et la confirmation du mot de passe ne correspondent pas." + "passNoMatch": "Le nouveau mot de passe et la confirmation du mot de passe ne correspondent pas.", + "saveChanges": "Enregistrer les modifications", + "cancel": "Annuler" }, "orgDelete": { "deleteOrg": "Supprimer l'organisation" @@ -604,7 +805,9 @@ "membershipRequest": { "accept": "Accepter", "reject": "Rejeter", - "memberAdded": "c'est accepté" + "memberAdded": "c'est accepté", + "joined": "Rejoint", + "talawaApiUnavailable": "API Talawa non disponible" }, "orgUpdate": { "city": "Ville", @@ -618,7 +821,15 @@ "userRegistrationRequired": "Inscription de l'utilisateur requise", "isVisibleInSearch": "Visible dans la recherche", "enterNameOrganization": "Entrez le nom de l'organisation", - "successfulUpdated": "Organisation mise à jour avec succès" + "successfulUpdated": "Organisation mise à jour avec succès", + "name": "Nom", + "description": "Description", + "location": "Lieu", + "address": "Adresse", + "displayImage": "Image d'affichage", + "saveChanges": "Enregistrer les modifications", + "cancel": "Annuler", + "talawaApiUnavailable": "API Talawa non disponible" }, "addOnRegister": { "addNew": "Ajouter un nouveau", @@ -628,7 +839,9 @@ "pluginDesc": "Description du plugin", "pName": "Ex : Dons", "cName": "Ex : John Doe", - "pDesc": "Ce plugin active l'interface utilisateur pour" + "pDesc": "Ce plugin active l'interface utilisateur pour", + "close": "Fermer", + "register": "Inscription" }, "addOnStore": { "title": "Ajouter sur la boutique", @@ -639,7 +852,8 @@ "pHeading": "Plugins", "install": "installée", "available": "Disponible", - "pMessage": "Le plugin n'existe pas" + "pMessage": "Le plugin n'existe pas", + "filter": "filtrer" }, "addOnEntry": { "enable": "Activé", @@ -681,14 +895,32 @@ "membershipRequests": "Demandes d'adhésion", "adminForEvents": "Administrateur pour les événements", "addedAsAdmin": "L'utilisateur est ajouté en tant qu'administrateur.", - "userType": "Type d'utilisateur" + "userType": "Type d'utilisateur", + "email": "Email", + "displayImage": "Image d'affichage", + "address": "Adresse", + "delete": "Supprimer", + "saveChanges": "Enregistrer les modifications", + "joined": "Rejoint", + "talawaApiUnavailable": "API Talawa non disponible" + }, + "people": { + "title": "Personnes", + "searchUsers": "Rechercher des utilisateurs" }, "userLogin": { "login": "Se connecter", "loginIntoYourAccount": "Connectez-vous à votre compte", "invalidDetailsMessage": "Veuillez entrer un email et un mot de passe valides.", "notAuthorised": "Désolé! ", - "invalidCredentials": "Les informations d'identification saisies sont incorrectes. " + "invalidCredentials": "Les informations d'identification saisies sont incorrectes. ", + "forgotPassword": "Mot de passe oublié", + "emailAddress": "Adresse email", + "enterEmail": "Entrer l'email", + "password": "Mot de passe", + "enterPassword": "Entrer le mot de passe", + "register": "Inscription", + "talawaApiUnavailable": "API Talawa non disponible" }, "userRegister": { "enterFirstName": "Entrez votre prénom", @@ -698,7 +930,16 @@ "login": "Se connecter", "afterRegister": "Enregistré avec succès. ", "passwordNotMatch": "Le mot de passe ne correspond pas. ", - "invalidDetailsMessage": "Veuillez saisir des informations valides." + "invalidDetailsMessage": "Veuillez saisir des informations valides.", + "register": "Inscription", + "firstName": "Prénom", + "lastName": "Nom de famille", + "emailAddress": "Adresse email", + "enterEmail": "Entrer l'email", + "password": "Mot de passe", + "enterPassword": "Entrer le mot de passe", + "confirmPassword": "Confirmer le mot de passe", + "talawaApiUnavailable": "API Talawa non disponible" }, "userNavbar": { "talawa": "Talawa", @@ -707,7 +948,10 @@ "events": "Événements", "chat": "Chat", "donate": "Faire un don", - "language": "Langue" + "language": "Langue", + "settings": "Paramètres", + "logout": "Déconnexion", + "close": "Fermer" }, "userOrganizations": { "allOrganizations": "Toutes les organisations", @@ -716,7 +960,11 @@ "selectOrganization": "Sélectionnez une organisation", "searchUsers": "Rechercher des utilisateurs", "nothingToShow": "Rien à montrer ici.", - "organizations": "Organisations" + "organizations": "Organisations", + "search": "Rechercher", + "filter": "Filtrer", + "searchByName": "Rechercher par nom", + "searchOrganizations": "Rechercher Organisations" }, "userSidebarOrg": { "yourOrganizations": "Vos organisations", @@ -724,13 +972,20 @@ "viewAll": "Voir tout", "talawaUserPortal": "Portail utilisateur Talawa", "my organizations": "Mes organisations", - "communityProfile": "Profil de la communauté" + "communityProfile": "Profil de la communauté", + "users": "utilisateurs", + "requests": "demandes", + "logout": "se déconnecter", + "settings": "paramètres", + "chat": "discussion", + "menu": "Menu" }, "organizationSidebar": { "viewAll": "Voir tout", "events": "Événements", "noEvents": "Aucun événement à afficher", - "noMembers": "Aucun membre à afficher" + "noMembers": "Aucun membre à afficher", + "members": "Membres" }, "postCard": { "likes": "Aime", @@ -809,9 +1064,18 @@ "fullTime": "À temps plein", "partTime": "À temps partiel", "selectCountry": "Choisissez un pays", - "enterState": "Entrez la ville ou l'état" + "enterState": "Entrez la ville ou l'état", + "settings": "Paramètres", + "firstName": "Prénom", + "lastName": "Nom de famille", + "emailAddress": "Adresse email", + "displayImage": "Image d'affichage", + "address": "Adresse", + "saveChanges": "Enregistrer les modifications", + "joined": "Rejoint" }, "donate": { + "title": "Des dons", "donations": "Des dons", "searchDonations": "Rechercher des dons", "donateForThe": "Faites un don pour le", @@ -819,9 +1083,14 @@ "yourPreviousDonations": "Vos dons précédents", "donate": "Faire un don", "nothingToShow": "Rien à montrer ici.", - "success": "Don réussi" + "success": "Don réussi", + "invalidAmount": "Veuillez saisir une valeur numérique pour le montant du don.", + "donationAmountDescription": "Veuillez saisir la valeur numérique du montant du don.", + "donationOutOfRange": "Le montant du don doit être compris entre {{min}} et {{max}}.", + "donateTo": "Faire un don à" }, "userEvents": { + "title": "Événements", "nothingToShow": "Rien à montrer ici.", "createEvent": "Créer un évènement", "recurring": "Événement récurrent", @@ -839,13 +1108,22 @@ "publicEvent": "est public", "registerable": "Est enregistrable", "monthlyCalendarView": "Calendrier mensuel", - "yearlyCalendarView": "Calendrier annuel" + "yearlyCalendarView": "Calendrier annuel", + "search": "Rechercher", + "cancel": "Annuler", + "create": "Créer", + "eventDescription": "Description de l'événement", + "eventLocation": "Lieu de l'événement", + "startDate": "Date de début", + "endDate": "Date de fin" }, "userEventCard": { "starts": "Départs", "ends": "Prend fin", "creator": "Créateur", - "alreadyRegistered": "Déjà enregistré" + "alreadyRegistered": "Déjà enregistré", + "location": "Lieu", + "register": "Inscription" }, "advertisement": { "title": "Annonces", @@ -870,11 +1148,21 @@ "editAdvertisement": "Modifier l'annonce", "advertisementDeleted": "Publicité supprimée avec succès.", "endDateGreaterOrEqual": "La date de fin doit être supérieure ou égale à la date de début", - "advertisementCreated": "Publicité créée avec succès." + "advertisementCreated": "Publicité créée avec succès.", + "pHeading": "Titre principal", + "delete": "Supprimer", + "close": "Fermer", + "no": "Non", + "yes": "Oui", + "edit": "Modifier", + "saveChanges": "Enregistrer les modifications", + "endOfResults": "Fin des résultats" }, "userChat": { "chat": "Chat", - "contacts": "Contacts" + "contacts": "Contacts", + "search": "rechercher", + "messages": "messages" }, "userChatRoom": { "selectContact": "Sélectionnez un contact pour démarrer la conversation", @@ -892,20 +1180,28 @@ "String": "Chaîne", "Boolean": "Booléen", "Date": "Date", - "Number": "Nombre" + "Number": "Nombre", + "saveChanges": "Enregistrer les modifications" }, "orgActionItemCategories": { "enableButton": "Activer", "disableButton": "Désactiver", "updateActionItemCategory": "Mise à jour", "actionItemCategoryName": "Nom", - "actionItemCategoryDetails": "Détails de la catégorie d'élément d'action", + "categoryDetails": "Détails de la catégorie", "enterName": "Entrez le nom", "successfulCreation": "Catégorie d'élément d'action créée avec succès", "successfulUpdation": "Catégorie d'élément d'action mise à jour avec succès", "sameNameConflict": "Veuillez changer le nom pour effectuer une mise à jour", "categoryEnabled": "Catégorie d'élément d'action activée", - "categoryDisabled": "Catégorie d'élément d'action désactivée" + "categoryDisabled": "Catégorie d'élément d'action désactivée", + "noActionItemCategories": "Aucune catégorie d'élément d'action", + "status": "Statut", + "categoryDeleted": "Catégorie d'élément d'action supprimée avec succès", + "deleteCategory": "Supprimer la catégorie", + "deleteCategoryMsg": "Êtes-vous sûr de vouloir supprimer cette catégorie d'élément d'action ?", + "createButton": "Créer", + "editButton": "Modifier" }, "organizationVenues": { "title": "Lieux", @@ -929,7 +1225,12 @@ "view": "Voir", "venueTitleError": "Le titre du lieu ne peut pas être vide !", "venueCapacityError": "La capacité doit être un nombre positif !", - "searchBy": "Recherché par" + "searchBy": "Recherché par", + "description": "Description", + "edit": "Modifier", + "delete": "Supprimer", + "name": "Nom", + "desc": "Description" }, "addMember": { "title": "Ajouter un membre", @@ -943,7 +1244,18 @@ "organization": "Organisation", "invalidDetailsMessage": "Veuillez fournir tous les détails requis.", "passwordNotMatch": "Les mots de passe ne correspondent pas.", - "addMember": "Ajouter un membre" + "addMember": "Ajouter un membre", + "firstName": "Prénom", + "lastName": "Nom de famille", + "emailAddress": "Adresse email", + "enterEmail": "Entrer l'email", + "password": "Mot de passe", + "enterPassword": "Entrer le mot de passe", + "confirmPassword": "Confirmer le mot de passe", + "cancel": "Annuler", + "create": "Créer", + "user": "Utilisateur", + "profile": "Profil" }, "eventActionItems": { "title": "Éléments d'action", @@ -971,7 +1283,9 @@ "actionItemStatus": "Statut de l'action", "actionItemCompleted": "Élément d'action terminé", "markCompletion": "Marquer l'achèvement", - "save": "Sauvegarder" + "save": "Sauvegarder", + "yes": "Oui", + "no": "Non" }, "checkIn": { "errorCheckingIn": "Erreur lors de l'enregistrement", @@ -980,5 +1294,26 @@ "eventRegistrantsModal": { "errorAddingAttendee": "Erreur lors de l'ajout du participant", "errorRemovingAttendee": "Erreur lors de la suppression du participant" + }, + "userCampaigns": { + "title": "Campagnes de financement", + "searchByName": "Rechercher par nom...", + "searchBy": "Rechercher par", + "pledgers": "Contributeurs", + "campaigns": "Campagnes", + "myPledges": "Mes Promesses", + "lowestAmount": "Montant le plus bas", + "highestAmount": "Montant le plus élevé", + "lowestGoal": "Objectif le plus bas", + "highestGoal": "Objectif le plus élevé", + "latestEndDate": "Date de fin la plus tardive", + "earliestEndDate": "Date de fin la plus proche", + "addPledge": "Ajouter une promesse", + "viewPledges": "Voir les promesses", + "noPledges": "Aucune promesse trouvée", + "noCampaigns": "Aucune campagne trouvée" + }, + "userPledges": { + "title": "Mes Promesses" } } diff --git a/public/locales/hi/common.json b/public/locales/hi/common.json index 3889f73e59..c044033db5 100644 --- a/public/locales/hi/common.json +++ b/public/locales/hi/common.json @@ -82,5 +82,14 @@ "addedSuccessfully": "{{item}} सफलतापूर्वक जोड़ा गया", "updatedSuccessfully": "{{item}} सफलतापूर्वक अपडेट किया गया", "removedSuccessfully": "{{item}} सफलतापूर्वक हटाया गया", - "successfullyUpdated": "सफलतापूर्वक अपडेट किया गया" + "successfullyUpdated": "सफलतापूर्वक अपडेट किया गया", + "all": "सभी", + "active": "सक्रिय", + "disabled": "अक्षम", + "pending": "लंबित", + "completed": "पूरा हुआ", + "late": "देर से", + "createdLatest": "नवीनतम बनाया गया", + "createdEarliest": "सबसे पहले बनाया गया", + "searchBy": "के द्वारा खोजें {{item}}" } diff --git a/public/locales/hi/errors.json b/public/locales/hi/errors.json index c31c72fa34..63b6c3f5d3 100644 --- a/public/locales/hi/errors.json +++ b/public/locales/hi/errors.json @@ -6,5 +6,6 @@ "errorSendingMail": "मेल भेजने में त्रुटि", "emailNotRegistered": "ईमेल पंजीकृत नहीं है", "notFoundMsg": "उफ़! ", - "errorOccurredCouldntCreate": "एक त्रुटि हुई। {{entity}} नहीं बना सके" + "errorOccurredCouldntCreate": "एक त्रुटि हुई। {{entity}} नहीं बना सके", + "errorLoading": "{{entity}} डेटा लोड करते समय त्रुटि हुई" } diff --git a/public/locales/hi/translation.json b/public/locales/hi/translation.json index ab850249e2..95d704daca 100644 --- a/public/locales/hi/translation.json +++ b/public/locales/hi/translation.json @@ -1,49 +1,83 @@ { "loginPage": { - "title": "तलावा प्रशासन", - "fromPalisadoes": "पैलिसाडोज़ फाउंडेशन के स्वयंसेवकों द्वारा एक खुला स्रोत एप्लिकेशन", + "title": "तालावा व्यवस्थापक", + "fromPalisadoes": "Palisadoes फाउंडेशन स्वयंसेवकों द्वारा विकसित एक ओपन-सोर्स एप्लिकेशन", "userLogin": "उपयोगकर्ता लॉगिन", - "atleast_8_char_long": "कम से कम 8 अक्षर लंबा", - "atleast_6_char_long": "कम से कम 6 अक्षर लंबा", - "firstName_invalid": "प्रथम नाम में केवल छोटे और बड़े अक्षर होने चाहिए", - "lastName_invalid": "अंतिम नाम में केवल छोटे और बड़े अक्षर होने चाहिए", - "password_invalid": "पासवर्ड में कम से कम एक लोअरकेस अक्षर, एक अपरकेस अक्षर, एक संख्यात्मक मान और एक विशेष अक्षर होना चाहिए", + "atleast_8_char_long": "कम से कम 8 अक्षर लंबे", + "atleast_6_char_long": "कम से कम 6 अक्षर लंबे", + "firstName_invalid": "पहला नाम केवल छोटे और बड़े अक्षरों को शामिल कर सकता है", + "lastName_invalid": "अंतिम नाम केवल छोटे और बड़े अक्षरों को शामिल कर सकता है", + "password_invalid": "पासवर्ड में कम से कम 1 छोटा अक्षर, 1 बड़ा अक्षर, 1 संख्या और 1 विशेष अक्षर होना चाहिए", "email_invalid": "ईमेल में कम से कम 8 अक्षर होने चाहिए", - "Password_and_Confirm_password_mismatches.": "पासवर्ड और पासवर्ड बेमेल होने की पुष्टि करें।", - "doNotOwnAnAccount": "क्या आपके पास कोई खाता नहीं है?", + "Password_and_Confirm_password_mismatches.": "पासवर्ड और पुष्टि पासवर्ड मेल नहीं खाते।", + "doNotOwnAnAccount": "कोई खाता नहीं है?", "captchaError": "कैप्चा त्रुटि!", - "Please_check_the_captcha": "कृपया, कैप्चा जांचें।", - "Something_went_wrong": "कुछ ग़लत हो गया, कृपया कुछ देर बाद प्रयास करें।", - "passwordMismatches": "पासवर्ड और पासवर्ड बेमेल होने की पुष्टि करें।", - "fillCorrectly": "सभी विवरण सही-सही भरें।", - "successfullyRegistered": "पंजीकरण सफलतापूर्वक हो गया है। ", + "Please_check_the_captcha": "कृपया कैप्चा जांचें।", + "Something_went_wrong": "कुछ गलत हो गया, कृपया बाद में पुनः प्रयास करें।", + "passwordMismatches": "पासवर्ड और पुष्टि पासवर्ड मेल नहीं खाते।", + "fillCorrectly": "सभी विवरण सही ढंग से भरें।", + "successfullyRegistered": "सफलतापूर्वक पंजीकृत।", "lowercase_check": "कम से कम एक छोटा अक्षर", "uppercase_check": "कम से कम एक बड़ा अक्षर", - "numeric_value_check": "कम से कम एक संख्यात्मक मान निर्धारित करें", - "special_char_check": "कम से कम एक विशेष पात्र", + "numeric_value_check": "कम से कम एक संख्या", + "special_char_check": "कम से कम एक विशेष अक्षर", "selectOrg": "एक संगठन चुनें", - "afterRegister": "पंजीकरण सफलतापूर्वक हो गया है। " + "afterRegister": "सफलतापूर्वक पंजीकृत।", + "talawa_portal": "तालावा पोर्टल", + "login": "लॉगिन", + "register": "पंजीकरण", + "firstName": "पहला नाम", + "lastName": "अंतिम नाम", + "email": "ईमेल", + "password": "पासवर्ड", + "confirmPassword": "पुष्टि पासवर्ड", + "forgotPassword": "पासवर्ड भूल गए", + "enterEmail": "ईमेल दर्ज करें", + "enterPassword": "पासवर्ड दर्ज करें", + "talawaApiUnavailable": "तालावा एपीआई अनुपलब्ध", + "notAuthorised": "अनधिकृत", + "notFound": "नहीं मिला", + "OR": "या", + "admin": "व्यवस्थापक", + "user": "उपयोगकर्ता", + "loading": "लोड हो रहा है" }, "userLoginPage": { - "title": "तलावा प्रशासन", - "fromPalisadoes": "पैलिसाडोज़ फाउंडेशन के स्वयंसेवकों द्वारा एक खुला स्रोत एप्लिकेशन", - "atleast_8_char_long": "कम से कम 8 अक्षर लंबा", - "Password_and_Confirm_password_mismatches.": "पासवर्ड और पासवर्ड बेमेल होने की पुष्टि करें।", - "doNotOwnAnAccount": "क्या आपके पास कोई खाता नहीं है?", + "title": "तालावा व्यवस्थापक", + "fromPalisadoes": "Palisadoes फाउंडेशन स्वयंसेवकों द्वारा विकसित एक ओपन-सोर्स एप्लिकेशन", + "atleast_8_char_long": "कम से कम 8 अक्षर लंबे", + "Password_and_Confirm_password_mismatches.": "पासवर्ड और पुष्टि पासवर्ड मेल नहीं खाते।", + "doNotOwnAnAccount": "कोई खाता नहीं है?", "captchaError": "कैप्चा त्रुटि!", - "Please_check_the_captcha": "कृपया, कैप्चा जांचें।", - "Something_went_wrong": "कुछ ग़लत हो गया, कृपया कुछ देर बाद प्रयास करें।", - "passwordMismatches": "पासवर्ड और पासवर्ड बेमेल होने की पुष्टि करें।", - "fillCorrectly": "सभी विवरण सही-सही भरें।", - "successfullyRegistered": "पंजीकरण सफलतापूर्वक हो गया है। ", + "Please_check_the_captcha": "कृपया कैप्चा जांचें।", + "Something_went_wrong": "कुछ गलत हो गया, कृपया बाद में पुनः प्रयास करें।", + "passwordMismatches": "पासवर्ड और पुष्टि पासवर्ड मेल नहीं खाते।", + "fillCorrectly": "सभी विवरण सही ढंग से भरें।", + "successfullyRegistered": "सफलतापूर्वक पंजीकृत।", "userLogin": "उपयोगकर्ता लॉगिन", - "afterRegister": "पंजीकरण सफलतापूर्वक हो गया है। ", - "selectOrg": "एक संगठन चुनें" + "afterRegister": "सफलतापूर्वक पंजीकृत।", + "selectOrg": "एक संगठन चुनें", + "talawa_portal": "तालावा पोर्टल", + "login": "लॉगिन", + "register": "पंजीकरण", + "firstName": "पहला नाम", + "lastName": "अंतिम नाम", + "email": "ईमेल", + "password": "पासवर्ड", + "confirmPassword": "पुष्टि पासवर्ड", + "forgotPassword": "पासवर्ड भूल गए", + "enterEmail": "ईमेल दर्ज करें", + "enterPassword": "पासवर्ड दर्ज करें", + "talawaApiUnavailable": "तालावा एपीआई अनुपलब्ध", + "notAuthorised": "अनधिकृत", + "notFound": "नहीं मिला", + "OR": "या", + "loading": "लोड हो रहा है" }, "latestEvents": { - "eventCardTitle": "आगामी कार्यक्रम", + "eventCardTitle": "आगामी घटनाएँ", "eventCardSeeAll": "सभी देखें", - "noEvents": "कोई आगामी ईवेंट नहीं" + "noEvents": "कोई आगामी घटनाएँ नहीं हैं" }, "latestPosts": { "latestPostsTitle": "नवीनतम पोस्ट", @@ -51,65 +85,92 @@ "noPostsCreated": "कोई पोस्ट नहीं बनाई गई" }, "listNavbar": { - "roles": "भूमिकाएँ" + "roles": "भूमिकाएँ", + "talawa_portal": "तालावा पोर्टल", + "requests": "अनुरोध", + "logout": "लॉगआउट" }, "leftDrawer": { "my organizations": "मेरे संगठन", "requests": "सदस्यता अनुरोध", - "communityProfile": "सामुदायिक प्रोफ़ाइल" + "communityProfile": "समुदाय प्रोफ़ाइल", + "talawaAdminPortal": "तालावा व्यवस्थापक पोर्टल", + "menu": "मेनू", + "users": "उपयोगकर्ता", + "logout": "लॉगआउट" }, "leftDrawerOrg": { "Dashboard": "डैशबोर्ड", "People": "लोग", - "Events": "आयोजन", + "Events": "घटनाएँ", "Contributions": "योगदान", - "Posts": "पदों", - "Block/Unblock": "ब्लॉक/अनब्लॉक करें", - "Plugins": "प्लग-इन", + "Posts": "पोस्ट", + "Block/Unblock": "ब्लॉक/अनब्लॉक", + "Plugins": "प्लगइन्स", "Plugin Store": "प्लगइन स्टोर", - "Advertisement": "विज्ञापनों", + "Advertisement": "विज्ञापन", "allOrganizations": "सभी संगठन", - "yourOrganization": "आपकी संगठन", - "notification": "अधिसूचना", + "yourOrganization": "आपका संगठन", + "notification": "सूचना", "language": "भाषा", - "notifications": "सूचनाएं", - "spamsThe": "स्पैम करता है", + "notifications": "सूचनाएँ", + "spamsThe": "स्पैम", "group": "समूह", - "noNotifications": "कोई सूचनाएं नहीं" + "noNotifications": "कोई सूचनाएँ नहीं", + "talawaAdminPortal": "तालावा व्यवस्थापक पोर्टल", + "menu": "मेनू", + "talawa_portal": "तालावा पोर्टल", + "settings": "सेटिंग्स", + "logout": "लॉगआउट", + "close": "बंद करें" }, "orgList": { - "title": "तलावा संगठन", + "title": "तालावा संगठन", "you": "आप", - "designation": "पद का नाम", + "designation": "पदनाम", "my organizations": "मेरे संगठन", "createOrganization": "संगठन बनाएं", "createSampleOrganization": "नमूना संगठन बनाएं", "city": "शहर", - "countryCode": "कंट्री कोड", - "dependentLocality": "आश्रित इलाका", + "countryCode": "देश कोड", + "dependentLocality": "निर्भर स्थान", "line1": "लाइन 1", "line2": "लाइन 2", - "postalCode": "डाक कोड", - "sortingCode": "कोड क्रमबद्ध करना", - "state": "राज्य/प्रान्त", + "postalCode": "पोस्टल कोड", + "sortingCode": "सॉर्टिंग कोड", + "state": "राज्य", "userRegistrationRequired": "उपयोगकर्ता पंजीकरण आवश्यक", - "visibleInSearch": "खोज में दृश्यमान", + "visibleInSearch": "खोज में दिखाई दे", "enterName": "नाम दर्ज करें", - "sort": "क्रम से लगाना", + "sort": "प्रकार", "Latest": "नवीनतम", - "Earliest": "जल्द से जल्द", - "noOrgErrorTitle": "संगठन नहीं मिले", - "sampleOrgDuplicate": "केवल एक नमूना संगठन को अनुमति दी गई", - "noOrgErrorDescription": "कृपया डैशबोर्ड के माध्यम से एक संगठन बनाएं", - "manageFeatures": "सुविधाओं को प्रबंधित करें", - "manageFeaturesInfo": "सृजन सफल! ", - "goToStore": "प्लगइन स्टोर पर जाएँ", + "Earliest": "सबसे पहले", + "noOrgErrorTitle": "संगठन नहीं मिला", + "sampleOrgDuplicate": "केवल एक नमूना संगठन की अनुमति है", + "noOrgErrorDescription": "कृपया डैशबोर्ड के माध्यम से संगठन बनाएं", + "manageFeatures": "विशेषताएं प्रबंधित करें", + "manageFeaturesInfo": "सफलतापूर्वक बनाया गया!", + "goToStore": "प्लगइन स्टोर पर जाएं", "enableEverything": "सब कुछ सक्षम करें", - "sampleOrgSuccess": "नमूना संगठन सफलतापूर्वक बनाया गया" + "sampleOrgSuccess": "नमूना संगठन सफलतापूर्वक बनाया गया", + "name": "नाम", + "email": "ईमेल", + "searchByName": "नाम से खोजें", + "description": "विवरण", + "location": "स्थान", + "address": "पता", + "displayImage": "छवि प्रदर्शित करें", + "filter": "फ़िल्टर", + "cancel": "रद्द करें", + "endOfResults": "परिणाम समाप्त", + "noResultsFoundFor": "कोई परिणाम नहीं मिला", + "OR": "या" }, "orgListCard": { - "manage": "प्रबंधित करना", - "sampleOrganization": "नमूना संगठन" + "manage": "प्रबंधित करें", + "sampleOrganization": "संगठन नमूना", + "admins": "प्रशासक", + "members": "सदस्य" }, "paginationList": { "rowsPerPage": "प्रति पृष्ठ पंक्तियाँ", @@ -117,104 +178,187 @@ }, "requests": { "title": "सदस्यता अनुरोध", - "sl_no": "क्र.सं. ", - "accept": "स्वीकार करना", - "reject": "अस्वीकार करना", + "sl_no": "क्रम संख्या", + "accept": "स्वीकार करें", + "reject": "अस्वीकार करें", "searchRequests": "सदस्यता अनुरोध खोजें", - "noOrgError": "संगठन नहीं मिला, कृपया डैशबोर्ड के माध्यम से एक संगठन बनाएं", + "noOrgError": "संगठन नहीं मिला, कृपया डैशबोर्ड के माध्यम से संगठन बनाएं", "noRequestsFound": "कोई सदस्यता अनुरोध नहीं मिला", "acceptedSuccessfully": "अनुरोध सफलतापूर्वक स्वीकार किया गया", - "rejectedSuccessfully": "अनुरोध सफलतापूर्वक अस्वीकार कर दिया गया", - "noOrgErrorTitle": "संगठन नहीं मिले", - "noOrgErrorDescription": "कृपया डैशबोर्ड के माध्यम से एक संगठन बनाएं" + "rejectedSuccessfully": "अनुरोध सफलतापूर्वक अस्वीकार किया गया", + "noOrgErrorTitle": "संगठन नहीं मिला", + "noOrgErrorDescription": "कृपया डैशबोर्ड के माध्यम से संगठन बनाएं", + "name": "नाम", + "email": "ईमेल", + "endOfResults": "परिणाम समाप्त", + "noResultsFoundFor": "कोई परिणाम नहीं मिला" }, "users": { - "title": "तलावा भूमिकाएँ", - "joined_organizations": "संगठनों से जुड़े", + "title": "तालावा भूमिकाएँ", + "joined_organizations": "संगठनों में शामिल हुए", "blocked_organizations": "अवरुद्ध संगठन", - "orgJoinedBy": "संगठनों से जुड़े", - "orgThatBlocked": "वे संगठन जिन्होंने अवरुद्ध किया", - "hasNotJoinedAnyOrg": "किसी भी संगठन में शामिल नहीं हुआ है", - "isNotBlockedByAnyOrg": "किसी भी संगठन द्वारा अवरुद्ध नहीं किया गया है", + "orgJoinedBy": "द्वारा शामिल संगठन", + "orgThatBlocked": "अवरुद्ध संगठन", + "hasNotJoinedAnyOrg": "किसी भी संगठन में शामिल नहीं हुआ", + "isNotBlockedByAnyOrg": "किसी भी संगठन द्वारा अवरुद्ध नहीं किया गया", "searchByOrgName": "संगठन के नाम से खोजें", - "view": "देखना", + "view": "दृश्य", "enterName": "नाम दर्ज करें", - "loadingUsers": "उपयोगकर्ता लोड हो रहे हैं...", + "loadingUsers": "उपयोगकर्ताओं को लोड कर रहा है...", "noUserFound": "कोई उपयोगकर्ता नहीं मिला", - "sort": "क्रम से लगाना", - "Newest": "नवीनतम पहले", - "Oldest": "सबसे पुराना पहले", - "noOrgError": "संगठन नहीं मिला, कृपया डैशबोर्ड के माध्यम से एक संगठन बनाएं", - "roleUpdated": "भूमिका अद्यतन की गई.", - "joinNow": "अब शामिल हों", - "visit": "मिलने जाना", - "withdraw": "चौड़ाई निकालना", - "removeUserFrom": "{{org}} से उपयोगकर्ता हटाएं", - "removeConfirmation": "क्या आप वाकई '{{org}}' संगठन से '{{name}}' को हटाना चाहते हैं?" + "sort": "प्रकार", + "Newest": "नवीनतम", + "Oldest": "सबसे पुराना", + "noOrgError": "संगठन नहीं मिला, कृपया डैशबोर्ड के माध्यम से संगठन बनाएं", + "roleUpdated": "भूमिका अपडेट की गई।", + "joinNow": "अभी शामिल हों", + "visit": "यात्रा", + "withdraw": "वापस लें", + "removeUserFrom": "{{org}} से उपयोगकर्ता को हटाएं", + "removeConfirmation": "क्या आप वाकई '{{name}}' को संगठन '{{org}}' से हटाना चाहते हैं?", + "searchByName": "नाम से खोजें", + "users": "उपयोगकर्ता", + "name": "नाम", + "email": "ईमेल", + "endOfResults": "परिणाम समाप्त", + "admin": "प्रशासक", + "superAdmin": "सुपर प्रशासक", + "user": "उपयोगकर्ता", + "filter": "फ़िल्टर", + "noResultsFoundFor": "कोई परिणाम नहीं मिला", + "talawaApiUnavailable": "तालावा एपीआई अनुपलब्ध", + "cancel": "रद्द करें", + "admins": "प्रशासक", + "members": "सदस्य", + "orgJoined": "संगठन में शामिल", + "MembershipRequestSent": "सदस्यता अनुरोध भेजा गया", + "AlreadyJoined": "पहले से शामिल", + "errorOccured": "त्रुटि हुई" }, "communityProfile": { - "title": "सामुदायिक प्रोफ़ाइल", + "title": "समुदाय प्रोफ़ाइल", "editProfile": "प्रोफ़ाइल संपादित करें", - "communityProfileInfo": "ये विवरण आपके और आपके समुदाय के सदस्यों के लिए लॉगिन/साइनअप स्क्रीन पर दिखाई देंगे", + "communityProfileInfo": "ये विवरण आपके और आपके समुदाय के सदस्यों के लॉगिन/पंजीकरण स्क्रीन पर दिखाई देंगे", "communityName": "समुदाय का नाम", - "wesiteLink": "वेबसाइट की लिंक", - "logo": "प्रतीक चिन्ह", + "wesiteLink": "वेबसाइट लिंक", + "logo": "लोगो", "social": "सोशल मीडिया लिंक", - "url": "यू आर एल दर्ज करो", - "profileChangedMsg": "प्रोफ़ाइल विवरण सफलतापूर्वक अपडेट किया गया.", - "resetData": "प्रोफ़ाइल विवरण सफलतापूर्वक रीसेट करें।" + "url": "यूआरएल दर्ज करें", + "profileChangedMsg": "प्रोफ़ाइल विवरण सफलतापूर्वक अपडेट किया गया।", + "resetData": "प्रोफ़ाइल विवरण सफलतापूर्वक रीसेट किया गया।" }, "dashboard": { "title": "डैशबोर्ड", "about": "के बारे में", - "deleteThisOrganization": "इस संगठन को हटाएँ", + "deleteThisOrganization": "इस संगठन को हटाएं", "statistics": "आंकड़े", - "posts": "पदों", - "events": "आयोजन", - "blockedUsers": "रोके गए उपयोगकर्ता", - "viewAll": "सभी को देखें", - "upcomingEvents": "आगामी कार्यक्रम", - "noUpcomingEvents": "कोई आगामी ईवेंट नहीं", + "posts": "पोस्ट", + "events": "घटनाएँ", + "blockedUsers": "अवरुद्ध उपयोगकर्ता", + "viewAll": "सभी देखें", + "upcomingEvents": "आगामी घटनाएँ", + "noUpcomingEvents": "कोई आगामी घटनाएँ नहीं हैं", "latestPosts": "नवीनतम पोस्ट", - "noPostsPresent": "कोई पोस्ट मौजूद नहीं", + "noPostsPresent": "कोई पोस्ट नहीं हैं", "membershipRequests": "सदस्यता अनुरोध", - "noMembershipRequests": "कोई सदस्यता अनुरोध मौजूद नहीं है" + "noMembershipRequests": "कोई सदस्यता अनुरोध नहीं हैं", + "location": "स्थान", + "members": "सदस्य", + "admins": "प्रशासक", + "requests": "अनुरोध", + "talawaApiUnavailable": "तालावा एपीआई अनुपलब्ध" }, "organizationPeople": { - "title": "तलवा सदस्य", + "title": "तालावा सदस्य", "filterByName": "नाम से फ़िल्टर करें", - "filterByLocation": "स्थान के अनुसार फ़िल्टर करें", - "filterByEvent": "इवेंट के अनुसार फ़िल्टर करें", + "filterByLocation": "स्थान से फ़िल्टर करें", + "filterByEvent": "घटना से फ़िल्टर करें", "searchName": "नाम दर्ज करें", - "searchevent": "इवेंट दर्ज करें", + "searchevent": "घटना दर्ज करें", "searchFullName": "पूरा नाम दर्ज करें", "people": "लोग", - "sort": "भूमिका के आधार पर खोजें", - "actions": "कार्रवाई", + "sort": "भूमिका से खोजें", + "actions": "क्रियाएँ", "addMembers": "सदस्य जोड़ें", "existingUser": "मौजूदा उपयोगकर्ता", - "newUser": "नए उपयोगकर्ता", + "newUser": "नया उपयोगकर्ता", "enterFirstName": "अपना पहला नाम दर्ज करें", "enterLastName": "अपना अंतिम नाम दर्ज करें", - "enterConfirmPassword": "पुष्टि करने के लिए अपना पासवर्ड दर्ज करें", + "enterConfirmPassword": "अपना पासवर्ड पुष्टि के लिए दर्ज करें", "organization": "संगठन", - "invalidDetailsMessage": "कृपया वैध विवरण दर्ज करें." + "invalidDetailsMessage": "कृपया मान्य विवरण दर्ज करें।", + "members": "सदस्य", + "admins": "प्रशासक", + "users": "उपयोगकर्ता", + "searchFirstName": "प्रथम नाम खोजें", + "searchLastName": "अंतिम नाम खोजें", + "firstName": "प्रथम नाम", + "lastName": "अंतिम नाम", + "emailAddress": "ईमेल पता", + "enterEmail": "ईमेल दर्ज करें", + "password": "पासवर्ड", + "enterPassword": "पासवर्ड दर्ज करें", + "confirmPassword": "पासवर्ड की पुष्टि करें", + "user": "उपयोगकर्ता", + "profile": "प्रोफ़ाइल", + "create": "बनाएं", + "cancel": "रद्द करें" + }, + "organizationTags": { + "title": "संस्थान टैग", + "createTag": "नया टैग बनाएँ", + "manageTag": "प्रबंधित करें", + "editTag": "संपादित करें", + "removeTag": "हटाएँ", + "tagDetails": "टैग विवरण", + "tagName": "नाम", + "tagType": "प्रकार", + "tagNamePlaceholder": "टैग का नाम लिखें", + "tagCreationSuccess": "नई टैग सफलतापूर्वक बनाई गई", + "tagUpdationSuccess": "टैग सफलतापूर्वक अपडेट की गई", + "tagRemovalSuccess": "टैग सफलतापूर्वक हटाई गई", + "noTagsFound": "कोई टैग नहीं मिला", + "removeUserTag": "टैग हटाएँ", + "removeUserTagMessage": "क्या आप इस टैग को हटाना चाहते हैं?", + "addChildTag": "उप-टैग जोड़ें" + }, + "manageTag": { + "title": "टैग विवरण", + "addPeopleToTag": "टैग में लोगों को जोड़ें", + "viewProfile": "देखें", + "noAssignedMembersFound": "कोई असाइन किए गए सदस्य नहीं मिले", + "unassignUserTag": "टैग को हटाएं", + "unassignUserTagMessage": "क्या आप इस उपयोगकर्ता से टैग हटाना चाहते हैं?", + "successfullyUnassigned": "उपयोगकर्ता से टैग हटा दिया गया", + "addPeople": "लोगों को जोड़ें", + "add": "जोड़ें", + "subTags": "उप-टैग्स" }, "userListCard": { "addAdmin": "व्यवस्थापक जोड़ें", - "addedAsAdmin": "उपयोगकर्ता को व्यवस्थापक के रूप में जोड़ा गया है." + "addedAsAdmin": "उपयोगकर्ता को व्यवस्थापक के रूप में जोड़ा गया है.", + "joined": "शामिल हुए", + "talawaApiUnavailable": "Talawa API अनुपलब्ध" }, "orgAdminListCard": { "remove": "निकालना", "removeAdmin": "व्यवस्थापक हटाएँ", "removeAdminMsg": "क्या आप इस व्यवस्थापक को हटाना चाहते हैं?", - "adminRemoved": "व्यवस्थापक को हटा दिया गया है." + "adminRemoved": "व्यवस्थापक को हटा दिया गया है.", + "joined": "शामिल हुए", + "no": "नहीं", + "yes": "हाँ", + "talawaApiUnavailable": "Talawa API अनुपलब्ध" }, "orgPeopleListCard": { "remove": "निकालना", "removeMember": "सदस्य हटाएँ", "removeMemberMsg": "क्या आप इस सदस्य को हटाना चाहते हैं?", - "memberRemoved": "सदस्य को हटा दिया गया है" + "memberRemoved": "सदस्य को हटा दिया गया है", + "joined": "शामिल हुए", + "no": "नहीं", + "yes": "हाँ", + "talawaApiUnavailable": "Talawa API अनुपलब्ध" }, "organizationEvents": { "title": "आयोजन", @@ -245,7 +389,14 @@ "never": "कभी नहीं", "on": "पर", "after": "बाद", - "occurences": "घटनाओं" + "occurences": "घटनाओं", + "events": "कार्यक्रम", + "description": "विवरण", + "location": "स्थान", + "startDate": "प्रारंभ तिथि", + "endDate": "समाप्ति तिथि", + "talawaApiUnavailable": "Talawa API अनुपलब्ध", + "done": "पूर्ण" }, "organizationActionItems": { "actionItemCategory": "कार्य आइटम श्रेणी", @@ -256,7 +407,6 @@ "assignmentDate": "असाइनमेंट दिनांक", "active": "सक्रिय", "clearFilters": "फ़िल्टर साफ़ करें", - "completed": "पुरा होना।", "completionDate": "पूरा करने की तिथि", "createActionItem": "कार्रवाई आइटम बनाएं", "deleteActionItem": "क्रिया आइटम हटाएँ", @@ -281,7 +431,18 @@ "successfulCreation": "कार्रवाई आइटम सफलतापूर्वक बनाया गया", "successfulUpdation": "कार्रवाई आइटम सफलतापूर्वक अपडेट किया गया", "successfulDeletion": "कार्रवाई आइटम सफलतापूर्वक हटा दिया गया", - "title": "एक्शन आइटम्स" + "title": "एक्शन आइटम्स", + "category": "श्रेणी", + "allotedHours": "आवंटित घंटे", + "latestDueDate": "सबसे अधिक नियत तिथि", + "earliestDueDate": "सबसे पहले की नियत तिथि", + "updateActionItem": "कार्य आइटम अपडेट करें", + "noneUpdated": "कोई फ़ील्ड अपडेट नहीं किया गया", + "updateStatusMsg": "क्या आप वाकई इस कार्य आइटम को लंबित के रूप में चिह्नित करना चाहते हैं?", + "close": "बंद करें", + "eventActionItems": "कार्यक्रम कार्रवाई आइटम", + "no": "नहीं", + "yes": "हाँ" }, "organizationAgendaCategory": { "agendaCategoryDetails": "एजेंडा श्रेणी विवरण", @@ -360,7 +521,17 @@ "never": "कभी नहीं", "on": "पर", "after": "बाद", - "occurences": "घटनाओं" + "occurences": "घटनाओं", + "location": "स्थान", + "no": "नहीं", + "yes": "हाँ", + "description": "विवरण", + "startDate": "प्रारंभ तिथि", + "endDate": "समाप्ति तिथि", + "registerEvent": "कार्यक्रम के लिए पंजीकरण करें", + "close": "बंद करें", + "talawaApiUnavailable": "Talawa API अनुपलब्ध", + "done": "समाप्त" }, "funds": { "title": "फंड", @@ -436,7 +607,9 @@ "pledges": "प्रतिज्ञाएँ", "endsOn": "पर समाप्त होता है", "raisedAmount": "उठाया गया राशि", - "pledgedAmount": "प्रतिबद्ध राशि" + "pledgedAmount": "प्रतिबद्ध राशि", + "startDate": "प्रारंभ तिथि", + "endDate": "समाप्ति तिथि" }, "orgPost": { "title": "पदों", @@ -464,7 +637,8 @@ "postCreatedSuccess": "बधाई हो! ", "pinPost": "पिन पद", "Next": "अगला पृष्ठ", - "Previous": "पिछला पृष्ठ" + "Previous": "पिछला पृष्ठ", + "cancel": "रद्द करें" }, "postNotFound": { "post": "डाक", @@ -479,7 +653,8 @@ "user not found!": "उपयोगकर्ता नहीं मिला!", "member not found!": "सदस्य अनुपस्थित!", "admin not found!": "व्यवस्थापक नहीं मिला!", - "roles not found!": "भूमिकाएँ नहीं मिलीं!" + "roles not found!": "भूमिकाएँ नहीं मिलीं!", + "user": "उपयोगकर्ता" }, "orgPostCard": { "author": "लेखक", @@ -498,7 +673,12 @@ "postDeleted": "पोस्ट सफलतापूर्वक हटा दी गई.", "postUpdated": "पोस्ट सफलतापूर्वक अपडेट किया गया.", "tag": " आपका ब्राउज़र में वीडियो टैग समर्थित नहीं है", - "pin": "पिन पद" + "pin": "पिन पद", + "edit": "संपादित करें", + "no": "नहीं", + "yes": "हाँ", + "close": "बंद करें", + "talawaApiUnavailable": "Talawa API अनुपलब्ध" }, "blockUnblockUser": { "title": "उपयोगकर्ता को ब्लॉक/अनब्लॉक करें", @@ -514,7 +694,12 @@ "blockedUsers": "रोके गए उपयोगकर्ता", "searchByFirstName": "प्रथम नाम से खोजें", "searchByLastName": "अंतिम नाम से खोजें", - "noSpammerFound": "कोई स्पैमर नहीं मिला" + "noSpammerFound": "कोई स्पैमर नहीं मिला", + "searchByName": "नाम से खोजें", + "name": "नाम", + "email": "ईमेल", + "talawaApiUnavailable": "Talawa API अनुपलब्ध", + "noResultsFoundFor": "के लिए कोई परिणाम नहीं मिला" }, "eventManagement": { "title": "इवेंट मैनेजमेंट", @@ -539,7 +724,10 @@ "errorSendingMail": "मेल भेजने में त्रुटि.", "passwordMismatches": "पासवर्ड और पासवर्ड बेमेल होने की पुष्टि करें।", "passwordChanges": "पासवर्ड सफलतापूर्वक बदल गया.", - "OTPsent": "ओटीपी आपके पंजीकृत ईमेल पर भेजा जाता है।" + "OTPsent": "ओटीपी आपके पंजीकृत ईमेल पर भेजा जाता है।", + "forgotPassword": "पासवर्ड भूल गए", + "password": "पासवर्ड", + "talawaApiUnavailable": "Talawa API अनुपलब्ध" }, "pageNotFound": { "404": "404", @@ -569,15 +757,16 @@ "amount": "मात्रा" }, "orgSettings": { - "title": "समायोजन", + "title": "सेटिंग्स", "general": "सामान्य", - "actionItemCategories": "कार्रवाई आइटम श्रेणियाँ", - "updateOrganization": "संगठन अद्यतन करें", + "actionItemCategories": "कार्य आइटम श्रेणियाँ", + "updateOrganization": "संगठन अपडेट करें", "seeRequest": "अनुरोध देखें", "noData": "कोई डेटा नहीं", - "otherSettings": "अन्य सेटिंग", + "otherSettings": "अन्य सेटिंग्स", "changeLanguage": "भाषा बदलें", - "manageCustomFields": "कस्टम फ़ील्ड प्रबंधित करें" + "manageCustomFields": "कस्टम फ़ील्ड प्रबंधित करें", + "agendaItemCategories": "एजेंडा आइटम श्रेणियाँ" }, "deleteOrg": { "deleteOrganization": "संगठन हटाएँ", @@ -585,18 +774,30 @@ "deleteMsg": "क्या आप इस संगठन को हटाना चाहते हैं?", "confirmDelete": "हटाने की पुष्टि करें", "longDelOrgMsg": "संगठन हटाएं बटन पर क्लिक करने से संगठन अपने ईवेंट, टैग और सभी संबंधित डेटा के साथ स्थायी रूप से हटा दिया जाएगा।", - "successfullyDeletedSampleOrganization": "नमूना संगठन सफलतापूर्वक हटा दिया गया" + "successfullyDeletedSampleOrganization": "नमूना संगठन सफलतापूर्वक हटा दिया गया", + "cancel": "रद्द करें" }, "userUpdate": { "appLanguageCode": "डिफ़ॉल्ट भाषा", - "userType": "उपयोगकर्ता का प्रकार" + "userType": "उपयोगकर्ता का प्रकार", + "firstName": "प्रथम नाम", + "lastName": "अंतिम नाम", + "email": "ईमेल", + "password": "पासवर्ड", + "admin": "प्रशासक", + "superAdmin": "सुपर प्रशासक", + "displayImage": "प्रदर्शन छवि", + "saveChanges": "परिवर्तन सहेजें", + "cancel": "रद्द करें" }, "userPasswordUpdate": { "previousPassword": "पिछला पासवर्ड", "newPassword": "नया पासवर्ड", "confirmNewPassword": "नए पासवर्ड की पुष्टि करें", "passCantBeEmpty": "पासवर्ड खाली नहीं हो सकता", - "passNoMatch": "नया पासवर्ड और पुष्टि पासवर्ड मेल नहीं खाते।" + "passNoMatch": "नया पासवर्ड और पुष्टि पासवर्ड मेल नहीं खाते।", + "saveChanges": "परिवर्तन सहेजें", + "cancel": "रद्द करें" }, "orgDelete": { "deleteOrg": "संगठन हटाएं" @@ -604,7 +805,9 @@ "membershipRequest": { "accept": "स्वीकार करना", "reject": "अस्वीकार करना", - "memberAdded": "यह स्वीकृत है" + "memberAdded": "यह स्वीकृत है", + "joined": "शामिल हुए", + "talawaApiUnavailable": "Talawa API अनुपलब्ध" }, "orgUpdate": { "city": "शहर", @@ -618,7 +821,15 @@ "userRegistrationRequired": "उपयोगकर्ता पंजीकरण आवश्यक", "isVisibleInSearch": "खोज में दृश्यमान", "enterNameOrganization": "संगठन का नाम दर्ज करें", - "successfulUpdated": "संगठन सफलतापूर्वक अद्यतन किया गया" + "successfulUpdated": "संगठन सफलतापूर्वक अद्यतन किया गया", + "name": "नाम", + "description": "विवरण", + "location": "स्थान", + "address": "पता", + "displayImage": "प्रदर्शन छवि", + "saveChanges": "परिवर्तन सहेजें", + "cancel": "रद्द करें", + "talawaApiUnavailable": "Talawa API अनुपलब्ध" }, "addOnRegister": { "addNew": "नया जोड़ो", @@ -628,7 +839,9 @@ "pluginDesc": "प्लगइन विवरण", "pName": "उदाहरणार्थ: दान", "cName": "उदाहरण: जॉन डो", - "pDesc": "यह प्लगइन यूआई को सक्षम बनाता है" + "pDesc": "यह प्लगइन यूआई को सक्षम बनाता है", + "close": "बंद करें", + "register": "पंजीकरण करें" }, "addOnStore": { "title": "स्टोर पर जोड़ें", @@ -639,7 +852,8 @@ "pHeading": "प्लग-इन", "install": "स्थापित", "available": "उपलब्ध", - "pMessage": "प्लगइन मौजूद नहीं है" + "pMessage": "प्लगइन मौजूद नहीं है", + "filter": "फ़िल्टर" }, "addOnEntry": { "enable": "सक्रिय", @@ -681,14 +895,32 @@ "membershipRequests": "सदस्यता अनुरोध", "adminForEvents": "घटनाओं के लिए व्यवस्थापक", "addedAsAdmin": "उपयोगकर्ता को व्यवस्थापक के रूप में जोड़ा गया है.", - "userType": "उपयोगकर्ता का प्रकार" + "userType": "उपयोगकर्ता का प्रकार", + "email": "ईमेल", + "displayImage": "प्रदर्शन छवि", + "address": "पता", + "delete": "हटाएं", + "saveChanges": "परिवर्तन सहेजें", + "joined": "शामिल हुए", + "talawaApiUnavailable": "Talawa API अनुपलब्ध" + }, + "people": { + "title": "लोग", + "searchUsers": "उपयोगकर्ताओं को खोजें" }, "userLogin": { "login": "लॉग इन करें", "loginIntoYourAccount": "अपने खाते में लॉगिन करें", "invalidDetailsMessage": "कृपया एक वैध ईमेल और पासवर्ड दर्ज करें।", "notAuthorised": "क्षमा मांगना! ", - "invalidCredentials": "दर्ज किए गए क्रेडेंशियल ग़लत हैं. " + "invalidCredentials": "दर्ज किए गए क्रेडेंशियल ग़लत हैं. ", + "forgotPassword": "पासवर्ड भूल गए", + "emailAddress": "ईमेल पता", + "enterEmail": "ईमेल दर्ज करें", + "password": "पासवर्ड", + "enterPassword": "पासवर्ड दर्ज करें", + "register": "पंजीकरण करें", + "talawaApiUnavailable": "Talawa API अनुपलब्ध" }, "userRegister": { "enterFirstName": "अपना पहला नाम दर्ज करें", @@ -698,7 +930,16 @@ "login": "लॉग इन करें", "afterRegister": "पंजीकरण सफलतापूर्वक हो गया है। ", "passwordNotMatch": "पासवर्ड मेल नहीं खाता. ", - "invalidDetailsMessage": "कृपया वैध विवरण दर्ज करें." + "invalidDetailsMessage": "कृपया वैध विवरण दर्ज करें.", + "register": "पंजीकरण करें", + "firstName": "प्रथम नाम", + "lastName": "अंतिम नाम", + "emailAddress": "ईमेल पता", + "enterEmail": "ईमेल दर्ज करें", + "password": "पासवर्ड", + "enterPassword": "पासवर्ड दर्ज करें", + "confirmPassword": "पासवर्ड की पुष्टि करें", + "talawaApiUnavailable": "Talawa API अनुपलब्ध" }, "userNavbar": { "talawa": "तलावा", @@ -707,7 +948,10 @@ "events": "आयोजन", "chat": "बात करना", "donate": "दान करें", - "language": "भाषा" + "language": "भाषा", + "settings": "समायोजन", + "logout": "लॉग आउट करें", + "close": "बंद करें" }, "userOrganizations": { "allOrganizations": "सभी संगठन", @@ -716,7 +960,11 @@ "selectOrganization": "एक संगठन चुनें", "searchUsers": "उपयोगकर्ता खोजें", "nothingToShow": "यहां दिखाने के लिए कुछ भी नहीं है.", - "organizations": "संगठनों" + "organizations": "संगठनों", + "search": "खोजें", + "filter": "फ़िल्टर", + "searchByName": "नाम से खोजें", + "searchOrganizations": "संगठनों खोजें" }, "userSidebarOrg": { "yourOrganizations": "आपके संगठन", @@ -724,13 +972,20 @@ "viewAll": "सभी को देखें", "talawaUserPortal": "तलावा उपयोगकर्ता पोर्टल", "my organizations": "मेरे संगठन", - "communityProfile": "सामुदायिक प्रोफ़ाइल" + "communityProfile": "सामुदायिक प्रोफ़ाइल", + "users": "उपयोगकर्ता", + "requests": "अनुरोध", + "logout": "लॉग आउट", + "settings": "सेटिंग्स", + "chat": "चैट", + "menu": "मेनू" }, "organizationSidebar": { "viewAll": "सभी को देखें", "events": "आयोजन", "noEvents": "दिखाने के लिए कोई ईवेंट नहीं", - "noMembers": "दिखाने के लिए कोई सदस्य नहीं" + "noMembers": "दिखाने के लिए कोई सदस्य नहीं", + "members": "सदस्य" }, "postCard": { "likes": "पसंद है", @@ -740,9 +995,9 @@ "postedOn": "{{date}} को पोस्ट किया गया" }, "home": { + "title": "पदों", "posts": "पदों", "post": "डाक", - "title": "शीर्षक", "textArea": "आपके मन में कुछ है?", "feed": "खिलाना", "loading": "लोड हो रहा है", @@ -809,9 +1064,18 @@ "fullTime": "पूरा समय", "partTime": "पार्ट टाईम", "selectCountry": "कोई देश चुनें", - "enterState": "शहर या राज्य दर्ज करें" + "enterState": "शहर या राज्य दर्ज करें", + "settings": "समायोजन", + "firstName": "प्रथम नाम", + "lastName": "अंतिम नाम", + "emailAddress": "ईमेल पता", + "displayImage": "प्रदर्शन छवि", + "address": "पता", + "saveChanges": "परिवर्तन सहेजें", + "joined": "शामिल हुए" }, "donate": { + "title": "दान", "donations": "दान", "searchDonations": "दान खोजें", "donateForThe": "के लिए दान करें", @@ -819,9 +1083,14 @@ "yourPreviousDonations": "आपका पिछला दान", "donate": "दान करें", "nothingToShow": "यहां दिखाने के लिए कुछ भी नहीं है.", - "success": "दान सफल" + "success": "दान सफल", + "invalidAmount": "कृपया दान राशि के लिए संख्यात्मक मान दर्ज करें.", + "donationAmountDescription": "कृपया दान राशि के लिए संख्यात्मक मान दर्ज करें.", + "donationOutOfRange": "दान राशि {{min}} और {{max}} के बीच होनी चाहिए.", + "donateTo": "दान करें" }, "userEvents": { + "title": "ईवेंट", "nothingToShow": "यहां दिखाने के लिए कुछ भी नहीं है.", "createEvent": "कार्यक्रम बनाएँ", "recurring": "पुनरावर्ती ईवेंट", @@ -839,13 +1108,22 @@ "publicEvent": "सार्वजनिक है", "registerable": "पंजीकरण योग्य है", "monthlyCalendarView": "मासिक कैलेंडर", - "yearlyCalendarView": "वार्षिक कैलेंडर" + "yearlyCalendarView": "वार्षिक कैलेंडर", + "search": "खोजें", + "cancel": "रद्द करें", + "create": "बनाएं", + "eventDescription": "कार्यक्रम विवरण", + "eventLocation": "कार्यक्रम स्थान", + "startDate": "प्रारंभ तिथि", + "endDate": "समाप्ति तिथि" }, "userEventCard": { "starts": "प्रारंभ होगा", "ends": "समाप्त होता है", "creator": "निर्माता", - "alreadyRegistered": "पहले से ही पंजीकृत" + "alreadyRegistered": "पहले से ही पंजीकृत", + "location": "स्थान", + "register": "पंजीकरण करें" }, "advertisement": { "title": "विज्ञापनों", @@ -870,11 +1148,21 @@ "editAdvertisement": "विज्ञापन संपादित करें", "advertisementDeleted": "विज्ञापन सफलतापूर्वक हटाया गया।", "endDateGreaterOrEqual": "समाप्ति तिथि प्रारंभ तिथि से अधिक या उसके बराबर होनी चाहिए", - "advertisementCreated": "विज्ञापन सफलतापूर्वक बनाया गया।" + "advertisementCreated": "विज्ञापन सफलतापूर्वक बनाया गया।", + "pHeading": "विज्ञापन शीर्षक", + "delete": "हटाएं", + "close": "बंद करें", + "no": "नहीं", + "yes": "हाँ", + "edit": "संपादित करें", + "saveChanges": "परिवर्तन सहेजें", + "endOfResults": "परिणाम समाप्त" }, "userChat": { "chat": "बात करना", - "contacts": "संपर्क" + "contacts": "संपर्क", + "search": "खोज", + "messages": "संदेश" }, "userChatRoom": { "selectContact": "बातचीत शुरू करने के लिए एक संपर्क चुनें", @@ -892,20 +1180,28 @@ "String": "स्ट्रिंग", "Boolean": "बूलियन", "Date": "तारीख", - "Number": "संख्या" + "Number": "संख्या", + "saveChanges": "परिवर्तन सहेजें" }, "orgActionItemCategories": { "enableButton": "सक्षम", "disableButton": "अक्षम करना", "updateActionItemCategory": "अद्यतन", "actionItemCategoryName": "नाम", - "actionItemCategoryDetails": "कार्य आइटम श्रेणी विवरण", + "categoryDetails": "श्रेणी विवरण", "enterName": "नाम दर्ज करें", "successfulCreation": "कार्रवाई आइटम श्रेणी सफलतापूर्वक बनाई गई", "successfulUpdation": "कार्रवाई आइटम श्रेणी सफलतापूर्वक अपडेट की गई", "sameNameConflict": "अपडेट करने के लिए कृपया नाम बदलें", "categoryEnabled": "कार्य आइटम श्रेणी सक्षम", - "categoryDisabled": "कार्रवाई आइटम श्रेणी अक्षम" + "categoryDisabled": "कार्रवाई आइटम श्रेणी अक्षम", + "noActionItemCategories": "कोई कार्रवाई आइटम श्रेणी नहीं", + "status": "स्थिति", + "categoryDeleted": "कार्रवाई आइटम श्रेणी सफलतापूर्वक हटा दी गई", + "deleteCategory": "श्रेणी हटाएं", + "deleteCategoryMsg": "क्या आप वाकई इस कार्रवाई आइटम श्रेणी को हटाना चाहते हैं?", + "createButton": "बटन बनाएं", + "editButton": "संपादित बटन" }, "organizationVenues": { "title": "स्थानों", @@ -929,7 +1225,12 @@ "view": "देखना", "venueTitleError": "स्थान का शीर्षक खाली नहीं हो सकता!", "venueCapacityError": "क्षमता एक धनात्मक संख्या होनी चाहिए!", - "searchBy": "खोज से" + "searchBy": "खोज से", + "description": "विवरण", + "edit": "संपादित करें", + "delete": "हटाएं", + "name": "नाम", + "desc": "विवरण" }, "addMember": { "title": "सदस्य जोड़ें", @@ -943,7 +1244,18 @@ "organization": "संगठन", "invalidDetailsMessage": "कृपया सभी आवश्यक विवरण प्रदान करें।", "passwordNotMatch": "सांकेतिक शब्द मेल नहीं खाते।", - "addMember": "सदस्य जोड़ें" + "addMember": "सदस्य जोड़ें", + "firstName": "प्रथम नाम", + "lastName": "अंतिम नाम", + "emailAddress": "ईमेल पता", + "enterEmail": "ईमेल दर्ज करें", + "password": "पासवर्ड", + "enterPassword": "पासवर्ड दर्ज करें", + "confirmPassword": "पासवर्ड की पुष्टि करें", + "cancel": "रद्द करें", + "create": "बनाएं", + "user": "उपयोगकर्ता", + "profile": "प्रोफ़ाइल" }, "eventActionItems": { "title": "एक्शन आइटम्स", @@ -971,7 +1283,9 @@ "actionItemStatus": "कार्रवाई आइटम स्थिति", "actionItemCompleted": "कार्रवाई आइटम पूर्ण हुआ", "markCompletion": "पूर्णता को चिह्नित करें", - "save": "बचाना" + "save": "बचाना", + "yes": "हाँ", + "no": "नहीं" }, "checkIn": { "errorCheckingIn": "चेक-इन में त्रुटि", @@ -980,5 +1294,26 @@ "eventRegistrantsModal": { "errorAddingAttendee": "उपस्थित होने वाले को जोड़ने में त्रुटि", "errorRemovingAttendee": "उपस्थित होने वाले को हटाने में त्रुटि" + }, + "userCampaigns": { + "title": "धन उगाहने के अभियान", + "searchByName": "नाम से खोजें...", + "searchBy": "द्वारा खोजें", + "pledgers": "प्रतिज्ञाकर्ता", + "campaigns": "अभियान", + "myPledges": "मेरी प्रतिज्ञाएँ", + "lowestAmount": "सबसे कम राशि", + "highestAmount": "सबसे अधिक राशि", + "lowestGoal": "सबसे कम लक्ष्य", + "highestGoal": "सबसे बड़ा लक्ष्य", + "latestEndDate": "सबसे अंतिम समाप्ति तिथि", + "earliestEndDate": "सबसे पहले समाप्ति तिथि", + "addPledge": "प्रतिज्ञा जोड़ें", + "viewPledges": "प्रतिज्ञाएँ देखें", + "noPledges": "कोई प्रतिज्ञा नहीं मिली", + "noCampaigns": "कोई अभियान नहीं मिला" + }, + "userPledges": { + "title": "मेरी प्रतिज्ञाएँ" } } diff --git a/public/locales/sp/common.json b/public/locales/sp/common.json index d784652da5..7e5871c914 100644 --- a/public/locales/sp/common.json +++ b/public/locales/sp/common.json @@ -82,5 +82,14 @@ "addedSuccessfully": "{{item}} agregado con éxito", "updatedSuccessfully": "{{item}} actualizado con éxito", "removedSuccessfully": "{{item}} eliminado con éxito", - "successfullyUpdated": "Actualizado con éxito" + "successfullyUpdated": "Actualizado con éxito", + "all": "Todos", + "active": "Activo", + "disabled": "Deshabilitado", + "pending": "Pendiente", + "completed": "Completado", + "late": "Tarde", + "createdLatest": "Creado más reciente", + "createdEarliest": "Creado más temprano", + "searchBy": "Buscar por {{item}}" } diff --git a/public/locales/sp/errors.json b/public/locales/sp/errors.json index 7d5440637f..39b579abac 100644 --- a/public/locales/sp/errors.json +++ b/public/locales/sp/errors.json @@ -6,5 +6,6 @@ "errorSendingMail": "Error sending mail", "emailNotRegistered": "Email not registered", "notFoundMsg": "Oops! The Page you requested was not found!", - "errorOccurredCouldntCreate": "Ocurrió un error. No se pudo crear {{entity}}" + "errorOccurredCouldntCreate": "Ocurrió un error. No se pudo crear {{entity}}", + "errorLoading": "Ocurrió un error al cargar los datos de {{entity}}" } diff --git a/public/locales/sp/translation.json b/public/locales/sp/translation.json index 2d5f46db2b..bab46846a7 100644 --- a/public/locales/sp/translation.json +++ b/public/locales/sp/translation.json @@ -121,7 +121,8 @@ "spamsThe": "envía correo no deseado", "group": "grupo", "noNotifications": "No Notificaciones", - "close": "Cerca" + "close": "Cerca", + "Advertisement": "Publicidad" }, "orgList": { "title": "Organizaciones Talawa", @@ -159,7 +160,11 @@ "noOrgErrorDescription": "Por favor, crea una organización a través del panel de control", "noResultsFoundFor": "No se encontraron resultados para ", "OR": "O", - "sampleOrgSuccess": "Organización de ejemplo creada exitosamente" + "sampleOrgSuccess": "Organización de ejemplo creada exitosamente", + "manageFeatures": "Gestionar funciones", + "manageFeaturesInfo": "Información de gestión de funciones", + "goToStore": "Ir a la tienda", + "enableEverything": "Habilitar todo" }, "orgListCard": { "admins": "Administradores", @@ -227,7 +232,8 @@ "AlreadyJoined": "Ya eres miembro de esta organización.", "errorOccured": "Se produjo un error. Por favor, inténtalo de nuevo más tarde.", "removeUserFrom": "Eliminar Usuario de {{org}}", - "removeConfirmation": "¿Está seguro de que desea eliminar a '{{name}}' de la organización '{{org}}'?" + "removeConfirmation": "¿Está seguro de que desea eliminar a '{{name}}' de la organización '{{org}}'?", + "noOrgError": "Error sin organización" }, "communityProfile": { "title": "Perfil de la comunidad", @@ -292,7 +298,41 @@ "organization": "Organización", "create": "Crear", "cancel": "Cancelar", - "invalidDetailsMessage": "Ingrese detalles válidos." + "invalidDetailsMessage": "Ingrese detalles válidos.", + "addMembers": "Agregar miembros", + "searchFullName": "Ingrese el nombre completo", + "user": "Usuario", + "profile": "Perfil" + }, + "organizationTags": { + "title": "Etiquetas de Organización", + "createTag": "Crear una nueva etiqueta", + "manageTag": "Gestionar", + "editTag": "Editar", + "removeTag": "Eliminar", + "tagDetails": "Detalles de la Etiqueta", + "tagName": "Nombre", + "tagType": "Tipo", + "tagNamePlaceholder": "Escribe el nombre de la etiqueta", + "tagCreationSuccess": "Nueva etiqueta creada con éxito", + "tagUpdationSuccess": "Etiqueta actualizada con éxito", + "tagRemovalSuccess": "Etiqueta eliminada con éxito", + "noTagsFound": "No se encontraron etiquetas", + "removeUserTag": "Eliminar Etiqueta", + "removeUserTagMessage": "¿Desea eliminar esta etiqueta?", + "addChildTag": "Agregar una Sub Etiqueta" + }, + "manageTag": { + "title": "Detalles de la Etiqueta", + "addPeopleToTag": "Agregar Personas a la etiqueta", + "viewProfile": "Ver", + "noAssignedMembersFound": "Ningún miembro asignado", + "unassignUserTag": "Desasignar Etiqueta", + "unassignUserTagMessage": "¿Desea eliminar la etiqueta de este usuario?", + "successfullyUnassigned": "Etiqueta desasignada del usuario", + "addPeople": "Agregar Personas", + "add": "Agregar", + "subTags": "Subetiquetas" }, "userListCard": { "joined": "Unido", @@ -370,7 +410,6 @@ "active": "Activo", "clearFilters": "Borrar filtros", "close": "Cerrar", - "completed": "Completado", "completionDate": "Fecha de finalización", "createActionItem": "Crear ítem de acción", "deleteActionItem": "Eliminar ítem de acción", @@ -396,7 +435,14 @@ "successfulUpdation": "Ítem de acción actualizado con éxito", "successfulDeletion": "Ítem de acción eliminado con éxito", "title": "Ítems de acción", - "yes": "Sí" + "yes": "Sí", + "category": "Categoría", + "allotedHours": "Horas asignadas", + "latestDueDate": "Fecha de vencimiento más reciente", + "earliestDueDate": "Fecha de vencimiento más antigua", + "updateActionItem": "Actualizar elemento de acción", + "noneUpdated": "Ninguno de los campos se actualizó", + "updateStatusMsg": "¿Está seguro de que desea marcar este elemento de acción como pendiente?" }, "organizationAgendaCategory": { "agendaCategoryDetails": "Detalles de la categoría de la agenda", @@ -632,7 +678,8 @@ "postDeleted": "Publicación eliminada exitosamente.", "postUpdated": "Publicación actualizada exitosamente.", "tag": "Su navegador no admite la etiqueta de video", - "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está en funcionamiento? Compruebe también su conectividad de red." + "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está en funcionamiento? Compruebe también su conectividad de red.", + "pin": "Fijar" }, "blockUnblockUser": { "title": "Usuario de bloqueo/desbloqueo de Talawa", @@ -711,19 +758,16 @@ "amount": "Monto" }, "orgSettings": { - "title": "Configuración Talawa", - "pageName": "Configuración", + "title": "Configuración", "general": "General", "actionItemCategories": "Categorías de elementos de acción", - "updateYourDetails": "Actualiza tus datos", - "updateYourPassword": "Actualice su contraseña", - "updateOrganization": "Actualizar Organización", - "seeRequest": "Ver Solicitud", - "settings": "Ajustes", + "updateOrganization": "Actualizar organización", + "seeRequest": "Ver solicitud", "noData": "Sin datos", - "otherSettings": "Otras Configuraciones", - "changeLanguage": "Cambiar Idioma", - "manageCustomFields": "Gestionar Campos Personalizados" + "otherSettings": "Otras configuraciones", + "changeLanguage": "Cambiar idioma", + "manageCustomFields": "Administrar campos personalizados", + "agendaItemCategories": "Categorías de elementos de agenda" }, "deleteOrg": { "deleteOrganization": "Eliminar organización", @@ -815,7 +859,9 @@ "addOnEntry": { "enable": "Activada", "install": "Instalar", - "uninstall": "Desinstalar" + "uninstall": "Desinstalar", + "uninstallMsg": "Mensaje de desinstalación", + "installMsg": "Mensaje de instalación" }, "memberDetail": { "title": "Detalles del usuario", @@ -855,7 +901,9 @@ "membershipRequests": "Solicitudes de membresía", "adminForEvents": "Administrador de eventos", "addedAsAdmin": "El usuario se agrega como administrador.", - "talawaApiUnavailable": "El servicio Talawa-API no está disponible. Compruebe amablemente su conexión de red y espere un momento." + "talawaApiUnavailable": "El servicio Talawa-API no está disponible. Compruebe amablemente su conexión de red y espere un momento.", + "deleteUser": "Eliminar usuario", + "userType": "Tipo de usuario" }, "userLogin": { "login": "Acceso", @@ -871,6 +919,10 @@ "invalidCredentials": "Las credenciales ingresadas son incorrectas. Ingrese credenciales válidas.", "talawaApiUnavailable": "El servicio Talawa-API no está disponible. Compruebe amablemente su conexión de red y espere un momento." }, + "people": { + "title": "Gente", + "searchUsers": "Buscar usuarios" + }, "userRegister": { "register": "Registro", "firstName": "Nombre de pila", @@ -911,7 +963,9 @@ "selectOrganization": "Seleccionar organización", "filter": "Filtrar", "organizations": "Organizaciones", - "searchByName": "Buscar por nombre" + "searchByName": "Buscar por nombre", + "searchUsers": "Buscar usuarios", + "searchOrganizations": "Buscar Organizaciones" }, "userSidebarOrg": { "yourOrganizations": "Tus Organizaciones", @@ -924,7 +978,8 @@ "requests": "Solicitudes", "communityProfile": "Perfil de la comunidad", "logout": "Cerrar sesión", - "settings": "Ajustes" + "settings": "Ajustes", + "chat": "Chat" }, "organizationSidebar": { "viewAll": "Ver todo", @@ -941,15 +996,22 @@ "postedOn": "Publicado el {{date}}" }, "home": { - "feed": "Alimentar", - "pinnedPosts": "Ver publicaciones fijadas", - "somethingOnYourMind": "¿Algo en tu mente?", - "addPost": "Agregar publicación", + "posts": "Publicaciones", + "post": "Publicación", + "title": "Publicaciones", + "textArea": "¿Tienes algo en mente?", + "feed": "Feed", + "loading": "Cargando", + "pinnedPosts": "Publicaciones fijadas", + "yourFeed": "Tu feed", + "nothingToShowHere": "No hay nada que mostrar aquí", + "somethingOnYourMind": "¿Tienes algo en mente?", + "addPost": "Añadir publicación", "startPost": "Comenzar una publicación", "media": "Medios", "event": "Evento", "article": "Artículo", - "postNowVisibleInFeed": "La publicación ahora es visible en el feed" + "postNowVisibleInFeed": "Publicar ahora visible en el feed" }, "settings": { "settings": "Ajustes", @@ -1014,6 +1076,7 @@ "joined": "Unido" }, "donate": { + "title": "Donaciones", "donations": "Donaciones", "searchDonations": "Buscar donaciones", "donateForThe": "Donar para el", @@ -1022,9 +1085,13 @@ "yourPreviousDonations": "Tus donaciones anteriores", "donate": "Donar", "nothingToShow": "Nada que mostrar aquí.", - "success": "Donación exitosa" + "success": "Donación exitosa", + "invalidAmount": "Ingrese un valor numérico para el monto de la donación.", + "donationAmountDescription": "Ingrese el valor numérico del monto de la donación.", + "donationOutOfRange": "El monto de la donación debe estar entre {{min}} y {{max}}." }, "userEvents": { + "title": "Eventos", "nothingToShow": "No hay nada que mostrar aquí.", "search": "Buscar", "createEvent": "Crear evento", @@ -1081,12 +1148,22 @@ "endDateGreaterOrEqual": "La fecha de finalización debe ser mayor o igual a la fecha de inicio", "advertisementCreated": "Anuncio creado con éxito.", "saveChanges": "Guardar Cambios", - "endOfResults": "Fin de los resultados" + "endOfResults": "Fin de los resultados", + "Rname": "Nombre", + "Rtype": "Tipo", + "RstartDate": "Fecha de inicio", + "RendDate": "Fecha de finalización", + "RClose": "Cerrar", + "addNew": "Agregar nuevo", + "EXname": "Nombre", + "EXlink": "Enlace", + "createAdvertisement": "Crear publicidad" }, "userChat": { "chat": "Charlar", "search": "Buscar", - "contacts": "Contactos" + "contacts": "Contactos", + "messages": "Mensajes" }, "userChatRoom": { "selectContact": "Seleccione un contacto para iniciar una conversación", @@ -1114,13 +1191,18 @@ "disableButton": "Inhabilitar", "updateActionItemCategory": "Actualizar", "actionItemCategoryName": "Nombre", - "actionItemCategoryDetails": "Detalles de la categoría de elemento de acción", + "categoryDetails": "Detalles de la categoría", "enterName": "Introduzca el nombre", "successfulCreation": "Categoría de elemento de acción creada correctamente", "successfulUpdation": "Categoría de elemento de acción actualizada correctamente", "sameNameConflict": "Cambie el nombre para realizar una actualización", "categoryEnabled": "Categoría de elemento de acción habilitada", - "categoryDisabled": "Categoría de elemento de acción deshabilitada" + "categoryDisabled": "Categoría de elemento de acción deshabilitada", + "noActionItemCategories": "No hay categorías de elementos de acción", + "status": "Estado", + "categoryDeleted": "Categoría de elemento de acción eliminada con éxito", + "deleteCategory": "Eliminar categoría", + "deleteCategoryMsg": "¿Está seguro de que desea eliminar esta categoría de elemento de acción?" }, "organizationVenues": { "title": "Lugares", @@ -1173,6 +1255,7 @@ "invalidDetailsMessage": "Por favor proporcione todos los detalles requeridos.", "passwordNotMatch": "Las contraseñas no coinciden.", "user": "Usuario", + "profile": "Perfil", "addMember": "Agregar miembro" }, "eventActionItems": { @@ -1212,5 +1295,26 @@ "eventRegistrantsModal": { "errorAddingAttendee": "Error al agregar asistente", "errorRemovingAttendee": "Error al eliminar asistente" + }, + "userCampaigns": { + "title": "Campañas de recaudación de fondos", + "searchByName": "Buscar por nombre...", + "searchBy": "Buscar por", + "pledgers": "Contribuyentes", + "campaigns": "Campañas", + "myPledges": "Mis Promesas", + "lowestAmount": "Monto más bajo", + "highestAmount": "Monto más alto", + "lowestGoal": "Meta más baja", + "highestGoal": "Meta más alta", + "latestEndDate": "Fecha de finalización más tardía", + "earliestEndDate": "Fecha de finalización más temprana", + "addPledge": "Añadir Promesa", + "viewPledges": "Ver Promesas", + "noPledges": "No se encontraron promesas", + "noCampaigns": "No se encontraron campañas" + }, + "userPledges": { + "title": "Mis Promesas" } } diff --git a/public/locales/zh/common.json b/public/locales/zh/common.json index 71b697b354..93659c644c 100644 --- a/public/locales/zh/common.json +++ b/public/locales/zh/common.json @@ -82,5 +82,14 @@ "addedSuccessfully": "{{item}} 添加成功", "updatedSuccessfully": "{{item}} 更新成功", "removedSuccessfully": "{{item}} 删除成功", - "successfullyUpdated": "更新成功" + "successfullyUpdated": "更新成功", + "all": "全部", + "active": "活跃", + "disabled": "禁用", + "pending": "待处理", + "completed": "已完成", + "late": "迟到", + "createdLatest": "最近创建", + "createdEarliest": "最早创建", + "searchBy": "搜索依据 {{item}}" } diff --git a/public/locales/zh/errors.json b/public/locales/zh/errors.json index 1466985403..c872f367a5 100644 --- a/public/locales/zh/errors.json +++ b/public/locales/zh/errors.json @@ -6,5 +6,6 @@ "errorSendingMail": "发送邮件时出错", "emailNotRegistered": "邮箱未注册", "notFoundMsg": "哎呀!", - "errorOccurredCouldntCreate": "发生错误。 无法创建{{entity}}" + "errorOccurredCouldntCreate": "发生错误。 无法创建{{entity}}", + "errorLoading": "加载{{entity}}数据时出错" } diff --git a/public/locales/zh/translation.json b/public/locales/zh/translation.json index 6f8cf9e278..7f41c8baaf 100644 --- a/public/locales/zh/translation.json +++ b/public/locales/zh/translation.json @@ -22,7 +22,25 @@ "numeric_value_check": "至少设定一个数值", "special_char_check": "至少一个特殊字符", "selectOrg": "选择一个组织", - "afterRegister": "注册成功。" + "afterRegister": "注册成功。", + "talawa_portal": "塔拉瓦门户", + "login": "登录", + "register": "注册", + "firstName": "名字", + "lastName": "姓氏", + "email": "电子邮件", + "password": "密码", + "confirmPassword": "确认密码", + "forgotPassword": "忘记密码", + "enterEmail": "输入电子邮件", + "enterPassword": "输入密码", + "talawaApiUnavailable": "塔拉瓦 API 不可用", + "notAuthorised": "未授权", + "notFound": "未找到", + "OR": "或", + "admin": "管理员", + "user": "用户", + "loading": "加载中" }, "userLoginPage": { "title": "塔拉瓦管理员", @@ -38,7 +56,23 @@ "successfullyRegistered": "注册成功。", "userLogin": "用户登录", "afterRegister": "注册成功。", - "selectOrg": "选择一个组织" + "selectOrg": "选择一个组织", + "talawa_portal": "塔拉瓦门户", + "login": "登录", + "register": "注册", + "firstName": "名字", + "lastName": "姓氏", + "email": "电子邮件", + "password": "密码", + "confirmPassword": "确认密码", + "forgotPassword": "忘记密码", + "enterEmail": "输入电子邮件", + "enterPassword": "输入密码", + "talawaApiUnavailable": "塔拉瓦 API 不可用", + "notAuthorised": "未授权", + "notFound": "未找到", + "OR": "或", + "loading": "加载中" }, "latestEvents": { "eventCardTitle": "即将举行的活动", @@ -51,12 +85,19 @@ "noPostsCreated": "没有创建帖子" }, "listNavbar": { - "roles": "角色" + "roles": "角色", + "talawa_portal": "塔拉瓦门户", + "requests": "请求", + "logout": "退出登录" }, "leftDrawer": { "my organizations": "我的组织", "requests": "会员申请", - "communityProfile": "社区简介" + "communityProfile": "社区简介", + "talawaAdminPortal": "塔拉瓦管理员门户", + "menu": "菜单", + "users": "用户", + "logout": "退出登录" }, "leftDrawerOrg": { "Dashboard": "仪表板", @@ -75,7 +116,13 @@ "notifications": "通知", "spamsThe": "垃圾邮件", "group": "团体", - "noNotifications": "无通知" + "noNotifications": "无通知", + "talawaAdminPortal": "塔拉瓦管理员门户", + "menu": "菜单", + "talawa_portal": "塔拉瓦门户", + "settings": "设置", + "logout": "退出登录", + "close": "关闭" }, "orgList": { "title": "塔拉瓦组织", @@ -105,11 +152,25 @@ "manageFeaturesInfo": "创建成功!", "goToStore": "前往插件商店", "enableEverything": "启用一切", - "sampleOrgSuccess": "样本组织已成功创建" + "sampleOrgSuccess": "样本组织已成功创建", + "name": "名称", + "email": "电子邮件", + "searchByName": "按名称搜索", + "description": "描述", + "location": "位置", + "address": "地址", + "displayImage": "显示图像", + "filter": "筛选", + "cancel": "取消", + "endOfResults": "结果结束", + "noResultsFoundFor": "未找到结果", + "OR": "或" }, "orgListCard": { "manage": "管理", - "sampleOrganization": "组织样本" + "sampleOrganization": "组织样本", + "admins": "管理员", + "members": "成员" }, "paginationList": { "rowsPerPage": "每页行数", @@ -126,7 +187,11 @@ "acceptedSuccessfully": "请求已成功接受", "rejectedSuccessfully": "请求被成功拒绝", "noOrgErrorTitle": "未找到组织", - "noOrgErrorDescription": "请通过仪表板创建组织" + "noOrgErrorDescription": "请通过仪表板创建组织", + "name": "名称", + "email": "电子邮件", + "endOfResults": "结果结束", + "noResultsFoundFor": "未找到结果" }, "users": { "title": "塔拉瓦角色", @@ -150,7 +215,25 @@ "visit": "访问", "withdraw": "拉幅", "removeUserFrom": "从{{org}}中删除用户", - "removeConfirmation": "您确定要将'{{name}}'从组织'{{org}}'中删除吗?" + "removeConfirmation": "您确定要将'{{name}}'从组织'{{org}}'中删除吗?", + "searchByName": "按名称搜索", + "users": "用户", + "name": "名称", + "email": "电子邮件", + "endOfResults": "结果结束", + "admin": "管理员", + "superAdmin": "超级管理员", + "user": "用户", + "filter": "筛选", + "noResultsFoundFor": "未找到结果", + "talawaApiUnavailable": "塔拉瓦 API 不可用", + "cancel": "取消", + "admins": "管理员", + "members": "成员", + "orgJoined": "已加入组织", + "MembershipRequestSent": "会员请求已发送", + "AlreadyJoined": "已加入", + "errorOccured": "发生错误" }, "communityProfile": { "title": "社区简介", @@ -178,7 +261,12 @@ "latestPosts": "最新帖子", "noPostsPresent": "没有帖子", "membershipRequests": "会员请求", - "noMembershipRequests": "没有会员请求" + "noMembershipRequests": "没有会员请求", + "location": "位置", + "members": "成员", + "admins": "管理员", + "requests": "请求", + "talawaApiUnavailable": "塔拉瓦 API 不可用" }, "organizationPeople": { "title": "塔拉瓦会员", @@ -198,23 +286,79 @@ "enterLastName": "输入您的姓氏", "enterConfirmPassword": "输入您的密码进行确认", "organization": "组织", - "invalidDetailsMessage": "请输入有效的详细信息。" + "invalidDetailsMessage": "请输入有效的详细信息。", + "members": "成员", + "admins": "管理员", + "users": "用户", + "searchFirstName": "按名字搜索", + "searchLastName": "按姓氏搜索", + "firstName": "名字", + "lastName": "姓氏", + "emailAddress": "电子邮件地址", + "enterEmail": "输入你的电子邮件地址", + "password": "密码", + "enterPassword": "输入你的密码", + "confirmPassword": "确认密码", + "cancel": "取消", + "create": "创建", + "user": "用户", + "profile": "个人资料" + }, + "organizationTags": { + "title": "组织标签", + "createTag": "创建新标签", + "manageTag": "管理", + "editTag": "编辑", + "removeTag": "删除", + "tagDetails": "标签详情", + "tagName": "名称", + "tagType": "类型", + "tagNamePlaceholder": "输入标签名称", + "tagCreationSuccess": "新标签创建成功", + "tagUpdationSuccess": "标签更新成功", + "tagRemovalSuccess": "标签删除成功", + "noTagsFound": "未找到标签", + "removeUserTag": "删除标签", + "removeUserTagMessage": "您确定要删除此标签吗?", + "addChildTag": "添加子标签" + }, + "manageTag": { + "title": "标签详情", + "addPeopleToTag": "将人员添加到标签", + "viewProfile": "查看", + "noAssignedMembersFound": "没有分配成员", + "unassignUserTag": "取消分配标签", + "unassignUserTagMessage": "您想从此用户中删除标签吗?", + "successfullyUnassigned": "标签已从用户中取消分配", + "addPeople": "添加人员", + "add": "添加", + "subTags": "子标签" }, "userListCard": { "addAdmin": "添加管理员", - "addedAsAdmin": "用户被添加为管理员。" + "addedAsAdmin": "用户被添加为管理员。", + "joined": "已加入", + "talawaApiUnavailable": "塔拉瓦 API 不可用" }, "orgAdminListCard": { "remove": "消除", "removeAdmin": "删除管理员", "removeAdminMsg": "您想删除该管理员吗?", - "adminRemoved": "管理员被删除。" + "adminRemoved": "管理员被删除。", + "joined": "已加入", + "no": "否", + "yes": "是", + "talawaApiUnavailable": "塔拉瓦 API 不可用" }, "orgPeopleListCard": { "remove": "消除", "removeMember": "删除会员", "removeMemberMsg": "您想删除该成员吗?", - "memberRemoved": "该会员已被删除" + "memberRemoved": "该会员已被删除", + "joined": "已加入", + "no": "否", + "yes": "是", + "talawaApiUnavailable": "塔拉瓦 API 不可用" }, "organizationEvents": { "title": "活动", @@ -245,7 +389,14 @@ "never": "绝不", "on": "在", "after": "后", - "occurences": "事件" + "occurences": "事件", + "events": "活动", + "description": "描述", + "location": "位置", + "startDate": "开始日期", + "endDate": "结束日期", + "talawaApiUnavailable": "塔拉瓦 API 不可用", + "done": "完成" }, "organizationActionItems": { "actionItemCategory": "行动项目类别", @@ -256,7 +407,6 @@ "assignmentDate": "分配日期", "active": "积极的", "clearFilters": "清除过滤器", - "completed": "完全的", "completionDate": "完成日期", "createActionItem": "创建操作项", "deleteActionItem": "删除操作项", @@ -281,7 +431,18 @@ "successfulCreation": "操作项创建成功", "successfulUpdation": "操作项已成功更新", "successfulDeletion": "操作项已成功删除", - "title": "行动项目" + "title": "行动项目", + "category": "类别", + "allotedHours": "分配的小时", + "latestDueDate": "最晚到期日", + "earliestDueDate": "最早到期日", + "updateActionItem": "更新操作项", + "noneUpdated": "没有更新任何字段", + "updateStatusMsg": "您确定要将此操作项标记为待处理吗?", + "close": "关闭", + "eventActionItems": "活动行动项目", + "no": "否", + "yes": "是" }, "organizationAgendaCategory": { "agendaCategoryDetails": "议程类别详情", @@ -360,7 +521,17 @@ "never": "绝不", "on": "在", "after": "后", - "occurences": "事件" + "occurences": "事件", + "location": "位置", + "no": "否", + "yes": "是", + "description": "描述", + "startDate": "开始日期", + "endDate": "结束日期", + "registerEvent": "注册活动", + "close": "关闭", + "talawaApiUnavailable": "塔拉瓦 API 不可用", + "done": "完成" }, "funds": { "title": "基金", @@ -436,7 +607,9 @@ "pledges": "承诺", "endsOn": "结束于", "raisedAmount": "募集金額", - "pledgedAmount": "承诺金額" + "pledgedAmount": "承诺金額", + "startDate": "开始日期", + "endDate": "结束日期" }, "orgPost": { "title": "帖子", @@ -464,7 +637,8 @@ "postCreatedSuccess": "恭喜!", "pinPost": "针柱", "Next": "下一页", - "Previous": "上一页" + "Previous": "上一页", + "cancel": "取消" }, "postNotFound": { "post": "邮政", @@ -479,7 +653,8 @@ "user not found!": "未找到用户!", "member not found!": "未找到会员!", "admin not found!": "找不到管理员!", - "roles not found!": "未找到角色!" + "roles not found!": "未找到角色!", + "user": "用户" }, "orgPostCard": { "author": "作者", @@ -498,7 +673,12 @@ "postDeleted": "帖子删除成功。", "postUpdated": "帖子更新成功。", "tag": " 您的浏览器不支持video标签", - "pin": "针柱" + "pin": "针柱", + "edit": "编辑", + "no": "否", + "yes": "是", + "close": "关闭", + "talawaApiUnavailable": "塔拉瓦 API 不可用" }, "blockUnblockUser": { "title": "阻止/取消阻止用户", @@ -514,7 +694,12 @@ "blockedUsers": "被阻止的用户", "searchByFirstName": "按名字搜索", "searchByLastName": "按姓氏搜索", - "noSpammerFound": "未发现垃圾邮件发送者" + "noSpammerFound": "未发现垃圾邮件发送者", + "searchByName": "按名称搜索", + "name": "名称", + "email": "电子邮件", + "talawaApiUnavailable": "塔拉瓦 API 不可用", + "noResultsFoundFor": "未找到结果" }, "eventManagement": { "title": "事件管理", @@ -539,7 +724,10 @@ "errorSendingMail": "发送邮件时出错。", "passwordMismatches": "密码和确认密码不匹配。", "passwordChanges": "密码修改成功。", - "OTPsent": "OTP 已发送至您的注册邮箱。" + "OTPsent": "OTP 已发送至您的注册邮箱。", + "forgotPassword": "忘记密码", + "password": "密码", + "talawaApiUnavailable": "塔拉瓦 API 不可用" }, "pageNotFound": { "404": "404", @@ -570,14 +758,15 @@ }, "orgSettings": { "title": "设置", - "general": "一般的", - "actionItemCategories": "行动项目类别", + "general": "一般", + "actionItemCategories": "操作项目类别", "updateOrganization": "更新组织", "seeRequest": "查看请求", "noData": "没有数据", "otherSettings": "其他设置", - "changeLanguage": "改变语言", - "manageCustomFields": "管理自定义字段" + "changeLanguage": "更改语言", + "manageCustomFields": "管理自定义字段", + "agendaItemCategories": "议程项目类别" }, "deleteOrg": { "deleteOrganization": "删除组织", @@ -585,18 +774,30 @@ "deleteMsg": "您想删除该组织吗?", "confirmDelete": "确认删除", "longDelOrgMsg": "通过单击“删除组织”按钮,该组织及其事件、标签和所有相关数据将被永久删除。", - "successfullyDeletedSampleOrganization": "已成功删除样本组织" + "successfullyDeletedSampleOrganization": "已成功删除样本组织", + "cancel": "取消" }, "userUpdate": { "appLanguageCode": "默认语言", - "userType": "用户类型" + "userType": "用户类型", + "firstName": "名字", + "lastName": "姓氏", + "email": "电子邮件", + "password": "密码", + "admin": "管理员", + "superAdmin": "超级管理员", + "displayImage": "显示图像", + "saveChanges": "保存更改", + "cancel": "取消" }, "userPasswordUpdate": { "previousPassword": "旧密码", "newPassword": "新密码", "confirmNewPassword": "确认新密码", "passCantBeEmpty": "密码不能为空", - "passNoMatch": "新密码和确认密码不匹配。" + "passNoMatch": "新密码和确认密码不匹配。", + "saveChanges": "保存更改", + "cancel": "取消" }, "orgDelete": { "deleteOrg": "删除组织" @@ -604,7 +805,9 @@ "membershipRequest": { "accept": "接受", "reject": "拒绝", - "memberAdded": "它被接受" + "memberAdded": "它被接受", + "joined": "已加入", + "talawaApiUnavailable": "塔拉瓦 API 不可用" }, "orgUpdate": { "city": "城市", @@ -618,7 +821,15 @@ "userRegistrationRequired": "需要用户注册", "isVisibleInSearch": "在搜索中可见", "enterNameOrganization": "输入组织名称", - "successfulUpdated": "组织更新成功" + "successfulUpdated": "组织更新成功", + "name": "名称", + "description": "描述", + "location": "位置", + "address": "地址", + "displayImage": "显示图像", + "saveChanges": "保存更改", + "cancel": "取消", + "talawaApiUnavailable": "塔拉瓦 API 不可用" }, "addOnRegister": { "addNew": "添新", @@ -628,7 +839,9 @@ "pluginDesc": "插件说明", "pName": "例如:捐款", "cName": "例如:约翰·多伊", - "pDesc": "该插件启用 UI" + "pDesc": "该插件启用 UI", + "close": "关闭", + "register": "注册" }, "addOnStore": { "title": "添加商店", @@ -639,7 +852,8 @@ "pHeading": "插件", "install": "已安装", "available": "可用的", - "pMessage": "插件不存在" + "pMessage": "插件不存在", + "filter": "筛选" }, "addOnEntry": { "enable": "启用", @@ -681,14 +895,32 @@ "membershipRequests": "会员请求", "adminForEvents": "活动管理员", "addedAsAdmin": "用户被添加为管理员。", - "userType": "用户类型" + "userType": "用户类型", + "email": "电子邮件", + "displayImage": "显示图像", + "address": "地址", + "delete": "删除", + "saveChanges": "保存更改", + "joined": "已加入", + "talawaApiUnavailable": "塔拉瓦 API 不可用" }, "userLogin": { "login": "登录", "loginIntoYourAccount": "登录您的帐户", "invalidDetailsMessage": "请输入有效的电子邮件和密码。", "notAuthorised": "对不起!", - "invalidCredentials": "输入的凭据不正确。" + "invalidCredentials": "输入的凭据不正确。", + "forgotPassword": "忘记密码", + "emailAddress": "电子邮件地址", + "enterEmail": "输入电子邮件", + "password": "密码", + "enterPassword": "输入密码", + "register": "注册", + "talawaApiUnavailable": "塔拉瓦 API 不可用" + }, + "people": { + "title": "人们", + "searchUsers": "搜索用户" }, "userRegister": { "enterFirstName": "输入您的名字", @@ -698,7 +930,16 @@ "login": "登录", "afterRegister": "注册成功。", "passwordNotMatch": "密码不匹配。", - "invalidDetailsMessage": "请输入有效的详细信息。" + "invalidDetailsMessage": "请输入有效的详细信息。", + "register": "注册", + "firstName": "名字", + "lastName": "姓氏", + "emailAddress": "电子邮件地址", + "enterEmail": "输入电子邮件", + "password": "密码", + "enterPassword": "输入密码", + "confirmPassword": "确认密码", + "talawaApiUnavailable": "塔拉瓦 API 不可用" }, "userNavbar": { "talawa": "塔拉瓦", @@ -707,7 +948,10 @@ "events": "活动", "chat": "聊天", "donate": "捐", - "language": "语言" + "language": "语言", + "settings": "设置", + "logout": "退出登录", + "close": "关闭" }, "userOrganizations": { "allOrganizations": "所有组织", @@ -716,7 +960,11 @@ "selectOrganization": "选择一个组织", "searchUsers": "搜索用户", "nothingToShow": "这里没有什么可显示的。", - "organizations": "组织机构" + "organizations": "组织机构", + "search": "搜索", + "filter": "筛选", + "searchByName": "按名称搜索", + "searchOrganizations": "搜索组织" }, "userSidebarOrg": { "yourOrganizations": "您的组织", @@ -724,13 +972,20 @@ "viewAll": "查看全部", "talawaUserPortal": "塔拉瓦用户门户", "my organizations": "我的组织", - "communityProfile": "社区简介" + "communityProfile": "社区简介", + "users": "用户", + "requests": "请求", + "logout": "登出", + "settings": "设置", + "chat": "聊天", + "menu": "菜单" }, "organizationSidebar": { "viewAll": "查看全部", "events": "活动", "noEvents": "没有可显示的活动", - "noMembers": "没有可显示的会员" + "noMembers": "没有可显示的会员", + "members": "成员" }, "postCard": { "likes": "喜欢", @@ -740,9 +995,9 @@ "postedOn": "发布于 {{date}}" }, "home": { + "title": "帖子", "posts": "帖子", "post": "邮政", - "title": "标题", "textArea": "你有什么心事吗?", "feed": "喂养", "loading": "加载中", @@ -809,9 +1064,18 @@ "fullTime": "全职", "partTime": "兼职", "selectCountry": "选择一个国家", - "enterState": "输入城市或州" + "enterState": "输入城市或州", + "settings": "设置", + "firstName": "名字", + "lastName": "姓氏", + "emailAddress": "电子邮件地址", + "displayImage": "显示图像", + "address": "地址", + "saveChanges": "保存更改", + "joined": "已加入" }, "donate": { + "title": "捐款", "donations": "捐款", "searchDonations": "搜索捐款", "donateForThe": "为", @@ -819,9 +1083,14 @@ "yourPreviousDonations": "您之前的捐款", "donate": "捐", "nothingToShow": "这里没有什么可显示的。", - "success": "捐赠成功" + "success": "捐赠成功", + "invalidAmount": "请输入捐赠金额的数值。", + "donationAmountDescription": "请输入捐款金额的数值。", + "donationOutOfRange": "捐款金额必须在 {{min}} 和 {{max}} 之间。", + "donateTo": "捐赠给" }, "userEvents": { + "title": "活动", "nothingToShow": "这里没有什么可显示的。", "createEvent": "创建事件", "recurring": "重复事件", @@ -839,13 +1108,22 @@ "publicEvent": "是公开的", "registerable": "可注册", "monthlyCalendarView": "月历", - "yearlyCalendarView": "年历" + "yearlyCalendarView": "年历", + "search": "搜索", + "cancel": "取消", + "create": "创建", + "eventDescription": "活动描述", + "eventLocation": "活动位置", + "startDate": "开始日期", + "endDate": "结束日期" }, "userEventCard": { "starts": "开始", "ends": "结束", "creator": "创作者", - "alreadyRegistered": "已经注册" + "alreadyRegistered": "已经注册", + "location": "位置", + "register": "注册" }, "advertisement": { "title": "广告", @@ -870,11 +1148,21 @@ "editAdvertisement": "编辑广告", "advertisementDeleted": "广告已成功删除。", "endDateGreaterOrEqual": "结束日期应大于或等于开始日期", - "advertisementCreated": "广告已成功创建。" + "advertisementCreated": "广告已成功创建。", + "pHeading": "广告标题", + "delete": "删除", + "close": "关闭", + "no": "否", + "yes": "是", + "edit": "编辑", + "saveChanges": "保存更改", + "endOfResults": "结果结束" }, "userChat": { "chat": "聊天", - "contacts": "联系方式" + "contacts": "联系方式", + "search": "搜索", + "messages": "消息" }, "userChatRoom": { "selectContact": "选择联系人开始对话", @@ -892,20 +1180,28 @@ "String": "字符串", "Boolean": "布尔值", "Date": "日期", - "Number": "数字" + "Number": "数字", + "saveChanges": "保存更改" }, "orgActionItemCategories": { "enableButton": "使能够", "disableButton": "禁用", "updateActionItemCategory": "更新", "actionItemCategoryName": "姓名", - "actionItemCategoryDetails": "行动项目类别详细信息", + "categoryDetails": "类别详情", "enterName": "输入名字", "successfulCreation": "操作项类别创建成功", "successfulUpdation": "行动项目类别已成功更新", "sameNameConflict": "请更改名称以进行更新", "categoryEnabled": "已启用操作项类别", - "categoryDisabled": "操作项类别已禁用" + "categoryDisabled": "操作项类别已禁用", + "noActionItemCategories": "没有操作项目类别", + "status": "地位", + "categoryDeleted": "操作项目类别已成功删除", + "deleteCategory": "删除类别", + "deleteCategoryMsg": "您确定要删除此操作项目类别吗?", + "createButton": "创建按钮", + "editButton": "编辑按钮" }, "organizationVenues": { "title": "场地", @@ -929,7 +1225,12 @@ "view": "看法", "venueTitleError": "场地名称不能为空!", "venueCapacityError": "容量必须是正数!", - "searchBy": "搜索依据" + "searchBy": "搜索依据", + "description": "描述", + "edit": "编辑", + "delete": "删除", + "name": "名称", + "desc": "描述" }, "addMember": { "title": "添加会员", @@ -943,7 +1244,18 @@ "organization": "组织", "invalidDetailsMessage": "请提供所有必需的详细信息。", "passwordNotMatch": "密码不匹配。", - "addMember": "添加会员" + "firstName": "名字", + "lastName": "姓氏", + "emailAddress": "电子邮件地址", + "enterEmail": "输入电子邮件", + "password": "密码", + "enterPassword": "输入密码", + "confirmPassword": "确认密码", + "cancel": "取消", + "create": "创建", + "addMember": "添加会员", + "user": "用户", + "profile": "个人资料" }, "eventActionItems": { "title": "行动项目", @@ -971,7 +1283,9 @@ "actionItemStatus": "行动项目状态", "actionItemCompleted": "行动项目已完成", "markCompletion": "标记完成", - "save": "节省" + "save": "节省", + "yes": "是", + "no": "否" }, "checkIn": { "errorCheckingIn": "签到错误", @@ -980,5 +1294,26 @@ "eventRegistrantsModal": { "errorAddingAttendee": "添加与会者时出错", "errorRemovingAttendee": "删除与会者时出错" + }, + "userCampaigns": { + "title": "筹款活动", + "searchByName": "按名字搜索...", + "searchBy": "按...搜索", + "pledgers": "承诺者", + "campaigns": "活动", + "myPledges": "我的承诺", + "lowestAmount": "最低金额", + "highestAmount": "最高金额", + "lowestGoal": "最低目标", + "highestGoal": "最高目标", + "latestEndDate": "最晚结束日期", + "earliestEndDate": "最早结束日期", + "addPledge": "添加承诺", + "viewPledges": "查看承诺", + "noPledges": "未找到承诺", + "noCampaigns": "未找到活动" + }, + "userPledges": { + "title": "我的承诺" } } diff --git a/scripts/__mocks__/fileMock.js b/scripts/__mocks__/fileMock.js new file mode 100644 index 0000000000..06ad689c8b --- /dev/null +++ b/scripts/__mocks__/fileMock.js @@ -0,0 +1,2 @@ +// __mocks__/fileMock.js +module.exports = 'test-file-stub'; diff --git a/scripts/config-overrides/custom_build.js b/scripts/config-overrides/custom_build.js deleted file mode 100644 index d5c0ce93a2..0000000000 --- a/scripts/config-overrides/custom_build.js +++ /dev/null @@ -1,17 +0,0 @@ -require('dotenv').config(); -const { spawn } = require('child_process'); - -//use default react scritps config -const react_script_build = 'npx react-scripts build'; - -//use custom config overriden by react-app-rewired -const react_app_rewired_build = 'npx react-app-rewired build'; - -if (process.env.ALLOW_LOGS === "YES") { - spawn(react_app_rewired_build, { stdio: 'inherit', shell: true }); - -} -else { - spawn(react_script_build, { stdio: 'inherit', shell: true }); -} - diff --git a/scripts/config-overrides/custom_start.js b/scripts/config-overrides/custom_start.js deleted file mode 100644 index a784f1bb48..0000000000 --- a/scripts/config-overrides/custom_start.js +++ /dev/null @@ -1,19 +0,0 @@ -require('dotenv').config(); -const { spawn } = require('child_process'); - -const port = process.env.PORT || 4321; -process.env.PORT = port; - -const react_script_start = 'npx react-scripts start'; -const react_app_rewired_start = 'npx react-app-rewired start --config-overrides=scripts/config-overrides'; - -if (process.env.ALLOW_LOGS === "YES") { - // Execute the npm command - spawn(react_app_rewired_start, { stdio: 'inherit', shell: true }); - -} -else { - // Execute the npm command - spawn(react_script_start, { stdio: 'inherit', shell: true }); - } - diff --git a/scripts/config-overrides/index.js b/scripts/config-overrides/index.js deleted file mode 100644 index a8d16aa7e9..0000000000 --- a/scripts/config-overrides/index.js +++ /dev/null @@ -1,29 +0,0 @@ -const { override, addWebpackPlugin } = require('customize-cra'); -const webpack = require('webpack'); - - -module.exports = override( - // Add your new webpack plugin - addWebpackPlugin(new webpack.ProgressPlugin({ - activeModules: true, - entries: true, - handler: (percentage, message, ...args) => { - // Log a custom progress message with active module and its count - console.info(`: ${Math.floor(percentage * 100)}% ${message}`); - }, - modules: true, - modulesCount: 5000, - profile: false, - dependencies: true, - dependenciesCount: 10000, - percentBy: null, -})), - - // Modify infrastructureLogging level - (config) => { - config.infrastructureLogging = { - level: 'verbose', - }; - return config; - } -); \ No newline at end of file diff --git a/scripts/config-overrides/package.json b/scripts/config-overrides/package.json deleted file mode 100644 index c0a38b857f..0000000000 --- a/scripts/config-overrides/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "config-overrides", - "version": "1.0.0", - "type": "commonjs" -} diff --git a/scripts/test.js b/scripts/test.js deleted file mode 100644 index e5858251ff..0000000000 --- a/scripts/test.js +++ /dev/null @@ -1,52 +0,0 @@ -'use strict'; - -// Do this as the first thing so that any code reading it knows the right env. -process.env.BABEL_ENV = 'test'; -process.env.NODE_ENV = 'test'; -process.env.PUBLIC_URL = ''; - -// Makes the script crash on unhandled rejections instead of silently -// ignoring them. In the future, promise rejections that are not handled will -// terminate the Node.js process with a non-zero exit code. -process.on('unhandledRejection', (err) => { - throw err; -}); - -// Ensure environment variables are read. -import 'react-scripts/config/env.js'; - -import jest from 'jest'; -import { execSync } from 'child_process'; - -const argv = process.argv.slice(2); - -function isInGitRepository() { - try { - execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' }); - return true; - } catch (e) { - return false; - } -} - -function isInMercurialRepository() { - try { - execSync('hg --cwd . root', { stdio: 'ignore' }); - return true; - } catch (e) { - return false; - } -} - -// Watch unless on CI or explicitly running all tests -if ( - !process.env.CI && - argv.indexOf('--watchAll') === -1 && - argv.indexOf('--watchAll=false') === -1 -) { - // https://github.com/facebook/create-react-app/issues/5210 - const hasSourceControl = isInGitRepository() || isInMercurialRepository(); - argv.push(hasSourceControl ? '--watch' : '--watchAll'); -} - -jest.run(argv); diff --git a/src/App.test.tsx b/src/App.test.tsx index 3146066e26..f4fba2ebf8 100644 --- a/src/App.test.tsx +++ b/src/App.test.tsx @@ -1,5 +1,5 @@ -import React from 'react'; -import { act, render, screen } from '@testing-library/react'; +import React, { act } from 'react'; +import { render, screen } from '@testing-library/react'; import { Provider } from 'react-redux'; import { MockedProvider } from '@apollo/react-testing'; import { BrowserRouter } from 'react-router-dom'; diff --git a/src/App.tsx b/src/App.tsx index 7ee6ba72cb..d6e825006f 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -14,12 +14,14 @@ import OrgList from 'screens/OrgList/OrgList'; import OrgPost from 'screens/OrgPost/OrgPost'; import OrgSettings from 'screens/OrgSettings/OrgSettings'; import OrganizationActionItems from 'screens/OrganizationActionItems/OrganizationActionItems'; -import OrganizationAgendaCategory from 'screens/OrganizationAgendaCategory/OrganizationAgendaCategory'; import OrganizationDashboard from 'screens/OrganizationDashboard/OrganizationDashboard'; import OrganizationEvents from 'screens/OrganizationEvents/OrganizationEvents'; import OrganizaitionFundCampiagn from 'screens/OrganizationFundCampaign/OrganizationFundCampagins'; import OrganizationFunds from 'screens/OrganizationFunds/OrganizationFunds'; import OrganizationPeople from 'screens/OrganizationPeople/OrganizationPeople'; +import OrganizationTags from 'screens/OrganizationTags/OrganizationTags'; +import ManageTag from 'screens/ManageTag/ManageTag'; +import SubTags from 'screens/SubTags/SubTags'; import PageNotFound from 'screens/PageNotFound/PageNotFound'; import Requests from 'screens/Requests/Requests'; import Users from 'screens/Users/Users'; @@ -34,7 +36,6 @@ import Posts from 'screens/UserPortal/Posts/Posts'; import Organizations from 'screens/UserPortal/Organizations/Organizations'; import People from 'screens/UserPortal/People/People'; import Settings from 'screens/UserPortal/Settings/Settings'; -// import UserLoginPage from 'screens/UserPortal/UserLoginPage/UserLoginPage'; import Chat from 'screens/UserPortal/Chat/Chat'; import { useQuery } from '@apollo/client'; import { CHECK_AUTH } from 'GraphQl/Queries/Queries'; @@ -45,9 +46,28 @@ import FundCampaignPledge from 'screens/FundCampaignPledge/FundCampaignPledge'; import useLocalStorage from 'utils/useLocalstorage'; import UserScreen from 'screens/UserPortal/UserScreen/UserScreen'; import EventDashboardScreen from 'components/EventDashboardScreen/EventDashboardScreen'; +import Campaigns from 'screens/UserPortal/Campaigns/Campaigns'; +import Pledges from 'screens/UserPortal/Pledges/Pledges'; const { setItem } = useLocalStorage(); +/** + * This is the main function for our application. It sets up all the routes and components, + * defining how the user can navigate through the app. The function uses React Router's `Routes` + * and `Route` components to map different URL paths to corresponding screens and components. + * + * ## Important Details + * - **UseEffect Hook**: This hook checks user authentication status using the `CHECK_AUTH` GraphQL query. + * - **Plugins**: It dynamically loads additional routes for any installed plugins. + * - **Routes**: + * - The root route ("/") takes the user to the `LoginPage`. + * - Protected routes are wrapped with the `SecuredRoute` component to ensure they are only accessible to authenticated users. + * - Admin and Super Admin routes allow access to organization and user management screens. + * - User portal routes allow end-users to interact with organizations, settings, chat, events, etc. + * + * @returns The rendered routes and components of the application. + */ + function app(): JSX.Element { /*const { updatePluginLinks, updateInstalled } = bindActionCreators( actionCreators, @@ -100,12 +120,12 @@ function app(): JSX.Element { ], index: number, ) => { - const extraComponent = plugin[1]; + const ExtraComponent = plugin[1]; return ( } /> ); }, @@ -126,6 +146,12 @@ function app(): JSX.Element { } /> } /> } /> + } /> + } + /> + } /> } /> } /> } /> - } - /> } /> } /> } /> } /> + } /> + } /> }> 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

    @B;cpz)B6D9z#)g3sXMY zaa+t!3HYuvB@O+u@4g)lef*d1D~Omxk-gd>S4(r}5P<}ooJ4LUYeJQ#SID{CgHb9M zQMGWsWig-ExK0BozpQMR?D#V6fopnKu({2D)k3q+nm9V$z=x2f*R5avJok&PEsKU9 zCS!P@a+WawLUe-O9YGi4q+i^w-IwI_Cj+6u2-)ppNQt!;@+%h$$4;G(pPl(%Ne-SB zHc5F@^Rz$4b$Ne?G(vrIm)>t|bl+e`UcGd_TiEl@X(%BTIc4+XTWfqel2Qf4PLNdP z?fA%$K6JpCOcC9)2&Y{$E$Z7}i2D!{fn#BHn83R|<{Kp*qq-hO=XhMWv=w2J;-`t-ch8LDqjaq{`Ocdr^Gy?SRSxBa7I$sq7y=vtH_6T1Lkk({*Jf{>?=IE}pM< z^S*grl|p-l>B>kCoR;)@G{U1G$>TmNB*0+juj_K~4CJws(N16mhxJ9K_Fcz5u?wlY zq~;IvE^PnPH@_$8sD$YF-jU*Hr&9fGP}A3c9sa~_>KPKEybOIDH@AFKK)-L`8{_4x z31`Lzw=xnrMW0aLN@6#~izMrjoBF2C5R}+CxN#?EQKP{Gy*FGc z2Tmp39dlyC^8M3crSNiKUvQB}U<-PiFH&DphZ<#_=OObM8QB(}FCHHk^f}VWv*{TV z<=|j9w1Zu&_-F6khKx(09y0_vP1=aU8Q&MIx&V6%`bjnT29ih><0zzep4k_cer{Ph zgi1%4;{8D4=aMDlMZbal$`CP@VYs{Zl-^JsLXXbP^onLMqNdxVEqzmcMgB93^papg zpukf90XGX_h|=1uUIMhdV61bj*g-clnXm@c?sCd%SEZT>DdR+8t(l6b$%Jq1i9X`i z{`zsus>9Uvt)^nt=>5eVJ?3xmZwH$Uk}3PL5=~r^5Ppf3UJ>J2mKA4)QXREk(<`28 zSmf*;7P)lTK!KdvXl2Fu;(k6m$paxyHh$9(+Oc&7y^I#+8_Mp z_XIvt%3LRcGLW=qylo}fOJ`N`_2|~a#8FJ{o&DhxyJSn{T8Sf@ufHY@ znhT{mTZhG+Ti@s#&s0#>Y^$sW>`hBsxBnED0t8?^r1G<&B+u5yGF za2~}L@W|?<_Q{&jYm455;M2{7sqr}y&AEZn2n*{`v#-%kHL72*&F~vjYt57G%*^}* zvs64DG_0Y{H(ibK_)@|C!LRX8>875tmcI?H?=y3TTDdhuYZ}anJ0TB;g6YU*O@oqt zxGv;C#!mxwbp!PGsSG|GatB-=t`Rl~v~(-jmq^7c!9(^YZ)WGalZcR7g#1Ug*Q^zFF5yT5M4Bm(X$m&`}&e(XcHZU;uYbC{@?uZGIz0*rKp(6}w!UT*Joc|RvLU5)Kk zl%gW3EFf%6&jNik>u=BvljnbSn1yLa6FRaO+xci?FP1tFQ$HDvNb%+ATOoO4IWduE zq=Kutn5&Fg3ERW@0iOzT+$90|CziNPaJ}98&0Ayn6#M~CT;Ho8edNgp|D95WYdz+^ z#yanGW6EQ*;{nqD^LS&@ZG_fr>PK^_60^ke-08w%EVE{1o}=-7|Fd+n1Thc$xEiW>$pi0&bROYXa$DP1OWQ9*2Xz6+^;6phS}h52^1(^9Gy z51Sh`)6Kl15p9s`eq*r?;U87(-82?54?IJy`&OKWOvGMz?sj}_Ae{-~M6w+Teh}=w zWFlKQtc1Y5@z!44Wf-iuZ&ow$`&}M`H+dNU-(7FW$ZY-5wxo3LRAs)J3F8jiz2Zx6 z^SLj_)WU6veYLkF0JIpsnb}{jy_}7~Y#L__O9zvJw+-GlUS8PA)!;eikyQTO-|bZs zJ@EoY@BMRU{qqf~B%5BR<1TE{|MyEq@M7#80Yw#$_Sc*-W9+RdKn1FyfRcL?_#fiP BdOrXF diff --git a/src/assets/images/talawa-logo-600x600.png b/src/assets/images/talawa-logo-600x600.png new file mode 100644 index 0000000000000000000000000000000000000000..94981326003a9f36ac66bd29043df2b6f565f17f GIT binary patch literal 17667 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 literal 0 HcmV?d00001 diff --git a/src/assets/svgs/angleLeft.svg b/src/assets/svgs/angleLeft.svg deleted file mode 100644 index a0362e5e38..0000000000 --- a/src/assets/svgs/angleLeft.svg +++ /dev/null @@ -1,5 +0,0 @@ - - -angle-left - - \ No newline at end of file diff --git a/src/assets/svgs/eventDashboard.svg b/src/assets/svgs/eventDashboard.svg deleted file mode 100644 index 769c57d315..0000000000 --- a/src/assets/svgs/eventDashboard.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/src/assets/svgs/eventStats.svg b/src/assets/svgs/eventStats.svg deleted file mode 100644 index ffa43fdc4a..0000000000 --- a/src/assets/svgs/eventStats.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/src/assets/svgs/social-icons/Twitter-Logo.svg b/src/assets/svgs/social-icons/X-Logo.svg similarity index 100% rename from src/assets/svgs/social-icons/Twitter-Logo.svg rename to src/assets/svgs/social-icons/X-Logo.svg diff --git a/src/assets/svgs/social-icons/index.tsx b/src/assets/svgs/social-icons/index.tsx index af6ef77966..20544051e5 100644 --- a/src/assets/svgs/social-icons/index.tsx +++ b/src/assets/svgs/social-icons/index.tsx @@ -3,7 +3,7 @@ import GithubLogo from './Github-Logo.svg'; import InstagramLogo from './Instagram-Logo.svg'; import LinkedInLogo from './Linkedin-Logo.svg'; import SlackLogo from './Slack-Logo.svg'; -import TwitterLogo from './Twitter-Logo.svg'; +import XLogo from './X-Logo.svg'; import YoutubeLogo from './Youtube-Logo.svg'; import RedditLogo from './Reddit-Logo.svg'; @@ -13,7 +13,7 @@ export { InstagramLogo, LinkedInLogo, SlackLogo, - TwitterLogo, + XLogo, YoutubeLogo, RedditLogo, }; diff --git a/src/assets/svgs/tag.svg b/src/assets/svgs/tag.svg new file mode 100644 index 0000000000..e3646993be --- /dev/null +++ b/src/assets/svgs/tag.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/components/ActionItems/ActionItemsContainer.module.css b/src/components/ActionItems/ActionItemsContainer.module.css deleted file mode 100644 index b55328c563..0000000000 --- a/src/components/ActionItems/ActionItemsContainer.module.css +++ /dev/null @@ -1,25 +0,0 @@ -.actionItemStatusBadge { - width: 5.5rem; - margin-left: 1.1rem; -} - -.createModal { - margin-top: 20vh; - margin-left: 13vw; - max-width: 80vw; -} - -.titlemodal { - color: var(--bs-gray-600); - font-weight: 600; - font-size: 20px; - margin-bottom: 20px; - padding-bottom: 5px; - border-bottom: 3px solid var(--bs-primary); - width: 65%; -} - -.actionItemsOptionsButton { - width: 24px; - height: 24px; -} diff --git a/src/components/ActionItems/ActionItemsContainer.test.tsx b/src/components/ActionItems/ActionItemsContainer.test.tsx deleted file mode 100644 index 7cb9c9e9bb..0000000000 --- a/src/components/ActionItems/ActionItemsContainer.test.tsx +++ /dev/null @@ -1,777 +0,0 @@ -import React from 'react'; -import { - render, - screen, - fireEvent, - waitFor, - act, - waitForElementToBeRemoved, -} from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import 'jest-localstorage-mock'; -import { MockedProvider } from '@apollo/client/testing'; -import 'jest-location-mock'; -import { I18nextProvider } from 'react-i18next'; -import { Provider } from 'react-redux'; -import { BrowserRouter } from 'react-router-dom'; -import i18nForTest from 'utils/i18nForTest'; -import { toast } from 'react-toastify'; -import { LocalizationProvider } from '@mui/x-date-pickers'; -import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; - -import { store } from 'state/store'; -import { StaticMockLink } from 'utils/StaticMockLink'; - -import ActionItemsContainer from './ActionItemsContainer'; -import { props, props2 } from './ActionItemsContainerProps'; -import { MOCKS, MOCKS_ERROR_MUTATIONS } from './ActionItemsContainerMocks'; - -const link = new StaticMockLink(MOCKS, true); -const link2 = new StaticMockLink(MOCKS_ERROR_MUTATIONS, true); - -jest.mock('react-toastify', () => ({ - toast: { - success: jest.fn(), - error: jest.fn(), - }, -})); - -jest.mock('@mui/x-date-pickers/DateTimePicker', () => { - return { - DateTimePicker: jest.requireActual( - '@mui/x-date-pickers/DesktopDateTimePicker', - ).DesktopDateTimePicker, - }; -}); - -async function wait(ms = 100): Promise { - await act(() => { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); - }); -} - -const translations = JSON.parse( - JSON.stringify( - i18nForTest.getDataByLanguage('en')?.translation.organizationActionItems, - ), -); - -describe('Testing Action Item Categories Component', () => { - const formData = { - assignee: 'Scott Norris', - preCompletionNotes: 'pre completion notes edited', - dueDate: '02/14/2024', - completionDate: '02/21/2024', - }; - - test('component loads correctly with action items', async () => { - render( - - - - - - - - - , - ); - - await wait(); - - await waitFor(() => { - expect( - screen.queryByText(translations.noActionItems), - ).not.toBeInTheDocument(); - }); - - expect(screen.getByText('#')).toBeInTheDocument(); - expect(screen.getByText(translations.assignee)).toBeInTheDocument(); - expect( - screen.getByText(translations.actionItemCategory), - ).toBeInTheDocument(); - expect( - screen.getByText(translations.preCompletionNotes), - ).toBeInTheDocument(); - expect( - screen.getByText(translations.postCompletionNotes), - ).toBeInTheDocument(); - - await wait(); - expect(screen.getAllByText('Harve Lance')[0]).toBeInTheDocument(); - - const asigneeAnchorElement = screen.getAllByText('Harve Lance')[0]; - expect(asigneeAnchorElement.tagName).toBe('A'); - expect(asigneeAnchorElement).toHaveAttribute('href', '/member/event1'); - - expect(screen.getAllByText('ActionItemCategory 1')[0]).toBeInTheDocument(); - const updateButtons = screen.getAllByTestId('editActionItemModalBtn'); - const previewButtons = screen.getAllByTestId('previewActionItemModalBtn'); - const updateStatusButtons = screen.getAllByTestId( - 'actionItemStatusChangeCheckbox', - ); - expect(updateButtons[0]).toBeInTheDocument(); - expect(previewButtons[0]).toBeInTheDocument(); - expect(updateStatusButtons[0]).toBeInTheDocument(); - }); - - test('component loads correctly with no action items', async () => { - render( - - - - - - - - - , - ); - - await wait(); - - await waitFor(() => { - expect( - screen.queryByText(translations.noActionItems), - ).toBeInTheDocument(); - }); - }); - - test('opens and closes the update modal correctly', async () => { - render( - - - - - - - - - - - , - ); - - await wait(); - - await waitFor(() => { - expect( - screen.getAllByTestId('editActionItemModalBtn')[0], - ).toBeInTheDocument(); - }); - userEvent.click(screen.getAllByTestId('editActionItemModalBtn')[0]); - - await waitFor(() => { - return expect( - screen.findByTestId('updateActionItemModalCloseBtn'), - ).resolves.toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('updateActionItemModalCloseBtn')); - - await waitForElementToBeRemoved(() => - screen.queryByTestId('updateActionItemModalCloseBtn'), - ); - }); - - test('opens and closes the action item status change modal correctly', async () => { - render( - - - - - - - - - - - , - ); - - await wait(); - - await waitFor(() => { - expect( - screen.getAllByTestId('actionItemStatusChangeCheckbox')[0], - ).toBeInTheDocument(); - }); - userEvent.click(screen.getAllByTestId('actionItemStatusChangeCheckbox')[0]); - - await waitFor(() => { - return expect( - screen.findByTestId('actionItemStatusChangeModalCloseBtn'), - ).resolves.toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('actionItemStatusChangeModalCloseBtn')); - - await waitForElementToBeRemoved(() => - screen.queryByTestId('actionItemStatusChangeModalCloseBtn'), - ); - }); - - test('completed action item status change modal loads correctly', async () => { - render( - - - - - - - - - - - , - ); - - await wait(); - - await waitFor(() => { - expect( - screen.getAllByTestId('actionItemStatusChangeCheckbox')[1], - ).toBeInTheDocument(); - }); - userEvent.click(screen.getAllByTestId('actionItemStatusChangeCheckbox')[1]); - - await waitFor(() => { - return expect( - screen.findByTestId('actionItemStatusChangeModalCloseBtn'), - ).resolves.toBeInTheDocument(); - }); - expect(screen.getByText(translations.actionItemStatus)).toBeInTheDocument(); - - expect( - screen.getByTestId('actionItemsStatusChangeNotes'), - ).toBeInTheDocument(); - expect( - screen.getByPlaceholderText(translations.actionItemCompleted), - ).toBeInTheDocument(); - expect( - screen.getByRole('button', { name: translations.makeActive }), - ).toBeInTheDocument(); - }); - - test('opens and closes the preview modal correctly', async () => { - render( - - - - - - - - - - - , - ); - - await wait(); - - await waitFor(() => { - expect( - screen.getAllByTestId('previewActionItemModalBtn')[0], - ).toBeInTheDocument(); - }); - userEvent.click(screen.getAllByTestId('previewActionItemModalBtn')[0]); - - await waitFor(() => { - return expect( - screen.findByTestId('previewActionItemModalCloseBtn'), - ).resolves.toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('previewActionItemModalCloseBtn')); - - await waitForElementToBeRemoved(() => - screen.queryByTestId('previewActionItemModalCloseBtn'), - ); - }); - - test('opens and closes the update and delete modals through the preview modal', async () => { - render( - - - - - - - - - - - , - ); - - await wait(); - - await waitFor(() => { - expect( - screen.getAllByTestId('previewActionItemModalBtn')[0], - ).toBeInTheDocument(); - }); - userEvent.click(screen.getAllByTestId('previewActionItemModalBtn')[0]); - - await waitFor(() => { - return expect( - screen.findByTestId('previewActionItemModalCloseBtn'), - ).resolves.toBeInTheDocument(); - }); - - await waitFor(() => { - expect( - screen.getByTestId('deleteActionItemPreviewModalBtn'), - ).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('deleteActionItemPreviewModalBtn')); - - await waitFor(() => { - return expect( - screen.findByTestId('actionItemDeleteModalCloseBtn'), - ).resolves.toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('actionItemDeleteModalCloseBtn')); - - await waitForElementToBeRemoved(() => - screen.queryByTestId('actionItemDeleteModalCloseBtn'), - ); - - await waitFor(() => { - expect( - screen.getByTestId('editActionItemPreviewModalBtn'), - ).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('editActionItemPreviewModalBtn')); - - await waitFor(() => { - return expect( - screen.findByTestId('updateActionItemModalCloseBtn'), - ).resolves.toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('updateActionItemModalCloseBtn')); - - await waitForElementToBeRemoved(() => - screen.queryByTestId('updateActionItemModalCloseBtn'), - ); - }); - - test('updates an action item and toasts success', async () => { - render( - - - - - - - - - - - , - ); - - await wait(); - - await waitFor(() => { - expect( - screen.getAllByTestId('editActionItemModalBtn')[0], - ).toBeInTheDocument(); - }); - userEvent.click(screen.getAllByTestId('editActionItemModalBtn')[0]); - - await waitFor(() => { - expect(screen.getByTestId('formUpdateAssignee')).toBeInTheDocument(); - }); - - userEvent.selectOptions( - screen.getByTestId('formUpdateAssignee'), - formData.assignee, - ); - - const preCompletionNotes = screen.getByPlaceholderText( - translations.preCompletionNotes, - ); - fireEvent.change(preCompletionNotes, { target: { value: '' } }); - userEvent.type(preCompletionNotes, formData.preCompletionNotes); - - // const postCompletionNotes = screen.getByPlaceholderText( - // translations.postCompletionNotes, - // ); - // fireEvent.change(postCompletionNotes, { target: { value: '' } }); - // userEvent.type(postCompletionNotes, formData.postCompletionNotes); - - const dueDatePicker = screen.getByLabelText(translations.dueDate); - fireEvent.change(dueDatePicker, { - target: { value: formData.dueDate }, - }); - - const completionDatePicker = screen.getByLabelText( - translations.completionDate, - ); - fireEvent.change(completionDatePicker, { - target: { value: formData.completionDate }, - }); - - // await waitFor(() => { - // expect(screen.getByTestId('alldayCheck')).toBeInTheDocument(); - // }); - // userEvent.click(screen.getByTestId('alldayCheck')); - - await waitFor(() => { - expect(screen.getByTestId('editActionItemBtn')).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('editActionItemBtn')); - - await waitFor(() => { - expect(toast.success).toBeCalledWith(translations.successfulUpdation); - }); - }); - - test('toasts error on unsuccessful updation', async () => { - render( - - - - - - - - - - - , - ); - - await wait(); - - await waitFor(() => { - expect( - screen.getAllByTestId('editActionItemModalBtn')[0], - ).toBeInTheDocument(); - }); - userEvent.click(screen.getAllByTestId('editActionItemModalBtn')[0]); - - await waitFor(() => { - expect(screen.getByTestId('formUpdateAssignee')).toBeInTheDocument(); - }); - - userEvent.selectOptions( - screen.getByTestId('formUpdateAssignee'), - formData.assignee, - ); - - const preCompletionNotes = screen.getByPlaceholderText( - translations.preCompletionNotes, - ); - fireEvent.change(preCompletionNotes, { target: { value: '' } }); - userEvent.type(preCompletionNotes, formData.preCompletionNotes); - - // const postCompletionNotes = screen.getByPlaceholderText( - // translations.postCompletionNotes, - // ); - // fireEvent.change(postCompletionNotes, { target: { value: '' } }); - // userEvent.type(postCompletionNotes, formData.postCompletionNotes); - - const dueDatePicker = screen.getByLabelText(translations.dueDate); - fireEvent.change(dueDatePicker, { - target: { value: formData.dueDate }, - }); - - const completionDatePicker = screen.getByLabelText( - translations.completionDate, - ); - fireEvent.change(completionDatePicker, { - target: { value: formData.completionDate }, - }); - - // await waitFor(() => { - // expect(screen.getByTestId('alldayCheck')).toBeInTheDocument(); - // }); - // userEvent.click(screen.getByTestId('alldayCheck')); - - await waitFor(() => { - expect(screen.getByTestId('editActionItemBtn')).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('editActionItemBtn')); - - await waitFor(() => { - expect(toast.error).toHaveBeenCalled(); - }); - }); - - test('updates an action item status through the action item status change modal', async () => { - render( - - - - - - - - - - - , - ); - - await wait(); - - await waitFor(() => { - expect( - screen.getAllByTestId('actionItemStatusChangeCheckbox')[0], - ).toBeInTheDocument(); - }); - userEvent.click(screen.getAllByTestId('actionItemStatusChangeCheckbox')[0]); - - await waitFor(() => { - expect( - screen.getByTestId('actionItemsStatusChangeNotes'), - ).toBeInTheDocument(); - }); - - const postCompletionNotes = screen.getByTestId( - 'actionItemsStatusChangeNotes', - ); - fireEvent.change(postCompletionNotes, { target: { value: '' } }); - userEvent.type( - postCompletionNotes, - 'this action item has been completed successfully', - ); - - await waitFor(() => { - expect( - screen.getByTestId('actionItemStatusChangeSubmitBtn'), - ).toBeInTheDocument(); - }); - expect( - screen.getByTestId('actionItemStatusChangeSubmitBtn'), - ).toHaveTextContent(translations.markCompletion); - userEvent.click(screen.getByTestId('actionItemStatusChangeSubmitBtn')); - - await waitFor(() => { - expect(toast.success).toBeCalledWith(translations.successfulUpdation); - }); - - await waitFor(() => { - expect( - screen.getAllByTestId('actionItemStatusChangeCheckbox')[1], - ).toBeInTheDocument(); - }); - userEvent.click(screen.getAllByTestId('actionItemStatusChangeCheckbox')[1]); - - await waitFor(() => { - expect( - screen.getByTestId('actionItemsStatusChangeNotes'), - ).toBeInTheDocument(); - }); - - const preCompletionNotes = screen.getByTestId( - 'actionItemsStatusChangeNotes', - ); - fireEvent.change(preCompletionNotes, { target: { value: '' } }); - userEvent.type( - preCompletionNotes, - 'this action item has been made active again', - ); - - await waitFor(() => { - expect( - screen.getByTestId('actionItemStatusChangeSubmitBtn'), - ).toBeInTheDocument(); - }); - expect( - screen.getByTestId('actionItemStatusChangeSubmitBtn'), - ).toHaveTextContent(translations.makeActive); - userEvent.click(screen.getByTestId('actionItemStatusChangeSubmitBtn')); - - await waitFor(() => { - expect(toast.success).toBeCalledWith(translations.successfulUpdation); - }); - }); - - test('deletes the action item and toasts success', async () => { - render( - - - - - - - - - - - , - ); - - await wait(); - - await waitFor(() => { - expect( - screen.getAllByTestId('previewActionItemModalBtn')[0], - ).toBeInTheDocument(); - }); - userEvent.click(screen.getAllByTestId('previewActionItemModalBtn')[0]); - - await waitFor(() => { - return expect( - screen.findByTestId('previewActionItemModalCloseBtn'), - ).resolves.toBeInTheDocument(); - }); - - await waitFor(() => { - expect( - screen.getByTestId('deleteActionItemPreviewModalBtn'), - ).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('deleteActionItemPreviewModalBtn')); - - await waitFor(() => { - return expect( - screen.findByTestId('actionItemDeleteModalCloseBtn'), - ).resolves.toBeInTheDocument(); - }); - - userEvent.click(screen.getByTestId('deleteActionItemBtn')); - - await waitFor(() => { - expect(toast.success).toBeCalledWith(translations.successfulDeletion); - }); - }); - - test('toasts error on unsuccessful deletion', async () => { - render( - - - - - - - - - - - , - ); - - await wait(); - - await waitFor(() => { - expect( - screen.getAllByTestId('previewActionItemModalBtn')[0], - ).toBeInTheDocument(); - }); - userEvent.click(screen.getAllByTestId('previewActionItemModalBtn')[0]); - - await waitFor(() => { - return expect( - screen.findByTestId('previewActionItemModalCloseBtn'), - ).resolves.toBeInTheDocument(); - }); - - await waitFor(() => { - expect( - screen.getByTestId('deleteActionItemPreviewModalBtn'), - ).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('deleteActionItemPreviewModalBtn')); - - await waitFor(() => { - return expect( - screen.findByTestId('actionItemDeleteModalCloseBtn'), - ).resolves.toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('deleteActionItemBtn')); - - await waitFor(() => { - expect(toast.error).toHaveBeenCalled(); - }); - }); - - test('shows the overlay text on action item notes', async () => { - const { getAllByTestId } = render( - - - - - - - - - - - , - ); - - await wait(); - - await waitFor(() => { - expect( - screen.getAllByTestId('actionItemPreCompletionNotesOverlay')[0], - ).toBeInTheDocument(); - }); - - await waitFor(() => { - fireEvent.mouseEnter( - getAllByTestId('actionItemPreCompletionNotesOverlay')[0], - ); - }); - - await waitFor(() => { - expect(screen.getByTestId('popover-actionItem1')).toBeInTheDocument(); - }); - - await waitFor(() => { - fireEvent.mouseLeave( - getAllByTestId('actionItemPreCompletionNotesOverlay')[0], - ); - }); - - await waitFor(() => { - fireEvent.mouseEnter( - getAllByTestId('actionItemPostCompletionNotesOverlay')[0], - ); - }); - - await waitFor(() => { - expect(screen.getByTestId('popover-actionItem2')).toBeInTheDocument(); - }); - - await waitFor(() => { - fireEvent.mouseLeave( - getAllByTestId('actionItemPostCompletionNotesOverlay')[0], - ); - }); - }); - - test('Action Items loads with correct headers', async () => { - render( - - - - - - - - - , - ); - - await wait(); - - const actionItemHeaders = screen.getByTestId('actionItemsHeader'); - expect(actionItemHeaders).toBeInTheDocument(); - expect(screen.getByText(translations.assignee)).toBeInTheDocument(); - expect( - screen.getByText(translations.actionItemCategory), - ).toBeInTheDocument(); - expect( - screen.getByText(translations.preCompletionNotes), - ).toBeInTheDocument(); - expect( - screen.getByText(translations.postCompletionNotes), - ).toBeInTheDocument(); - expect(screen.getByText(translations.options)).toBeInTheDocument(); - }); -}); diff --git a/src/components/ActionItems/ActionItemsContainer.tsx b/src/components/ActionItems/ActionItemsContainer.tsx deleted file mode 100644 index 42e57f3822..0000000000 --- a/src/components/ActionItems/ActionItemsContainer.tsx +++ /dev/null @@ -1,499 +0,0 @@ -import React, { useState } from 'react'; -import dayjs from 'dayjs'; -import type { ChangeEvent } from 'react'; -import { - Button, - Col, - Form, - Modal, - OverlayTrigger, - Popover, - Row, -} from 'react-bootstrap'; -import { useTranslation } from 'react-i18next'; -import { toast } from 'react-toastify'; - -import { - DELETE_ACTION_ITEM_MUTATION, - UPDATE_ACTION_ITEM_MUTATION, -} from 'GraphQl/Mutations/mutations'; -import { useMutation } from '@apollo/client'; - -import type { - InterfaceActionItemInfo, - InterfaceMemberInfo, -} from 'utils/interfaces'; -import styles from './ActionItemsContainer.module.css'; -import ActionItemUpdateModal from '../../screens/OrganizationActionItems/ActionItemUpdateModal'; -import ActionItemPreviewModal from '../../screens/OrganizationActionItems/ActionItemPreviewModal'; -import ActionItemDeleteModal from '../../screens/OrganizationActionItems/ActionItemDeleteModal'; -import { Link } from 'react-router-dom'; - -function actionItemsContainer({ - actionItemsConnection, - actionItemsData, - membersData, - actionItemsRefetch, -}: { - actionItemsConnection: 'Organization' | 'Event'; - actionItemsData: InterfaceActionItemInfo[] | undefined; - membersData: InterfaceMemberInfo[] | undefined; - actionItemsRefetch: () => void; -}): JSX.Element { - const { t } = useTranslation('translation', { - keyPrefix: 'organizationActionItems', - }); - const { t: tCommon } = useTranslation('common'); - - const [actionItemPreviewModalIsOpen, setActionItemPreviewModalIsOpen] = - useState(false); - const [actionItemUpdateModalIsOpen, setActionItemUpdateModalIsOpen] = - useState(false); - const [actionItemDeleteModalIsOpen, setActionItemDeleteModalIsOpen] = - useState(false); - const [actionItemStatusModal, setActionItemStatusModal] = useState(false); - const [isActionItemCompleted, setIsActionItemCompleted] = useState(false); - - const [assignmentDate, setAssignmentDate] = useState(new Date()); - const [dueDate, setDueDate] = useState(new Date()); - const [completionDate, setCompletionDate] = useState(new Date()); - const [actionItemId, setActionItemId] = useState(''); - const [actionItemNotes, setActionItemNotes] = useState(''); - - const [formState, setFormState] = useState({ - assignee: '', - assigner: '', - assigneeId: '', - preCompletionNotes: '', - postCompletionNotes: '', - isCompleted: false, - }); - - const showPreviewModal = (actionItem: InterfaceActionItemInfo): void => { - setActionItemState(actionItem); - setActionItemPreviewModalIsOpen(true); - }; - - const showUpdateModal = (): void => { - setActionItemUpdateModalIsOpen(!actionItemUpdateModalIsOpen); - }; - - const hidePreviewModal = (): void => { - setActionItemPreviewModalIsOpen(false); - }; - - const hideUpdateModal = (): void => { - setActionItemId(''); - setActionItemUpdateModalIsOpen(!actionItemUpdateModalIsOpen); - }; - - const toggleDeleteModal = (): void => { - setActionItemDeleteModalIsOpen(!actionItemDeleteModalIsOpen); - }; - - const [updateActionItem] = useMutation(UPDATE_ACTION_ITEM_MUTATION); - - const updateActionItemHandler = async ( - e: ChangeEvent, - ): Promise => { - e.preventDefault(); - try { - await updateActionItem({ - variables: { - actionItemId, - assigneeId: formState.assigneeId, - preCompletionNotes: formState.preCompletionNotes, - postCompletionNotes: formState.postCompletionNotes, - dueDate: dayjs(dueDate).format('YYYY-MM-DD'), - completionDate: dayjs(completionDate).format('YYYY-MM-DD'), - isCompleted: formState.isCompleted, - }, - }); - - actionItemsRefetch(); - hideUpdateModal(); - toast.success(t('successfulUpdation')); - } catch (error: unknown) { - if (error instanceof Error) { - toast.error(error.message); - console.log(error.message); - } - } - }; - - const [removeActionItem] = useMutation(DELETE_ACTION_ITEM_MUTATION); - const deleteActionItemHandler = async (): Promise => { - try { - await removeActionItem({ - variables: { - actionItemId, - }, - }); - - actionItemsRefetch(); - toggleDeleteModal(); - toast.success(t('successfulDeletion')); - } catch (error: unknown) { - if (error instanceof Error) { - toast.error(error.message); - console.log(error.message); - } - } - }; - - const handleEditClick = (actionItem: InterfaceActionItemInfo): void => { - setActionItemState(actionItem); - showUpdateModal(); - }; - - const handleActionItemStatusChange = ( - actionItem: InterfaceActionItemInfo, - ): void => { - actionItem = { ...actionItem, isCompleted: !actionItem.isCompleted }; - setIsActionItemCompleted(!actionItem.isCompleted); - setActionItemState(actionItem); - setActionItemStatusModal(true); - }; - - const hideActionItemStatusModal = (): void => { - setActionItemStatusModal(false); - }; - - const setActionItemState = (actionItem: InterfaceActionItemInfo): void => { - setFormState({ - ...formState, - assignee: `${actionItem.assignee.firstName} ${actionItem.assignee.lastName}`, - assigner: `${actionItem.assigner.firstName} ${actionItem.assigner.lastName}`, - assigneeId: actionItem.assignee._id, - preCompletionNotes: actionItem.preCompletionNotes, - postCompletionNotes: actionItem.postCompletionNotes, - isCompleted: actionItem.isCompleted, - }); - setActionItemId(actionItem._id); - setDueDate(actionItem.dueDate); - setAssignmentDate(actionItem.assignmentDate); - setCompletionDate(actionItem.completionDate); - }; - - const popover = ( - - {actionItemNotes} - - ); - - return ( - <> -

    -
    - - -
    {'#'}
    - - -
    {t('assignee')}
    - - - {t('actionItemCategory')} - - -
    {t('preCompletionNotes')}
    - - -
    {t('postCompletionNotes')}
    - - -
    {t('options')}
    - -
    -
    - -
    - {actionItemsData?.map((actionItem, index) => ( -
    - - - {index + 1} - - - - {`${actionItem.assignee.firstName} ${actionItem.assignee.lastName}`} - - - - {actionItem.actionItemCategory.name} - - -
    - - { - setActionItemId(actionItem._id); - setActionItemNotes(actionItem.preCompletionNotes); - }} - > - {actionItem.preCompletionNotes.length > 25 - ? `${actionItem.preCompletionNotes.substring(0, 25)}...` - : actionItem.preCompletionNotes} - - -
    - - -
    - {actionItem.isCompleted ? ( - - { - setActionItemId(actionItem._id); - setActionItemNotes(actionItem.postCompletionNotes); - }} - className="ms-3 " - > - {actionItem.postCompletionNotes?.length > 25 - ? `${actionItem.postCompletionNotes.substring(0, 25)}...` - : actionItem.postCompletionNotes} - - - ) : ( - - {t('actionItemActive')} - - )} -
    - - -
    - handleActionItemStatusChange(actionItem)} - /> - - -
    - -
    - - {index !== actionItemsData.length - 1 &&
    } -
    - ))} - - {actionItemsData?.length === 0 && ( -
    - {t('noActionItems')} -
    - )} -
    -
    - - {/* action item status change modal */} - - -

    {t('actionItemStatus')}

    - -
    - -
    - - {isActionItemCompleted - ? t('preCompletionNotes') - : t('postCompletionNotes')} - - { - if (isActionItemCompleted) { - setFormState({ - ...formState, - preCompletionNotes: e.target.value, - }); - } else { - setFormState({ - ...formState, - postCompletionNotes: e.target.value, - }); - } - }} - /> - - -
    -
    - - {/* preview modal */} - - - {/* Update Modal */} - - - {/* Delete Modal */} - - - ); -} - -export default actionItemsContainer; diff --git a/src/components/ActionItems/ActionItemsContainerMocks.ts b/src/components/ActionItems/ActionItemsContainerMocks.ts deleted file mode 100644 index a2dc20c5eb..0000000000 --- a/src/components/ActionItems/ActionItemsContainerMocks.ts +++ /dev/null @@ -1,112 +0,0 @@ -import { - UPDATE_ACTION_ITEM_MUTATION, - DELETE_ACTION_ITEM_MUTATION, -} from 'GraphQl/Mutations/mutations'; - -export const MOCKS = [ - { - request: { - query: UPDATE_ACTION_ITEM_MUTATION, - variables: { - actionItemId: 'actionItem1', - assigneeId: 'user2', - preCompletionNotes: 'pre completion notes edited', - postCompletionNotes: 'Post Completion Notes', - dueDate: '2024-02-14', - completionDate: '2024-02-21', - isCompleted: false, - }, - }, - result: { - data: { - updateActionItem: { - _id: 'actionItem1', - }, - }, - }, - }, - { - request: { - query: UPDATE_ACTION_ITEM_MUTATION, - variables: { - actionItemId: 'actionItem1', - assigneeId: 'user1', - preCompletionNotes: 'Pre Completion Notes', - postCompletionNotes: 'this action item has been completed successfully', - dueDate: '2024-02-21', - completionDate: '2024-02-21', - isCompleted: true, - }, - }, - result: { - data: { - updateActionItem: { - _id: 'actionItem1', - }, - }, - }, - }, - { - request: { - query: UPDATE_ACTION_ITEM_MUTATION, - variables: { - actionItemId: 'actionItem2', - assigneeId: 'user1', - preCompletionNotes: 'this action item has been made active again', - postCompletionNotes: 'Post Completion Notes', - dueDate: '2024-02-21', - completionDate: '2024-02-21', - isCompleted: false, - }, - }, - result: { - data: { - updateActionItem: { - _id: 'actionItem1', - }, - }, - }, - }, - { - request: { - query: DELETE_ACTION_ITEM_MUTATION, - variables: { - actionItemId: 'actionItem1', - }, - }, - result: { - data: { - removeActionItem: { - _id: 'actionItem1', - }, - }, - }, - }, -]; - -export const MOCKS_ERROR_MUTATIONS = [ - { - request: { - query: UPDATE_ACTION_ITEM_MUTATION, - variables: { - actionItemId: 'actionItem1', - assigneeId: 'user2', - preCompletionNotes: 'pre completion notes edited', - postCompletionNotes: '', - dueDate: '2024-02-14', - completionDate: '2024-02-21', - isCompleted: false, - }, - }, - error: new Error('Mock Graphql Error'), - }, - { - request: { - query: DELETE_ACTION_ITEM_MUTATION, - variables: { - actionItemId: 'actionItem1', - }, - }, - error: new Error('Mock Graphql Error'), - }, -]; diff --git a/src/components/ActionItems/ActionItemsContainerProps.ts b/src/components/ActionItems/ActionItemsContainerProps.ts deleted file mode 100644 index 19ba6f6369..0000000000 --- a/src/components/ActionItems/ActionItemsContainerProps.ts +++ /dev/null @@ -1,131 +0,0 @@ -type ActionItemsConnectionType = 'Organization' | 'Event'; - -export const props = { - actionItemsConnection: 'Organization' as ActionItemsConnectionType, - actionItemsData: [ - { - _id: 'actionItem1', - assignee: { - _id: 'user1', - firstName: 'Harve', - lastName: 'Lance', - }, - actionItemCategory: { - _id: 'actionItemCategory1', - name: 'ActionItemCategory 1', - }, - preCompletionNotes: 'Pre Completion Notes', - postCompletionNotes: 'Post Completion Notes', - assignmentDate: new Date('2024-02-14'), - dueDate: new Date('2024-02-21'), - completionDate: new Date('2024-02-21'), - isCompleted: false, - assigner: { - _id: 'user0', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - event: { - _id: 'event1', - title: 'event 1', - }, - creator: { - _id: 'user0', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - }, - { - _id: 'actionItem2', - assignee: { - _id: 'user1', - firstName: 'Harve', - lastName: 'Lance', - }, - actionItemCategory: { - _id: 'actionItemCategory1', - name: 'ActionItemCategory 1', - }, - preCompletionNotes: 'Pre Completion Notes', - postCompletionNotes: 'Post Completion Notes', - assignmentDate: new Date('2024-02-14'), - dueDate: new Date('2024-02-21'), - completionDate: new Date('2024-02-21'), - isCompleted: true, - assigner: { - _id: 'user0', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - event: { - _id: 'event1', - title: 'event 1', - }, - creator: { - _id: 'user0', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - }, - { - _id: 'actionItem3', - assignee: { - _id: 'user1', - firstName: 'Harve', - lastName: 'Lance', - }, - actionItemCategory: { - _id: 'actionItemCategory1', - name: 'ActionItemCategory 1', - }, - preCompletionNotes: 'Pre Completion Notes more than 25 characters', - postCompletionNotes: 'Post Completion Notes more than 25 characters', - assignmentDate: new Date('2024-02-14'), - dueDate: new Date('2024-02-21'), - completionDate: new Date('2024-02-21'), - isCompleted: true, - assigner: { - _id: 'user0', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - event: { - _id: 'event1', - title: 'event 1', - }, - creator: { - _id: 'user0', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - }, - ], - membersData: [ - { - _id: 'user1', - firstName: 'Harve', - lastName: 'Lance', - email: 'harve@example.com', - image: '', - organizationsBlockedBy: [], - createdAt: '2024-02-14', - }, - { - _id: 'user2', - firstName: 'Scott', - lastName: 'Norris', - email: 'scott@example.com', - image: '', - organizationsBlockedBy: [], - createdAt: '2024-02-14', - }, - ], - actionItemsRefetch: jest.fn(), -}; - -export const props2 = { - actionItemsConnection: 'Organization' as ActionItemsConnectionType, - actionItemsData: [], - membersData: [], - actionItemsRefetch: jest.fn(), -}; diff --git a/src/components/ActionItems/ActionItemsModal.test.tsx b/src/components/ActionItems/ActionItemsModal.test.tsx deleted file mode 100644 index 01a15ee6aa..0000000000 --- a/src/components/ActionItems/ActionItemsModal.test.tsx +++ /dev/null @@ -1,294 +0,0 @@ -import React from 'react'; -import { - act, - fireEvent, - render, - screen, - waitFor, -} from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import { MockedProvider } from '@apollo/react-testing'; -import { ActionItemsModal } from './ActionItemsModal'; -import { BrowserRouter } from 'react-router-dom'; -import { Provider } from 'react-redux'; -import { store } from 'state/store'; -import { I18nextProvider } from 'react-i18next'; -import i18nForTest from 'utils/i18nForTest'; -import { LocalizationProvider } from '@mui/x-date-pickers'; -import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; -import { toast } from 'react-toastify'; - -import { - MOCKS_ERROR_ACTION_ITEM_CATEGORY_LIST_QUERY, - MOCKS_ERROR_ACTION_ITEM_LIST_QUERY, - MOCKS_ERROR_MEMBERS_LIST_QUERY, - MOCKS_ERROR_MUTATIONS, -} from '../../screens/OrganizationActionItems/OrganizationActionItemsErrorMocks'; -import { MOCKS } from '../../screens/OrganizationActionItems/OrganizationActionItemMocks'; -import { StaticMockLink } from 'utils/StaticMockLink'; - -jest.mock('react-toastify', () => ({ - toast: { - success: jest.fn(), - error: jest.fn(), - }, -})); - -jest.mock('@mui/x-date-pickers/DateTimePicker', () => { - return { - DateTimePicker: jest.requireActual( - '@mui/x-date-pickers/DesktopDateTimePicker', - ).DesktopDateTimePicker, - }; -}); - -async function wait(ms = 100): Promise { - await act(() => { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); - }); -} - -const link = new StaticMockLink(MOCKS, true); -const link2 = new StaticMockLink( - MOCKS_ERROR_ACTION_ITEM_CATEGORY_LIST_QUERY, - true, -); -const link3 = new StaticMockLink(MOCKS_ERROR_MEMBERS_LIST_QUERY, true); -const link4 = new StaticMockLink(MOCKS_ERROR_ACTION_ITEM_LIST_QUERY, true); -const link5 = new StaticMockLink(MOCKS_ERROR_MUTATIONS, true); - -const translations = JSON.parse( - JSON.stringify( - i18nForTest.getDataByLanguage('en')?.translation.organizationActionItems, - ), -); - -describe('Testing Check In Attendees Modal', () => { - const formData = { - actionItemCategory: 'ActionItemCategory 1', - assignee: 'Harve Lance', - preCompletionNotes: 'pre completion notes', - dueDate: '02/14/2024', - }; - - const props = { - show: true, - eventId: 'event1', - orgId: '123', - handleClose: jest.fn(), - }; - - test('The modal should be rendered properly', async () => { - render( - - - - - - - - - - - , - ); - - await waitFor(() => - expect(screen.queryByTestId('modal-title')).toBeInTheDocument(), - ); - - await waitFor(() => { - return expect( - screen.findByTestId('createEventActionItemBtn'), - ).resolves.toBeInTheDocument(); - }); - }); - - test('render error component on unsuccessful action item category list query', async () => { - const { queryByText } = render( - - - - - - - - - , - ); - - await wait(); - - await waitFor(() => { - expect(queryByText('createEventActionItemBtn')).not.toBeInTheDocument(); - }); - }); - - test('render error component on unsuccessful member list query', async () => { - const { queryByText } = render( - - - - - - - - - , - ); - - await wait(); - - await waitFor(() => { - expect(queryByText('createEventActionItemBtn')).not.toBeInTheDocument(); - }); - }); - - test('render error component on unsuccessful action items list query', async () => { - const { queryByText } = render( - - - - - - - - - , - ); - - await wait(); - - await waitFor(() => { - expect(queryByText('createEventActionItemBtn')).not.toBeInTheDocument(); - }); - }); - - test('creates new action item associated with the event', async () => { - render( - - - - - - - - - - - , - ); - - await wait(); - - await waitFor(() => { - expect( - screen.getByTestId('createEventActionItemBtn'), - ).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('createEventActionItemBtn')); - - await waitFor(() => { - return expect( - screen.findByTestId('createActionItemModalCloseBtn'), - ).resolves.toBeInTheDocument(); - }); - - await waitFor(() => { - expect( - screen.getByTestId('formSelectActionItemCategory'), - ).toBeInTheDocument(); - }); - - userEvent.selectOptions( - screen.getByTestId('formSelectActionItemCategory'), - formData.actionItemCategory, - ); - - userEvent.selectOptions( - screen.getByTestId('formSelectAssignee'), - formData.assignee, - ); - - userEvent.type( - screen.getByPlaceholderText(translations.preCompletionNotes), - formData.preCompletionNotes, - ); - - const dueDatePicker = screen.getByLabelText(translations.dueDate); - fireEvent.change(dueDatePicker, { - target: { value: formData.dueDate }, - }); - - userEvent.click(screen.getByTestId('createActionItemFormSubmitBtn')); - - await waitFor(() => { - expect(toast.success).toBeCalledWith(translations.successfulCreation); - }); - }); - - test('toasts error on unsuccessful creation', async () => { - render( - - - - - - - - - - - , - ); - - await wait(); - - await waitFor(() => { - expect( - screen.getByTestId('createEventActionItemBtn'), - ).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('createEventActionItemBtn')); - - await waitFor(() => { - return expect( - screen.findByTestId('createActionItemModalCloseBtn'), - ).resolves.toBeInTheDocument(); - }); - - await waitFor(() => { - expect( - screen.getByTestId('formSelectActionItemCategory'), - ).toBeInTheDocument(); - }); - - userEvent.selectOptions( - screen.getByTestId('formSelectActionItemCategory'), - formData.actionItemCategory, - ); - - userEvent.selectOptions( - screen.getByTestId('formSelectAssignee'), - formData.assignee, - ); - - userEvent.type( - screen.getByPlaceholderText(translations.preCompletionNotes), - formData.preCompletionNotes, - ); - - const dueDatePicker = screen.getByLabelText(translations.dueDate); - fireEvent.change(dueDatePicker, { - target: { value: formData.dueDate }, - }); - - userEvent.click(screen.getByTestId('createActionItemFormSubmitBtn')); - - await waitFor(() => { - expect(toast.error).toHaveBeenCalled(); - }); - }); -}); diff --git a/src/components/ActionItems/ActionItemsModal.tsx b/src/components/ActionItems/ActionItemsModal.tsx deleted file mode 100644 index 8b8cafba4a..0000000000 --- a/src/components/ActionItems/ActionItemsModal.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React from 'react'; -import { Modal } from 'react-bootstrap'; -import styles from 'components/ActionItems/ActionItemsWrapper.module.css'; -import { ActionItemsModalBody } from './ActionItemsModalBody'; -import { useTranslation } from 'react-i18next'; - -export interface InterfaceModalProp { - show: boolean; - eventId: string; - orgId: string; - handleClose: () => void; -} - -export const ActionItemsModal = (props: InterfaceModalProp): JSX.Element => { - const { t } = useTranslation('translation', { - keyPrefix: 'organizationActionItems', - }); - - return ( - <> - - - - {t('eventActionItems')} - - - - - - - - ); -}; diff --git a/src/components/ActionItems/ActionItemsModalBody.tsx b/src/components/ActionItems/ActionItemsModalBody.tsx deleted file mode 100644 index 1aeb536b8b..0000000000 --- a/src/components/ActionItems/ActionItemsModalBody.tsx +++ /dev/null @@ -1,218 +0,0 @@ -import React, { useState } from 'react'; -import type { ChangeEvent } from 'react'; -import { Button } from 'react-bootstrap'; -import { useMutation, useQuery } from '@apollo/client'; -import { - ACTION_ITEM_CATEGORY_LIST, - ACTION_ITEM_LIST, - MEMBERS_LIST, -} from 'GraphQl/Queries/Queries'; -import styles from 'components/ActionItems/ActionItemsWrapper.module.css'; -import type { - InterfaceActionItemCategoryList, - InterfaceActionItemList, - InterfaceMembersList, -} from 'utils/interfaces'; - -import ActionItemsContainer from 'components/ActionItems/ActionItemsContainer'; -import Loader from 'components/Loader/Loader'; -import { WarningAmberRounded } from '@mui/icons-material'; -import { CREATE_ACTION_ITEM_MUTATION } from 'GraphQl/Mutations/ActionItemMutations'; -import dayjs from 'dayjs'; -import { toast } from 'react-toastify'; -import ActionItemCreateModal from 'screens/OrganizationActionItems/ActionItemCreateModal'; -import { useTranslation } from 'react-i18next'; - -export const ActionItemsModalBody = ({ - organizationId, - eventId, -}: { - organizationId: string; - eventId: string; -}): JSX.Element => { - const { t } = useTranslation('translation', { - keyPrefix: 'organizationActionItems', - }); - const { t: tCommon } = useTranslation('common'); - - const [dueDate, setDueDate] = useState(new Date()); - const [actionItemCreateModalIsOpen, setActionItemCreateModalIsOpen] = - useState(false); - - const [formState, setFormState] = useState({ - actionItemCategoryId: '', - assigneeId: '', - preCompletionNotes: '', - }); - - const { - data: actionItemCategoriesData, - loading: actionItemCategoriesLoading, - error: actionItemCategoriesError, - }: { - data: InterfaceActionItemCategoryList | undefined; - loading: boolean; - error?: Error | undefined; - } = useQuery(ACTION_ITEM_CATEGORY_LIST, { - variables: { - organizationId, - }, - notifyOnNetworkStatusChange: true, - }); - - const { - data: membersData, - loading: membersLoading, - error: membersError, - }: { - data: InterfaceMembersList | undefined; - loading: boolean; - error?: Error | undefined; - } = useQuery(MEMBERS_LIST, { - variables: { id: organizationId }, - }); - - const { - data: actionItemsData, - loading: actionItemsLoading, - error: actionItemsError, - refetch: actionItemsRefetch, - }: { - data: InterfaceActionItemList | undefined; - loading: boolean; - error?: Error | undefined; - refetch: () => void; - } = useQuery(ACTION_ITEM_LIST, { - variables: { - organizationId, - eventId, - orderBy: 'createdAt_DESC', - }, - notifyOnNetworkStatusChange: true, - }); - - const [createActionItem] = useMutation(CREATE_ACTION_ITEM_MUTATION); - - const createActionItemHandler = async ( - e: ChangeEvent, - ): Promise => { - e.preventDefault(); - try { - await createActionItem({ - variables: { - assigneeId: formState.assigneeId, - actionItemCategoryId: formState.actionItemCategoryId, - eventId, - preCompletionNotes: formState.preCompletionNotes, - dueDate: dayjs(dueDate).format('YYYY-MM-DD'), - }, - }); - - setFormState({ - assigneeId: '', - actionItemCategoryId: '', - preCompletionNotes: '', - }); - - setDueDate(new Date()); - - actionItemsRefetch(); - hideCreateModal(); - toast.success(t('successfulCreation')); - } catch (error: unknown) { - if (error instanceof Error) { - toast.error(error.message); - console.log(error.message); - } - } - }; - - const showCreateModal = (): void => { - setActionItemCreateModalIsOpen(!actionItemCreateModalIsOpen); - }; - - const hideCreateModal = (): void => { - setActionItemCreateModalIsOpen(!actionItemCreateModalIsOpen); - }; - - if (actionItemCategoriesLoading || membersLoading || actionItemsLoading) { - return ; - } - - if (actionItemCategoriesError || membersError || actionItemsError) { - return ( -
    - -
    - Error occured while loading{' '} - {actionItemCategoriesError - ? 'Action Item Categories' - : membersError - ? 'Members List' - : 'Action Items List'}{' '} - Data -
    - {actionItemCategoriesError - ? actionItemCategoriesError.message - : membersError - ? membersError.message - : actionItemsError?.message} -
    -
    - ); - } - - const actionItemCategories = - actionItemCategoriesData?.actionItemCategoriesByOrganization.filter( - (category) => !category.isDisabled, - ); - - const completedActionItemsCount = - actionItemsData?.actionItemsByOrganization.reduce( - (acc, item) => (item.isCompleted === true ? acc + 1 : acc), - 0, - ); - - return ( - <> -
    - - Status: - {actionItemsData?.actionItemsByOrganization.length} action items - assigned, {completedActionItemsCount} completed - - - -
    - - - - {/* Create Modal */} - - - ); -}; diff --git a/src/components/ActionItems/ActionItemsWrapper.module.css b/src/components/ActionItems/ActionItemsWrapper.module.css deleted file mode 100644 index 125db8a125..0000000000 --- a/src/components/ActionItems/ActionItemsWrapper.module.css +++ /dev/null @@ -1,53 +0,0 @@ -.actionItemsModal { - margin: auto; - max-width: 85%; -} - -button .iconWrapper { - width: 32px; - padding-right: 4px; - margin-right: 4px; -} - -button .iconWrapperSm { - width: 32px; - display: flex; - justify-content: center; - align-items: center; -} - -.errorIcon { - transform: scale(1.5); - color: var(--bs-danger); - margin-bottom: 1rem; -} - -.greenregbtn { - margin: 1rem 0 0; - margin-top: 0; - margin-right: 4px; - border: 1px solid var(--bs-gray-300); - box-shadow: 0 2px 2px var(--bs-gray-300); - padding: 10px 10px; - border-radius: 5px; - background-color: var(--bs-primary); - width: 100%; - font-size: 16px; - color: var(--bs-white); - outline: none; - font-weight: 600; - cursor: pointer; - transition: - transform 0.2s, - box-shadow 0.2s; - max-width: 100px; -} - -.message { - margin-top: 15%; - margin-bottom: 15%; - display: flex; - justify-content: center; - align-items: center; - flex-direction: column; -} diff --git a/src/components/ActionItems/ActionItemsWrapper.test.tsx b/src/components/ActionItems/ActionItemsWrapper.test.tsx deleted file mode 100644 index 7b27e7ccd3..0000000000 --- a/src/components/ActionItems/ActionItemsWrapper.test.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import React from 'react'; -import { act, render, screen, waitFor } from '@testing-library/react'; -import { MockedProvider } from '@apollo/react-testing'; -import { ActionItemsWrapper } from './ActionItemsWrapper'; -import { BrowserRouter } from 'react-router-dom'; -import { Provider } from 'react-redux'; -import { store } from 'state/store'; -import { I18nextProvider } from 'react-i18next'; -import i18nForTest from 'utils/i18nForTest'; -import { ToastContainer } from 'react-toastify'; -import { LocalizationProvider } from '@mui/x-date-pickers'; -import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; -import { StaticMockLink } from 'utils/StaticMockLink'; -import userEvent from '@testing-library/user-event'; -import { MOCKS } from '../../screens/OrganizationActionItems/OrganizationActionItemMocks'; - -async function wait(ms = 100): Promise { - await act(() => { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); - }); -} - -const link = new StaticMockLink(MOCKS, true); - -describe('Testing Action Items Wrapper', () => { - const props = { - eventId: 'event1', - orgId: '123', - }; - - test('The button to open and close the modal should work properly', async () => { - render( - - - - - - - - - - - - , - ); - - await wait(); - - await waitFor(() => { - expect( - screen.getByLabelText('eventDashboardActionItems'), - ).toBeInTheDocument(); - }); - - userEvent.click(screen.getByLabelText('eventDashboardActionItems')); - - await waitFor(() => - expect(screen.queryByTestId('modal-title')).toBeInTheDocument(), - ); - - await waitFor(() => { - expect(screen.getByLabelText('Close')).toBeInTheDocument(); - }); - - userEvent.click(screen.getByLabelText('Close')); - - await waitFor(() => - expect(screen.queryByTestId('modal-title')).not.toBeInTheDocument(), - ); - }); -}); diff --git a/src/components/ActionItems/ActionItemsWrapper.tsx b/src/components/ActionItems/ActionItemsWrapper.tsx deleted file mode 100644 index b44e0782b2..0000000000 --- a/src/components/ActionItems/ActionItemsWrapper.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import React, { useState } from 'react'; -import { ActionItemsModal } from './ActionItemsModal'; -import { Button } from 'react-bootstrap'; -import IconComponent from 'components/IconComponent/IconComponent'; -import styles from './ActionItemsWrapper.module.css'; -import { useTranslation } from 'react-i18next'; - -type PropType = { - orgId: string; - eventId: string; -}; - -export const ActionItemsWrapper = (props: PropType): JSX.Element => { - const { t } = useTranslation('translation', { - keyPrefix: 'organizationActionItems', - }); - - const [showModal, setShowModal] = useState(false); - - return ( - <> - - {showModal && ( - setShowModal(false)} - orgId={props.orgId} - eventId={props.eventId} - /> - )} - - ); -}; diff --git a/src/components/AddOn/AddOn.test.tsx b/src/components/AddOn/AddOn.test.tsx index 8313fefcb1..68475e8196 100644 --- a/src/components/AddOn/AddOn.test.tsx +++ b/src/components/AddOn/AddOn.test.tsx @@ -15,6 +15,14 @@ describe('Testing Addon component', () => { children: 'This is a dummy text', }; + test('should render with default props', () => { + const { getByTestId } = render(); + const container = getByTestId('pluginContainer'); + expect(container).toBeInTheDocument(); + expect(container).toHaveClass('plugin-container'); + expect(container).toHaveTextContent('Default text'); + }); + test('should render props and text elements test for the page component', () => { const { getByTestId, getByText } = render( diff --git a/src/components/AddOn/AddOn.tsx b/src/components/AddOn/AddOn.tsx index 4e73c52b7c..850cc05ee4 100644 --- a/src/components/AddOn/AddOn.tsx +++ b/src/components/AddOn/AddOn.tsx @@ -2,35 +2,43 @@ import React from 'react'; import PropTypes from 'prop-types'; interface InterfaceAddOnProps { - extras: any; - name: string; - children: any; + extras?: any; + name?: string; + children?: React.ReactNode; } -// Validate Extras -function addOn({ children }: InterfaceAddOnProps): JSX.Element { +/** + * The AddOn component is used to wrap children within a plugin container. + * It also accepts additional properties (`extras` and `name`) to allow for + * extensibility and custom naming. + * + * @param props - The props for the AddOn component. + * @param extras - Additional properties for the AddOn component. + * @param name - The name for the AddOn component. + * @param children - The child elements to be rendered within the AddOn component. + * + * @returns The JSX element representing the AddOn component. + */ +function AddOn({ + children = 'Default text', + extras = {}, + name = '', +}: InterfaceAddOnProps): JSX.Element { return ( - <> -
    - {children} -
    - +
    + {children} +
    ); } -addOn.defaultProps = { - extras: {}, - name: '', - children: null, -}; - -addOn.propTypes = { +// PropTypes validation for the AddOn component +AddOn.propTypes = { extras: PropTypes.shape({ components: PropTypes.shape({}), actions: PropTypes.shape({}), }), name: PropTypes.string, - children: PropTypes.any, + children: PropTypes.node, }; -export default addOn; +export default AddOn; diff --git a/src/components/AddOn/core/AddOnEntry/AddOnEntry.test.tsx b/src/components/AddOn/core/AddOnEntry/AddOnEntry.test.tsx index c09840a8f0..3d800eb59f 100644 --- a/src/components/AddOn/core/AddOnEntry/AddOnEntry.test.tsx +++ b/src/components/AddOn/core/AddOnEntry/AddOnEntry.test.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { render } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; import { BrowserRouter } from 'react-router-dom'; import AddOnEntry from './AddOnEntry'; import { @@ -76,6 +76,32 @@ describe('Testing AddOnEntry', () => { expect(getByTestId('AddOnEntry')).toBeInTheDocument(); }); + test('uses default values for title and description when not provided', () => { + // Render the component with only required parameters + const mockGetInstalledPlugins = jest.fn(); + render( + + + + + + + + + , + ); + + const titleElement = screen.getByText('No title provided'); // This will check for the default empty string in the title + const descriptionElement = screen.getByText('Description not available'); // This will check for the default empty string in the description + expect(titleElement).toBeInTheDocument(); // Ensure the title element with default value exists + expect(descriptionElement).toBeInTheDocument(); // Ensure the description element with default value exists + }); + it('renders correctly', () => { const props = { id: '1', @@ -110,6 +136,7 @@ describe('Testing AddOnEntry', () => { expect(getByText('Test addon description')).toBeInTheDocument(); expect(getByText('Test User')).toBeInTheDocument(); }); + it('Uninstall Button works correctly', async () => { const props = { id: '1', diff --git a/src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx b/src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx index 6f2cdaf1dc..257917e2c2 100644 --- a/src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx +++ b/src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx @@ -1,5 +1,4 @@ import React, { useState } from 'react'; -import PropTypes from 'prop-types'; import styles from './AddOnEntry.module.css'; import { Button, Card, Spinner } from 'react-bootstrap'; import { UPDATE_INSTALL_STATUS_PLUGIN_MUTATION } from 'GraphQl/Mutations/mutations'; @@ -8,41 +7,78 @@ import { useTranslation } from 'react-i18next'; import { toast } from 'react-toastify'; import { Navigate, useParams } from 'react-router-dom'; +/** + * Props for the `addOnEntry` component. + */ interface InterfaceAddOnEntryProps { id: string; - enabled: boolean; - title: string; - description: string; + enabled?: boolean; // Optional props + title?: string; // Optional props + description?: string; // Optional props createdBy: string; - component: string; - modified: any; + component?: string; // Optional props + modified?: any; // Optional props uninstalledOrgs: string[]; getInstalledPlugins: () => any; } +/** + * A React component that represents an add-on entry, displaying its details and allowing installation or uninstallation. + * + * @param props - The properties for the component. + * @returns A JSX element containing the add-on entry. + * + * @example + * ```tsx + * {}} + * /> + * ``` + */ function addOnEntry({ id, - title, - description, + title = 'No title provided', // Default parameter + description = 'Description not available', // Default parameter createdBy, uninstalledOrgs, getInstalledPlugins, + // enabled = false, // Default parameter + // component = '', // Default parameter + // modified = null, // Default parameter }: InterfaceAddOnEntryProps): JSX.Element { + // Translation hook with namespace 'addOnEntry' const { t } = useTranslation('translation', { keyPrefix: 'addOnEntry' }); - //getting orgId from URL + + // Getting orgId from URL parameters const { orgId: currentOrg } = useParams(); if (!currentOrg) { + // If orgId is not present in the URL, navigate to the org list page return ; } + + // State to manage button loading state const [buttonLoading, setButtonLoading] = useState(false); + // State to manage local installation status of the add-on const [isInstalledLocal, setIsInstalledLocal] = useState( uninstalledOrgs.includes(currentOrg), ); - // const [addOrgAsUninstalled] = useMutation(UPDATE_ORG_STATUS_PLUGIN_MUTATION); + + // Mutation hook for updating the install status of the plugin const [addOrgAsUninstalled] = useMutation( UPDATE_INSTALL_STATUS_PLUGIN_MUTATION, ); + /** + * Function to toggle the installation status of the plugin. + */ const togglePluginInstall = async (): Promise => { setButtonLoading(true); await addOrgAsUninstalled({ @@ -52,8 +88,11 @@ function addOnEntry({ }, }); + // Toggle the local installation status setIsInstalledLocal(!isInstalledLocal); setButtonLoading(false); + + // Display a success message based on the new installation status const dialog: string = isInstalledLocal ? t('installMsg') : t('uninstallMsg'); @@ -110,20 +149,4 @@ function addOnEntry({ ); } -addOnEntry.defaultProps = { - enabled: false, - configurable: true, - title: '', - description: '', - isInstalled: false, -}; - -addOnEntry.propTypes = { - enabled: PropTypes.bool, - configurable: PropTypes.bool, - title: PropTypes.string, - description: PropTypes.string, - isInstalled: PropTypes.bool, -}; - export default addOnEntry; diff --git a/src/components/AddOn/core/AddOnRegister/AddOnRegister.test.tsx b/src/components/AddOn/core/AddOnRegister/AddOnRegister.test.tsx index 6df580aa76..b04b450977 100644 --- a/src/components/AddOn/core/AddOnRegister/AddOnRegister.test.tsx +++ b/src/components/AddOn/core/AddOnRegister/AddOnRegister.test.tsx @@ -1,5 +1,5 @@ -import React from 'react'; -import { act, render, screen, waitFor } from '@testing-library/react'; +import React, { act } from 'react'; +import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { MockedProvider } from '@apollo/react-testing'; import { ADD_PLUGIN_MUTATION } from 'GraphQl/Mutations/mutations'; @@ -41,7 +41,7 @@ const mocks = [ query: ADD_PLUGIN_MUTATION, variables: { pluginName: 'Test Plugin', - pluginCreatedBy: 'Test Creator', + pluginCreatedBy: 'AdminTest Creator', pluginDesc: 'Test Description', pluginInstallStatus: false, installedOrgs: ['id'], @@ -52,7 +52,7 @@ const mocks = [ createPlugin: { _id: '1', pluginName: 'Test Plugin', - pluginCreatedBy: 'Test Creator', + pluginCreatedBy: 'AdminTest Creator', pluginDesc: 'Test Description', }, }, @@ -100,26 +100,31 @@ describe('Testing AddOnRegister', () => { - {} + , ); - - await wait(100); - - userEvent.click(screen.getByRole('button', { name: /Add New/i })); - userEvent.type(screen.getByPlaceholderText(/Ex: Donations/i), 'myplugin'); - userEvent.type( - screen.getByPlaceholderText(/This Plugin enables UI for/i), - 'test description', - ); - userEvent.type( - screen.getByPlaceholderText(/Ex: john Doe/i), - 'test creator', - ); }); + // Wait for the button to be in the document + await waitFor(() => + expect( + screen.getByRole('button', { name: /Add New/i }), + ).toBeInTheDocument(), + ); + + // Simulate user interactions + userEvent.click(screen.getByRole('button', { name: /Add New/i })); + userEvent.type(screen.getByPlaceholderText(/Ex: Donations/i), 'myplugin'); + userEvent.type( + screen.getByPlaceholderText(/This Plugin enables UI for/i), + 'test description', + ); + userEvent.type( + screen.getByPlaceholderText(/Ex: john Doe/i), + 'test creator', + ); }); test('Expect toast.success to be called on successful plugin addition', async () => { @@ -135,22 +140,22 @@ describe('Testing AddOnRegister', () => {
    , ); - await waitFor(() => new Promise((resolve) => setTimeout(resolve, 0))); - - userEvent.click(screen.getByRole('button', { name: /Add New/i })); - await wait(100); - expect(screen.getByTestId('addonregisterBtn')).toBeInTheDocument(); - userEvent.type(screen.getByTestId('pluginName'), pluginData.pluginName); - userEvent.type( - screen.getByTestId('pluginCreatedBy'), - pluginData.pluginCreatedBy, - ); - userEvent.type(screen.getByTestId('pluginDesc'), pluginData.pluginDesc); - userEvent.click(screen.getByTestId('addonregisterBtn')); - - await wait(100); - expect(toast.success).toBeCalledWith('Plugin added Successfully'); }); + await waitFor(() => new Promise((resolve) => setTimeout(resolve, 0))); + + userEvent.click(screen.getByRole('button', { name: /Add New/i })); + await wait(100); + expect(screen.getByTestId('addonregisterBtn')).toBeInTheDocument(); + userEvent.type(screen.getByTestId('pluginName'), pluginData.pluginName); + userEvent.type( + screen.getByTestId('pluginCreatedBy'), + pluginData.pluginCreatedBy, + ); + userEvent.type(screen.getByTestId('pluginDesc'), pluginData.pluginDesc); + userEvent.click(screen.getByTestId('addonregisterBtn')); + + await wait(100); + expect(toast.success).toBeCalledWith('Plugin added Successfully'); }); test('Expect the window to reload after successful plugin addition', async () => { @@ -166,23 +171,24 @@ describe('Testing AddOnRegister', () => { , ); - await waitFor(() => new Promise((resolve) => setTimeout(resolve, 0))); - - userEvent.click(screen.getByRole('button', { name: /Add New/i })); - await wait(100); - expect(screen.getByTestId('addonregisterBtn')).toBeInTheDocument(); - userEvent.type(screen.getByTestId('pluginName'), pluginData.pluginName); - userEvent.type( - screen.getByTestId('pluginCreatedBy'), - pluginData.pluginCreatedBy, - ); - userEvent.type(screen.getByTestId('pluginDesc'), pluginData.pluginDesc); - userEvent.click(screen.getByTestId('addonregisterBtn')); - - await wait(3000); // Waiting for 3 seconds to reload the page as timeout is set to 2 seconds in the component - expect(mockNavigate).toHaveBeenCalledWith(0); }); + await waitFor(() => new Promise((resolve) => setTimeout(resolve, 0))); + + userEvent.click(screen.getByRole('button', { name: /Add New/i })); + await wait(100); + expect(screen.getByTestId('addonregisterBtn')).toBeInTheDocument(); + userEvent.type(screen.getByTestId('pluginName'), pluginData.pluginName); + userEvent.type( + screen.getByTestId('pluginCreatedBy'), + pluginData.pluginCreatedBy, + ); + userEvent.type(screen.getByTestId('pluginDesc'), pluginData.pluginDesc); + userEvent.click(screen.getByTestId('addonregisterBtn')); + + await wait(3000); // Waiting for 3 seconds to reload the page as timeout is set to 2 seconds in the component + expect(mockNavigate).toHaveBeenCalledWith(0); }); + test('should be redirected to /orglist if orgId is undefined', async () => { mockId = undefined; render( @@ -190,7 +196,7 @@ describe('Testing AddOnRegister', () => { - {} + diff --git a/src/components/AddOn/core/AddOnRegister/AddOnRegister.tsx b/src/components/AddOn/core/AddOnRegister/AddOnRegister.tsx index 059eae5d43..56ed6006c2 100644 --- a/src/components/AddOn/core/AddOnRegister/AddOnRegister.tsx +++ b/src/components/AddOn/core/AddOnRegister/AddOnRegister.tsx @@ -8,6 +8,9 @@ import { useTranslation } from 'react-i18next'; import { toast } from 'react-toastify'; import { Navigate, useNavigate, useParams } from 'react-router-dom'; +/** + * Interface defining the form state for the `addOnRegister` component. + */ interface InterfaceFormStateTypes { pluginName: string; pluginCreatedBy: string; @@ -16,30 +19,62 @@ interface InterfaceFormStateTypes { installedOrgs: [string] | []; } -function addOnRegister(): JSX.Element { +interface AddOnRegisterProps { + createdBy?: string; +} + +/** + * A React component for registering a new add-on plugin. + * + * This component: + * - Displays a button to open a modal for plugin registration. + * - Contains a form in the modal for entering plugin details. + * - Uses GraphQL mutation to register the plugin. + * - Uses `react-i18next` for localization and `react-toastify` for notifications. + * - Redirects to the organization list page if no `orgId` is found in the URL. + * + * @returns A JSX element containing the button and modal for plugin registration. + */ +function addOnRegister({ + createdBy = 'Admin', +}: AddOnRegisterProps): JSX.Element { + // Translation hook for the 'addOnRegister' namespace const { t } = useTranslation('translation', { keyPrefix: 'addOnRegister' }); + // Translation hook for the 'common' namespace const { t: tCommon } = useTranslation('common'); + // Get the organization ID from the URL parameters const { orgId: currentUrl } = useParams(); const navigate = useNavigate(); + + // Redirect to the organization list if no organization ID is found if (!currentUrl) { return ; } + // State to manage the visibility of the modal const [show, setShow] = useState(false); + // Functions to show and hide the modal const handleClose = (): void => setShow(false); const handleShow = (): void => setShow(true); + + // GraphQL mutation hook for adding a plugin const [create] = useMutation(ADD_PLUGIN_MUTATION); + // Initial form state const [formState, setFormState] = useState({ pluginName: '', - pluginCreatedBy: '', + pluginCreatedBy: createdBy, // Using the default value here pluginDesc: '', pluginInstallStatus: false, installedOrgs: [currentUrl], }); + /** + * Handles the registration of the plugin. + * Sends the form data to the GraphQL mutation and displays a success message. + */ const handleRegister = async (): Promise => { const { data } = await create({ variables: { @@ -52,14 +87,18 @@ function addOnRegister(): JSX.Element { }); if (data) { - toast.success(tCommon('addedSuccessfully', { item: 'Plugin' })); + // Show a success message when the plugin is added + toast.success(tCommon('addedSuccessfully', { item: 'Plugin' }) as string); + // Refresh the page after 2 seconds setTimeout(() => { navigate(0); }, 2000); } }; + return ( <> + {/* Button to open the modal */} + {/* Button to register the plugin */} + * + */ function action(props: InterfaceActionProps): JSX.Element { const actionRef = useRef(null); diff --git a/src/components/AddOn/support/components/MainContent/MainContent.tsx b/src/components/AddOn/support/components/MainContent/MainContent.tsx index 7ca4dfc8c4..eddc1b993d 100644 --- a/src/components/AddOn/support/components/MainContent/MainContent.tsx +++ b/src/components/AddOn/support/components/MainContent/MainContent.tsx @@ -1,12 +1,27 @@ import React from 'react'; import styles from './MainContent.module.css'; + +/** + * Props for the `mainContent` component. + */ interface InterfaceMainContentProps { + /** + * The child elements to be rendered inside the main content container. + */ children: any; } -// TODO: Implement extras plugins -// TODO: Implement additional styles -// id - [plugin/component-name]-main-content if is in plugin +/** + * A React component that renders a main content container with additional styles. + * + * @param props - The properties for the component. + * @returns A JSX element containing the main content container with the provided child elements. + * + * @example + * + *

    Main content goes here

    + *
    + */ function mainContent({ children }: InterfaceMainContentProps): JSX.Element { return (
    diff --git a/src/components/AddOn/support/components/SidePanel/SidePanel.tsx b/src/components/AddOn/support/components/SidePanel/SidePanel.tsx index 2eda5e7225..d4c0d65966 100644 --- a/src/components/AddOn/support/components/SidePanel/SidePanel.tsx +++ b/src/components/AddOn/support/components/SidePanel/SidePanel.tsx @@ -1,12 +1,32 @@ import React from 'react'; import styles from './SidePanel.module.css'; + +/** + * Props for the `sidePanel` component. + */ interface InterfaceSidePanelProps { + /** + * Whether the side panel should be collapsed. + */ collapse?: boolean; + + /** + * The child elements to be rendered inside the side panel. + */ children: any; } -// TODO: Implement Extras Plugin -// id - [plugin-name]-side-panel +/** + * A React component that renders a side panel with an optional collapse state. + * + * @param props - The properties for the component. + * @returns A JSX element containing the side panel with the provided child elements. + * + * @example + * + *

    Side panel content

    + *
    + */ function sidePanel({ collapse, children, diff --git a/src/components/AddOn/support/services/Plugin.helper.ts b/src/components/AddOn/support/services/Plugin.helper.ts index 4730f0c568..1ebefc351f 100644 --- a/src/components/AddOn/support/services/Plugin.helper.ts +++ b/src/components/AddOn/support/services/Plugin.helper.ts @@ -1,14 +1,34 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/** + * Helper class for managing plugin-related tasks such as fetching store data, installed plugins, and generating plugin links. + */ class PluginHelper { + /** + * Fetches the store data from a local server. + * + * @returns A promise that resolves to the store data in JSON format. + */ fetchStore = async (): Promise => { const result = await fetch(`http://localhost:${process.env.PORT}/store`); return await result.json(); }; + /** + * Fetches the list of installed plugins from a local server. + * + * @returns A promise that resolves to the installed plugins data in JSON format. + */ fetchInstalled = async (): Promise => { const result = await fetch(`http://localhost:3005/installed`); return await result.json(); }; + /** + * Generates an array of links for the enabled plugins. + * + * @param plugins - An array of plugin objects. + * @returns An array of objects containing the name and URL of each enabled plugin. + */ generateLinks = (plugins: any[]): { name: string; url: string }[] => { return plugins .filter((plugin: any) => plugin.enabled) diff --git a/src/components/Advertisements/Advertisements.test.tsx b/src/components/Advertisements/Advertisements.test.tsx index b45e1bab38..c0992a1012 100644 --- a/src/components/Advertisements/Advertisements.test.tsx +++ b/src/components/Advertisements/Advertisements.test.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { act } from 'react'; import { ApolloClient, ApolloLink, @@ -7,7 +7,7 @@ import { InMemoryCache, } from '@apollo/client'; import { MockedProvider } from '@apollo/client/testing'; -import { act, fireEvent, render, screen } from '@testing-library/react'; +import { fireEvent, render, screen } from '@testing-library/react'; import 'jest-location-mock'; import type { DocumentNode, NormalizedCacheObject } from '@apollo/client'; diff --git a/src/components/Advertisements/Advertisements.tsx b/src/components/Advertisements/Advertisements.tsx index 0b880700d9..f20c2a7d8e 100644 --- a/src/components/Advertisements/Advertisements.tsx +++ b/src/components/Advertisements/Advertisements.tsx @@ -10,13 +10,34 @@ import { useParams } from 'react-router-dom'; import type { InterfaceQueryOrganizationAdvertisementListItem } from 'utils/interfaces'; import InfiniteScroll from 'react-infinite-scroll-component'; -export default function advertisements(): JSX.Element { +/** + * The `Advertisements` component displays a list of advertisements for a specific organization. + * It uses a tab-based interface to toggle between active and archived advertisements. + * + * The component utilizes the `useQuery` hook from Apollo Client to fetch advertisements data + * and implements infinite scrolling to load more advertisements as the user scrolls. + * + * @example + * return ( + * + * ) + * + */ + +export default function Advertisements(): JSX.Element { + // Retrieve the organization ID from URL parameters const { orgId: currentOrgId } = useParams(); + // Translation hook for internationalization const { t } = useTranslation('translation', { keyPrefix: 'advertisement' }); const { t: tCommon } = useTranslation('common'); + + // Set the document title based on the translation document.title = t('title'); + + // State to manage pagination cursor for infinite scrolling const [after, setAfter] = useState(null); + // Type definition for an advertisement object type Ad = { _id: string; name: string; @@ -26,6 +47,7 @@ export default function advertisements(): JSX.Element { startDate: string; // Assuming it's a string in the format 'yyyy-MM-dd' }; + // GraphQL query to fetch the list of advertisements const { data: orgAdvertisementListData, refetch, @@ -41,24 +63,28 @@ export default function advertisements(): JSX.Element { first: 6, }, }); - const [advertisements, setAdvertisements] = useState( + + // State to manage the list of advertisements + const [advertisements, setAdvertisements] = useState( orgAdvertisementListData?.organizations[0].advertisements?.edges.map( (edge: { node: Ad }) => edge.node, ) || [], ); + // Effect hook to update advertisements list when data changes or pagination cursor changes useEffect(() => { if (orgAdvertisementListData && orgAdvertisementListData.organizations) { const ads: Ad[] = orgAdvertisementListData.organizations[0].advertisements?.edges.map( (edge) => edge.node, - ); - after - ? setAdvertisements([...advertisements, ...ads]) - : setAdvertisements(ads); + ) || []; + setAdvertisements(after ? [...advertisements, ...ads] : ads); } }, [orgAdvertisementListData, after]); + /** + * Fetches more advertisements for infinite scrolling. + */ async function loadMoreAdvertisements(): Promise { await refetch(); @@ -75,18 +101,23 @@ export default function advertisements(): JSX.Element {
    + {/* Component for registering a new advertisement */} + + {/* Tabs for active and archived advertisements */} + {/* Tab for active advertisements */} + {/* Skeleton loader while fetching more advertisements */} {[...Array(6)].map((_, index) => (
    @@ -156,12 +187,15 @@ export default function advertisements(): JSX.Element { )} + + {/* Tab for archived advertisements */} + {/* Skeleton loader while fetching more advertisements */} {[...Array(6)].map((_, index) => (
    @@ -237,7 +271,3 @@ export default function advertisements(): JSX.Element { ); } - -advertisements.defaultProps = {}; - -advertisements.propTypes = {}; diff --git a/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.test.tsx b/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.test.tsx index 0850d1f89f..dbd6f88cc3 100644 --- a/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.test.tsx +++ b/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.test.tsx @@ -130,7 +130,64 @@ describe('Testing Advertisement Entry Component', () => { expect(deletionFailedText).toBeNull(); }); }); + it('should use default props when none are provided', () => { + render( + , + ): void { + throw new Error('Function not implemented.'); + }} + />, + ); + + //Check if component renders with default ''(empty string) + const elements = screen.getAllByText(''); // This will return an array of matching elements + elements.forEach((element) => expect(element).toBeInTheDocument()); + + // Check that the component renders with default `mediaUrl` (empty string) + const mediaElement = screen.getByTestId('media'); + expect(mediaElement).toHaveAttribute('src', ''); + + // Check that the component renders with default `endDate` + const defaultEndDate = new Date().toDateString(); + expect(screen.getByText(`Ends on ${defaultEndDate}`)).toBeInTheDocument(); + // Check that the component renders with default `startDate` + const defaultStartDate = new Date().toDateString(); + console.log(screen.getByText); + expect(screen.getByText(`Ends on ${defaultStartDate}`)).toBeInTheDocument(); //fix text "Ends on"? + }); + it('should correctly override default props when values are provided', () => { + const mockName = 'Test Ad'; + const mockType = 'Banner'; + const mockMediaUrl = 'https://example.com/media.png'; + const mockEndDate = new Date(2025, 11, 31); + const mockStartDate = new Date(2024, 0, 1); + const mockOrganizationId = 'org123'; + + const { getByText } = render( + , + ): void { + throw new Error('Function not implemented.'); + }} + />, + ); + + // Check that the component renders with provided values + expect(getByText(mockName)).toBeInTheDocument(); + // Add more checks based on how each prop affects rendering + }); it('should open and close the dropdown when options button is clicked', () => { const { getByTestId, queryByText, getAllByText } = render( diff --git a/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.tsx b/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.tsx index afb66e7ff4..7368ded68e 100644 --- a/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.tsx +++ b/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.tsx @@ -12,30 +12,43 @@ import { toast } from 'react-toastify'; interface InterfaceAddOnEntryProps { id: string; - name: string; - mediaUrl: string; - type: string; - organizationId: string; - startDate: Date; - endDate: Date; + name?: string; + mediaUrl?: string; + type?: string; + organizationId?: string; + startDate?: Date; + endDate?: Date; setAfter: React.Dispatch>; } -function advertisementEntry({ + +/** + * Component for displaying an advertisement entry. + * Allows viewing, editing, and deleting of the advertisement. + * + * @param props - Component properties + * @returns The rendered component + */ +function AdvertisementEntry({ id, - name, - type, - mediaUrl, - endDate, - organizationId, - startDate, + name = '', + type = '', + mediaUrl = '', + endDate = new Date(), + organizationId = '', + startDate = new Date(), setAfter, }: InterfaceAddOnEntryProps): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'advertisement' }); const { t: tCommon } = useTranslation('common'); + + // State for loading button const [buttonLoading, setButtonLoading] = useState(false); + // State for dropdown menu visibility const [dropdown, setDropdown] = useState(false); + // State for delete confirmation modal visibility const [showDeleteModal, setShowDeleteModal] = useState(false); + // Mutation hook for deleting an advertisement const [deleteAdById] = useMutation(DELETE_ADVERTISEMENT_BY_ID, { refetchQueries: [ { @@ -45,7 +58,15 @@ function advertisementEntry({ ], }); + /** + * Toggles the visibility of the delete confirmation modal. + */ const toggleShowDeleteModal = (): void => setShowDeleteModal((prev) => !prev); + + /** + * Handles advertisement deletion. + * Displays a success or error message based on the result. + */ const onDelete = async (): Promise => { setButtonLoading(true); try { @@ -54,9 +75,9 @@ function advertisementEntry({ id: id.toString(), }, }); - toast.success(t('advertisementDeleted')); + toast.success(t('advertisementDeleted') as string); setButtonLoading(false); - setAfter(null); + setAfter?.(null); } catch (error: unknown) { if (error instanceof Error) { toast.error(error.message); @@ -64,9 +85,14 @@ function advertisementEntry({ setButtonLoading(false); } }; + + /** + * Toggles the visibility of the dropdown menu. + */ const handleOptionsClick = (): void => { setDropdown(!dropdown); }; + return ( <> @@ -183,7 +209,7 @@ function advertisementEntry({ ); } -advertisementEntry.propTypes = { +AdvertisementEntry.propTypes = { name: PropTypes.string, type: PropTypes.string, organizationId: PropTypes.string, @@ -192,12 +218,4 @@ advertisementEntry.propTypes = { startDate: PropTypes.instanceOf(Date), }; -advertisementEntry.defaultProps = { - name: '', - type: '', - organizationId: '', - mediaUrl: '', - endDate: new Date(), - startDate: new Date(), -}; -export default advertisementEntry; +export default AdvertisementEntry; diff --git a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.module.css b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.module.css index 75b90fd1d7..0c5678676b 100644 --- a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.module.css +++ b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.module.css @@ -1,4 +1,5 @@ .modalbtn { + margin-top: 1rem; display: flex !important; margin-left: auto; align-items: center; diff --git a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.test.tsx b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.test.tsx index c3aa536d1f..1bf16ec76b 100644 --- a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.test.tsx +++ b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.test.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { act } from 'react'; import { render, fireEvent, waitFor, screen } from '@testing-library/react'; import { @@ -147,12 +147,12 @@ describe('Testing Advertisement Register Component', () => { @@ -166,176 +166,242 @@ describe('Testing Advertisement Register Component', () => { }); test('create advertisement', async () => { + jest.useFakeTimers(); const setTimeoutSpy = jest.spyOn(global, 'setTimeout'); - const { getByText, queryByText, getByLabelText } = render( - - - - - - - - - , - ); - expect(getByText(translations.createAdvertisement)).toBeInTheDocument(); + await act(async () => { + render( + + + + + + + + + , + ); + }); - fireEvent.click(getByText(translations.createAdvertisement)); - expect(queryByText(translations.addNew)).toBeInTheDocument(); + expect( + screen.getByText(translations.createAdvertisement), + ).toBeInTheDocument(); - fireEvent.change(getByLabelText(translations.Rname), { - target: { value: 'Ad1' }, + await act(async () => { + fireEvent.click(screen.getByText(translations.createAdvertisement)); }); - expect(getByLabelText(translations.Rname)).toHaveValue('Ad1'); - const mediaFile = new File(['media content'], 'test.png', { - type: 'image/png', + expect(screen.queryByText(translations.addNew)).toBeInTheDocument(); + + await act(async () => { + fireEvent.change(screen.getByLabelText(translations.Rname), { + target: { value: 'Ad1' }, + }); + + const mediaFile = new File(['media content'], 'test.png', { + type: 'image/png', + }); + + fireEvent.change(screen.getByLabelText(translations.Rmedia), { + target: { + files: [mediaFile], + }, + }); }); - const mediaInput = getByLabelText(translations.Rmedia); - fireEvent.change(mediaInput, { - target: { - files: [mediaFile], - }, + await waitFor(() => { + expect(screen.getByTestId('mediaPreview')).toBeInTheDocument(); }); - const mediaPreview = await screen.findByTestId('mediaPreview'); - expect(mediaPreview).toBeInTheDocument(); + await act(async () => { + fireEvent.change(screen.getByLabelText(translations.Rtype), { + target: { value: 'BANNER' }, + }); - fireEvent.change(getByLabelText(translations.Rtype), { - target: { value: 'BANNER' }, - }); - expect(getByLabelText(translations.Rtype)).toHaveValue('BANNER'); + fireEvent.change(screen.getByLabelText(translations.RstartDate), { + target: { value: '2023-01-01' }, + }); - fireEvent.change(getByLabelText(translations.RstartDate), { - target: { value: '2023-01-01' }, + fireEvent.change(screen.getByLabelText(translations.RendDate), { + target: { value: '2023-02-01' }, + }); }); - expect(getByLabelText(translations.RstartDate)).toHaveValue('2023-01-01'); - fireEvent.change(getByLabelText(translations.RendDate), { - target: { value: '2023-02-01' }, + expect(screen.getByLabelText(translations.Rname)).toHaveValue('Ad1'); + expect(screen.getByLabelText(translations.Rtype)).toHaveValue('BANNER'); + expect(screen.getByLabelText(translations.RstartDate)).toHaveValue( + '2023-01-01', + ); + expect(screen.getByLabelText(translations.RendDate)).toHaveValue( + '2023-02-01', + ); + + await act(async () => { + fireEvent.click(screen.getByText(translations.register)); }); - expect(getByLabelText(translations.RendDate)).toHaveValue('2023-02-01'); await waitFor(() => { - fireEvent.click(getByText(translations.register)); + expect(toast.success).toBeCalledWith( + 'Advertisement created successfully.', + ); + expect(setTimeoutSpy).toHaveBeenCalled(); }); - expect(toast.success).toBeCalledWith('Advertisement created successfully.'); - expect(setTimeoutSpy).toHaveBeenCalled(); + jest.useRealTimers(); }); test('update advertisement', async () => { + jest.useFakeTimers(); const setTimeoutSpy = jest.spyOn(global, 'setTimeout'); - const { getByText, getByLabelText } = render( - - - - - - - - - , - ); - - fireEvent.click(getByText(translations.edit)); - fireEvent.change(getByLabelText(translations.Rname), { - target: { value: 'Ad1' }, + await act(async () => { + render( + + + + + + + + + , + ); }); - expect(getByLabelText(translations.Rname)).toHaveValue('Ad1'); - const mediaFile = new File(['media content'], 'test.png', { - type: 'image/png', + await waitFor(() => { + expect(screen.getByText(translations.edit)).toBeInTheDocument(); }); - const mediaInput = getByLabelText(translations.Rmedia); - fireEvent.change(mediaInput, { - target: { - files: [mediaFile], - }, + await act(async () => { + fireEvent.click(screen.getByText(translations.edit)); }); - const mediaPreview = await screen.findByTestId('mediaPreview'); - expect(mediaPreview).toBeInTheDocument(); + await act(async () => { + fireEvent.change(screen.getByLabelText(translations.Rname), { + target: { value: 'Ad1' }, + }); - fireEvent.change(getByLabelText(translations.Rtype), { - target: { value: 'BANNER' }, + const mediaFile = new File(['media content'], 'test.png', { + type: 'image/png', + }); + + fireEvent.change(screen.getByLabelText(translations.Rmedia), { + target: { + files: [mediaFile], + }, + }); }); - expect(getByLabelText(translations.Rtype)).toHaveValue('BANNER'); - fireEvent.change(getByLabelText(translations.RstartDate), { - target: { value: '2023-01-01' }, + await waitFor(() => { + expect(screen.getByTestId('mediaPreview')).toBeInTheDocument(); }); - expect(getByLabelText(translations.RstartDate)).toHaveValue('2023-01-01'); - fireEvent.change(getByLabelText(translations.RendDate), { - target: { value: '2023-02-01' }, + await act(async () => { + fireEvent.change(screen.getByLabelText(translations.Rtype), { + target: { value: 'BANNER' }, + }); + + fireEvent.change(screen.getByLabelText(translations.RstartDate), { + target: { value: '2023-01-01' }, + }); + + fireEvent.change(screen.getByLabelText(translations.RendDate), { + target: { value: '2023-02-01' }, + }); + }); + + expect(screen.getByLabelText(translations.Rname)).toHaveValue('Ad1'); + expect(screen.getByLabelText(translations.Rtype)).toHaveValue('BANNER'); + expect(screen.getByLabelText(translations.RstartDate)).toHaveValue( + '2023-01-01', + ); + expect(screen.getByLabelText(translations.RendDate)).toHaveValue( + '2023-02-01', + ); + + await act(async () => { + fireEvent.click(screen.getByText(translations.saveChanges)); }); - expect(getByLabelText(translations.RendDate)).toHaveValue('2023-02-01'); await waitFor(() => { - fireEvent.click(getByText(translations.saveChanges)); + expect(toast.success).toBeCalledWith( + 'Advertisement created successfully.', + ); + expect(setTimeoutSpy).toHaveBeenCalled(); }); - expect(toast.success).toBeCalledWith('Advertisement created successfully.'); - expect(setTimeoutSpy).toHaveBeenCalled(); + + jest.useRealTimers(); }); test('Logs error to the console and shows error toast when advertisement creation fails', async () => { + jest.useFakeTimers(); const setTimeoutSpy = jest.spyOn(global, 'setTimeout'); - const { getByText, queryByText } = render( - - - - - - - - - , - ); + const toastErrorSpy = jest.spyOn(toast, 'error'); + + await act(async () => { + render( + + + + + + + + + , + ); + }); - expect(getByText(translations.createAdvertisement)).toBeInTheDocument(); + expect( + screen.getByText(translations.createAdvertisement), + ).toBeInTheDocument(); - fireEvent.click(getByText(translations.createAdvertisement)); - expect(queryByText(translations.addNew)).toBeInTheDocument(); + await act(async () => { + fireEvent.click(screen.getByText(translations.createAdvertisement)); + }); + + expect(screen.queryByText(translations.addNew)).toBeInTheDocument(); + + await act(async () => { + fireEvent.click(screen.getByText(translations.register)); + }); await waitFor(() => { - fireEvent.click(getByText(translations.register)); + expect(toastErrorSpy).toHaveBeenCalledWith( + `An error occurred. Couldn't create advertisement`, + ); }); - expect(toast.error).toBeCalledWith( - `An error occurred. Couldn't create advertisement`, - ); + expect(setTimeoutSpy).toHaveBeenCalled(); + jest.useRealTimers(); }); test('Throws error when the end date is less than the start date', async () => { + jest.useFakeTimers(); const setTimeoutSpy = jest.spyOn(global, 'setTimeout'); const { getByText, queryByText, getByLabelText } = render( @@ -343,12 +409,12 @@ describe('Testing Advertisement Register Component', () => { @@ -403,21 +469,23 @@ describe('Testing Advertisement Register Component', () => { 'End Date should be greater than or equal to Start Date', ); expect(setTimeoutSpy).toHaveBeenCalled(); + jest.useRealTimers(); }); test('AdvertismentRegister component loads correctly in edit mode', async () => { + jest.useFakeTimers(); render( @@ -429,21 +497,23 @@ describe('Testing Advertisement Register Component', () => { await waitFor(() => { expect(screen.getByTestId('editBtn')).toBeInTheDocument(); }); + jest.useRealTimers(); }); test('Opens and closes modals on button click', async () => { + jest.useFakeTimers(); const { getByText, queryByText } = render( @@ -459,9 +529,11 @@ describe('Testing Advertisement Register Component', () => { await waitFor(() => { expect(queryByText(translations.close)).not.toBeInTheDocument(); }); + jest.useRealTimers(); }); test('Throws error when the end date is less than the start date while editing the advertisement', async () => { + jest.useFakeTimers(); const { getByText, getByLabelText, queryByText } = render( @@ -470,12 +542,12 @@ describe('Testing Advertisement Register Component', () => { { } @@ -524,21 +596,23 @@ describe('Testing Advertisement Register Component', () => { 'End Date should be greater than or equal to Start Date', ); }); + jest.useRealTimers(); }); test('Media preview renders correctly', async () => { + jest.useFakeTimers(); render( @@ -563,4 +637,5 @@ describe('Testing Advertisement Register Component', () => { fireEvent.click(closeButton); expect(mediaPreview).not.toBeInTheDocument(); }); + jest.useRealTimers(); }); diff --git a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.tsx b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.tsx index ee812f2b00..1d5c51ce84 100644 --- a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.tsx +++ b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.tsx @@ -13,36 +13,58 @@ import dayjs from 'dayjs'; import convertToBase64 from 'utils/convertToBase64'; import { ORGANIZATION_ADVERTISEMENT_LIST } from 'GraphQl/Queries/Queries'; import { useParams } from 'react-router-dom'; + +/** + * Props for the `advertisementRegister` component. + */ interface InterfaceAddOnRegisterProps { - id?: string; // organizationId - createdBy?: string; // User - formStatus?: string; - idEdit?: string; - nameEdit?: string; - typeEdit?: string; - orgIdEdit?: string; - advertisementMediaEdit?: string; - endDateEdit?: Date; - startDateEdit?: Date; - setAfter: React.Dispatch>; + id?: string; // Optional organization ID + createdBy?: string; // Optional user who created the advertisement + formStatus?: string; // Determines if the form is in register or edit mode + idEdit?: string; // ID of the advertisement to edit + nameEdit?: string; // Name of the advertisement to edit + typeEdit?: string; // Type of the advertisement to edit + orgIdEdit?: string; // Organization ID associated with the advertisement + advertisementMediaEdit?: string; // Media URL of the advertisement to edit + endDateEdit?: Date; // End date of the advertisement to edit + startDateEdit?: Date; // Start date of the advertisement to edit + setAfter: React.Dispatch>; // Function to update parent state } + +/** + * State for the advertisement form. + */ interface InterfaceFormStateTypes { - name: string; - advertisementMedia: string; - type: string; - startDate: Date; - endDate: Date; - organizationId: string | undefined; + name: string; // Name of the advertisement + advertisementMedia: string; // Base64-encoded media of the advertisement + type: string; // Type of advertisement (e.g., BANNER, POPUP) + startDate: Date; // Start date of the advertisement + endDate: Date; // End date of the advertisement + organizationId: string | undefined; // Organization ID } +/** + * Component for registering or editing an advertisement. + * + * @param props - Contains form status, advertisement details, and a function to update parent state. + * @returns A JSX element that renders a form inside a modal for creating or editing an advertisement. + * + * @example + * ```tsx + * console.log(value)} + * /> + * ``` + */ function advertisementRegister({ - formStatus, + formStatus = 'register', idEdit, - nameEdit, - typeEdit, - advertisementMediaEdit, - endDateEdit, - startDateEdit, + nameEdit = '', + typeEdit = 'BANNER', + advertisementMediaEdit = '', + endDateEdit = new Date(), + startDateEdit = new Date(), setAfter, }: InterfaceAddOnRegisterProps): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'advertisement' }); @@ -52,8 +74,9 @@ function advertisementRegister({ const { orgId: currentOrg } = useParams(); const [show, setShow] = useState(false); - const handleClose = (): void => setShow(false); - const handleShow = (): void => setShow(true); + const handleClose = (): void => setShow(false); // Closes the modal + const handleShow = (): void => setShow(true); // Shows the modal + const [create] = useMutation(ADD_ADVERTISEMENT_MUTATION, { refetchQueries: [ { @@ -62,6 +85,7 @@ function advertisementRegister({ }, ], }); + const [updateAdvertisement] = useMutation(UPDATE_ADVERTISEMENT_MUTATION, { refetchQueries: [ { @@ -70,8 +94,8 @@ function advertisementRegister({ }, ], }); - //getting organizationId from URL + // Initialize form state const [formState, setFormState] = useState({ name: '', advertisementMedia: '', @@ -81,7 +105,7 @@ function advertisementRegister({ organizationId: currentOrg, }); - //if set to edit set the formState by edit variables + // Set form state if editing useEffect(() => { if (formStatus === 'edit') { setFormState((prevState) => ({ @@ -103,12 +127,15 @@ function advertisementRegister({ endDateEdit, currentOrg, ]); - + /** + * Handles advertisement registration. + * Validates the date range and performs the mutation to create an advertisement. + */ const handleRegister = async (): Promise => { try { console.log('At handle register', formState); if (formState.endDate < formState.startDate) { - toast.error(t('endDateGreaterOrEqual')); + toast.error(t('endDateGreaterOrEqual') as string); return; } const { data } = await create({ @@ -123,7 +150,7 @@ function advertisementRegister({ }); if (data) { - toast.success(t('advertisementCreated')); + toast.success(t('advertisementCreated') as string); setFormState({ name: '', advertisementMedia: '', @@ -137,12 +164,19 @@ function advertisementRegister({ } catch (error: unknown) { if (error instanceof Error) { toast.error( - tErrors('errorOccurredCouldntCreate', { entity: 'advertisement' }), + tErrors('errorOccurredCouldntCreate', { + entity: 'advertisement', + }) as string, ); console.log('error occured', error.message); } } }; + + /** + * Handles advertisement update. + * Validates the date range and performs the mutation to update the advertisement. + */ const handleUpdate = async (): Promise => { try { const updatedFields: Partial = {}; @@ -158,7 +192,7 @@ function advertisementRegister({ updatedFields.type = formState.type; } if (formState.endDate < formState.startDate) { - toast.error(t('endDateGreaterOrEqual')); + toast.error(t('endDateGreaterOrEqual') as string); return; } const startDateFormattedString = dayjs(formState.startDate).format( @@ -199,7 +233,7 @@ function advertisementRegister({ if (data) { toast.success( - tCommon('updatedSuccessfully', { item: 'Advertisement' }), + tCommon('updatedSuccessfully', { item: 'Advertisement' }) as string, ); handleClose(); setAfter(null); @@ -398,16 +432,6 @@ function advertisementRegister({ ); } -advertisementRegister.defaultProps = { - name: '', - advertisementMedia: '', - type: 'BANNER', - startDate: new Date(), - endDate: new Date(), - organizationId: '', - formStatus: 'register', -}; - advertisementRegister.propTypes = { name: PropTypes.string, advertisementMedia: PropTypes.string, diff --git a/src/components/AgendaCategory/AgendaCategoryContainer.tsx b/src/components/AgendaCategory/AgendaCategoryContainer.tsx index e803e77172..7b4c5cf8f4 100644 --- a/src/components/AgendaCategory/AgendaCategoryContainer.tsx +++ b/src/components/AgendaCategory/AgendaCategoryContainer.tsx @@ -12,10 +12,25 @@ import { import type { InterfaceAgendaItemCategoryInfo } from 'utils/interfaces'; import styles from './AgendaCategoryContainer.module.css'; -import AgendaCategoryDeleteModal from 'screens/OrganizationAgendaCategory/AgendaCategoryDeleteModal'; -import AgendaCategoryPreviewModal from 'screens/OrganizationAgendaCategory/AgendaCategoryPreviewModal'; -import AgendaCategoryUpdateModal from 'screens/OrganizationAgendaCategory/AgendaCategoryUpdateModal'; +import AgendaCategoryDeleteModal from 'components/OrgSettings/AgendaItemCategories/AgendaCategoryDeleteModal'; +import AgendaCategoryPreviewModal from 'components/OrgSettings/AgendaItemCategories/AgendaCategoryPreviewModal'; +import AgendaCategoryUpdateModal from 'components/OrgSettings/AgendaItemCategories/AgendaCategoryUpdateModal'; +/** + * Component for displaying and managing agenda item categories. + * + * @param props - Contains agenda category data and functions for data management. + * @returns A JSX element that renders agenda item categories with options to preview, edit, and delete. + * + * @example + * ```tsx + * + * ``` + */ function agendaCategoryContainer({ agendaCategoryConnection, agendaCategoryData, @@ -29,6 +44,8 @@ function agendaCategoryContainer({ keyPrefix: 'organizationAgendaCategory', }); const { t: tCommon } = useTranslation('common'); + + // State management for modals and form data const [ agendaCategoryPreviewModalIsOpen, setAgendaCategoryPreviewModalIsOpen, @@ -46,6 +63,11 @@ function agendaCategoryContainer({ createdBy: '', }); + /** + * Opens the preview modal and sets the state for the selected agenda category. + * + * @param agendaItemCategory - The agenda category to preview. + */ const showPreviewModal = ( agendaItemCategory: InterfaceAgendaItemCategoryInfo, ): void => { @@ -53,18 +75,30 @@ function agendaCategoryContainer({ setAgendaCategoryPreviewModalIsOpen(true); }; + /** + * Closes the preview modal. + */ const hidePreviewModal = (): void => { setAgendaCategoryPreviewModalIsOpen(false); }; + /** + * Toggles the visibility of the update modal. + */ const showUpdateModal = (): void => { setAgendaCategoryUpdateModalIsOpen(!agendaCategoryUpdateModalIsOpen); }; + /** + * Toggles the visibility of the update modal. + */ const hideUpdateModal = (): void => { setAgendaCategoryUpdateModalIsOpen(!agendaCategoryUpdateModalIsOpen); }; + /** + * Toggles the visibility of the delete modal. + */ const toggleDeleteModal = (): void => { setAgendaCategoryDeleteModalIsOpen(!agendaCategoryDeleteModalIsOpen); }; @@ -73,6 +107,11 @@ function agendaCategoryContainer({ UPDATE_AGENDA_ITEM_CATEGORY_MUTATION, ); + /** + * Handles the update of an agenda category. + * + * @param event - The form submit event. + */ const updateAgendaCategoryHandler = async ( event: ChangeEvent, ): Promise => { @@ -90,7 +129,7 @@ function agendaCategoryContainer({ agendaCategoryRefetch(); hideUpdateModal(); - toast.success(t('agendaCategoryUpdated')); + toast.success(t('agendaCategoryUpdated') as string); } catch (error: unknown) { if (error instanceof Error) { toast.error(`Agenda Category Update Failed ${error.message}`); @@ -102,6 +141,9 @@ function agendaCategoryContainer({ DELETE_AGENDA_ITEM_CATEGORY_MUTATION, ); + /** + * Handles the deletion of an agenda category. + */ const deleteAgendaCategoryHandler = async (): Promise => { try { await deleteAgendaCategory({ @@ -111,7 +153,7 @@ function agendaCategoryContainer({ }); agendaCategoryRefetch(); toggleDeleteModal(); - toast.success(t('agendaCategoryDeleted')); + toast.success(t('agendaCategoryDeleted') as string); } catch (error: unknown) { if (error instanceof Error) { toast.error(`Agenda Category Delete Failed, ${error.message}`); @@ -119,6 +161,11 @@ function agendaCategoryContainer({ } }; + /** + * Prepares the form state and shows the update modal for the selected agenda category. + * + * @param agendaItemCategory - The agenda category to edit. + */ const handleEditClick = ( agendaItemCategory: InterfaceAgendaItemCategoryInfo, ): void => { @@ -126,6 +173,11 @@ function agendaCategoryContainer({ showUpdateModal(); }; + /** + * Updates the form state with the selected agenda category's details. + * + * @param agendaItemCategory - The agenda category details. + */ const setAgendaCategoryState = ( agendaItemCategory: InterfaceAgendaItemCategoryInfo, ): void => { @@ -239,7 +291,7 @@ function agendaCategoryContainer({
    - {/* Preview model */} + {/* Preview modal */} - {/* Update model */} + {/* Update modal */} - {/* Delete model */} + {/* Delete modal */} ({ }, })); +//temporarily fixes react-beautiful-dnd droppable method's depreciation error +//needs to be fixed in React 19 +jest.spyOn(console, 'error').mockImplementation((message) => { + if (message.includes('Support for defaultProps will be removed')) { + return; + } + console.error(message); +}); + async function wait(ms = 100): Promise { await act(async () => { return new Promise((resolve) => setTimeout(resolve, ms)); diff --git a/src/components/AgendaItems/AgendaItemsContainer.tsx b/src/components/AgendaItems/AgendaItemsContainer.tsx index 5b3a00b139..4e50cb5fe8 100644 --- a/src/components/AgendaItems/AgendaItemsContainer.tsx +++ b/src/components/AgendaItems/AgendaItemsContainer.tsx @@ -21,6 +21,14 @@ import AgendaItemsPreviewModal from 'components/AgendaItems/AgendaItemsPreviewMo import AgendaItemsDeleteModal from 'components/AgendaItems/AgendaItemsDeleteModal'; import AgendaItemsUpdateModal from 'components/AgendaItems/AgendaItemsUpdateModal'; +/** + * Component for displaying and managing agenda items. + * Supports drag-and-drop functionality, and includes modals for previewing, + * updating, and deleting agenda items. + * + * @param props - The props for the component. + * @returns JSX.Element + */ function AgendaItemsContainer({ agendaItemConnection, agendaItemData, @@ -37,6 +45,7 @@ function AgendaItemsContainer({ }); const { t: tCommon } = useTranslation('common'); + // State for modals const [agendaItemPreviewModalIsOpen, setAgendaItemPreviewModalIsOpen] = useState(false); const [agendaItemUpdateModalIsOpen, setAgendaItemUpdateModalIsOpen] = @@ -44,6 +53,7 @@ function AgendaItemsContainer({ const [agendaItemDeleteModalIsOpen, setAgendaItemDeleteModalIsOpen] = useState(false); + // State for current agenda item ID and form data const [agendaItemId, setAgendaItemId] = useState(''); const [formState, setFormState] = useState<{ @@ -72,29 +82,49 @@ function AgendaItemsContainer({ }, }); + /** + * Shows the preview modal with the details of the selected agenda item. + * @param agendaItem - The agenda item to preview. + */ const showPreviewModal = (agendaItem: InterfaceAgendaItemInfo): void => { setAgendaItemState(agendaItem); setAgendaItemPreviewModalIsOpen(true); }; + /** + * Hides the preview modal. + */ const hidePreviewModal = (): void => { setAgendaItemPreviewModalIsOpen(false); }; + /** + * Toggles the visibility of the update modal. + */ const showUpdateModal = (): void => { setAgendaItemUpdateModalIsOpen(!agendaItemUpdateModalIsOpen); }; + /** + * Toggles the visibility of the update modal. + */ const hideUpdateModal = (): void => { setAgendaItemUpdateModalIsOpen(!agendaItemUpdateModalIsOpen); }; + /** + * Toggles the visibility of the delete modal. + */ const toggleDeleteModal = (): void => { setAgendaItemDeleteModalIsOpen(!agendaItemDeleteModalIsOpen); }; const [updateAgendaItem] = useMutation(UPDATE_AGENDA_ITEM_MUTATION); + /** + * Handles updating an agenda item. + * @param e - The form submission event. + */ const updateAgendaItemHandler = async ( e: ChangeEvent, ): Promise => { @@ -115,7 +145,7 @@ function AgendaItemsContainer({ }); agendaItemRefetch(); hideUpdateModal(); - toast.success(t('agendaItemUpdated')); + toast.success(t('agendaItemUpdated') as string); } catch (error) { if (error instanceof Error) { toast.error(`${error.message}`); @@ -125,6 +155,9 @@ function AgendaItemsContainer({ const [deleteAgendaItem] = useMutation(DELETE_AGENDA_ITEM_MUTATION); + /** + * Handles deleting an agenda item. + */ const deleteAgendaItemHandler = async (): Promise => { try { await deleteAgendaItem({ @@ -134,7 +167,7 @@ function AgendaItemsContainer({ }); agendaItemRefetch(); toggleDeleteModal(); - toast.success(t('agendaItemDeleted')); + toast.success(t('agendaItemDeleted') as string); } catch (error) { if (error instanceof Error) { toast.error(`${error.message}`); @@ -142,11 +175,19 @@ function AgendaItemsContainer({ } }; + /** + * Handles click event to show the update modal for the selected agenda item. + * @param agendaItem - The agenda item to update. + */ const handleEditClick = (agendaItem: InterfaceAgendaItemInfo): void => { setAgendaItemState(agendaItem); showUpdateModal(); }; + /** + * Sets the state for the selected agenda item. + * @param agendaItem - The agenda item to set in the state. + */ const setAgendaItemState = (agendaItem: InterfaceAgendaItemInfo): void => { setFormState({ ...formState, @@ -169,6 +210,10 @@ function AgendaItemsContainer({ setAgendaItemId(agendaItem._id); }; + /** + * Handles the end of a drag-and-drop operation. + * @param result - The result of the drag-and-drop operation. + */ const onDragEnd = async (result: DropResult): Promise => { if (!result.destination || !agendaItemData) { return; @@ -377,7 +422,7 @@ function AgendaItemsContainer({
    - {/* Preview model */} + {/* Preview modal */} - {/* Delete model */} + {/* Delete modal */} - {/* Update model */} + {/* Update modal */} = ({ @@ -42,6 +54,7 @@ const AgendaItemsCreateModal: React.FC< const [newUrl, setNewUrl] = useState(''); useEffect(() => { + // Ensure URLs and attachments do not have empty or invalid entries setFormState((prevState) => ({ ...prevState, urls: prevState.urls.filter((url) => url.trim() !== ''), @@ -49,13 +62,23 @@ const AgendaItemsCreateModal: React.FC< })); }, []); - // Function to validate URL + /** + * Validates if a given URL is in a correct format. + * + * @param url - URL string to validate. + * @returns True if the URL is valid, false otherwise. + */ const isValidUrl = (url: string): boolean => { // Regular expression for basic URL validation const urlRegex = /^(ftp|http|https):\/\/[^ "]+$/; return urlRegex.test(url); }; + /** + * Handles adding a new URL to the form state. + * + * Checks if the URL is valid before adding it. + */ const handleAddUrl = (): void => { if (newUrl.trim() !== '' && isValidUrl(newUrl.trim())) { setFormState({ @@ -68,6 +91,11 @@ const AgendaItemsCreateModal: React.FC< } }; + /** + * Handles removing a URL from the form state. + * + * @param url - URL to remove. + */ const handleRemoveUrl = (url: string): void => { setFormState({ ...formState, @@ -75,6 +103,11 @@ const AgendaItemsCreateModal: React.FC< }); }; + /** + * Handles file selection and converts files to base64 before updating the form state. + * + * @param e - File input change event. + */ const handleFileChange = async ( e: React.ChangeEvent, ): Promise => { @@ -99,6 +132,11 @@ const AgendaItemsCreateModal: React.FC< } }; + /** + * Handles removing an attachment from the form state. + * + * @param attachment - Attachment to remove. + */ const handleRemoveAttachment = (attachment: string): void => { setFormState({ ...formState, @@ -136,7 +174,6 @@ const AgendaItemsCreateModal: React.FC< formState.agendaItemCategoryIds.includes(category._id), ) || [] } - // isOptionEqualToValue={(option, value) => option._id === value._id} filterSelectedOptions={true} getOptionLabel={( category: InterfaceAgendaItemCategoryInfo, diff --git a/src/components/AgendaItems/AgendaItemsDeleteModal.tsx b/src/components/AgendaItems/AgendaItemsDeleteModal.tsx index 5361ca4985..cba3b29446 100644 --- a/src/components/AgendaItems/AgendaItemsDeleteModal.tsx +++ b/src/components/AgendaItems/AgendaItemsDeleteModal.tsx @@ -10,6 +10,16 @@ interface InterfaceAgendaItemsDeleteModalProps { tCommon: (key: string) => string; } +/** + * Modal component for confirming the deletion of an agenda item. + * Displays a confirmation dialog when a user attempts to delete an agenda item. + * + * @param agendaItemDeleteModalIsOpen - Boolean flag indicating if the modal is open. + * @param toggleDeleteModal - Function to toggle the visibility of the modal. + * @param deleteAgendaItemHandler - Function to handle the deletion of the agenda item. + * @param t - Function for translating text based on keys. + * @param tCommon - Function for translating common text keys. + */ const AgendaItemsDeleteModal: React.FC< InterfaceAgendaItemsDeleteModalProps > = ({ diff --git a/src/components/AgendaItems/AgendaItemsPreviewModal.tsx b/src/components/AgendaItems/AgendaItemsPreviewModal.tsx index fc8cb257a2..299165656c 100644 --- a/src/components/AgendaItems/AgendaItemsPreviewModal.tsx +++ b/src/components/AgendaItems/AgendaItemsPreviewModal.tsx @@ -26,6 +26,18 @@ interface InterfaceAgendaItemsPreviewModalProps { t: (key: string) => string; } +/** + * Modal component for previewing details of an agenda item. + * Displays the details of the selected agenda item, including its categories, title, description, duration, creator, URLs, and attachments. + * Also provides options to update or delete the agenda item. + * + * @param agendaItemPreviewModalIsOpen - Boolean flag indicating if the preview modal is open. + * @param hidePreviewModal - Function to hide the preview modal. + * @param showUpdateModal - Function to show the update modal. + * @param toggleDeleteModal - Function to toggle the delete modal. + * @param formState - The current state of the form containing agenda item details. + * @param t - Function for translating text based on keys. + */ const AgendaItemsPreviewModal: React.FC< InterfaceAgendaItemsPreviewModalProps > = ({ @@ -36,6 +48,11 @@ const AgendaItemsPreviewModal: React.FC< formState, t, }) => { + /** + * Renders the attachments preview. + * + * @returns JSX elements for each attachment, displaying videos and images. + */ const renderAttachments = (): JSX.Element[] => { return formState.attachments.map((attachment, index) => (
    @@ -61,6 +78,11 @@ const AgendaItemsPreviewModal: React.FC< )); }; + /** + * Renders the URLs list. + * + * @returns JSX elements for each URL, displaying clickable links. + */ const renderUrls = (): JSX.Element[] => { return formState.urls.map((url, index) => (
  • diff --git a/src/components/AgendaItems/AgendaItemsUpdateModal.tsx b/src/components/AgendaItems/AgendaItemsUpdateModal.tsx index d2be91e15a..7761c912ca 100644 --- a/src/components/AgendaItems/AgendaItemsUpdateModal.tsx +++ b/src/components/AgendaItems/AgendaItemsUpdateModal.tsx @@ -33,6 +33,19 @@ interface InterfaceAgendaItemsUpdateModalProps { agendaItemCategories: InterfaceAgendaItemCategoryInfo[] | undefined; } +/** + * Modal component for updating details of an agenda item. + * Provides a form to update the agenda item's title, description, duration, categories, URLs, and attachments. + * Also includes functionality to add, remove URLs and attachments. + * + * @param agendaItemUpdateModalIsOpen - Boolean flag indicating if the update modal is open. + * @param hideUpdateModal - Function to hide the update modal. + * @param formState - The current state of the form containing agenda item details. + * @param setFormState - Function to update the form state. + * @param updateAgendaItemHandler - Handler function for submitting the form. + * @param t - Function for translating text based on keys. + * @param agendaItemCategories - List of agenda item categories for selection. + */ const AgendaItemsUpdateModal: React.FC< InterfaceAgendaItemsUpdateModalProps > = ({ @@ -54,13 +67,22 @@ const AgendaItemsUpdateModal: React.FC< })); }, []); - // Function to validate URL + /** + * Validates if a given URL is in a correct format. + * + * @param url - The URL to validate. + * @returns True if the URL is valid, false otherwise. + */ const isValidUrl = (url: string): boolean => { // Regular expression for basic URL validation const urlRegex = /^(ftp|http|https):\/\/[^ "]+$/; return urlRegex.test(url); }; + /** + * Handles adding a new URL to the form state. + * Displays an error toast if the URL is invalid. + */ const handleAddUrl = (): void => { if (newUrl.trim() !== '' && isValidUrl(newUrl.trim())) { setFormState({ @@ -73,6 +95,11 @@ const AgendaItemsUpdateModal: React.FC< } }; + /** + * Handles removing a URL from the form state. + * + * @param url - The URL to remove. + */ const handleRemoveUrl = (url: string): void => { setFormState({ ...formState, @@ -80,6 +107,13 @@ const AgendaItemsUpdateModal: React.FC< }); }; + /** + * Handles file input change event. + * Converts selected files to base64 format and updates the form state. + * Displays an error toast if the total file size exceeds the limit. + * + * @param e - The change event for file input. + */ const handleFileChange = async ( e: React.ChangeEvent, ): Promise => { @@ -104,6 +138,11 @@ const AgendaItemsUpdateModal: React.FC< } }; + /** + * Handles removing an attachment from the form state. + * + * @param attachment - The attachment to remove. + */ const handleRemoveAttachment = (attachment: string): void => { setFormState({ ...formState, @@ -140,7 +179,6 @@ const AgendaItemsUpdateModal: React.FC< formState.agendaItemCategoryIds.includes(category._id), ) || [] } - // isOptionEqualToValue={(option, value) => option._id === value._id} filterSelectedOptions={true} getOptionLabel={( category: InterfaceAgendaItemCategoryInfo, diff --git a/src/components/Avatar/Avatar.tsx b/src/components/Avatar/Avatar.tsx index 6d4cab405b..64b452b0c3 100644 --- a/src/components/Avatar/Avatar.tsx +++ b/src/components/Avatar/Avatar.tsx @@ -7,19 +7,35 @@ interface InterfaceAvatarProps { name: string; alt?: string; size?: number; + containerStyle?: string; avatarStyle?: string; dataTestId?: string; radius?: number; } +/** + * A component that generates and displays an avatar based on the provided name. + * The avatar is generated using the DiceBear library with the initials style. + * + * @param name - The name used to generate the avatar. + * @param alt - Alternative text for the avatar image. + * @param size - Size of the avatar image. + * @param avatarStyle - Custom CSS class for the avatar image. + * @param dataTestId - Data-testid attribute for testing purposes. + * @param radius - Radius of the avatar corners. + * + * @returns JSX.Element - The rendered avatar image component. + */ const Avatar = ({ name, alt = 'Dummy Avatar', size, avatarStyle, + containerStyle, dataTestId, radius, }: InterfaceAvatarProps): JSX.Element => { + // Memoize the avatar creation to avoid unnecessary recalculations const avatar = useMemo(() => { return createAvatar(initials, { size: size || 128, @@ -31,7 +47,7 @@ const Avatar = ({ const svg = avatar.toString(); return ( -
    +
    {alt} { @@ -21,6 +33,11 @@ const ChangeLanguageDropDown = ( const userId = getItem('userId'); const [updateUser] = useMutation(UPDATE_USER_MUTATION); + /** + * Changes the application's language and updates the user's language preference. + * + * @param languageCode - The code of the language to switch to. + */ const changeLanguage = async (languageCode: string): Promise => { if (userId) { try { diff --git a/src/components/ChangeLanguageDropdown/ChangeLanguageDropdown.test.tsx b/src/components/ChangeLanguageDropdown/ChangeLanguageDropdown.test.tsx index 71f01677b4..dc14f6ce17 100644 --- a/src/components/ChangeLanguageDropdown/ChangeLanguageDropdown.test.tsx +++ b/src/components/ChangeLanguageDropdown/ChangeLanguageDropdown.test.tsx @@ -1,5 +1,5 @@ -import React from 'react'; -import { act, render } from '@testing-library/react'; +import React, { act } from 'react'; +import { render } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { I18nextProvider } from 'react-i18next'; import { BrowserRouter } from 'react-router-dom'; @@ -11,8 +11,8 @@ import { MockedProvider } from '@apollo/react-testing'; import { UPDATE_USER_MUTATION } from 'GraphQl/Mutations/mutations'; import { StaticMockLink } from 'utils/StaticMockLink'; import useLocalStorage from 'utils/useLocalstorage'; -import { Provider } from 'react-redux'; -import { store } from 'state/store'; +// import { Provider } from 'react-redux'; +// import { store } from 'state/store'; const { setItem } = useLocalStorage(); async function wait(ms = 100): Promise { diff --git a/src/components/CheckIn/CheckInModal.tsx b/src/components/CheckIn/CheckInModal.tsx index 6b4e5425c0..8c75bab598 100644 --- a/src/components/CheckIn/CheckInModal.tsx +++ b/src/components/CheckIn/CheckInModal.tsx @@ -13,26 +13,48 @@ import type { GridColDef, GridRowHeightReturnValue } from '@mui/x-data-grid'; import { DataGrid } from '@mui/x-data-grid'; import TextField from '@mui/material/TextField'; -export const CheckInModal = (props: InterfaceModalProp): JSX.Element => { +/** + * Modal component for managing event check-ins. Displays a list of attendees + * and their check-in statuses, allowing for filtering by user name. + * + * @param show - Boolean indicating whether the modal is visible. + * @param eventId - ID of the event whose check-ins are to be displayed. + * @param handleClose - Function to call when the modal is closed. + * + * @returns JSX.Element - The rendered modal component. + */ +export const CheckInModal = ({ + show, + eventId, + handleClose, +}: InterfaceModalProp): JSX.Element => { + // State to hold the data for the table const [tableData, setTableData] = useState([]); + // State for search filter input const [userFilterQuery, setUserFilterQuery] = useState(''); + + // State for filter model used in DataGrid const [filterQueryModel, setFilterQueryModel] = useState({ items: [{ field: 'userName', operator: 'contains', value: '' }], }); + // Query to get check-in data from the server const { data: checkInData, loading: checkInLoading, refetch: checkInRefetch, } = useQuery(EVENT_CHECKINS, { - variables: { id: props.eventId }, + variables: { id: eventId }, }); + // Effect runs whenever checkInData, eventId, or checkInLoading changes useEffect(() => { - checkInRefetch(); - if (checkInLoading) setTableData([]); - else + checkInRefetch(); // Refetch data when component mounts or updates + if (checkInLoading) { + setTableData([]); // Clear table data while loading + } else { + // Map the check-in data to table rows setTableData( checkInData.event.attendeesCheckInStatus.map( (checkIn: InterfaceAttendeeCheckIn) => ({ @@ -43,26 +65,29 @@ export const CheckInModal = (props: InterfaceModalProp): JSX.Element => { name: `${checkIn.user.firstName} ${checkIn.user.lastName}`, userId: checkIn.user._id, checkIn: checkIn.checkIn, - eventId: props.eventId, + eventId, }, }), ), ); - }, [checkInData, props.eventId, checkInLoading]); + } + }, [checkInData, eventId, checkInLoading]); + // Define columns for the DataGrid const columns: GridColDef[] = [ - { field: 'userName', headerName: 'User', width: 300 }, + { field: 'userName', headerName: 'User', width: 300 }, // Column for user names { field: 'checkInData', headerName: 'Check In Status', width: 400, renderCell: (props) => ( + // Render a custom row component for check-in status ), }, ]; - // Render the loading screen + // Show a loading indicator while data is loading if (checkInLoading) { return ( <> @@ -70,11 +95,12 @@ export const CheckInModal = (props: InterfaceModalProp): JSX.Element => { ); } + return ( <> { +/** + * Wrapper component that displays a button to open the CheckInModal. + * + * @param eventId - The ID of the event for which check-in management is being handled. + * + * @returns JSX.Element - The rendered CheckInWrapper component. + */ +export const CheckInWrapper = ({ eventId }: PropType): JSX.Element => { const [showModal, setShowModal] = useState(false); return ( @@ -33,7 +40,7 @@ export const CheckInWrapper = (props: PropType): JSX.Element => { setShowModal(false)} - eventId={props.eventId} + eventId={eventId} /> )} diff --git a/src/components/CheckIn/TableRow.test.tsx b/src/components/CheckIn/TableRow.test.tsx index 9a206047d0..14c3d20c29 100644 --- a/src/components/CheckIn/TableRow.test.tsx +++ b/src/components/CheckIn/TableRow.test.tsx @@ -13,7 +13,11 @@ import { MockedProvider } from '@apollo/react-testing'; import { checkInMutationSuccess, checkInMutationUnsuccess } from './mocks'; describe('Testing Table Row for CheckIn Table', () => { - test('If the user in not checked in, button to check in should be displayed, and the user should be able to check in succesfully', async () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + test('If the user is not checked in, button to check in should be displayed, and the user should be able to check in successfully', async () => { const props = { data: { id: `123`, @@ -25,7 +29,7 @@ describe('Testing Table Row for CheckIn Table', () => { refetch: jest.fn(), }; - const { queryByText } = render( + const { findByText } = render( @@ -40,31 +44,29 @@ describe('Testing Table Row for CheckIn Table', () => { , ); - await waitFor(() => expect(queryByText('Check In')).toBeInTheDocument()); + expect(await findByText('Check In')).toBeInTheDocument(); - fireEvent.click(queryByText('Check In') as Element); + fireEvent.click(await findByText('Check In')); - await waitFor(() => - expect(queryByText('Checked in successfully')).toBeInTheDocument(), - ); + expect(await findByText('Checked in successfully')).toBeInTheDocument(); }); - test('If the user in checked in, option to download tag should be shown', async () => { + test('If the user is checked in, the option to download tag should be shown', async () => { const props = { data: { - id: `123`, - name: `John Doe`, - userId: `user123`, + id: '123', + name: 'John Doe', + userId: 'user123', checkIn: { _id: '123', time: '12:00:00', }, - eventId: `event123`, + eventId: 'event123', }, refetch: jest.fn(), }; - const { queryByText } = render( + const { findByText } = render( @@ -79,26 +81,22 @@ describe('Testing Table Row for CheckIn Table', () => { , ); - // Stubbing functions required by the @pdfme to show pdfs - global.URL.createObjectURL = jest.fn(); + global.URL.createObjectURL = jest.fn(() => 'mockURL'); global.window.open = jest.fn(); - await waitFor(() => expect(queryByText('Checked In')).toBeInTheDocument()); - await waitFor(() => - expect(queryByText('Download Tag')).toBeInTheDocument(), - ); + expect(await findByText('Checked In')).toBeInTheDocument(); + expect(await findByText('Download Tag')).toBeInTheDocument(); - fireEvent.click(queryByText('Download Tag') as Element); + fireEvent.click(await findByText('Download Tag')); - await waitFor(() => - expect(queryByText('Generating pdf...')).toBeInTheDocument(), - ); - await waitFor(() => { - expect(queryByText('PDF generated successfully!')).toBeInTheDocument(); - }); + expect(await findByText('Generating pdf...')).toBeInTheDocument(); + expect(await findByText('PDF generated successfully!')).toBeInTheDocument(); + + // Cleanup mocks + jest.clearAllMocks(); }); - test('Upon failing of check in mutation, the appropiate error message should be shown', async () => { + test('Upon failing of check in mutation, the appropriate error message should be shown', async () => { const props = { data: { id: `123`, @@ -110,7 +108,7 @@ describe('Testing Table Row for CheckIn Table', () => { refetch: jest.fn(), }; - const { queryByText } = render( + const { findByText } = render( @@ -125,13 +123,11 @@ describe('Testing Table Row for CheckIn Table', () => { , ); - await waitFor(() => expect(queryByText('Check In')).toBeInTheDocument()); + expect(await findByText('Check In')).toBeInTheDocument(); - fireEvent.click(queryByText('Check In') as Element); + fireEvent.click(await findByText('Check In')); - await waitFor(() => - expect(queryByText('Error checking in')).toBeInTheDocument(), - ); - await waitFor(() => expect(queryByText('Oops')).toBeInTheDocument()); + expect(await findByText('Error checking in')).toBeInTheDocument(); + expect(await findByText('Oops')).toBeInTheDocument(); }); }); diff --git a/src/components/CheckIn/TableRow.tsx b/src/components/CheckIn/TableRow.tsx index 8daa5ed222..38d1dda912 100644 --- a/src/components/CheckIn/TableRow.tsx +++ b/src/components/CheckIn/TableRow.tsx @@ -7,7 +7,15 @@ import { toast } from 'react-toastify'; import { generate } from '@pdfme/generator'; import { tagTemplate } from './tagTemplate'; import { useTranslation } from 'react-i18next'; - +/** + * Component that represents a single row in the check-in table. + * Allows users to mark themselves as checked in and download a tag if they are already checked in. + * + * @param data - The data for the current row, including user and event information. + * @param refetch - Function to refetch the check-in data after marking a check-in. + * + * @returns JSX.Element - The rendered TableRow component. + */ export const TableRow = ({ data, refetch, @@ -18,6 +26,10 @@ export const TableRow = ({ const [checkInMutation] = useMutation(MARK_CHECKIN); const { t } = useTranslation('translation', { keyPrefix: 'checkIn' }); + /** + * Marks the user as checked in for the event. + * Displays success or error messages based on the result of the mutation. + */ const markCheckIn = (): void => { // as we do not want to clutter the UI currently with the same (only provide the most basic of operations) checkInMutation({ @@ -27,26 +39,48 @@ export const TableRow = ({ }, }) .then(() => { - toast.success(t('checkedInSuccessfully')); + toast.success(t('checkedInSuccessfully') as string); refetch(); }) .catch((err) => { - toast.error(t('errorCheckingIn')); + toast.error(t('errorCheckingIn') as string); toast.error(err.message); }); }; - + /** + * Triggers a notification while generating and downloading a PDF tag. + * + * @returns A promise that resolves when the PDF is generated and opened. + */ const notify = (): Promise => toast.promise(generateTag, { pending: 'Generating pdf...', success: 'PDF generated successfully!', error: 'Error generating pdf!', }); + + /** + * Generates a PDF tag based on the provided data and opens it in a new tab. + * + * @returns A promise that resolves when the PDF is successfully generated and opened. + */ const generateTag = async (): Promise => { - const inputs = [{ name: data.name }]; - const pdf = await generate({ template: tagTemplate, inputs }); - const blob = new Blob([pdf.buffer], { type: 'application/pdf' }); - window.open(URL.createObjectURL(blob)); + try { + const inputs = [{ name: data.name }]; + const pdf = await generate({ template: tagTemplate, inputs }); + // istanbul ignore next + const blob = new Blob([pdf.buffer], { type: 'application/pdf' }); + // istanbul ignore next + const url = URL.createObjectURL(blob); + // istanbul ignore next + window.open(url); + // istanbul ignore next + toast.success('PDF generated successfully!'); + } catch (error: unknown) { + const errorMessage = + error instanceof Error ? error.message : 'Unknown error'; + toast.error(`Error generating pdf: ${errorMessage}`); + } }; return ( diff --git a/src/components/CheckIn/tagTemplate.ts b/src/components/CheckIn/tagTemplate.ts index 0af9eeeb15..4aa4475e02 100644 --- a/src/components/CheckIn/tagTemplate.ts +++ b/src/components/CheckIn/tagTemplate.ts @@ -1,4 +1,4 @@ -import { Template } from '@pdfme/generator'; +import { Template } from '@pdfme/common'; export const tagTemplate: Template = { schemas: [ diff --git a/src/components/CollapsibleDropdown/CollapsibleDropdown.test.tsx b/src/components/CollapsibleDropdown/CollapsibleDropdown.test.tsx index cfb1001e6b..efee248ffb 100644 --- a/src/components/CollapsibleDropdown/CollapsibleDropdown.test.tsx +++ b/src/components/CollapsibleDropdown/CollapsibleDropdown.test.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { act } from 'react'; import { render, screen, fireEvent } from '@testing-library/react'; import { BrowserRouter } from 'react-router-dom'; @@ -72,7 +72,9 @@ describe('Testing CollapsibleDropdown component', () => { const nonActiveDropdownBtn = screen.getByText('SubCategory 2'); // Check if dropdown is rendered with correct classes - activeDropdownBtn.click(); + act(() => { + fireEvent.click(activeDropdownBtn); + }); expect(parentDropdownBtn).toBeInTheDocument(); expect(parentDropdownBtn).toHaveClass('text-white'); expect(parentDropdownBtn).toHaveClass('btn-success'); @@ -88,15 +90,21 @@ describe('Testing CollapsibleDropdown component', () => { expect(nonActiveDropdownBtn).toHaveClass('btn-light'); // Check if dropdown is collapsed after clicking on it - fireEvent.click(parentDropdownBtn); + act(() => { + fireEvent.click(parentDropdownBtn); + }); expect(props.setShowDropdown).toHaveBeenCalledWith(false); // Check if dropdown is expanded after clicking on it again - fireEvent.click(parentDropdownBtn); + act(() => { + fireEvent.click(parentDropdownBtn); + }); expect(props.setShowDropdown).toHaveBeenCalledWith(true); - // Click on non active dropdown button and check if it navigates to the correct url - nonActiveDropdownBtn.click(); + // Click on non-active dropdown button and check if it navigates to the correct URL + act(() => { + fireEvent.click(nonActiveDropdownBtn); + }); expect(window.location.pathname).toBe('/sub-category-2'); }); }); diff --git a/src/components/CollapsibleDropdown/CollapsibleDropdown.tsx b/src/components/CollapsibleDropdown/CollapsibleDropdown.tsx index 4b85a1911b..2991c2ade5 100644 --- a/src/components/CollapsibleDropdown/CollapsibleDropdown.tsx +++ b/src/components/CollapsibleDropdown/CollapsibleDropdown.tsx @@ -12,6 +12,15 @@ export interface InterfaceCollapsibleDropdown { setShowDropdown: React.Dispatch>; } +/** + * A collapsible dropdown component that toggles visibility of sub-targets. + * + * @param showDropdown - Boolean indicating whether the dropdown is visible or not. + * @param target - Object containing the target information, including the name and sub-targets. + * @param setShowDropdown - Function to toggle the visibility of the dropdown. + * + * @returns JSX.Element - The rendered CollapsibleDropdown component. + */ const collapsibleDropdown = ({ target, showDropdown, @@ -22,6 +31,7 @@ const collapsibleDropdown = ({ const navigate = useNavigate(); const location = useLocation(); useEffect(() => { + // Show dropdown if the current path includes 'orgstore', otherwise hide it. if (location.pathname.includes('orgstore')) { setShowDropdown(true); } else { diff --git a/src/components/ContriStats/ContriStats.test.tsx b/src/components/ContriStats/ContriStats.test.tsx index 3164c880c8..8edb853684 100644 --- a/src/components/ContriStats/ContriStats.test.tsx +++ b/src/components/ContriStats/ContriStats.test.tsx @@ -14,7 +14,6 @@ const client: ApolloClient = new ApolloClient({ describe('Testing Contribution Stats', () => { const props = { - key: '123', id: '234', recentAmount: '200', highestAmount: '500', diff --git a/src/components/ContriStats/ContriStats.tsx b/src/components/ContriStats/ContriStats.tsx index 7891878335..a2db307d91 100644 --- a/src/components/ContriStats/ContriStats.tsx +++ b/src/components/ContriStats/ContriStats.tsx @@ -4,14 +4,20 @@ import { useTranslation } from 'react-i18next'; import styles from './ContriStats.module.css'; interface InterfaceContriStatsProps { - key: string; id: string; recentAmount: string; highestAmount: string; totalAmount: string; } -function contriStats(props: InterfaceContriStatsProps): JSX.Element { +/** + * A component that displays contribution statistics. + * + * @param props - The properties passed to the component, including `recentAmount`, `highestAmount`, and `totalAmount`. + * + * @returns JSX.Element - The rendered component displaying the contribution stats. + */ +function ContriStats(props: InterfaceContriStatsProps): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'contriStats', }); @@ -30,4 +36,4 @@ function contriStats(props: InterfaceContriStatsProps): JSX.Element { ); } -export default contriStats; +export default ContriStats; diff --git a/src/components/CurrentHourIndicator/CurrentHourIndicator.tsx b/src/components/CurrentHourIndicator/CurrentHourIndicator.tsx index 9e4a85454a..98e02bbf5f 100644 --- a/src/components/CurrentHourIndicator/CurrentHourIndicator.tsx +++ b/src/components/CurrentHourIndicator/CurrentHourIndicator.tsx @@ -1,6 +1,11 @@ import React from 'react'; import styles from './CurrentHourIndicator.module.css'; +/** + * A component that displays an indicator for the current hour. + * + * @returns JSX.Element - The rendered component showing the current hour indicator. + */ const CurrentHourIndicator = (): JSX.Element => { return (
    diff --git a/src/components/DeleteOrg/DeleteOrg.test.tsx b/src/components/DeleteOrg/DeleteOrg.test.tsx deleted file mode 100644 index d9ac99f3ad..0000000000 --- a/src/components/DeleteOrg/DeleteOrg.test.tsx +++ /dev/null @@ -1,248 +0,0 @@ -import React from 'react'; -import { MockedProvider } from '@apollo/react-testing'; -import { render, screen } from '@testing-library/react'; -import 'jest-location-mock'; -import { I18nextProvider } from 'react-i18next'; -import { Provider } from 'react-redux'; -import { BrowserRouter } from 'react-router-dom'; - -import { - DELETE_ORGANIZATION_MUTATION, - REMOVE_SAMPLE_ORGANIZATION_MUTATION, -} from 'GraphQl/Mutations/mutations'; -import { act } from 'react-dom/test-utils'; -import { store } from 'state/store'; -import { StaticMockLink } from 'utils/StaticMockLink'; -import i18nForTest from 'utils/i18nForTest'; -import DeleteOrg from './DeleteOrg'; -import { ToastContainer, toast } from 'react-toastify'; -import { IS_SAMPLE_ORGANIZATION_QUERY } from 'GraphQl/Queries/Queries'; -import useLocalStorage from 'utils/useLocalstorage'; - -const { setItem } = useLocalStorage(); - -async function wait(ms = 1000): Promise { - await act(async () => { - await new Promise((resolve) => setTimeout(resolve, ms)); - }); -} - -const MOCKS = [ - { - request: { - query: IS_SAMPLE_ORGANIZATION_QUERY, - variables: { - isSampleOrganizationId: '123', - }, - }, - result: { - data: { - isSampleOrganization: true, - }, - }, - }, - { - request: { - query: REMOVE_SAMPLE_ORGANIZATION_MUTATION, - }, - result: { - data: { - removeSampleOrganization: true, - }, - }, - }, - { - request: { - query: DELETE_ORGANIZATION_MUTATION, - variables: { - id: '456', - }, - }, - result: { - data: { - removeOrganization: { - _id: '456', - }, - }, - }, - }, -]; - -const MOCKS_WITH_ERROR = [ - { - request: { - query: IS_SAMPLE_ORGANIZATION_QUERY, - variables: { - isSampleOrganizationId: '123', - }, - }, - result: { - data: { - isSampleOrganization: true, - }, - }, - }, - { - request: { - query: DELETE_ORGANIZATION_MUTATION, - variables: { - id: '456', - }, - }, - error: new Error('Failed to delete organization'), - }, - { - request: { - query: REMOVE_SAMPLE_ORGANIZATION_MUTATION, - }, - error: new Error('Failed to delete sample organization'), - }, -]; -const mockNavgatePush = jest.fn(); -let mockURL = '123'; -jest.mock('react-router-dom', () => ({ - ...jest.requireActual('react-router-dom'), - useParams: () => ({ orgId: mockURL }), - useNavigate: () => mockNavgatePush, -})); - -const link = new StaticMockLink(MOCKS, true); -const link2 = new StaticMockLink(MOCKS_WITH_ERROR, true); - -afterEach(() => { - localStorage.clear(); -}); - -describe('Delete Organization Component', () => { - test('should be able to Toggle Delete Organization Modal', async () => { - mockURL = '456'; - setItem('SuperAdmin', true); - render( - - - - - - - - - - , - ); - await wait(); - screen.getByTestId(/openDeleteModalBtn/i).click(); - expect(screen.getByTestId(/orgDeleteModal/i)).toBeInTheDocument(); - screen.getByTestId(/closeDelOrgModalBtn/i).click(); - await act(async () => { - expect(screen.queryByTestId(/orgDeleteModal/i)).not.toHaveFocus(); - }); - }); - - test('should be able to Toggle Delete Organization Modal When Organization is Sample Organization', async () => { - mockURL = '123'; - setItem('SuperAdmin', true); - render( - - - - - - - - - - , - ); - await wait(); - screen.getByTestId(/openDeleteModalBtn/i).click(); - expect(screen.getByTestId(/orgDeleteModal/i)).toBeInTheDocument(); - screen.getByTestId(/closeDelOrgModalBtn/i).click(); - await act(async () => { - expect(screen.queryByTestId(/orgDeleteModal/i)).not.toHaveFocus(); - }); - }); - - test('Delete organization functionality should work properly', async () => { - mockURL = '456'; - setItem('SuperAdmin', true); - render( - - - - - - - - - , - ); - await wait(); - screen.getByTestId(/openDeleteModalBtn/i).click(); - screen.getByTestId(/deleteOrganizationBtn/i).click(); - }); - - test('Delete organization functionality should work properly for sample org', async () => { - mockURL = '123'; - setItem('SuperAdmin', true); - render( - - - - - - - - - , - ); - await wait(); - screen.getByTestId(/openDeleteModalBtn/i).click(); - screen.getByTestId(/deleteOrganizationBtn/i).click(); - await wait(2000); - expect(mockNavgatePush).toHaveBeenCalledWith('/orglist'); - }); - - test('Error handling for IS_SAMPLE_ORGANIZATION_QUERY mock', async () => { - mockURL = '123'; - setItem('SuperAdmin', true); - jest.spyOn(toast, 'error'); - render( - - - - - - - - - , - ); - await wait(); - screen.getByTestId(/openDeleteModalBtn/i).click(); - screen.getByTestId(/deleteOrganizationBtn/i).click(); - await wait(); - expect(toast.error).toHaveBeenCalledWith( - 'Failed to delete sample organization', - ); - }); - - test('Error handling for DELETE_ORGANIZATION_MUTATION mock', async () => { - mockURL = '456'; - setItem('SuperAdmin', true); - render( - - - - - - - - - , - ); - await wait(); - screen.getByTestId(/openDeleteModalBtn/i).click(); - screen.getByTestId(/deleteOrganizationBtn/i).click(); - await wait(); - }); -}); diff --git a/src/components/DynamicDropDown/DynamicDropDown.tsx b/src/components/DynamicDropDown/DynamicDropDown.tsx index 170b6be29b..fac8b8fd85 100644 --- a/src/components/DynamicDropDown/DynamicDropDown.tsx +++ b/src/components/DynamicDropDown/DynamicDropDown.tsx @@ -2,6 +2,9 @@ import React from 'react'; import { Dropdown } from 'react-bootstrap'; import styles from './DynamicDropDown.module.css'; +/** + * Props for the DynamicDropDown component. + */ interface InterfaceChangeDropDownProps { parentContainerStyle?: string; btnStyle?: string; @@ -12,13 +15,45 @@ interface InterfaceChangeDropDownProps { fieldName: string; // Field name for labeling } -const DynamicDropDown = (props: InterfaceChangeDropDownProps): JSX.Element => { +/** + * A dynamic dropdown component that allows users to select an option. + * + * This component renders a dropdown with a toggle button. Clicking the button + * opens a menu with options. When an option is selected, it updates the form state. + * + * @param parentContainerStyle - Optional CSS class for styling the container. + * @param btnStyle - Optional CSS class for styling the dropdown button. + * @param setFormState - Function to update the form state with the selected option. + * @param formState - Current state of the form, used to determine the selected value. + * @param fieldOptions - Options to display in the dropdown. Each option has a value and a label. + * @param fieldName - The name of the field, used for labeling and key identification. + * @returns JSX.Element - The rendered dropdown component. + */ +const DynamicDropDown = ({ + parentContainerStyle = '', + btnStyle = '', + setFormState, + formState, + fieldOptions, + fieldName, +}: InterfaceChangeDropDownProps): JSX.Element => { + /** + * Updates the form state when a dropdown option is selected. + * + * @param value - The value of the selected option. + */ const handleFieldChange = (value: string): void => { - props.setFormState({ ...props.formState, [props.fieldName]: value }); + setFormState({ ...formState, [fieldName]: value }); }; + /** + * Retrieves the label for a given value from the options. + * + * @param value - The value for which to get the label. + * @returns The label corresponding to the value, or 'None' if not found. + */ const getLabel = (value: string): string => { - const selectedOption = props.fieldOptions.find( + const selectedOption = fieldOptions.find( (option) => option.value === value, ); return selectedOption ? selectedOption.label : `None`; @@ -26,23 +61,23 @@ const DynamicDropDown = (props: InterfaceChangeDropDownProps): JSX.Element => { return ( - {getLabel(props.formState[props.fieldName])} + {getLabel(formState[fieldName])} - {props.fieldOptions.map((option, index: number) => ( + {fieldOptions.map((option, index: number) => ( handleFieldChange(option.value)} - data-testid={`change-${props.fieldName.toLowerCase()}-btn-${option.value}`} + data-testid={`change-${fieldName.toLowerCase()}-btn-${option.value}`} > {option.label} diff --git a/src/components/EditCustomFieldDropDown/EditCustomFieldDropDown.test.tsx b/src/components/EditCustomFieldDropDown/EditCustomFieldDropDown.test.tsx index 2e3c52ad38..19d2249a43 100644 --- a/src/components/EditCustomFieldDropDown/EditCustomFieldDropDown.test.tsx +++ b/src/components/EditCustomFieldDropDown/EditCustomFieldDropDown.test.tsx @@ -1,13 +1,13 @@ import type { Dispatch, SetStateAction } from 'react'; -import React from 'react'; -import { act, render } from '@testing-library/react'; +import React, { act } from 'react'; +import { render } from '@testing-library/react'; import { BrowserRouter } from 'react-router-dom'; import EditOrgCustomFieldDropDown from './EditCustomFieldDropDown'; -import type { InterfaceCustomFieldData } from 'components/OrgProfileFieldSettings/OrgProfileFieldSettings'; import userEvent from '@testing-library/user-event'; import availableFieldTypes from 'utils/fieldTypes'; import { I18nextProvider } from 'react-i18next'; import i18nForTest from 'utils/i18nForTest'; +import type { InterfaceCustomFieldData } from 'utils/interfaces'; async function wait(ms = 100): Promise { await act(() => { diff --git a/src/components/EditCustomFieldDropDown/EditCustomFieldDropDown.tsx b/src/components/EditCustomFieldDropDown/EditCustomFieldDropDown.tsx index 7a81e78e27..2350d2c9c4 100644 --- a/src/components/EditCustomFieldDropDown/EditCustomFieldDropDown.tsx +++ b/src/components/EditCustomFieldDropDown/EditCustomFieldDropDown.tsx @@ -2,9 +2,12 @@ import React from 'react'; import type { SetStateAction, Dispatch } from 'react'; import { Dropdown } from 'react-bootstrap'; import availableFieldTypes from 'utils/fieldTypes'; -import type { InterfaceCustomFieldData } from 'components/OrgProfileFieldSettings/OrgProfileFieldSettings'; import { useTranslation } from 'react-i18next'; +import type { InterfaceCustomFieldData } from 'utils/interfaces'; +/** + * Props for the EditOrgCustomFieldDropDown component. + */ interface InterfaceEditCustomFieldDropDownProps { customFieldData: InterfaceCustomFieldData; setCustomFieldData: Dispatch>; @@ -13,6 +16,20 @@ interface InterfaceEditCustomFieldDropDownProps { btnTextStyle?: string; } +/** + * A dropdown component for editing custom field types. + * + * This component displays a dropdown menu that allows users to select a custom field type. + * It shows the current type of the field and provides a list of available types to choose from. + * When a new type is selected, it updates the custom field data. + * + * @param customFieldData - The current data of the custom field being edited. + * @param setCustomFieldData - Function to update the custom field data with the new type. + * @param parentContainerStyle - Optional CSS class to style the container of the dropdown. + * @param btnStyle - Optional CSS class to style the dropdown button. + * @param btnTextStyle - Optional CSS class to style the text inside the button. + * @returns JSX.Element - The rendered dropdown component. + */ const EditOrgCustomFieldDropDown = ({ customFieldData, setCustomFieldData, diff --git a/src/components/EventCalendar/EventCalendar.tsx b/src/components/EventCalendar/EventCalendar.tsx index 566e66d62a..fb76eb597c 100644 --- a/src/components/EventCalendar/EventCalendar.tsx +++ b/src/components/EventCalendar/EventCalendar.tsx @@ -56,6 +56,7 @@ enum Role { interface InterfaceIOrgList { admins: { _id: string }[]; } + const Calendar: React.FC = ({ eventData, refetchEvents, @@ -125,6 +126,9 @@ const Calendar: React.FC = ({ setEvents(data); }, [eventData, orgData, userRole, userId]); + /** + * Moves the calendar view to the previous month. + */ const handlePrevMonth = (): void => { /*istanbul ignore next*/ if (currentMonth === 0) { @@ -135,6 +139,9 @@ const Calendar: React.FC = ({ } }; + /** + * Moves the calendar view to the next month. + */ const handleNextMonth = (): void => { /*istanbul ignore next*/ if (currentMonth === 11) { @@ -145,6 +152,9 @@ const Calendar: React.FC = ({ } }; + /** + * Moves the calendar view to the previous date. + */ const handlePrevDate = (): void => { /*istanbul ignore next*/ if (currentDate > 1) { @@ -188,6 +198,9 @@ const Calendar: React.FC = ({ } }; + /** + * Moves the calendar view to today's date. + */ const handleTodayButton = (): void => { /*istanbul ignore next*/ setCurrentYear(today.getFullYear()); diff --git a/src/components/EventCalendar/EventHeader.test.tsx b/src/components/EventCalendar/EventHeader.test.tsx index 215182af9c..e18d066306 100644 --- a/src/components/EventCalendar/EventHeader.test.tsx +++ b/src/components/EventCalendar/EventHeader.test.tsx @@ -1,10 +1,9 @@ -import React from 'react'; +import React, { act } from 'react'; // Import act for async testing import { render, fireEvent } from '@testing-library/react'; import EventHeader from './EventHeader'; import { ViewType } from '../../screens/OrganizationEvents/OrganizationEvents'; import { I18nextProvider } from 'react-i18next'; import i18nForTest from 'utils/i18nForTest'; -import { act } from 'react-dom/test-utils'; // Import act for async testing describe('EventHeader Component', () => { const viewType = ViewType.MONTH; diff --git a/src/components/EventCalendar/EventHeader.tsx b/src/components/EventCalendar/EventHeader.tsx index a4bc59596c..1e4653ebf4 100644 --- a/src/components/EventCalendar/EventHeader.tsx +++ b/src/components/EventCalendar/EventHeader.tsx @@ -5,12 +5,24 @@ import styles from './EventCalendar.module.css'; import { ViewType } from '../../screens/OrganizationEvents/OrganizationEvents'; import { useTranslation } from 'react-i18next'; +/** + * Props for the EventHeader component. + */ interface InterfaceEventHeaderProps { viewType: ViewType; handleChangeView: (item: string | null) => void; showInviteModal: () => void; } +/** + * EventHeader component displays the header for the event calendar. + * It includes a search field, view type dropdown, event type dropdown, and a button to create an event. + * + * @param viewType - The current view type of the calendar. + * @param handleChangeView - Function to handle changing the view type. + * @param showInviteModal - Function to show the invite modal for creating an event. + * @returns JSX.Element - The rendered EventHeader component. + */ function eventHeader({ viewType, handleChangeView, @@ -34,6 +46,11 @@ function eventHeader({ required className={styles.inputField} value={eventName} + /** + * Updates the event name state when the input value changes. + * + * @param e - The event object from the input change. + */ /*istanbul ignore next*/ onChange={(e) => setEventName(e.target.value)} /> diff --git a/src/components/EventCalendar/YearlyEventCalender.tsx b/src/components/EventCalendar/YearlyEventCalender.tsx index 7b7a4d4b03..63870ded3c 100644 --- a/src/components/EventCalendar/YearlyEventCalender.tsx +++ b/src/components/EventCalendar/YearlyEventCalender.tsx @@ -7,6 +7,9 @@ import type { ViewType } from 'screens/OrganizationEvents/OrganizationEvents'; import { ChevronLeft, ChevronRight } from '@mui/icons-material'; import type { InterfaceRecurrenceRule } from 'utils/recurrenceUtils'; +/** + * Interface for event data used in the calendar. + */ interface InterfaceEventListCardProps { userRole?: string; key?: string; @@ -49,12 +52,18 @@ enum Status { DELETED = 'DELETED', } +/** + * Enum for different user roles. + */ enum Role { USER = 'USER', SUPERADMIN = 'SUPERADMIN', ADMIN = 'ADMIN', } +/** + * Interface for event attendees. + */ interface InterfaceIEventAttendees { userId: string; user?: string; @@ -62,9 +71,27 @@ interface InterfaceIEventAttendees { createdAt?: Date; } +/** + * Interface for organization list. + */ interface InterfaceIOrgList { admins: { _id: string }[]; } + +/** + * Calendar component to display events for a selected year. + * + * This component renders a yearly calendar with navigation to view previous and next years. + * It displays events for each day, with functionality to expand and view details of events. + * + * @param eventData - Array of event data to display on the calendar. + * @param refetchEvents - Function to refresh the event data. + * @param orgData - Organization data to filter events. + * @param userRole - Role of the user for access control. + * @param userId - ID of the user for filtering events they are attending. + * @param viewType - Type of view for the calendar. + * @returns JSX.Element - The rendered calendar component. + */ const Calendar: React.FC = ({ eventData, refetchEvents, @@ -95,6 +122,15 @@ const Calendar: React.FC = ({ ); const [expandedY, setExpandedY] = useState(null); + /** + * Filters events based on user role, organization data, and user ID. + * + * @param eventData - Array of event data to filter. + * @param orgData - Organization data for filtering events. + * @param userRole - Role of the user for access control. + * @param userId - ID of the user for filtering events they are attending. + * @returns Filtered array of event data. + */ const filterData = ( eventData: InterfaceEventListCardProps[], orgData?: InterfaceIOrgList, @@ -137,16 +173,27 @@ const Calendar: React.FC = ({ setEvents(data); }, [eventData, orgData, userRole, userId]); + /** + * Navigates to the previous year. + */ const handlePrevYear = (): void => { /*istanbul ignore next*/ setCurrentYear(currentYear - 1); }; + /** + * Navigates to the next year. + */ const handleNextYear = (): void => { /*istanbul ignore next*/ setCurrentYear(currentYear + 1); }; + /** + * Renders the days of the month for the calendar. + * + * @returns Array of JSX elements representing the days of each month. + */ const renderMonthDays = (): JSX.Element[] => { const renderedMonths: JSX.Element[] = []; @@ -320,6 +367,11 @@ const Calendar: React.FC = ({ return renderedMonths; }; + /** + * Renders the yearly calendar with navigation buttons. + * + * @returns JSX.Element - The rendered yearly calendar component. + */ const renderYearlyCalendar = (): JSX.Element => { return (
    diff --git a/src/components/EventDashboardScreen/EventDashboardScreen.tsx b/src/components/EventDashboardScreen/EventDashboardScreen.tsx index 9b518f5e0b..11b9ec936f 100644 --- a/src/components/EventDashboardScreen/EventDashboardScreen.tsx +++ b/src/components/EventDashboardScreen/EventDashboardScreen.tsx @@ -1,15 +1,23 @@ import LeftDrawerOrg from 'components/LeftDrawerOrg/LeftDrawerOrg'; import React, { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { useDispatch, useSelector } from 'react-redux'; +import { useSelector } from 'react-redux'; import { Navigate, Outlet, useLocation, useParams } from 'react-router-dom'; import { updateTargets } from 'state/action-creators'; +import { useAppDispatch } from 'state/hooks'; import type { RootState } from 'state/reducers'; import type { TargetsType } from 'state/reducers/routesReducer'; import styles from './EventDashboardScreen.module.css'; import ProfileDropdown from 'components/ProfileDropdown/ProfileDropdown'; import useLocalStorage from 'utils/useLocalstorage'; +import type { InterfaceMapType } from 'utils/interfaces'; +/** + * The EventDashboardScreen component is the main dashboard view for event management. + * It includes navigation, a sidebar, and a profile dropdown. + * + * @returns JSX.Element - The rendered EventDashboardScreen component. + */ const EventDashboardScreen = (): JSX.Element => { const { getItem } = useLocalStorage(); const isLoggedIn = getItem('IsLoggedIn'); @@ -19,6 +27,8 @@ const EventDashboardScreen = (): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: titleKey }); const [hideDrawer, setHideDrawer] = useState(null); const { orgId } = useParams(); + + // Redirect to home if orgId is not present or if user is not logged in if (!orgId) { return ; } @@ -43,22 +53,31 @@ const EventDashboardScreen = (): JSX.Element => { ); } + // Access targets from Redux store const appRoutes: { targets: TargetsType[]; } = useSelector((state: RootState) => state.appRoutes); const { targets } = appRoutes; - const dispatch = useDispatch(); + const dispatch = useAppDispatch(); + + // Update targets when orgId changes useEffect(() => { dispatch(updateTargets(orgId)); - }, [orgId]); // Added orgId to the dependency array + }, [orgId]); + /** + * Handles window resize events to toggle the visibility of the sidebar drawer. + */ const handleResize = (): void => { if (window.innerWidth <= 820 && !hideDrawer) { setHideDrawer(true); } }; + /** + * Toggles the visibility of the sidebar drawer. + */ const toggleDrawer = (): void => { setHideDrawer(!hideDrawer); }; @@ -119,10 +138,6 @@ const EventDashboardScreen = (): JSX.Element => { export default EventDashboardScreen; -interface InterfaceMapType { - [key: string]: string; -} - const map: InterfaceMapType = { orgdash: 'dashboard', orgpeople: 'organizationPeople', diff --git a/src/components/EventListCard/EventListCard.test.tsx b/src/components/EventListCard/EventListCard.test.tsx index 22ddccd8d2..b882d5887b 100644 --- a/src/components/EventListCard/EventListCard.test.tsx +++ b/src/components/EventListCard/EventListCard.test.tsx @@ -1,12 +1,6 @@ -import React from 'react'; +import React, { act } from 'react'; import type { RenderResult } from '@testing-library/react'; -import { - act, - render, - screen, - fireEvent, - waitFor, -} from '@testing-library/react'; +import { render, screen, fireEvent, waitFor } from '@testing-library/react'; import { MockedProvider } from '@apollo/react-testing'; import userEvent from '@testing-library/user-event'; import { I18nextProvider } from 'react-i18next'; @@ -57,6 +51,8 @@ const translations = { const renderEventListCard = ( props: InterfaceEventListCardProps, ): RenderResult => { + const { key, ...restProps } = props; // Destructure the key and separate other props + return render( @@ -66,11 +62,11 @@ const renderEventListCard = ( } + element={} /> } + element={} /> { }); test('should show an error toast when the delete event mutation fails', async () => { + // Destructure key from props[1] and pass it separately to avoid spreading it + const { key, ...otherProps } = props[1]; render( @@ -887,11 +885,11 @@ describe('Testing Event List Card', () => { } + element={} /> } + element={} /> diff --git a/src/components/EventListCard/EventListCard.tsx b/src/components/EventListCard/EventListCard.tsx index 9d89647ee1..ffa508ff7c 100644 --- a/src/components/EventListCard/EventListCard.tsx +++ b/src/components/EventListCard/EventListCard.tsx @@ -5,6 +5,9 @@ import { Navigate, useParams } from 'react-router-dom'; import EventListCardModals from './EventListCardModals'; import type { InterfaceRecurrenceRule } from 'utils/recurrenceUtils'; +/** + * Props for the EventListCard component. + */ export interface InterfaceEventListCardProps { refetchEvents?: () => void; userRole?: string; @@ -33,6 +36,12 @@ export interface InterfaceEventListCardProps { }; } +/** + * Component that displays an event card with a modal for event details. + * + * @param props - The props for the EventListCard component. + * @returns The rendered EventListCard component. + */ function eventListCard(props: InterfaceEventListCardProps): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'eventListCard', @@ -42,14 +51,22 @@ function eventListCard(props: InterfaceEventListCardProps): JSX.Element { const [eventModalIsOpen, setEventModalIsOpen] = useState(false); const { orgId } = useParams(); + + // Redirect to home if orgId is not present if (!orgId) { return ; } + /** + * Opens the event modal. + */ const showViewModal = (): void => { setEventModalIsOpen(true); }; + /** + * Closes the event modal. + */ const hideViewModal = (): void => { setEventModalIsOpen(false); }; diff --git a/src/components/EventListCard/EventListCardMocks.ts b/src/components/EventListCard/EventListCardMocks.ts index e5f7ea3227..6312b5af51 100644 --- a/src/components/EventListCard/EventListCardMocks.ts +++ b/src/components/EventListCard/EventListCardMocks.ts @@ -69,8 +69,8 @@ export const MOCKS = [ startDate: '2022-03-18', endDate: '2022-03-20', location: 'New Delhi', - startTime: '09:00:00Z', - endTime: '17:00:00Z', + startTime: '09:00:00', + endTime: '17:00:00', }, }, result: { diff --git a/src/components/EventListCard/EventListCardModals.tsx b/src/components/EventListCard/EventListCardModals.tsx index 51612f45e5..193890941c 100644 --- a/src/components/EventListCard/EventListCardModals.tsx +++ b/src/components/EventListCard/EventListCardModals.tsx @@ -37,11 +37,24 @@ enum Role { ADMIN = 'ADMIN', } +/** + * Converts a time string to a Dayjs object representing the current date with the specified time. + * @param time - A string representing the time in 'HH:mm:ss' format. + * @returns A Dayjs object with the current date and specified time. + */ const timeToDayJs = (time: string): Dayjs => { const dateTimeString = dayjs().format('YYYY-MM-DD') + ' ' + time; return dayjs(dateTimeString, { format: 'YYYY-MM-DD HH:mm:ss' }); }; +/** + * Properties for the `EventListCardModals` component. + * eventListCardProps - The properties of the event list card. + * eventModalIsOpen - Boolean indicating if the event modal is open. + * hideViewModal - Function to hide the event modal. + * t - Function for translation of text. + * tCommon - Function for translation of common text. + */ interface InterfaceEventListCardModalProps { eventListCardProps: InterfaceEventListCardProps; eventModalIsOpen: boolean; @@ -50,6 +63,12 @@ interface InterfaceEventListCardModalProps { tCommon: (key: string) => string; } +/** + * The `EventListCardModals` component displays the modals related to events, such as viewing, + * updating, and deleting events. + * @param props - The properties for the component. + * @returns A JSX element containing the event modals. + */ function EventListCardModals({ eventListCardProps, eventModalIsOpen, @@ -236,8 +255,8 @@ function EventListCardModals({ startDate: dayjs(eventStartDate).format('YYYY-MM-DD'), endDate: dayjs(eventEndDate).format('YYYY-MM-DD'), location: formState.location, - startTime: !alldaychecked ? formState.startTime + 'Z' : undefined, - endTime: !alldaychecked ? formState.endTime + 'Z' : undefined, + startTime: !alldaychecked ? formState.startTime : undefined, + endTime: !alldaychecked ? formState.endTime : undefined, recurrenceStartDate: recurringchecked ? recurringEventUpdateType === thisAndFollowingInstances && (instanceDatesChanged || recurrenceRuleChanged) @@ -265,7 +284,7 @@ function EventListCardModals({ }); if (data) { - toast.success(t('eventUpdated')); + toast.success(t('eventUpdated') as string); setRecurringEventUpdateModalIsOpen(false); hideViewModal(); if (refetchEvents) { @@ -304,7 +323,7 @@ function EventListCardModals({ }); if (data) { - toast.success(t('eventDeleted')); + toast.success(t('eventDeleted') as string); setEventDeleteModalIsOpen(false); hideViewModal(); if (refetchEvents) { diff --git a/src/components/EventManagement/Dashboard/EventDashboard.tsx b/src/components/EventManagement/Dashboard/EventDashboard.tsx index 84b0493198..dfb3eb0245 100644 --- a/src/components/EventManagement/Dashboard/EventDashboard.tsx +++ b/src/components/EventManagement/Dashboard/EventDashboard.tsx @@ -6,6 +6,13 @@ import { EVENT_DETAILS } from 'GraphQl/Queries/Queries'; import { useQuery } from '@apollo/client'; import Loader from 'components/Loader/Loader'; +/** + * Component that displays event details. + * + * @param props - The props for the EventDashboard component. + * @param eventId - The ID of the event to fetch and display. + * @returns The rendered EventDashboard component. + */ const EventDashboard = (props: { eventId: string }): JSX.Element => { const { eventId } = props; const { t } = useTranslation('translation', { @@ -19,15 +26,28 @@ const EventDashboard = (props: { eventId: string }): JSX.Element => { }, ); + // Display a loader while fetching event data if (eventInfoLoading) { return ; } + /** + * Formats a time string (HH:MM) to a more readable format. + * + * @param timeString - The time string to format. + * @returns - The formatted time string. + */ function formatTime(timeString: string): string { const [hours, minutes] = timeString.split(':').slice(0, 2); return `${hours}:${minutes}`; } + /** + * Formats a date string to a more readable format (e.g., 1st Jan 2024). + * + * @param dateString - The date string to format. + * @returns - The formatted date string. + */ function formatDate(dateString: string): string { const date = new Date(dateString); const day = date.getDate(); @@ -55,6 +75,11 @@ const EventDashboard = (props: { eventId: string }): JSX.Element => { const formattedDate = `${day}${suffix} ${monthNames[monthIndex]} ${year}`; return formattedDate; } + if (!eventData || !eventData.event) { + return ; // Fallback UI while data is loading + } + + // Render event details return (
    @@ -64,37 +89,36 @@ const EventDashboard = (props: { eventId: string }): JSX.Element => {

    - {eventData.event.startTime !== null - ? `${formatTime(eventData.event.startTime)}` - : ``} + {eventData?.event?.startTime !== null + ? `${formatTime(eventData?.event?.startTime)}` + : ''} {' '} - {formatDate(eventData.event.startDate)}{' '} + {formatDate(eventData?.event?.startDate)}{' '}

    {t('to')}

    - {' '} - {eventData.event.endTime !== null - ? `${formatTime(eventData.event.endTime)}` + {eventData?.event?.endTime !== null + ? `${formatTime(eventData?.event?.endTime)}` : ``} {' '} - {formatDate(eventData.event.endDate)}{' '} + {formatDate(eventData?.event?.endDate)}{' '}

    -

    {eventData.event.title}

    +

    {eventData?.event?.title}

    - {eventData.event.description} + {eventData?.event?.description}

    - Location: {eventData.event.location} + Location: {eventData?.event?.location}

    Registrants:{' '} - {eventData.event.attendees.length} + {eventData?.event?.attendees?.length}


    diff --git a/src/components/EventManagement/EventActionItems/EventActionItems.module.css b/src/components/EventManagement/EventActionItems/EventActionItems.module.css deleted file mode 100644 index 120177d155..0000000000 --- a/src/components/EventManagement/EventActionItems/EventActionItems.module.css +++ /dev/null @@ -1,206 +0,0 @@ -@media screen and (max-width: 575.5px) { - .mainpageright { - width: 98%; - } -} -.actionItemModal { - max-width: 80vw; - margin-top: 2vh; - margin-left: 13vw; -} -.modalContent { - width: 670px; - max-width: 680px; -} -.dropdown { - background-color: white; - border: 1px solid #31bb6b; - position: relative; - display: inline-block; - margin-top: 10px; - margin-bottom: 10px; - color: #31bb6b; -} -.input { - flex: 1; - position: relative; -} - -.btnsContainer { - display: flex; - margin: 2.5rem 0 2.5rem 0; -} - -.btnsContainer .btnsBlock { - display: flex; -} - -.btnsContainer .btnsBlock button { - margin-left: 1rem; - display: flex; - justify-content: center; - align-items: center; -} - -.btnsContainer .input { - flex: 1; - position: relative; -} - -/* input { - outline: 1px solid var(--bs-gray-400); -} */ - -.btnsContainer .input button { - width: 52px; -} - -.inputField { - margin-top: 10px; - margin-bottom: 10px; - background-color: white; - box-shadow: 0 1px 1px #31bb6b; -} -.inputFieldModal { - margin-bottom: 10px; - background-color: white; - box-shadow: 0 1px 1px #31bb6b; -} -.inputField > button { - padding-top: 10px; - padding-bottom: 10px; -} -.TableImage { - object-fit: cover; - width: 50px !important; - height: 50px !important; - border-radius: 100% !important; -} -.datagrid { - overflow: auto; - border-radius: 10px; -} -.tableHead { - background-color: #31bb6b !important; - color: white; - border-radius: 20px !important; - padding: 20px; - margin-top: 20px; -} - -.tableHead :nth-first-child() { - border-top-left-radius: 20px; -} - -.mainpageright > hr { - margin-top: 10px; - width: 100%; - margin-left: -15px; - margin-right: -15px; - margin-bottom: 20px; -} -.rowBackground { - background-color: var(--bs-white); -} -.tableHeader { - color: var(--bs-black); - font-size: var(--bs-body-font-size); -} -.addButton { - width: 7em; - position: absolute; - right: 1rem; - top: 1rem; -} - -.createModal { - margin-top: 20vh; - margin-left: 13vw; - max-width: 80vw; -} - -.icon { - transform: scale(1.5); - color: var(--bs-danger); - margin-bottom: 1rem; -} - -.message { - display: flex; - justify-content: center; - align-items: center; - flex-direction: column; -} - -.titlemodal { - color: var(--bs-gray-600); - font-weight: 600; - font-size: 20px; - margin-bottom: 20px; - padding-bottom: 5px; - border-bottom: 3px solid var(--bs-primary); - width: 65%; -} - -.editDelBtns { - margin-top: 15px; - border: 1px solid var(--bs-gray-300); - box-shadow: 0 2px 2px var(--bs-gray-300); - padding: 10px 10px; - border-radius: 5px; - background-color: var(--bs-primary); - width: 100%; - font-size: 16px; - color: var(--bs-white); - outline: none; - font-weight: 600; - cursor: pointer; - transition: - transform 0.2s, - box-shadow 0.2s; - width: 100%; -} - -.greenregbtn { - margin-left: 93%; -} - -.datatable { - margin-top: 5rem; -} - -.datediv { - display: flex; - flex-direction: row; -} -.datebox { - width: 90%; - border-radius: 7px; - outline: none; - box-shadow: none; -} -.actionItemsOptionsButton { - width: 24px; - height: 24px; -} - -@-webkit-keyframes load8 { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } -} -@keyframes load8 { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } -} diff --git a/src/components/EventManagement/EventActionItems/EventActionItems.test.tsx b/src/components/EventManagement/EventActionItems/EventActionItems.test.tsx deleted file mode 100644 index 9da0b5247a..0000000000 --- a/src/components/EventManagement/EventActionItems/EventActionItems.test.tsx +++ /dev/null @@ -1,1179 +0,0 @@ -import React from 'react'; -import { MockedProvider } from '@apollo/react-testing'; -import { LocalizationProvider } from '@mui/x-date-pickers'; -import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; -import { - act, - fireEvent, - render, - screen, - waitFor, - waitForElementToBeRemoved, -} from '@testing-library/react'; -import 'jest-localstorage-mock'; -import { Provider } from 'react-redux'; -import { BrowserRouter } from 'react-router-dom'; -import userEvent from '@testing-library/user-event'; -import { I18nextProvider } from 'react-i18next'; -import EventActionItems from './EventActionItems'; -import { store } from 'state/store'; -import 'jest-location-mock'; -import { toast } from 'react-toastify'; -import i18nForTest from 'utils/i18nForTest'; -import { StaticMockLink } from 'utils/StaticMockLink'; -import { - CREATE_ACTION_ITEM_MUTATION, - UPDATE_ACTION_ITEM_MUTATION, - DELETE_ACTION_ITEM_MUTATION, -} from 'GraphQl/Mutations/ActionItemMutations'; -import { - ACTION_ITEM_CATEGORY_LIST, - MEMBERS_LIST, -} from 'GraphQl/Queries/Queries'; -import { ACTION_ITEM_LIST_BY_EVENTS } from 'GraphQl/Queries/ActionItemQueries'; - -async function wait(ms = 100): Promise { - await act(() => { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); - }); -} - -jest.mock('react-toastify', () => ({ - toast: { - success: jest.fn(), - error: jest.fn(), - }, -})); - -const MOCKS = [ - { - request: { - query: CREATE_ACTION_ITEM_MUTATION, - variables: { - assigneeId: '658930fd2caa9d8d6908745c', - actionItemCategoryId: '65f069a53b63ad266db32b3f', - eventId: '123', - preCompletionNotes: 'task to be done with high priority', - dueDate: '2024-04-05', - }, - }, - result: { - data: { - createActionItem: { - _id: 'newly_created_action_item_id', - }, - }, - }, - }, - { - request: { - query: UPDATE_ACTION_ITEM_MUTATION, - variables: { - actionItemId: '_6613ef741677gygwuyu', - assigneeId: '658930fd2caa9d8d690sfhgush', - preCompletionNotes: 'pre completion notes edited', - postCompletionNotes: 'Post Completion Notes', - dueDate: '2024-02-14', - completionDate: '2024-02-21', - isCompleted: false, - }, - }, - result: { - data: { - updateActionItem: { - _id: '_6613ef741677gygwuyu', - }, - }, - }, - }, - { - request: { - query: UPDATE_ACTION_ITEM_MUTATION, - variables: { - actionItemId: '_6613ef741677gygwuyu', - assigneeId: '658930fd2caa9d8d6908745c', - preCompletionNotes: 'Pre Completion Notes', - postCompletionNotes: 'this action item has been completed successfully', - dueDate: '2024-02-21', - completionDate: '2024-02-21', - isCompleted: true, - }, - }, - result: { - data: { - updateActionItem: { - _id: '_6613ef741677gygwuyu', - }, - }, - }, - }, - { - request: { - query: UPDATE_ACTION_ITEM_MUTATION, - variables: { - actionItemId: 'actionItem2', - assigneeId: 'user1', - preCompletionNotes: 'this action item has been made active again', - postCompletionNotes: 'Post Completion Notes', - dueDate: '2024-02-21', - completionDate: '2024-02-21', - isCompleted: false, - }, - }, - result: { - data: { - updateActionItem: { - _id: '_6613ef741677gygwuyu', - }, - }, - }, - }, - { - request: { - query: DELETE_ACTION_ITEM_MUTATION, - variables: { - actionItemId: '_6613ef741677gygwuyu', - }, - }, - result: { - data: { - removeActionItem: { - _id: '_6613ef741677gygwuyu', - __typename: 'ActionItem', - }, - }, - }, - }, - { - request: { - query: ACTION_ITEM_CATEGORY_LIST, - variables: { - organizationId: '111', - }, - }, - result: { - data: { - actionItemCategoriesByOrganization: [ - { - _id: '65f069a53b63ad266db32b3f', - name: 'Default', - isDisabled: false, - __typename: 'ActionItemCategory', - }, - ], - }, - }, - }, - { - request: { - query: MEMBERS_LIST, - variables: { - id: '111', - }, - }, - result: { - data: { - organizations: [ - { - _id: '111', - members: [ - { - createdAt: '2023-04-13', - email: 'testuser4@example.com', - firstName: 'Teresa', - image: null, - lastName: 'Bradley', - organizationsBlockedBy: [], - __typename: 'User', - _id: '658930fd2caa9d8d6908745c', - }, - { - createdAt: '2024-04-13', - email: 'testuser2@example.com', - firstName: 'Anna', - image: null, - lastName: 'Bradley', - organizationsBlockedBy: [], - __typename: 'User', - _id: '658930fd2caa9d8d690sfhgush', - }, - ], - }, - ], - }, - }, - }, - { - request: { - query: ACTION_ITEM_LIST_BY_EVENTS, - variables: { - eventId: '123', - }, - }, - result: { - data: { - actionItemsByEvent: [ - { - _id: '_6613ef741677gygwuyu', - actionItemCategory: { - __typename: 'ActionItemCategory', - _id: '65f069a53b63ad266db32b3j', - name: 'Default', - }, - assignee: { - __typename: 'User', - _id: '658930fd2caa9d8d6908745c', - firstName: 'Burton', - lastName: 'Sanders', - }, - assigner: { - __typename: 'User', - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - assignmentDate: new Date('2024-02-14'), - dueDate: new Date('2024-02-21'), - completionDate: new Date('2024-02-21'), - creator: { - __typename: 'User', - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - event: { - __typename: 'Event', - _id: '123', - title: 'Adult Painting Lessons', - }, - isCompleted: false, - postCompletionNotes: 'Post Completion Notes', - preCompletionNotes: 'Pre Completion Notes', - }, - { - _id: 'actionItem2', - assignee: { - _id: '658930fd2caa9d8d6908745c', - firstName: 'Harve', - lastName: 'Lance', - }, - actionItemCategory: { - _id: 'actionItemCategory1', - name: 'ActionItemCategory 1', - }, - preCompletionNotes: - 'Long Pre Completion Notes Text that exceeds 25 characters', - postCompletionNotes: - 'Long Post Completion Notes Text that exceeds 25 characters', - assignmentDate: new Date('2024-02-14'), - dueDate: new Date('2024-02-21'), - completionDate: new Date('2024-02-21'), - isCompleted: true, - assigner: { - _id: 'user0', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - event: { - _id: 'event1', - title: 'event 1', - }, - creator: { - _id: 'user0', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - }, - { - _id: 'actionItem3', - assignee: { - _id: '658930fd2caa9d8d6908745c', - firstName: 'Harve', - lastName: 'Lance', - }, - actionItemCategory: { - _id: 'actionItemCategory1', - name: 'ActionItemCategory 1', - }, - preCompletionNotes: 'Pre Completion Text', - postCompletionNotes: 'Post Completion Text', - assignmentDate: new Date('2024-02-14'), - dueDate: new Date('2024-02-21'), - completionDate: new Date('2024-02-21'), - isCompleted: true, - assigner: { - _id: 'user0', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - event: { - _id: 'event1', - title: 'event 1', - }, - creator: { - _id: 'user0', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - }, - ], - }, - refetch: jest.fn(), - }, - }, -]; - -const CREATE_ACTION_ITEM_ERROR_MOCK = [ - { - request: { - query: CREATE_ACTION_ITEM_MUTATION, - variables: { - assigneeId: '658930fd2caa9d8d6908745c', - actionItemCategoryId: '65f069a53b63ad266db32b3f', - eventId: '123', - preCompletionNotes: 'task to be done with high priority', - dueDate: '2024-04-05', - }, - }, - result: { - data: { - createActionItem: { - _id: undefined, - }, - }, - }, - }, -]; - -const UPDATE_ACTION_ITEM_ERROR_MOCK = [ - { - request: { - query: ACTION_ITEM_LIST_BY_EVENTS, - variables: { - eventId: '123', - }, - }, - result: { - data: { - actionItemsByEvent: [ - { - _id: '_6613ef741677gygwuyu', - actionItemCategory: { - __typename: 'ActionItemCategory', - _id: '65f069a53b63ad266db32b3j', - name: 'Default', - }, - assignee: { - __typename: 'User', - _id: '658930fd2caa9d8d6908745c', - firstName: 'Burton', - lastName: 'Sanders', - }, - assigner: { - __typename: 'User', - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - assignmentDate: new Date('2024-02-14'), - dueDate: new Date('2024-02-21'), - completionDate: new Date('2024-02-21'), - creator: { - __typename: 'User', - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - event: { - __typename: 'Event', - _id: '123', - title: 'Adult Painting Lessons', - }, - isCompleted: false, - postCompletionNotes: 'Post Completion Note', - preCompletionNotes: 'Pre Completion Note', - }, - ], - }, - refetch: jest.fn(), - }, - }, - { - request: { - query: MEMBERS_LIST, - variables: { - id: '111', - }, - }, - result: { - data: { - organizations: [ - { - _id: '111', - members: [ - { - createdAt: '2023-04-13', - email: 'testuser4@example.com', - firstName: 'Teresa', - image: null, - lastName: 'Bradley', - organizationsBlockedBy: [], - __typename: 'User', - _id: '658930fd2caa9d8d6908745c', - }, - { - createdAt: '2024-04-13', - email: 'testuser2@example.com', - firstName: 'Anna', - image: null, - lastName: 'Bradley', - organizationsBlockedBy: [], - __typename: 'User', - _id: '658930fd2caa9d8d690sfhgush', - }, - ], - }, - ], - }, - }, - }, - { - request: { - query: DELETE_ACTION_ITEM_MUTATION, - variables: { - actionItemId: '_6613ef741677gygwuyu', - }, - }, - error: new Error('Mock Graphql Error'), - }, - { - request: { - query: UPDATE_ACTION_ITEM_MUTATION, - variables: { - actionItemId: '_6613ef741677gygwuyu', - assigneeId: '658930fd2caa9d8d690sfhgush', - preCompletionNotes: 'pre completion notes edited', - postCompletionNotes: '', - dueDate: '2024-02-14', - completionDate: '2024-02-21', - isCompleted: false, - }, - }, - error: new Error('Mock Graphql Error'), - }, -]; - -const NO_ACTION_ITEMS_ERROR_MOCK = [ - { - request: { - query: ACTION_ITEM_LIST_BY_EVENTS, - variables: { - eventId: '123', - }, - }, - result: { - data: { - actionItemsByEvent: [], - }, - refetch: jest.fn(), - }, - }, -]; - -const link = new StaticMockLink(MOCKS, true); -const link2 = new StaticMockLink(CREATE_ACTION_ITEM_ERROR_MOCK, true); -const link3 = new StaticMockLink(UPDATE_ACTION_ITEM_ERROR_MOCK, true); -const link4 = new StaticMockLink(NO_ACTION_ITEMS_ERROR_MOCK, true); - -const translations = JSON.parse( - JSON.stringify( - i18nForTest.getDataByLanguage('en')?.translation.eventActionItems, - ), -); - -describe('Event Action Items Page', () => { - const formData = { - assignee: 'Anna Bradley', - preCompletionNotes: 'pre completion notes edited', - dueDate: '02/14/2024', - completionDate: '02/21/2024', - }; - test('Testing add new action item modal', async () => { - window.location.assign('/event/111/123'); - render( - - - - - - {} - - - - - , - ); - await wait(); - userEvent.click(screen.getByTestId('createEventActionItemBtn')); - - await wait(); - expect( - screen.getByText(translations.actionItemDetails), - ).toBeInTheDocument(); - - const categoryDropdown = screen.getByTestId('formSelectActionItemCategory'); - userEvent.selectOptions(categoryDropdown, 'Default'); - - expect(categoryDropdown).toHaveValue('65f069a53b63ad266db32b3f'); - - const assigneeDropdown = screen.getByTestId('formSelectAssignee'); - userEvent.selectOptions(assigneeDropdown, 'Teresa Bradley'); - - expect(assigneeDropdown).toHaveValue('658930fd2caa9d8d6908745c'); - - fireEvent.change( - screen.getByPlaceholderText(translations.preCompletionNotes), - { - target: { value: 'task to be done with high priority' }, - }, - ); - expect( - screen.getByPlaceholderText(translations.preCompletionNotes), - ).toHaveValue('task to be done with high priority'); - - fireEvent.change(screen.getByLabelText(translations.dueDate), { - target: { value: '04/05/2024' }, - }); - expect(screen.getByLabelText(translations.dueDate)).toHaveValue( - '04/05/2024', - ); - - userEvent.click(screen.getByTestId('createActionItemFormSubmitBtn')); - - await wait(); - - expect(toast.success).toBeCalledWith(translations.successfulCreation); - }); - - test('Display all the action items', async () => { - window.location.assign('/event/111/123'); - render( - - - - - - {} - - - - - , - ); - await wait(); - - expect(screen.getByText('#')).toBeInTheDocument(); - expect(screen.getByText(translations.assignee)).toBeInTheDocument(); - expect( - screen.getByText(translations.actionItemCategory), - ).toBeInTheDocument(); - expect( - screen.getByText(translations.preCompletionNotes), - ).toBeInTheDocument(); - expect( - screen.getByText(translations.postCompletionNotes), - ).toBeInTheDocument(); - - await wait(); - const asigneeAnchorElement = screen.getByText('Burton Sanders'); - expect(asigneeAnchorElement.tagName).toBe('A'); - expect(asigneeAnchorElement).toHaveAttribute('href', '/member/123'); - - expect(screen.getByText('Burton Sanders')).toBeInTheDocument(); - const updateButtons = screen.getAllByTestId('editActionItemModalBtn'); - const previewButtons = screen.getAllByTestId('previewActionItemModalBtn'); - const updateStatusButtons = screen.getAllByTestId( - 'actionItemStatusChangeCheckbox', - ); - expect(updateButtons[0]).toBeInTheDocument(); - expect(previewButtons[0]).toBeInTheDocument(); - expect(updateStatusButtons[0]).toBeInTheDocument(); - - // Truncate notes and long completion notes txt - expect( - screen.getAllByTestId('actionItemPreCompletionNotesOverlay')[1], - ).toHaveTextContent('Long Pre Completion Notes...'); - expect( - screen.getAllByTestId('actionItemPostCompletionNotesOverlay')[0], - ).toHaveTextContent('Long Post Completion Note...'); - expect( - screen.getAllByTestId('actionItemPostCompletionNotesOverlay')[1], - ).toHaveTextContent('Post Completion Text'); - expect( - screen.getAllByTestId('actionItemPreCompletionNotesOverlay')[2], - ).toHaveTextContent('Pre Completion Text'); - }); - - test('opens and closes the update and delete modals through the preview modal', async () => { - window.location.assign('/event/111/123'); - render( - - - - - - {} - - - - - , - ); - - await wait(); - - expect( - screen.getAllByTestId('previewActionItemModalBtn')[0], - ).toBeInTheDocument(); - userEvent.click(screen.getAllByTestId('previewActionItemModalBtn')[0]); - - await waitFor(() => { - return expect( - screen.findByTestId('previewActionItemModalCloseBtn'), - ).resolves.toBeInTheDocument(); - }); - - await waitFor(() => { - expect( - screen.getByTestId('deleteActionItemPreviewModalBtn'), - ).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('deleteActionItemPreviewModalBtn')); - - await waitFor(() => { - return expect( - screen.findByTestId('actionItemDeleteModalCloseBtn'), - ).resolves.toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('actionItemDeleteModalCloseBtn')); - - await waitForElementToBeRemoved(() => - screen.queryByTestId('actionItemDeleteModalCloseBtn'), - ); - - expect( - screen.getByTestId('editActionItemPreviewModalBtn'), - ).toBeInTheDocument(); - userEvent.click(screen.getByTestId('editActionItemPreviewModalBtn')); - - await waitFor(() => { - return expect( - screen.findByTestId('updateActionItemModalCloseBtn'), - ).resolves.toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('updateActionItemModalCloseBtn')); - - await waitForElementToBeRemoved(() => - screen.queryByTestId('updateActionItemModalCloseBtn'), - ); - }); - test('opens and closes the action item status change modal correctly', async () => { - window.location.assign('/event/111/123'); - render( - - - - - - {} - - - - - , - ); - await wait(); - - await waitFor(() => { - expect( - screen.getAllByTestId('actionItemStatusChangeCheckbox')[0], - ).toBeInTheDocument(); - }); - userEvent.click(screen.getAllByTestId('actionItemStatusChangeCheckbox')[0]); - - await waitFor(() => { - return expect( - screen.findByTestId('actionItemStatusChangeModalCloseBtn'), - ).resolves.toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('actionItemStatusChangeModalCloseBtn')); - - await waitForElementToBeRemoved(() => - screen.queryByTestId('actionItemStatusChangeModalCloseBtn'), - ); - }); - - test('updates an action item status through the action item status change modal', async () => { - window.location.assign('/event/111/123'); - render( - - - - - - {} - - - - - , - ); - await wait(); - - await waitFor(() => { - expect( - screen.getAllByTestId('actionItemStatusChangeCheckbox')[0], - ).toBeInTheDocument(); - }); - userEvent.click(screen.getAllByTestId('actionItemStatusChangeCheckbox')[0]); - - await waitFor(() => { - expect( - screen.getByTestId('actionItemsStatusChangeNotes'), - ).toBeInTheDocument(); - }); - - const postCompletionNotes = screen.getByTestId( - 'actionItemsStatusChangeNotes', - ); - fireEvent.change(postCompletionNotes, { target: { value: '' } }); - userEvent.type( - postCompletionNotes, - 'this action item has been completed successfully', - ); - - await waitFor(() => { - expect( - screen.getByTestId('actionItemStatusChangeSubmitBtn'), - ).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('actionItemStatusChangeSubmitBtn')); - - await waitFor(() => { - expect(toast.success).toBeCalledWith(translations.successfulUpdation); - }); - - await waitFor(() => { - expect( - screen.getAllByTestId('actionItemStatusChangeCheckbox')[1], - ).toBeInTheDocument(); - }); - userEvent.click(screen.getAllByTestId('actionItemStatusChangeCheckbox')[1]); - - await waitFor(() => { - expect( - screen.getByTestId('actionItemsStatusChangeNotes'), - ).toBeInTheDocument(); - }); - - const preCompletionNotes = screen.getByTestId( - 'actionItemsStatusChangeNotes', - ); - fireEvent.change(preCompletionNotes, { target: { value: '' } }); - userEvent.type( - preCompletionNotes, - 'this action item has been made active again', - ); - - await waitFor(() => { - expect( - screen.getByTestId('actionItemStatusChangeSubmitBtn'), - ).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('actionItemStatusChangeSubmitBtn')); - - await waitFor(() => { - expect(toast.success).toBeCalledWith(translations.successfulUpdation); - }); - }); - - test('Testing update action item modal', async () => { - window.location.assign('/event/111/123'); - render( - - - - - - {} - - - - - , - ); - await wait(); - - await waitFor(() => { - expect( - screen.getAllByTestId('editActionItemModalBtn')[0], - ).toBeInTheDocument(); - }); - userEvent.click(screen.getAllByTestId('editActionItemModalBtn')[0]); - - await waitFor(() => { - expect(screen.getByTestId('formUpdateAssignee')).toBeInTheDocument(); - }); - - userEvent.selectOptions( - screen.getByTestId('formUpdateAssignee'), - formData.assignee, - ); - - const preCompletionNotes = screen.getByPlaceholderText( - translations.preCompletionNotes, - ); - fireEvent.change(preCompletionNotes, { target: { value: '' } }); - userEvent.type(preCompletionNotes, formData.preCompletionNotes); - - const dueDatePicker = screen.getByLabelText(translations.dueDate); - fireEvent.change(dueDatePicker, { - target: { value: formData.dueDate }, - }); - - const completionDatePicker = screen.getByLabelText( - translations.completionDate, - ); - fireEvent.change(completionDatePicker, { - target: { value: formData.completionDate }, - }); - - await waitFor(() => { - expect( - screen.getByTestId('updateActionItemFormSubmitBtn'), - ).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('updateActionItemFormSubmitBtn')); - - await waitFor(() => { - expect(toast.success).toBeCalledWith(translations.successfulUpdation); - }); - }); - test('Testing delete action item modal and delete the record', async () => { - window.location.assign('/event/111/123'); - render( - - - - - - {} - - - - - , - ); - await wait(); - expect( - screen.getAllByTestId('previewActionItemModalBtn')[0], - ).toBeInTheDocument(); - userEvent.click(screen.getAllByTestId('previewActionItemModalBtn')[0]); - - await waitFor(() => { - expect( - screen.getByTestId('deleteActionItemPreviewModalBtn'), - ).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('deleteActionItemPreviewModalBtn')); - await wait(); - expect( - screen.getByText(translations.deleteActionItemMsg), - ).toBeInTheDocument(); - userEvent.click(screen.getByText('Yes')); - await wait(); - - expect(toast.success).toBeCalledWith(translations.successfulDeletion); - }); - - test('Testing delete action item modal and does not delete the record', async () => { - window.location.assign('/event/111/123'); - render( - - - - - - {} - - - - - , - ); - await wait(); - expect( - screen.getAllByTestId('previewActionItemModalBtn')[0], - ).toBeInTheDocument(); - userEvent.click(screen.getAllByTestId('previewActionItemModalBtn')[0]); - - await waitFor(() => { - expect( - screen.getByTestId('deleteActionItemPreviewModalBtn'), - ).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('deleteActionItemPreviewModalBtn')); - await wait(); - expect( - screen.getByText(translations.deleteActionItemMsg), - ).toBeInTheDocument(); - userEvent.click(screen.getByText('No')); - await wait(); - expect(screen.getByRole('dialog')).toBeInTheDocument(); - expect( - screen.getByText(translations.actionItemDetails), - ).toBeInTheDocument(); - }); - - test('toasts error on unsuccessful deletion', async () => { - window.location.assign('/event/111/123'); - render( - - - - - - {} - - - - - , - ); - await wait(); - - expect( - screen.getAllByTestId('previewActionItemModalBtn')[0], - ).toBeInTheDocument(); - userEvent.click(screen.getAllByTestId('previewActionItemModalBtn')[0]); - - await waitFor(() => { - return expect( - screen.findByTestId('previewActionItemModalCloseBtn'), - ).resolves.toBeInTheDocument(); - }); - - await waitFor(() => { - expect( - screen.getByTestId('deleteActionItemPreviewModalBtn'), - ).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('deleteActionItemPreviewModalBtn')); - - await waitFor(() => { - return expect( - screen.findByTestId('actionItemDeleteModalCloseBtn'), - ).resolves.toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('deleteActionItemBtn')); - - await waitFor(() => { - expect(toast.error).toHaveBeenCalled(); - }); - }); - - test('toasts error on unsuccessful updation', async () => { - window.location.assign('/event/111/123'); - render( - - - - - - {} - - - - - , - ); - await wait(); - - await waitFor(() => { - expect( - screen.getAllByTestId('editActionItemModalBtn')[0], - ).toBeInTheDocument(); - }); - userEvent.click(screen.getAllByTestId('editActionItemModalBtn')[0]); - - await waitFor(() => { - expect(screen.getByTestId('formUpdateAssignee')).toBeInTheDocument(); - }); - - userEvent.selectOptions( - screen.getByTestId('formUpdateAssignee'), - formData.assignee, - ); - - const preCompletionNotes = screen.getByPlaceholderText( - translations.preCompletionNotes, - ); - fireEvent.change(preCompletionNotes, { target: { value: '' } }); - userEvent.type(preCompletionNotes, formData.preCompletionNotes); - - const dueDatePicker = screen.getByLabelText(translations.dueDate); - fireEvent.change(dueDatePicker, { - target: { value: formData.dueDate }, - }); - - const completionDatePicker = screen.getByLabelText( - translations.completionDate, - ); - fireEvent.change(completionDatePicker, { - target: { value: formData.completionDate }, - }); - - await waitFor(() => { - expect( - screen.getByTestId('updateActionItemFormSubmitBtn'), - ).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('updateActionItemFormSubmitBtn')); - - await waitFor(() => { - expect(toast.error).toHaveBeenCalled(); - }); - }); - - test('Raises an error when incorrect information is filled while creation', async () => { - window.location.assign('/event/111/123'); - render( - - - - - - {} - - - - - , - ); - await wait(); - userEvent.click(screen.getByTestId('createEventActionItemBtn')); - - await wait(); - expect( - screen.getByText(translations.actionItemDetails), - ).toBeInTheDocument(); - - fireEvent.change( - screen.getByPlaceholderText(translations.preCompletionNotes), - { - target: { value: 'task to be done with high priority' }, - }, - ); - expect( - screen.getByPlaceholderText(translations.preCompletionNotes), - ).toHaveValue('task to be done with high priority'); - - fireEvent.change(screen.getByLabelText(translations.dueDate), { - target: { value: '04/05/2024' }, - }); - expect(screen.getByLabelText(translations.dueDate)).toHaveValue( - '04/05/2024', - ); - - userEvent.click(screen.getByTestId('createActionItemFormSubmitBtn')); - await wait(); - - expect(toast.error).toBeCalled(); - }); - - test('Raises an error when incorrect information is filled while updation', async () => { - window.location.assign('/event/111/123'); - render( - - - - - - {} - - - - - , - ); - await wait(); - const updateButtons = screen.getAllByTestId('editActionItemModalBtn'); - userEvent.click(updateButtons[0]); - - expect( - screen.getByText(translations.actionItemDetails), - ).toBeInTheDocument(); - - userEvent.click(screen.getByTestId('updateActionItemFormSubmitBtn')); - - await wait(); - - expect(toast.error).toBeCalled(); - }); - - test('Displays message when no data is available', async () => { - window.location.assign('/event/111/123'); - render( - - - - - - {} - - - - - , - ); - await wait(); - expect(screen.getByText('Nothing Found !!')).toBeInTheDocument(); - }); - - test('Testing update action modal to have correct initial values', async () => { - window.location.assign('/event/111/123'); - render( - - - - - - {} - - - - - , - ); - await wait(); - const updateButtons = screen.getAllByTestId('editActionItemModalBtn'); - userEvent.click(updateButtons[0]); - - expect(screen.getByText('Action Item Details')).toBeInTheDocument(); - const assigneeDropdown = screen.getByTestId( - 'formUpdateAssignee', - ) as HTMLSelectElement; - expect(assigneeDropdown.value).toBe('658930fd2caa9d8d6908745c'); - expect(assigneeDropdown).toHaveTextContent('Teresa Bradley'); - - expect( - screen.getByPlaceholderText(translations.preCompletionNotes), - ).toHaveValue('Pre Completion Notes'); - const editActionItem = screen.getByRole('button', { - name: translations.editActionItem, - }); - expect(editActionItem).toBeInTheDocument(); - }); -}); diff --git a/src/components/EventManagement/EventActionItems/EventActionItems.tsx b/src/components/EventManagement/EventActionItems/EventActionItems.tsx deleted file mode 100644 index cbe878fa07..0000000000 --- a/src/components/EventManagement/EventActionItems/EventActionItems.tsx +++ /dev/null @@ -1,599 +0,0 @@ -import { useMutation, useQuery } from '@apollo/client'; -import type { Dayjs } from 'dayjs'; -import dayjs from 'dayjs'; -import type { ChangeEvent } from 'react'; -import React, { useEffect, useState } from 'react'; -import { Button, Form } from 'react-bootstrap'; -import { useTranslation } from 'react-i18next'; -import { toast } from 'react-toastify'; -import styles from './EventActionItems.module.css'; -import { DataGrid } from '@mui/x-data-grid'; -import type { GridCellParams } from '@mui/x-data-grid'; -import { Stack } from '@mui/material'; -import Modal from 'react-bootstrap/Modal'; -import { - CREATE_ACTION_ITEM_MUTATION, - DELETE_ACTION_ITEM_MUTATION, - UPDATE_ACTION_ITEM_MUTATION, -} from 'GraphQl/Mutations/ActionItemMutations'; -import type { - InterfaceActionItemCategoryList, - InterfaceActionItemInfo, - InterfaceMembersList, -} from 'utils/interfaces'; -import { DatePicker } from '@mui/x-date-pickers'; -import { - ACTION_ITEM_CATEGORY_LIST, - MEMBERS_LIST, -} from 'GraphQl/Queries/Queries'; -import { ACTION_ITEM_LIST_BY_EVENTS } from 'GraphQl/Queries/ActionItemQueries'; -import { useEventActionColumnConfig } from './useEventActionColumnConfig'; -import ActionItemPreviewModal from 'screens/OrganizationActionItems/ActionItemPreviewModal'; -import ActionItemDeleteModal from 'screens/OrganizationActionItems/ActionItemDeleteModal'; - -function eventActionItems(props: { eventId: string }): JSX.Element { - const { eventId } = props; - const { t } = useTranslation('translation', { - keyPrefix: 'eventActionItems', - }); - const { t: tCommon } = useTranslation('common'); - - const [actionItemPreviewModalIsOpen, setActionItemPreviewModalIsOpen] = - useState(false); - const [actionItemStatusModal, setActionItemStatusModal] = useState(false); - const [isActionItemCompleted, setIsActionItemCompleted] = useState(false); - const [assignmentDate, setAssignmentDate] = useState(new Date()); - const [actionItemCreateModalIsOpen, setActionItemCreateModalIsOpen] = - useState(false); - const [actionItemUpdateModalIsOpen, setActionItemUpdateModalIsOpen] = - useState(false); - const [actionItemDeleteModalIsOpen, setActionItemDeleteModalIsOpen] = - useState(false); - const [dueDate, setDueDate] = useState(new Date()); - const [completionDate, setCompletionDate] = useState(new Date()); - const [actionItemId, setActionItemId] = useState(''); - document.title = t('title'); - const url: string = window.location.href; - const startIdx: number = url.indexOf('/event/') + '/event/'.length; - const orgId: string = url.slice(startIdx, url.indexOf('/', startIdx)); - const [formState, setFormState] = useState({ - actionItemCategoryId: '', - assignee: '', - assigner: '', - assigneeId: '', - preCompletionNotes: '', - postCompletionNotes: '', - isCompleted: false, - }); - const showCreateModal = (): void => { - const newState = !actionItemCreateModalIsOpen; - setActionItemCreateModalIsOpen(newState); - }; - const hideCreateModal = (): void => { - setActionItemCreateModalIsOpen(!actionItemCreateModalIsOpen); - }; - const showUpdateModal = (): void => { - setActionItemUpdateModalIsOpen(!actionItemUpdateModalIsOpen); - }; - const hideUpdateModal = (): void => { - setActionItemId(''); - setActionItemUpdateModalIsOpen(!actionItemUpdateModalIsOpen); - }; - const toggleDeleteModal = (): void => { - setActionItemDeleteModalIsOpen(!actionItemDeleteModalIsOpen); - }; - const setActionItemState = (actionItem: InterfaceActionItemInfo): void => { - setFormState((prevState) => ({ - ...prevState, - assignee: `${actionItem.assignee.firstName} ${actionItem.assignee.lastName}`, - assigner: `${actionItem.assigner.firstName} ${actionItem.assigner.lastName}`, - assigneeId: actionItem.assignee._id, - preCompletionNotes: actionItem.preCompletionNotes, - postCompletionNotes: actionItem.postCompletionNotes, - isCompleted: actionItem.isCompleted, - })); - setActionItemId(actionItem._id); - setDueDate(actionItem.dueDate); - setAssignmentDate(actionItem.assignmentDate); - setCompletionDate(actionItem.completionDate); - }; - const { - data: actionItemCategoriesData, - }: { - data: InterfaceActionItemCategoryList | undefined; - loading: boolean; - error?: Error | undefined; - } = useQuery(ACTION_ITEM_CATEGORY_LIST, { - variables: { - organizationId: orgId, - }, - }); - const actionItemCategories = - actionItemCategoriesData?.actionItemCategoriesByOrganization.filter( - (category) => !category.isDisabled, - ); - const { data: actionItemsData, refetch: actionItemsRefetch } = useQuery( - ACTION_ITEM_LIST_BY_EVENTS, - { - variables: { - eventId, - }, - }, - ); - const { - data: membersData, - }: { - data: InterfaceMembersList | undefined; - loading: boolean; - error?: Error | undefined; - } = useQuery(MEMBERS_LIST, { - variables: { id: orgId }, - }); - const [createActionItem] = useMutation(CREATE_ACTION_ITEM_MUTATION); - const createActionItemHandler = async ( - e: ChangeEvent, - ): Promise => { - e.preventDefault(); - try { - await createActionItem({ - variables: { - assigneeId: formState.assigneeId, - actionItemCategoryId: formState.actionItemCategoryId, - eventId, - preCompletionNotes: formState.preCompletionNotes, - dueDate: dayjs(dueDate).format('YYYY-MM-DD'), - }, - }); - setFormState({ - actionItemCategoryId: '', - assignee: '', - assigner: '', - assigneeId: '', - preCompletionNotes: '', - postCompletionNotes: '', - isCompleted: false, - }); - setDueDate(new Date()); - actionItemsRefetch(); - hideCreateModal(); - toast.success(t('successfulCreation')); - } catch (error: unknown) { - if (error instanceof Error) { - toast.error(error.message); - } - } - }; - useEffect(() => { - actionItemsRefetch({ - eventId, - }); - }, []); - const [updateActionItem] = useMutation(UPDATE_ACTION_ITEM_MUTATION); - const updateActionItemHandler = async ( - e: ChangeEvent, - ): Promise => { - e.preventDefault(); - try { - await updateActionItem({ - variables: { - actionItemId, - assigneeId: formState.assigneeId, - preCompletionNotes: formState.preCompletionNotes, - postCompletionNotes: formState.postCompletionNotes, - dueDate: dayjs(dueDate).format('YYYY-MM-DD'), - completionDate: dayjs(completionDate).format('YYYY-MM-DD'), - isCompleted: formState.isCompleted, - }, - }); - actionItemsRefetch(); - hideUpdateModal(); - hideActionItemStatusModal(); - toast.success(t('successfulUpdation')); - } catch (error: unknown) { - if (error instanceof Error) { - toast.error(error.message); - } - } - }; - const [removeActionItem] = useMutation(DELETE_ACTION_ITEM_MUTATION); - const deleteActionItemHandler = async (): Promise => { - try { - await removeActionItem({ - variables: { - actionItemId, - }, - }); - actionItemsRefetch(); - toggleDeleteModal(); - hidePreviewModal(); - toast.success(t('successfulDeletion')); - } catch (error: unknown) { - if (error instanceof Error) { - toast.error(error.message); - console.log(error.message); - } - } - }; - - const handleActionItemStatusChange = ( - actionItem: InterfaceActionItemInfo, - ): void => { - actionItem = { ...actionItem, isCompleted: !actionItem.isCompleted }; - setIsActionItemCompleted(!actionItem.isCompleted); - setActionItemState(actionItem); - setActionItemStatusModal(true); - }; - - const showPreviewModal = (actionItem: InterfaceActionItemInfo): void => { - setActionItemState(actionItem); - setActionItemPreviewModalIsOpen(true); - }; - - const handleEditClick = (actionItem: InterfaceActionItemInfo): void => { - setActionItemId(actionItem._id); - setActionItemState(actionItem); - showUpdateModal(); - }; - - const hidePreviewModal = (): void => { - setActionItemPreviewModalIsOpen(false); - }; - - const hideActionItemStatusModal = (): void => { - setActionItemStatusModal(false); - setActionItemUpdateModalIsOpen(false); - }; - - const { columns } = useEventActionColumnConfig({ - eventId, - handleActionItemStatusChange, - showPreviewModal, - handleEditClick, - }); - - return ( - <> - -
    - {/* create action item modal */} - - -

    {t('actionItemDetails')}

    - -
    - - - - {t('actionItemCategory')} - - setFormState({ - ...formState, - actionItemCategoryId: e.target.value, - }) - } - > - - {actionItemCategories?.map((category, index) => ( - - ))} - - - - {t('assignee')} - - setFormState({ ...formState, assigneeId: e.target.value }) - } - > - - {membersData?.organizations[0].members?.map((member, index) => ( - - ))} - - - - { - setFormState({ - ...formState, - preCompletionNotes: e.target.value, - }); - }} - /> -
    - { - if (date) { - setDueDate(date?.toDate()); - } - }} - /> -
    - - -
    -
    - {/* update action items modal */} - - -

    {t('actionItemDetails')}

    - -
    - -
    - - Assignee - - setFormState({ ...formState, assigneeId: e.target.value }) - } - > - - {membersData?.organizations[0].members.map((member, index) => { - const currMemberName = `${member.firstName} ${member.lastName}`; - if (currMemberName !== formState.assignee) { - return ( - - ); - } - })} - - - - { - setFormState({ - ...formState, - preCompletionNotes: e.target.value, - }); - }} - /> -
    - { - if (date) { - setDueDate(date?.toDate()); - } - }} - /> -   - { - /* istanbul ignore next */ - if (date) { - setCompletionDate(date?.toDate()); - } - } - } - /> -
    -
    - -
    - -
    -
    - - {/* preview modal */} - - - {/* Delete Modal */} - - - {/* action item status change modal */} - - -

    {t('actionItemStatus')}

    - -
    - -
    - - {isActionItemCompleted - ? t('preCompletionNotes') - : t('postCompletionNotes')} - - { - if (isActionItemCompleted) { - setFormState({ - ...formState, - preCompletionNotes: e.target.value, - }); - } else { - setFormState({ - ...formState, - postCompletionNotes: e.target.value, - }); - } - }} - /> - - -
    -
    - {actionItemsData && ( -
    - row._id} - slots={{ - noRowsOverlay: () => ( - - Nothing Found !! - - ), - }} - sx={{ - '&.MuiDataGrid-root .MuiDataGrid-cell:focus-within': { - outline: 'none !important', - }, - '&.MuiDataGrid-root .MuiDataGrid-columnHeader:focus-within': { - outline: 'none', - }, - '& .MuiDataGrid-row:hover': { - backgroundColor: 'transparent', - }, - '& .MuiDataGrid-row.Mui-hovered': { - backgroundColor: 'transparent', - }, - '& .MuiDataGrid-columnHeaderTitle': { - fontWeight: 700, - }, - }} - getRowClassName={() => `${styles.rowBackground}`} - autoHeight - rowHeight={50} - columnHeaderHeight={40} - rows={actionItemsData?.actionItemsByEvent?.map( - (item: object, index: number) => ({ - ...item, - index: index + 1, - }), - )} - columns={columns} - isRowSelectable={() => false} - /> -
    - )} - - ); -} -export default eventActionItems; diff --git a/src/components/EventManagement/EventActionItems/useEventActionColumnConfig.tsx b/src/components/EventManagement/EventActionItems/useEventActionColumnConfig.tsx deleted file mode 100644 index 0db74323f6..0000000000 --- a/src/components/EventManagement/EventActionItems/useEventActionColumnConfig.tsx +++ /dev/null @@ -1,200 +0,0 @@ -import React from 'react'; -import type { GridCellParams, GridColDef } from '@mui/x-data-grid'; -import { Link } from 'react-router-dom'; -import { Button, OverlayTrigger, Popover } from 'react-bootstrap'; -import styles from './EventActionItems.module.css'; -import type { InterfaceActionItemInfo } from 'utils/interfaces'; -import { useTranslation } from 'react-i18next'; - -export type Props = { - eventId: string; - handleActionItemStatusChange: (actionItem: InterfaceActionItemInfo) => void; - showPreviewModal: (actionItem: InterfaceActionItemInfo) => void; - handleEditClick: (actionItem: InterfaceActionItemInfo) => void; -}; - -type ColumnConfig = { - columns: GridColDef[]; -}; - -const popover = ( - actionItemId: string, - actionItemNotes: string, -): JSX.Element => { - return ( - - {actionItemNotes} - - ); -}; - -export const useEventActionColumnConfig = ({ - eventId, - handleActionItemStatusChange, - showPreviewModal, - handleEditClick, -}: Props): ColumnConfig => { - const { t } = useTranslation('translation', { - keyPrefix: 'eventActionItems', - }); - const columns: GridColDef[] = [ - { - field: 'serialNo', - headerName: '#', - flex: 1, - minWidth: 50, - align: 'center', - headerAlign: 'center', - headerClassName: `${styles.tableHeader}`, - sortable: false, - renderCell: (params: GridCellParams) => { - return params.row?.index; - }, - }, - { - field: 'assignee', - headerName: 'Assignee', - flex: 2, - minWidth: 150, - align: 'center', - headerAlign: 'center', - headerClassName: `${styles.tableHeader}`, - sortable: false, - renderCell: (params: GridCellParams) => { - return ( - - {params.row?.assignee.firstName + - ' ' + - params.row?.assignee.lastName} - - ); - }, - }, - { - field: 'actionItemCategory', - headerName: 'Action Item Category', - flex: 2, - minWidth: 100, - align: 'center', - headerAlign: 'center', - headerClassName: `${styles.tableHeader}`, - sortable: false, - renderCell: (params: GridCellParams) => { - return params.row.actionItemCategory.name; - }, - }, - { - field: 'notes', - headerName: 'Notes', - minWidth: 150, - align: 'center', - headerAlign: 'center', - headerClassName: `${styles.tableHeader}`, - flex: 2, - sortable: false, - renderCell: (params: GridCellParams) => { - const actionItem = params.row; - return ( - - - {actionItem.preCompletionNotes.length > 25 - ? `${actionItem.preCompletionNotes.substring(0, 25)}...` - : actionItem.preCompletionNotes} - - - ); - }, - }, - { - field: 'completionNotes', - headerName: 'Completion Notes', - minWidth: 150, - align: 'center', - headerAlign: 'center', - headerClassName: `${styles.tableHeader}`, - flex: 2, - sortable: false, - renderCell: (params: GridCellParams) => { - const actionItem = params.row; - return actionItem.isCompleted ? ( - - - {actionItem.postCompletionNotes?.length > 25 - ? `${actionItem.postCompletionNotes.substring(0, 25)}...` - : actionItem.postCompletionNotes} - - - ) : ( - - {t('actionItemActive')} - - ); - }, - }, - { - field: 'options', - headerName: 'Options', - flex: 2, - minWidth: 100, - align: 'center', - headerAlign: 'center', - headerClassName: `${styles.tableHeader}`, - sortable: false, - renderCell: (params: GridCellParams) => { - return ( -
    - handleActionItemStatusChange(params.row)} - /> - - -
    - ); - }, - }, - ]; - return { - columns, - }; -}; diff --git a/src/components/EventManagement/EventAgendaItems/EventAgendaItems.test.tsx b/src/components/EventManagement/EventAgendaItems/EventAgendaItems.test.tsx index b1b3ed6094..3bce7ad11e 100644 --- a/src/components/EventManagement/EventAgendaItems/EventAgendaItems.test.tsx +++ b/src/components/EventManagement/EventAgendaItems/EventAgendaItems.test.tsx @@ -14,7 +14,7 @@ import { I18nextProvider } from 'react-i18next'; import { Provider } from 'react-redux'; import { BrowserRouter } from 'react-router-dom'; import i18n from 'utils/i18nForTest'; -import { toast } from 'react-toastify'; +// import { toast } from 'react-toastify'; import { LocalizationProvider } from '@mui/x-date-pickers'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; @@ -26,7 +26,7 @@ import EventAgendaItems from './EventAgendaItems'; import { MOCKS, MOCKS_ERROR_QUERY, - MOCKS_ERROR_MUTATION, + // MOCKS_ERROR_MUTATION, } from './EventAgendaItemsMocks'; jest.mock('react-toastify', () => ({ @@ -41,6 +41,15 @@ jest.mock('react-router-dom', () => ({ useParams: () => ({ eventId: '123' }), })); +//temporarily fixes react-beautiful-dnd droppable method's depreciation error +//needs to be fixed in React 19 +jest.spyOn(console, 'error').mockImplementation((message) => { + if (message.includes('Support for defaultProps will be removed')) { + return; + } + console.error(message); +}); + async function wait(ms = 100): Promise { await act(() => { return new Promise((resolve) => { @@ -51,7 +60,7 @@ async function wait(ms = 100): Promise { const link = new StaticMockLink(MOCKS, true); const link2 = new StaticMockLink(MOCKS_ERROR_QUERY, true); -const link3 = new StaticMockLink(MOCKS_ERROR_MUTATION, true); +// const link3 = new StaticMockLink(MOCKS_ERROR_MUTATION, true); const translations = JSON.parse( JSON.stringify(i18n.getDataByLanguage('en')?.translation.agendaItems), diff --git a/src/components/EventManagement/EventAgendaItems/EventAgendaItems.tsx b/src/components/EventManagement/EventAgendaItems/EventAgendaItems.tsx index 09cc560bf1..b49ade4626 100644 --- a/src/components/EventManagement/EventAgendaItems/EventAgendaItems.tsx +++ b/src/components/EventManagement/EventAgendaItems/EventAgendaItems.tsx @@ -23,6 +23,13 @@ import AgendaItemsCreateModal from 'components/AgendaItems/AgendaItemsCreateModa import styles from './EventAgendaItems.module.css'; import Loader from 'components/Loader/Loader'; +/** + * Component to manage and display agenda items for a specific event. + * + * @param props - The component props. + * @param eventId - The ID of the event to manage agenda items for. + * @returns The rendered component. + */ function EventAgendaItems(props: { eventId: string }): JSX.Element { const { eventId } = props; @@ -30,13 +37,16 @@ function EventAgendaItems(props: { eventId: string }): JSX.Element { keyPrefix: 'agendaItems', }); + // Extract organization ID from URL const url: string = window.location.href; const startIdx: number = url.indexOf('/event/') + '/event/'.length; const orgId: string = url.slice(startIdx, url.indexOf('/', startIdx)); + // State to manage the create agenda item modal visibility const [agendaItemCreateModalIsOpen, setAgendaItemCreateModalIsOpen] = useState(false); + // State to manage form values const [formState, setFormState] = useState({ agendaItemCategoryIds: [''], title: '', @@ -46,6 +56,7 @@ function EventAgendaItems(props: { eventId: string }): JSX.Element { urls: [''], }); + // Query for agenda item categories const { data: agendaCategoryData, loading: agendaCategoryLoading, @@ -59,6 +70,7 @@ function EventAgendaItems(props: { eventId: string }): JSX.Element { notifyOnNetworkStatusChange: true, }); + // Query for agenda items by event const { data: agendaItemData, loading: agendaItemLoading, @@ -74,8 +86,14 @@ function EventAgendaItems(props: { eventId: string }): JSX.Element { notifyOnNetworkStatusChange: true, }); + // Mutation for creating an agenda item const [createAgendaItem] = useMutation(CREATE_AGENDA_ITEM_MUTATION); + /** + * Handler for creating a new agenda item. + * + * @param e - The form submit event. + */ const createAgendaItemHandler = async ( e: ChangeEvent, ): Promise => { @@ -97,6 +115,7 @@ function EventAgendaItems(props: { eventId: string }): JSX.Element { }, }); + // Reset form state and hide modal setFormState({ title: '', description: '', @@ -107,7 +126,7 @@ function EventAgendaItems(props: { eventId: string }): JSX.Element { }); hideCreateModal(); refetchAgendaItem(); - toast.success(t('agendaItemCreated')); + toast.success(t('agendaItemCreated') as string); } catch (error: unknown) { if (error instanceof Error) { toast.error(error.message); @@ -115,31 +134,39 @@ function EventAgendaItems(props: { eventId: string }): JSX.Element { } }; + /** + * Toggles the visibility of the create agenda item modal. + */ const showCreateModal = (): void => { setAgendaItemCreateModalIsOpen(!agendaItemCreateModalIsOpen); }; + /** + * Hides the create agenda item modal. + */ const hideCreateModal = (): void => { setAgendaItemCreateModalIsOpen(!agendaItemCreateModalIsOpen); }; + // Show loader while data is loading if (agendaItemLoading || agendaCategoryLoading) return ; + // Show error message if there is an error loading data if (agendaItemError || agendaCategoryError) { + const errorMessage = + agendaCategoryError?.message || + (agendaItemError as Error)?.message || + 'Unknown error'; + return (
    Error occurred while loading{' '} - {agendaCategoryError - ? 'Agenda Categories' - : agendaItemError && 'Agenda Items'} - Data + {agendaCategoryError ? 'Agenda Categories' : 'Agenda Items'} Data
    - {agendaCategoryError - ? agendaCategoryError.message - : agendaItemError && (agendaItemError as Error).message} + {errorMessage}
    diff --git a/src/components/EventRegistrantsModal/EventRegistrantsModal.tsx b/src/components/EventRegistrantsModal/EventRegistrantsModal.tsx index 811dd44941..bd2adc8a2c 100644 --- a/src/components/EventRegistrantsModal/EventRegistrantsModal.tsx +++ b/src/components/EventRegistrantsModal/EventRegistrantsModal.tsx @@ -15,6 +15,7 @@ import TextField from '@mui/material/TextField'; import Autocomplete from '@mui/material/Autocomplete'; import { useTranslation } from 'react-i18next'; +// Props for the EventRegistrantsModal component type ModalPropType = { show: boolean; eventId: string; @@ -22,23 +23,38 @@ type ModalPropType = { handleClose: () => void; }; +// User information interface interface InterfaceUser { _id: string; firstName: string; lastName: string; } +/** + * Modal component for managing event registrants. + * Allows adding and removing attendees from an event. + * + * @param show - Whether the modal is visible or not. + * @param eventId - The ID of the event. + * @param orgId - The ID of the organization. + * @param handleClose - Function to close the modal. + * @returns JSX element representing the modal. + */ export const EventRegistrantsModal = (props: ModalPropType): JSX.Element => { const { eventId, orgId, handleClose, show } = props; const [member, setMember] = useState(null); + // Hooks for mutation operations const [addRegistrantMutation] = useMutation(ADD_EVENT_ATTENDEE); const [removeRegistrantMutation] = useMutation(REMOVE_EVENT_ATTENDEE); + // Translation hooks const { t } = useTranslation('translation', { keyPrefix: 'eventRegistrantsModal', }); const { t: tCommon } = useTranslation('common'); + + // Query hooks to fetch event attendees and organization members const { data: attendeesData, loading: attendeesLoading, @@ -51,6 +67,7 @@ export const EventRegistrantsModal = (props: ModalPropType): JSX.Element => { variables: { id: orgId }, }); + // Function to add a new registrant to the event const addRegistrant = (): void => { if (member == null) { toast.warning('Please choose an user to add first!'); @@ -64,15 +81,18 @@ export const EventRegistrantsModal = (props: ModalPropType): JSX.Element => { }, }) .then(() => { - toast.success(tCommon('addedSuccessfully', { item: 'Attendee' })); - attendeesRefetch(); + toast.success( + tCommon('addedSuccessfully', { item: 'Attendee' }) as string, + ); + attendeesRefetch(); // Refresh the list of attendees }) .catch((err) => { - toast.error(t('errorAddingAttendee')); + toast.error(t('errorAddingAttendee') as string); toast.error(err.message); }); }; + // Function to remove a registrant from the event const deleteRegistrant = (userId: string): void => { toast.warn('Removing the attendee...'); removeRegistrantMutation({ @@ -82,16 +102,18 @@ export const EventRegistrantsModal = (props: ModalPropType): JSX.Element => { }, }) .then(() => { - toast.success(tCommon('removedSuccessfully', { item: 'Attendee' })); - attendeesRefetch(); + toast.success( + tCommon('removedSuccessfully', { item: 'Attendee' }) as string, + ); + attendeesRefetch(); // Refresh the list of attendees }) .catch((err) => { - toast.error(t('errorRemovingAttendee')); + toast.error(t('errorRemovingAttendee') as string); toast.error(err.message); }); }; - // Render the loading screen + // Show a loading screen if data is still being fetched if (attendeesLoading || memberLoading) { return ( <> diff --git a/src/components/EventRegistrantsModal/EventRegistrantsWrapper.tsx b/src/components/EventRegistrantsModal/EventRegistrantsWrapper.tsx index b621f8673a..b198fcdd6d 100644 --- a/src/components/EventRegistrantsModal/EventRegistrantsWrapper.tsx +++ b/src/components/EventRegistrantsModal/EventRegistrantsWrapper.tsx @@ -4,22 +4,35 @@ import { Button } from 'react-bootstrap'; import IconComponent from 'components/IconComponent/IconComponent'; import styles from './EventRegistrantsWrapper.module.css'; +// Props for the EventRegistrantsWrapper component type PropType = { eventId: string; orgId: string; }; -export const EventRegistrantsWrapper = (props: PropType): JSX.Element => { +/** + * Wrapper component that displays a button to show the event registrants modal. + * + * @param eventId - The ID of the event. + * @param orgId - The ID of the organization. + * @returns JSX element representing the wrapper with a button to show the modal. + */ +export const EventRegistrantsWrapper = ({ + eventId, + orgId, +}: PropType): JSX.Element => { + // State to control the visibility of the modal const [showModal, setShowModal] = useState(false); return ( <> + {/* Button to open the event registrants modal */} + {/* Render the EventRegistrantsModal if showModal is true */} {showModal && ( { - setShowModal(false); + setShowModal(false); // Hide the modal when closed }} - eventId={props.eventId} - orgId={props.orgId} + eventId={eventId} + orgId={orgId} /> )} diff --git a/src/components/EventStats/EventStats.tsx b/src/components/EventStats/EventStats.tsx index c9f1a70e8d..ce1e55e4bc 100644 --- a/src/components/EventStats/EventStats.tsx +++ b/src/components/EventStats/EventStats.tsx @@ -8,22 +8,33 @@ import eventStatsStyles from './EventStats.module.css'; import { useQuery } from '@apollo/client'; import { EVENT_FEEDBACKS } from 'GraphQl/Queries/Queries'; +// Props for the EventStats component type ModalPropType = { show: boolean; eventId: string; handleClose: () => void; }; +/** + * Component that displays event statistics in a modal. + * Shows feedback, reviews, and average rating for the event. + * + * @param show - Whether the modal is visible or not. + * @param handleClose - Function to close the modal. + * @param eventId - The ID of the event. + * @returns JSX element representing the event statistics modal. + */ export const EventStats = ({ show, handleClose, eventId, }: ModalPropType): JSX.Element => { + // Query to fetch event feedback data const { data, loading } = useQuery(EVENT_FEEDBACKS, { variables: { id: eventId }, }); - // Render the loading screen + // Show a loading screen while data is being fetched if (loading) { return ( <> @@ -36,7 +47,7 @@ export const EventStats = ({ <> Event Statistics + {/* Render feedback statistics */}
    + {/* Render review statistics and average rating */}
    diff --git a/src/components/EventStats/EventStatsWrapper.tsx b/src/components/EventStats/EventStatsWrapper.tsx index b501e77430..fb701a00da 100644 --- a/src/components/EventStats/EventStatsWrapper.tsx +++ b/src/components/EventStats/EventStatsWrapper.tsx @@ -4,21 +4,30 @@ import { Button } from 'react-bootstrap'; import IconComponent from 'components/IconComponent/IconComponent'; import styles from './EventStatsWrapper.module.css'; +// Props for the EventStatsWrapper component type PropType = { eventId: string; }; -export const EventStatsWrapper = (props: PropType): JSX.Element => { +/** + * Wrapper component that displays a button to show event statistics. + * + * @param eventId - The ID of the event. + * @returns JSX element representing the wrapper with a button to view event statistics. + */ +export const EventStatsWrapper = ({ eventId }: PropType): JSX.Element => { + // State to control the visibility of the EventStats component const [showModal, setShowModal] = useState(false); return ( <> + {/* Button to open the event statistics view */} + + {/* Render the EventStats component if showModal is true */} setShowModal(false)} - key={props.eventId || 'eventStatsDetails'} - eventId={props.eventId} + handleClose={(): void => setShowModal(false)} // Hide the EventStats component when closed + key={eventId || 'eventStatsDetails'} // Use eventId as key for the component + eventId={eventId} /> ); diff --git a/src/components/EventStats/Statistics/AverageRating.tsx b/src/components/EventStats/Statistics/AverageRating.tsx index 6dcfa03b3f..9f1a157e01 100644 --- a/src/components/EventStats/Statistics/AverageRating.tsx +++ b/src/components/EventStats/Statistics/AverageRating.tsx @@ -5,6 +5,7 @@ import FavoriteIcon from '@mui/icons-material/Favorite'; import FavoriteBorderIcon from '@mui/icons-material/FavoriteBorder'; import Typography from '@mui/material/Typography'; +// Props for the AverageRating component type ModalPropType = { data: { event: { @@ -15,12 +16,20 @@ type ModalPropType = { }; }; +// Type representing individual feedback type FeedbackType = { _id: string; rating: number; review: string | null; }; +/** + * Component that displays the average rating for an event. + * Shows a rating value and a star rating icon. + * + * @param data - Data containing the average feedback score to be displayed. + * @returns JSX element representing the average rating card with a star rating. + */ export const AverageRating = ({ data }: ModalPropType): JSX.Element => { return ( <> @@ -43,10 +52,10 @@ export const AverageRating = ({ data }: ModalPropType): JSX.Element => { emptyIcon={} sx={{ '& .MuiRating-iconFilled': { - color: '#ff6d75', + color: '#ff6d75', // Color for filled stars }, '& .MuiRating-iconHover': { - color: '#ff3d47', + color: '#ff3d47', // Color for star on hover }, }} /> diff --git a/src/components/EventStats/Statistics/Feedback.tsx b/src/components/EventStats/Statistics/Feedback.tsx index a4a9e41430..a6a255828f 100644 --- a/src/components/EventStats/Statistics/Feedback.tsx +++ b/src/components/EventStats/Statistics/Feedback.tsx @@ -6,6 +6,7 @@ import { } from '@mui/x-charts/PieChart'; import Card from 'react-bootstrap/Card'; +// Props for the FeedbackStats component type ModalPropType = { data: { event: { @@ -16,13 +17,22 @@ type ModalPropType = { }; }; +// Type representing individual feedback type FeedbackType = { _id: string; rating: number; review: string | null; }; +/** + * Component that displays a pie chart of feedback ratings for an event. + * Shows how many people gave each rating. + * + * @param data - Data containing event feedback to be displayed in the chart. + * @returns JSX element representing the feedback analysis card with a pie chart. + */ export const FeedbackStats = ({ data }: ModalPropType): JSX.Element => { + // Colors for the pie chart slices, from green (high ratings) to red (low ratings) const ratingColors = [ '#57bb8a', // Green '#94bd77', @@ -32,6 +42,7 @@ export const FeedbackStats = ({ data }: ModalPropType): JSX.Element => { '#dd776e', // Red ]; + // Count the number of feedbacks for each rating const count: Record = {}; data.event.feedback.forEach((feedback: FeedbackType) => { @@ -39,6 +50,7 @@ export const FeedbackStats = ({ data }: ModalPropType): JSX.Element => { else count[feedback.rating] = 1; }); + // Prepare data for the pie chart const chartData = []; for (let rating = 0; rating <= 5; rating++) { if (rating in count) diff --git a/src/components/EventStats/Statistics/Review.tsx b/src/components/EventStats/Statistics/Review.tsx index 0afc687023..343a8107c3 100644 --- a/src/components/EventStats/Statistics/Review.tsx +++ b/src/components/EventStats/Statistics/Review.tsx @@ -2,6 +2,7 @@ import React from 'react'; import Card from 'react-bootstrap/Card'; import Rating from '@mui/material/Rating'; +// Props for the ReviewStats component type ModalPropType = { data: { event: { @@ -12,13 +13,22 @@ type ModalPropType = { }; }; +// Type representing individual feedback type FeedbackType = { _id: string; rating: number; review: string | null; }; +/** + * Component that displays reviews for an event. + * Shows a list of reviews with ratings and text. + * + * @param data - Data containing event feedback to be displayed. + * @returns JSX element representing the reviews card. + */ export const ReviewStats = ({ data }: ModalPropType): JSX.Element => { + // Filter out feedback that has a review const reviews = data.event.feedback.filter( (feedback: FeedbackType) => feedback.review != null, ); diff --git a/src/components/HolidayCards/HolidayCard.tsx b/src/components/HolidayCards/HolidayCard.tsx index 0235659ee2..56ac86405d 100644 --- a/src/components/HolidayCards/HolidayCard.tsx +++ b/src/components/HolidayCards/HolidayCard.tsx @@ -1,9 +1,17 @@ import React from 'react'; import styles from './HolidayCard.module.css'; +// Props for the HolidayCard component interface InterfaceHolidayList { holidayName: string; } + +/** + * Component that displays a card with the name of a holiday. + * + * @param props - Contains the holidayName to be displayed on the card. + * @returns JSX element representing a card with the holiday name. + */ const HolidayCard = (props: InterfaceHolidayList): JSX.Element => { /*istanbul ignore next*/ return
    {props?.holidayName}
    ; diff --git a/src/components/IconComponent/IconComponent.test.tsx b/src/components/IconComponent/IconComponent.test.tsx index e8faa75404..686a8e6f75 100644 --- a/src/components/IconComponent/IconComponent.test.tsx +++ b/src/components/IconComponent/IconComponent.test.tsx @@ -1,7 +1,12 @@ +import React from 'react'; import { render, screen } from '@testing-library/react'; import IconComponent from './IconComponent'; -import React from 'react'; + const screenTestIdMap: Record> = { + MyOrganizations: { + name: 'My Organizations', + testId: 'Icon-Component-MyOrganizationsIcon', + }, Dashboard: { name: 'Dashboard', testId: 'Icon-Component-DashboardIcon', @@ -10,6 +15,18 @@ const screenTestIdMap: Record> = { name: 'People', testId: 'Icon-Component-PeopleIcon', }, + Tags: { + name: 'Tags', + testId: 'Icon-Component-TagsIcon', + }, + Tag: { + name: 'Tag', + testId: 'Icon-Component-TagIcon', + }, + Requests: { + name: 'Requests', + testId: 'Icon-Component-RequestsIcon', + }, Events: { name: 'Events', testId: 'Icon-Component-EventsIcon', @@ -22,10 +39,6 @@ const screenTestIdMap: Record> = { name: 'Posts', testId: 'Icon-Component-PostsIcon', }, - Funds: { - name: 'Funds', - testId: 'Icon-Component-Funds', - }, BlockUnblock: { name: 'Block/Unblock', testId: 'Block/Icon-Component-UnblockIcon', @@ -38,11 +51,7 @@ const screenTestIdMap: Record> = { name: 'Settings', testId: 'Icon-Component-SettingsIcon', }, - AllOrganizations: { - name: 'My Organizations', - testId: 'Icon-Component-MyOrganizationsIcon', - }, - ListEventRegistrant: { + ListEventRegistrants: { name: 'List Event Registrants', testId: 'Icon-Component-List-Event-Registrants', }, @@ -50,18 +59,30 @@ const screenTestIdMap: Record> = { name: 'Check In Registrants', testId: 'Icon-Component-Check-In-Registrants', }, - EventStats: { - name: 'Event Stats', - testId: 'Icon-Component-Event-Stats', - }, Advertisement: { name: 'Advertisement', testId: 'Icon-Component-Advertisement', }, + Funds: { + name: 'Funds', + testId: 'Icon-Component-Funds', + }, Venues: { name: 'Venues', testId: 'Icon-Component-Venues', }, + Donate: { + name: 'Donate', + testId: 'Icon-Component-Donate', + }, + Campaigns: { + name: 'Campaigns', + testId: 'Icon-Component-Campaigns', + }, + MyPledges: { + name: 'My Pledges', + testId: 'Icon-Component-My-Pledges', + }, default: { name: 'default', testId: 'Icon-Component-DefaultIcon', diff --git a/src/components/IconComponent/IconComponent.tsx b/src/components/IconComponent/IconComponent.tsx index 17f9af8b32..4708dc7966 100644 --- a/src/components/IconComponent/IconComponent.tsx +++ b/src/components/IconComponent/IconComponent.tsx @@ -1,22 +1,24 @@ -import { QuestionMarkOutlined } from '@mui/icons-material'; -import { ReactComponent as ActionItemIcon } from 'assets/svgs/actionItem.svg'; -import { ReactComponent as AgendaCategoryIcon } from 'assets/svgs/agenda-category-icon.svg'; -import { ReactComponent as BlockUserIcon } from 'assets/svgs/blockUser.svg'; -import { ReactComponent as CheckInRegistrantsIcon } from 'assets/svgs/checkInRegistrants.svg'; -import { ReactComponent as DashboardIcon } from 'assets/svgs/dashboard.svg'; -import { ReactComponent as EventStatsIcon } from 'assets/svgs/eventStats.svg'; -import { ReactComponent as EventsIcon } from 'assets/svgs/events.svg'; -import { ReactComponent as FundsIcon } from 'assets/svgs/funds.svg'; -import { ReactComponent as ListEventRegistrantsIcon } from 'assets/svgs/listEventRegistrants.svg'; -import { ReactComponent as OrganizationsIcon } from 'assets/svgs/organizations.svg'; -import { ReactComponent as PeopleIcon } from 'assets/svgs/people.svg'; -import { ReactComponent as PluginsIcon } from 'assets/svgs/plugins.svg'; -import { ReactComponent as PostsIcon } from 'assets/svgs/posts.svg'; -import { ReactComponent as SettingsIcon } from 'assets/svgs/settings.svg'; -import { ReactComponent as VenueIcon } from 'assets/svgs/venues.svg'; -import { ReactComponent as RequestsIcon } from 'assets/svgs/requests.svg'; -// import { ReactComponent as HomeIcon } from 'assets/svgs/home.svg'; -// import { ReactComponent as DonateIcon } from 'assets/svgs/donate.svg'; +import { + QuestionMarkOutlined, + ContactPageOutlined, + NewspaperOutlined, +} from '@mui/icons-material'; +import ActionItemIcon from 'assets/svgs/actionItem.svg?react'; +import BlockUserIcon from 'assets/svgs/blockUser.svg?react'; +import CheckInRegistrantsIcon from 'assets/svgs/checkInRegistrants.svg?react'; +import DashboardIcon from 'assets/svgs/dashboard.svg?react'; +import EventsIcon from 'assets/svgs/events.svg?react'; +import FundsIcon from 'assets/svgs/funds.svg?react'; +import ListEventRegistrantsIcon from 'assets/svgs/listEventRegistrants.svg?react'; +import OrganizationsIcon from 'assets/svgs/organizations.svg?react'; +import PeopleIcon from 'assets/svgs/people.svg?react'; +import TagsIcon from 'assets/svgs/tags.svg?react'; +import TagIcon from 'assets/svgs/tag.svg?react'; +import PluginsIcon from 'assets/svgs/plugins.svg?react'; +import PostsIcon from 'assets/svgs/posts.svg?react'; +import SettingsIcon from 'assets/svgs/settings.svg?react'; +import VenueIcon from 'assets/svgs/venues.svg?react'; +import RequestsIcon from 'assets/svgs/requests.svg?react'; import React from 'react'; @@ -26,7 +28,12 @@ export interface InterfaceIconComponent { height?: string; width?: string; } - +/** + * Renders an icon based on the provided name. + * + * @param props - Contains the name of the icon and optional styles (fill, height, width). + * @returns JSX element representing the icon. + */ const iconComponent = (props: InterfaceIconComponent): JSX.Element => { switch (props.name) { case 'My Organizations': @@ -42,6 +49,10 @@ const iconComponent = (props: InterfaceIconComponent): JSX.Element => { ); case 'People': return ; + case 'Tags': + return ; + case 'Tag': + return ; case 'Requests': return ( @@ -55,13 +66,6 @@ const iconComponent = (props: InterfaceIconComponent): JSX.Element => { data-testid="Icon-Component-ActionItemIcon" /> ); - case 'Agenda Items Category': - return ( - - ); case 'Posts': return ; case 'Block/Unblock': @@ -99,13 +103,6 @@ const iconComponent = (props: InterfaceIconComponent): JSX.Element => { stroke={props.fill} /> ); - case 'Event Stats': - return ( - - ); case 'Advertisement': return ( { return ( ); - case 'Home': - return ( - - ); case 'Donate': return ( ); + case 'Campaigns': + return ( + + ); + case 'My Pledges': + return ( + + ); default: return ( ); diff --git a/src/components/LeftDrawer/LeftDrawer.test.tsx b/src/components/LeftDrawer/LeftDrawer.test.tsx index 3873d66dc2..6701d2d4bb 100644 --- a/src/components/LeftDrawer/LeftDrawer.test.tsx +++ b/src/components/LeftDrawer/LeftDrawer.test.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { act } from 'react'; import { fireEvent, render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import 'jest-localstorage-mock'; @@ -63,102 +63,131 @@ afterEach(() => { }); describe('Testing Left Drawer component for SUPERADMIN', () => { - test('Component should be rendered properly', () => { - setItem('UserImage', ''); - setItem('UserImage', ''); - setItem('SuperAdmin', true); - setItem('FirstName', 'John'); - setItem('LastName', 'Doe'); + test('Component should be rendered properly', async () => { setItem('UserImage', ''); setItem('SuperAdmin', true); setItem('FirstName', 'John'); setItem('LastName', 'Doe'); - render( - - - - - - - , - ); + + await act(async () => { + render( + + + + + + + , + ); + }); expect(screen.getByText('My Organizations')).toBeInTheDocument(); expect(screen.getByText('Users')).toBeInTheDocument(); expect(screen.getByText('Community Profile')).toBeInTheDocument(); - expect(screen.getByText('Community Profile')).toBeInTheDocument(); expect(screen.getByText('Talawa Admin Portal')).toBeInTheDocument(); const orgsBtn = screen.getByTestId(/orgsBtn/i); const rolesBtn = screen.getByTestId(/rolesBtn/i); const communityProfileBtn = screen.getByTestId(/communityProfileBtn/i); - orgsBtn.click(); + await act(async () => { + orgsBtn.click(); + }); + expect( orgsBtn.className.includes('text-white btn btn-success'), ).toBeTruthy(); expect(rolesBtn.className.includes('text-secondary btn')).toBeTruthy(); - expect(rolesBtn.className.includes('text-secondary btn')).toBeTruthy(); expect( communityProfileBtn.className.includes('text-secondary btn'), ).toBeTruthy(); - // Send to roles screen - userEvent.click(rolesBtn); + await act(async () => { + userEvent.click(rolesBtn); + }); + expect(global.window.location.pathname).toContain('/users'); - userEvent.click(communityProfileBtn); + + await act(async () => { + userEvent.click(communityProfileBtn); + }); }); - test('Testing Drawer when hideDrawer is null', () => { + test('Testing Drawer when hideDrawer is null', async () => { const tempProps: InterfaceLeftDrawerProps = { ...props, hideDrawer: false, }; - render( - - - - - - - , - ); + await act(async () => { + render( + + + + + + + , + ); + }); }); - test('Testing Drawer when hideDrawer is false', () => { + + test('Testing Drawer when hideDrawer is false', async () => { const tempProps: InterfaceLeftDrawerProps = { ...props, hideDrawer: false, }; + + await act(async () => { + render( + + + + + + + , + ); + }); }); - test('Testing Drawer when the screen size is less than or equal to 820px', () => { + + test('Testing Drawer when the screen size is less than or equal to 820px', async () => { const tempProps: InterfaceLeftDrawerProps = { ...props, hideDrawer: false, }; resizeWindow(800); - render( - - - - - - - , - ); + + await act(async () => { + render( + + + + + + + , + ); + }); + expect(screen.getByText('My Organizations')).toBeInTheDocument(); expect(screen.getByText('Talawa Admin Portal')).toBeInTheDocument(); const orgsBtn = screen.getByTestId(/orgsBtn/i); - orgsBtn.click(); + await act(async () => { + orgsBtn.click(); + }); + expect( orgsBtn.className.includes('text-white btn btn-success'), ).toBeTruthy(); }); +}); - describe('Testing Left Drawer component for ADMIN', () => { - test('Components should be rendered properly', () => { +describe('Testing Left Drawer component for ADMIN', () => { + test('Components should be rendered properly', async () => { + await act(async () => { render( @@ -168,24 +197,30 @@ describe('Testing Left Drawer component for SUPERADMIN', () => { , ); + }); + + expect(screen.getByText('My Organizations')).toBeInTheDocument(); + expect(screen.getByText('Talawa Admin Portal')).toBeInTheDocument(); - expect(screen.getByText('My Organizations')).toBeInTheDocument(); - expect(screen.getByText('Talawa Admin Portal')).toBeInTheDocument(); + expect(screen.getAllByText(/admin/i)).toHaveLength(1); - expect(screen.getAllByText(/admin/i)).toHaveLength(1); - expect(screen.getAllByText(/admin/i)).toHaveLength(1); + const orgsBtn = screen.getByTestId(/orgsBtn/i); - const orgsBtn = screen.getByTestId(/orgsBtn/i); + await act(async () => { orgsBtn.click(); - expect( - orgsBtn.className.includes('text-white btn btn-success'), - ).toBeTruthy(); + }); - // These screens arent meant for admins so they should not be present - expect(screen.queryByTestId(/rolesBtn/i)).toBeNull(); + expect( + orgsBtn.className.includes('text-white btn btn-success'), + ).toBeTruthy(); + // These screens aren't meant for admins, so they should not be present + expect(screen.queryByTestId(/rolesBtn/i)).toBeNull(); + + await act(async () => { userEvent.click(orgsBtn); - expect(global.window.location.pathname).toContain('/orglist'); }); + + expect(global.window.location.pathname).toContain('/orglist'); }); }); diff --git a/src/components/LeftDrawer/LeftDrawer.tsx b/src/components/LeftDrawer/LeftDrawer.tsx index dc501d6185..4628603ba1 100644 --- a/src/components/LeftDrawer/LeftDrawer.tsx +++ b/src/components/LeftDrawer/LeftDrawer.tsx @@ -2,18 +2,25 @@ import React from 'react'; import Button from 'react-bootstrap/Button'; import { useTranslation } from 'react-i18next'; import { NavLink } from 'react-router-dom'; -import { ReactComponent as OrganizationsIcon } from 'assets/svgs/organizations.svg'; -import { ReactComponent as RolesIcon } from 'assets/svgs/roles.svg'; -import { ReactComponent as SettingsIcon } from 'assets/svgs/settings.svg'; -import { ReactComponent as TalawaLogo } from 'assets/svgs/talawa.svg'; +import OrganizationsIcon from 'assets/svgs/organizations.svg?react'; +import RolesIcon from 'assets/svgs/roles.svg?react'; +import SettingsIcon from 'assets/svgs/settings.svg?react'; +import TalawaLogo from 'assets/svgs/talawa.svg?react'; import styles from './LeftDrawer.module.css'; import useLocalStorage from 'utils/useLocalstorage'; export interface InterfaceLeftDrawerProps { - hideDrawer: boolean | null; - setHideDrawer: React.Dispatch>; + hideDrawer: boolean | null; // Controls the visibility of the drawer + setHideDrawer: React.Dispatch>; // Function to set the visibility state } +/** + * LeftDrawer component for displaying navigation options. + * + * @param hideDrawer - Determines if the drawer should be hidden or shown. + * @param setHideDrawer - Function to update the visibility state of the drawer. + * @returns JSX element for the left navigation drawer. + */ const leftDrawer = ({ hideDrawer, setHideDrawer, @@ -24,6 +31,9 @@ const leftDrawer = ({ const { getItem } = useLocalStorage(); const superAdmin = getItem('SuperAdmin'); + /** + * Handles link click to hide the drawer on smaller screens. + */ const handleLinkClick = (): void => { if (window.innerWidth <= 820) { setHideDrawer(true); diff --git a/src/components/LeftDrawerOrg/LeftDrawerOrg.module.css b/src/components/LeftDrawerOrg/LeftDrawerOrg.module.css index 54560e7969..e792ef34bb 100644 --- a/src/components/LeftDrawerOrg/LeftDrawerOrg.module.css +++ b/src/components/LeftDrawerOrg/LeftDrawerOrg.module.css @@ -7,12 +7,21 @@ z-index: 100; display: flex; flex-direction: column; - padding: 0.8rem 1rem 0 1rem; + padding: 0.8rem 0rem 0 1rem; background-color: var(--bs-white); transition: 0.5s; font-family: var(--bs-leftDrawer-font-family); } +.avatarContainer { + display: flex; + justify-content: center; + align-items: center; + margin: 1rem 0; + width: 75%; + height: 75%; +} + .activeDrawer { width: calc(300px + 2rem); position: fixed; @@ -61,6 +70,8 @@ .leftDrawer .optionList { height: 100%; + overflow-y: scroll; + padding-bottom: 1.5rem; } .leftDrawer .optionList button { @@ -114,6 +125,7 @@ .leftDrawer .imageContainer { width: 68px; + margin-left: 0.75rem; margin-right: 8px; } @@ -151,7 +163,7 @@ @media (max-width: 1120px) { .leftDrawer { width: calc(250px + 2rem); - padding: 1rem 1rem 0 1rem; + padding: 1rem 0rem 0 1rem; } } @@ -186,7 +198,7 @@ } @media (max-height: 650px) { .leftDrawer { - padding: 0.5rem 0.8rem 0 0.8rem; + padding: 0.5rem 0rem 0 0.8rem; width: calc(250px); } .leftDrawer .talawaText { @@ -213,7 +225,7 @@ } .leftDrawer .imageContainer { width: 40px; - margin-left: 5px; + margin-left: 0.75rem; margin-right: 12px; } .leftDrawer .imageContainer img { diff --git a/src/components/LeftDrawerOrg/LeftDrawerOrg.test.tsx b/src/components/LeftDrawerOrg/LeftDrawerOrg.test.tsx index 58a7168552..2a0ef3815d 100644 --- a/src/components/LeftDrawerOrg/LeftDrawerOrg.test.tsx +++ b/src/components/LeftDrawerOrg/LeftDrawerOrg.test.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { act } from 'react'; import { fireEvent, render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import 'jest-localstorage-mock'; @@ -12,7 +12,6 @@ import { Provider } from 'react-redux'; import { MockedProvider } from '@apollo/react-testing'; import { store } from 'state/store'; import { ORGANIZATIONS_LIST } from 'GraphQl/Queries/Queries'; -import { act } from 'react-dom/test-utils'; import { StaticMockLink } from 'utils/StaticMockLink'; import { REVOKE_REFRESH_TOKEN } from 'GraphQl/Mutations/mutations'; import useLocalStorage from 'utils/useLocalstorage'; @@ -345,8 +344,8 @@ describe('Testing LeftDrawerOrg component for SUPERADMIN', () => { ); await wait(); resizeWindow(800); - expect(screen.getByText(/Dashboard/i)).toBeInTheDocument(); - expect(screen.getByText(/People/i)).toBeInTheDocument(); + expect(screen.getAllByText(/Dashboard/i)[0]).toBeInTheDocument(); + expect(screen.getAllByText(/People/i)[0]).toBeInTheDocument(); const peopelBtn = screen.getByTestId(/People/i); userEvent.click(peopelBtn); @@ -391,7 +390,7 @@ describe('Testing LeftDrawerOrg component for SUPERADMIN', () => { ); await wait(); expect( - screen.getByText(/Error Occured while loading the Organization/i), + screen.getByText(/Error occured while loading Organization data/i), ).toBeInTheDocument(); }); diff --git a/src/components/LeftDrawerOrg/LeftDrawerOrg.tsx b/src/components/LeftDrawerOrg/LeftDrawerOrg.tsx index 6cc501db45..3a3ba378cf 100644 --- a/src/components/LeftDrawerOrg/LeftDrawerOrg.tsx +++ b/src/components/LeftDrawerOrg/LeftDrawerOrg.tsx @@ -9,8 +9,8 @@ import { useTranslation } from 'react-i18next'; import { NavLink } from 'react-router-dom'; import type { TargetsType } from 'state/reducers/routesReducer'; import type { InterfaceQueryOrganizationsListObject } from 'utils/interfaces'; -import { ReactComponent as AngleRightIcon } from 'assets/svgs/angleRight.svg'; -import { ReactComponent as TalawaLogo } from 'assets/svgs/talawa.svg'; +import AngleRightIcon from 'assets/svgs/angleRight.svg?react'; +import TalawaLogo from 'assets/svgs/talawa.svg?react'; import styles from './LeftDrawerOrg.module.css'; import Avatar from 'components/Avatar/Avatar'; @@ -21,6 +21,15 @@ export interface InterfaceLeftDrawerProps { setHideDrawer: React.Dispatch>; } +/** + * LeftDrawerOrg component for displaying organization details and navigation options. + * + * @param orgId - ID of the current organization. + * @param targets - List of navigation targets. + * @param hideDrawer - Determines if the drawer should be hidden or shown. + * @param setHideDrawer - Function to update the visibility state of the drawer. + * @returns JSX element for the left navigation drawer with organization details. + */ const leftDrawerOrg = ({ targets, orgId, @@ -28,7 +37,8 @@ const leftDrawerOrg = ({ setHideDrawer, }: InterfaceLeftDrawerProps): JSX.Element => { const { t: tCommon } = useTranslation('common'); - const [showDropdown, setShowDropdown] = React.useState(false); + const { t: tErrors } = useTranslation('errors'); + const [showDropdown, setShowDropdown] = useState(false); const [organization, setOrganization] = useState(); @@ -43,18 +53,21 @@ const leftDrawerOrg = ({ } = useQuery(ORGANIZATIONS_LIST, { variables: { id: orgId }, }); - // Set organization data + + // Set organization data when query data is available useEffect(() => { let isMounted = true; if (data && isMounted) { setOrganization(data?.organizations[0]); - console.log(targets, 'targets'); } return () => { isMounted = false; }; }, [data]); + /** + * Handles link click to hide the drawer on smaller screens. + */ const handleLinkClick = (): void => { if (window.innerWidth <= 820) { setHideDrawer(true); @@ -82,7 +95,7 @@ const leftDrawerOrg = ({
    {/* Organization Section */} -
    +
    {loading ? ( <>
    - Error Occured while loading the Organization + {tErrors('errorLoading', { entity: 'Organization' })} ) : ( @@ -110,6 +123,7 @@ const leftDrawerOrg = ({ ) : ( )} @@ -126,10 +140,10 @@ const leftDrawerOrg = ({
    {/* Options List */} +
    + {tCommon('menu')} +
    -
    - {tCommon('menu')} -
    {targets.map(({ name, url }, index) => { return url ? ( diff --git a/src/components/Loader/Loader.tsx b/src/components/Loader/Loader.tsx index fe5ddef793..b59c735175 100644 --- a/src/components/Loader/Loader.tsx +++ b/src/components/Loader/Loader.tsx @@ -3,10 +3,17 @@ import styles from './Loader.module.css'; import { Spinner } from 'react-bootstrap'; interface InterfaceLoaderProps { - styles?: StyleSheet | string; - size?: 'sm' | 'lg' | 'xl'; + styles?: StyleSheet | string; // Custom styles for the spinner wrapper + size?: 'sm' | 'lg' | 'xl'; // Size of the spinner } +/** + * Loader component for displaying a loading spinner. + * + * @param styles - Optional custom styles for the spinner wrapper. + * @param size - Size of the spinner. Can be 'sm', 'lg', or 'xl'. + * @returns JSX element for a loading spinner. + */ const Loader = (props: InterfaceLoaderProps): JSX.Element => { return ( <> diff --git a/src/components/LoginPortalToggle/LoginPortalToggle.test.tsx b/src/components/LoginPortalToggle/LoginPortalToggle.test.tsx index ac971e52ea..327e6cccea 100644 --- a/src/components/LoginPortalToggle/LoginPortalToggle.test.tsx +++ b/src/components/LoginPortalToggle/LoginPortalToggle.test.tsx @@ -1,5 +1,5 @@ -import React from 'react'; -import { act, render } from '@testing-library/react'; +import React, { act } from 'react'; +import { render } from '@testing-library/react'; import { Provider } from 'react-redux'; import { BrowserRouter } from 'react-router-dom'; import { I18nextProvider } from 'react-i18next'; diff --git a/src/components/LoginPortalToggle/LoginPortalToggle.tsx b/src/components/LoginPortalToggle/LoginPortalToggle.tsx index c1feb9f4da..76305b02d3 100644 --- a/src/components/LoginPortalToggle/LoginPortalToggle.tsx +++ b/src/components/LoginPortalToggle/LoginPortalToggle.tsx @@ -6,25 +6,36 @@ import Row from 'react-bootstrap/Row'; import { NavLink } from 'react-router-dom'; interface InterfaceLoginPortalToggleProps { - onToggle: (role: 'admin' | 'user') => void; + onToggle: (role: 'admin' | 'user') => void; // Callback function for role change } +/** + * Component for toggling between admin and user login portals. + * + * @param onToggle - Callback function to handle role changes ('admin' or 'user'). + * @returns JSX element for login portal toggle. + */ function loginPortalToggle({ onToggle, }: InterfaceLoginPortalToggleProps): JSX.Element { const { t: tCommon } = useTranslation('common'); - const [activeRole, setActiveRole] = useState<'admin' | 'user'>('admin'); + const [activeRole, setActiveRole] = useState<'admin' | 'user'>('admin'); // Default role is 'admin' + /** + * Handles navigation link click and updates the active role. + * + * @param role - The role to be activated ('admin' or 'user'). + */ const handleNavLinkClick = (role: 'admin' | 'user'): void => { - onToggle(role); - setActiveRole(role); + onToggle(role); // Invoke the callback with the new role + setActiveRole(role); // Update the active role }; return ( handleNavLinkClick('admin')} > @@ -33,7 +44,7 @@ function loginPortalToggle({ handleNavLinkClick('user')} > diff --git a/src/components/MemberRequestCard/MemberRequestCard.test.tsx b/src/components/MemberRequestCard/MemberRequestCard.test.tsx index 121213e4e7..a38a046ea2 100644 --- a/src/components/MemberRequestCard/MemberRequestCard.test.tsx +++ b/src/components/MemberRequestCard/MemberRequestCard.test.tsx @@ -1,5 +1,5 @@ -import React from 'react'; -import { act, render, screen } from '@testing-library/react'; +import React, { act } from 'react'; +import { render, screen } from '@testing-library/react'; import { MockedProvider } from '@apollo/react-testing'; import userEvent from '@testing-library/user-event'; import { I18nextProvider } from 'react-i18next'; @@ -16,7 +16,7 @@ const MOCKS = [ { request: { query: ACCEPT_ORGANIZATION_REQUEST_MUTATION, - variable: { id: '123' }, + variables: { id: '123' }, }, result: { data: { @@ -31,7 +31,7 @@ const MOCKS = [ { request: { query: REJECT_ORGANIZATION_REQUEST_MUTATION, - variable: { id: '234' }, + variables: { userid: '234' }, }, result: { data: { @@ -44,7 +44,9 @@ const MOCKS = [ }, }, ]; + const link = new StaticMockLink(MOCKS, true); + async function wait(ms = 100): Promise { await act(() => { return new Promise((resolve) => { @@ -55,7 +57,6 @@ async function wait(ms = 100): Promise { describe('Testing Member Request Card', () => { const props = { - key: '123', id: '1', memberName: 'John Doe', memberLocation: 'India', @@ -89,14 +90,13 @@ describe('Testing Member Request Card', () => { expect(screen.getByText(props.email)).toBeInTheDocument(); }); - it('Should render text elements when props value is not passed', async () => { + it('should render text elements when props value is not passed', async () => { global.confirm = (): boolean => false; render( => { try { await acceptMutation({ @@ -43,7 +52,7 @@ function memberRequestCard( }); /* istanbul ignore next */ - toast.success(t('memberAdded')); + toast.success(t('memberAdded') as string); /* istanbul ignore next */ setTimeout(() => { window.location.reload(); @@ -54,6 +63,10 @@ function memberRequestCard( } }; + /** + * Handles rejecting a member request. + * Confirms rejection and reloads the page if confirmed. + */ const rejectMember = async (): Promise => { const sure = window.confirm('Are you sure you want to Reject Request ?'); if (sure) { @@ -118,9 +131,8 @@ function memberRequestCard(
    -
    +
    ); } -export {}; -export default memberRequestCard; +export default MemberRequestCard; diff --git a/src/components/NotFound/NotFound.tsx b/src/components/NotFound/NotFound.tsx index 6e2853cf82..6b5332bbcf 100644 --- a/src/components/NotFound/NotFound.tsx +++ b/src/components/NotFound/NotFound.tsx @@ -4,10 +4,17 @@ import { useTranslation } from 'react-i18next'; import styles from './NotFound.module.css'; interface InterfaceNotFoundProps { - title: string; - keyPrefix: string; + title: string; // Title of the page or resource not found + keyPrefix: string; // Translation key prefix } +/** + * Component to display a "Not Found" message. + * + * @param title - Title of the page or resource that was not found. + * @param keyPrefix - Prefix for translation keys. + * @returns JSX element for the "Not Found" page. + */ function notFound(props: InterfaceNotFoundProps): JSX.Element { const key = props.keyPrefix.toString(); const { t } = useTranslation('translation', { diff --git a/src/components/OrgActionItemCategories/OrgActionItemCategories.module.css b/src/components/OrgActionItemCategories/OrgActionItemCategories.module.css deleted file mode 100644 index ac9f4a5900..0000000000 --- a/src/components/OrgActionItemCategories/OrgActionItemCategories.module.css +++ /dev/null @@ -1,33 +0,0 @@ -.addButton { - width: 7em; - position: absolute; - right: 1rem; - top: 1rem; -} - -.createModal { - margin-top: 20vh; - margin-left: 13vw; - max-width: 80vw; -} - -.icon { - transform: scale(1.5); - color: var(--bs-danger); - margin-bottom: 1rem; -} - -.message { - display: flex; - justify-content: center; - align-items: center; - flex-direction: column; -} - -.titlemodal { - color: var(--bs-gray-600); - font-weight: 600; - font-size: 20px; - margin-top: 1rem; - width: 65%; -} diff --git a/src/components/OrgActionItemCategories/OrgActionItemCategories.test.tsx b/src/components/OrgActionItemCategories/OrgActionItemCategories.test.tsx deleted file mode 100644 index 0665ce6fc4..0000000000 --- a/src/components/OrgActionItemCategories/OrgActionItemCategories.test.tsx +++ /dev/null @@ -1,372 +0,0 @@ -import React from 'react'; -import { - render, - screen, - fireEvent, - waitFor, - act, -} from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import 'jest-localstorage-mock'; -import { MockedProvider } from '@apollo/client/testing'; -import 'jest-location-mock'; -import { I18nextProvider } from 'react-i18next'; -import { Provider } from 'react-redux'; -import { BrowserRouter } from 'react-router-dom'; -import i18n from 'utils/i18nForTest'; -import { toast } from 'react-toastify'; - -import { store } from 'state/store'; -import { StaticMockLink } from 'utils/StaticMockLink'; - -import OrgActionItemCategories from './OrgActionItemCategories'; -import { - MOCKS, - MOCKS_ERROR_QUERY, - MOCKS_ERROR_MUTATIONS, -} from './OrgActionItemCategoryMocks'; - -jest.mock('react-toastify', () => ({ - toast: { - success: jest.fn(), - error: jest.fn(), - }, -})); -jest.mock('react-router-dom', () => ({ - ...jest.requireActual('react-router-dom'), - useParams: () => ({ orgId: '123' }), -})); - -async function wait(ms = 100): Promise { - await act(() => { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); - }); -} - -const link = new StaticMockLink(MOCKS, true); -const link2 = new StaticMockLink(MOCKS_ERROR_QUERY, true); -const link3 = new StaticMockLink(MOCKS_ERROR_MUTATIONS, true); - -const translations = { - ...JSON.parse( - JSON.stringify( - i18n.getDataByLanguage('en')?.translation.orgActionItemCategories ?? {}, - ), - ), - ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), - ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), -}; - -describe('Testing Action Item Categories Component', () => { - test('Component loads correctly', async () => { - window.location.assign('/orgsetting/123'); - const { getByText } = render( - - - - - {} - - - - , - ); - - await wait(); - - await waitFor(() => { - expect(getByText(translations.create)).toBeInTheDocument(); - }); - }); - - test('render error component on unsuccessful query', async () => { - window.location.assign('/orgsetting/123'); - const { queryByText } = render( - - - - - {} - - - - , - ); - - await wait(); - - await waitFor(() => { - expect(queryByText(translations.create)).not.toBeInTheDocument(); - }); - }); - - test('opens and closes create and update modals on button clicks', async () => { - window.location.assign('/orgsetting/123'); - render( - - - - - {} - - - - , - ); - - await wait(); - - await waitFor(() => { - userEvent.click(screen.getByTestId('actionItemCategoryModalOpenBtn')); - userEvent.click(screen.getByTestId('actionItemCategoryModalCloseBtn')); - }); - - await waitFor(() => { - userEvent.click( - screen.getAllByTestId('actionItemCategoryUpdateModalOpenBtn')[0], - ); - userEvent.click(screen.getByTestId('actionItemCategoryModalCloseBtn')); - }); - }); - - test('create a new action item category', async () => { - window.location.assign('/orgsetting/123'); - render( - - - - - {} - - - - , - ); - - await wait(); - - await waitFor(() => { - userEvent.click(screen.getByTestId('actionItemCategoryModalOpenBtn')); - userEvent.type( - screen.getByPlaceholderText(translations.enterName), - 'ActionItemCategory 4', - ); - - userEvent.click(screen.getByTestId('formSubmitButton')); - }); - - await waitFor(() => { - expect(toast.success).toBeCalledWith(translations.successfulCreation); - }); - }); - - test('toast error on unsuccessful creation', async () => { - window.location.assign('/orgsetting/123'); - render( - - - - - {} - - - - , - ); - - await wait(); - - await waitFor(() => { - userEvent.click(screen.getByTestId('actionItemCategoryModalOpenBtn')); - userEvent.type( - screen.getByPlaceholderText(translations.enterName), - 'ActionItemCategory 4', - ); - - userEvent.click(screen.getByTestId('formSubmitButton')); - }); - - await waitFor(() => { - expect(toast.error).toHaveBeenCalled(); - }); - }); - - test('update an action item category', async () => { - window.location.assign('/orgsetting/123'); - render( - - - - - {} - - - - , - ); - - await wait(); - - await waitFor(() => { - userEvent.click( - screen.getAllByTestId('actionItemCategoryUpdateModalOpenBtn')[0], - ); - - const name = screen.getByPlaceholderText(translations.enterName); - fireEvent.change(name, { target: { value: '' } }); - - userEvent.type( - screen.getByPlaceholderText(translations.enterName), - 'ActionItemCategory 1 updated', - ); - - userEvent.click(screen.getByTestId('formSubmitButton')); - }); - - await waitFor(() => { - expect(toast.success).toBeCalledWith(translations.successfulUpdation); - }); - }); - - test('toast error on unsuccessful updation', async () => { - window.location.assign('/orgsetting/123'); - render( - - - - - {} - - - - , - ); - - await wait(); - - await waitFor(() => { - userEvent.click( - screen.getAllByTestId('actionItemCategoryUpdateModalOpenBtn')[0], - ); - - const name = screen.getByPlaceholderText(translations.enterName); - fireEvent.change(name, { target: { value: '' } }); - - userEvent.type( - screen.getByPlaceholderText(translations.enterName), - 'ActionItemCategory 1 updated', - ); - - userEvent.click(screen.getByTestId('formSubmitButton')); - }); - - await waitFor(() => { - expect(toast.error).toHaveBeenCalled(); - }); - }); - - test('toast error on providing the same name on updation', async () => { - window.location.assign('/orgsetting/123'); - render( - - - - - {} - - - - , - ); - - await wait(); - - await waitFor(() => { - userEvent.click( - screen.getAllByTestId('actionItemCategoryUpdateModalOpenBtn')[0], - ); - - const name = screen.getByPlaceholderText(translations.enterName); - fireEvent.change(name, { target: { value: '' } }); - - userEvent.type( - screen.getByPlaceholderText(translations.enterName), - 'ActionItemCategory 1', - ); - - userEvent.click(screen.getByTestId('formSubmitButton')); - }); - - await waitFor(() => { - expect(toast.error).toBeCalledWith(translations.sameNameConflict); - }); - }); - - test('toggle the disablity status of an action item category', async () => { - window.location.assign('/orgsetting/123'); - render( - - - - - {} - - - - , - ); - - await wait(); - - await waitFor(() => { - userEvent.click(screen.getAllByTestId('disabilityStatusButton')[0]); - }); - - await waitFor(() => { - expect(toast.success).toBeCalledWith(translations.categoryDisabled); - }); - - await waitFor(() => { - userEvent.click(screen.getAllByTestId('disabilityStatusButton')[1]); - }); - - await waitFor(() => { - expect(toast.success).toBeCalledWith(translations.categoryEnabled); - }); - }); - - test('toast error on unsuccessful toggling of the disablity status', async () => { - window.location.assign('/orgsetting/123'); - render( - - - - - {} - - - - , - ); - - await wait(); - - await waitFor(() => { - userEvent.click(screen.getAllByTestId('disabilityStatusButton')[0]); - }); - - await waitFor(() => { - expect(toast.error).toHaveBeenCalled(); - }); - - await waitFor(() => { - userEvent.click(screen.getAllByTestId('disabilityStatusButton')[1]); - }); - - await waitFor(() => { - expect(toast.error).toHaveBeenCalled(); - }); - }); -}); diff --git a/src/components/OrgActionItemCategories/OrgActionItemCategories.tsx b/src/components/OrgActionItemCategories/OrgActionItemCategories.tsx deleted file mode 100644 index f893319e38..0000000000 --- a/src/components/OrgActionItemCategories/OrgActionItemCategories.tsx +++ /dev/null @@ -1,292 +0,0 @@ -import type { ChangeEvent } from 'react'; -import React, { useState } from 'react'; -import { Button, Form, Modal } from 'react-bootstrap'; -import styles from './OrgActionItemCategories.module.css'; -import { useTranslation } from 'react-i18next'; -import { toast } from 'react-toastify'; -import { WarningAmberRounded } from '@mui/icons-material'; - -import { useMutation, useQuery } from '@apollo/client'; -import { - CREATE_ACTION_ITEM_CATEGORY_MUTATION, - UPDATE_ACTION_ITEM_CATEGORY_MUTATION, -} from 'GraphQl/Mutations/mutations'; -import { ACTION_ITEM_CATEGORY_LIST } from 'GraphQl/Queries/Queries'; -import type { InterfaceActionItemCategoryList } from 'utils/interfaces'; -import Loader from 'components/Loader/Loader'; -import { useParams } from 'react-router-dom'; - -type ModalType = 'Create' | 'Update'; - -const OrgActionItemCategories = (): JSX.Element => { - const { t } = useTranslation('translation', { - keyPrefix: 'orgActionItemCategories', - }); - const { t: tCommon } = useTranslation('common'); - - const [modalIsOpen, setModalIsOpen] = useState(false); - const [modalType, setModalType] = useState('Create'); - const [categoryId, setCategoryId] = useState(''); - - const [name, setName] = useState(''); - const [currName, setCurrName] = useState(''); - - const { orgId: currentUrl } = useParams(); - - const { - data, - loading, - error, - refetch, - }: { - data: InterfaceActionItemCategoryList | undefined; - loading: boolean; - error?: Error | undefined; - refetch: () => void; - } = useQuery(ACTION_ITEM_CATEGORY_LIST, { - variables: { - organizationId: currentUrl, - }, - notifyOnNetworkStatusChange: true, - }); - - const [createActionItemCategory] = useMutation( - CREATE_ACTION_ITEM_CATEGORY_MUTATION, - ); - - const [updateActionItemCategory] = useMutation( - UPDATE_ACTION_ITEM_CATEGORY_MUTATION, - ); - - const handleCreate = async ( - e: ChangeEvent, - ): Promise => { - e.preventDefault(); - try { - await createActionItemCategory({ - variables: { - name, - organizationId: currentUrl, - }, - }); - - setName(''); - refetch(); - - setModalIsOpen(false); - - toast.success(t('successfulCreation')); - } catch (error: unknown) { - if (error instanceof Error) { - toast.error(error.message); - console.log(error.message); - } - } - }; - - const handleEdit = async (e: ChangeEvent): Promise => { - e.preventDefault(); - if (name === currName) { - toast.error(t('sameNameConflict')); - } else { - try { - await updateActionItemCategory({ - variables: { - actionItemCategoryId: categoryId, - name, - }, - }); - - setName(''); - setCategoryId(''); - refetch(); - - setModalIsOpen(false); - - toast.success(t('successfulUpdation')); - } catch (error: unknown) { - if (error instanceof Error) { - toast.error(error.message); - console.log(error.message); - } - } - } - }; - - const handleStatusChange = async ( - id: string, - disabledStatus: boolean, - ): Promise => { - try { - await updateActionItemCategory({ - variables: { - actionItemCategoryId: id, - isDisabled: !disabledStatus, - }, - }); - - refetch(); - - toast.success( - disabledStatus ? t('categoryEnabled') : t('categoryDisabled'), - ); - } catch (error: unknown) { - if (error instanceof Error) { - toast.error(error.message); - console.log(error.message); - } - } - }; - - const showCreateModal = (): void => { - setModalType('Create'); - setModalIsOpen(true); - }; - - const showUpdateModal = (name: string, id: string): void => { - setCurrName(name); - setName(name); - setCategoryId(id); - setModalType('Update'); - setModalIsOpen(true); - }; - - const hideModal = (): void => { - setName(''); - setCategoryId(''); - setModalIsOpen(false); - }; - - if (loading) { - return ; - } - - if (error) { - return ( -
    - -
    - Error occured while loading Action Item Categories Data -
    - {`${error.message}`} -
    -
    - ); - } - - const actionItemCategories = data?.actionItemCategoriesByOrganization; - - return ( - <> - - -
    - {actionItemCategories?.map((category, index) => { - return ( -
    -
    -
    - {category.name} -
    -
    - - -
    -
    - - {index !== actionItemCategories.length - 1 &&
    } -
    - ); - })} -
    - - - -

    - {t('actionItemCategoryDetails')} -

    - -
    - -
    - - {t('actionItemCategoryName')} - - { - setName(e.target.value); - }} - /> - - -
    -
    - - ); -}; - -export default OrgActionItemCategories; diff --git a/src/components/OrgActionItemCategories/OrgActionItemCategoryMocks.ts b/src/components/OrgActionItemCategories/OrgActionItemCategoryMocks.ts deleted file mode 100644 index b03e53c5f5..0000000000 --- a/src/components/OrgActionItemCategories/OrgActionItemCategoryMocks.ts +++ /dev/null @@ -1,174 +0,0 @@ -import { - CREATE_ACTION_ITEM_CATEGORY_MUTATION, - UPDATE_ACTION_ITEM_CATEGORY_MUTATION, -} from 'GraphQl/Mutations/mutations'; - -import { ACTION_ITEM_CATEGORY_LIST } from 'GraphQl/Queries/Queries'; - -export const MOCKS = [ - { - request: { - query: ACTION_ITEM_CATEGORY_LIST, - variables: { organizationId: '123' }, - }, - result: { - data: { - actionItemCategoriesByOrganization: [ - { - _id: '1', - name: 'ActionItemCategory 1', - isDisabled: false, - }, - { - _id: '2', - name: 'ActionItemCategory 2', - isDisabled: true, - }, - { - _id: '3', - name: 'ActionItemCategory 3', - isDisabled: false, - }, - ], - }, - }, - }, - { - request: { - query: CREATE_ACTION_ITEM_CATEGORY_MUTATION, - variables: { name: 'ActionItemCategory 4', organizationId: '123' }, - }, - result: { - data: { - createActionItemCategory: { - _id: '4', - }, - }, - }, - }, - { - request: { - query: UPDATE_ACTION_ITEM_CATEGORY_MUTATION, - variables: { - name: 'ActionItemCategory 1 updated', - actionItemCategoryId: '1', - }, - }, - result: { - data: { - updateActionItemCategory: { - _id: '1', - }, - }, - }, - }, - { - request: { - query: UPDATE_ACTION_ITEM_CATEGORY_MUTATION, - variables: { - isDisabled: true, - actionItemCategoryId: '1', - }, - }, - result: { - data: { - updateActionItemCategory: { - _id: '1', - }, - }, - }, - }, - { - request: { - query: UPDATE_ACTION_ITEM_CATEGORY_MUTATION, - variables: { - isDisabled: false, - actionItemCategoryId: '2', - }, - }, - result: { - data: { - updateActionItemCategory: { - _id: '2', - }, - }, - }, - }, -]; - -export const MOCKS_ERROR_QUERY = [ - { - request: { - query: ACTION_ITEM_CATEGORY_LIST, - variables: { organizationId: '123' }, - }, - error: new Error('Mock Graphql Error'), - }, -]; - -export const MOCKS_ERROR_MUTATIONS = [ - { - request: { - query: ACTION_ITEM_CATEGORY_LIST, - variables: { organizationId: '123' }, - }, - result: { - data: { - actionItemCategoriesByOrganization: [ - { - _id: '1', - name: 'ActionItemCategory 1', - isDisabled: false, - }, - { - _id: '2', - name: 'ActionItemCategory 2', - isDisabled: true, - }, - { - _id: '3', - name: 'ActionItemCategory 3', - isDisabled: false, - }, - ], - }, - }, - }, - { - request: { - query: CREATE_ACTION_ITEM_CATEGORY_MUTATION, - variables: { name: 'ActionItemCategory 4', organizationId: '123' }, - }, - error: new Error('Mock Graphql Error'), - }, - { - request: { - query: UPDATE_ACTION_ITEM_CATEGORY_MUTATION, - variables: { - name: 'ActionItemCategory 1 updated', - actionItemCategoryId: '1', - }, - }, - error: new Error('Mock Graphql Error'), - }, - { - request: { - query: UPDATE_ACTION_ITEM_CATEGORY_MUTATION, - variables: { - isDisabled: true, - actionItemCategoryId: '1', - }, - }, - error: new Error('Mock Graphql Error'), - }, - { - request: { - query: UPDATE_ACTION_ITEM_CATEGORY_MUTATION, - variables: { - isDisabled: false, - actionItemCategoryId: '2', - }, - }, - error: new Error('Mock Graphql Error'), - }, -]; diff --git a/src/components/OrgAdminListCard/OrgAdminListCard.test.tsx b/src/components/OrgAdminListCard/OrgAdminListCard.test.tsx index 282dedb330..7baea946d2 100644 --- a/src/components/OrgAdminListCard/OrgAdminListCard.test.tsx +++ b/src/components/OrgAdminListCard/OrgAdminListCard.test.tsx @@ -1,5 +1,5 @@ -import React from 'react'; -import { act, render, screen, waitFor } from '@testing-library/react'; +import React, { act } from 'react'; +import { render, screen, waitFor } from '@testing-library/react'; import type { RenderResult } from '@testing-library/react'; import { MockedProvider } from '@apollo/react-testing'; import userEvent from '@testing-library/user-event'; diff --git a/src/components/OrgAdminListCard/OrgAdminListCard.tsx b/src/components/OrgAdminListCard/OrgAdminListCard.tsx index 9afb47000d..f8fc454823 100644 --- a/src/components/OrgAdminListCard/OrgAdminListCard.tsx +++ b/src/components/OrgAdminListCard/OrgAdminListCard.tsx @@ -12,7 +12,13 @@ interface InterfaceOrgPeopleListCardProps { id: string | undefined; toggleRemoveModal: () => void; } - +/** + * Component to confirm and handle the removal of an admin. + * + * @param id - ID of the admin to be removed. + * @param toggleRemoveModal - Function to toggle the visibility of the modal. + * @returns JSX element for the removal confirmation modal. + */ function orgAdminListCard(props: InterfaceOrgPeopleListCardProps): JSX.Element { if (!props.id) { return ; @@ -25,6 +31,10 @@ function orgAdminListCard(props: InterfaceOrgPeopleListCardProps): JSX.Element { }); const { t: tCommon } = useTranslation('common'); + /** + * Function to remove the admin from the organization + * and display a success message. + */ const removeAdmin = async (): Promise => { try { const { data } = await remove({ @@ -34,7 +44,7 @@ function orgAdminListCard(props: InterfaceOrgPeopleListCardProps): JSX.Element { }, }); if (data) { - toast.success(t('adminRemoved')); + toast.success(t('adminRemoved') as string); setTimeout(() => { window.location.reload(); }, 2000); diff --git a/src/components/OrgContriCards/OrgContriCards.tsx b/src/components/OrgContriCards/OrgContriCards.tsx index 69a9e03d58..6635be09b8 100644 --- a/src/components/OrgContriCards/OrgContriCards.tsx +++ b/src/components/OrgContriCards/OrgContriCards.tsx @@ -5,6 +5,9 @@ import { useTranslation } from 'react-i18next'; import styles from './OrgContriCards.module.css'; +/** + * Props for the OrgContriCards component + */ interface InterfaceOrgContriCardsProps { key: string; id: string; @@ -14,6 +17,16 @@ interface InterfaceOrgContriCardsProps { contriTransactionId: string; userEmail: string; } + +/** + * Component to display organization contribution cards + * + * This component shows the contribution details of a user in a card format. It includes + * the user's name, email, contribution date, transaction ID, and the contribution amount. + * + * @param props - The properties passed to the component + * @returns JSX.Element representing a contribution card + */ function orgContriCards(props: InterfaceOrgContriCardsProps): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'orgContriCards', diff --git a/src/components/OrgDelete/OrgDelete.tsx b/src/components/OrgDelete/OrgDelete.tsx index 0f1335dae4..e596445e5c 100644 --- a/src/components/OrgDelete/OrgDelete.tsx +++ b/src/components/OrgDelete/OrgDelete.tsx @@ -1,6 +1,13 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; +/** + * Component for displaying organization deletion message + * + * This component renders a message related to deleting an organization. + * + * @returns JSX.Element representing the organization deletion message + */ function orgDelete(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'orgDelete', @@ -8,6 +15,7 @@ function orgDelete(): JSX.Element { return ( <> + {/* Container for the organization deletion message */}
    {t('deleteOrg')}
    diff --git a/src/components/OrgListCard/OrgListCard.test.tsx b/src/components/OrgListCard/OrgListCard.test.tsx index 25d7f01ed1..4072265ea4 100644 --- a/src/components/OrgListCard/OrgListCard.test.tsx +++ b/src/components/OrgListCard/OrgListCard.test.tsx @@ -1,5 +1,5 @@ -import React from 'react'; -import { act, render, screen } from '@testing-library/react'; +import React, { act } from 'react'; +import { render, screen } from '@testing-library/react'; import 'jest-location-mock'; import { I18nextProvider } from 'react-i18next'; diff --git a/src/components/OrgListCard/OrgListCard.tsx b/src/components/OrgListCard/OrgListCard.tsx index bdba9107b0..10365d2364 100644 --- a/src/components/OrgListCard/OrgListCard.tsx +++ b/src/components/OrgListCard/OrgListCard.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { ReactComponent as FlaskIcon } from 'assets/svgs/flask.svg'; +import FlaskIcon from 'assets/svgs/flask.svg?react'; import Button from 'react-bootstrap/Button'; import { useTranslation } from 'react-i18next'; import styles from './OrgListCard.module.css'; @@ -16,20 +16,38 @@ import { useQuery } from '@apollo/client'; import { Tooltip } from '@mui/material'; import Avatar from 'components/Avatar/Avatar'; +/** + * Props for the OrgListCard component + */ export interface InterfaceOrgListCardProps { data: InterfaceOrgConnectionInfoType; } +/** + * Component for displaying a list card for an organization + * + * This component renders a card that displays information about an organization, + * including its name, address, members, and admins. It also provides a button + * to manage the organization, navigating to the organization's dashboard. + * + * @param props - The properties passed to the component + * @returns JSX.Element representing an organization list card + */ function orgListCard(props: InterfaceOrgListCardProps): JSX.Element { + // Destructure data from props const { _id, admins, image, address, members, name } = props.data; + // Query to check if the organization is a sample organization const { data } = useQuery(IS_SAMPLE_ORGANIZATION_QUERY, { variables: { isSampleOrganizationId: _id, }, }); + // Use navigate hook from react-router-dom to navigate to the organization dashboard const navigate = useNavigate(); + + // Query to get the organization list const { data: userData, }: { @@ -40,6 +58,7 @@ function orgListCard(props: InterfaceOrgListCardProps): JSX.Element { variables: { id: _id }, }); + // Handle click event to navigate to the organization dashboard function handleClick(): void { const url = '/orgdash/' + _id; @@ -54,8 +73,10 @@ function orgListCard(props: InterfaceOrgListCardProps): JSX.Element { return ( <> + {/* Container for the organization card */}
    + {/* Container for the organization image */}
    {image ? ( {`${name} @@ -68,12 +89,15 @@ function orgListCard(props: InterfaceOrgListCardProps): JSX.Element { )}
    + {/* Tooltip for the organization name */}

    {name}

    + {/* Description of the organization */}
    {userData?.organizations[0].description}
    + {/* Display the organization address if available */} {address && address.city && (
    @@ -83,17 +107,20 @@ function orgListCard(props: InterfaceOrgListCardProps): JSX.Element {
    )} + {/* Display the number of admins and members */}
    {tCommon('admins')}: {admins.length}       {tCommon('members')}: {members.length}
    + {/* Button to manage the organization */} {t('removeMemberMsg')} + {/* Button to cancel the removal action */} + {/* Button to confirm the removal action */} + + +
    + {/* Input field to enter amount to be pledged */} + + + + setFormState({ ...formState, name: e.target.value }) + } + required + /> + + + + + setFormState({ + ...formState, + isDisabled: !isDisabled, + }) + } + /> + + + +
    +
    + + ); +}; + +export default CategoryModal; diff --git a/src/components/OrgSettings/ActionItemCategories/OrgActionItemCategories.module.css b/src/components/OrgSettings/ActionItemCategories/OrgActionItemCategories.module.css new file mode 100644 index 0000000000..919421b0f2 --- /dev/null +++ b/src/components/OrgSettings/ActionItemCategories/OrgActionItemCategories.module.css @@ -0,0 +1,138 @@ +/* Button Styles */ +.addButton { + /* Position and size of the button */ + width: 7em; + position: absolute; + right: 1rem; + top: 1rem; +} + +/* Modal Styles */ +.createModal { + /* Position and size of the modal */ + margin-top: 20vh; + margin-left: 13vw; + max-width: 80vw; +} + +.icon { + /* Size and color of the icon */ + transform: scale(1.5); + color: var(--bs-danger); + margin-bottom: 1rem; +} + +.message { + /* Centering the content of the modal */ + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; +} + +.titlemodal { + /* Styling for the modal title */ + color: #707070; + font-weight: 600; + font-size: 32px; + width: 65%; + margin-bottom: 0px; +} + +.modalCloseBtn { + /* Styling for the modal close button */ + width: 40px; + height: 40px; + padding: 1rem; + display: flex; + justify-content: center; + align-items: center; +} + +/* Input Styles */ +.noOutline input { + /* Removing the outline from the input */ + outline: none; +} + +/* Header and Action Item Categories Styles */ +.btnsContainer { + /* Styling for the container of the buttons */ + display: flex; + margin: 0.5rem 0 1.5rem 0; +} + +.btnsContainer .input { + /* Styling for the input field */ + flex: 1; + min-width: 18rem; + position: relative; +} + +.btnsContainer input { + /* Styling for the input border */ + outline: 1px solid var(--bs-gray-400); +} + +.btnsContainer .input button { + /* Styling for the button in the input field */ + width: 52px; +} + +.inputField { + margin-top: 10px; + margin-bottom: 10px; + background-color: white; + box-shadow: 0 1px 1px #31bb6b; +} + +.inputField > button { + padding-top: 10px; + padding-bottom: 10px; +} + +/* Dropdown Styles */ +.dropdown { + /* Styling for the dropdown */ + background-color: white; + border: 1px solid #31bb6b; + position: relative; + display: inline-block; + color: #31bb6b; +} + +/* Datagrid Styles */ +.rowBackground { + /* Styling for the row background */ + background-color: var(--bs-white); + max-height: 120px; +} + +.tableHeader { + /* Styling for the table header */ + background-color: var(--bs-primary); + color: var(--bs-white); + font-size: 1rem; +} + +.chipIcon { + /* Styling for the chip icon */ + height: 0.9rem !important; +} + +.chip { + /* Styling for the chip */ + height: 1.5rem !important; +} + +.active { + /* Styling for the active state */ + background-color: #31bb6a50 !important; +} + +.pending { + /* Styling for the pending state */ + background-color: #ffd76950 !important; + color: #bb952bd0 !important; + border-color: #bb952bd0 !important; +} diff --git a/src/components/OrgSettings/ActionItemCategories/OrgActionItemCategories.test.tsx b/src/components/OrgSettings/ActionItemCategories/OrgActionItemCategories.test.tsx new file mode 100644 index 0000000000..d3698bf346 --- /dev/null +++ b/src/components/OrgSettings/ActionItemCategories/OrgActionItemCategories.test.tsx @@ -0,0 +1,241 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import type { RenderResult } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18n from 'utils/i18nForTest'; +import type { ApolloLink } from '@apollo/client'; +import { MOCKS, MOCKS_EMPTY, MOCKS_ERROR } from './OrgActionItemCategoryMocks'; +import OrgActionItemCategories from './OrgActionItemCategories'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +jest.mock('@mui/x-date-pickers/DateTimePicker', () => { + return { + DateTimePicker: jest.requireActual( + '@mui/x-date-pickers/DesktopDateTimePicker', + ).DesktopDateTimePicker, + }; +}); + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(MOCKS_EMPTY); +const link3 = new StaticMockLink(MOCKS_ERROR); +const t = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.orgActionItemCategories ?? {}, + ), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const renderActionItemCategories = ( + link: ApolloLink, + orgId: string, +): RenderResult => { + return render( + + + + + + + + + , + ); +}; + +describe('Testing Organisation Action Item Categories', () => { + it('should render the Action Item Categories Screen', async () => { + renderActionItemCategories(link1, 'orgId'); + await waitFor(() => { + expect(screen.getByTestId('searchByName')).toBeInTheDocument(); + expect(screen.getByText('Category 1')).toBeInTheDocument(); + expect(screen.getByText('Category 2')).toBeInTheDocument(); + }); + }); + + it('Sort the Categories (asc/desc) by createdAt', async () => { + renderActionItemCategories(link1, 'orgId'); + + const sortBtn = await screen.findByTestId('sort'); + expect(sortBtn).toBeInTheDocument(); + + // Sort by createdAt_DESC + fireEvent.click(sortBtn); + await waitFor(() => { + expect(screen.getByTestId('createdAt_DESC')).toBeInTheDocument(); + }); + fireEvent.click(screen.getByTestId('createdAt_DESC')); + await waitFor(() => { + expect(screen.getAllByTestId('categoryName')[0]).toHaveTextContent( + 'Category 1', + ); + }); + + // Sort by createdAt_ASC + fireEvent.click(sortBtn); + await waitFor(() => { + expect(screen.getByTestId('createdAt_ASC')).toBeInTheDocument(); + }); + fireEvent.click(screen.getByTestId('createdAt_ASC')); + await waitFor(() => { + expect(screen.getAllByTestId('categoryName')[0]).toHaveTextContent( + 'Category 2', + ); + }); + }); + + it('Filter the categories by status (All/Disabled)', async () => { + renderActionItemCategories(link1, 'orgId'); + + const filterBtn = await screen.findByTestId('filter'); + expect(filterBtn).toBeInTheDocument(); + + // Filter by All + fireEvent.click(filterBtn); + await waitFor(() => { + expect(screen.getByTestId('statusAll')).toBeInTheDocument(); + }); + fireEvent.click(screen.getByTestId('statusAll')); + + await waitFor(() => { + expect(screen.getByText('Category 1')).toBeInTheDocument(); + expect(screen.getByText('Category 2')).toBeInTheDocument(); + }); + + // Filter by Disabled + fireEvent.click(filterBtn); + await waitFor(() => { + expect(screen.getByTestId('statusDisabled')).toBeInTheDocument(); + }); + fireEvent.click(screen.getByTestId('statusDisabled')); + await waitFor(() => { + expect(screen.queryByText('Category 1')).toBeNull(); + expect(screen.getByText('Category 2')).toBeInTheDocument(); + }); + }); + + it('Filter the categories by status (Active)', async () => { + renderActionItemCategories(link1, 'orgId'); + + const filterBtn = await screen.findByTestId('filter'); + expect(filterBtn).toBeInTheDocument(); + + fireEvent.click(filterBtn); + await waitFor(() => { + expect(screen.getByTestId('statusActive')).toBeInTheDocument(); + }); + fireEvent.click(screen.getByTestId('statusActive')); + await waitFor(() => { + expect(screen.getByText('Category 1')).toBeInTheDocument(); + expect(screen.queryByText('Category 2')).toBeNull(); + }); + }); + + it('open and closes Create Category modal', async () => { + renderActionItemCategories(link1, 'orgId'); + + const addCategoryBtn = await screen.findByTestId( + 'createActionItemCategoryBtn', + ); + expect(addCategoryBtn).toBeInTheDocument(); + userEvent.click(addCategoryBtn); + + await waitFor(() => expect(screen.getAllByText(t.create)).toHaveLength(2)); + userEvent.click(screen.getByTestId('actionItemCategoryModalCloseBtn')); + await waitFor(() => + expect( + screen.queryByTestId('actionItemCategoryModalCloseBtn'), + ).toBeNull(), + ); + }); + + it('open and closes Edit Category modal', async () => { + renderActionItemCategories(link1, 'orgId'); + + const editCategoryBtn = await screen.findByTestId('editCategoryBtn1'); + await waitFor(() => expect(editCategoryBtn).toBeInTheDocument()); + userEvent.click(editCategoryBtn); + + await waitFor(() => + expect(screen.getByText(t.updateActionItemCategory)).toBeInTheDocument(), + ); + userEvent.click(screen.getByTestId('actionItemCategoryModalCloseBtn')); + await waitFor(() => + expect( + screen.queryByTestId('actionItemCategoryModalCloseBtn'), + ).toBeNull(), + ); + }); + + it('Search categories by name', async () => { + renderActionItemCategories(link1, 'orgId'); + + const searchInput = await screen.findByTestId('searchByName'); + expect(searchInput).toBeInTheDocument(); + + userEvent.type(searchInput, 'Category 1'); + userEvent.click(screen.getByTestId('searchBtn')); + await waitFor(() => { + expect(screen.getByText('Category 1')).toBeInTheDocument(); + expect(screen.queryByText('Category 2')).toBeNull(); + }); + }); + + it('Search categories by name and clear the input by backspace', async () => { + renderActionItemCategories(link1, 'orgId'); + + const searchInput = await screen.findByTestId('searchByName'); + expect(searchInput).toBeInTheDocument(); + + // Clear the search input by backspace + userEvent.type(searchInput, 'A{backspace}'); + await waitFor(() => { + expect(screen.getByText('Category 1')).toBeInTheDocument(); + expect(screen.getByText('Category 2')).toBeInTheDocument(); + }); + }); + + it('Search categories by name on press of ENTER', async () => { + renderActionItemCategories(link1, 'orgId'); + + const searchInput = await screen.findByTestId('searchByName'); + expect(searchInput).toBeInTheDocument(); + + userEvent.type(searchInput, 'Category 1'); + userEvent.type(searchInput, '{enter}'); + await waitFor(() => { + expect(screen.getByText('Category 1')).toBeInTheDocument(); + expect(screen.queryByText('Category 2')).toBeNull(); + }); + }); + + it('should render Empty Action Item Categories Screen', async () => { + renderActionItemCategories(link2, 'orgId'); + await waitFor(() => { + expect(screen.getByTestId('searchByName')).toBeInTheDocument(); + expect(screen.getByText(t.noActionItemCategories)).toBeInTheDocument(); + }); + }); + + it('should render the Action Item Categories Screen with error', async () => { + renderActionItemCategories(link3, 'orgId'); + await waitFor(() => { + expect(screen.getByTestId('errorMsg')).toBeInTheDocument(); + }); + }); +}); diff --git a/src/components/OrgSettings/ActionItemCategories/OrgActionItemCategories.tsx b/src/components/OrgSettings/ActionItemCategories/OrgActionItemCategories.tsx new file mode 100644 index 0000000000..49cf47dd49 --- /dev/null +++ b/src/components/OrgSettings/ActionItemCategories/OrgActionItemCategories.tsx @@ -0,0 +1,418 @@ +import type { FC } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; +import { Button, Dropdown, Form } from 'react-bootstrap'; +import styles from './OrgActionItemCategories.module.css'; +import { useTranslation } from 'react-i18next'; + +import { useQuery } from '@apollo/client'; +import { ACTION_ITEM_CATEGORY_LIST } from 'GraphQl/Queries/Queries'; +import type { InterfaceActionItemCategoryInfo } from 'utils/interfaces'; +import Loader from 'components/Loader/Loader'; +import { + Circle, + Search, + Sort, + WarningAmberRounded, + FilterAltOutlined, +} from '@mui/icons-material'; +import { + DataGrid, + type GridCellParams, + type GridColDef, +} from '@mui/x-data-grid'; +import dayjs from 'dayjs'; +import { Chip, Stack } from '@mui/material'; +import CategoryModal from './CategoryModal'; + +enum ModalState { + SAME = 'same', + DELETE = 'delete', +} + +enum CategoryStatus { + Active = 'active', + Disabled = 'disabled', +} + +interface InterfaceActionItemCategoryProps { + orgId: string; +} + +const dataGridStyle = { + '&.MuiDataGrid-root .MuiDataGrid-cell:focus-within': { + outline: 'none !important', + }, + '&.MuiDataGrid-root .MuiDataGrid-columnHeader:focus-within': { + outline: 'none', + }, + '& .MuiDataGrid-row:hover': { + backgroundColor: 'transparent', + }, + '& .MuiDataGrid-row.Mui-hovered': { + backgroundColor: 'transparent', + }, + '& .MuiDataGrid-root': { + borderRadius: '0.5rem', + }, + '& .MuiDataGrid-main': { + borderRadius: '0.5rem', + }, +}; + +/** + * Represents the component for managing organization action item categories. + * This component allows creating, updating, enabling, and disabling action item categories. + */ +const OrgActionItemCategories: FC = ({ + orgId, +}) => { + const { t } = useTranslation('translation', { + keyPrefix: 'orgActionItemCategories', + }); + const { t: tCommon } = useTranslation('common'); + const { t: tErrors } = useTranslation('errors'); + + const [category, setCategory] = + useState(null); + const [searchTerm, setSearchTerm] = useState(''); + const [searchValue, setSearchValue] = useState(''); + const [sortBy, setSortBy] = useState<'createdAt_ASC' | 'createdAt_DESC'>( + 'createdAt_DESC', + ); + const [status, setStatus] = useState(null); + const [categories, setCategories] = useState< + InterfaceActionItemCategoryInfo[] + >([]); + const [modalMode, setModalMode] = useState<'edit' | 'create'>('create'); + const [modalState, setModalState] = useState<{ + [key in ModalState]: boolean; + }>({ + [ModalState.SAME]: false, + [ModalState.DELETE]: false, + }); + + // Query to fetch action item categories + const { + data: catData, + loading: catLoading, + error: catError, + refetch: refetchCategories, + }: { + data?: { + actionItemCategoriesByOrganization: InterfaceActionItemCategoryInfo[]; + }; + loading: boolean; + error?: Error | undefined; + refetch: () => void; + } = useQuery(ACTION_ITEM_CATEGORY_LIST, { + variables: { + organizationId: orgId, + where: { + name_contains: searchTerm, + is_disabled: !status ? undefined : status === CategoryStatus.Disabled, + }, + orderBy: sortBy, + }, + }); + + const openModal = (modal: ModalState): void => + setModalState((prevState) => ({ ...prevState, [modal]: true })); + + const closeModal = (modal: ModalState): void => + setModalState((prevState) => ({ ...prevState, [modal]: false })); + + const handleOpenModal = useCallback( + ( + category: InterfaceActionItemCategoryInfo | null, + mode: 'edit' | 'create', + ): void => { + setCategory(category); + setModalMode(mode); + openModal(ModalState.SAME); + }, + [openModal], + ); + + useEffect(() => { + if (catData && catData.actionItemCategoriesByOrganization) { + setCategories(catData.actionItemCategoriesByOrganization); + } + }, [catData]); + + // Show loader while data is being fetched + if (catLoading) { + return ; + } + + // Show error message if there's an error + if (catError) { + return ( +
    + +
    + {tErrors('errorLoading', { entity: 'Action Item Categories' })} +
    + {`${catError.message}`} +
    +
    + ); + } + + const columns: GridColDef[] = [ + { + field: 'id', + headerName: 'Sr. No.', + flex: 1, + minWidth: 100, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return
    {params.row.id}
    ; + }, + }, + { + field: 'categoryName', + headerName: 'Category', + flex: 2, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( +
    + {params.row.name} +
    + ); + }, + }, + { + field: 'status', + headerName: 'Status', + flex: 1, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( + } + label={params.row.isDisabled ? 'Disabled' : 'Active'} + variant="outlined" + color="primary" + className={`${styles.chip} ${params.row.isDisabled ? styles.pending : styles.active}`} + /> + ); + }, + }, + { + field: 'createdBy', + headerName: 'Created By', + flex: 1, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return params.row.creator.firstName + ' ' + params.row.creator.lastName; + }, + }, + { + field: 'createdOn', + headerName: 'Created On', + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + flex: 1, + renderCell: (params: GridCellParams) => { + return ( +
    + {dayjs(params.row.createdAt).format('DD/MM/YYYY')} +
    + ); + }, + }, + { + field: 'action', + headerName: 'Action', + flex: 2, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( + + ); + }, + }, + ]; + + return ( +
    + {/* Header with search, filter and Create Button */} +
    +
    + setSearchValue(e.target.value)} + onKeyUp={(e) => { + if (e.key === 'Enter') { + setSearchTerm(searchValue); + } else if (e.key === 'Backspace' && searchValue === '') { + setSearchTerm(''); + } + }} + data-testid="searchByName" + /> + +
    +
    +
    + + + + {tCommon('sort')} + + + setSortBy('createdAt_DESC')} + data-testid="createdAt_DESC" + > + {tCommon('createdLatest')} + + setSortBy('createdAt_ASC')} + data-testid="createdAt_ASC" + > + {tCommon('createdEarliest')} + + + + + + + {t('status')} + + + setStatus(null)} + data-testid="statusAll" + > + {tCommon('all')} + + setStatus(CategoryStatus.Active)} + data-testid="statusActive" + > + {tCommon('active')} + + setStatus(CategoryStatus.Disabled)} + data-testid="statusDisabled" + > + {tCommon('disabled')} + + + +
    +
    + +
    +
    +
    + + {/* Table with Action Item Categories */} + row._id} + slots={{ + noRowsOverlay: () => ( + + {t('noActionItemCategories')} + + ), + }} + sx={dataGridStyle} + getRowClassName={() => `${styles.rowBackground}`} + autoHeight + rowHeight={65} + rows={categories.map((category, index) => ({ + id: index + 1, + ...category, + }))} + columns={columns} + isRowSelectable={() => false} + /> + + closeModal(ModalState.SAME)} + refetchCategories={refetchCategories} + category={category} + orgId={orgId} + mode={modalMode} + /> +
    + ); +}; + +export default OrgActionItemCategories; diff --git a/src/components/OrgSettings/ActionItemCategories/OrgActionItemCategoryMocks.ts b/src/components/OrgSettings/ActionItemCategories/OrgActionItemCategoryMocks.ts new file mode 100644 index 0000000000..10310a01e4 --- /dev/null +++ b/src/components/OrgSettings/ActionItemCategories/OrgActionItemCategoryMocks.ts @@ -0,0 +1,288 @@ +import { + CREATE_ACTION_ITEM_CATEGORY_MUTATION, + UPDATE_ACTION_ITEM_CATEGORY_MUTATION, +} from 'GraphQl/Mutations/mutations'; + +import { ACTION_ITEM_CATEGORY_LIST } from 'GraphQl/Queries/Queries'; + +export const MOCKS = [ + { + request: { + query: ACTION_ITEM_CATEGORY_LIST, + variables: { + organizationId: 'orgId', + where: { name_contains: '' }, + orderBy: 'createdAt_DESC', + }, + }, + result: { + data: { + actionItemCategoriesByOrganization: [ + { + _id: 'categoryId1', + name: 'Category 1', + isDisabled: false, + createdAt: '2024-08-26', + creator: { + _id: 'creatorId1', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + { + _id: 'categoryId2', + name: 'Category 2', + isDisabled: true, + createdAt: '2024-08-25', + creator: { + _id: 'creatorId2', + firstName: 'John', + lastName: 'Doe', + }, + }, + ], + }, + }, + }, + { + request: { + query: ACTION_ITEM_CATEGORY_LIST, + variables: { + organizationId: 'orgId', + where: { name_contains: '' }, + orderBy: 'createdAt_ASC', + }, + }, + result: { + data: { + actionItemCategoriesByOrganization: [ + { + _id: 'categoryId2', + name: 'Category 2', + isDisabled: true, + createdAt: '2024-08-25', + creator: { + _id: 'creatorId2', + firstName: 'John', + lastName: 'Doe', + }, + }, + { + _id: 'categoryId1', + name: 'Category 1', + isDisabled: false, + createdAt: '2024-08-26', + creator: { + _id: 'creatorId1', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + ], + }, + }, + }, + { + request: { + query: ACTION_ITEM_CATEGORY_LIST, + variables: { + organizationId: 'orgId', + where: { name_contains: '', is_disabled: false }, + orderBy: 'createdAt_DESC', + }, + }, + result: { + data: { + actionItemCategoriesByOrganization: [ + { + _id: 'categoryId1', + name: 'Category 1', + isDisabled: false, + createdAt: '2024-08-26', + creator: { + _id: 'creatorId1', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + ], + }, + }, + }, + { + request: { + query: ACTION_ITEM_CATEGORY_LIST, + variables: { + organizationId: 'orgId', + where: { name_contains: '', is_disabled: true }, + orderBy: 'createdAt_DESC', + }, + }, + result: { + data: { + actionItemCategoriesByOrganization: [ + { + _id: 'categoryId2', + name: 'Category 2', + isDisabled: true, + createdAt: '2024-08-25', + creator: { + _id: 'creatorId2', + firstName: 'John', + lastName: 'Doe', + }, + }, + ], + }, + }, + }, + { + request: { + query: ACTION_ITEM_CATEGORY_LIST, + variables: { + organizationId: 'orgId', + where: { name_contains: 'Category 1' }, + orderBy: 'createdAt_DESC', + }, + }, + result: { + data: { + actionItemCategoriesByOrganization: [ + { + _id: 'categoryId1', + name: 'Category 1', + isDisabled: false, + createdAt: '2024-08-26', + creator: { + _id: 'creatorId1', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + ], + }, + }, + }, + { + request: { + query: CREATE_ACTION_ITEM_CATEGORY_MUTATION, + variables: { + name: 'Category 2', + isDisabled: true, + organizationId: 'orgId', + }, + }, + result: { + data: { + createActionItemCategory: { + _id: 'categoryId3', + }, + }, + }, + }, + { + request: { + query: UPDATE_ACTION_ITEM_CATEGORY_MUTATION, + variables: { + name: 'Category 2', + isDisabled: true, + actionItemCategoryId: 'categoryId', + }, + }, + result: { + data: { + updateActionItemCategory: { + _id: 'categoryId', + }, + }, + }, + }, + { + request: { + query: UPDATE_ACTION_ITEM_CATEGORY_MUTATION, + variables: { + name: 'Category 2', + isDisabled: false, + actionItemCategoryId: 'categoryId', + }, + }, + result: { + data: { + updateActionItemCategory: { + _id: 'categoryId', + }, + }, + }, + }, + { + request: { + query: UPDATE_ACTION_ITEM_CATEGORY_MUTATION, + variables: { + name: 'Category 1', + isDisabled: true, + actionItemCategoryId: 'categoryId', + }, + }, + result: { + data: { + updateActionItemCategory: { + _id: 'categoryId', + }, + }, + }, + }, +]; + +export const MOCKS_EMPTY = [ + { + request: { + query: ACTION_ITEM_CATEGORY_LIST, + variables: { + organizationId: 'orgId', + where: { name_contains: '' }, + orderBy: 'createdAt_DESC', + }, + }, + result: { + data: { + actionItemCategoriesByOrganization: [], + }, + }, + }, +]; + +export const MOCKS_ERROR = [ + { + request: { + query: ACTION_ITEM_CATEGORY_LIST, + variables: { + organizationId: 'orgId', + where: { name_contains: '' }, + orderBy: 'createdAt_DESC', + }, + }, + error: new Error('Mock Graphql Error'), + }, + { + request: { + query: CREATE_ACTION_ITEM_CATEGORY_MUTATION, + variables: { + name: 'Category 2', + isDisabled: true, + organizationId: 'orgId', + }, + }, + error: new Error('Mock Graphql Error'), + }, + { + request: { + query: UPDATE_ACTION_ITEM_CATEGORY_MUTATION, + variables: { + name: 'Category 2', + isDisabled: true, + actionItemCategoryId: 'categoryId', + }, + }, + error: new Error('Mock Graphql Error'), + }, +]; diff --git a/src/screens/OrganizationAgendaCategory/AgendaCategoryCreateModal.test.tsx b/src/components/OrgSettings/AgendaItemCategories/AgendaCategoryCreateModal.test.tsx similarity index 100% rename from src/screens/OrganizationAgendaCategory/AgendaCategoryCreateModal.test.tsx rename to src/components/OrgSettings/AgendaItemCategories/AgendaCategoryCreateModal.test.tsx diff --git a/src/screens/OrganizationAgendaCategory/AgendaCategoryCreateModal.tsx b/src/components/OrgSettings/AgendaItemCategories/AgendaCategoryCreateModal.tsx similarity index 77% rename from src/screens/OrganizationAgendaCategory/AgendaCategoryCreateModal.tsx rename to src/components/OrgSettings/AgendaItemCategories/AgendaCategoryCreateModal.tsx index 9b260d877f..57a3057b3f 100644 --- a/src/screens/OrganizationAgendaCategory/AgendaCategoryCreateModal.tsx +++ b/src/components/OrgSettings/AgendaItemCategories/AgendaCategoryCreateModal.tsx @@ -3,12 +3,18 @@ import { Modal, Form, Button } from 'react-bootstrap'; import type { ChangeEvent } from 'react'; import styles from './OrganizationAgendaCategory.module.css'; +/** + * InterfaceFormStateType is an object containing the form state + */ interface InterfaceFormStateType { name: string; description: string; createdBy: string; } +/** + * InterfaceAgendaCategoryCreateModalProps is an object containing the props for AgendaCategoryCreateModal component + */ interface InterfaceAgendaCategoryCreateModalProps { agendaCategoryCreateModalIsOpen: boolean; hideCreateModal: () => void; @@ -20,6 +26,16 @@ interface InterfaceAgendaCategoryCreateModalProps { t: (key: string) => string; } +/** + * AgendaCategoryCreateModal component is used to create the agenda category details like name, description + * @param agendaCategoryCreateModalIsOpen - boolean value to check if the modal is open or not + * @param hideCreateModal - function to hide the modal + * @param formState - object containing the form state + * @param setFormState - function to set the form state + * @param createAgendaCategoryHandler - function to create the agenda category + * @param t - i18n function to translate the text + * @returns returns the AgendaCategoryCreateModal component + */ const AgendaCategoryCreateModal: React.FC< InterfaceAgendaCategoryCreateModalProps > = ({ diff --git a/src/screens/OrganizationAgendaCategory/AgendaCategoryDeleteModal.tsx b/src/components/OrgSettings/AgendaItemCategories/AgendaCategoryDeleteModal.tsx similarity index 73% rename from src/screens/OrganizationAgendaCategory/AgendaCategoryDeleteModal.tsx rename to src/components/OrgSettings/AgendaItemCategories/AgendaCategoryDeleteModal.tsx index f2edb8fc62..a16186bac7 100644 --- a/src/screens/OrganizationAgendaCategory/AgendaCategoryDeleteModal.tsx +++ b/src/components/OrgSettings/AgendaItemCategories/AgendaCategoryDeleteModal.tsx @@ -2,6 +2,9 @@ import React from 'react'; import { Modal, Button } from 'react-bootstrap'; import styles from './OrganizationAgendaCategory.module.css'; +/** + * InterfaceAgendaCategoryDeleteModalProps is an object containing the props for AgendaCategoryDeleteModal component + */ interface InterfaceAgendaCategoryDeleteModalProps { agendaCategoryDeleteModalIsOpen: boolean; toggleDeleteModal: () => void; @@ -10,6 +13,15 @@ interface InterfaceAgendaCategoryDeleteModalProps { tCommon: (key: string) => string; } +/** + * AgendaCategoryDeleteModal component is used to delete the agenda category + * @param agendaCategoryDeleteModalIsOpen - boolean value to check if the modal is open or not + * @param toggleDeleteModal - function to toggle the modal + * @param deleteAgendaCategoryHandler - function to delete the agenda category + * @param t - i18n function to translate the text + * @param tCommon - i18n function to translate the text + * @returns returns the AgendaCategoryDeleteModal component + */ const AgendaCategoryDeleteModal: React.FC< InterfaceAgendaCategoryDeleteModalProps > = ({ diff --git a/src/screens/OrganizationAgendaCategory/AgendaCategoryPreviewModal.tsx b/src/components/OrgSettings/AgendaItemCategories/AgendaCategoryPreviewModal.tsx similarity index 76% rename from src/screens/OrganizationAgendaCategory/AgendaCategoryPreviewModal.tsx rename to src/components/OrgSettings/AgendaItemCategories/AgendaCategoryPreviewModal.tsx index c9dc17e56f..794db27ad3 100644 --- a/src/screens/OrganizationAgendaCategory/AgendaCategoryPreviewModal.tsx +++ b/src/components/OrgSettings/AgendaItemCategories/AgendaCategoryPreviewModal.tsx @@ -3,12 +3,18 @@ import { Modal, Form, Button } from 'react-bootstrap'; import styles from './OrganizationAgendaCategory.module.css'; +/** + * InterfaceFormStateType is an object containing the form state + */ interface InterfaceFormStateType { name: string; description: string; createdBy: string; } +/** + * InterfaceAgendaCategoryPreviewModalProps is an object containing the props for AgendaCategoryPreviewModal component + */ interface InterfaceAgendaCategoryPreviewModalProps { agendaCategoryPreviewModalIsOpen: boolean; hidePreviewModal: () => void; @@ -19,6 +25,16 @@ interface InterfaceAgendaCategoryPreviewModalProps { t: (key: string) => string; } +/** + * AgendaCategoryPreviewModal component is used to preview the agenda category details like name, description, createdBy + * @param agendaCategoryPreviewModalIsOpen - boolean value to check if the modal is open or not + * @param hidePreviewModal - function to hide the modal + * @param showUpdateModal - function to show the update modal + * @param toggleDeleteModal - function to toggle the delete modal + * @param formState - object containing the form state + * @param t - i18n function to translate the text + * @returns returns the AgendaCategoryPreviewModal component + */ const AgendaCategoryPreviewModal: React.FC< InterfaceAgendaCategoryPreviewModalProps > = ({ diff --git a/src/screens/OrganizationAgendaCategory/AgendaCategoryUpdateModal.test.tsx b/src/components/OrgSettings/AgendaItemCategories/AgendaCategoryUpdateModal.test.tsx similarity index 100% rename from src/screens/OrganizationAgendaCategory/AgendaCategoryUpdateModal.test.tsx rename to src/components/OrgSettings/AgendaItemCategories/AgendaCategoryUpdateModal.test.tsx diff --git a/src/screens/OrganizationAgendaCategory/AgendaCategoryUpdateModal.tsx b/src/components/OrgSettings/AgendaItemCategories/AgendaCategoryUpdateModal.tsx similarity index 76% rename from src/screens/OrganizationAgendaCategory/AgendaCategoryUpdateModal.tsx rename to src/components/OrgSettings/AgendaItemCategories/AgendaCategoryUpdateModal.tsx index 868205c339..508f1db69b 100644 --- a/src/screens/OrganizationAgendaCategory/AgendaCategoryUpdateModal.tsx +++ b/src/components/OrgSettings/AgendaItemCategories/AgendaCategoryUpdateModal.tsx @@ -4,12 +4,18 @@ import type { ChangeEvent } from 'react'; import styles from './OrganizationAgendaCategory.module.css'; +/** + * InterfaceFormStateType is an object containing the form state + */ interface InterfaceFormStateType { name: string; description: string; createdBy: string; } +/** + * InterfaceAgendaCategoryUpdateModalProps is an object containing the props for AgendaCategoryUpdateModal component + */ interface InterfaceAgendaCategoryUpdateModalProps { agendaCategoryUpdateModalIsOpen: boolean; hideUpdateModal: () => void; @@ -21,6 +27,16 @@ interface InterfaceAgendaCategoryUpdateModalProps { t: (key: string) => string; } +/** + * AgendaCategoryUpdateModal component is used to update the agenda category details like name, description + * @param agendaCategoryUpdateModalIsOpen - boolean value to check if the modal is open or not + * @param hideUpdateModal - function to hide the modal + * @param formState - object containing the form state + * @param setFormState - function to set the form state + * @param updateAgendaCategoryHandler - function to update the agenda category + * @param t - i18n function to translate the text + * @returns returns the AgendaCategoryUpdateModal component + */ const AgendaCategoryUpdateModal: React.FC< InterfaceAgendaCategoryUpdateModalProps > = ({ diff --git a/src/screens/OrganizationAgendaCategory/OrganizationAgendaCategory.module.css b/src/components/OrgSettings/AgendaItemCategories/OrganizationAgendaCategory.module.css similarity index 100% rename from src/screens/OrganizationAgendaCategory/OrganizationAgendaCategory.module.css rename to src/components/OrgSettings/AgendaItemCategories/OrganizationAgendaCategory.module.css diff --git a/src/screens/OrganizationAgendaCategory/OrganizationAgendaCategory.test.tsx b/src/components/OrgSettings/AgendaItemCategories/OrganizationAgendaCategory.test.tsx similarity index 96% rename from src/screens/OrganizationAgendaCategory/OrganizationAgendaCategory.test.tsx rename to src/components/OrgSettings/AgendaItemCategories/OrganizationAgendaCategory.test.tsx index 732db13a74..e05edc665d 100644 --- a/src/screens/OrganizationAgendaCategory/OrganizationAgendaCategory.test.tsx +++ b/src/components/OrgSettings/AgendaItemCategories/OrganizationAgendaCategory.test.tsx @@ -76,7 +76,7 @@ describe('Testing Agenda Categories Component', () => { - {} + {} @@ -96,7 +96,7 @@ describe('Testing Agenda Categories Component', () => { - {} + {} @@ -119,7 +119,7 @@ describe('Testing Agenda Categories Component', () => { - {} + {} @@ -152,7 +152,7 @@ describe('Testing Agenda Categories Component', () => { - {} + {} diff --git a/src/screens/OrganizationAgendaCategory/OrganizationAgendaCategory.tsx b/src/components/OrgSettings/AgendaItemCategories/OrganizationAgendaCategory.tsx similarity index 78% rename from src/screens/OrganizationAgendaCategory/OrganizationAgendaCategory.tsx rename to src/components/OrgSettings/AgendaItemCategories/OrganizationAgendaCategory.tsx index 4216d309a2..884371d862 100644 --- a/src/screens/OrganizationAgendaCategory/OrganizationAgendaCategory.tsx +++ b/src/components/OrgSettings/AgendaItemCategories/OrganizationAgendaCategory.tsx @@ -1,8 +1,7 @@ import React, { useState } from 'react'; -import type { ChangeEvent } from 'react'; +import type { ChangeEvent, FC } from 'react'; import { useTranslation } from 'react-i18next'; import { Button } from 'react-bootstrap'; -import { useParams } from 'react-router-dom'; import { WarningAmberRounded } from '@mui/icons-material'; import { toast } from 'react-toastify'; @@ -17,13 +16,26 @@ import AgendaCategoryCreateModal from './AgendaCategoryCreateModal'; import styles from './OrganizationAgendaCategory.module.css'; import Loader from 'components/Loader/Loader'; -function organizationAgendaCategory(): JSX.Element { +interface InterfaceAgendaCategoryProps { + orgId: string; +} + +/** + * Component for managing and displaying agenda item categories within an organization. + * + * This component allows users to view, create, and manage agenda item categories. It includes functionality for displaying categories, handling creation, and managing modal visibility. + * + * @returns The rendered component. + */ + +const organizationAgendaCategory: FC = ({ + orgId, +}) => { const { t } = useTranslation('translation', { keyPrefix: 'organizationAgendaCategory', }); - const { orgId: currentUrl } = useParams(); - + // State for managing modal visibility and form data const [agendaCategoryCreateModalIsOpen, setAgendaCategoryCreateModalIsOpen] = useState(false); @@ -33,6 +45,9 @@ function organizationAgendaCategory(): JSX.Element { createdBy: '', }); + /** + * Query to fetch agenda item categories for the organization. + */ const { data: agendaCategoryData, loading: agendaCategoryLoading, @@ -44,14 +59,23 @@ function organizationAgendaCategory(): JSX.Element { error?: unknown | undefined; refetch: () => void; } = useQuery(AGENDA_ITEM_CATEGORY_LIST, { - variables: { organizationId: currentUrl }, + variables: { organizationId: orgId }, notifyOnNetworkStatusChange: true, }); + /** + * Mutation to create a new agenda item category. + */ const [createAgendaCategory] = useMutation( CREATE_AGENDA_ITEM_CATEGORY_MUTATION, ); + /** + * Handler function to create a new agenda item category. + * + * @param e - The form submit event. + * @returns A promise that resolves when the agenda item category is created. + */ const createAgendaCategoryHandler = async ( e: ChangeEvent, ): Promise => { @@ -60,13 +84,13 @@ function organizationAgendaCategory(): JSX.Element { await createAgendaCategory({ variables: { input: { - organizationId: currentUrl, + organizationId: orgId, name: formState.name, description: formState.description, }, }, }); - toast.success(t('agendaCategoryCreated')); + toast.success(t('agendaCategoryCreated') as string); setFormState({ name: '', description: '', createdBy: '' }); refetchAgendaCategory(); hideCreateModal(); @@ -77,10 +101,16 @@ function organizationAgendaCategory(): JSX.Element { } }; + /** + * Toggles the visibility of the create agenda item category modal. + */ const showCreateModal = (): void => { setAgendaCategoryCreateModalIsOpen(!agendaCategoryCreateModalIsOpen); }; + /** + * Hides the create agenda item category modal. + */ const hideCreateModal = (): void => { setAgendaCategoryCreateModalIsOpen(!agendaCategoryCreateModalIsOpen); }; @@ -105,7 +135,7 @@ function organizationAgendaCategory(): JSX.Element { } return ( -
    +
    @@ -152,6 +182,6 @@ function organizationAgendaCategory(): JSX.Element { />
    ); -} +}; export default organizationAgendaCategory; diff --git a/src/screens/OrganizationAgendaCategory/OrganizationAgendaCategoryErrorMocks.ts b/src/components/OrgSettings/AgendaItemCategories/OrganizationAgendaCategoryErrorMocks.ts similarity index 100% rename from src/screens/OrganizationAgendaCategory/OrganizationAgendaCategoryErrorMocks.ts rename to src/components/OrgSettings/AgendaItemCategories/OrganizationAgendaCategoryErrorMocks.ts diff --git a/src/screens/OrganizationAgendaCategory/OrganizationAgendaCategoryMocks.ts b/src/components/OrgSettings/AgendaItemCategories/OrganizationAgendaCategoryMocks.ts similarity index 100% rename from src/screens/OrganizationAgendaCategory/OrganizationAgendaCategoryMocks.ts rename to src/components/OrgSettings/AgendaItemCategories/OrganizationAgendaCategoryMocks.ts diff --git a/src/components/DeleteOrg/DeleteOrg.module.css b/src/components/OrgSettings/General/DeleteOrg/DeleteOrg.module.css similarity index 100% rename from src/components/DeleteOrg/DeleteOrg.module.css rename to src/components/OrgSettings/General/DeleteOrg/DeleteOrg.module.css diff --git a/src/components/OrgSettings/General/DeleteOrg/DeleteOrg.test.tsx b/src/components/OrgSettings/General/DeleteOrg/DeleteOrg.test.tsx new file mode 100644 index 0000000000..77ffe65c08 --- /dev/null +++ b/src/components/OrgSettings/General/DeleteOrg/DeleteOrg.test.tsx @@ -0,0 +1,307 @@ +import React, { act } from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { render, screen, waitFor } from '@testing-library/react'; +import 'jest-location-mock'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; + +import { + DELETE_ORGANIZATION_MUTATION, + REMOVE_SAMPLE_ORGANIZATION_MUTATION, +} from 'GraphQl/Mutations/mutations'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18nForTest from 'utils/i18nForTest'; +import DeleteOrg from './DeleteOrg'; +import { ToastContainer, toast } from 'react-toastify'; +import { IS_SAMPLE_ORGANIZATION_QUERY } from 'GraphQl/Queries/Queries'; +import useLocalStorage from 'utils/useLocalstorage'; + +const { setItem } = useLocalStorage(); + +async function wait(ms = 1000): Promise { + await act(async () => { + await new Promise((resolve) => setTimeout(resolve, ms)); + }); +} + +const MOCKS = [ + { + request: { + query: IS_SAMPLE_ORGANIZATION_QUERY, + variables: { + isSampleOrganizationId: '123', + }, + }, + result: { + data: { + isSampleOrganization: true, + }, + }, + }, + { + request: { + query: REMOVE_SAMPLE_ORGANIZATION_MUTATION, + }, + result: { + data: { + removeSampleOrganization: true, + }, + }, + }, + { + request: { + query: DELETE_ORGANIZATION_MUTATION, + variables: { + id: '456', + }, + }, + result: { + data: { + removeOrganization: { + _id: '456', + }, + }, + }, + }, +]; + +const MOCKS_WITH_ERROR = [ + { + request: { + query: IS_SAMPLE_ORGANIZATION_QUERY, + variables: { + isSampleOrganizationId: '123', + }, + }, + result: { + data: { + isSampleOrganization: true, + }, + }, + }, + { + request: { + query: DELETE_ORGANIZATION_MUTATION, + variables: { + id: '456', + }, + }, + error: new Error('Failed to delete organization'), + }, + { + request: { + query: REMOVE_SAMPLE_ORGANIZATION_MUTATION, + }, + error: new Error('Failed to delete sample organization'), + }, +]; + +const mockNavgatePush = jest.fn(); +let mockURL = '123'; +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: mockURL }), + useNavigate: () => mockNavgatePush, +})); + +const link = new StaticMockLink(MOCKS, true); +const link2 = new StaticMockLink(MOCKS_WITH_ERROR, true); + +afterEach(() => { + localStorage.clear(); +}); + +describe('Delete Organization Component', () => { + test('should be able to Toggle Delete Organization Modal', async () => { + mockURL = '456'; + setItem('SuperAdmin', true); + await act(async () => { + render( + + + + + + + + + + , + ); + }); + act(() => { + screen.getByTestId(/openDeleteModalBtn/i).click(); + }); + expect(await screen.findByTestId(/orgDeleteModal/i)).toBeInTheDocument(); + act(() => { + screen.getByTestId(/closeDelOrgModalBtn/i).click(); + }); + await waitFor(() => { + expect(screen.queryByTestId(/orgDeleteModal/i)).not.toBeInTheDocument(); + }); + }); + + test('should be able to Toggle Delete Organization Modal When Organization is Sample Organization', async () => { + mockURL = '123'; + setItem('SuperAdmin', true); + await act(async () => { + render( + + + + + + + + + + , + ); + }); + await wait(); + act(() => { + screen.getByTestId(/openDeleteModalBtn/i).click(); + }); + expect(screen.getByTestId(/orgDeleteModal/i)).toBeInTheDocument(); + act(() => { + screen.getByTestId(/closeDelOrgModalBtn/i).click(); + }); + await waitFor(() => { + expect(screen.queryByTestId(/orgDeleteModal/i)).not.toBeInTheDocument(); + }); + }); + + test('Delete organization functionality should work properly', async () => { + mockURL = '456'; + setItem('SuperAdmin', true); + await act(async () => { + render( + + + + + + + + + , + ); + }); + screen.debug(); + act(() => { + screen.getByTestId('openDeleteModalBtn').click(); + }); + screen.debug(); + expect(await screen.findByTestId('orgDeleteModal')).toBeInTheDocument(); + const deleteButton = await screen.findByTestId('deleteOrganizationBtn'); + act(() => { + deleteButton.click(); + }); + }); + + test('Delete organization functionality should work properly for sample org', async () => { + mockURL = '123'; + setItem('SuperAdmin', true); + await act(async () => { + render( + + + + + + + + + , + ); + }); + await waitFor(() => { + expect(screen.getByTestId('openDeleteModalBtn')).toBeInTheDocument(); + }); + act(() => { + screen.getByTestId('openDeleteModalBtn').click(); + }); + await waitFor(() => { + expect(screen.getByTestId('orgDeleteModal')).toBeInTheDocument(); + }); + const deleteButton = await screen.findByTestId('deleteOrganizationBtn'); + act(() => { + deleteButton.click(); + }); + await wait(2000); + expect(mockNavgatePush).toHaveBeenCalledWith('/orglist'); + }); + + test('Error handling for IS_SAMPLE_ORGANIZATION_QUERY mock', async () => { + mockURL = '123'; + setItem('SuperAdmin', true); + jest.spyOn(toast, 'error'); + await act(async () => { + render( + + + + + + + + + , + ); + }); + await waitFor(() => { + expect(screen.getByTestId('openDeleteModalBtn')).toBeInTheDocument(); + }); + act(() => { + screen.getByTestId('openDeleteModalBtn').click(); + }); + await waitFor(() => { + expect(screen.getByTestId('orgDeleteModal')).toBeInTheDocument(); + }); + act(() => { + screen.getByTestId('deleteOrganizationBtn').click(); + }); + await waitFor(() => { + expect(toast.error).toHaveBeenCalledWith( + 'Failed to delete sample organization', + ); + }); + }); + + test('Error handling for DELETE_ORGANIZATION_MUTATION mock', async () => { + mockURL = '456'; + setItem('SuperAdmin', true); + jest.spyOn(toast, 'error'); + + await act(async () => { + render( + + + + + + + + + , + ); + }); + await waitFor(() => { + expect(screen.getByTestId('openDeleteModalBtn')).toBeInTheDocument(); + }); + act(() => { + screen.getByTestId('openDeleteModalBtn').click(); + }); + await waitFor(() => { + expect(screen.getByTestId('orgDeleteModal')).toBeInTheDocument(); + }); + act(() => { + screen.getByTestId('deleteOrganizationBtn').click(); + }); + await waitFor(() => { + expect(toast.error).toHaveBeenCalledWith('Failed to delete organization'); + }); + }); +}); diff --git a/src/components/DeleteOrg/DeleteOrg.tsx b/src/components/OrgSettings/General/DeleteOrg/DeleteOrg.tsx similarity index 76% rename from src/components/DeleteOrg/DeleteOrg.tsx rename to src/components/OrgSettings/General/DeleteOrg/DeleteOrg.tsx index ab2772785f..8edf11ca22 100644 --- a/src/components/DeleteOrg/DeleteOrg.tsx +++ b/src/components/OrgSettings/General/DeleteOrg/DeleteOrg.tsx @@ -13,34 +13,63 @@ import styles from './DeleteOrg.module.css'; import { useNavigate, useParams } from 'react-router-dom'; import useLocalStorage from 'utils/useLocalstorage'; +/** + * A component for deleting an organization. + * + * It displays a card with a delete button. When the delete button is clicked, + * a modal appears asking for confirmation. Depending on the type of organization + * (sample or regular), it performs the delete operation and shows appropriate + * success or error messages. + * + * @returns JSX.Element - The rendered component with delete functionality. + */ function deleteOrg(): JSX.Element { + // Translation hook for localization const { t } = useTranslation('translation', { keyPrefix: 'deleteOrg', }); const { t: tCommon } = useTranslation('common'); + + // Get the current organization ID from the URL const { orgId: currentUrl } = useParams(); + // Navigation hook for redirecting const navigate = useNavigate(); + // State to control the visibility of the delete confirmation modal const [showDeleteModal, setShowDeleteModal] = useState(false); + + // Hook for accessing local storage const { getItem } = useLocalStorage(); + // Check if the user has super admin privileges const canDelete = getItem('SuperAdmin'); + + /** + * Toggles the visibility of the delete confirmation modal. + */ const toggleDeleteModal = (): void => setShowDeleteModal(!showDeleteModal); + // GraphQL mutations for deleting organizations const [del] = useMutation(DELETE_ORGANIZATION_MUTATION); const [removeSampleOrganization] = useMutation( REMOVE_SAMPLE_ORGANIZATION_MUTATION, ); + // Query to check if the organization is a sample organization const { data } = useQuery(IS_SAMPLE_ORGANIZATION_QUERY, { variables: { isSampleOrganizationId: currentUrl, }, }); + /** + * Deletes the organization. It handles both sample and regular organizations. + * Displays success or error messages based on the operation result. + */ const deleteOrg = async (): Promise => { if (data && data.isSampleOrganization) { + // If it's a sample organization, use a specific mutation removeSampleOrganization() .then(() => { - toast.success(t('successfullyDeletedSampleOrganization')); + toast.success(t('successfullyDeletedSampleOrganization') as string); setTimeout(() => { navigate('/orglist'); }, 1000); @@ -49,6 +78,7 @@ function deleteOrg(): JSX.Element { toast.error(error.message); }); } else { + // For regular organizations, use a different mutation try { await del({ variables: { diff --git a/src/components/OrgSettings/General/GeneralSettings.tsx b/src/components/OrgSettings/General/GeneralSettings.tsx new file mode 100644 index 0000000000..4dbca1b6eb --- /dev/null +++ b/src/components/OrgSettings/General/GeneralSettings.tsx @@ -0,0 +1,73 @@ +import React, { type FC } from 'react'; +import { Card, Col, Form, Row } from 'react-bootstrap'; +import styles from 'screens/OrgSettings/OrgSettings.module.css'; +import OrgProfileFieldSettings from './OrgProfileFieldSettings/OrgProfileFieldSettings'; +import ChangeLanguageDropDown from 'components/ChangeLanguageDropdown/ChangeLanguageDropDown'; +import DeleteOrg from './DeleteOrg/DeleteOrg'; +import OrgUpdate from './OrgUpdate/OrgUpdate'; +import { useTranslation } from 'react-i18next'; + +/** + * Props for the `GeneralSettings` component. + */ +interface InterfaceGeneralSettingsProps { + orgId: string; +} + +/** + * A component for displaying general settings for an organization. + * + * @param props - The properties passed to the component. + * @returns The `GeneralSettings` component. + */ +const GeneralSettings: FC = ({ orgId }) => { + const { t } = useTranslation('translation', { + keyPrefix: 'orgSettings', + }); + + return ( + + + +
    +
    {t('updateOrganization')}
    +
    + + {/* Render organization update component */} + + +
    + + + + +
    +
    {t('otherSettings')}
    +
    + +
    + + {t('changeLanguage')} + + {/* Render language change dropdown component */} + +
    +
    +
    + + + +
    +
    {t('manageCustomFields')}
    +
    + + {/* Render organization profile field settings component */} + + +
    + +
    + ); +}; + +export default GeneralSettings; diff --git a/src/components/OrgProfileFieldSettings/OrgProfileFieldSettings.module.css b/src/components/OrgSettings/General/OrgProfileFieldSettings/OrgProfileFieldSettings.module.css similarity index 100% rename from src/components/OrgProfileFieldSettings/OrgProfileFieldSettings.module.css rename to src/components/OrgSettings/General/OrgProfileFieldSettings/OrgProfileFieldSettings.module.css diff --git a/src/components/OrgProfileFieldSettings/OrgProfileFieldSettings.test.tsx b/src/components/OrgSettings/General/OrgProfileFieldSettings/OrgProfileFieldSettings.test.tsx similarity index 98% rename from src/components/OrgProfileFieldSettings/OrgProfileFieldSettings.test.tsx rename to src/components/OrgSettings/General/OrgProfileFieldSettings/OrgProfileFieldSettings.test.tsx index 2630c6c4ee..8db8773381 100644 --- a/src/components/OrgProfileFieldSettings/OrgProfileFieldSettings.test.tsx +++ b/src/components/OrgSettings/General/OrgProfileFieldSettings/OrgProfileFieldSettings.test.tsx @@ -1,5 +1,5 @@ -import React from 'react'; -import { act, render, screen } from '@testing-library/react'; +import React, { act } from 'react'; +import { render, screen } from '@testing-library/react'; import { MockedProvider } from '@apollo/react-testing'; import userEvent from '@testing-library/user-event'; import { I18nextProvider } from 'react-i18next'; diff --git a/src/components/OrgProfileFieldSettings/OrgProfileFieldSettings.tsx b/src/components/OrgSettings/General/OrgProfileFieldSettings/OrgProfileFieldSettings.tsx similarity index 82% rename from src/components/OrgProfileFieldSettings/OrgProfileFieldSettings.tsx rename to src/components/OrgSettings/General/OrgProfileFieldSettings/OrgProfileFieldSettings.tsx index ba2d3a9c02..dcb6992e21 100644 --- a/src/components/OrgProfileFieldSettings/OrgProfileFieldSettings.tsx +++ b/src/components/OrgSettings/General/OrgProfileFieldSettings/OrgProfileFieldSettings.tsx @@ -13,28 +13,39 @@ import { useTranslation } from 'react-i18next'; import { toast } from 'react-toastify'; import EditOrgCustomFieldDropDown from 'components/EditCustomFieldDropDown/EditCustomFieldDropDown'; import { useParams } from 'react-router-dom'; +import type { InterfaceCustomFieldData } from 'utils/interfaces'; -export interface InterfaceCustomFieldData { - type: string; - name: string; -} - +/** + * Component for managing organization profile field settings + * + * This component allows adding and removing custom fields for an organization. + * It displays existing custom fields and provides a form to add new fields. + * + * @returns JSX.Element representing the organization profile field settings + */ const OrgProfileFieldSettings = (): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'orgProfileField', }); const { t: tCommon } = useTranslation('common'); + // State to hold the custom field data const [customFieldData, setCustomFieldData] = useState({ type: '', name: '', }); + + // Get the current organization ID from the URL parameters const { orgId: currentOrgId } = useParams(); + // Mutation to add a custom field const [addCustomField] = useMutation(ADD_CUSTOM_FIELD); + + // Mutation to remove a custom field const [removeCustomField] = useMutation(REMOVE_CUSTOM_FIELD); + // Query to fetch custom fields for the organization const { loading, error, data, refetch } = useQuery( ORGANIZATION_CUSTOM_FIELDS, { @@ -44,6 +55,7 @@ const OrgProfileFieldSettings = (): JSX.Element => { }, ); + // Function to handle saving a new custom field const handleSave = async (): Promise => { try { await addCustomField({ @@ -52,7 +64,7 @@ const OrgProfileFieldSettings = (): JSX.Element => { ...customFieldData, }, }); - toast.success(t('fieldSuccessMessage')); + toast.success(t('fieldSuccessMessage') as string); setCustomFieldData({ type: '', name: '' }); refetch(); } catch (error) { @@ -60,6 +72,7 @@ const OrgProfileFieldSettings = (): JSX.Element => { } }; + // Function to handle removing a custom field const handleRemove = async (customFieldId: string): Promise => { try { await removeCustomField({ @@ -69,18 +82,20 @@ const OrgProfileFieldSettings = (): JSX.Element => { }, }); - toast.success(t('fieldRemovalSuccess')); + toast.success(t('fieldRemovalSuccess') as string); refetch(); } catch (error) { toast.error((error as Error).message); } }; + // Render loading or error messages if needed if (loading) return

    {tCommon('loading')}

    ; if (error) return

    {error.message}

    ; return (
    + {/* Display existing custom fields or a message if there are none */} {data.customFieldsByOrganization.length === 0 ? (

    {t('noCustomField')}

    ) : ( @@ -99,6 +114,7 @@ const OrgProfileFieldSettings = (): JSX.Element => { {field.name} {field.type} + {/* Button to remove a custom field */}
    + {/* Delete button */}
    + {/* Dropdown for filtering members */} + {/* Dropdown for sorting by name */}
    {/* Table */} - {loadingMembers == false && + {loadingMembers === false && membersData.length === 0 && searchByName.length > 0 ? (
    @@ -241,7 +280,7 @@ const Requests = (): JSX.Element => { {tCommon('noResultsFoundFor')} "{searchByName}"
    - ) : loadingMembers == false && membersData.length === 0 ? ( + ) : loadingMembers === false && membersData.length === 0 ? (

    {t('noSpammerFound')}

    diff --git a/src/screens/CommunityProfile/CommunityProfile.test.tsx b/src/screens/CommunityProfile/CommunityProfile.test.tsx index 6f1717bf30..d7e056caa4 100644 --- a/src/screens/CommunityProfile/CommunityProfile.test.tsx +++ b/src/screens/CommunityProfile/CommunityProfile.test.tsx @@ -1,6 +1,6 @@ -import React from 'react'; +import React, { act } from 'react'; import { MockedProvider } from '@apollo/react-testing'; -import { act, render, screen } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import 'jest-localstorage-mock'; import 'jest-location-mock'; @@ -36,7 +36,7 @@ const MOCKS1 = [ socialMediaUrls: { facebook: 'https://socialurl.com', instagram: 'https://socialurl.com', - twitter: 'https://socialurl.com', + X: 'https://socialurl.com', linkedIn: 'https://socialurl.com', gitHub: 'https://socialurl.com', youTube: 'https://socialurl.com', @@ -74,7 +74,7 @@ const MOCKS2 = [ linkedIn: null, reddit: null, slack: null, - twitter: null, + X: null, }, }, }, @@ -115,7 +115,7 @@ const MOCKS3 = [ linkedIn: 'http://sociallink.com', reddit: 'http://sociallink.com', slack: 'http://sociallink.com', - twitter: 'http://sociallink.com', + X: 'http://sociallink.com', }, }, }, @@ -188,7 +188,7 @@ describe('Testing Community Profile Screen', () => { expect(screen.getByPlaceholderText(/Website Link/i)).toBeInTheDocument(); expect(screen.getByTestId(/facebook/i)).toBeInTheDocument(); expect(screen.getByTestId(/instagram/i)).toBeInTheDocument(); - expect(screen.getByTestId(/twitter/i)).toBeInTheDocument(); + expect(screen.getByTestId(/X/i)).toBeInTheDocument(); expect(screen.getByTestId(/linkedIn/i)).toBeInTheDocument(); expect(screen.getByTestId(/github/i)).toBeInTheDocument(); expect(screen.getByTestId(/youtube/i)).toBeInTheDocument(); @@ -213,53 +213,53 @@ describe('Testing Community Profile Screen', () => { , ); - await wait(); + }); + await wait(); - const communityName = screen.getByPlaceholderText(/Community Name/i); - const websiteLink = screen.getByPlaceholderText(/Website Link/i); - const logo = screen.getByTestId(/fileInput/i); - const facebook = screen.getByTestId(/facebook/i); - const instagram = screen.getByTestId(/instagram/i); - const twitter = screen.getByTestId(/twitter/i); - const linkedIn = screen.getByTestId(/linkedIn/i); - const github = screen.getByTestId(/github/i); - const youtube = screen.getByTestId(/youtube/i); - const reddit = screen.getByTestId(/reddit/i); - const slack = screen.getByTestId(/slack/i); - const saveChangesBtn = screen.getByTestId(/saveChangesBtn/i); - const resetChangeBtn = screen.getByTestId(/resetChangesBtn/i); + const communityName = screen.getByPlaceholderText(/Community Name/i); + const websiteLink = screen.getByPlaceholderText(/Website Link/i); + const logo = screen.getByTestId(/fileInput/i); + const facebook = screen.getByTestId(/facebook/i); + const instagram = screen.getByTestId(/instagram/i); + const X = screen.getByTestId(/X/i); + const linkedIn = screen.getByTestId(/linkedIn/i); + const github = screen.getByTestId(/github/i); + const youtube = screen.getByTestId(/youtube/i); + const reddit = screen.getByTestId(/reddit/i); + const slack = screen.getByTestId(/slack/i); + const saveChangesBtn = screen.getByTestId(/saveChangesBtn/i); + const resetChangeBtn = screen.getByTestId(/resetChangesBtn/i); - userEvent.type(communityName, profileVariables.name); - userEvent.type(websiteLink, profileVariables.websiteLink); - userEvent.type(facebook, profileVariables.socialUrl); - userEvent.type(instagram, profileVariables.socialUrl); - userEvent.type(twitter, profileVariables.socialUrl); - userEvent.type(linkedIn, profileVariables.socialUrl); - userEvent.type(github, profileVariables.socialUrl); - userEvent.type(youtube, profileVariables.socialUrl); - userEvent.type(reddit, profileVariables.socialUrl); - userEvent.type(slack, profileVariables.socialUrl); - userEvent.upload(logo, profileVariables.logo); - await wait(); + userEvent.type(communityName, profileVariables.name); + userEvent.type(websiteLink, profileVariables.websiteLink); + userEvent.type(facebook, profileVariables.socialUrl); + userEvent.type(instagram, profileVariables.socialUrl); + userEvent.type(X, profileVariables.socialUrl); + userEvent.type(linkedIn, profileVariables.socialUrl); + userEvent.type(github, profileVariables.socialUrl); + userEvent.type(youtube, profileVariables.socialUrl); + userEvent.type(reddit, profileVariables.socialUrl); + userEvent.type(slack, profileVariables.socialUrl); + userEvent.upload(logo, profileVariables.logo); + await wait(); - expect(communityName).toHaveValue(profileVariables.name); - expect(websiteLink).toHaveValue(profileVariables.websiteLink); - // expect(logo).toBeTruthy(); - expect(facebook).toHaveValue(profileVariables.socialUrl); - expect(instagram).toHaveValue(profileVariables.socialUrl); - expect(twitter).toHaveValue(profileVariables.socialUrl); - expect(linkedIn).toHaveValue(profileVariables.socialUrl); - expect(github).toHaveValue(profileVariables.socialUrl); - expect(youtube).toHaveValue(profileVariables.socialUrl); - expect(reddit).toHaveValue(profileVariables.socialUrl); - expect(slack).toHaveValue(profileVariables.socialUrl); - expect(saveChangesBtn).not.toBeDisabled(); - expect(resetChangeBtn).not.toBeDisabled(); - await wait(); + expect(communityName).toHaveValue(profileVariables.name); + expect(websiteLink).toHaveValue(profileVariables.websiteLink); + // expect(logo).toBeTruthy(); + expect(facebook).toHaveValue(profileVariables.socialUrl); + expect(instagram).toHaveValue(profileVariables.socialUrl); + expect(X).toHaveValue(profileVariables.socialUrl); + expect(linkedIn).toHaveValue(profileVariables.socialUrl); + expect(github).toHaveValue(profileVariables.socialUrl); + expect(youtube).toHaveValue(profileVariables.socialUrl); + expect(reddit).toHaveValue(profileVariables.socialUrl); + expect(slack).toHaveValue(profileVariables.socialUrl); + expect(saveChangesBtn).not.toBeDisabled(); + expect(resetChangeBtn).not.toBeDisabled(); + await wait(); - userEvent.click(saveChangesBtn); - await wait(); - }); + userEvent.click(saveChangesBtn); + await wait(); }); test('If the queried data has some fields null then the input field should be empty', async () => { @@ -276,7 +276,7 @@ describe('Testing Community Profile Screen', () => { expect(screen.getByPlaceholderText(/Website Link/i)).toHaveValue(''); expect(screen.getByTestId(/facebook/i)).toHaveValue(''); expect(screen.getByTestId(/instagram/i)).toHaveValue(''); - expect(screen.getByTestId(/twitter/i)).toHaveValue(''); + expect(screen.getByTestId(/X/i)).toHaveValue(''); expect(screen.getByTestId(/linkedIn/i)).toHaveValue(''); expect(screen.getByTestId(/github/i)).toHaveValue(''); expect(screen.getByTestId(/youtube/i)).toHaveValue(''); @@ -302,7 +302,7 @@ describe('Testing Community Profile Screen', () => { expect(screen.getByPlaceholderText(/Website Link/i)).toHaveValue(''); expect(screen.getByTestId(/facebook/i)).toHaveValue(''); expect(screen.getByTestId(/instagram/i)).toHaveValue(''); - expect(screen.getByTestId(/twitter/i)).toHaveValue(''); + expect(screen.getByTestId(/X/i)).toHaveValue(''); expect(screen.getByTestId(/linkedIn/i)).toHaveValue(''); expect(screen.getByTestId(/github/i)).toHaveValue(''); expect(screen.getByTestId(/youtube/i)).toHaveValue(''); @@ -324,7 +324,7 @@ describe('Testing Community Profile Screen', () => { expect(screen.getByPlaceholderText(/Website Link/i)).toHaveValue(''); expect(screen.getByTestId(/facebook/i)).toHaveValue(''); expect(screen.getByTestId(/instagram/i)).toHaveValue(''); - expect(screen.getByTestId(/twitter/i)).toHaveValue(''); + expect(screen.getByTestId(/X/i)).toHaveValue(''); expect(screen.getByTestId(/linkedIn/i)).toHaveValue(''); expect(screen.getByTestId(/github/i)).toHaveValue(''); expect(screen.getByTestId(/youtube/i)).toHaveValue(''); diff --git a/src/screens/CommunityProfile/CommunityProfile.tsx b/src/screens/CommunityProfile/CommunityProfile.tsx index 96650c1ed8..02f8b8aca4 100644 --- a/src/screens/CommunityProfile/CommunityProfile.tsx +++ b/src/screens/CommunityProfile/CommunityProfile.tsx @@ -10,7 +10,7 @@ import { UPDATE_COMMUNITY, RESET_COMMUNITY } from 'GraphQl/Mutations/mutations'; import { FacebookLogo, InstagramLogo, - TwitterLogo, + XLogo, LinkedInLogo, GithubLogo, YoutubeLogo, @@ -21,14 +21,31 @@ import convertToBase64 from 'utils/convertToBase64'; import styles from './CommunityProfile.module.css'; import { errorHandler } from 'utils/errorHandler'; +/** + * `CommunityProfile` component allows users to view and update their community profile details. + * + * It includes functionalities to: + * - Display current community profile information + * - Update profile details including social media links and logo + * - Reset profile changes to the initial state + * + * @returns JSX.Element - The `CommunityProfile` component. + * + * @example + * ```tsx + * + * ``` + */ const CommunityProfile = (): JSX.Element => { + // Translation hooks for internationalization const { t } = useTranslation('translation', { keyPrefix: 'communityProfile', }); const { t: tCommon } = useTranslation('common'); - document.title = t('title'); + document.title = t('title'); // Set document title + // Define the type for pre-login imagery data type PreLoginImageryDataType = { _id: string; name: string | undefined; @@ -37,7 +54,7 @@ const CommunityProfile = (): JSX.Element => { socialMediaUrls: { facebook: string | undefined; instagram: string | undefined; - twitter: string | undefined; + X: string | undefined; linkedIn: string | undefined; gitHub: string | undefined; youTube: string | undefined; @@ -46,13 +63,14 @@ const CommunityProfile = (): JSX.Element => { }; }; + // State hook for managing profile variables const [profileVariable, setProfileVariable] = React.useState({ name: '', websiteLink: '', logoUrl: '', facebook: '', instagram: '', - twitter: '', + X: '', linkedIn: '', github: '', youtube: '', @@ -60,10 +78,14 @@ const CommunityProfile = (): JSX.Element => { slack: '', }); + // Query to fetch community data const { data, loading } = useQuery(GET_COMMUNITY_DATA); + + // Mutations for updating and resetting community data const [uploadPreLoginImagery] = useMutation(UPDATE_COMMUNITY); const [resetPreLoginImagery] = useMutation(RESET_COMMUNITY); + // Effect to set profile data from fetched data React.useEffect(() => { const preLoginData: PreLoginImageryDataType | undefined = data?.getCommunityData; @@ -74,7 +96,7 @@ const CommunityProfile = (): JSX.Element => { logoUrl: preLoginData.logoUrl ?? '', facebook: preLoginData.socialMediaUrls.facebook ?? '', instagram: preLoginData.socialMediaUrls.instagram ?? '', - twitter: preLoginData.socialMediaUrls.twitter ?? '', + X: preLoginData.socialMediaUrls.X ?? '', linkedIn: preLoginData.socialMediaUrls.linkedIn ?? '', github: preLoginData.socialMediaUrls.gitHub ?? '', youtube: preLoginData.socialMediaUrls.youTube ?? '', @@ -83,6 +105,11 @@ const CommunityProfile = (): JSX.Element => { }); }, [data]); + /** + * Handles change events for form inputs. + * + * @param e - Change event for input elements + */ const handleOnChange = (e: React.ChangeEvent): void => { setProfileVariable({ ...profileVariable, @@ -90,6 +117,11 @@ const CommunityProfile = (): JSX.Element => { }); }; + /** + * Handles form submission to update community profile. + * + * @param e - Form submit event + */ const handleOnSubmit = async ( e: React.FormEvent, ): Promise => { @@ -104,7 +136,7 @@ const CommunityProfile = (): JSX.Element => { socialMediaUrls: { facebook: profileVariable.facebook, instagram: profileVariable.instagram, - twitter: profileVariable.twitter, + X: profileVariable.X, linkedIn: profileVariable.linkedIn, gitHub: profileVariable.github, youTube: profileVariable.youtube, @@ -114,13 +146,16 @@ const CommunityProfile = (): JSX.Element => { }, }, }); - toast.success(t('profileChangedMsg')); + toast.success(t('profileChangedMsg') as string); } catch (error: unknown) { /* istanbul ignore next */ errorHandler(t, error as Error); } }; + /** + * Resets profile data to initial values and performs a reset operation. + */ const resetData = async (): Promise => { const preLoginData: PreLoginImageryDataType | undefined = data?.getCommunityData; @@ -131,7 +166,7 @@ const CommunityProfile = (): JSX.Element => { logoUrl: '', facebook: '', instagram: '', - twitter: '', + X: '', linkedIn: '', github: '', youtube: '', @@ -144,13 +179,18 @@ const CommunityProfile = (): JSX.Element => { resetPreLoginImageryId: preLoginData?._id, }, }); - toast.success(t(`resetData`)); + toast.success(t(`resetData`) as string); } catch (error: unknown) { /* istanbul ignore next */ errorHandler(t, error as Error); } }; + /** + * Determines whether the save and reset buttons should be disabled. + * + * @returns boolean - True if buttons should be disabled, otherwise false + */ const isDisabled = (): boolean => { if ( profileVariable.name == '' && @@ -166,6 +206,7 @@ const CommunityProfile = (): JSX.Element => { if (loading) { ; } + return (
    @@ -237,6 +278,7 @@ const CommunityProfile = (): JSX.Element => { {t('social')} + {/* Social media inputs */}
    Facebook Logo { />
    - Twitter Logo + X Logo , + icon: , }, { value: 'registrants', @@ -30,19 +33,21 @@ const eventDashboardTabs: { }, { value: 'eventActions', - icon: , + icon: , }, { value: 'eventAgendas', icon: , }, - { value: 'eventStats', - icon: , + icon: , }, ]; +/** + * Tab options for the event management component. + */ type TabOptions = | 'dashboard' | 'registrants' @@ -50,13 +55,33 @@ type TabOptions = | 'eventAgendas' | 'eventStats'; +/** + * `EventManagement` component handles the display and navigation of different event management sections. + * + * It provides a tabbed interface for: + * - Viewing event dashboard + * - Managing event registrants + * - Handling event actions + * - Reviewing event agendas + * - Viewing event statistics + * + * @returns JSX.Element - The `EventManagement` component. + * + * @example + * ```tsx + * + * ``` + */ const EventManagement = (): JSX.Element => { + // Translation hook for internationalization const { t } = useTranslation('translation', { keyPrefix: 'eventManagement', }); + // Custom hook for accessing local storage const { getItem } = useLocalStorage(); + // Determine user role based on local storage const superAdmin = getItem('SuperAdmin'); const adminFor = getItem('AdminFor'); /*istanbul ignore next*/ @@ -66,19 +91,27 @@ const EventManagement = (): JSX.Element => { ? 'ADMIN' : 'USER'; + // Extract event and organization IDs from URL parameters const { eventId, orgId } = useParams(); /*istanbul ignore next*/ if (!eventId || !orgId) { + // Redirect if event ID or organization ID is missing return ; } + // Hook for navigation const navigate = useNavigate(); - const [tab, setTab] = useState('dashboard'); - const handleClick = (value: TabOptions): void => { - setTab(value); - }; + // State hook for managing the currently selected tab + const [tab, setTab] = useState('dashboard'); + /** + * Renders a button for each tab with the appropriate icon and label. + * + * @param value - The tab value + * @param icon - The icon to display for the tab + * @returns JSX.Element - The rendered button component + */ const renderButton = ({ value, icon, @@ -89,85 +122,123 @@ const EventManagement = (): JSX.Element => { const selected = tab === value; const variant = selected ? 'success' : 'light'; const translatedText = t(value); + const className = selected - ? 'px-4' - : 'text-secondary border-secondary-subtle px-4'; + ? 'px-4 d-flex align-items-center shadow' + : 'text-secondary bg-white px-4 d-flex align-items-center rounded shadow'; const props = { variant, className, - key: value, + style: { height: '2.5rem' }, size: 'sm' as 'sm' | 'lg', - onClick: () => handleClick(value), + onClick: () => setTab(value), 'data-testid': `${value}Btn`, }; return ( - ); }; + const handleBack = (): void => { + /*istanbul ignore next*/ + userRole === 'USER' + ? navigate(`/user/events/${orgId}`) + : navigate(`/orgevents/${orgId}`); + }; + return ( -
    -
    - { - /*istanbul ignore next*/ - userRole === 'USER' - ? navigate(`/user/events/${orgId}`) - : navigate(`/orgevents/${orgId}`); - }} - className="mt-1" - /> -
    - {eventDashboardTabs.map(renderButton)} -
    -
    - - - {(() => { - switch (tab) { - case 'dashboard': - return ( -
    - -
    - ); - case 'registrants': - return ( -
    -

    Event Registrants

    -
    - ); - case 'eventActions': - return ( -
    - -
    - ); - case 'eventAgendas': - return ( -
    - -
    - ); - case 'eventStats': - return ( -
    -

    Event Statistics

    -
    - ); - } - })()} +
    + + +
    + + {eventDashboardTabs.map(renderButton)} +
    + + + + {t(tab)} + + + {/* Render dropdown items for each settings category */} + {eventDashboardTabs.map(({ value, icon }, index) => ( + setTab(value) + } + className={`d-flex gap-2 ${tab === value && 'text-secondary'}`} + > + {icon} {t(value)} + + ))} + + + + +
    +
    + + {/* Render content based on the selected settings category */} + {(() => { + switch (tab) { + case 'dashboard': + return ( +
    + +
    + ); + case 'registrants': + return ( +
    +

    Event Registrants

    +
    + ); + case 'eventActions': + return ( +
    + +
    + ); + case 'eventAgendas': + return ( +
    + +
    + ); + case 'eventStats': + return ( +
    +

    Event Statistics

    +
    + ); + } + })()}
    ); }; diff --git a/src/screens/ForgotPassword/ForgotPassword.test.tsx b/src/screens/ForgotPassword/ForgotPassword.test.tsx index eb62cb0178..be1b1706f8 100644 --- a/src/screens/ForgotPassword/ForgotPassword.test.tsx +++ b/src/screens/ForgotPassword/ForgotPassword.test.tsx @@ -1,13 +1,13 @@ import React from 'react'; import { MockedProvider } from '@apollo/react-testing'; -import { act, render, screen } from '@testing-library/react'; +import { act, render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import 'jest-localstorage-mock'; import 'jest-location-mock'; import { I18nextProvider } from 'react-i18next'; import { Provider } from 'react-redux'; import { BrowserRouter } from 'react-router-dom'; -import { ToastContainer } from 'react-toastify'; +import { toast, ToastContainer } from 'react-toastify'; import { GENERATE_OTP_MUTATION } from 'GraphQl/Mutations/mutations'; import { store } from 'state/store'; @@ -19,6 +19,14 @@ import useLocalStorage from 'utils/useLocalstorage'; const { setItem, removeItem } = useLocalStorage(); +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + warn: jest.fn(), + }, +})); + const MOCKS = [ { request: { @@ -159,7 +167,9 @@ describe('Testing Forgot Password screen', () => { ); userEvent.click(screen.getByText('Get OTP')); - await wait(); + await waitFor(() => { + expect(toast.success).toHaveBeenCalled(); + }); }); test('Testing forgot password functionality', async () => { @@ -294,7 +304,6 @@ describe('Testing Forgot Password screen', () => { - @@ -310,11 +319,9 @@ describe('Testing Forgot Password screen', () => { ); userEvent.click(screen.getByText('Get OTP')); - await wait(); - - expect( - await screen.findByText(translations.emailNotRegistered), - ).toBeInTheDocument(); + await waitFor(() => { + expect(toast.warn).toHaveBeenCalledWith(translations.emailNotRegistered); + }); }); test('Testing forgot password functionality, when there is an error except unregistered email and api failure', async () => { @@ -323,7 +330,6 @@ describe('Testing Forgot Password screen', () => { - @@ -331,11 +337,9 @@ describe('Testing Forgot Password screen', () => { , ); userEvent.click(screen.getByText('Get OTP')); - await wait(); - - expect( - await screen.findByText(translations.errorSendingMail), - ).toBeInTheDocument(); + await waitFor(() => { + expect(toast.error).toHaveBeenCalledWith(translations.errorSendingMail); + }); }); test('Testing forgot password functionality, when talawa api failed', async () => { @@ -347,7 +351,6 @@ describe('Testing Forgot Password screen', () => { - @@ -362,11 +365,11 @@ describe('Testing Forgot Password screen', () => { formData.email, ); userEvent.click(screen.getByText('Get OTP')); - await wait(); - - expect( - await screen.findByText(translations.talawaApiUnavailable), - ).toBeInTheDocument(); + await waitFor(() => { + expect(toast.error).toHaveBeenCalledWith( + translations.talawaApiUnavailable, + ); + }); }); test('Testing forgot password functionality, when otp token is not present', async () => { diff --git a/src/screens/ForgotPassword/ForgotPassword.tsx b/src/screens/ForgotPassword/ForgotPassword.tsx index bf1e8c1ee8..663960572b 100644 --- a/src/screens/ForgotPassword/ForgotPassword.tsx +++ b/src/screens/ForgotPassword/ForgotPassword.tsx @@ -8,7 +8,7 @@ import { FORGOT_PASSWORD_MUTATION, GENERATE_OTP_MUTATION, } from 'GraphQl/Mutations/mutations'; -import { ReactComponent as KeyLogo } from 'assets/svgs/key.svg'; +import KeyLogo from 'assets/svgs/key.svg?react'; import ArrowRightAlt from '@mui/icons-material/ArrowRightAlt'; import Loader from 'components/Loader/Loader'; @@ -19,17 +19,35 @@ import { errorHandler } from 'utils/errorHandler'; import styles from './ForgotPassword.module.css'; import useLocalStorage from 'utils/useLocalstorage'; +/** + * `ForgotPassword` component allows users to reset their password. + * + * It provides two stages: + * 1. Entering the registered email to receive an OTP. + * 2. Entering the OTP and new password to reset the password. + * + * @returns JSX.Element - The `ForgotPassword` component. + * + * @example + * ```tsx + * + * ``` + */ const ForgotPassword = (): JSX.Element => { + // Translation hook for internationalization const { t } = useTranslation('translation', { keyPrefix: 'forgotPassword', }); const { t: tCommon } = useTranslation('common'); const { t: tErrors } = useTranslation('errors'); + // Set the page title document.title = t('title'); + // Custom hook for accessing local storage const { getItem, removeItem, setItem } = useLocalStorage(); + // State hooks for form data and UI const [showEnterEmail, setShowEnterEmail] = useState(true); const [registeredEmail, setregisteredEmail] = useState(''); @@ -40,10 +58,13 @@ const ForgotPassword = (): JSX.Element => { confirmNewPassword: '', }); + // GraphQL mutations const [otp, { loading: otpLoading }] = useMutation(GENERATE_OTP_MUTATION); const [forgotPassword, { loading: forgotPasswordLoading }] = useMutation( FORGOT_PASSWORD_MUTATION, ); + + // Check if the user is already logged in const isLoggedIn = getItem('IsLoggedIn'); useEffect(() => { if (isLoggedIn == 'TRUE') { @@ -54,6 +75,11 @@ const ForgotPassword = (): JSX.Element => { }; }, []); + /** + * Handles the form submission for generating OTP. + * + * @param e - The form submit event + */ const getOTP = async (e: ChangeEvent): Promise => { e.preventDefault(); @@ -64,24 +90,25 @@ const ForgotPassword = (): JSX.Element => { }, }); - if (data) { - setItem('otpToken', data.otp.otpToken); - toast.success(t('OTPsent')); - setShowEnterEmail(false); - } + setItem('otpToken', data.otp.otpToken); + toast.success(t('OTPsent')); + setShowEnterEmail(false); } catch (error: unknown) { - if (error instanceof Error) { - if (error.message === 'User not found') { - toast.warn(tErrors('emailNotRegistered')); - } else if (error.message === 'Failed to fetch') { - toast.error(tErrors('talawaApiUnavailable')); - } else { - toast.error(tErrors('errorSendingMail')); - } + if ((error as Error).message === 'User not found') { + toast.warn(tErrors('emailNotRegistered')); + } else if ((error as Error).message === 'Failed to fetch') { + toast.error(tErrors('talawaApiUnavailable')); + } else { + toast.error(tErrors('errorSendingMail')); } } }; + /** + * Handles the form submission for resetting the password. + * + * @param e - The form submit event + */ const submitForgotPassword = async ( e: ChangeEvent, ): Promise => { @@ -89,7 +116,7 @@ const ForgotPassword = (): JSX.Element => { const { userOtp, newPassword, confirmNewPassword } = forgotPassFormData; if (newPassword !== confirmNewPassword) { - toast.error(t('passwordMismatches')); + toast.error(t('passwordMismatches') as string); return; } @@ -110,7 +137,7 @@ const ForgotPassword = (): JSX.Element => { /* istanbul ignore next */ if (data) { - toast.success(t('passwordChanges')); + toast.success(t('passwordChanges') as string); setShowEnterEmail(true); setForgotPassFormData({ userOtp: '', @@ -125,9 +152,11 @@ const ForgotPassword = (): JSX.Element => { } }; + // Show loader while performing OTP or password reset operations if (otpLoading || forgotPasswordLoading) { return ; } + return ( <>
    diff --git a/src/screens/FundCampaignPledge/FundCampaignPledge.module.css b/src/screens/FundCampaignPledge/FundCampaignPledge.module.css index c46adfada3..cdf4476267 100644 --- a/src/screens/FundCampaignPledge/FundCampaignPledge.module.css +++ b/src/screens/FundCampaignPledge/FundCampaignPledge.module.css @@ -56,6 +56,12 @@ flex-direction: column; } +.errorIcon { + transform: scale(1.5); + color: var(--bs-danger); + margin-bottom: 1rem; +} + .btnsContainer { display: flex; gap: 0.8rem; @@ -112,6 +118,12 @@ height: 26px; } +.imageContainer { + display: flex; + align-items: center; + justify-content: center; +} + .pledgerContainer { display: flex; align-items: center; @@ -121,6 +133,8 @@ padding: 0.25rem 0.45rem; border-radius: 0.35rem; background-color: #31bb6b33; + height: 2.2rem; + margin-top: 0.75rem; } .noOutline input { diff --git a/src/screens/FundCampaignPledge/FundCampaignPledge.test.tsx b/src/screens/FundCampaignPledge/FundCampaignPledge.test.tsx index 25e049e19d..3fb5993775 100644 --- a/src/screens/FundCampaignPledge/FundCampaignPledge.test.tsx +++ b/src/screens/FundCampaignPledge/FundCampaignPledge.test.tsx @@ -85,17 +85,6 @@ describe('Testing Campaign Pledge Screen', () => { jest.clearAllMocks(); }); - afterEach(() => { - cleanup(); - }); - - it('should render the Campaign Pledge screen', async () => { - renderFundCampaignPledge(link1); - await waitFor(() => { - expect(screen.getByTestId('searchPledger')).toBeInTheDocument(); - }); - }); - it('should redirect to fallback URL if URL params are undefined', async () => { render( @@ -122,6 +111,13 @@ describe('Testing Campaign Pledge Screen', () => { }); }); + it('should render the Campaign Pledge screen', async () => { + renderFundCampaignPledge(link1); + await waitFor(() => { + expect(screen.getByTestId('searchPledger')).toBeInTheDocument(); + }); + }); + it('open and closes Create Pledge modal', async () => { renderFundCampaignPledge(link1); @@ -213,6 +209,19 @@ describe('Testing Campaign Pledge Screen', () => { await waitFor(() => { expect(screen.getByTestId('searchPledger')).toBeInTheDocument(); }); + const searchPledger = await screen.findByTestId('searchPledger'); + expect(searchPledger).toBeInTheDocument(); + + fireEvent.click(screen.getByTestId('filter')); + await waitFor(() => { + expect(screen.getByTestId('amount_DESC')).toBeInTheDocument(); + }); + fireEvent.click(screen.getByTestId('amount_DESC')); + + await waitFor(() => { + expect(screen.getByText('John Doe')).toBeInTheDocument(); + expect(screen.queryByText('Jane Doe')).toBeInTheDocument(); + }); expect(screen.getByText('John Doe')).toBeInTheDocument(); expect(screen.getByText('John Doe2')).toBeInTheDocument(); diff --git a/src/screens/FundCampaignPledge/FundCampaignPledge.tsx b/src/screens/FundCampaignPledge/FundCampaignPledge.tsx index 9798336412..f7e339dc89 100644 --- a/src/screens/FundCampaignPledge/FundCampaignPledge.tsx +++ b/src/screens/FundCampaignPledge/FundCampaignPledge.tsx @@ -56,12 +56,12 @@ const dataGridStyle = { borderRadius: '0.5rem', }, }; - const fundCampaignPledge = (): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'pledges', }); const { t: tCommon } = useTranslation('common'); + const { t: tErrors } = useTranslation('errors'); const { fundCampaignId, orgId } = useParams(); if (!fundCampaignId || !orgId) { @@ -107,31 +107,33 @@ const fundCampaignPledge = (): JSX.Element => { refetch: refetchPledge, }: { data?: { - getFundraisingCampaignById: InterfaceQueryFundCampaignsPledges; + getFundraisingCampaigns: InterfaceQueryFundCampaignsPledges[]; }; loading: boolean; error?: Error | undefined; refetch: () => Promise< ApolloQueryResult<{ - getFundraisingCampaignById: InterfaceQueryFundCampaignsPledges; + getFundraisingCampaigns: InterfaceQueryFundCampaignsPledges[]; }> >; } = useQuery(FUND_CAMPAIGN_PLEDGE, { variables: { - id: fundCampaignId, - orderBy: sortBy, + where: { + id: fundCampaignId, + }, + pledgeOrderBy: sortBy, }, }); const endDate = dayjs( - pledgeData?.getFundraisingCampaignById?.endDate, + pledgeData?.getFundraisingCampaigns[0]?.endDate, 'YYYY-MM-DD', ).toDate(); - const { pledges, totalPledged } = useMemo(() => { + const { pledges, totalPledged, fundName } = useMemo(() => { let totalPledged = 0; const pledges = - pledgeData?.getFundraisingCampaignById.pledges.filter((pledge) => { + pledgeData?.getFundraisingCampaigns[0].pledges.filter((pledge) => { totalPledged += pledge.amount; const search = searchTerm.toLowerCase(); return pledge.users.some((user) => { @@ -139,17 +141,19 @@ const fundCampaignPledge = (): JSX.Element => { return fullName.toLowerCase().includes(search); }); }) ?? []; - return { pledges, totalPledged }; + const fundName = + pledgeData?.getFundraisingCampaigns[0].fundId.name ?? tCommon('Funds'); + return { pledges, totalPledged, fundName }; }, [pledgeData, searchTerm]); useEffect(() => { if (pledgeData) { setCampaignInfo({ - name: pledgeData.getFundraisingCampaignById.name, - goal: pledgeData.getFundraisingCampaignById.fundingGoal, - startDate: pledgeData.getFundraisingCampaignById.startDate, - endDate: pledgeData.getFundraisingCampaignById.endDate, - currency: pledgeData.getFundraisingCampaignById.currency, + name: pledgeData.getFundraisingCampaigns[0].name, + goal: pledgeData.getFundraisingCampaigns[0].fundingGoal, + startDate: pledgeData.getFundraisingCampaigns[0].startDate, + endDate: pledgeData.getFundraisingCampaigns[0].endDate, + currency: pledgeData.getFundraisingCampaigns[0].currency, }); } }, [pledgeData]); @@ -198,7 +202,7 @@ const fundCampaignPledge = (): JSX.Element => {
    - Error occured while loading Funds + {tErrors('errorLoading', { entity: 'Pledges' })}
    {pledgeError.message}
    @@ -235,6 +239,7 @@ const fundCampaignPledge = (): JSX.Element => {
    { () => history.go(-2) } > - {tCommon('Funds')} + {fundName} { () => history.back() } > - {t('campaigns')} + {campaignInfo?.name} {t('pledges')} @@ -574,7 +579,7 @@ const fundCampaignPledge = (): JSX.Element => { orgId={orgId} pledge={pledge} refetchPledge={refetchPledge} - endDate={pledgeData?.getFundraisingCampaignById.endDate as Date} + endDate={pledgeData?.getFundraisingCampaigns[0].endDate as Date} mode={pledgeModalMode} /> {/* Delete Pledge ModalState */} @@ -608,6 +613,7 @@ const fundCampaignPledge = (): JSX.Element => {
    void; } + +/** + * A modal dialog for confirming the deletion of a pledge. + * + * @param isOpen - Indicates whether the modal is open. + * @param hide - Function to close the modal. + * @param pledge - The pledge object to be deleted. + * @param refetchPledge - Function to refetch the pledges after deletion. + * + * @returns The rendered modal component. + * + * + * The `PledgeDeleteModal` component displays a confirmation dialog when a user attempts to delete a pledge. + * It allows the user to either confirm or cancel the deletion. + * On confirmation, the `deletePledge` mutation is called to remove the pledge from the database, + * and the `refetchPledge` function is invoked to update the list of pledges. + * A success or error toast notification is shown based on the result of the deletion operation. + * + * The modal includes: + * - A header with a title and a close button. + * - A body with a message asking for confirmation. + * - A footer with "Yes" and "No" buttons to confirm or cancel the deletion. + * + * The `deletePledge` mutation is used to perform the deletion operation. + */ + const PledgeDeleteModal: React.FC = ({ isOpen, hide, @@ -35,7 +61,7 @@ const PledgeDeleteModal: React.FC = ({ }); refetchPledge(); hide(); - toast.success(t('pledgeDeleted')); + toast.success(t('pledgeDeleted') as string); } catch (error: unknown) { toast.error((error as Error).message); } diff --git a/src/screens/FundCampaignPledge/PledgeModal.tsx b/src/screens/FundCampaignPledge/PledgeModal.tsx index 3e22d604a0..782a051277 100644 --- a/src/screens/FundCampaignPledge/PledgeModal.tsx +++ b/src/screens/FundCampaignPledge/PledgeModal.tsx @@ -35,6 +35,40 @@ export interface InterfacePledgeModal { endDate: Date; mode: 'create' | 'edit'; } + +/** + * A modal dialog for creating or editing a pledge. + * + * @param isOpen - Indicates whether the modal is open. + * @param hide - Function to close the modal. + * @param campaignId - The ID of the campaign associated with the pledge. + * @param orgId - The ID of the organization associated with the pledge. + * @param pledge - The pledge object to be edited, or `null` if creating a new pledge. + * @param refetchPledge - Function to refetch the list of pledges after creation or update. + * @param endDate - The end date of the campaign to ensure pledge dates are within this range. + * @param mode - The mode indicating whether the modal is for creating a new pledge or editing an existing one. + * + * @returns The rendered modal component. + * + * The `PledgeModal` component displays a form within a modal dialog for creating or editing a pledge. + * It includes fields for selecting users, entering an amount, choosing a currency, and setting start and end dates for the pledge. + * + * The modal includes: + * - A header with a title indicating the current mode (create or edit) and a close button. + * - A form with: + * - A multi-select dropdown for selecting users to participate in the pledge. + * - Date pickers for selecting the start and end dates of the pledge. + * - A dropdown for selecting the currency of the pledge amount. + * - An input field for entering the pledge amount. + * - A submit button to create or update the pledge. + * + * On form submission, the component either: + * - Calls `updatePledge` mutation to update an existing pledge, or + * - Calls `createPledge` mutation to create a new pledge. + * + * Success or error messages are displayed using toast notifications based on the result of the mutation. + */ + const PledgeModal: React.FC = ({ isOpen, hide, @@ -123,7 +157,7 @@ const PledgeModal: React.FC = ({ ...updatedFields, }, }); - toast.success(t('pledgeUpdated')); + toast.success(t('pledgeUpdated') as string); refetchPledge(); hide(); } catch (error: unknown) { @@ -149,7 +183,7 @@ const PledgeModal: React.FC = ({ }, }); - toast.success(t('pledgeCreated')); + toast.success(t('pledgeCreated') as string); refetchPledge(); setFormState({ pledgeUsers: [], diff --git a/src/screens/FundCampaignPledge/PledgesMocks.ts b/src/screens/FundCampaignPledge/PledgesMocks.ts index 71d74b1805..2a583fa887 100644 --- a/src/screens/FundCampaignPledge/PledgesMocks.ts +++ b/src/screens/FundCampaignPledge/PledgesMocks.ts @@ -6,162 +6,104 @@ import { import { MEMBERS_LIST } from 'GraphQl/Queries/Queries'; import { FUND_CAMPAIGN_PLEDGE } from 'GraphQl/Queries/fundQueries'; -export const MOCKS = [ - { - request: { - query: FUND_CAMPAIGN_PLEDGE, - variables: { - id: 'fundCampaignId', - orderBy: 'endDate_DESC', - }, +const memberList = { + request: { + query: MEMBERS_LIST, + variables: { + id: 'orgId', }, - result: { - data: { - getFundraisingCampaignById: { - name: 'Campaign Name', - fundingGoal: 1000, - currency: 'USD', - startDate: '2024-01-01', - endDate: '2024-08-08', - pledges: [ + }, + result: { + data: { + organizations: [ + { + _id: 'orgId', + members: [ { + createdAt: '2023-04-13T04:53:17.742Z', + email: 'testuser4@example.com', + firstName: 'John', + image: 'img-url', + lastName: 'Doe', + organizationsBlockedBy: [], + __typename: 'User', _id: '1', - amount: 100, - currency: 'USD', - startDate: '2024-01-01', - endDate: '2024-01-10', - users: [ - { - _id: '1', - firstName: 'John', - lastName: 'Doe', - image: 'img-url', - }, - { - _id: '2', - firstName: 'John', - lastName: 'Doe2', - image: 'img-url2', - }, - { - _id: '3', - firstName: 'John', - lastName: 'Doe3', - image: 'img-url3', - }, - { - _id: '4', - firstName: 'John', - lastName: 'Doe4', - image: 'img-url4', - }, - { - _id: '5', - firstName: 'John', - lastName: 'Doe5', - image: 'img-url5', - }, - { - _id: '6', - firstName: 'John', - lastName: 'Doe6', - image: 'img-url6', - }, - { - _id: '7', - firstName: 'John', - lastName: 'Doe7', - image: 'img-url7', - }, - { - _id: '8', - firstName: 'John', - lastName: 'Doe8', - image: 'img-url8', - }, - { - _id: '9', - firstName: 'John', - lastName: 'Doe9', - image: 'img-url9', - }, - { - _id: '10', - firstName: 'John', - lastName: 'Doe10', - image: null, - }, - ], }, { + createdAt: '2024-04-13T04:53:17.742Z', + email: 'testuser2@example.com', + firstName: 'Anna', + image: null, + lastName: 'Bradley', + organizationsBlockedBy: [], + __typename: 'User', _id: '2', - amount: 200, - currency: 'USD', - startDate: '2024-01-01', - endDate: '2024-01-09', - users: [ - { - _id: '2', - firstName: 'Jane', - lastName: 'Doe', - image: null, - }, - ], }, ], }, - }, + ], }, }, +}; + +export const MOCKS = [ + memberList, { request: { query: FUND_CAMPAIGN_PLEDGE, variables: { - id: 'fundCampaignId', - orderBy: 'endDate_ASC', + where: { + id: 'fundCampaignId', + }, + pledgeOrderBy: 'endDate_DESC', }, }, result: { data: { - getFundraisingCampaignById: { - name: 'Campaign Name', - fundingGoal: 1000, - currency: 'USD', - startDate: '2024-01-01', - endDate: '2024-08-08', - pledges: [ - { - _id: '2', - amount: 200, - currency: 'USD', - startDate: '2024-01-01', - endDate: '2024-01-09', - users: [ - { - _id: '2', - firstName: 'Jane', - lastName: 'Doe', - image: null, - }, - ], - }, - { - _id: '1', - amount: 100, - currency: 'USD', - startDate: '2024-01-01', - endDate: '2024-01-10', - users: [ - { - _id: '1', - firstName: 'John', - lastName: 'Doe', - image: null, - }, - ], + getFundraisingCampaigns: [ + { + fundId: { + name: 'Fund 1', }, - ], - }, + name: 'Campaign Name', + fundingGoal: 1000, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2034-08-08', + pledges: [ + { + _id: '1', + amount: 100, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-01-10', + users: [ + { + _id: '1', + firstName: 'John', + lastName: 'Doe', + image: 'img-url', + }, + ], + }, + { + _id: '2', + amount: 200, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-01-09', + users: [ + { + _id: '2', + firstName: 'Jane', + lastName: 'Doe', + image: null, + }, + ], + }, + ], + }, + ], }, }, }, @@ -169,51 +111,58 @@ export const MOCKS = [ request: { query: FUND_CAMPAIGN_PLEDGE, variables: { - id: 'fundCampaignId', - orderBy: 'amount_DESC', + where: { + id: 'fundCampaignId', + }, + pledgeOrderBy: 'endDate_ASC', }, }, result: { data: { - getFundraisingCampaignById: { - name: 'Campaign Name', - fundingGoal: 1000, - currency: 'USD', - startDate: '2024-01-01', - endDate: '2024-08-08', - pledges: [ - { - _id: '2', - amount: 200, - currency: 'USD', - startDate: '2024-01-01', - endDate: '2024-01-09', - users: [ - { - _id: '2', - firstName: 'Jane', - lastName: 'Doe', - image: null, - }, - ], - }, - { - _id: '1', - amount: 100, - currency: 'USD', - startDate: '2024-01-01', - endDate: '2024-01-10', - users: [ - { - _id: '1', - firstName: 'John', - lastName: 'Doe', - image: null, - }, - ], + getFundraisingCampaigns: [ + { + fundId: { + name: 'Fund 1', }, - ], - }, + name: 'Campaign Name', + fundingGoal: 1000, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-08-08', + pledges: [ + { + _id: '2', + amount: 200, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-01-09', + users: [ + { + _id: '2', + firstName: 'Jane', + lastName: 'Doe', + image: null, + }, + ], + }, + { + _id: '1', + amount: 100, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-01-10', + users: [ + { + _id: '1', + firstName: 'John', + lastName: 'Doe', + image: null, + }, + ], + }, + ], + }, + ], }, }, }, @@ -221,250 +170,209 @@ export const MOCKS = [ request: { query: FUND_CAMPAIGN_PLEDGE, variables: { - id: 'fundCampaignId', - orderBy: 'amount_ASC', + where: { + id: 'fundCampaignId', + }, + pledgeOrderBy: 'amount_DESC', }, }, result: { data: { - getFundraisingCampaignById: { - name: 'Campaign Name', - fundingGoal: 1000, - currency: 'USD', - startDate: '2024-01-01', - endDate: '2024-08-08', - pledges: [ - { - _id: '1', - amount: 100, - currency: 'USD', - startDate: '2024-01-01', - endDate: '2024-01-10', - users: [ - { - _id: '1', - firstName: 'John', - lastName: 'Doe', - image: null, - }, - ], - }, - { - _id: '2', - amount: 200, - currency: 'USD', - startDate: '2024-01-01', - endDate: '2024-01-09', - users: [ - { - _id: '2', - firstName: 'Jane', - lastName: 'Doe', - image: null, - }, - ], + getFundraisingCampaigns: [ + { + fundId: { + name: 'Fund 1', }, - ], - }, + name: 'Campaign Name', + fundingGoal: 1000, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-08-08', + pledges: [ + { + _id: '2', + amount: 200, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-01-09', + users: [ + { + _id: '2', + firstName: 'Jane', + lastName: 'Doe', + image: null, + }, + { + _id: '2', + firstName: 'John', + lastName: 'Doe2', + image: 'img-url2', + }, + { + _id: '3', + firstName: 'John', + lastName: 'Doe3', + image: 'img-url3', + }, + { + _id: '4', + firstName: 'John', + lastName: 'Doe4', + image: 'img-url4', + }, + { + _id: '5', + firstName: 'John', + lastName: 'Doe5', + image: 'img-url5', + }, + { + _id: '6', + firstName: 'John', + lastName: 'Doe6', + image: 'img-url6', + }, + { + _id: '7', + firstName: 'John', + lastName: 'Doe7', + image: 'img-url7', + }, + { + _id: '8', + firstName: 'John', + lastName: 'Doe8', + image: 'img-url8', + }, + { + _id: '9', + firstName: 'John', + lastName: 'Doe9', + image: 'img-url9', + }, + { + _id: '10', + firstName: 'John', + lastName: 'Doe10', + image: null, + }, + ], + }, + { + _id: '1', + amount: 100, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-01-10', + users: [ + { + _id: '1', + firstName: 'John', + lastName: 'Doe', + image: null, + }, + ], + }, + ], + }, + ], }, }, }, { request: { - query: DELETE_PLEDGE, + query: FUND_CAMPAIGN_PLEDGE, variables: { - id: '1', + where: { + id: 'fundCampaignId', + }, + pledgeOrderBy: 'amount_ASC', }, }, result: { data: { - removeFundraisingCampaignPledge: { - _id: '1', - }, - }, - }, - }, -]; - -export const MOCKS_FUND_CAMPAIGN_PLEDGE_ERROR = [ - { - request: { - query: FUND_CAMPAIGN_PLEDGE, - variables: { - id: 'fundCampaignId', - orderBy: 'endDate_DESC', + getFundraisingCampaigns: [ + { + fundId: { + name: 'Fund 1', + }, + name: 'Campaign Name', + fundingGoal: 1000, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-08-08', + pledges: [ + { + _id: '1', + amount: 100, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-01-10', + users: [ + { + _id: '1', + firstName: 'John', + lastName: 'Doe', + image: null, + }, + ], + }, + { + _id: '2', + amount: 200, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-01-09', + users: [ + { + _id: '2', + firstName: 'Jane', + lastName: 'Doe', + image: null, + }, + ], + }, + ], + }, + ], }, }, - error: new Error('Error fetching pledges'), }, -]; - -export const MOCKS_CREATE_PLEDGE_ERROR = [ { request: { - query: FUND_CAMPAIGN_PLEDGE, + query: DELETE_PLEDGE, variables: { - id: undefined, + id: '1', }, }, result: { data: { - getFundraisingCampaignById: { - startDate: '2024-01-01', - endDate: '2024-01-01', - pledges: [ - { - _id: '1', - amount: 100, - currency: 'USD', - startDate: '2024-01-01', - endDate: '2024-01-01', - users: [ - { - _id: '1', - firstName: 'John', - }, - ], - }, - { - _id: '2', - amount: 200, - currency: 'USD', - startDate: '2024-03-03', - endDate: '2024-04-03', - users: [ - { - _id: '2', - firstName: 'Jane', - }, - ], - }, - ], + removeFundraisingCampaignPledge: { + _id: '1', }, }, }, }, - { - request: { - query: CREATE_PlEDGE, - variables: { - campaignId: 'campaignId', - amount: 200, - currency: 'USD', - startDate: '2024-01-02', - endDate: '2024-01-02', - userIds: ['1'], - }, - }, - error: new Error('Error creating pledge'), - }, ]; -export const MOCKS_UPDATE_PLEDGE_ERROR = [ +export const MOCKS_FUND_CAMPAIGN_PLEDGE_ERROR = [ + memberList, { request: { query: FUND_CAMPAIGN_PLEDGE, variables: { - id: undefined, - }, - }, - result: { - data: { - getFundraisingCampaignById: { - startDate: '2024-01-01', - endDate: '2024-01-01', - pledges: [ - { - _id: '1', - amount: 100, - currency: 'USD', - startDate: '2024-01-01', - endDate: '2024-01-01', - users: [ - { - _id: '1', - firstName: 'John', - }, - ], - }, - { - _id: '2', - amount: 200, - currency: 'USD', - startDate: '2024-03-03', - endDate: '2024-04-03', - users: [ - { - _id: '2', - firstName: 'Jane', - }, - ], - }, - ], + where: { + id: 'fundCampaignId', }, + pledgeOrderBy: 'endDate_DESC', }, }, - }, - { - request: { - query: UPDATE_PLEDGE, - variables: { - id: '1', - amount: 200, - currency: 'USD', - startDate: '2024-03-10', - endDate: '2024-03-10', - }, - }, - error: new Error('Error updating pledge'), + error: new Error('Error fetching pledges'), }, ]; export const MOCKS_DELETE_PLEDGE_ERROR = [ - { - request: { - query: FUND_CAMPAIGN_PLEDGE, - variables: { - id: undefined, - }, - }, - result: { - data: { - getFundraisingCampaignById: { - startDate: '2024-01-01', - endDate: '2024-01-01', - pledges: [ - { - _id: '1', - amount: 100, - currency: 'USD', - startDate: '2024-01-01', - endDate: '2024-01-01', - users: [ - { - _id: '1', - firstName: 'John', - }, - ], - }, - { - _id: '2', - amount: 200, - currency: 'USD', - startDate: '2024-03-03', - endDate: '2024-04-03', - users: [ - { - _id: '2', - firstName: 'Jane', - }, - ], - }, - ], - }, - }, - }, - }, + memberList, { request: { query: DELETE_PLEDGE, @@ -477,69 +385,39 @@ export const MOCKS_DELETE_PLEDGE_ERROR = [ ]; export const EMPTY_MOCKS = [ + memberList, { request: { query: FUND_CAMPAIGN_PLEDGE, variables: { - id: 'fundCampaignId', - orderBy: 'endDate_DESC', - }, - }, - result: { - data: { - getFundraisingCampaignById: { - name: 'Campaign Name', - fundingGoal: 1000, - currency: 'USD', - startDate: '2024-01-01', - endDate: '2024-01-01', - pledges: [], + where: { + id: 'fundCampaignId', }, - }, - }, - }, -]; - -export const PLEDGE_MODAL_MOCKS = [ - { - request: { - query: MEMBERS_LIST, - variables: { - id: 'orgId', + pledgeOrderBy: 'endDate_DESC', }, }, result: { data: { - organizations: [ + getFundraisingCampaigns: [ { - _id: 'orgId', - members: [ - { - createdAt: '2023-04-13T04:53:17.742Z', - email: 'testuser4@example.com', - firstName: 'John', - image: 'img-url', - lastName: 'Doe', - organizationsBlockedBy: [], - __typename: 'User', - _id: '1', - }, - { - createdAt: '2024-04-13T04:53:17.742Z', - email: 'testuser2@example.com', - firstName: 'Anna', - image: null, - lastName: 'Bradley', - organizationsBlockedBy: [], - __typename: 'User', - _id: '2', - }, - ], + fundId: { + name: 'Fund 1', + }, + name: 'Campaign Name', + fundingGoal: 1000, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-01-01', + pledges: [], }, ], }, }, }, +]; + +export const PLEDGE_MODAL_MOCKS = [ + memberList, { request: { query: UPDATE_PLEDGE, diff --git a/src/screens/LoginPage/LoginPage.test.tsx b/src/screens/LoginPage/LoginPage.test.tsx index a61f8adb2e..3733a454dd 100644 --- a/src/screens/LoginPage/LoginPage.test.tsx +++ b/src/screens/LoginPage/LoginPage.test.tsx @@ -1,6 +1,6 @@ -import React from 'react'; +import React, { act } from 'react'; import { MockedProvider } from '@apollo/react-testing'; -import { act, render, screen, fireEvent, within } from '@testing-library/react'; +import { render, screen, fireEvent, within } from '@testing-library/react'; import { Provider } from 'react-redux'; import { BrowserRouter } from 'react-router-dom'; import userEvent from '@testing-library/user-event'; @@ -114,7 +114,7 @@ const MOCKS2 = [ linkedIn: 'http://url.com', reddit: 'http://url.com', slack: 'http://url.com', - twitter: null, + X: null, __typename: 'SocialMediaUrls', }, }, diff --git a/src/screens/LoginPage/LoginPage.tsx b/src/screens/LoginPage/LoginPage.tsx index 24b247e427..7d007a7112 100644 --- a/src/screens/LoginPage/LoginPage.tsx +++ b/src/screens/LoginPage/LoginPage.tsx @@ -23,10 +23,9 @@ import { SIGNUP_MUTATION, } from 'GraphQl/Mutations/mutations'; import { GET_COMMUNITY_DATA, ORGANIZATION_LIST } from 'GraphQl/Queries/Queries'; -import { ReactComponent as PalisadoesLogo } from 'assets/svgs/palisadoes.svg'; -import { ReactComponent as TalawaLogo } from 'assets/svgs/talawa.svg'; +import PalisadoesLogo from 'assets/svgs/palisadoes.svg?react'; +import TalawaLogo from 'assets/svgs/talawa.svg?react'; import ChangeLanguageDropDown from 'components/ChangeLanguageDropdown/ChangeLanguageDropDown'; -import Loader from 'components/Loader/Loader'; import LoginPortalToggle from 'components/LoginPortalToggle/LoginPortalToggle'; import { errorHandler } from 'utils/errorHandler'; import useLocalStorage from 'utils/useLocalstorage'; @@ -36,6 +35,12 @@ import type { InterfaceQueryOrganizationListObject } from 'utils/interfaces'; import { Autocomplete, TextField } from '@mui/material'; import i18n from 'utils/i18n'; +/** + * LoginPage component is used to render the login page of the application where user can login or register + * to the application using email and password. The component also provides the functionality to switch between login and + * register form. + * + */ const loginPage = (): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'loginPage' }); const { t: tCommon } = useTranslation('common'); @@ -57,7 +62,6 @@ const loginPage = (): JSX.Element => { const [recaptchaToken, setRecaptchaToken] = useState(null); const [showTab, setShowTab] = useState<'LOGIN' | 'REGISTER'>('LOGIN'); const [role, setRole] = useState<'admin' | 'user'>('admin'); - const [componentLoader, setComponentLoader] = useState(true); const [isInputFocused, setIsInputFocused] = useState(false); const [signformState, setSignFormState] = useState({ signfirstName: '', @@ -107,22 +111,20 @@ const loginPage = (): JSX.Element => { if (isLoggedIn == 'TRUE') { navigate(getItem('userId') !== null ? '/user/organizations' : '/orglist'); } - setComponentLoader(false); }, []); const togglePassword = (): void => setShowPassword(!showPassword); const toggleConfirmPassword = (): void => setShowConfirmPassword(!showConfirmPassword); - const { data, loading, refetch } = useQuery(GET_COMMUNITY_DATA); + const { data, refetch } = useQuery(GET_COMMUNITY_DATA); useEffect(() => { // refetching the data if the pre-login data updates refetch(); }, [data]); const [login, { loading: loginLoading }] = useMutation(LOGIN_MUTATION); const [signup, { loading: signinLoading }] = useMutation(SIGNUP_MUTATION); - const [recaptcha, { loading: recaptchaLoading }] = - useMutation(RECAPTCHA_MUTATION); + const [recaptcha] = useMutation(RECAPTCHA_MUTATION); const { data: orgData } = useQuery(ORGANIZATION_LIST); useEffect(() => { @@ -173,7 +175,7 @@ const loginPage = (): JSX.Element => { return data.recaptcha; } catch (error) { /* istanbul ignore next */ - toast.error(t('captchaError')); + toast.error(t('captchaError') as string); } }; @@ -196,7 +198,7 @@ const loginPage = (): JSX.Element => { const isVerified = await verifyRecaptcha(recaptchaToken); /* istanbul ignore next */ if (!isVerified) { - toast.error(t('Please_check_the_captcha')); + toast.error(t('Please_check_the_captcha') as string); return; } const isValidatedString = (value: string): boolean => @@ -237,7 +239,9 @@ const loginPage = (): JSX.Element => { /* istanbul ignore next */ if (signUpData) { toast.success( - t(role === 'admin' ? 'successfullyRegistered' : 'afterRegister'), + t( + role === 'admin' ? 'successfullyRegistered' : 'afterRegister', + ) as string, ); setShowTab('LOGIN'); setSignFormState({ @@ -254,20 +258,20 @@ const loginPage = (): JSX.Element => { errorHandler(t, error); } } else { - toast.warn(t('passwordMismatches')); + toast.warn(t('passwordMismatches') as string); } } else { if (!isValidatedString(signfirstName)) { - toast.warn(t('firstName_invalid')); + toast.warn(t('firstName_invalid') as string); } if (!isValidatedString(signlastName)) { - toast.warn(t('lastName_invalid')); + toast.warn(t('lastName_invalid') as string); } if (!validatePassword(signPassword)) { - toast.warn(t('password_invalid')); + toast.warn(t('password_invalid') as string); } if (signEmail.length < 8) { - toast.warn(t('email_invalid')); + toast.warn(t('email_invalid') as string); } } }; @@ -277,7 +281,7 @@ const loginPage = (): JSX.Element => { const isVerified = await verifyRecaptcha(recaptchaToken); /* istanbul ignore next */ if (!isVerified) { - toast.error(t('Please_check_the_captcha')); + toast.error(t('Please_check_the_captcha') as string); return; } @@ -298,7 +302,7 @@ const loginPage = (): JSX.Element => { appUserProfile.isSuperAdmin || appUserProfile.adminFor.length !== 0; if (role === 'admin' && !isAdmin) { - toast.warn(tErrors('notAuthorised')); + toast.warn(tErrors('notAuthorised') as string); return; } const loggedInUserId = user._id; @@ -322,7 +326,7 @@ const loginPage = (): JSX.Element => { navigate(role === 'admin' ? '/orglist' : '/user/organizations'); } else { - toast.warn(tErrors('notFound')); + toast.warn(tErrors('notFound') as string); } } catch (error) { /* istanbul ignore next */ @@ -330,15 +334,6 @@ const loginPage = (): JSX.Element => { } }; - if ( - componentLoader || - loginLoading || - signinLoading || - recaptchaLoading || - loading - ) { - return ; - } const socialIconsList = socialMediaLinks.map(({ href, logo, tag }, index) => data?.getCommunityData ? ( data.getCommunityData?.socialMediaUrls?.[tag] && ( @@ -429,6 +424,7 @@ const loginPage = (): JSX.Element => {
    { password: e.target.value, }); }} + disabled={loginLoading} autoComplete="current-password" /> diff --git a/src/screens/ManageTag/ManageTag.module.css b/src/screens/ManageTag/ManageTag.module.css new file mode 100644 index 0000000000..db1886099a --- /dev/null +++ b/src/screens/ManageTag/ManageTag.module.css @@ -0,0 +1,119 @@ +.btnsContainer { + display: flex; + margin: 2rem 0; +} + +.btnsContainer .btnsBlock { + display: flex; + width: max-content; +} + +.btnsContainer .btnsBlock button { + margin-left: 1rem; + display: flex; + justify-content: center; + align-items: center; +} + +.btnsContainer .input { + flex: 1; + position: relative; + max-width: 60%; + justify-content: space-between; +} + +.btnsContainer input { + outline: 1px solid var(--bs-gray-400); +} + +.btnsContainer .input button { + width: 52px; +} + +@media (max-width: 1020px) { + .btnsContainer { + flex-direction: column; + margin: 1.5rem 0; + } + + .btnsContainer .btnsBlock { + margin: 1.5rem 0 0 0; + justify-content: space-between; + } + + .btnsContainer .btnsBlock button { + margin: 0; + } + + .btnsContainer .btnsBlock div button { + margin-right: 1.5rem; + } +} + +/* For mobile devices */ + +@media (max-width: 520px) { + .btnsContainer { + margin-bottom: 0; + } + + .btnsContainer .btnsBlock { + display: block; + margin-top: 1rem; + margin-right: 0; + } + + .btnsContainer .btnsBlock div { + flex: 1; + } + + .btnsContainer .btnsBlock div[title='Sort organizations'] { + margin-right: 0.5rem; + } + + .btnsContainer .btnsBlock button { + margin-bottom: 1rem; + margin-right: 0; + width: 100%; + } +} + +.errorContainer { + min-height: 100vh; +} + +.errorMessage { + margin-top: 25%; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; +} + +.errorIcon { + transform: scale(1.5); + color: var(--bs-danger); + margin-bottom: 1rem; +} + +.tableHeader { + background-color: var(--bs-primary); + color: var(--bs-white); + font-size: 1rem; +} + +.rowBackground { + background-color: var(--bs-white); + max-height: 120px; +} + +.tagsBreadCrumbs { + color: var(--bs-gray); + cursor: pointer; +} + +.tagsBreadCrumbs:hover { + color: var(--bs-blue); + font-weight: 600; + text-decoration: underline; +} diff --git a/src/screens/ManageTag/ManageTag.test.tsx b/src/screens/ManageTag/ManageTag.test.tsx new file mode 100644 index 0000000000..38ebba7402 --- /dev/null +++ b/src/screens/ManageTag/ManageTag.test.tsx @@ -0,0 +1,296 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import type { RenderResult } from '@testing-library/react'; +import { + act, + cleanup, + render, + screen, + waitFor, + waitForElementToBeRemoved, +} from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import 'jest-location-mock'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; +import { toast } from 'react-toastify'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18n from 'utils/i18nForTest'; +import ManageTag from './ManageTag'; +import { + MOCKS, + MOCKS_ERROR_ASSIGNED_MEMBERS, + MOCKS_ERROR_TAG_ANCESTORS, +} from './ManageTagMocks'; +import { InMemoryCache, type ApolloLink } from '@apollo/client'; + +const translations = { + ...JSON.parse( + JSON.stringify(i18n.getDataByLanguage('en')?.translation.manageTag ?? {}), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const link = new StaticMockLink(MOCKS, true); +const link2 = new StaticMockLink(MOCKS_ERROR_ASSIGNED_MEMBERS, true); +const link3 = new StaticMockLink(MOCKS_ERROR_TAG_ANCESTORS, true); + +async function wait(ms = 500): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +const cache = new InMemoryCache({ + typePolicies: { + Query: { + fields: { + getUserTag: { + keyArgs: false, + merge(existing = {}, incoming) { + return incoming; + }, + }, + }, + }, + }, +}); + +const renderManageTag = (link: ApolloLink): RenderResult => { + return render( + + + + + +
    } + /> + } + /> +
    } + /> +
    } + /> + + + + + , + ); +}; + +describe('Organisation Tags Page', () => { + beforeEach(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId' }), + })); + cache.reset(); + }); + + afterEach(() => { + jest.clearAllMocks(); + cleanup(); + }); + + test('Component loads correctly', async () => { + const { getByText } = renderManageTag(link); + + await wait(); + + await waitFor(() => { + expect(getByText(translations.addPeopleToTag)).toBeInTheDocument(); + }); + }); + + test('renders error component on unsuccessful userTag assigned members query', async () => { + const { queryByText } = renderManageTag(link2); + + await wait(); + + await waitFor(() => { + expect(queryByText(translations.addPeopleToTag)).not.toBeInTheDocument(); + }); + }); + + test('renders error component on unsuccessful userTag ancestors query', async () => { + const { queryByText } = renderManageTag(link3); + + await wait(); + + await waitFor(() => { + expect(queryByText(translations.addPeopleToTag)).not.toBeInTheDocument(); + }); + }); + + test('opens and closes the add people to tag modal', async () => { + renderManageTag(link); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('addPeopleToTagBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('addPeopleToTagBtn')); + + await waitFor(() => { + return expect( + screen.findByTestId('closeAddPeopleToTagModal'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('closeAddPeopleToTagModal')); + + await waitForElementToBeRemoved(() => + screen.queryByTestId('closeAddPeopleToTagModal'), + ); + }); + + test('opens and closes the unassign tag modal', async () => { + renderManageTag(link); + + await wait(); + + await waitFor(() => { + expect(screen.getAllByTestId('unassignTagBtn')[0]).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('unassignTagBtn')[0]); + + await waitFor(() => { + return expect( + screen.findByTestId('unassignTagModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('unassignTagModalCloseBtn')); + + await waitForElementToBeRemoved(() => + screen.queryByTestId('unassignTagModalCloseBtn'), + ); + }); + + test("navigates to the member's profile after clicking the view option", async () => { + renderManageTag(link); + + await wait(); + + await waitFor(() => { + expect(screen.getAllByTestId('viewProfileBtn')[0]).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('viewProfileBtn')[0]); + + await waitFor(() => { + expect(screen.getByTestId('memberProfileScreen')).toBeInTheDocument(); + }); + }); + + test('navigates to the subTags screen after clicking the subTags option', async () => { + renderManageTag(link); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('subTagsBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('subTagsBtn')); + + await waitFor(() => { + expect(screen.getByTestId('subTagsScreen')).toBeInTheDocument(); + }); + }); + + test('navigates to the manageTag screen after clicking a tag in the breadcrumbs', async () => { + renderManageTag(link); + + await wait(); + + await waitFor(() => { + expect( + screen.getAllByTestId('redirectToManageTag')[0], + ).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('redirectToManageTag')[0]); + + await waitFor(() => { + expect(screen.getByTestId('addPeopleToTagBtn')).toBeInTheDocument(); + }); + }); + + test('navigates to organization tags screen screen after clicking tha all tags option in the breadcrumbs', async () => { + renderManageTag(link); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('allTagsBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('allTagsBtn')); + + await waitFor(() => { + expect(screen.getByTestId('organizationTagsScreen')).toBeInTheDocument(); + }); + }); + + test('paginates between different pages', async () => { + renderManageTag(link); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('nextPagBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('nextPagBtn')); + + await waitFor(() => { + expect(screen.getAllByTestId('memberName')[0]).toHaveTextContent( + 'member 6', + ); + }); + + await waitFor(() => { + expect(screen.getByTestId('previousPageBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('previousPageBtn')); + + await waitFor(() => { + expect(screen.getAllByTestId('memberName')[0]).toHaveTextContent( + 'member 1', + ); + }); + }); + + test('unassigns a tag from a member', async () => { + renderManageTag(link); + + await wait(); + + await waitFor(() => { + expect(screen.getAllByTestId('unassignTagBtn')[0]).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('unassignTagBtn')[0]); + + userEvent.click(screen.getByTestId('unassignTagModalSubmitBtn')); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.successfullyUnassigned); + }); + }); +}); diff --git a/src/screens/ManageTag/ManageTag.tsx b/src/screens/ManageTag/ManageTag.tsx new file mode 100644 index 0000000000..86a44fb169 --- /dev/null +++ b/src/screens/ManageTag/ManageTag.tsx @@ -0,0 +1,511 @@ +import React, { useState } from 'react'; +import { useMutation, useQuery, type ApolloError } from '@apollo/client'; +import { Search, WarningAmberRounded } from '@mui/icons-material'; +import SortIcon from '@mui/icons-material/Sort'; +import Loader from 'components/Loader/Loader'; +import IconComponent from 'components/IconComponent/IconComponent'; +import { useNavigate, useParams, Link } from 'react-router-dom'; +import { Col, Form } from 'react-bootstrap'; +import Button from 'react-bootstrap/Button'; +import Dropdown from 'react-bootstrap/Dropdown'; +import Modal from 'react-bootstrap/Modal'; +import Row from 'react-bootstrap/Row'; +import { useTranslation } from 'react-i18next'; +import { toast } from 'react-toastify'; +import type { InterfaceQueryUserTagsAssignedMembers } from 'utils/interfaces'; +import styles from './ManageTag.module.css'; +import { DataGrid } from '@mui/x-data-grid'; +import { dataGridStyle } from 'utils/organizationTagsUtils'; +import type { GridCellParams, GridColDef } from '@mui/x-data-grid'; +import { Stack } from '@mui/material'; +import { UNASSIGN_USER_TAG } from 'GraphQl/Mutations/TagMutations'; +import { + USER_TAG_ANCESTORS, + USER_TAGS_ASSIGNED_MEMBERS, +} from 'GraphQl/Queries/userTagQueries'; + +/** + * Component that renders the Manage Tag screen when the app navigates to '/orgtags/:orgId/managetag/:tagId'. + * + * This component does not accept any props and is responsible for displaying + * the content associated with the corresponding route. + */ + +function ManageTag(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'manageTag', + }); + const { t: tCommon } = useTranslation('common'); + + const [addPeopleToTagModalIsOpen, setAddPeopleToTagModalIsOpen] = + useState(false); + const [unassignTagModalIsOpen, setUnassignTagModalIsOpen] = useState(false); + + const { orgId, tagId: currentTagId } = useParams(); + const navigate = useNavigate(); + const [after, setAfter] = useState(null); + const [before, setBefore] = useState(null); + const [first, setFirst] = useState(5); + const [last, setLast] = useState(null); + + const [unassignUserId, setUnassignUserId] = useState(null); + + const showAddPeopleToTagModal = (): void => { + setAddPeopleToTagModalIsOpen(true); + }; + + const hideAddPeopleToTagModal = (): void => { + setAddPeopleToTagModalIsOpen(false); + }; + + const { + data: userTagAssignedMembersData, + loading: userTagAssignedMembersLoading, + error: userTagAssignedMembersError, + refetch: userTagAssignedMembersRefetch, + }: { + data?: { + getUserTag: InterfaceQueryUserTagsAssignedMembers; + }; + loading: boolean; + error?: ApolloError; + refetch: () => void; + } = useQuery(USER_TAGS_ASSIGNED_MEMBERS, { + variables: { + id: currentTagId, + after: after, + before: before, + first: first, + last: last, + }, + }); + + const { + data: orgUserTagAncestorsData, + loading: orgUserTagsAncestorsLoading, + error: orgUserTagsAncestorsError, + }: { + data?: { + getUserTagAncestors: { + _id: string; + name: string; + }[]; + }; + loading: boolean; + error?: ApolloError; + refetch: () => void; + } = useQuery(USER_TAG_ANCESTORS, { + variables: { + id: currentTagId, + }, + }); + + const [unassignUserTag] = useMutation(UNASSIGN_USER_TAG); + + const handleUnassignTag = async (): Promise => { + try { + await unassignUserTag({ + variables: { + tagId: currentTagId, + userId: unassignUserId, + }, + }); + + userTagAssignedMembersRefetch(); + toggleUnassignTagModal(); + toast.success(t('successfullyUnassigned') as string); + } catch (error: unknown) { + /* istanbul ignore next */ + if (error instanceof Error) { + toast.error(error.message); + } + } + }; + + if (userTagAssignedMembersLoading || orgUserTagsAncestorsLoading) { + return ; + } + + if (userTagAssignedMembersError || orgUserTagsAncestorsError) { + return ( +
    +
    + +
    + Error occured while loading{' '} + {userTagAssignedMembersError ? 'assigned users' : 'tag ancestors'} +
    + {userTagAssignedMembersError + ? userTagAssignedMembersError.message + : orgUserTagsAncestorsError?.message} +
    +
    +
    + ); + } + + const userTagAssignedMembers = + userTagAssignedMembersData?.getUserTag.usersAssignedTo.edges.map( + (edge) => edge.node, + ); + + const orgUserTagAncestors = orgUserTagAncestorsData?.getUserTagAncestors; + + const redirectToSubTags = (tagId: string): void => { + navigate(`/orgtags/${orgId}/subTags/${tagId}`); + }; + + const redirectToManageTag = (tagId: string): void => { + navigate(`/orgtags/${orgId}/managetag/${tagId}`); + }; + + const handleNextPage = (): void => { + setAfter( + userTagAssignedMembersData?.getUserTag.usersAssignedTo.pageInfo.endCursor, + ); + setBefore(null); + setFirst(5); + setLast(null); + }; + const handlePreviousPage = (): void => { + setBefore( + userTagAssignedMembersData?.getUserTag.usersAssignedTo.pageInfo + .startCursor, + ); + setAfter(null); + setFirst(null); + setLast(5); + }; + + const toggleUnassignTagModal = (): void => { + if (unassignTagModalIsOpen) { + setUnassignUserId(null); + } + setUnassignTagModalIsOpen(!unassignTagModalIsOpen); + }; + + const columns: GridColDef[] = [ + { + field: 'id', + headerName: '#', + minWidth: 100, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return
    {params.row.id}
    ; + }, + }, + { + field: 'userName', + headerName: 'User Name', + flex: 2, + minWidth: 100, + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( +
    + {params.row.firstName + ' ' + params.row.lastName} +
    + ); + }, + }, + { + field: 'actions', + headerName: 'Actions', + flex: 1, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( +
    + +
    {t('viewProfile')}
    + + + +
    + ); + }, + }, + ]; + + return ( + <> + +
    +
    +
    + + +
    + +
    + + + + + +
    +
    + + + +
    +
    + +
    + +
    navigate(`/orgtags/${orgId}`)} + className={`fs-6 ms-3 my-1 ${styles.tagsBreadCrumbs}`} + data-testid="allTagsBtn" + > + {'Tags'} + +
    + + {orgUserTagAncestors?.map((tag, index) => ( +
    redirectToManageTag(tag._id as string)} + data-testid="redirectToManageTag" + > + {tag.name} + + {orgUserTagAncestors.length - 1 !== index && ( + /* istanbul ignore next */ + + )} +
    + ))} +
    + row._id} + slots={{ + noRowsOverlay: /* istanbul ignore next */ () => ( + + {t('noAssignedMembersFound')} + + ), + }} + sx={dataGridStyle} + getRowClassName={() => `${styles.rowBackground}`} + autoHeight + rowHeight={65} + rows={userTagAssignedMembers?.map((assignedMembers, index) => ({ + id: index + 1, + ...assignedMembers, + }))} + columns={columns} + isRowSelectable={() => false} + /> + +
    +
    + +
    +
    + +
    +
    + + + +
    +
    {'Actions'}
    +
    +
    +
    + {'Email Users'} +
    +
    +
    +
    +
    + {'Add to tags'} +
    +
    + {'Remove from tags'} +
    +
    + +
    +
    +
    + + {/* Add People To Tag Modal */} + + + {t('addPeople')} + + + + + + + + + + + + {/* Unassign Tag Modal */} + + + + {t('unassignUserTag')} + + + {t('unassignUserTagMessage')} + + + + + + + ); +} + +export default ManageTag; diff --git a/src/screens/ManageTag/ManageTagMocks.ts b/src/screens/ManageTag/ManageTagMocks.ts new file mode 100644 index 0000000000..c42c4a9e5f --- /dev/null +++ b/src/screens/ManageTag/ManageTagMocks.ts @@ -0,0 +1,290 @@ +import { UNASSIGN_USER_TAG } from 'GraphQl/Mutations/TagMutations'; +import { + USER_TAG_ANCESTORS, + USER_TAGS_ASSIGNED_MEMBERS, +} from 'GraphQl/Queries/userTagQueries'; + +export const MOCKS = [ + { + request: { + query: USER_TAGS_ASSIGNED_MEMBERS, + variables: { + id: '1', + after: null, + before: null, + first: 5, + last: null, + }, + }, + result: { + data: { + getUserTag: { + name: 'tag1', + usersAssignedTo: { + edges: [ + { + node: { + _id: '1', + firstName: 'member', + lastName: '1', + }, + cursor: '1', + }, + { + node: { + _id: '2', + firstName: 'member', + lastName: '2', + }, + cursor: '2', + }, + { + node: { + _id: '3', + firstName: 'member', + lastName: '3', + }, + cursor: '3', + }, + { + node: { + _id: '4', + firstName: 'member', + lastName: '4', + }, + cursor: '4', + }, + { + node: { + _id: '5', + firstName: 'member', + lastName: '5', + }, + cursor: '5', + }, + ], + pageInfo: { + startCursor: '1', + endCursor: '5', + hasNextPage: true, + hasPreviousPage: false, + }, + totalCount: 6, + }, + }, + }, + }, + }, + { + request: { + query: USER_TAGS_ASSIGNED_MEMBERS, + variables: { + id: '1', + after: '5', + before: null, + first: 5, + last: null, + }, + }, + result: { + data: { + getUserTag: { + name: 'tag1', + usersAssignedTo: { + edges: [ + { + node: { + _id: '6', + firstName: 'member', + lastName: '6', + }, + cursor: '6', + }, + ], + pageInfo: { + startCursor: '6', + endCursor: '6', + hasNextPage: false, + hasPreviousPage: true, + }, + totalCount: 6, + }, + }, + }, + }, + }, + { + request: { + query: USER_TAGS_ASSIGNED_MEMBERS, + variables: { + id: '1', + after: null, + before: '6', + first: null, + last: 5, + }, + }, + result: { + data: { + getUserTag: { + name: 'tag1', + usersAssignedTo: { + edges: [ + { + node: { + _id: '1', + firstName: 'member', + lastName: '1', + }, + cursor: '1', + }, + { + node: { + _id: '2', + firstName: 'member', + lastName: '2', + }, + cursor: '2', + }, + { + node: { + _id: '3', + firstName: 'member', + lastName: '3', + }, + cursor: '3', + }, + { + node: { + _id: '4', + firstName: 'member', + lastName: '4', + }, + cursor: '4', + }, + { + node: { + _id: '5', + firstName: 'member', + lastName: '5', + }, + cursor: '5', + }, + ], + pageInfo: { + startCursor: '1', + endCursor: '5', + hasNextPage: true, + hasPreviousPage: false, + }, + totalCount: 6, + }, + }, + }, + }, + }, + { + request: { + query: USER_TAG_ANCESTORS, + variables: { + id: '1', + }, + }, + result: { + data: { + getUserTagAncestors: [ + { + _id: '1', + name: 'tag1', + }, + ], + }, + }, + }, + { + request: { + query: UNASSIGN_USER_TAG, + variables: { + tagId: '1', + userId: '1', + }, + }, + result: { + data: { + unassignUserTag: { + _id: '1', + }, + }, + }, + }, +]; + +export const MOCKS_ERROR_ASSIGNED_MEMBERS = [ + { + request: { + query: USER_TAGS_ASSIGNED_MEMBERS, + variables: { + id: '1', + after: null, + before: null, + first: 5, + last: null, + }, + }, + error: new Error('Mock Graphql Error'), + }, + { + request: { + query: USER_TAG_ANCESTORS, + variables: { + id: '1', + }, + }, + result: { + data: { + getUserTagAncestors: [], + }, + }, + }, +]; + +export const MOCKS_ERROR_TAG_ANCESTORS = [ + { + request: { + query: USER_TAGS_ASSIGNED_MEMBERS, + variables: { + id: '1', + after: null, + before: null, + first: 5, + last: null, + }, + }, + result: { + data: { + getUserTag: { + name: 'tag1', + usersAssignedTo: { + edges: [], + pageInfo: { + startCursor: '1', + endCursor: '5', + hasNextPage: true, + hasPreviousPage: false, + }, + totalCount: 6, + }, + }, + }, + }, + }, + { + request: { + query: USER_TAG_ANCESTORS, + variables: { + id: '1', + }, + }, + error: new Error('Mock Graphql Error'), + }, +]; diff --git a/src/screens/MemberDetail/MemberDetail.test.tsx b/src/screens/MemberDetail/MemberDetail.test.tsx index e094354552..7b3707754c 100644 --- a/src/screens/MemberDetail/MemberDetail.test.tsx +++ b/src/screens/MemberDetail/MemberDetail.test.tsx @@ -442,7 +442,6 @@ describe('MemberDetail', () => { test('should display warnings for blank form submission', async () => { jest.spyOn(toast, 'warning'); const props = { - key: '123', id: '1', toggleStateValue: jest.fn(), }; @@ -452,7 +451,7 @@ describe('MemberDetail', () => { - + @@ -467,6 +466,7 @@ describe('MemberDetail', () => { expect(toast.warning).toHaveBeenCalledWith('Last Name cannot be blank!'); expect(toast.warning).toHaveBeenCalledWith('Email cannot be blank!'); }); + test('display admin', async () => { const props = { id: 'rishav-jha-mech', diff --git a/src/screens/MemberDetail/MemberDetail.tsx b/src/screens/MemberDetail/MemberDetail.tsx index be9b891b3c..6d92ccbb4a 100644 --- a/src/screens/MemberDetail/MemberDetail.tsx +++ b/src/screens/MemberDetail/MemberDetail.tsx @@ -35,6 +35,15 @@ type MemberDetailProps = { id?: string; // This is the userId }; +/** + * MemberDetail component is used to display the details of a user. + * It also allows the user to update the details. It uses the UPDATE_USER_MUTATION to update the user details. + * It uses the USER_DETAILS query to get the user details. It uses the useLocalStorage hook to store the user + * details in the local storage. + * @param id - The id of the user whose details are to be displayed. + * @returns React component + * + */ const MemberDetail: React.FC = ({ id }): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'memberDetail', @@ -185,7 +194,7 @@ const MemberDetail: React.FC = ({ id }): JSX.Element => { setItem('Email', email); setItem('UserImage', image); } - toast.success(tCommon('successfullyUpdated')); + toast.success(tCommon('successfullyUpdated') as string); } } catch (error: unknown) { if (error instanceof Error) { diff --git a/src/screens/OrgContribution/OrgContribution.test.tsx b/src/screens/OrgContribution/OrgContribution.test.tsx index d2abc134df..f9f63c6807 100644 --- a/src/screens/OrgContribution/OrgContribution.test.tsx +++ b/src/screens/OrgContribution/OrgContribution.test.tsx @@ -1,6 +1,6 @@ -import React from 'react'; +import React, { act } from 'react'; import { MockedProvider } from '@apollo/react-testing'; -import { act, render } from '@testing-library/react'; +import { render } from '@testing-library/react'; import { Provider } from 'react-redux'; import { BrowserRouter } from 'react-router-dom'; import 'jest-location-mock'; diff --git a/src/screens/OrgContribution/OrgContribution.tsx b/src/screens/OrgContribution/OrgContribution.tsx index bcd8641609..db155cdb47 100644 --- a/src/screens/OrgContribution/OrgContribution.tsx +++ b/src/screens/OrgContribution/OrgContribution.tsx @@ -8,11 +8,19 @@ import OrgContriCards from 'components/OrgContriCards/OrgContriCards'; import { Form } from 'react-bootstrap'; import styles from './OrgContribution.module.css'; +/** + * The `orgContribution` component displays the contributions to an organization. + * It includes a sidebar for filtering contributions by organization name and transaction ID. + * Additionally, it shows recent contribution statistics and a list of contribution cards. + * + */ function orgContribution(): JSX.Element { + // Hook to get translation functions and translation text const { t } = useTranslation('translation', { keyPrefix: 'orgContribution', }); + // Set the document title based on the translated title for this page document.title = t('title'); return ( @@ -21,6 +29,7 @@ function orgContribution(): JSX.Element {
    + {/* Input for filtering by organization name */}
    {t('filterByName')}
    + {/* Input for filtering by transaction ID */}
    {t('filterByTransId')}
    + {/* Section displaying recent contribution statistics */}
    {t('recentStats')}

    {t('contribution')}

    + {/* Section displaying a list of contribution cards */} { ); await wait(); + }); + const sortDropdown = await waitFor(() => screen.getByTestId('sort')); + expect(sortDropdown).toBeInTheDocument(); - const searchInput = screen.getByTestId('sort'); - expect(searchInput).toBeInTheDocument(); - - const inputText = screen.getByTestId('sortOrgs'); + const sortToggle = screen.getByTestId('sortOrgs'); - fireEvent.click(inputText); - const toggleText = screen.getByTestId('latest'); + fireEvent.click(sortToggle); + const latestOption = await waitFor(() => screen.getByTestId('latest')); - fireEvent.click(toggleText); + fireEvent.click(latestOption); - expect(searchInput).toBeInTheDocument(); - fireEvent.click(inputText); - const toggleTite = screen.getByTestId('oldest'); - fireEvent.click(toggleTite); - expect(searchInput).toBeInTheDocument(); - }); + expect(sortDropdown).toBeInTheDocument(); + fireEvent.click(sortToggle); + const oldestOption = await waitFor(() => screen.getByTestId('oldest')); + fireEvent.click(oldestOption); + expect(sortDropdown).toBeInTheDocument(); }); }); diff --git a/src/screens/OrgList/OrgList.tsx b/src/screens/OrgList/OrgList.tsx index 5c91678217..7023bfa9b1 100644 --- a/src/screens/OrgList/OrgList.tsx +++ b/src/screens/OrgList/OrgList.tsx @@ -169,11 +169,11 @@ function orgList(): JSX.Element { const triggerCreateSampleOrg = (): void => { createSampleOrganization() .then(() => { - toast.success(t('sampleOrgSuccess')); + toast.success(t('sampleOrgSuccess') as string); window.location.reload(); }) .catch(() => { - toast.error(t('sampleOrgDuplicate')); + toast.error(t('sampleOrgDuplicate') as string); }); }; diff --git a/src/screens/OrgPost/OrgPost.test.tsx b/src/screens/OrgPost/OrgPost.test.tsx index 465da98642..9829589350 100644 --- a/src/screens/OrgPost/OrgPost.test.tsx +++ b/src/screens/OrgPost/OrgPost.test.tsx @@ -1,11 +1,11 @@ import { MockedProvider } from '@apollo/react-testing'; -import { act, fireEvent, render, screen } from '@testing-library/react'; +import { fireEvent, render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import 'jest-location-mock'; import { I18nextProvider } from 'react-i18next'; import { Provider } from 'react-redux'; import { BrowserRouter } from 'react-router-dom'; -import React from 'react'; +import React, { act } from 'react'; import { CREATE_POST_MUTATION } from 'GraphQl/Mutations/mutations'; import { ORGANIZATION_POST_LIST } from 'GraphQl/Queries/Queries'; import { ToastContainer } from 'react-toastify'; @@ -286,25 +286,34 @@ describe('Organisation Post Page', () => { , ); + }); + await wait(); - await wait(); - - const searchInput = screen.getByTestId('searchByName'); - expect(searchInput).toHaveAttribute('placeholder', 'Search By Title'); + const searchInput = screen.getByTestId('searchByName'); + expect(searchInput).toHaveAttribute('placeholder', 'Search By Title'); - const inputText = screen.getByTestId('searchBy'); + const inputText = screen.getByTestId('searchBy'); + await act(async () => { fireEvent.click(inputText); - const toggleText = screen.getByTestId('Text'); + }); + const toggleText = screen.getByTestId('Text'); + + await act(async () => { fireEvent.click(toggleText); + }); - expect(searchInput).toHaveAttribute('placeholder', 'Search By Text'); + expect(searchInput).toHaveAttribute('placeholder', 'Search By Text'); + await act(async () => { fireEvent.click(inputText); - const toggleTite = screen.getByTestId('searchTitle'); + }); + const toggleTite = screen.getByTestId('searchTitle'); + await act(async () => { fireEvent.click(toggleTite); - expect(searchInput).toHaveAttribute('placeholder', 'Search By Title'); }); + + expect(searchInput).toHaveAttribute('placeholder', 'Search By Title'); }); test('Testing search latest and oldest toggle', async () => { await act(async () => { @@ -320,25 +329,34 @@ describe('Organisation Post Page', () => { , ); + }); + await wait(); - await wait(); - - const searchInput = screen.getByTestId('sort'); - expect(searchInput).toBeInTheDocument(); + const searchInput = screen.getByTestId('sort'); + expect(searchInput).toBeInTheDocument(); - const inputText = screen.getByTestId('sortpost'); + const inputText = screen.getByTestId('sortpost'); + await act(async () => { fireEvent.click(inputText); - const toggleText = screen.getByTestId('latest'); + }); + + const toggleText = screen.getByTestId('latest'); + await act(async () => { fireEvent.click(toggleText); + }); - expect(searchInput).toBeInTheDocument(); + expect(searchInput).toBeInTheDocument(); + await act(async () => { fireEvent.click(inputText); - const toggleTite = screen.getByTestId('oldest'); + }); + + const toggleTite = screen.getByTestId('oldest'); + await act(async () => { fireEvent.click(toggleTite); - expect(searchInput).toBeInTheDocument(); }); + expect(searchInput).toBeInTheDocument(); }); test('After creating a post, the data should be refetched', async () => { const refetchMock = jest.fn(); @@ -575,34 +593,43 @@ describe('Organisation Post Page', () => { , ); + }); + await wait(); - await wait(); - + await act(async () => { userEvent.click(screen.getByTestId('createPostModalBtn')); + }); - const postTitleInput = screen.getByTestId('modalTitle'); + const postTitleInput = screen.getByTestId('modalTitle'); + await act(async () => { fireEvent.change(postTitleInput, { target: { value: 'Test Post' } }); + }); - const postInfoTextarea = screen.getByTestId('modalinfo'); + const postInfoTextarea = screen.getByTestId('modalinfo'); + await act(async () => { fireEvent.change(postInfoTextarea, { target: { value: 'Test post information' }, }); + }); - const videoFile = new File(['video content'], 'video.mp4', { - type: 'video/mp4', - }); + const videoFile = new File(['video content'], 'video.mp4', { + type: 'video/mp4', + }); + await act(async () => { userEvent.upload(screen.getByTestId('addMediaField'), videoFile); + }); - // Check if the video is displayed - const videoPreview = await screen.findByTestId('videoPreview'); - expect(videoPreview).toBeInTheDocument(); + // Check if the video is displayed + const videoPreview = await screen.findByTestId('videoPreview'); + expect(videoPreview).toBeInTheDocument(); - // Check if the close button for the video works - const closeVideoPreviewButton = screen.getByTestId('mediaCloseButton'); + // Check if the close button for the video works + const closeVideoPreviewButton = screen.getByTestId('mediaCloseButton'); + await act(async () => { fireEvent.click(closeVideoPreviewButton); - expect(videoPreview).not.toBeInTheDocument(); }); + expect(videoPreview).not.toBeInTheDocument(); }); test('Sorting posts by pinned status', async () => { // Mocked data representing posts with different pinned statuses diff --git a/src/screens/OrgPost/OrgPost.tsx b/src/screens/OrgPost/OrgPost.tsx index 29b7de0614..1931f6c76a 100644 --- a/src/screens/OrgPost/OrgPost.tsx +++ b/src/screens/OrgPost/OrgPost.tsx @@ -43,6 +43,12 @@ interface InterfaceOrgPost { }[]; } +/** + * This function is used to display the posts of the organization. It displays the posts in a card format. + * It also provides the functionality to create a new post. The user can also sort the posts based on the date of creation. + * The user can also search for a post based on the title of the post. + * @returns JSX.Element which contains the posts of the organization. + */ function orgPost(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'orgPost', @@ -98,14 +104,18 @@ function orgPost(): JSX.Element { error?: ApolloError; refetch: (filterData?: { id: string | undefined; - title_contains: string | null; - text_contains: string | null; + // title_contains: string | null; + // text_contains: string | null; + after: string | null | undefined; + before: string | null | undefined; + first: number | null; + last: number | null; }) => void; } = useQuery(ORGANIZATION_POST_LIST, { variables: { - id: currentUrl, - after: after, - before: before, + id: currentUrl as string, + after: after ?? null, + before: before ?? null, first: first, last: last, }, @@ -160,7 +170,7 @@ function orgPost(): JSX.Element { /* istanbul ignore next */ if (data) { - toast.success(t('postCreatedSuccess')); + toast.success(t('postCreatedSuccess') as string); refetch(); setPostFormState({ posttitle: '', @@ -212,6 +222,10 @@ function orgPost(): JSX.Element { id: currentUrl, title_contains: showTitle ? value : null, text_contains: !showTitle ? value : null, + after: after || null, + before: before || null, + first: first || null, + last: last || null, }; refetch(filterData); }; @@ -295,7 +309,7 @@ function orgPost(): JSX.Element {
    } + /> + + + + + + , + ); +}; -async function wait(ms = 100): Promise { - await act(() => { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); +describe('Organisation Settings Page', () => { + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId' }), + })); }); -} - -const translations = JSON.parse( - JSON.stringify(i18nForTest.getDataByLanguage('en')?.translation.orgSettings), -); -afterEach(() => { - localStorage.clear(); -}); - -describe('Organisation Settings Page', () => { - test('correct mock data should be queried', async () => { - const dataQuery1 = MOCKS[1]?.result?.data?.removeOrganization; - expect(dataQuery1).toEqual([ - { - _id: 123, - }, - ]); + afterAll(() => { + jest.clearAllMocks(); }); - test('should render props and text elements test for the screen', async () => { - window.location.assign('/orgsetting/123'); - setItem('SuperAdmin', true); + it('should redirect to fallback URL if URL params are undefined', async () => { render( - - + + - + + } /> +
    } + /> + - + , ); - - await wait(); - - expect(screen.getAllByText(/Delete Organization/i)).toHaveLength(3); - expect( - screen.getByText( - /By clicking on Delete Organization button the organization will be permanently deleted along with its events, tags and all related data/i, - ), - ).toBeInTheDocument(); - expect(screen.getByText(/Other Settings/i)).toBeInTheDocument(); - expect(screen.getByText(/Change Language/i)).toBeInTheDocument(); - expect(window.location).toBeAt('/orgsetting/123'); + await waitFor(() => { + expect(screen.getByTestId('paramsError')).toBeInTheDocument(); + }); }); - test('should render appropriate settings based on the orgSetting state', async () => { - window.location.assign('/orgsetting/123'); - setItem('SuperAdmin', true); - - const { queryByText } = render( - - - - - - - - - , - ); - - await wait(); + test('should render the organisation settings page', async () => { + renderOrganisationSettings(link1); await waitFor(() => { - userEvent.click(screen.getByTestId('actionItemCategoriesSettings')); + expect(screen.getByTestId('generalSettings')).toBeInTheDocument(); expect( - queryByText(translations.actionItemCategories), + screen.getByTestId('actionItemCategoriesSettings'), ).toBeInTheDocument(); + expect( + screen.getByTestId('agendaItemCategoriesSettings'), + ).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('generalSettings')); + + await waitFor(() => { + expect(screen.getByTestId('generalTab')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('actionItemCategoriesSettings')); + await waitFor(() => { + expect(screen.getByTestId('actionItemCategoriesTab')).toBeInTheDocument(); }); + userEvent.click(screen.getByTestId('agendaItemCategoriesSettings')); await waitFor(() => { - userEvent.click(screen.getByTestId('generalSettings')); - expect(queryByText(translations.updateOrganization)).toBeInTheDocument(); + expect(screen.getByTestId('agendaItemCategoriesTab')).toBeInTheDocument(); }); }); }); diff --git a/src/screens/OrgSettings/OrgSettings.tsx b/src/screens/OrgSettings/OrgSettings.tsx index 8065911508..e4ae5424a6 100644 --- a/src/screens/OrgSettings/OrgSettings.tsx +++ b/src/screens/OrgSettings/OrgSettings.tsx @@ -1,146 +1,128 @@ import React, { useState } from 'react'; -import ChangeLanguageDropDown from 'components/ChangeLanguageDropdown/ChangeLanguageDropDown'; -import DeleteOrg from 'components/DeleteOrg/DeleteOrg'; -import OrgUpdate from 'components/OrgUpdate/OrgUpdate'; -import { Button, Card, Dropdown, Form } from 'react-bootstrap'; -import Col from 'react-bootstrap/Col'; -import Row from 'react-bootstrap/Row'; +import { Button, Dropdown, Row, Col } from 'react-bootstrap'; import { useTranslation } from 'react-i18next'; import styles from './OrgSettings.module.css'; -import OrgProfileFieldSettings from 'components/OrgProfileFieldSettings/OrgProfileFieldSettings'; -import OrgActionItemCategories from 'components/OrgActionItemCategories/OrgActionItemCategories'; -import { useParams } from 'react-router-dom'; +import OrgActionItemCategories from 'components/OrgSettings/ActionItemCategories/OrgActionItemCategories'; +import OrganizationAgendaCategory from 'components/OrgSettings/AgendaItemCategories/OrganizationAgendaCategory'; +import { Navigate, useParams } from 'react-router-dom'; +import GeneralSettings from 'components/OrgSettings/General/GeneralSettings'; -type SettingType = 'general' | 'actionItemCategories'; +// Type representing the different settings categories available +type SettingType = 'general' | 'actionItemCategories' | 'agendaItemCategories'; +// List of available settings categories +const settingtabs: SettingType[] = [ + 'general', + 'actionItemCategories', + 'agendaItemCategories', +]; + +/** + * The `orgSettings` component provides a user interface for managing various settings related to an organization. + * It includes options for updating organization details, deleting the organization, changing language preferences, + * and managing custom fields and action item categories. + * + * The component renders different settings sections based on the user's selection from the tabs or dropdown menu. + * + * @returns The rendered component displaying the organization settings. + */ function orgSettings(): JSX.Element { + // Translation hook for internationalization const { t } = useTranslation('translation', { keyPrefix: 'orgSettings', }); - const orgSettings: SettingType[] = ['general', 'actionItemCategories']; - - const [orgSetting, setOrgSetting] = useState('general'); + const [tab, setTab] = useState('general'); + // Set the document title using the translated title for this page document.title = t('title'); + + // Get the organization ID from the URL parameters const { orgId } = useParams(); + if (!orgId) { + return ; + } + return ( - <> -
    - - -
    - {orgSettings.map((setting, index) => ( - + ))} +
    + + {/* Dropdown menu for selecting settings category */} + + + {t(tab)} + + + {/* Render dropdown items for each settings category */} + {settingtabs.map((setting, index) => ( + setOrgSetting(setting)} - data-testid={`${setting}Settings`} + onClick={ + /* istanbul ignore next */ + () => setTab(setting) + } + className={tab === setting ? 'text-secondary' : ''} > {t(setting)} - + ))} -
    + + + - - - {t(orgSetting)} - - - {orgSettings.map((setting, index) => ( - setOrgSetting(setting) - } - className={orgSetting === setting ? 'text-secondary' : ''} - > - {t(setting)} - - ))} - - - - - -
    -
    + +
    + - {orgSetting === 'general' && ( - - - -
    -
    - {t('updateOrganization')} -
    -
    - - {orgId && } - -
    - - - - -
    -
    {t('otherSettings')}
    -
    - -
    - - {t('changeLanguage')} - - -
    -
    -
    - - - -
    -
    - {t('manageCustomFields')} -
    -
    - - {orgId && } - -
    - -
    - )} - - {orgSetting === 'actionItemCategories' && ( - -
    -
    - {t('actionItemCategories')} + {/* Render content based on the selected settings category */} + {(() => { + switch (tab) { + case 'general': + return ( +
    + +
    + ); + case 'actionItemCategories': + return ( +
    + +
    + ); + case 'agendaItemCategories': + return ( +
    +
    -
    -
    - {orgId && } -
    - - )} -
    - + ); + } + })()} +
    ); } diff --git a/src/screens/OrganizationActionItems/ActionItemCreateModal.tsx b/src/screens/OrganizationActionItems/ActionItemCreateModal.tsx deleted file mode 100644 index 88701077a6..0000000000 --- a/src/screens/OrganizationActionItems/ActionItemCreateModal.tsx +++ /dev/null @@ -1,155 +0,0 @@ -import React from 'react'; -import { Modal, Form, Button } from 'react-bootstrap'; -import type { ChangeEvent } from 'react'; -import styles from './OrganizationActionItems.module.css'; -import { DatePicker } from '@mui/x-date-pickers'; -import dayjs from 'dayjs'; -import type { Dayjs } from 'dayjs'; - -import type { - InterfaceActionItemCategoryInfo, - InterfaceMemberInfo, -} from 'utils/interfaces'; - -interface InterfaceFormStateType { - actionItemCategoryId: string; - assigneeId: string; - eventId?: string; - preCompletionNotes: string; -} - -interface InterfaceActionItemCreateModalProps { - actionItemCreateModalIsOpen: boolean; - hideCreateModal: () => void; - formState: InterfaceFormStateType; - setFormState: (state: React.SetStateAction) => void; - createActionItemHandler: (e: ChangeEvent) => Promise; - t: (key: string) => string; - actionItemCategories: InterfaceActionItemCategoryInfo[] | undefined; - membersData: InterfaceMemberInfo[] | undefined; - dueDate: Date | null; - setDueDate: (state: React.SetStateAction) => void; -} - -const ActionItemCreateModal: React.FC = ({ - actionItemCreateModalIsOpen, - hideCreateModal, - formState, - setFormState, - createActionItemHandler, - t, - actionItemCategories, - membersData, - dueDate, - setDueDate, -}) => { - return ( - <> - - -

    {t('actionItemDetails')}

    - -
    - -
    - - {t('actionItemCategory')} - - setFormState({ - ...formState, - actionItemCategoryId: e.target.value, - }) - } - > - - {actionItemCategories?.map((category, index) => ( - - ))} - - - - - {t('assignee')} - - setFormState({ ...formState, assigneeId: e.target.value }) - } - > - - {membersData?.map((member, index) => ( - - ))} - - - - - { - setFormState({ - ...formState, - preCompletionNotes: e.target.value, - }); - }} - /> - -
    - { - if (date) { - setDueDate(date?.toDate()); - } - }} - /> -
    - - - -
    -
    - - ); -}; - -export default ActionItemCreateModal; diff --git a/src/screens/OrganizationActionItems/ActionItemDeleteModal.tsx b/src/screens/OrganizationActionItems/ActionItemDeleteModal.tsx deleted file mode 100644 index 53b93ba9e5..0000000000 --- a/src/screens/OrganizationActionItems/ActionItemDeleteModal.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import React from 'react'; -import { Modal, Button } from 'react-bootstrap'; -import styles from './OrganizationActionItems.module.css'; - -interface InterfaceActionItemCreateModalProps { - actionItemDeleteModalIsOpen: boolean; - deleteActionItemHandler: () => Promise; - toggleDeleteModal: () => void; - t: (key: string) => string; - tCommon: (key: string) => string; -} - -const ActionItemPreviewModal: React.FC = ({ - actionItemDeleteModalIsOpen, - deleteActionItemHandler, - toggleDeleteModal, - t, - tCommon, -}) => { - return ( - <> - - - - {t('deleteActionItem')} - - - {t('deleteActionItemMsg')} - - - - - - - ); -}; - -export default ActionItemPreviewModal; diff --git a/src/screens/OrganizationActionItems/ActionItemPreviewModal.tsx b/src/screens/OrganizationActionItems/ActionItemPreviewModal.tsx deleted file mode 100644 index 8f2d0b8f1c..0000000000 --- a/src/screens/OrganizationActionItems/ActionItemPreviewModal.tsx +++ /dev/null @@ -1,133 +0,0 @@ -import React from 'react'; -import { Modal, Form, Button } from 'react-bootstrap'; - -import styles from './OrganizationActionItems.module.css'; -import dayjs from 'dayjs'; - -interface InterfaceFormStateType { - assigneeId: string; - assignee: string; - assigner: string; - isCompleted: boolean; - preCompletionNotes: string; - postCompletionNotes: string; -} - -interface InterfaceActionItemCreateModalProps { - actionItemPreviewModalIsOpen: boolean; - hidePreviewModal: () => void; - showUpdateModal: () => void; - toggleDeleteModal: () => void; - formState: InterfaceFormStateType; - t: (key: string) => string; - dueDate: Date | null; - completionDate: Date | null; - assignmentDate: Date | null; -} - -const ActionItemPreviewModal: React.FC = ({ - actionItemPreviewModalIsOpen, - hidePreviewModal, - showUpdateModal, - toggleDeleteModal, - formState, - t, - dueDate, - completionDate, - assignmentDate, -}) => { - return ( - <> - - -

    {t('actionItemDetails')}

    - -
    - -
    -
    -

    - {t('assignee')}:{' '} - {formState.assignee} -

    -

    - {t('assigner')}:{' '} - {formState.assigner} -

    -

    - {t('preCompletionNotes')}: - - {formState.preCompletionNotes} - -

    -

    - {t('postCompletionNotes')}: - - {formState.postCompletionNotes} - -

    -

    - {t('assignmentDate')}:{' '} - - {dayjs(assignmentDate).format('YYYY-MM-DD')} - -

    -

    - {t('dueDate')}:{' '} - - {dayjs(dueDate).format('YYYY-MM-DD')} - -

    -

    - {t('completionDate')}:{' '} - - {dayjs(completionDate).format('YYYY-MM-DD')} - -

    -

    - {t('status')}:{' '} - - {formState.isCompleted ? 'Completed' : 'Active'} - -

    -
    -
    - - -
    -
    -
    -
    - - ); -}; - -export default ActionItemPreviewModal; diff --git a/src/screens/OrganizationActionItems/ActionItemUpdateModal.test.tsx b/src/screens/OrganizationActionItems/ActionItemUpdateModal.test.tsx deleted file mode 100644 index f52da23530..0000000000 --- a/src/screens/OrganizationActionItems/ActionItemUpdateModal.test.tsx +++ /dev/null @@ -1,235 +0,0 @@ -import React from 'react'; -import { render, screen, fireEvent } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import ActionItemUpdateModal from './ActionItemUpdateModal'; -import { MockedProvider } from '@apollo/react-testing'; -import { I18nextProvider } from 'react-i18next'; -import { Provider } from 'react-redux'; -import { BrowserRouter } from 'react-router-dom'; -import { store } from 'state/store'; -import i18nForTest from 'utils/i18nForTest'; -import { LocalizationProvider } from '@mui/x-date-pickers'; -import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; -import type { InterfaceMemberInfo } from 'utils/interfaces'; -import { t } from 'i18next'; - -const mockMembersData: InterfaceMemberInfo[] = [ - { - _id: '1', - firstName: 'John', - lastName: 'Doe', - email: 'john.doe@example.com', - image: 'https://example.com/john-doe.jpg', - createdAt: '2022-01-01T00:00:00.000Z', - organizationsBlockedBy: [], - }, - { - _id: '2', - firstName: 'Jane', - lastName: 'Smith', - email: 'jane.smith@example.com', - image: 'https://example.com/jane-smith.jpg', - createdAt: '2022-02-01T00:00:00.000Z', - organizationsBlockedBy: [], - }, -]; - -const mockFormState = { - assigneeId: '1', - assignee: 'John Doe', - assigner: 'Jane Smith', - isCompleted: false, - preCompletionNotes: 'Test pre-completion notes', - postCompletionNotes: '', -}; - -const mockDueDate = new Date('2023-05-01'); -const mockCompletionDate = new Date('2023-05-15'); - -const mockHideUpdateModal = jest.fn(); -const mockSetFormState = jest.fn(); -const mockUpdateActionItemHandler = jest.fn(); -const mockSetDueDate = jest.fn(); -const mockSetCompletionDate = jest.fn(); -const mockT = (key: string): string => key; - -describe('ActionItemUpdateModal', () => { - test('renders modal correctly', () => { - render( - - - - - - - - - - - , - ); - - expect(screen.getByText('actionItemDetails')).toBeInTheDocument(); - expect( - screen.getByTestId('updateActionItemModalCloseBtn'), - ).toBeInTheDocument(); - expect(screen.getByTestId('formUpdateAssignee')).toBeInTheDocument(); - expect(screen.getByLabelText('preCompletionNotes')).toBeInTheDocument(); - expect(screen.getByLabelText('dueDate')).toBeInTheDocument(); - expect(screen.getByLabelText('completionDate')).toBeInTheDocument(); - expect(screen.getByTestId('editActionItemBtn')).toBeInTheDocument(); - }); - - test('closes modal when close button is clicked', () => { - render( - - - - - - - - - - - , - ); - - fireEvent.click(screen.getByTestId('updateActionItemModalCloseBtn')); - expect(mockHideUpdateModal).toHaveBeenCalled(); - }); - - test('updates form state when assignee is changed', () => { - render( - - - - - - - - - - - , - ); - - const assigneeSelect = screen.getByTestId('formUpdateAssignee'); - userEvent.selectOptions(assigneeSelect, '2'); - expect(mockSetFormState).toHaveBeenCalledWith({ - ...mockFormState, - assigneeId: '2', - }); - }); - - test('tests the condition for formState.preCompletionNotes', () => { - const mockFormState = { - assigneeId: '1', - assignee: 'John Doe', - assigner: 'Jane Smith', - isCompleted: false, - preCompletionNotes: '', - postCompletionNotes: '', - }; - render( - - - - - - - - - - - , - ); - const preCompletionNotesInput = screen.getByLabelText('preCompletionNotes'); - fireEvent.change(preCompletionNotesInput, { - target: { value: 'New pre-completion notes' }, - }); - expect(mockSetFormState).toHaveBeenCalledWith({ - ...mockFormState, - preCompletionNotes: 'New pre-completion notes', - }); - }); - - test('calls updateActionItemHandler when form is submitted', () => { - render( - - - - - - - - - - - , - ); - - fireEvent.submit(screen.getByTestId('editActionItemBtn')); - expect(mockUpdateActionItemHandler).toHaveBeenCalled(); - }); -}); diff --git a/src/screens/OrganizationActionItems/ActionItemUpdateModal.tsx b/src/screens/OrganizationActionItems/ActionItemUpdateModal.tsx deleted file mode 100644 index 8b0510a4dc..0000000000 --- a/src/screens/OrganizationActionItems/ActionItemUpdateModal.tsx +++ /dev/null @@ -1,154 +0,0 @@ -import React from 'react'; -import { Modal, Form, Button } from 'react-bootstrap'; -import type { ChangeEvent } from 'react'; -import { DatePicker } from '@mui/x-date-pickers'; -import dayjs from 'dayjs'; -import type { Dayjs } from 'dayjs'; - -import styles from './OrganizationActionItems.module.css'; -import type { InterfaceMemberInfo } from 'utils/interfaces'; - -interface InterfaceFormStateType { - assigneeId: string; - assignee: string; - assigner: string; - isCompleted: boolean; - preCompletionNotes: string; - postCompletionNotes: string; -} - -interface InterfaceActionItemCreateModalProps { - actionItemUpdateModalIsOpen: boolean; - hideUpdateModal: () => void; - formState: InterfaceFormStateType; - setFormState: (state: React.SetStateAction) => void; - updateActionItemHandler: (e: ChangeEvent) => Promise; - t: (key: string) => string; - membersData: InterfaceMemberInfo[] | undefined; - dueDate: Date | null; - setDueDate: (state: React.SetStateAction) => void; - completionDate: Date | null; - setCompletionDate: (state: React.SetStateAction) => void; -} - -const ActionItemUpdateModal: React.FC = ({ - actionItemUpdateModalIsOpen, - hideUpdateModal, - formState, - setFormState, - updateActionItemHandler, - t, - membersData, - dueDate, - setDueDate, - completionDate, - setCompletionDate, -}) => { - return ( - <> - - -

    {t('actionItemDetails')}

    - -
    - -
    - - {t('assignee')} - - setFormState({ ...formState, assigneeId: e.target.value }) - } - > - - {membersData?.map((member: InterfaceMemberInfo) => { - const currMemberName = `${member.firstName} ${member.lastName}`; - if (currMemberName !== formState.assignee) { - return ( - - ); - } - })} - - - - - { - setFormState({ - ...formState, - preCompletionNotes: e.target.value, - }); - }} - className="mb-2" - /> - -
    - { - /* istanbul ignore next */ - if (date) { - setDueDate(date?.toDate()); - } - } - } - /> -   - { - /* istanbul ignore next */ - if (date) { - setCompletionDate(date?.toDate()); - } - } - } - /> -
    - - - -
    -
    - - ); -}; - -export default ActionItemUpdateModal; diff --git a/src/screens/OrganizationActionItems/ItemDeleteModal.test.tsx b/src/screens/OrganizationActionItems/ItemDeleteModal.test.tsx new file mode 100644 index 0000000000..3d45e12a25 --- /dev/null +++ b/src/screens/OrganizationActionItems/ItemDeleteModal.test.tsx @@ -0,0 +1,120 @@ +import React from 'react'; +import type { ApolloLink } from '@apollo/client'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import type { RenderResult } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import i18nForTest from '../../utils/i18nForTest'; +import { MOCKS, MOCKS_ERROR } from './OrganizationActionItem.mocks'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { toast } from 'react-toastify'; +import ItemDeleteModal, { + type InterfaceItemDeleteModalProps, +} from './ItemDeleteModal'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(MOCKS_ERROR); +const t = JSON.parse( + JSON.stringify( + i18nForTest.getDataByLanguage('en')?.translation.organizationActionItems, + ), +); + +const itemProps: InterfaceItemDeleteModalProps = { + isOpen: true, + hide: jest.fn(), + actionItemsRefetch: jest.fn(), + actionItem: { + _id: 'actionItemId1', + assignee: { + _id: 'userId1', + firstName: 'John', + lastName: 'Doe', + image: null, + }, + actionItemCategory: { + _id: 'actionItemCategoryId1', + name: 'Category 1', + }, + preCompletionNotes: 'Notes 1', + postCompletionNotes: 'Cmp Notes 1', + assignmentDate: new Date('2024-08-27'), + dueDate: new Date('2044-08-30'), + completionDate: new Date('2044-09-03'), + isCompleted: true, + event: null, + allotedHours: 24, + assigner: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + creator: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, +}; + +const renderItemDeleteModal = ( + link: ApolloLink, + props: InterfaceItemDeleteModalProps, +): RenderResult => { + return render( + + + + + + + + + + + , + ); +}; + +describe('Testing ItemDeleteModal', () => { + it('should render ItemDeleteModal', () => { + renderItemDeleteModal(link1, itemProps); + expect(screen.getByText(t.deleteActionItem)).toBeInTheDocument(); + }); + + it('should successfully Delete Action Item', async () => { + renderItemDeleteModal(link1, itemProps); + expect(screen.getByTestId('deleteyesbtn')).toBeInTheDocument(); + + fireEvent.click(screen.getByTestId('deleteyesbtn')); + + await waitFor(() => { + expect(itemProps.actionItemsRefetch).toHaveBeenCalled(); + expect(itemProps.hide).toHaveBeenCalled(); + expect(toast.success).toHaveBeenCalledWith(t.successfulDeletion); + }); + }); + + it('should fail to Delete Action Item', async () => { + renderItemDeleteModal(link2, itemProps); + expect(screen.getByTestId('deleteyesbtn')).toBeInTheDocument(); + fireEvent.click(screen.getByTestId('deleteyesbtn')); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalledWith('Mock Graphql Error'); + }); + }); +}); diff --git a/src/screens/OrganizationActionItems/ItemDeleteModal.tsx b/src/screens/OrganizationActionItems/ItemDeleteModal.tsx new file mode 100644 index 0000000000..2526486993 --- /dev/null +++ b/src/screens/OrganizationActionItems/ItemDeleteModal.tsx @@ -0,0 +1,92 @@ +import React from 'react'; +import { Modal, Button } from 'react-bootstrap'; +import styles from './OrganizationActionItems.module.css'; +import { useMutation } from '@apollo/client'; +import { DELETE_ACTION_ITEM_MUTATION } from 'GraphQl/Mutations/ActionItemMutations'; +import { toast } from 'react-toastify'; +import { useTranslation } from 'react-i18next'; +import type { InterfaceActionItemInfo } from 'utils/interfaces'; + +/** + * Props for the `ItemDeleteModal` component. + */ +export interface InterfaceItemDeleteModalProps { + isOpen: boolean; + hide: () => void; + actionItem: InterfaceActionItemInfo | null; + actionItemsRefetch: () => void; +} + +/** + * A modal component for confirming the deletion of an action item. + * + * @param props - The properties passed to the component. + * @returns The `ItemDeleteModal` component. + */ +const ItemDeleteModal: React.FC = ({ + isOpen, + hide, + actionItem, + actionItemsRefetch, +}) => { + const { t } = useTranslation('translation', { + keyPrefix: 'organizationActionItems', + }); + const { t: tCommon } = useTranslation('common'); + + const [removeActionItem] = useMutation(DELETE_ACTION_ITEM_MUTATION); + + /** + * Handles the action item deletion. + */ + const deleteActionItemHandler = async (): Promise => { + try { + await removeActionItem({ + variables: { + actionItemId: actionItem?._id, + }, + }); + + actionItemsRefetch(); + hide(); + toast.success(t('successfulDeletion')); + } catch (error: unknown) { + toast.error((error as Error).message); + } + }; + return ( + <> + + +

    {t('deleteActionItem')}

    + +
    + +

    {t('deleteActionItemMsg')}

    +
    + + + + +
    + + ); +}; + +export default ItemDeleteModal; diff --git a/src/screens/OrganizationActionItems/ItemModal.test.tsx b/src/screens/OrganizationActionItems/ItemModal.test.tsx new file mode 100644 index 0000000000..6901e16291 --- /dev/null +++ b/src/screens/OrganizationActionItems/ItemModal.test.tsx @@ -0,0 +1,373 @@ +import React from 'react'; +import type { ApolloLink } from '@apollo/client'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import type { RenderResult } from '@testing-library/react'; +import { + fireEvent, + render, + screen, + waitFor, + within, +} from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import i18n from '../../utils/i18nForTest'; +import { MOCKS, MOCKS_ERROR } from './OrganizationActionItem.mocks'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { toast } from 'react-toastify'; +import type { InterfaceItemModalProps } from './ItemModal'; +import ItemModal from './ItemModal'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + warning: jest.fn(), + }, +})); + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(MOCKS_ERROR); +const t = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.organizationActionItems ?? {}, + ), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const itemProps: InterfaceItemModalProps[] = [ + { + isOpen: true, + hide: jest.fn(), + orgId: 'orgId', + actionItemsRefetch: jest.fn(), + editMode: false, + actionItem: null, + }, + { + isOpen: true, + hide: jest.fn(), + orgId: 'orgId', + actionItemsRefetch: jest.fn(), + editMode: true, + actionItem: { + _id: 'actionItemId1', + assignee: { + _id: 'userId1', + firstName: 'Harve', + lastName: 'Lance', + image: '', + }, + actionItemCategory: { + _id: 'categoryId1', + name: 'Category 1', + }, + preCompletionNotes: 'Notes 1', + postCompletionNotes: 'Cmp Notes 1', + assignmentDate: new Date('2024-08-27'), + dueDate: new Date('2044-08-30'), + completionDate: new Date('2044-09-03'), + isCompleted: true, + event: null, + allotedHours: 24, + assigner: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + creator: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + }, + { + isOpen: true, + hide: jest.fn(), + orgId: 'orgId', + actionItemsRefetch: jest.fn(), + editMode: true, + actionItem: { + _id: 'actionItemId2', + assignee: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + actionItemCategory: { + _id: 'categoryId2', + name: 'Category 2', + }, + preCompletionNotes: 'Notes 2', + postCompletionNotes: null, + assignmentDate: new Date('2024-08-27'), + dueDate: new Date('2044-09-30'), + completionDate: new Date('2044-10-03'), + isCompleted: false, + event: null, + allotedHours: null, + assigner: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + image: 'wilt-image', + }, + creator: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + }, +]; + +const renderItemModal = ( + link: ApolloLink, + props: InterfaceItemModalProps, +): RenderResult => { + return render( + + + + + + + + + + + , + ); +}; + +describe('Testing ItemModal', () => { + it('Create Action Item', async () => { + renderItemModal(link1, itemProps[0]); + expect(screen.getAllByText(t.createActionItem)).toHaveLength(2); + + // Select Category 1 + const categorySelect = await screen.findByTestId('categorySelect'); + expect(categorySelect).toBeInTheDocument(); + const inputField = within(categorySelect).getByRole('combobox'); + fireEvent.mouseDown(inputField); + + const categoryOption = await screen.findByText('Category 1'); + expect(categoryOption).toBeInTheDocument(); + fireEvent.click(categoryOption); + + // Select Assignee + const memberSelect = await screen.findByTestId('memberSelect'); + expect(memberSelect).toBeInTheDocument(); + const memberInputField = within(memberSelect).getByRole('combobox'); + fireEvent.mouseDown(memberInputField); + + const memberOption = await screen.findByText('Harve Lance'); + expect(memberOption).toBeInTheDocument(); + fireEvent.click(memberOption); + + // Select Due Date + fireEvent.change(screen.getByLabelText(t.dueDate), { + target: { value: '02/01/2044' }, + }); + + // Select Allotted Hours (try all options) + const allotedHours = screen.getByLabelText(t.allotedHours); + const allotedHoursOptions = ['', '-1', '9']; + + allotedHoursOptions.forEach((option) => { + fireEvent.change(allotedHours, { target: { value: option } }); + expect(allotedHours).toHaveValue(parseInt(option) > 0 ? option : ''); + }); + + // Add Pre Completion Notes + fireEvent.change(screen.getByLabelText(t.preCompletionNotes), { + target: { value: 'Notes' }, + }); + + // Click Submit + const submitButton = screen.getByTestId('submitBtn'); + expect(submitButton).toBeInTheDocument(); + fireEvent.click(submitButton); + + await waitFor(() => { + expect(itemProps[0].actionItemsRefetch).toHaveBeenCalled(); + expect(itemProps[0].hide).toHaveBeenCalled(); + expect(toast.success).toHaveBeenCalledWith(t.successfulCreation); + }); + }); + + it('Update Action Item (completed)', async () => { + renderItemModal(link1, itemProps[1]); + expect(screen.getAllByText(t.updateActionItem)).toHaveLength(2); + + // Update Category + const categorySelect = await screen.findByTestId('categorySelect'); + expect(categorySelect).toBeInTheDocument(); + const inputField = within(categorySelect).getByRole('combobox'); + fireEvent.mouseDown(inputField); + + const categoryOption = await screen.findByText('Category 2'); + expect(categoryOption).toBeInTheDocument(); + fireEvent.click(categoryOption); + + // Update Allotted Hours (try all options) + const allotedHours = screen.getByLabelText(t.allotedHours); + const allotedHoursOptions = ['', '-1', '19']; + + allotedHoursOptions.forEach((option) => { + fireEvent.change(allotedHours, { target: { value: option } }); + expect(allotedHours).toHaveValue(parseInt(option) > 0 ? option : ''); + }); + + // Update Post Completion Notes + fireEvent.change(screen.getByLabelText(t.postCompletionNotes), { + target: { value: 'Cmp Notes 2' }, + }); + + // Click Submit + const submitButton = screen.getByTestId('submitBtn'); + expect(submitButton).toBeInTheDocument(); + fireEvent.click(submitButton); + + await waitFor(() => { + expect(itemProps[1].actionItemsRefetch).toHaveBeenCalled(); + expect(itemProps[1].hide).toHaveBeenCalled(); + expect(toast.success).toHaveBeenCalledWith(t.successfulUpdation); + }); + }); + + it('Update Action Item (not completed)', async () => { + renderItemModal(link1, itemProps[2]); + expect(screen.getAllByText(t.updateActionItem)).toHaveLength(2); + + // Update Category + const categorySelect = await screen.findByTestId('categorySelect'); + expect(categorySelect).toBeInTheDocument(); + const inputField = within(categorySelect).getByRole('combobox'); + fireEvent.mouseDown(inputField); + + const categoryOption = await screen.findByText('Category 1'); + expect(categoryOption).toBeInTheDocument(); + fireEvent.click(categoryOption); + + // Update Assignee + const memberSelect = await screen.findByTestId('memberSelect'); + expect(memberSelect).toBeInTheDocument(); + const memberInputField = within(memberSelect).getByRole('combobox'); + fireEvent.mouseDown(memberInputField); + + const memberOption = await screen.findByText('Harve Lance'); + expect(memberOption).toBeInTheDocument(); + fireEvent.click(memberOption); + + // Update Allotted Hours (try all options) + const allotedHours = screen.getByLabelText(t.allotedHours); + const allotedHoursOptions = ['', '-1', '19']; + + allotedHoursOptions.forEach((option) => { + fireEvent.change(allotedHours, { target: { value: option } }); + expect(allotedHours).toHaveValue(parseInt(option) > 0 ? option : ''); + }); + + // Update Due Date + fireEvent.change(screen.getByLabelText(t.dueDate), { + target: { value: '02/01/2044' }, + }); + + // Update Pre Completion Notes + fireEvent.change(screen.getByLabelText(t.preCompletionNotes), { + target: { value: 'Notes 3' }, + }); + + // Click Submit + const submitButton = screen.getByTestId('submitBtn'); + expect(submitButton).toBeInTheDocument(); + fireEvent.click(submitButton); + + await waitFor(() => { + expect(itemProps[2].actionItemsRefetch).toHaveBeenCalled(); + expect(itemProps[2].hide).toHaveBeenCalled(); + expect(toast.success).toHaveBeenCalledWith(t.successfulUpdation); + }); + }); + + it('Try adding negative Allotted Hours', async () => { + renderItemModal(link1, itemProps[0]); + expect(screen.getAllByText(t.createActionItem)).toHaveLength(2); + const allotedHours = screen.getByLabelText(t.allotedHours); + fireEvent.change(allotedHours, { target: { value: '-1' } }); + + await waitFor(() => { + expect(allotedHours).toHaveValue(''); + }); + + fireEvent.change(allotedHours, { target: { value: '' } }); + + await waitFor(() => { + expect(allotedHours).toHaveValue(''); + }); + + fireEvent.change(allotedHours, { target: { value: '0' } }); + await waitFor(() => { + expect(allotedHours).toHaveValue('0'); + }); + + fireEvent.change(allotedHours, { target: { value: '19' } }); + await waitFor(() => { + expect(allotedHours).toHaveValue('19'); + }); + }); + + it('should fail to Create Action Item', async () => { + renderItemModal(link2, itemProps[0]); + // Click Submit + const submitButton = screen.getByTestId('submitBtn'); + expect(submitButton).toBeInTheDocument(); + fireEvent.click(submitButton); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalledWith('Mock Graphql Error'); + }); + }); + + it('No Fields Updated while Updating', async () => { + renderItemModal(link2, itemProps[1]); + // Click Submit + const submitButton = screen.getByTestId('submitBtn'); + expect(submitButton).toBeInTheDocument(); + fireEvent.click(submitButton); + + await waitFor(() => { + expect(toast.warning).toHaveBeenCalledWith(t.noneUpdated); + }); + }); + + it('should fail to Update Action Item', async () => { + renderItemModal(link2, itemProps[1]); + expect(screen.getAllByText(t.updateActionItem)).toHaveLength(2); + + // Update Post Completion Notes + fireEvent.change(screen.getByLabelText(t.postCompletionNotes), { + target: { value: 'Cmp Notes 2' }, + }); + + // Click Submit + const submitButton = screen.getByTestId('submitBtn'); + expect(submitButton).toBeInTheDocument(); + fireEvent.click(submitButton); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalledWith('Mock Graphql Error'); + }); + }); +}); diff --git a/src/screens/OrganizationActionItems/ItemModal.tsx b/src/screens/OrganizationActionItems/ItemModal.tsx new file mode 100644 index 0000000000..d7a38ee0df --- /dev/null +++ b/src/screens/OrganizationActionItems/ItemModal.tsx @@ -0,0 +1,440 @@ +import React, { useEffect, useMemo, useState } from 'react'; +import { Modal, Form, Button } from 'react-bootstrap'; +import type { ChangeEvent, FC } from 'react'; +import styles from './OrganizationActionItems.module.css'; +import { DatePicker } from '@mui/x-date-pickers'; +import dayjs from 'dayjs'; +import type { Dayjs } from 'dayjs'; + +import type { + InterfaceActionItemCategoryInfo, + InterfaceActionItemCategoryList, + InterfaceActionItemInfo, + InterfaceMemberInfo, + InterfaceMembersList, +} from 'utils/interfaces'; +import { useTranslation } from 'react-i18next'; +import { toast } from 'react-toastify'; +import { useMutation, useQuery } from '@apollo/client'; +import { + CREATE_ACTION_ITEM_MUTATION, + UPDATE_ACTION_ITEM_MUTATION, +} from 'GraphQl/Mutations/ActionItemMutations'; +import { ACTION_ITEM_CATEGORY_LIST } from 'GraphQl/Queries/ActionItemCategoryQueries'; +import { MEMBERS_LIST } from 'GraphQl/Queries/Queries'; +import { Autocomplete, FormControl, TextField } from '@mui/material'; + +/** + * Interface for the form state used in the `ItemModal` component. + */ +interface InterfaceFormStateType { + dueDate: Date; + actionItemCategoryId: string; + assigneeId: string; + eventId?: string; + preCompletionNotes: string; + postCompletionNotes: string | null; + allotedHours: number | null; + isCompleted: boolean; +} + +/** + * Props for the `ItemModal` component. + */ +export interface InterfaceItemModalProps { + isOpen: boolean; + hide: () => void; + orgId: string; + actionItemsRefetch: () => void; + actionItem: InterfaceActionItemInfo | null; + editMode: boolean; +} + +/** + * Initializes the form state for the `ItemModal` component. + * + * @param actionItem - The action item to be edited. + * @returns + */ + +const initializeFormState = ( + actionItem: InterfaceActionItemInfo | null, +): InterfaceFormStateType => ({ + dueDate: actionItem?.dueDate || new Date(), + actionItemCategoryId: actionItem?.actionItemCategory?._id || '', + assigneeId: actionItem?.assignee._id || '', + preCompletionNotes: actionItem?.preCompletionNotes || '', + postCompletionNotes: actionItem?.postCompletionNotes || null, + allotedHours: actionItem?.allotedHours || null, + isCompleted: actionItem?.isCompleted || false, +}); + +/** + * A modal component for creating action items. + * + * @param props - The properties passed to the component. + * @returns The `ItemModal` component. + */ +const ItemModal: FC = ({ + isOpen, + hide, + orgId, + actionItem, + editMode, + actionItemsRefetch, +}) => { + const { t } = useTranslation('translation', { + keyPrefix: 'organizationActionItems', + }); + + const [actionItemCategory, setActionItemCategory] = + useState(null); + const [assignee, setAssignee] = useState(null); + + const [formState, setFormState] = useState( + initializeFormState(actionItem), + ); + + const { + dueDate, + actionItemCategoryId, + assigneeId, + preCompletionNotes, + postCompletionNotes, + allotedHours, + isCompleted, + } = formState; + + /** + * Query to fetch action item categories for the organization. + */ + const { + data: actionItemCategoriesData, + }: { + data: InterfaceActionItemCategoryList | undefined; + } = useQuery(ACTION_ITEM_CATEGORY_LIST, { + variables: { + organizationId: orgId, + where: { is_disabled: false }, + }, + }); + + /** + * Query to fetch members of the organization. + */ + const { + data: membersData, + }: { + data: InterfaceMembersList | undefined; + } = useQuery(MEMBERS_LIST, { + variables: { id: orgId }, + }); + + const actionItemCategories = useMemo( + () => actionItemCategoriesData?.actionItemCategoriesByOrganization || [], + [actionItemCategoriesData], + ); + + const members = useMemo( + () => membersData?.organizations[0].members || [], + [membersData], + ); + + /** + * Mutation to create & update a new action item. + */ + const [createActionItem] = useMutation(CREATE_ACTION_ITEM_MUTATION); + const [updateActionItem] = useMutation(UPDATE_ACTION_ITEM_MUTATION); + + /** + * Handler function to update the form state. + * + * @param field - The field to be updated. + * @param value - The value to be set. + * @returns void + */ + const handleFormChange = ( + field: keyof InterfaceFormStateType, + value: string | number | boolean | Date | undefined | null, + ): void => { + setFormState((prevState) => ({ ...prevState, [field]: value })); + }; + + /** + * Handler function to create a new action item. + * + * @param e - The form submit event. + * @returns A promise that resolves when the action item is created. + */ + const createActionItemHandler = async ( + e: ChangeEvent, + ): Promise => { + e.preventDefault(); + try { + await createActionItem({ + variables: { + assigneeId: assignee?._id, + actionItemCategoryId: actionItemCategory?._id, + preCompletionNotes: preCompletionNotes, + allotedHours: allotedHours, + dueDate: dayjs(dueDate).format('YYYY-MM-DD'), + }, + }); + + // Reset form and date after successful creation + setFormState(initializeFormState(null)); + setActionItemCategory(null); + setAssignee(null); + + actionItemsRefetch(); + hide(); + toast.success(t('successfulCreation')); + } catch (error: unknown) { + toast.error((error as Error).message); + } + }; + + /** + * Handles the form submission for updating an action item. + * + * @param e - The form submission event. + */ + const updateActionItemHandler = async ( + e: ChangeEvent, + ): Promise => { + e.preventDefault(); + try { + const updatedFields: { + [key: string]: number | string | boolean | Date | undefined | null; + } = {}; + + if (actionItemCategoryId !== actionItem?.actionItemCategory?._id) { + updatedFields.actionItemCategoryId = actionItemCategoryId; + } + if (assigneeId !== actionItem?.assignee._id) { + updatedFields.assigneeId = assigneeId; + } + + if (preCompletionNotes !== actionItem?.preCompletionNotes) { + updatedFields.preCompletionNotes = preCompletionNotes; + } + + if (postCompletionNotes !== actionItem?.postCompletionNotes) { + updatedFields.postCompletionNotes = postCompletionNotes; + } + + if (allotedHours !== actionItem?.allotedHours) { + updatedFields.allotedHours = allotedHours; + } + + if (dueDate !== actionItem?.dueDate) { + updatedFields.dueDate = dayjs(dueDate).format('YYYY-MM-DD'); + } + + if (Object.keys(updatedFields).length === 0) { + toast.warning(t('noneUpdated')); + return; + } + + await updateActionItem({ + variables: { + actionItemId: actionItem?._id, + assigneeId: assigneeId, + ...updatedFields, + }, + }); + + setFormState(initializeFormState(null)); + actionItemsRefetch(); + hide(); + toast.success(t('successfulUpdation')); + } catch (error: unknown) { + toast.error((error as Error).message); + } + }; + + useEffect(() => { + setFormState(initializeFormState(actionItem)); + setActionItemCategory( + actionItemCategories.find( + (category) => category._id === actionItem?.actionItemCategory?._id, + ) || null, + ); + setAssignee( + members.find((member) => member._id === actionItem?.assignee._id) || null, + ); + }, [actionItem, actionItemCategories, members]); + + return ( + + +

    + {editMode ? t('updateActionItem') : t('createActionItem')} +

    + +
    + +
    + + option._id === value._id} + filterSelectedOptions={true} + getOptionLabel={(item: InterfaceActionItemCategoryInfo): string => + item.name + } + onChange={(_, newCategory): void => { + /* istanbul ignore next */ + handleFormChange( + 'actionItemCategoryId', + newCategory?._id ?? '', + ); + setActionItemCategory(newCategory); + }} + renderInput={(params) => ( + + )} + /> + {isCompleted && ( + <> + {/* Input text Component to add alloted Hours for action item */} + + + handleFormChange( + 'allotedHours', + e.target.value === '' || parseInt(e.target.value) < 0 + ? null + : parseInt(e.target.value), + ) + } + /> + + + )} + + {!isCompleted && ( + <> + + + option._id === value._id + } + filterSelectedOptions={true} + getOptionLabel={(member: InterfaceMemberInfo): string => + `${member.firstName} ${member.lastName}` + } + onChange={(_, newAssignee): void => { + /* istanbul ignore next */ + handleFormChange('assigneeId', newAssignee?._id ?? ''); + setAssignee(newAssignee); + }} + renderInput={(params) => ( + + )} + /> + + + + {/* Date Calendar Component to select due date of an action item */} + { + /* istanbul ignore next */ + if (date) handleFormChange('dueDate', date.toDate()); + }} + /> + + {/* Input text Component to add alloted Hours for action item */} + + + handleFormChange( + 'allotedHours', + e.target.value === '' || parseInt(e.target.value) < 0 + ? null + : parseInt(e.target.value), + ) + } + /> + + + + {/* Input text Component to add notes for action item */} + + + handleFormChange('preCompletionNotes', e.target.value) + } + /> + + + )} + + {isCompleted && ( + + + handleFormChange('postCompletionNotes', e.target.value) + } + /> + + )} + + +
    +
    +
    + ); +}; + +export default ItemModal; diff --git a/src/screens/OrganizationActionItems/ItemUpdateStatusModal.test.tsx b/src/screens/OrganizationActionItems/ItemUpdateStatusModal.test.tsx new file mode 100644 index 0000000000..c1fee119cc --- /dev/null +++ b/src/screens/OrganizationActionItems/ItemUpdateStatusModal.test.tsx @@ -0,0 +1,173 @@ +import React from 'react'; +import type { ApolloLink } from '@apollo/client'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import type { RenderResult } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import i18nForTest from '../../utils/i18nForTest'; +import { MOCKS, MOCKS_ERROR } from './OrganizationActionItem.mocks'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { toast } from 'react-toastify'; +import ItemUpdateStatusModal, { + type InterfaceItemUpdateStatusModalProps, +} from './ItemUpdateStatusModal'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(MOCKS_ERROR); +const t = JSON.parse( + JSON.stringify( + i18nForTest.getDataByLanguage('en')?.translation.organizationActionItems, + ), +); + +const itemProps: InterfaceItemUpdateStatusModalProps[] = [ + { + isOpen: true, + hide: jest.fn(), + actionItemsRefetch: jest.fn(), + actionItem: { + _id: 'actionItemId1', + assignee: { + _id: 'userId1', + firstName: 'John', + lastName: 'Doe', + image: null, + }, + actionItemCategory: { + _id: 'actionItemCategoryId1', + name: 'Category 1', + }, + preCompletionNotes: 'Notes 1', + postCompletionNotes: 'Cmp Notes 1', + assignmentDate: new Date('2024-08-27'), + dueDate: new Date('2044-08-30'), + completionDate: new Date('2044-09-03'), + isCompleted: true, + event: null, + allotedHours: 24, + assigner: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + creator: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + }, + { + isOpen: true, + hide: jest.fn(), + actionItemsRefetch: jest.fn(), + actionItem: { + _id: 'actionItemId1', + assignee: { + _id: 'userId1', + firstName: 'John', + lastName: 'Doe', + image: null, + }, + actionItemCategory: { + _id: 'actionItemCategoryId1', + name: 'Category 1', + }, + preCompletionNotes: 'Notes 1', + postCompletionNotes: null, + assignmentDate: new Date('2024-08-27'), + dueDate: new Date('2044-08-30'), + completionDate: new Date('2044-09-03'), + isCompleted: false, + event: null, + allotedHours: 24, + assigner: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + creator: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + }, +]; + +const renderItemUpdateStatusModal = ( + link: ApolloLink, + props: InterfaceItemUpdateStatusModalProps, +): RenderResult => { + return render( + + + + + + + + + + + , + ); +}; + +describe('Testing ItemUpdateStatusModal', () => { + it('Update Status of Completed ActionItem', async () => { + renderItemUpdateStatusModal(link1, itemProps[0]); + expect(screen.getByText(t.actionItemStatus)).toBeInTheDocument(); + const yesBtn = await screen.findByTestId('yesBtn'); + fireEvent.click(yesBtn); + + await waitFor(() => { + expect(itemProps[0].actionItemsRefetch).toHaveBeenCalled(); + expect(itemProps[0].hide).toHaveBeenCalled(); + expect(toast.success).toHaveBeenCalledWith(t.successfulUpdation); + }); + }); + + it('Update Status of Pending ActionItem', async () => { + renderItemUpdateStatusModal(link1, itemProps[1]); + expect(screen.getByText(t.actionItemStatus)).toBeInTheDocument(); + + const notes = await screen.findByLabelText(t.postCompletionNotes); + fireEvent.change(notes, { target: { value: 'Cmp Notes 1' } }); + + const createBtn = await screen.findByTestId('createBtn'); + fireEvent.click(createBtn); + + await waitFor(() => { + expect(itemProps[1].actionItemsRefetch).toHaveBeenCalled(); + expect(itemProps[1].hide).toHaveBeenCalled(); + expect(toast.success).toHaveBeenCalledWith(t.successfulUpdation); + }); + }); + + it('should fail to Update status of Action Item', async () => { + renderItemUpdateStatusModal(link2, itemProps[0]); + + expect(screen.getByText(t.actionItemStatus)).toBeInTheDocument(); + const yesBtn = await screen.findByTestId('yesBtn'); + fireEvent.click(yesBtn); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalledWith('Mock Graphql Error'); + }); + }); +}); diff --git a/src/screens/OrganizationActionItems/ItemUpdateStatusModal.tsx b/src/screens/OrganizationActionItems/ItemUpdateStatusModal.tsx new file mode 100644 index 0000000000..44ac0e63e6 --- /dev/null +++ b/src/screens/OrganizationActionItems/ItemUpdateStatusModal.tsx @@ -0,0 +1,129 @@ +import React, { type FC, type FormEvent, useEffect, useState } from 'react'; +import { Modal, Button, Form } from 'react-bootstrap'; +import { useTranslation } from 'react-i18next'; +import { FormControl, TextField } from '@mui/material'; +import styles from './OrganizationActionItems.module.css'; +import { useMutation } from '@apollo/client'; +import { UPDATE_ACTION_ITEM_MUTATION } from 'GraphQl/Mutations/ActionItemMutations'; +import { toast } from 'react-toastify'; +import type { InterfaceActionItemInfo } from 'utils/interfaces'; + +export interface InterfaceItemUpdateStatusModalProps { + isOpen: boolean; + hide: () => void; + actionItemsRefetch: () => void; + actionItem: InterfaceActionItemInfo | null; +} + +const ItemUpdateStatusModal: FC = ({ + hide, + isOpen, + actionItemsRefetch, + actionItem, +}) => { + const { t } = useTranslation('translation', { + keyPrefix: 'organizationActionItems', + }); + const { t: tCommon } = useTranslation('common'); + + const [isCompleted, setIsCompleted] = useState( + actionItem?.isCompleted ?? false, + ); + const [postCompletionNotes, setPostCompletionNotes] = useState( + actionItem?.postCompletionNotes ?? '', + ); + + /** + * Mutation to update an action item. + */ + const [updateActionItem] = useMutation(UPDATE_ACTION_ITEM_MUTATION); + + /** + * Handles the form submission for updating an action item. + * + * @param e - The form submission event. + */ + const updateActionItemHandler = async ( + e: FormEvent, + ): Promise => { + e.preventDefault(); + + try { + await updateActionItem({ + variables: { + actionItemId: actionItem?._id, + assigneeId: actionItem?.assignee?._id, + postCompletionNotes: isCompleted ? '' : postCompletionNotes, + isCompleted: !isCompleted, + }, + }); + + actionItemsRefetch(); + hide(); + toast.success(t('successfulUpdation')); + } catch (error: unknown) { + toast.error((error as Error).message); + } + }; + + useEffect(() => { + if (actionItem) { + setIsCompleted(actionItem?.isCompleted); + setPostCompletionNotes(actionItem?.postCompletionNotes ?? ''); + } + }, [actionItem]); + + return ( + + +

    {t('actionItemStatus')}

    + +
    + +
    + {!isCompleted ? ( + + setPostCompletionNotes(e.target.value)} + /> + + ) : ( +

    {t('updateStatusMsg')}

    + )} + + {isCompleted ? ( +
    + + +
    + ) : ( + + )} +
    +
    +
    + ); +}; + +export default ItemUpdateStatusModal; diff --git a/src/screens/OrganizationActionItems/ItemViewModal.test.tsx b/src/screens/OrganizationActionItems/ItemViewModal.test.tsx new file mode 100644 index 0000000000..13c208b854 --- /dev/null +++ b/src/screens/OrganizationActionItems/ItemViewModal.test.tsx @@ -0,0 +1,147 @@ +import React from 'react'; +import type { ApolloLink } from '@apollo/client'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import type { RenderResult } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import i18nForTest from '../../utils/i18nForTest'; +import { MOCKS } from './OrganizationActionItem.mocks'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import ItemViewModal, { type InterfaceViewModalProps } from './ItemViewModal'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +const link1 = new StaticMockLink(MOCKS); +const t = JSON.parse( + JSON.stringify( + i18nForTest.getDataByLanguage('en')?.translation.organizationActionItems, + ), +); + +const itemProps: InterfaceViewModalProps[] = [ + { + isOpen: true, + hide: jest.fn(), + item: { + _id: 'actionItemId1', + assignee: { + _id: 'userId1', + firstName: 'John', + lastName: 'Doe', + image: null, + }, + actionItemCategory: { + _id: 'actionItemCategoryId1', + name: 'Category 1', + }, + preCompletionNotes: 'Notes 1', + postCompletionNotes: 'Cmp Notes 1', + assignmentDate: new Date('2024-08-27'), + dueDate: new Date('2044-08-30'), + completionDate: new Date('2044-09-03'), + isCompleted: true, + event: null, + allotedHours: 24, + assigner: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + creator: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + }, + { + isOpen: true, + hide: jest.fn(), + item: { + _id: 'actionItemId2', + assignee: { + _id: 'userId1', + firstName: 'Jane', + lastName: 'Doe', + image: 'image-url', + }, + actionItemCategory: { + _id: 'actionItemCategoryId2', + name: 'Category 2', + }, + preCompletionNotes: 'Notes 2', + postCompletionNotes: null, + assignmentDate: new Date('2024-08-27'), + dueDate: new Date('2044-09-30'), + completionDate: new Date('2044-10-03'), + isCompleted: false, + event: null, + allotedHours: null, + assigner: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + image: 'wilt-image', + }, + creator: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + }, +]; + +const renderItemViewModal = ( + link: ApolloLink, + props: InterfaceViewModalProps, +): RenderResult => { + return render( + + + + + + + + + + + , + ); +}; + +describe('Testing ItemViewModal', () => { + it('should render ItemViewModal with pending item & assignee with null image', () => { + renderItemViewModal(link1, itemProps[0]); + expect(screen.getByText(t.actionItemDetails)).toBeInTheDocument(); + expect(screen.getByTestId('John_avatar')).toBeInTheDocument(); + expect(screen.getByTestId('Wilt_avatar')).toBeInTheDocument(); + expect(screen.getByLabelText(t.postCompletionNotes)).toBeInTheDocument(); + expect(screen.getByLabelText(t.allotedHours)).toBeInTheDocument(); + expect(screen.getByLabelText(t.allotedHours)).toHaveValue('24'); + }); + + it('should render ItemViewModal with completed item & assignee with null image', () => { + renderItemViewModal(link1, itemProps[1]); + expect(screen.getByText(t.actionItemDetails)).toBeInTheDocument(); + expect(screen.getByTestId('Jane_image')).toBeInTheDocument(); + expect(screen.getByTestId('Wilt_image')).toBeInTheDocument(); + expect( + screen.queryByLabelText(t.postCompletionNotes), + ).not.toBeInTheDocument(); + expect(screen.getByLabelText(t.allotedHours)).toBeInTheDocument(); + expect(screen.getByLabelText(t.allotedHours)).toHaveValue('-'); + }); +}); diff --git a/src/screens/OrganizationActionItems/ItemViewModal.tsx b/src/screens/OrganizationActionItems/ItemViewModal.tsx new file mode 100644 index 0000000000..84d9a3e7fe --- /dev/null +++ b/src/screens/OrganizationActionItems/ItemViewModal.tsx @@ -0,0 +1,233 @@ +import { DatePicker } from '@mui/x-date-pickers'; +import React from 'react'; +import dayjs from 'dayjs'; +import type { FC } from 'react'; +import { Button, Form, Modal } from 'react-bootstrap'; +import type { InterfaceActionItemInfo } from 'utils/interfaces'; +import styles from './OrganizationActionItems.module.css'; +import { useTranslation } from 'react-i18next'; +import { FormControl, TextField } from '@mui/material'; +import { TaskAlt, HistoryToggleOff } from '@mui/icons-material'; +import Avatar from 'components/Avatar/Avatar'; + +export interface InterfaceViewModalProps { + isOpen: boolean; + hide: () => void; + item: InterfaceActionItemInfo; +} + +/** + * A modal dialog for viewing action item details. + * + * @param isOpen - Indicates whether the modal is open. + * @param hide - Function to close the modal. + * @param item - The action item object to be displayed. + * + * @returns The rendered modal component. + * + * The `ItemViewModal` component displays all the fields of an action item in a modal dialog. + * It includes fields for assignee, assigner, category, pre and post completion notes, assignment date, due date, completion date, and event. + */ + +const ItemViewModal: FC = ({ isOpen, hide, item }) => { + const { t } = useTranslation('translation', { + keyPrefix: 'organizationActionItems', + }); + const { t: tCommon } = useTranslation('common'); + + const { + actionItemCategory, + assignee, + assigner, + completionDate, + dueDate, + isCompleted, + postCompletionNotes, + preCompletionNotes, + allotedHours, + } = item; + + return ( + + +

    {t('actionItemDetails')}

    + +
    + +
    + + + + + + + + + {assignee.image ? ( + Assignee + ) : ( +
    + +
    + )} + + ), + }} + /> +
    + + + {assigner.image ? ( + Assignee + ) : ( +
    + +
    + )} + + ), + }} + /> +
    +
    + + {/* Status of Action Item */} + + {isCompleted ? ( + + ) : ( + + )} + + ), + style: { + color: isCompleted ? 'green' : '#ed6c02', + }, + }} + inputProps={{ + style: { + WebkitTextFillColor: isCompleted ? 'green' : '#ed6c02', + }, + }} + disabled + /> + + + + + {/* Date Calendar Component to display due date of Action Item */} + + + {/* Date Calendar Component to display completion Date of Action Item */} + {isCompleted && ( + + )} + + + + + + + {isCompleted && ( + + + + )} +
    +
    +
    + ); +}; +export default ItemViewModal; diff --git a/src/screens/OrganizationActionItems/OrganizationActionItem.mocks.ts b/src/screens/OrganizationActionItems/OrganizationActionItem.mocks.ts new file mode 100644 index 0000000000..0a324d39ac --- /dev/null +++ b/src/screens/OrganizationActionItems/OrganizationActionItem.mocks.ts @@ -0,0 +1,482 @@ +import dayjs from 'dayjs'; +import { + CREATE_ACTION_ITEM_MUTATION, + DELETE_ACTION_ITEM_MUTATION, + UPDATE_ACTION_ITEM_MUTATION, +} from 'GraphQl/Mutations/ActionItemMutations'; +import { + ACTION_ITEM_CATEGORY_LIST, + ACTION_ITEM_LIST, + MEMBERS_LIST, +} from 'GraphQl/Queries/Queries'; +import { act } from 'react-dom/test-utils'; + +const baseActionItem = { + assigner: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + creator: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + __typename: 'User', + }, +}; + +const actionItem1 = { + _id: 'actionItemId1', + assignee: { + _id: 'userId1', + firstName: 'John', + lastName: 'Doe', + image: null, + }, + actionItemCategory: { + _id: 'actionItemCategoryId1', + name: 'Category 1', + }, + preCompletionNotes: 'Notes 1', + postCompletionNotes: 'Cmp Notes 1', + assignmentDate: '2024-08-27', + dueDate: '2044-08-30', + completionDate: '2044-09-03', + isCompleted: true, + event: null, + allotedHours: 24, + ...baseActionItem, +}; + +const actionItem2 = { + _id: 'actionItemId2', + assignee: { + _id: 'userId1', + firstName: 'Jane', + lastName: 'Doe', + image: 'image-url', + }, + actionItemCategory: { + _id: 'actionItemCategoryId2', + name: 'Category 2', + }, + preCompletionNotes: 'Notes 2', + postCompletionNotes: null, + assignmentDate: '2024-08-27', + dueDate: '2044-09-30', + completionDate: '2044-10-03', + isCompleted: false, + event: null, + allotedHours: null, + ...baseActionItem, +}; + +const memberListQuery = { + request: { + query: MEMBERS_LIST, + variables: { id: 'orgId' }, + }, + result: { + data: { + organizations: [ + { + _id: 'orgId', + members: [ + { + _id: 'userId1', + firstName: 'Harve', + lastName: 'Lance', + email: 'harve@example.com', + image: '', + organizationsBlockedBy: [], + createdAt: '2024-02-14', + }, + { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'wilt@example.com', + image: '', + organizationsBlockedBy: [], + createdAt: '2024-02-14', + }, + ], + }, + ], + }, + }, +}; + +const actionItemCategoryListQuery = { + request: { + query: ACTION_ITEM_CATEGORY_LIST, + variables: { + organizationId: 'orgId', + where: { is_disabled: false }, + }, + }, + result: { + data: { + actionItemCategoriesByOrganization: [ + { + _id: 'categoryId1', + name: 'Category 1', + isDisabled: false, + createdAt: '2024-08-26', + creator: { + _id: 'creatorId1', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + { + _id: 'categoryId2', + name: 'Category 2', + isDisabled: true, + createdAt: '2024-08-25', + creator: { + _id: 'creatorId2', + firstName: 'John', + lastName: 'Doe', + }, + }, + ], + }, + }, +}; + +export const MOCKS = [ + { + request: { + query: ACTION_ITEM_LIST, + variables: { + organizationId: 'orgId', + orderBy: null, + where: { + assigneeName: '', + }, + }, + }, + result: { + data: { + actionItemsByOrganization: [actionItem1, actionItem2], + }, + }, + }, + { + request: { + query: ACTION_ITEM_LIST, + variables: { + organizationId: 'orgId', + orderBy: null, + where: { + categoryName: '', + }, + }, + }, + result: { + data: { + actionItemsByOrganization: [actionItem1, actionItem2], + }, + }, + }, + { + request: { + query: ACTION_ITEM_LIST, + variables: { + organizationId: 'orgId', + orderBy: 'dueDate_ASC', + where: { + assigneeName: '', + }, + }, + }, + result: { + data: { + actionItemsByOrganization: [actionItem1, actionItem2], + }, + }, + }, + { + request: { + query: ACTION_ITEM_LIST, + variables: { + organizationId: 'orgId', + orderBy: 'dueDate_DESC', + where: { + assigneeName: '', + }, + }, + }, + result: { + data: { + actionItemsByOrganization: [actionItem2, actionItem1], + }, + }, + }, + { + request: { + query: ACTION_ITEM_LIST, + variables: { + organizationId: 'orgId', + orderBy: null, + where: { + assigneeName: '', + is_completed: true, + }, + }, + }, + result: { + data: { + actionItemsByOrganization: [actionItem1], + }, + }, + }, + { + request: { + query: ACTION_ITEM_LIST, + variables: { + organizationId: 'orgId', + orderBy: null, + where: { + assigneeName: '', + is_completed: false, + }, + }, + }, + result: { + data: { + actionItemsByOrganization: [actionItem2], + }, + }, + }, + { + request: { + query: ACTION_ITEM_LIST, + variables: { + organizationId: 'orgId', + orderBy: null, + where: { + assigneeName: 'John', + }, + }, + }, + result: { + data: { + actionItemsByOrganization: [actionItem1], + }, + }, + }, + { + request: { + query: ACTION_ITEM_LIST, + variables: { + organizationId: 'orgId', + orderBy: null, + where: { + categoryName: 'Category 1', + }, + }, + }, + result: { + data: { + actionItemsByOrganization: [actionItem1], + }, + }, + }, + { + request: { + query: DELETE_ACTION_ITEM_MUTATION, + variables: { + actionItemId: 'actionItemId1', + }, + }, + result: { + data: { + removeActionItem: { + _id: 'actionItemId1', + }, + }, + }, + }, + { + request: { + query: UPDATE_ACTION_ITEM_MUTATION, + variables: { + actionItemId: 'actionItemId1', + assigneeId: 'userId1', + postCompletionNotes: '', + isCompleted: false, + }, + }, + result: { + data: { + updateActionItem: { + _id: 'actionItemId1', + }, + }, + }, + }, + { + request: { + query: UPDATE_ACTION_ITEM_MUTATION, + variables: { + actionItemId: 'actionItemId1', + assigneeId: 'userId1', + actionItemCategoryId: 'categoryId2', + postCompletionNotes: 'Cmp Notes 2', + allotedHours: 19, + }, + }, + result: { + data: { + updateActionItem: { + _id: 'actionItemId1', + }, + }, + }, + }, + { + request: { + query: UPDATE_ACTION_ITEM_MUTATION, + variables: { + actionItemId: 'actionItemId2', + assigneeId: 'userId1', + actionItemCategoryId: 'categoryId1', + preCompletionNotes: 'Notes 3', + allotedHours: 19, + dueDate: '2044-01-02', + }, + }, + result: { + data: { + updateActionItem: { + _id: 'actionItemId1', + }, + }, + }, + }, + { + request: { + query: UPDATE_ACTION_ITEM_MUTATION, + variables: { + actionItemId: 'actionItemId1', + assigneeId: 'userId1', + postCompletionNotes: 'Cmp Notes 1', + isCompleted: true, + }, + }, + result: { + data: { + updateActionItem: { + _id: 'actionItemId1', + }, + }, + }, + }, + { + request: { + query: CREATE_ACTION_ITEM_MUTATION, + variables: { + assigneeId: 'userId1', + actionItemCategoryId: 'categoryId1', + preCompletionNotes: 'Notes', + allotedHours: 9, + dueDate: '2044-01-02', + }, + }, + result: { + data: { + createActionItem: { + _id: 'actionItemId1', + }, + }, + }, + }, + memberListQuery, + actionItemCategoryListQuery, +]; + +export const MOCKS_ERROR = [ + { + request: { + query: ACTION_ITEM_LIST, + variables: { + organizationId: 'orgId', + orderBy: null, + where: { + assigneeName: '', + }, + }, + }, + error: new Error('Mock Graphql Error'), + }, + { + request: { + query: DELETE_ACTION_ITEM_MUTATION, + variables: { + actionItemId: 'actionItemId1', + }, + }, + error: new Error('Mock Graphql Error'), + }, + { + request: { + query: UPDATE_ACTION_ITEM_MUTATION, + variables: { + actionItemId: 'actionItemId1', + assigneeId: 'userId1', + postCompletionNotes: '', + isCompleted: false, + }, + }, + error: new Error('Mock Graphql Error'), + }, + { + request: { + query: CREATE_ACTION_ITEM_MUTATION, + variables: { + preCompletionNotes: '', + allotedHours: null, + dueDate: dayjs().format('YYYY-MM-DD'), + }, + }, + error: new Error('Mock Graphql Error'), + }, + { + request: { + query: UPDATE_ACTION_ITEM_MUTATION, + variables: { + actionItemId: 'actionItemId1', + assigneeId: 'userId1', + postCompletionNotes: 'Cmp Notes 2', + }, + }, + error: new Error('Mock Graphql Error'), + }, + memberListQuery, + actionItemCategoryListQuery, +]; + +export const MOCKS_EMPTY = [ + { + request: { + query: ACTION_ITEM_LIST, + variables: { + organizationId: 'orgId', + orderBy: null, + where: { + assigneeName: '', + }, + }, + }, + result: { + data: { + actionItemsByOrganization: [], + }, + }, + }, + memberListQuery, + actionItemCategoryListQuery, +]; diff --git a/src/screens/OrganizationActionItems/OrganizationActionItemMocks.ts b/src/screens/OrganizationActionItems/OrganizationActionItemMocks.ts deleted file mode 100644 index acbb243e5d..0000000000 --- a/src/screens/OrganizationActionItems/OrganizationActionItemMocks.ts +++ /dev/null @@ -1,417 +0,0 @@ -import { CREATE_ACTION_ITEM_MUTATION } from 'GraphQl/Mutations/mutations'; - -import { - ACTION_ITEM_CATEGORY_LIST, - ACTION_ITEM_LIST, - MEMBERS_LIST, -} from 'GraphQl/Queries/Queries'; - -export const MOCKS = [ - { - request: { - query: ACTION_ITEM_CATEGORY_LIST, - variables: { organizationId: '123' }, - }, - result: { - data: { - actionItemCategoriesByOrganization: [ - { - _id: 'actionItemCategory1', - name: 'ActionItemCategory 1', - isDisabled: false, - }, - ], - }, - }, - }, - { - request: { - query: MEMBERS_LIST, - variables: { id: '123' }, - }, - result: { - data: { - organizations: [ - { - _id: '123', - members: [ - { - _id: 'user1', - firstName: 'Harve', - lastName: 'Lance', - email: 'harve@example.com', - image: '', - organizationsBlockedBy: [], - createdAt: '2024-02-14', - }, - ], - }, - ], - }, - }, - }, - { - request: { - query: ACTION_ITEM_LIST, - variables: { - organizationId: '123', - orderBy: 'createdAt_DESC', - actionItemCategoryId: '', - isActive: false, - isCompleted: false, - }, - }, - result: { - data: { - actionItemsByOrganization: [ - { - _id: 'actionItem1', - assignee: { - _id: 'user1', - firstName: 'Harve', - lastName: 'Lance', - }, - actionItemCategory: { - _id: 'actionItemCategory1', - name: 'ActionItemCategory 1', - }, - preCompletionNotes: 'Pre Completion Notes', - postCompletionNotes: 'Post Completion Notes', - assignmentDate: '2024-02-14', - dueDate: '2024-02-21', - completionDate: '2024-02-21', - isCompleted: false, - assigner: { - _id: 'user0', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - event: { - _id: 'event1', - title: 'event 1', - }, - creator: { - _id: 'user0', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - }, - { - _id: 'actionItem2', - assignee: { - _id: 'user2', - firstName: 'John', - lastName: 'Doe', - }, - actionItemCategory: { - _id: 'actionItemCategory2', - name: 'ActionItemCategory 2', - }, - preCompletionNotes: 'Pre Completion Notes', - postCompletionNotes: 'Post Completion Notes', - assignmentDate: '2024-02-14', - dueDate: '2024-02-21', - completionDate: '2024-02-21', - isCompleted: false, - assigner: { - _id: 'user0', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - event: null, - creator: { - _id: 'user0', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - }, - ], - }, - }, - }, - { - request: { - query: ACTION_ITEM_LIST, - variables: { - organizationId: '123', - eventId: 'event1', - orderBy: 'createdAt_DESC', - }, - }, - result: { - data: { - actionItemsByOrganization: [ - { - _id: 'actionItem1', - assignee: { - _id: 'user1', - firstName: 'Harve', - lastName: 'Lance', - }, - actionItemCategory: { - _id: 'actionItemCategory1', - name: 'ActionItemCategory 1', - }, - preCompletionNotes: 'Pre Completion Notes', - postCompletionNotes: 'Post Completion Notes', - assignmentDate: '2024-02-14', - dueDate: '2024-02-21', - completionDate: '2024-02-21', - isCompleted: false, - assigner: { - _id: 'user0', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - event: { - _id: 'event1', - title: 'event 1', - }, - creator: { - _id: 'user0', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - }, - ], - }, - }, - }, - { - request: { - query: ACTION_ITEM_LIST, - variables: { - organizationId: '123', - orderBy: 'createdAt_ASC', - actionItemCategoryId: '', - isActive: false, - isCompleted: false, - }, - }, - result: { - data: { - actionItemsByOrganization: [ - { - _id: 'actionItem3', - assignee: { - _id: 'user1', - firstName: 'Praise', - lastName: 'Norris', - }, - actionItemCategory: { - _id: 'actionItemCategory3', - name: 'ActionItemCategory 3', - }, - preCompletionNotes: 'Pre Completion Notes', - postCompletionNotes: 'Post Completion Notes', - assignmentDate: '2024-02-14', - dueDate: '2024-02-21', - completionDate: '2024-02-21', - isCompleted: false, - assigner: { - _id: 'user0', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - event: { - _id: 'event1', - title: 'event 1', - }, - creator: { - _id: 'user0', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - }, - ], - }, - }, - }, - { - request: { - query: ACTION_ITEM_LIST, - variables: { - organizationId: '123', - orderBy: 'createdAt_ASC', - actionItemCategoryId: '', - isActive: true, - isCompleted: false, - }, - }, - result: { - data: { - actionItemsByOrganization: [ - { - _id: 'actionItem1', - assignee: { - _id: 'user1', - firstName: 'Harve', - lastName: 'Lance', - }, - actionItemCategory: { - _id: 'actionItemCategory1', - name: 'ActionItemCategory 1', - }, - preCompletionNotes: 'Pre Completion Notes', - postCompletionNotes: 'Post Completion Notes', - assignmentDate: '2024-02-14', - dueDate: '2024-02-21', - completionDate: '2024-02-21', - isCompleted: true, - assigner: { - _id: 'user0', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - event: { - _id: 'event1', - title: 'event 1', - }, - creator: { - _id: 'user0', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - }, - ], - }, - }, - }, - { - request: { - query: ACTION_ITEM_LIST, - variables: { - organizationId: '123', - orderBy: 'createdAt_ASC', - actionItemCategoryId: '', - isActive: false, - isCompleted: true, - }, - }, - result: { - data: { - actionItemsByOrganization: [ - { - _id: 'actionItem1', - assignee: { - _id: 'user1', - firstName: 'Harve', - lastName: 'Lance', - }, - actionItemCategory: { - _id: 'actionItemCategory1', - name: 'ActionItemCategory 1', - }, - preCompletionNotes: 'Pre Completion Notes', - postCompletionNotes: 'Post Completion Notes', - assignmentDate: '2024-02-14', - dueDate: '2024-02-21', - completionDate: '2024-02-21', - isCompleted: true, - assigner: { - _id: 'user0', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - event: { - _id: 'event1', - title: 'event 1', - }, - creator: { - _id: 'user0', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - }, - ], - }, - }, - }, - { - request: { - query: ACTION_ITEM_LIST, - variables: { - organizationId: '123', - orderBy: 'createdAt_ASC', - actionItemCategoryId: 'actionItemCategory1', - isActive: false, - isCompleted: true, - }, - }, - result: { - data: { - actionItemsByOrganization: [ - { - _id: 'actionItem1', - assignee: { - _id: 'user1', - firstName: 'Harve', - lastName: 'Lance', - }, - actionItemCategory: { - _id: 'actionItemCategory1', - name: 'ActionItemCategory 1', - }, - preCompletionNotes: 'Pre Completion Notes', - postCompletionNotes: 'Post Completion Notes', - assignmentDate: '2024-02-14', - dueDate: '2024-02-21', - completionDate: '2024-02-21', - isCompleted: true, - assigner: { - _id: 'user0', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - event: { - _id: 'event1', - title: 'event 1', - }, - creator: { - _id: 'user0', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - }, - ], - }, - }, - }, - { - request: { - query: CREATE_ACTION_ITEM_MUTATION, - variables: { - actionItemCategoryId: 'actionItemCategory1', - assigneeId: 'user1', - preCompletionNotes: 'pre completion notes', - dueDate: '2024-02-14', - }, - }, - result: { - data: { - createActionItem: { - _id: 'actionItem2', - }, - }, - }, - }, - { - request: { - query: CREATE_ACTION_ITEM_MUTATION, - variables: { - eventId: 'event1', - actionItemCategoryId: 'actionItemCategory1', - assigneeId: 'user1', - preCompletionNotes: 'pre completion notes', - dueDate: '2024-02-14', - }, - }, - result: { - data: { - createActionItem: { - _id: 'actionItem2', - }, - }, - }, - }, -]; diff --git a/src/screens/OrganizationActionItems/OrganizationActionItems.module.css b/src/screens/OrganizationActionItems/OrganizationActionItems.module.css index 7a67362c8b..48720ac902 100644 --- a/src/screens/OrganizationActionItems/OrganizationActionItems.module.css +++ b/src/screens/OrganizationActionItems/OrganizationActionItems.module.css @@ -8,26 +8,6 @@ margin-left: 13vw; } -.btnsContainer { - display: flex; - gap: 10px; -} - -.btnsContainer .btnsBlock { - display: flex; - gap: 10px; -} - -.btnsContainer button { - display: flex; - justify-content: center; - align-items: center; -} - -.container { - min-height: 100vh; -} - .datediv { display: flex; flex-direction: row; @@ -46,10 +26,6 @@ margin-left: 5px; } -.dropdown { - display: block; -} - .dropdownToggle { margin-bottom: 0; display: flex; @@ -108,10 +84,6 @@ hr { flex-direction: column; } -.organizationActionItemsContainer h2 { - margin: 0.6rem 0; -} - .preview { display: flex; flex-direction: row; @@ -128,16 +100,6 @@ hr { display: inline; } -.titlemodal { - color: var(--bs-gray-600); - font-weight: 600; - font-size: 20px; - margin-bottom: 20px; - padding-bottom: 5px; - border-bottom: 3px solid var(--bs-primary); - width: 65%; -} - .view { margin-left: 2%; font-weight: 600; @@ -145,24 +107,127 @@ hr { color: var(--bs-gray-600); } -@media (max-width: 767px) { - .btnsContainer { - margin-bottom: 0; - display: flex; - flex-direction: column; - } +/* header (search, filter, dropdown) */ +.btnsContainer { + display: flex; + margin: 0.5rem 0 1.5rem 0; +} + +.btnsContainer .input { + flex: 1; + min-width: 18rem; + position: relative; +} + +.btnsContainer input { + outline: 1px solid var(--bs-gray-400); +} + +.btnsContainer .input button { + width: 52px; +} + +.noOutline input { + outline: none; +} + +.noOutline input:disabled { + -webkit-text-fill-color: black !important; +} + +.noOutline textarea:disabled { + -webkit-text-fill-color: black !important; +} + +.inputField { + margin-top: 10px; + margin-bottom: 10px; + background-color: white; + box-shadow: 0 1px 1px #31bb6b; +} + +.inputField > button { + padding-top: 10px; + padding-bottom: 10px; +} - .btnsContainer .btnsBlock .dropdownToggle { - flex-grow: 1; - } +.dropdown { + background-color: white; + border: 1px solid #31bb6b; + position: relative; + display: inline-block; + color: #31bb6b; +} - .btnsContainer button { - width: 100%; - } +/* Action Items Data Grid */ +.rowBackground { + background-color: var(--bs-white); + max-height: 120px; +} + +.tableHeader { + background-color: var(--bs-primary); + color: var(--bs-white); + font-size: 1rem; +} + +.chipIcon { + height: 0.9rem !important; +} + +.chip { + height: 1.5rem !important; +} + +.active { + background-color: #31bb6a50 !important; +} + +.pending { + background-color: #ffd76950 !important; + color: #bb952bd0 !important; + border-color: #bb952bd0 !important; +} + +/* Modals */ +.itemModal { + max-width: 80vw; + margin-top: 2vh; + margin-left: 13vw; +} + +.titlemodal { + color: #707070; + font-weight: 600; + font-size: 32px; + width: 65%; + margin-bottom: 0px; +} + +.modalCloseBtn { + width: 40px; + height: 40px; + padding: 1rem; + display: flex; + justify-content: center; + align-items: center; +} + +.imageContainer { + display: flex; + align-items: center; + justify-content: center; + margin-right: 0.5rem; +} + +.TableImage { + object-fit: cover; + width: 25px !important; + height: 25px !important; + border-radius: 100% !important; +} - .createActionItemButton { - position: absolute; - top: 1rem; - right: 2rem; - } +.avatarContainer { + width: 28px; + height: 26px; } diff --git a/src/screens/OrganizationActionItems/OrganizationActionItems.test.tsx b/src/screens/OrganizationActionItems/OrganizationActionItems.test.tsx index 7a9060a892..c163ff9546 100644 --- a/src/screens/OrganizationActionItems/OrganizationActionItems.test.tsx +++ b/src/screens/OrganizationActionItems/OrganizationActionItems.test.tsx @@ -1,35 +1,23 @@ import React from 'react'; -import { - render, - screen, - fireEvent, - waitFor, - act, - waitForElementToBeRemoved, -} from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import type { RenderResult } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import 'jest-localstorage-mock'; -import { MockedProvider } from '@apollo/client/testing'; -import 'jest-location-mock'; import { I18nextProvider } from 'react-i18next'; import { Provider } from 'react-redux'; -import { BrowserRouter } from 'react-router-dom'; -import i18n from 'utils/i18nForTest'; -import { toast } from 'react-toastify'; -import { LocalizationProvider } from '@mui/x-date-pickers'; -import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; - +import { MemoryRouter, Route, Routes } from 'react-router-dom'; import { store } from 'state/store'; import { StaticMockLink } from 'utils/StaticMockLink'; - -import OrganizationActionItems from './OrganizationActionItems'; +import i18n from 'utils/i18nForTest'; +import OrganizationActionItems from 'screens/OrganizationActionItems/OrganizationActionItems'; +import type { ApolloLink } from '@apollo/client'; import { - MOCKS_ERROR_ACTION_ITEM_CATEGORY_LIST_QUERY, - MOCKS_ERROR_ACTION_ITEM_LIST_QUERY, - MOCKS_ERROR_MEMBERS_LIST_QUERY, - MOCKS_ERROR_MUTATIONS, -} from './OrganizationActionItemsErrorMocks'; -import { MOCKS } from './OrganizationActionItemMocks'; + MOCKS, + MOCKS_EMPTY, + MOCKS_ERROR, +} from './OrganizationActionItem.mocks'; jest.mock('react-toastify', () => ({ toast: { @@ -46,29 +34,10 @@ jest.mock('@mui/x-date-pickers/DateTimePicker', () => { }; }); -jest.mock('react-router-dom', () => ({ - ...jest.requireActual('react-router-dom'), - useParams: () => ({ orgId: '123' }), -})); - -async function wait(ms = 100): Promise { - await act(() => { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); - }); -} - -const link = new StaticMockLink(MOCKS, true); -const link2 = new StaticMockLink( - MOCKS_ERROR_ACTION_ITEM_CATEGORY_LIST_QUERY, - true, -); -const link3 = new StaticMockLink(MOCKS_ERROR_MEMBERS_LIST_QUERY, true); -const link4 = new StaticMockLink(MOCKS_ERROR_ACTION_ITEM_LIST_QUERY, true); -const link5 = new StaticMockLink(MOCKS_ERROR_MUTATIONS, true); - -const translations = { +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(MOCKS_ERROR); +const link3 = new StaticMockLink(MOCKS_EMPTY); +const t = { ...JSON.parse( JSON.stringify( i18n.getDataByLanguage('en')?.translation.organizationActionItems ?? {}, @@ -78,542 +47,331 @@ const translations = { ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), }; -describe('Testing Action Item Categories Component', () => { - const formData = { - actionItemCategory: 'ActionItemCategory 1', - assignee: 'Harve Lance', - preCompletionNotes: 'pre completion notes', - dueDate: '02/14/2024', - }; - - test('Component loads correctly', async () => { - const { getByText } = render( - +const renderOrganizationActionItems = (link: ApolloLink): RenderResult => { + return render( + + - + - {} + + } + /> +
    } + /> + -
    + - , - ); - - await wait(); + + , + ); +}; - await waitFor(() => { - expect(getByText(translations.create)).toBeInTheDocument(); - }); +describe('Testing Organization Action Items Screen', () => { + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId', eventId: 'eventId' }), + })); }); - test('render error component on unsuccessful action item category list query', async () => { - const { queryByText } = render( - - - - - {} - - - - , - ); - - await wait(); - - await waitFor(() => { - expect(queryByText(translations.create)).not.toBeInTheDocument(); - }); + afterAll(() => { + jest.clearAllMocks(); }); - test('render error component on unsuccessful members list query', async () => { - const { queryByText } = render( - - - + it('should redirect to fallback URL if URL params are undefined', async () => { + render( + + + - {} + + } + /> +
    } + /> + - - + + , ); - - await wait(); - await waitFor(() => { - expect(queryByText(translations.create)).not.toBeInTheDocument(); + expect(screen.getByTestId('paramsError')).toBeInTheDocument(); }); }); - test('render error component on unsuccessful action item list query', async () => { - const { queryByText } = render( - - - - - {} - - - - , - ); - - await wait(); - + it('should render Organization Action Items screen', async () => { + renderOrganizationActionItems(link1); await waitFor(() => { - expect(queryByText(translations.create)).not.toBeInTheDocument(); + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + expect(screen.getByText('John Doe')).toBeInTheDocument(); + expect(screen.getByText('Jane Doe')).toBeInTheDocument(); }); }); - test('sorts action items in earliest or latest first order based on orderBy', async () => { - render( - - - - - {} - - - - , - ); + it('Sort Action Items descending by dueDate', async () => { + renderOrganizationActionItems(link1); - await wait(); + const sortBtn = await screen.findByTestId('sort'); + expect(sortBtn).toBeInTheDocument(); + // Sort by dueDate_DESC + fireEvent.click(sortBtn); await waitFor(() => { - expect(screen.getByTestId('sortActionItems')).toBeInTheDocument(); + expect(screen.getByTestId('dueDate_DESC')).toBeInTheDocument(); }); - userEvent.click(screen.getByTestId('sortActionItems')); - + fireEvent.click(screen.getByTestId('dueDate_DESC')); await waitFor(() => { - expect(screen.getByTestId('earliest')).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('earliest')); - - await waitFor(() => { - expect(screen.getByTestId('sortActionItems')).toHaveTextContent( - translations.earliest, - ); - }); - - await waitFor(() => { - expect(screen.getByTestId('sortActionItems')).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('sortActionItems')); - - await waitFor(() => { - expect(screen.getByTestId('latest')).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('latest')); - - await waitFor(() => { - expect(screen.getByTestId('sortActionItems')).toHaveTextContent( - translations.latest, + expect(screen.getAllByTestId('categoryName')[0]).toHaveTextContent( + 'Category 2', ); }); }); - test('applies and then clears filters one by one', async () => { - render( - - - - - {} - - - - , - ); - - await wait(); + it('Sort Action Items ascending by dueDate', async () => { + renderOrganizationActionItems(link1); - await waitFor(() => { - expect(screen.getByTestId('sortActionItems')).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('sortActionItems')); + const sortBtn = await screen.findByTestId('sort'); + expect(sortBtn).toBeInTheDocument(); + // Sort by dueDate_ASC + fireEvent.click(sortBtn); await waitFor(() => { - expect(screen.getByTestId('earliest')).toBeInTheDocument(); + expect(screen.getByTestId('dueDate_ASC')).toBeInTheDocument(); }); - userEvent.click(screen.getByTestId('earliest')); - - // all the action items ordered by earliest first + fireEvent.click(screen.getByTestId('dueDate_ASC')); await waitFor(() => { - expect(screen.getByTestId('sortActionItems')).toHaveTextContent( - translations.earliest, + expect(screen.getAllByTestId('categoryName')[0]).toHaveTextContent( + 'Category 1', ); }); + }); - await waitFor(() => { - expect(screen.getByTestId('selectActionItemStatus')).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('selectActionItemStatus')); - - await waitFor(() => { - expect(screen.getByTestId('activeActionItems')).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('activeActionItems')); + it('Filter Action Items by status (All/Pending)', async () => { + renderOrganizationActionItems(link1); - // all the action items that are active - await waitFor(() => { - expect(screen.getByTestId('selectActionItemStatus')).toHaveTextContent( - translations.active, - ); - }); + const filterBtn = await screen.findByTestId('filter'); + expect(filterBtn).toBeInTheDocument(); + // Filter by All + fireEvent.click(filterBtn); await waitFor(() => { - expect(screen.getByTestId('selectActionItemStatus')).toBeInTheDocument(); + expect(screen.getByTestId('statusAll')).toBeInTheDocument(); }); - userEvent.click(screen.getByTestId('selectActionItemStatus')); + fireEvent.click(screen.getByTestId('statusAll')); await waitFor(() => { - expect(screen.getByTestId('completedActionItems')).toBeInTheDocument(); + expect(screen.getByText('Category 1')).toBeInTheDocument(); + expect(screen.getByText('Category 2')).toBeInTheDocument(); }); - userEvent.click(screen.getByTestId('completedActionItems')); - // all the action items that are completed + // Filter by Pending + fireEvent.click(filterBtn); await waitFor(() => { - expect(screen.getByTestId('selectActionItemStatus')).toHaveTextContent( - translations.completed, - ); + expect(screen.getByTestId('statusPending')).toBeInTheDocument(); }); - + fireEvent.click(screen.getByTestId('statusPending')); await waitFor(() => { - expect( - screen.getByTestId('selectActionItemCategory'), - ).toBeInTheDocument(); + expect(screen.queryByText('Category 1')).toBeNull(); + expect(screen.getByText('Category 2')).toBeInTheDocument(); }); - userEvent.click(screen.getByTestId('selectActionItemCategory')); + }); - await waitFor(() => { - expect( - screen.getAllByTestId('actionItemCategory')[0], - ).toBeInTheDocument(); - }); - userEvent.click(screen.getAllByTestId('actionItemCategory')[0]); + it('Filter Action Items by status (Completed)', async () => { + renderOrganizationActionItems(link1); - // action items belonging to this action item category - await waitFor(() => { - expect(screen.getByTestId('selectActionItemCategory')).toHaveTextContent( - 'ActionItemCategory 1', - ); - }); + const filterBtn = await screen.findByTestId('filter'); + expect(filterBtn).toBeInTheDocument(); + fireEvent.click(filterBtn); await waitFor(() => { - expect( - screen.getByTestId('clearActionItemCategoryFilter'), - ).toBeInTheDocument(); + expect(screen.getByTestId('statusCompleted')).toBeInTheDocument(); }); - // remove the action item category filter - userEvent.click(screen.getByTestId('clearActionItemCategoryFilter')); - + fireEvent.click(screen.getByTestId('statusCompleted')); await waitFor(() => { - expect( - screen.queryByTestId('clearActionItemCategoryFilter'), - ).not.toBeInTheDocument(); + expect(screen.getByText('Category 1')).toBeInTheDocument(); + expect(screen.queryByText('Category 2')).toBeNull(); }); + }); - await waitFor(() => { - expect( - screen.getByTestId('clearActionItemStatusFilter'), - ).toBeInTheDocument(); - }); - // remove the action item status filter - userEvent.click(screen.getByTestId('clearActionItemStatusFilter')); + it('open and close Item modal (create)', async () => { + renderOrganizationActionItems(link1); - await waitFor(() => { - expect(screen.getByTestId('selectActionItemStatus')).toHaveTextContent( - translations.status, - ); - expect(screen.getByTestId('selectActionItemCategory')).toHaveTextContent( - translations.actionItemCategory, - ); - }); - }); + const addItemBtn = await screen.findByTestId('createActionItemBtn'); + expect(addItemBtn).toBeInTheDocument(); + userEvent.click(addItemBtn); - test('applies and then clears all the filters', async () => { - render( - - - - - {} - - - - , + await waitFor(() => + expect(screen.getAllByText(t.createActionItem)).toHaveLength(2), + ); + userEvent.click(screen.getByTestId('modalCloseBtn')); + await waitFor(() => + expect(screen.queryByTestId('modalCloseBtn')).toBeNull(), ); + }); - await wait(); + it('open and close Item modal (view)', async () => { + renderOrganizationActionItems(link1); - await waitFor(() => { - expect(screen.getByTestId('sortActionItems')).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('sortActionItems')); + const viewItemBtn = await screen.findByTestId('viewItemBtn1'); + expect(viewItemBtn).toBeInTheDocument(); + userEvent.click(viewItemBtn); - await waitFor(() => { - expect(screen.getByTestId('earliest')).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('earliest')); + await waitFor(() => + expect(screen.getByText(t.actionItemDetails)).toBeInTheDocument(), + ); + userEvent.click(screen.getByTestId('modalCloseBtn')); + await waitFor(() => + expect(screen.queryByTestId('modalCloseBtn')).toBeNull(), + ); + }); - // all the action items ordered by earliest first - await waitFor(() => { - expect(screen.getByTestId('sortActionItems')).toHaveTextContent( - translations.earliest, - ); - }); + it('open and closes Item modal (edit)', async () => { + renderOrganizationActionItems(link1); - await waitFor(() => { - expect(screen.getByTestId('selectActionItemStatus')).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('selectActionItemStatus')); + const editItemBtn = await screen.findByTestId('editItemBtn1'); + await waitFor(() => expect(editItemBtn).toBeInTheDocument()); + userEvent.click(editItemBtn); - await waitFor(() => { - expect(screen.getByTestId('activeActionItems')).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('activeActionItems')); + await waitFor(() => + expect(screen.getAllByText(t.updateActionItem)).toHaveLength(2), + ); + userEvent.click(screen.getByTestId('modalCloseBtn')); + await waitFor(() => + expect(screen.queryByTestId('modalCloseBtn')).toBeNull(), + ); + }); - // all the action items that are active - await waitFor(() => { - expect(screen.getByTestId('selectActionItemStatus')).toHaveTextContent( - translations.active, - ); - }); + it('open and closes Item modal (delete)', async () => { + renderOrganizationActionItems(link1); - await waitFor(() => { - expect(screen.getByTestId('selectActionItemStatus')).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('selectActionItemStatus')); + const deleteItemBtn = await screen.findByTestId('deleteItemBtn1'); + expect(deleteItemBtn).toBeInTheDocument(); + userEvent.click(deleteItemBtn); - await waitFor(() => { - expect(screen.getByTestId('completedActionItems')).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('completedActionItems')); + await waitFor(() => + expect(screen.getByText(t.deleteActionItem)).toBeInTheDocument(), + ); + userEvent.click(screen.getByTestId('modalCloseBtn')); + await waitFor(() => + expect(screen.queryByTestId('modalCloseBtn')).toBeNull(), + ); + }); - // all the action items that are completed - await waitFor(() => { - expect(screen.getByTestId('selectActionItemStatus')).toHaveTextContent( - translations.completed, - ); - }); + it('open and closes Item modal (update status)', async () => { + renderOrganizationActionItems(link1); - await waitFor(() => { - expect( - screen.getByTestId('selectActionItemCategory'), - ).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('selectActionItemCategory')); + const statusCheckbox = await screen.findByTestId('statusCheckbox1'); + expect(statusCheckbox).toBeInTheDocument(); + userEvent.click(statusCheckbox); - await waitFor(() => { - expect( - screen.getAllByTestId('actionItemCategory')[0], - ).toBeInTheDocument(); - }); - userEvent.click(screen.getAllByTestId('actionItemCategory')[0]); + await waitFor(() => + expect(screen.getByText(t.actionItemStatus)).toBeInTheDocument(), + ); + userEvent.click(screen.getByTestId('modalCloseBtn')); + await waitFor(() => + expect(screen.queryByTestId('modalCloseBtn')).toBeNull(), + ); + }); - // action items belonging to this action item category - await waitFor(() => { - expect(screen.getByTestId('selectActionItemCategory')).toHaveTextContent( - 'ActionItemCategory 1', - ); - }); + it('Search action items by assignee', async () => { + renderOrganizationActionItems(link1); - await waitFor(() => { - expect(screen.getByTestId('clearFilters')).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('clearFilters')); + const searchByToggle = await screen.findByTestId('searchByToggle'); + expect(searchByToggle).toBeInTheDocument(); - // filters cleared, all the action items belonging to the organization + userEvent.click(searchByToggle); await waitFor(() => { - expect(screen.getByTestId('sortActionItems')).toHaveTextContent( - translations.latest, - ); - expect(screen.getByTestId('selectActionItemStatus')).toHaveTextContent( - translations.status, - ); - expect(screen.getByTestId('selectActionItemCategory')).toHaveTextContent( - translations.actionItemCategory, - ); + expect(screen.getByTestId('assignee')).toBeInTheDocument(); }); - }); - test('opens and closes the create action item modal', async () => { - render( - - - - - - {} - - - - - , - ); + userEvent.click(screen.getByTestId('assignee')); - await wait(); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + userEvent.type(searchInput, 'John'); + userEvent.click(screen.getByTestId('searchBtn')); await waitFor(() => { - expect(screen.getByTestId('createActionItemBtn')).toBeInTheDocument(); + expect(screen.getByText('Category 1')).toBeInTheDocument(); + expect(screen.queryByText('Category 2')).toBeNull(); }); - userEvent.click(screen.getByTestId('createActionItemBtn')); - - await waitFor(() => { - return expect( - screen.findByTestId('createActionItemModalCloseBtn'), - ).resolves.toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('createActionItemModalCloseBtn')); - - await waitForElementToBeRemoved(() => - screen.queryByTestId('createActionItemModalCloseBtn'), - ); }); - test('creates new action item', async () => { - render( - - - - - - {} - - - - - , - ); + it('Search action items by category', async () => { + renderOrganizationActionItems(link1); - await wait(); + const searchByToggle = await screen.findByTestId('searchByToggle'); + expect(searchByToggle).toBeInTheDocument(); + userEvent.click(searchByToggle); await waitFor(() => { - expect(screen.getByTestId('createActionItemBtn')).toBeInTheDocument(); + expect(screen.getByTestId('category')).toBeInTheDocument(); }); - userEvent.click(screen.getByTestId('createActionItemBtn')); - await waitFor(() => { - return expect( - screen.findByTestId('createActionItemModalCloseBtn'), - ).resolves.toBeInTheDocument(); - }); + userEvent.click(screen.getByTestId('category')); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + userEvent.type(searchInput, 'Category 1'); + userEvent.click(screen.getByTestId('searchBtn')); await waitFor(() => { - expect( - screen.getByTestId('formSelectActionItemCategory'), - ).toBeInTheDocument(); + expect(screen.getByText('Category 1')).toBeInTheDocument(); + expect(screen.queryByText('Category 2')).toBeNull(); }); + }); - userEvent.selectOptions( - screen.getByTestId('formSelectActionItemCategory'), - formData.actionItemCategory, - ); - - userEvent.selectOptions( - screen.getByTestId('formSelectAssignee'), - formData.assignee, - ); - - userEvent.type( - screen.getByPlaceholderText(translations.preCompletionNotes), - formData.preCompletionNotes, - ); - - const dueDatePicker = screen.getByLabelText(translations.dueDate); - fireEvent.change(dueDatePicker, { - target: { value: formData.dueDate }, - }); + it('Search action items by name and clear the input by backspace', async () => { + renderOrganizationActionItems(link1); - userEvent.click(screen.getByTestId('createActionItemFormSubmitBtn')); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + // Clear the search input by backspace + userEvent.type(searchInput, 'A{backspace}'); await waitFor(() => { - expect(toast.success).toBeCalledWith(translations.successfulCreation); + expect(screen.getByText('Category 1')).toBeInTheDocument(); + expect(screen.getByText('Category 2')).toBeInTheDocument(); }); }); - test('toasts error on unsuccessful creation', async () => { - render( - - - - - - {} - - - - - , - ); - - await wait(); + it('Search action items by name on press of ENTER', async () => { + renderOrganizationActionItems(link1); - await waitFor(() => { - expect(screen.getByTestId('createActionItemBtn')).toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('createActionItemBtn')); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + userEvent.type(searchInput, 'John'); + userEvent.type(searchInput, '{enter}'); await waitFor(() => { - return expect( - screen.findByTestId('createActionItemModalCloseBtn'), - ).resolves.toBeInTheDocument(); + expect(screen.getByText('Category 1')).toBeInTheDocument(); + expect(screen.queryByText('Category 2')).toBeNull(); }); + }); + it('should render Empty Action Item Categories Screen', async () => { + renderOrganizationActionItems(link3); await waitFor(() => { - expect( - screen.getByTestId('formSelectActionItemCategory'), - ).toBeInTheDocument(); - }); - - userEvent.selectOptions( - screen.getByTestId('formSelectActionItemCategory'), - formData.actionItemCategory, - ); - - userEvent.selectOptions( - screen.getByTestId('formSelectAssignee'), - formData.assignee, - ); - - userEvent.type( - screen.getByPlaceholderText(translations.preCompletionNotes), - formData.preCompletionNotes, - ); - - const dueDatePicker = screen.getByLabelText(translations.dueDate); - fireEvent.change(dueDatePicker, { - target: { value: formData.dueDate }, + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + expect(screen.getByText(t.noActionItems)).toBeInTheDocument(); }); + }); - userEvent.click(screen.getByTestId('createActionItemFormSubmitBtn')); - + it('should render the Action Item Categories Screen with error', async () => { + renderOrganizationActionItems(link2); await waitFor(() => { - expect(toast.error).toHaveBeenCalled(); + expect(screen.getByTestId('errorMsg')).toBeInTheDocument(); }); }); - - test('Testing Only Action Items Displaying', async () => { - const mockApp = render( - - - - - - {} - - - - - , - ); - - await waitFor(mockApp.asFragment); - - const actionItem = screen.getByText(/John Doe/i); - - expect(actionItem).toContainHTML('John Doe'); - }); }); diff --git a/src/screens/OrganizationActionItems/OrganizationActionItems.tsx b/src/screens/OrganizationActionItems/OrganizationActionItems.tsx index 4a863724fc..ba48f212e0 100644 --- a/src/screens/OrganizationActionItems/OrganizationActionItems.tsx +++ b/src/screens/OrganizationActionItems/OrganizationActionItems.tsx @@ -1,81 +1,133 @@ -import React, { useState } from 'react'; -import type { ChangeEvent } from 'react'; +import React, { useCallback, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { Button, Dropdown } from 'react-bootstrap'; -import { useParams } from 'react-router-dom'; +import { Button, Dropdown, Form } from 'react-bootstrap'; +import { Navigate, useParams } from 'react-router-dom'; -import SortIcon from '@mui/icons-material/Sort'; -import { WarningAmberRounded } from '@mui/icons-material'; +import { + Circle, + FilterAltOutlined, + Search, + Sort, + WarningAmberRounded, +} from '@mui/icons-material'; import dayjs from 'dayjs'; -import { toast } from 'react-toastify'; -import { useMutation, useQuery } from '@apollo/client'; -import { - ACTION_ITEM_CATEGORY_LIST, - ACTION_ITEM_LIST, - MEMBERS_LIST, -} from 'GraphQl/Queries/Queries'; -import { CREATE_ACTION_ITEM_MUTATION } from 'GraphQl/Mutations/mutations'; +import { useQuery } from '@apollo/client'; +import { ACTION_ITEM_LIST } from 'GraphQl/Queries/Queries'; import type { - InterfaceActionItemCategoryList, + InterfaceActionItemInfo, InterfaceActionItemList, - InterfaceMembersList, } from 'utils/interfaces'; -import ActionItemsContainer from 'components/ActionItems/ActionItemsContainer'; -import ActionItemCreateModal from './ActionItemCreateModal'; import styles from './OrganizationActionItems.module.css'; import Loader from 'components/Loader/Loader'; +import { + DataGrid, + type GridCellParams, + type GridColDef, +} from '@mui/x-data-grid'; +import { Chip, Stack } from '@mui/material'; +import ItemViewModal from './ItemViewModal'; +import ItemModal from './ItemModal'; +import ItemDeleteModal from './ItemDeleteModal'; +import Avatar from 'components/Avatar/Avatar'; +import ItemUpdateStatusModal from './ItemUpdateStatusModal'; + +enum ItemStatus { + Pending = 'pending', + Completed = 'completed', + Late = 'late', +} + +enum ModalState { + SAME = 'same', + DELETE = 'delete', + VIEW = 'view', + STATUS = 'status', +} +const dataGridStyle = { + '&.MuiDataGrid-root .MuiDataGrid-cell:focus-within': { + outline: 'none !important', + }, + '&.MuiDataGrid-root .MuiDataGrid-columnHeader:focus-within': { + outline: 'none', + }, + '& .MuiDataGrid-row:hover': { + backgroundColor: 'transparent', + }, + '& .MuiDataGrid-row.Mui-hovered': { + backgroundColor: 'transparent', + }, + '& .MuiDataGrid-root': { + borderRadius: '0.5rem', + }, + '& .MuiDataGrid-main': { + borderRadius: '0.5rem', + }, +}; + +/** + * Component for managing and displaying action items within an organization. + * + * This component allows users to view, filter, sort, and create action items. It also handles fetching and displaying related data such as action item categories and members. + * + * @returns The rendered component. + */ function organizationActionItems(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'organizationActionItems', }); const { t: tCommon } = useTranslation('common'); + const { t: tErrors } = useTranslation('errors'); - const { orgId: currentUrl } = useParams(); + // Get the organization ID from URL parameters + const { orgId, eventId } = useParams(); - const [actionItemCreateModalIsOpen, setActionItemCreateModalIsOpen] = - useState(false); - const [dueDate, setDueDate] = useState(new Date()); - const [orderBy, setOrderBy] = useState<'Latest' | 'Earliest'>('Latest'); - const [actionItemStatus, setActionItemStatus] = useState(''); - const [actionItemCategoryId, setActionItemCategoryId] = useState(''); - const [actionItemCategoryName, setActionItemCategoryName] = useState(''); + if (!orgId) { + return ; + } - const [formState, setFormState] = useState({ - actionItemCategoryId: '', - assigneeId: '', - preCompletionNotes: '', + const [actionItem, setActionItem] = useState( + null, + ); + const [modalMode, setModalMode] = useState<'create' | 'edit'>('create'); + const [searchValue, setSearchValue] = useState(''); + const [searchTerm, setSearchTerm] = useState(''); + const [sortBy, setSortBy] = useState<'dueDate_ASC' | 'dueDate_DESC' | null>( + null, + ); + const [status, setStatus] = useState(null); + const [searchBy, setSearchBy] = useState<'assignee' | 'category'>('assignee'); + const [modalState, setModalState] = useState<{ + [key in ModalState]: boolean; + }>({ + [ModalState.SAME]: false, + [ModalState.DELETE]: false, + [ModalState.VIEW]: false, + [ModalState.STATUS]: false, }); - const { - data: actionItemCategoriesData, - loading: actionItemCategoriesLoading, - error: actionItemCategoriesError, - }: { - data: InterfaceActionItemCategoryList | undefined; - loading: boolean; - error?: Error | undefined; - } = useQuery(ACTION_ITEM_CATEGORY_LIST, { - variables: { - organizationId: currentUrl, - }, - notifyOnNetworkStatusChange: true, - }); + const openModal = (modal: ModalState): void => + setModalState((prevState) => ({ ...prevState, [modal]: true })); - const { - data: membersData, - loading: membersLoading, - error: membersError, - }: { - data: InterfaceMembersList | undefined; - loading: boolean; - error?: Error | undefined; - } = useQuery(MEMBERS_LIST, { - variables: { id: currentUrl }, - }); + const closeModal = (modal: ModalState): void => + setModalState((prevState) => ({ ...prevState, [modal]: false })); + const handleModalClick = useCallback( + (actionItem: InterfaceActionItemInfo | null, modal: ModalState): void => { + if (modal === ModalState.SAME) { + setModalMode(actionItem ? 'edit' : 'create'); + } + setActionItem(actionItem); + openModal(modal); + }, + [openModal], + ); + + /** + * Query to fetch action items for the organization based on filters and sorting. + */ const { data: actionItemsData, loading: actionItemsLoading, @@ -88,306 +140,407 @@ function organizationActionItems(): JSX.Element { refetch: () => void; } = useQuery(ACTION_ITEM_LIST, { variables: { - organizationId: currentUrl, - actionItemCategoryId, - orderBy: orderBy === 'Latest' ? 'createdAt_DESC' : 'createdAt_ASC', - isActive: actionItemStatus === 'Active' ? true : false, - isCompleted: actionItemStatus === 'Completed' ? true : false, + organizationId: orgId, + eventId: eventId, + orderBy: sortBy, + where: { + assigneeName: searchBy === 'assignee' ? searchTerm : undefined, + categoryName: searchBy === 'category' ? searchTerm : undefined, + is_completed: + status === null ? undefined : status === ItemStatus.Completed, + }, }, - notifyOnNetworkStatusChange: true, }); - const [createActionItem] = useMutation(CREATE_ACTION_ITEM_MUTATION); - - const createActionItemHandler = async ( - e: ChangeEvent, - ): Promise => { - e.preventDefault(); - try { - await createActionItem({ - variables: { - assigneeId: formState.assigneeId, - actionItemCategoryId: formState.actionItemCategoryId, - preCompletionNotes: formState.preCompletionNotes, - dueDate: dayjs(dueDate).format('YYYY-MM-DD'), - }, - }); - - setFormState({ - assigneeId: '', - actionItemCategoryId: '', - preCompletionNotes: '', - }); - - setDueDate(new Date()); - - actionItemsRefetch(); - hideCreateModal(); - toast.success(t('successfulCreation')); - } catch (error: unknown) { - if (error instanceof Error) { - toast.error(error.message); - console.log(error.message); - } - } - }; - - const showCreateModal = (): void => { - setActionItemCreateModalIsOpen(!actionItemCreateModalIsOpen); - }; - - const hideCreateModal = (): void => { - setActionItemCreateModalIsOpen(!actionItemCreateModalIsOpen); - }; - - const handleSorting = (sort: string): void => { - if (sort === 'Latest') { - setOrderBy('Latest'); - } else { - setOrderBy('Earliest'); - } - }; - - const handleStatusFilter = (status: string): void => { - if (status === 'Active') { - setActionItemStatus('Active'); - } else { - setActionItemStatus('Completed'); - } - }; - - const handleClearFilters = (): void => { - setActionItemCategoryId(''); - setActionItemCategoryName(''); - setActionItemStatus(''); - setOrderBy('Latest'); - }; + const actionItems = useMemo( + () => actionItemsData?.actionItemsByOrganization || [], + [actionItemsData], + ); - if (actionItemCategoriesLoading || membersLoading || actionItemsLoading) { + if (actionItemsLoading) { return ; } - if (actionItemCategoriesError || membersError || actionItemsError) { + if (actionItemsError) { return ( -
    -
    - -
    - Error occured while loading{' '} - {actionItemCategoriesError - ? 'Action Item Categories' - : membersError - ? 'Members List' - : 'Action Items List'}{' '} - Data -
    - {actionItemCategoriesError - ? actionItemCategoriesError.message - : membersError - ? membersError.message - : actionItemsError?.message} -
    -
    +
    + +
    + {tErrors('errorLoading', { entity: 'Action Items' })} +
    + {`${actionItemsError.message}`} +
    ); } - const actionItemCategories = - actionItemCategoriesData?.actionItemCategoriesByOrganization.filter( - (category) => !category.isDisabled, - ); - - const actionItemOnly = actionItemsData?.actionItemsByOrganization.filter( - (item) => item.event == null, - ); + const columns: GridColDef[] = [ + { + field: 'assignee', + headerName: 'Assignee', + flex: 1, + align: 'left', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + const { _id, firstName, lastName, image } = params.row.assignee; + return ( +
    + {image ? ( + Assignee + ) : ( +
    + +
    + )} + {params.row.assignee.firstName + ' ' + params.row.assignee.lastName} +
    + ); + }, + }, + { + field: 'itemCategory', + headerName: 'Item Category', + flex: 1, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( +
    + {params.row.actionItemCategory?.name} +
    + ); + }, + }, + { + field: 'status', + headerName: 'Status', + flex: 1, + align: 'center', + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( + } + label={params.row.isCompleted ? 'Completed' : 'Pending'} + variant="outlined" + color="primary" + className={`${styles.chip} ${params.row.isCompleted ? styles.active : styles.pending}`} + /> + ); + }, + }, + { + field: 'allotedHours', + headerName: 'Alloted Hours', + align: 'center', + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + flex: 1, + renderCell: (params: GridCellParams) => { + return ( +
    {params.row.allotedHours ?? '-'}
    + ); + }, + }, + { + field: 'dueDate', + headerName: 'Due Date', + align: 'center', + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + flex: 1, + renderCell: (params: GridCellParams) => { + return ( +
    + {dayjs(params.row.dueDate).format('DD/MM/YYYY')} +
    + ); + }, + }, + { + field: 'options', + headerName: 'Options', + align: 'center', + flex: 1, + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( + <> + + + + + ); + }, + }, + { + field: 'completed', + headerName: 'Completed', + align: 'center', + flex: 1, + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( +
    + handleModalClick(params.row, ModalState.STATUS)} + /> +
    + ); + }, + }, + ]; return ( -
    -
    -
    -
    -
    -
    -
    + {/* Table with Action Items */} + row._id} + slots={{ + noRowsOverlay: () => ( + + {t('noActionItems')} + + ), + }} + sx={dataGridStyle} + getRowClassName={() => `${styles.rowBackground}`} + autoHeight + rowHeight={65} + rows={actionItems.map((actionItem, index) => ({ + id: index + 1, + ...actionItem, + }))} + columns={columns} + isRowSelectable={() => false} + /> - -
    + {/* Item Modal (Create/Edit) */} + closeModal(ModalState.SAME)} + orgId={orgId} + actionItemsRefetch={actionItemsRefetch} + actionItem={actionItem} + editMode={modalMode === 'edit'} + /> + + closeModal(ModalState.DELETE)} + actionItem={actionItem} + actionItemsRefetch={actionItemsRefetch} + /> - {/* Create Modal */} - closeModal(ModalState.STATUS)} + actionItemsRefetch={actionItemsRefetch} /> + + {/* View Modal */} + {actionItem && ( + closeModal(ModalState.VIEW)} + item={actionItem} + /> + )}
    ); } diff --git a/src/screens/OrganizationActionItems/OrganizationActionItemsErrorMocks.ts b/src/screens/OrganizationActionItems/OrganizationActionItemsErrorMocks.ts deleted file mode 100644 index bedba6572b..0000000000 --- a/src/screens/OrganizationActionItems/OrganizationActionItemsErrorMocks.ts +++ /dev/null @@ -1,266 +0,0 @@ -import { CREATE_ACTION_ITEM_MUTATION } from 'GraphQl/Mutations/mutations'; - -import { - ACTION_ITEM_CATEGORY_LIST, - ACTION_ITEM_LIST, - MEMBERS_LIST, -} from 'GraphQl/Queries/Queries'; - -export const MOCKS_ERROR_ACTION_ITEM_CATEGORY_LIST_QUERY = [ - { - request: { - query: ACTION_ITEM_CATEGORY_LIST, - variables: { organizationId: '123' }, - }, - error: new Error('Mock Graphql Error'), - }, -]; - -export const MOCKS_ERROR_MEMBERS_LIST_QUERY = [ - { - request: { - query: ACTION_ITEM_CATEGORY_LIST, - variables: { organizationId: '123' }, - }, - result: { - data: { - actionItemCategoriesByOrganization: [ - { - _id: 'actionItemCategory1', - name: 'ActionItemCategory 1', - isDisabled: false, - }, - ], - }, - }, - }, - { - request: { - query: MEMBERS_LIST, - variables: { id: '123' }, - }, - error: new Error('Mock Graphql Error'), - }, -]; - -export const MOCKS_ERROR_ACTION_ITEM_LIST_QUERY = [ - { - request: { - query: ACTION_ITEM_CATEGORY_LIST, - variables: { organizationId: '123' }, - }, - result: { - data: { - actionItemCategoriesByOrganization: [ - { - _id: 'actionItemCategory1', - name: 'ActionItemCategory 1', - isDisabled: false, - }, - ], - }, - }, - }, - { - request: { - query: MEMBERS_LIST, - variables: { id: '123' }, - }, - result: { - data: { - organizations: [ - { - _id: '123', - members: [ - { - _id: 'user1', - firstName: 'Harve', - lastName: 'Lance', - email: 'harve@example.com', - image: '', - organizationsBlockedBy: [], - createdAt: '2024-02-14', - }, - ], - }, - ], - }, - }, - }, - { - request: { - query: ACTION_ITEM_LIST, - variables: { id: '123' }, - }, - error: new Error('Mock Graphql Error'), - }, -]; - -export const MOCKS_ERROR_MUTATIONS = [ - { - request: { - query: ACTION_ITEM_CATEGORY_LIST, - variables: { organizationId: '123' }, - }, - result: { - data: { - actionItemCategoriesByOrganization: [ - { - _id: 'actionItemCategory1', - name: 'ActionItemCategory 1', - isDisabled: false, - }, - ], - }, - }, - }, - { - request: { - query: MEMBERS_LIST, - variables: { id: '123' }, - }, - result: { - data: { - organizations: [ - { - _id: '123', - members: [ - { - _id: 'user1', - firstName: 'Harve', - lastName: 'Lance', - email: 'harve@example.com', - image: '', - organizationsBlockedBy: [], - createdAt: '2024-02-14', - }, - ], - }, - ], - }, - }, - }, - { - request: { - query: ACTION_ITEM_LIST, - variables: { - organizationId: '123', - orderBy: 'createdAt_DESC', - actionItemCategoryId: '', - isActive: false, - isCompleted: false, - }, - }, - result: { - data: { - actionItemsByOrganization: [ - { - _id: 'actionItem1', - assignee: { - _id: 'user1', - firstName: 'Harve', - lastName: 'Lance', - }, - actionItemCategory: { - _id: 'actionItemCategory1', - name: 'ActionItemCategory 1', - }, - preCompletionNotes: 'Pre Completion Notes', - postCompletionNotes: 'Post Completion Notes', - assignmentDate: '2024-02-14', - dueDate: '2024-02-21', - completionDate: '2024-02-21', - isCompleted: false, - assigner: { - _id: 'user0', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - event: { - _id: 'event1', - title: 'event 1', - }, - creator: { - _id: 'user0', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - }, - ], - }, - }, - }, - { - request: { - query: ACTION_ITEM_LIST, - variables: { - organizationId: '123', - eventId: 'event1', - orderBy: 'createdAt_DESC', - }, - }, - result: { - data: { - actionItemsByOrganization: [ - { - _id: 'actionItem1', - assignee: { - _id: 'user1', - firstName: 'Harve', - lastName: 'Lance', - }, - actionItemCategory: { - _id: 'actionItemCategory1', - name: 'ActionItemCategory 1', - }, - preCompletionNotes: 'Pre Completion Notes', - postCompletionNotes: 'Post Completion Notes', - assignmentDate: '2024-02-14', - dueDate: '2024-02-21', - completionDate: '2024-02-21', - isCompleted: false, - assigner: { - _id: 'user0', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - event: { - _id: 'event1', - title: 'event 1', - }, - creator: { - _id: 'user0', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - }, - ], - }, - }, - }, - { - request: { - query: CREATE_ACTION_ITEM_MUTATION, - variables: { - actionItemCategoryId: 'actionItemCategory1', - assigneeId: 'user1', - preCompletionNotes: 'pre completion notes', - dueDate: '2024-02-14', - }, - }, - error: new Error('Mock Graphql Error'), - }, - { - request: { - query: CREATE_ACTION_ITEM_MUTATION, - variables: { - eventId: 'event1', - actionItemCategoryId: 'actionItemCategory1', - assigneeId: 'user1', - preCompletionNotes: 'pre completion notes', - dueDate: '2024-02-14', - }, - }, - error: new Error('Mock Graphql Error'), - }, -]; diff --git a/src/screens/OrganizationDashboard/OrganizationDashboard.test.tsx b/src/screens/OrganizationDashboard/OrganizationDashboard.test.tsx index e377826a73..dde6b3120f 100644 --- a/src/screens/OrganizationDashboard/OrganizationDashboard.test.tsx +++ b/src/screens/OrganizationDashboard/OrganizationDashboard.test.tsx @@ -1,5 +1,5 @@ import { MockedProvider } from '@apollo/react-testing'; -import { act, fireEvent, render, screen } from '@testing-library/react'; +import { fireEvent, render, screen } from '@testing-library/react'; import 'jest-location-mock'; import { I18nextProvider } from 'react-i18next'; import { Provider } from 'react-redux'; @@ -13,7 +13,7 @@ import i18nForTest from 'utils/i18nForTest'; import useLocalStorage from 'utils/useLocalstorage'; import OrganizationDashboard from './OrganizationDashboard'; import { EMPTY_MOCKS, ERROR_MOCKS, MOCKS } from './OrganizationDashboardMocks'; -import React from 'react'; +import React, { act } from 'react'; const { setItem } = useLocalStorage(); import type { InterfaceQueryOrganizationEventListItem } from 'utils/interfaces'; diff --git a/src/screens/OrganizationDashboard/OrganizationDashboard.tsx b/src/screens/OrganizationDashboard/OrganizationDashboard.tsx index 5c32d292a3..6927e4f874 100644 --- a/src/screens/OrganizationDashboard/OrganizationDashboard.tsx +++ b/src/screens/OrganizationDashboard/OrganizationDashboard.tsx @@ -11,11 +11,11 @@ import { ORGANIZATION_EVENT_CONNECTION_LIST, ORGANIZATION_POST_LIST, } from 'GraphQl/Queries/Queries'; -import { ReactComponent as AdminsIcon } from 'assets/svgs/admin.svg'; -import { ReactComponent as BlockedUsersIcon } from 'assets/svgs/blockedUser.svg'; -import { ReactComponent as EventsIcon } from 'assets/svgs/events.svg'; -import { ReactComponent as PostsIcon } from 'assets/svgs/post.svg'; -import { ReactComponent as UsersIcon } from 'assets/svgs/users.svg'; +import AdminsIcon from 'assets/svgs/admin.svg?react'; +import BlockedUsersIcon from 'assets/svgs/blockedUser.svg?react'; +import EventsIcon from 'assets/svgs/events.svg?react'; +import PostsIcon from 'assets/svgs/post.svg?react'; +import UsersIcon from 'assets/svgs/users.svg?react'; import CardItem from 'components/OrganizationDashCards/CardItem'; import CardItemLoading from 'components/OrganizationDashCards/CardItemLoading'; import DashBoardCard from 'components/OrganizationDashCards/DashboardCard'; @@ -29,6 +29,13 @@ import type { } from 'utils/interfaces'; import styles from './OrganizationDashboard.module.css'; +/** + * Component for displaying the organization dashboard. + * + * This component provides an overview of various statistics and information related to an organization, including members, admins, posts, events, blocked users, and membership requests. It also displays upcoming events and latest posts. + * + * @returns The rendered component. + */ function organizationDashboard(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'dashboard' }); const { t: tCommon } = useTranslation('common'); @@ -45,6 +52,9 @@ function organizationDashboard(): JSX.Element { InterfaceQueryOrganizationEventListItem[] >([]); + /** + * Query to fetch organization data. + */ const { data, loading: loadingOrgData, @@ -59,6 +69,9 @@ function organizationDashboard(): JSX.Element { variables: { id: currentUrl }, }); + /** + * Query to fetch posts for the organization. + */ const { data: postData, loading: loadingPost, @@ -73,6 +86,9 @@ function organizationDashboard(): JSX.Element { variables: { id: currentUrl, first: 10 }, }); + /** + * Query to fetch events for the organization. + */ const { data: eventData, loading: loadingEvent, @@ -83,7 +99,9 @@ function organizationDashboard(): JSX.Element { }, }); - // UseEffect to update upcomingEvents array + /** + * UseEffect to update the list of upcoming events. + */ useEffect(() => { if (eventData && eventData?.eventsByOrganizationConnection.length > 0) { const tempUpcomingEvents: InterfaceQueryOrganizationEventListItem[] = []; @@ -100,6 +118,9 @@ function organizationDashboard(): JSX.Element { } }, [eventData?.eventsByOrganizationConnection]); + /** + * UseEffect to handle errors and navigate if necessary. + */ useEffect(() => { if (errorOrg || errorPost || errorEvent) { console.log('error', errorPost?.message); diff --git a/src/screens/OrganizationEvents/OrganizationEvents.tsx b/src/screens/OrganizationEvents/OrganizationEvents.tsx index aaa6f911a6..4c90777c6e 100644 --- a/src/screens/OrganizationEvents/OrganizationEvents.tsx +++ b/src/screens/OrganizationEvents/OrganizationEvents.tsx @@ -40,6 +40,19 @@ export enum ViewType { YEAR = 'Year View', } +/** + * Organization Events Page Component to display the events of an organization + * and create new events for the organization by the admin or superadmin user. + * The component uses the EventCalendar component to display the events and EventHeader component + * to display the view type and create event button. + * The component uses the RecurrenceOptions component to display the recurrence options for the event. + * The component uses the CREATE_EVENT_MUTATION mutation to create a new event for the organization. + * The component uses the ORGANIZATION_EVENT_CONNECTION_LIST and ORGANIZATIONS_LIST queries to fetch the events + * and organization details. + * The component uses the useLocalStorage hook to get the user details from the local storage. + * + * @returns JSX.Element to display the Organization Events Page + */ function organizationEvents(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'organizationEvents', @@ -157,8 +170,8 @@ function organizationEvents(): JSX.Element { endDate: dayjs(endDate).format('YYYY-MM-DD'), allDay: alldaychecked, location: formState.location, - startTime: !alldaychecked ? formState.startTime + 'Z' : undefined, - endTime: !alldaychecked ? formState.endTime + 'Z' : undefined, + startTime: !alldaychecked ? formState.startTime : undefined, + endTime: !alldaychecked ? formState.endTime : undefined, recurrenceStartDate: recurringchecked ? dayjs(recurrenceStartDate).format('YYYY-MM-DD') : undefined, @@ -183,7 +196,7 @@ function organizationEvents(): JSX.Element { }); if (createEventData) { - toast.success(t('eventCreated')); + toast.success(t('eventCreated') as string); refetchEvents(); hideCreateEventModal(); setFormState({ diff --git a/src/screens/OrganizationEvents/OrganizationEventsMocks.ts b/src/screens/OrganizationEvents/OrganizationEventsMocks.ts index 3ff2d73d5a..4f844d33fa 100644 --- a/src/screens/OrganizationEvents/OrganizationEventsMocks.ts +++ b/src/screens/OrganizationEvents/OrganizationEventsMocks.ts @@ -106,8 +106,8 @@ export const MOCKS = [ startDate: '2022-03-28', endDate: '2022-03-30', allDay: false, - startTime: '09:00:00Z', - endTime: '17:00:00Z', + startTime: '09:00:00', + endTime: '17:00:00', }, }, result: { @@ -132,8 +132,8 @@ export const MOCKS = [ startDate: '2022-03-28', endDate: '2022-03-30', allDay: false, - startTime: '09:00:00Z', - endTime: '17:00:00Z', + startTime: '09:00:00', + endTime: '17:00:00', recurrenceStartDate: '2022-03-28', recurrenceEndDate: null, frequency: 'DAILY', @@ -162,8 +162,8 @@ export const MOCKS = [ startDate: '2022-03-28', endDate: '2022-03-30', allDay: false, - startTime: '09:00:00Z', - endTime: '17:00:00Z', + startTime: '09:00:00', + endTime: '17:00:00', recurrenceStartDate: '2022-03-28', recurrenceEndDate: null, frequency: 'WEEKLY', diff --git a/src/screens/OrganizationFundCampaign/CampaignDeleteModal.test.tsx b/src/screens/OrganizationFundCampaign/CampaignDeleteModal.test.tsx deleted file mode 100644 index 7baf9bd933..0000000000 --- a/src/screens/OrganizationFundCampaign/CampaignDeleteModal.test.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import React from 'react'; -import type { ApolloLink } from '@apollo/client'; -import { MockedProvider } from '@apollo/react-testing'; -import { LocalizationProvider } from '@mui/x-date-pickers'; -import type { RenderResult } from '@testing-library/react'; -import { fireEvent, render, screen, waitFor } from '@testing-library/react'; -import { I18nextProvider } from 'react-i18next'; -import { Provider } from 'react-redux'; -import { BrowserRouter } from 'react-router-dom'; -import { store } from 'state/store'; -import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; -import i18nForTest from '../../utils/i18nForTest'; -import { StaticMockLink } from 'utils/StaticMockLink'; -import { toast } from 'react-toastify'; -import { MOCKS, MOCK_ERROR } from './OrganizationFundCampaignMocks'; -import CampaignDeleteModal, { - type InterfaceDeleteCampaignModal, -} from './CampaignDeleteModal'; - -jest.mock('react-toastify', () => ({ - toast: { - success: jest.fn(), - error: jest.fn(), - }, -})); - -const link1 = new StaticMockLink(MOCKS); -const link2 = new StaticMockLink(MOCK_ERROR); -const translations = JSON.parse( - JSON.stringify(i18nForTest.getDataByLanguage('en')?.translation.fundCampaign), -); - -const campaignProps: InterfaceDeleteCampaignModal = { - isOpen: true, - hide: jest.fn(), - campaign: { - _id: 'campaignId1', - name: 'Campaign 1', - fundingGoal: 100, - startDate: new Date('2021-01-01'), - endDate: new Date('2024-01-01'), - currency: 'USD', - createdAt: '2021-01-01', - }, - refetchCampaign: jest.fn(), -}; -const renderFundDeleteModal = ( - link: ApolloLink, - props: InterfaceDeleteCampaignModal, -): RenderResult => { - return render( - - - - - - - - - - - , - ); -}; - -describe('CampaignDeleteModal', () => { - it('should render CampaignDeleteModal', () => { - renderFundDeleteModal(link1, campaignProps); - expect(screen.getByTestId('deleteCampaignCloseBtn')).toBeInTheDocument(); - }); - - it('should successfully Delete Campaign', async () => { - renderFundDeleteModal(link1, campaignProps); - expect(screen.getByTestId('deleteCampaignCloseBtn')).toBeInTheDocument(); - - fireEvent.click(screen.getByTestId('deleteyesbtn')); - - await waitFor(() => { - expect(campaignProps.refetchCampaign).toHaveBeenCalled(); - expect(campaignProps.hide).toHaveBeenCalled(); - expect(toast.success).toHaveBeenCalledWith(translations.deletedCampaign); - }); - }); - - it('should fail to Delete Campaign', async () => { - renderFundDeleteModal(link2, campaignProps); - expect(screen.getByTestId('deleteCampaignCloseBtn')).toBeInTheDocument(); - - fireEvent.click(screen.getByTestId('deleteyesbtn')); - - await waitFor(() => { - expect(toast.error).toHaveBeenCalledWith('Mock graphql error'); - }); - }); -}); diff --git a/src/screens/OrganizationFundCampaign/CampaignDeleteModal.tsx b/src/screens/OrganizationFundCampaign/CampaignDeleteModal.tsx deleted file mode 100644 index 840c4869bb..0000000000 --- a/src/screens/OrganizationFundCampaign/CampaignDeleteModal.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import React from 'react'; -import { Button, Modal } from 'react-bootstrap'; -import styles from './OrganizationFundCampaign.module.css'; -import { useMutation } from '@apollo/client'; -import { DELETE_CAMPAIGN_MUTATION } from 'GraphQl/Mutations/CampaignMutation'; -import type { InterfaceCampaignInfo } from 'utils/interfaces'; -import { toast } from 'react-toastify'; -import { useTranslation } from 'react-i18next'; - -export interface InterfaceDeleteCampaignModal { - isOpen: boolean; - hide: () => void; - campaign: InterfaceCampaignInfo | null; - refetchCampaign: () => void; -} -const CampaignDeleteModal: React.FC = ({ - isOpen, - hide, - campaign, - refetchCampaign, -}) => { - const { t } = useTranslation('translation', { - keyPrefix: 'fundCampaign', - }); - const { t: tCommon } = useTranslation('common'); - - const [deleteCampaign] = useMutation(DELETE_CAMPAIGN_MUTATION); - - const deleteCampaignHandler = async (): Promise => { - try { - await deleteCampaign({ - variables: { - id: campaign?._id, - }, - }); - toast.success(t('deletedCampaign')); - refetchCampaign(); - hide(); - } catch (error: unknown) { - toast.error((error as Error).message); - } - }; - return ( - <> - - -

    {t('deleteCampaign')}

    - -
    - -

    {t('deleteCampaignMsg')}

    -
    - - - - -
    - - ); -}; -export default CampaignDeleteModal; diff --git a/src/screens/OrganizationFundCampaign/CampaignModal.test.tsx b/src/screens/OrganizationFundCampaign/CampaignModal.test.tsx index cdf631f87c..2a5a61a22b 100644 --- a/src/screens/OrganizationFundCampaign/CampaignModal.test.tsx +++ b/src/screens/OrganizationFundCampaign/CampaignModal.test.tsx @@ -48,6 +48,7 @@ const campaignProps: InterfaceCampaignModal[] = [ isOpen: true, hide: jest.fn(), fundId: 'fundId', + orgId: 'orgId', campaign: { _id: 'campaignId1', name: 'Campaign 1', @@ -64,6 +65,7 @@ const campaignProps: InterfaceCampaignModal[] = [ isOpen: true, hide: jest.fn(), fundId: 'fundId', + orgId: 'orgId', campaign: { _id: 'campaignId1', name: 'Campaign 1', diff --git a/src/screens/OrganizationFundCampaign/CampaignModal.tsx b/src/screens/OrganizationFundCampaign/CampaignModal.tsx index dfe0738c07..63d1e8de3a 100644 --- a/src/screens/OrganizationFundCampaign/CampaignModal.tsx +++ b/src/screens/OrganizationFundCampaign/CampaignModal.tsx @@ -3,7 +3,7 @@ import type { Dayjs } from 'dayjs'; import dayjs from 'dayjs'; import type { ChangeEvent } from 'react'; import React, { useEffect, useState } from 'react'; -import { Button, Col, Form, Modal } from 'react-bootstrap'; +import { Button, Form, Modal } from 'react-bootstrap'; import { currencyOptions, currencySymbols } from 'utils/currency'; import styles from './OrganizationFundCampaign.module.css'; import { useTranslation } from 'react-i18next'; @@ -22,19 +22,30 @@ import { } from '@mui/material'; import type { InterfaceCampaignInfo } from 'utils/interfaces'; +/** + * Props for the CampaignModal component. + */ export interface InterfaceCampaignModal { isOpen: boolean; hide: () => void; fundId: string; + orgId: string; campaign: InterfaceCampaignInfo | null; refetchCampaign: () => void; mode: 'create' | 'edit'; } +/** + * Modal component for creating or editing a campaign. + * + * @param props - The props for the CampaignModal component. + * @returns JSX.Element + */ const CampaignModal: React.FC = ({ isOpen, hide, fundId, + orgId, refetchCampaign, mode, campaign, @@ -73,6 +84,12 @@ const CampaignModal: React.FC = ({ const [createCampaign] = useMutation(CREATE_CAMPAIGN_MUTATION); const [updateCampaign] = useMutation(UPDATE_CAMPAIGN_MUTATION); + /** + * Handles form submission to create a new campaign. + * + * @param e - The form event. + * @returns Promise + */ const createCampaignHandler = async ( e: ChangeEvent, ): Promise => { @@ -83,12 +100,13 @@ const CampaignModal: React.FC = ({ name: formState.campaignName, currency: formState.campaignCurrency, fundingGoal: formState.campaignGoal, + organizationId: orgId, startDate: dayjs(formState.campaignStartDate).format('YYYY-MM-DD'), endDate: dayjs(formState.campaignEndDate).format('YYYY-MM-DD'), fundId, }, }); - toast.success(t('createdCampaign')); + toast.success(t('createdCampaign') as string); setFormState({ campaignName: '', campaignCurrency: 'USD', @@ -103,6 +121,12 @@ const CampaignModal: React.FC = ({ } }; + /** + * Handles form submission to update an existing campaign. + * + * @param e - The form event. + * @returns Promise + */ /*istanbul ignore next*/ const updateCampaignHandler = async ( e: ChangeEvent, @@ -142,7 +166,7 @@ const CampaignModal: React.FC = ({ }); refetchCampaign(); hide(); - toast.success(t('updatedCampaign')); + toast.success(t('updatedCampaign') as string); } catch (error: unknown) { toast.error((error as Error).message); } diff --git a/src/screens/OrganizationFundCampaign/OrganizationFundCampagins.tsx b/src/screens/OrganizationFundCampaign/OrganizationFundCampagins.tsx index 6cc671c5b1..1c6dbf2cc6 100644 --- a/src/screens/OrganizationFundCampaign/OrganizationFundCampagins.tsx +++ b/src/screens/OrganizationFundCampaign/OrganizationFundCampagins.tsx @@ -13,7 +13,6 @@ import React, { useCallback, useMemo, useState } from 'react'; import dayjs from 'dayjs'; import Loader from 'components/Loader/Loader'; import CampaignModal from './CampaignModal'; -import CampaignDeleteModal from './CampaignDeleteModal'; import { FUND_CAMPAIGN } from 'GraphQl/Queries/fundQueries'; import styles from './OrganizationFundCampaign.module.css'; import { currencySymbols } from 'utils/currency'; @@ -43,11 +42,38 @@ const dataGridStyle = { }, }; -enum ModalState { - SAME = 'same', - DELETE = 'delete', -} - +/** + * `orgFundCampaign` component displays a list of fundraising campaigns for a specific fund within an organization. + * It allows users to search, sort, view and edit campaigns. + * + * ### Functionality + * - Displays a data grid with campaigns information, including their names, start and end dates, funding goals, and actions. + * - Provides search functionality to filter campaigns by name. + * - Offers sorting options based on funding goal and end date. + * - Opens modals for creating or editing campaigns. + * + * + * ### State + * - `campaign`: The current campaign being edited or deleted. + * - `searchTerm`: The term used for searching campaigns by name. + * - `sortBy`: The current sorting criteria for campaigns. + * - `modalState`: An object indicating the visibility of different modals (`same` for create/edit). + * - `campaignModalMode`: Determines if the modal is in 'edit' or 'create' mode. + * + * ### Methods + * - `handleOpenModal(campaign: InterfaceCampaignInfo | null, mode: 'edit' | 'create')`: Opens the modal for creating or editing a campaign. + * - `handleClick(campaignId: string)`: Navigates to the pledge details page for a specific campaign. + * + * ### GraphQL Queries + * - Uses `FUND_CAMPAIGN` query to fetch the list of campaigns based on the provided fund ID, search term, and sorting criteria. + * + * ### Rendering + * - Renders a `DataGrid` component with campaigns information. + * - Displays modals for creating and editing campaigns. + * - Shows error and loading states using `Loader` and error message components. + * + * @returns The rendered component including breadcrumbs, search and filter controls, data grid, and modals. + */ const orgFundCampaign = (): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'fundCampaign', @@ -65,36 +91,18 @@ const orgFundCampaign = (): JSX.Element => { const [searchTerm, setSearchTerm] = useState(''); const [sortBy, setSortBy] = useState(null); - const [modalState, setModalState] = useState<{ - [key in ModalState]: boolean; - }>({ - [ModalState.SAME]: false, - [ModalState.DELETE]: false, - }); + const [modalState, setModalState] = useState(false); const [campaignModalMode, setCampaignModalMode] = useState<'edit' | 'create'>( 'create', ); - const openModal = (modal: ModalState): void => - setModalState((prevState) => ({ ...prevState, [modal]: true })); - - const closeModal = (modal: ModalState): void => - setModalState((prevState) => ({ ...prevState, [modal]: false })); const handleOpenModal = useCallback( (campaign: InterfaceCampaignInfo | null, mode: 'edit' | 'create'): void => { setCampaign(campaign); setCampaignModalMode(mode); - openModal(ModalState.SAME); - }, - [openModal], - ); - - const handleDeleteClick = useCallback( - (campaign: InterfaceCampaignInfo): void => { - setCampaign(campaign); - openModal(ModalState.DELETE); + setModalState(true); }, - [openModal], + [], ); const { @@ -123,10 +131,11 @@ const orgFundCampaign = (): JSX.Element => { navigate(`/fundCampaignPledge/${orgId}/${campaignId}`); }; - const campaigns = useMemo(() => { - if (campaignData?.getFundById?.campaigns) - return campaignData.getFundById.campaigns; - return []; + const { campaigns, fundName, isArchived } = useMemo(() => { + const fundName = campaignData?.getFundById?.name || 'Fund'; + const isArchived = campaignData?.getFundById?.isArchived || false; + const campaigns = campaignData?.getFundById?.campaigns || []; + return { fundName, campaigns, isArchived }; }, [campaignData]); if (campaignLoading) { @@ -165,7 +174,6 @@ const orgFundCampaign = (): JSX.Element => { field: 'campaignName', headerName: 'Campaign Name', flex: 2, - minWidth: 150, align: 'center', headerAlign: 'center', headerClassName: `${styles.tableHeader}`, @@ -186,7 +194,6 @@ const orgFundCampaign = (): JSX.Element => { field: 'startDate', headerName: 'Start Date', flex: 1, - minWidth: 150, align: 'center', headerAlign: 'center', headerClassName: `${styles.tableHeader}`, @@ -198,7 +205,6 @@ const orgFundCampaign = (): JSX.Element => { { field: 'endDate', headerName: 'End Date', - minWidth: 150, align: 'center', headerAlign: 'center', headerClassName: `${styles.tableHeader}`, @@ -237,6 +243,31 @@ const orgFundCampaign = (): JSX.Element => { ); }, }, + { + field: 'fundingRaised', + headerName: 'Raised', + flex: 1, + minWidth: 100, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return ( +
    + { + currencySymbols[ + params.row.campaign.currency as keyof typeof currencySymbols + ] + } + 0 +
    + ); + }, + }, { field: 'action', headerName: 'Action', @@ -263,17 +294,6 @@ const orgFundCampaign = (): JSX.Element => { > - ); }, @@ -314,9 +334,9 @@ const orgFundCampaign = (): JSX.Element => { data-testid="fundsLink" onClick={() => navigate(`/orgfunds/${orgId}`)} > - {tCommon('Funds')} + {fundName} - FundRaising Campaign + {t('title')}
    @@ -384,6 +404,7 @@ const orgFundCampaign = (): JSX.Element => { className={styles.orgFundCampaignButton} onClick={() => handleOpenModal(null, 'create')} data-testid="addCampaignBtn" + disabled={isArchived} > {t('addCampaign')} @@ -394,7 +415,7 @@ const orgFundCampaign = (): JSX.Element => { row.campaign._id} slots={{ @@ -418,20 +439,14 @@ const orgFundCampaign = (): JSX.Element => { {/* Create Campaign ModalState */} closeModal(ModalState.SAME)} + isOpen={modalState} + hide={() => setModalState(false)} refetchCampaign={refetchCampaign} fundId={fundId} + orgId={orgId} campaign={campaign} mode={campaignModalMode} /> - - closeModal(ModalState.DELETE)} - campaign={campaign} - refetchCampaign={refetchCampaign} - />
    ); }; diff --git a/src/screens/OrganizationFundCampaign/OrganizationFundCampaign.test.tsx b/src/screens/OrganizationFundCampaign/OrganizationFundCampaign.test.tsx index 74f646f51a..9c169e355a 100644 --- a/src/screens/OrganizationFundCampaign/OrganizationFundCampaign.test.tsx +++ b/src/screens/OrganizationFundCampaign/OrganizationFundCampaign.test.tsx @@ -173,22 +173,6 @@ describe('FundCampaigns Screen', () => { ); }); - it('open and closes delete campaign modal', async () => { - renderFundCampaign(link1); - - const deleteCampaignBtn = await screen.findAllByTestId('deleteCampaignBtn'); - await waitFor(() => expect(deleteCampaignBtn[0]).toBeInTheDocument()); - userEvent.click(deleteCampaignBtn[0]); - - await waitFor(() => - expect(screen.getByText(translations.deleteCampaign)).toBeInTheDocument(), - ); - userEvent.click(screen.getByTestId('deleteCampaignCloseBtn')); - await waitFor(() => - expect(screen.queryByTestId('deleteCampaignCloseBtn')).toBeNull(), - ); - }); - it('Search the Campaigns list by Name', async () => { renderFundCampaign(link1); const searchField = await screen.findByTestId('searchFullName'); diff --git a/src/screens/OrganizationFundCampaign/OrganizationFundCampaignMocks.ts b/src/screens/OrganizationFundCampaign/OrganizationFundCampaignMocks.ts index 160dfad5fb..fa871c3593 100644 --- a/src/screens/OrganizationFundCampaign/OrganizationFundCampaignMocks.ts +++ b/src/screens/OrganizationFundCampaign/OrganizationFundCampaignMocks.ts @@ -1,6 +1,5 @@ import { CREATE_CAMPAIGN_MUTATION, - DELETE_CAMPAIGN_MUTATION, UPDATE_CAMPAIGN_MUTATION, } from 'GraphQl/Mutations/CampaignMutation'; import { FUND_CAMPAIGN } from 'GraphQl/Queries/fundQueries'; @@ -18,6 +17,8 @@ export const MOCKS = [ result: { data: { getFundById: { + name: 'Fund 1', + isArchived: false, campaigns: [ { _id: 'campaignId1', @@ -52,6 +53,8 @@ export const MOCKS = [ result: { data: { getFundById: { + name: 'Fund 1', + isArchived: false, campaigns: [ { _id: '2', @@ -78,6 +81,8 @@ export const MOCKS = [ result: { data: { getFundById: { + name: 'Fund 1', + isArchived: false, campaigns: [ { _id: '1', @@ -112,6 +117,8 @@ export const MOCKS = [ result: { data: { getFundById: { + name: 'Fund 1', + isArchived: false, campaigns: [ { _id: '2', @@ -146,6 +153,8 @@ export const MOCKS = [ result: { data: { getFundById: { + name: 'Fund 1', + isArchived: false, campaigns: [ { _id: '2', @@ -180,6 +189,8 @@ export const MOCKS = [ result: { data: { getFundById: { + name: 'Fund 1', + isArchived: false, campaigns: [ { _id: '1', @@ -207,6 +218,7 @@ export const MOCKS = [ query: CREATE_CAMPAIGN_MUTATION, variables: { fundId: 'fundId', + organizationId: 'orgId', name: 'Campaign 2', fundingGoal: 200, startDate: '2024-01-02', @@ -241,21 +253,6 @@ export const MOCKS = [ }, }, }, - { - request: { - query: DELETE_CAMPAIGN_MUTATION, - variables: { - id: 'campaignId1', - }, - }, - result: { - data: { - removeFundraisingCampaign: { - _id: 'campaignId1', - }, - }, - }, - }, ]; export const MOCK_ERROR = [ @@ -275,6 +272,7 @@ export const MOCK_ERROR = [ query: CREATE_CAMPAIGN_MUTATION, variables: { fundId: 'fundId', + organizationId: 'orgId', name: 'Campaign 2', fundingGoal: 200, startDate: '2024-01-02', @@ -297,15 +295,6 @@ export const MOCK_ERROR = [ }, error: new Error('Mock graphql error'), }, - { - request: { - query: DELETE_CAMPAIGN_MUTATION, - variables: { - id: 'campaignId1', - }, - }, - error: new Error('Mock graphql error'), - }, ]; export const EMPTY_MOCKS = [ @@ -321,6 +310,8 @@ export const EMPTY_MOCKS = [ result: { data: { getFundById: { + name: 'Fund 1', + isArchived: false, campaigns: [], }, }, diff --git a/src/screens/OrganizationFunds/FundDeleteModal.test.tsx b/src/screens/OrganizationFunds/FundDeleteModal.test.tsx deleted file mode 100644 index 41fcd3ec5e..0000000000 --- a/src/screens/OrganizationFunds/FundDeleteModal.test.tsx +++ /dev/null @@ -1,100 +0,0 @@ -import React from 'react'; -import type { ApolloLink } from '@apollo/client'; -import { MockedProvider } from '@apollo/react-testing'; -import { LocalizationProvider } from '@mui/x-date-pickers'; -import type { RenderResult } from '@testing-library/react'; -import { fireEvent, render, screen, waitFor } from '@testing-library/react'; -import { I18nextProvider } from 'react-i18next'; -import { Provider } from 'react-redux'; -import { BrowserRouter } from 'react-router-dom'; -import { store } from 'state/store'; -import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; -import i18nForTest from '../../utils/i18nForTest'; -import { StaticMockLink } from 'utils/StaticMockLink'; -import { toast } from 'react-toastify'; -import type { InterfaceDeleteFundModal } from './FundDeleteModal'; -import FundDeleteModal from './FundDeleteModal'; -import { MOCKS, MOCKS_ERROR } from './OrganizationFundsMocks'; - -jest.mock('react-toastify', () => ({ - toast: { - success: jest.fn(), - error: jest.fn(), - }, -})); - -const link1 = new StaticMockLink(MOCKS); -const link2 = new StaticMockLink(MOCKS_ERROR); -const translations = JSON.parse( - JSON.stringify(i18nForTest.getDataByLanguage('en')?.translation.funds), -); - -const fundProps: InterfaceDeleteFundModal = { - isOpen: true, - hide: jest.fn(), - fund: { - _id: 'fundId', - name: 'Fund 1', - refrenceNumber: '1111', - taxDeductible: true, - isArchived: false, - isDefault: false, - createdAt: '2024-06-22', - organizationId: 'orgId', - creator: { - _id: 'creatorId1', - firstName: 'John', - lastName: 'Doe', - }, - }, - refetchFunds: jest.fn(), -}; -const renderFundDeleteModal = ( - link: ApolloLink, - props: InterfaceDeleteFundModal, -): RenderResult => { - return render( - - - - - - - - - - - , - ); -}; - -describe('FundDeleteModal', () => { - it('should render FundDeleteModal', () => { - renderFundDeleteModal(link1, fundProps); - expect(screen.getByTestId('deleteFundCloseBtn')).toBeInTheDocument(); - }); - - it('should successfully Delete Fund', async () => { - renderFundDeleteModal(link1, fundProps); - expect(screen.getByTestId('deleteFundCloseBtn')).toBeInTheDocument(); - - fireEvent.click(screen.getByTestId('deleteyesbtn')); - - await waitFor(() => { - expect(fundProps.refetchFunds).toHaveBeenCalled(); - expect(fundProps.hide).toHaveBeenCalled(); - expect(toast.success).toHaveBeenCalledWith(translations.fundDeleted); - }); - }); - - it('should fail to Delete Fund', async () => { - renderFundDeleteModal(link2, fundProps); - expect(screen.getByTestId('deleteFundCloseBtn')).toBeInTheDocument(); - - fireEvent.click(screen.getByTestId('deleteyesbtn')); - - await waitFor(() => { - expect(toast.error).toHaveBeenCalledWith('Mock graphql error'); - }); - }); -}); diff --git a/src/screens/OrganizationFunds/FundDeleteModal.tsx b/src/screens/OrganizationFunds/FundDeleteModal.tsx deleted file mode 100644 index fb13206f1a..0000000000 --- a/src/screens/OrganizationFunds/FundDeleteModal.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import React from 'react'; -import { useTranslation } from 'react-i18next'; -import type { InterfaceFundInfo } from 'utils/interfaces'; -import styles from './OrganizationFunds.module.css'; -import { Button, Modal } from 'react-bootstrap'; -import { REMOVE_FUND_MUTATION } from 'GraphQl/Mutations/FundMutation'; -import { useMutation } from '@apollo/client'; -import { toast } from 'react-toastify'; - -export interface InterfaceDeleteFundModal { - isOpen: boolean; - hide: () => void; - fund: InterfaceFundInfo | null; - refetchFunds: () => void; -} - -const FundDeleteModal: React.FC = ({ - isOpen, - hide, - fund, - refetchFunds, -}) => { - const { t } = useTranslation('translation', { - keyPrefix: 'funds', - }); - const { t: tCommon } = useTranslation('common'); - - const [deleteFund] = useMutation(REMOVE_FUND_MUTATION); - - const deleteFundHandler = async (): Promise => { - try { - await deleteFund({ - variables: { - id: fund?._id, - }, - }); - refetchFunds(); - hide(); - toast.success(t('fundDeleted')); - } catch (error: unknown) { - toast.error((error as Error).message); - } - }; - - return ( - <> - - -

    {t('fundDelete')}

    - -
    - -

    {t('deleteFundMsg')}

    -
    - - - - -
    - - ); -}; - -export default FundDeleteModal; diff --git a/src/screens/OrganizationFunds/FundModal.tsx b/src/screens/OrganizationFunds/FundModal.tsx index f4c6350a1c..0f112cba9b 100644 --- a/src/screens/OrganizationFunds/FundModal.tsx +++ b/src/screens/OrganizationFunds/FundModal.tsx @@ -20,7 +20,35 @@ export interface InterfaceFundModal { orgId: string; mode: 'create' | 'edit'; } - +/** + * `FundModal` component provides a modal dialog for creating or editing a fund. + * It allows users to input fund details and submit them to the server. + * + * This component handles both the creation of new funds and the editing of existing funds, + * based on the `mode` prop. It displays a form with fields for the fund's name, description, + * and other relevant details. Upon submission, it interacts with the GraphQL API to save + * or update the fund details and triggers a refetch of the fund data. + * + * ### Props + * - `isOpen`: A boolean indicating whether the modal is open or closed. + * - `hide`: A function to close the modal. + * - `refetchFunds`: A function to refetch the fund list after a successful operation. + * - `fund`: The current fund object being edited or `null` if creating a new fund. + * - `orgId`: The ID of the organization to which the fund belongs. + * - `mode`: The mode of the modal, either 'edit' or 'create'. + * + * ### State + * - `name`: The name of the fund. + * - `description`: The description of the fund. + * - `amount`: The amount associated with the fund. + * - `status`: The status of the fund (e.g., active, archived). + * + * ### Methods + * - `handleSubmit()`: Handles form submission, creates or updates the fund, and triggers a refetch of the fund list. + * - `handleChange(event: React.ChangeEvent)`: Updates the state based on user input. + * + * @returns The rendered modal dialog. + */ const FundModal: React.FC = ({ isOpen, hide, @@ -79,7 +107,7 @@ const FundModal: React.FC = ({ taxDeductible: false, isArchived: false, }); - toast.success(t('fundCreated')); + toast.success(t('fundCreated') as string); refetchFunds(); hide(); } catch (error: unknown) { @@ -127,7 +155,7 @@ const FundModal: React.FC = ({ }); refetchFunds(); hide(); - toast.success(t('fundUpdated')); + toast.success(t('fundUpdated') as string); } catch (error: unknown) { if (error instanceof Error) { toast.error(error.message); diff --git a/src/screens/OrganizationFunds/OrganizationFunds.test.tsx b/src/screens/OrganizationFunds/OrganizationFunds.test.tsx index a1b49e68eb..c6983e1d6d 100644 --- a/src/screens/OrganizationFunds/OrganizationFunds.test.tsx +++ b/src/screens/OrganizationFunds/OrganizationFunds.test.tsx @@ -149,22 +149,6 @@ describe('OrganizationFunds Screen =>', () => { ); }); - it('open and closes delete fund modal', async () => { - renderOrganizationFunds(link1); - - const deleteFundBtn = await screen.findAllByTestId('deleteFundBtn'); - await waitFor(() => expect(deleteFundBtn[0]).toBeInTheDocument()); - userEvent.click(deleteFundBtn[0]); - - await waitFor(() => - expect(screen.getByText(translations.fundDelete)).toBeInTheDocument(), - ); - userEvent.click(screen.getByTestId('deleteFundCloseBtn')); - await waitFor(() => - expect(screen.queryByTestId('deleteFundCloseBtn')).toBeNull(), - ); - }); - it('Search the Funds list by name', async () => { renderOrganizationFunds(link1); const searchField = await screen.findByTestId('searchByName'); diff --git a/src/screens/OrganizationFunds/OrganizationFunds.tsx b/src/screens/OrganizationFunds/OrganizationFunds.tsx index 4357877105..29ffb0d865 100644 --- a/src/screens/OrganizationFunds/OrganizationFunds.tsx +++ b/src/screens/OrganizationFunds/OrganizationFunds.tsx @@ -13,7 +13,6 @@ import React, { useCallback, useMemo, useState } from 'react'; import dayjs from 'dayjs'; import Loader from 'components/Loader/Loader'; import FundModal from './FundModal'; -import FundDeleteModal from './FundDeleteModal'; import { FUND_LIST } from 'GraphQl/Queries/fundQueries'; import styles from './OrganizationFunds.module.css'; import type { InterfaceFundInfo } from 'utils/interfaces'; @@ -39,11 +38,40 @@ const dataGridStyle = { }, }; -enum ModalState { - SAME = 'same', - DELETE = 'delete', -} - +/** + * `organizationFunds` component displays a list of funds for a specific organization, + * allowing users to search, sort, view and edit funds. + * + * This component utilizes the `DataGrid` from Material-UI to present the list of funds in a tabular format, + * and includes functionality for filtering and sorting. It also handles the opening and closing of modals + * for creating and editing. + * + * It includes: + * - A search input field to filter funds by name. + * - A dropdown menu to sort funds by creation date. + * - A button to create a new fund. + * - A table to display the list of funds with columns for fund details and actions. + * - Modals for creating and editing funds. + * + * ### GraphQL Queries + * - `FUND_LIST`: Fetches a list of funds for the given organization, filtered and sorted based on the provided parameters. + * + * ### Props + * - `orgId`: The ID of the organization whose funds are being managed. + * + * ### State + * - `fund`: The currently selected fund for editing or deletion. + * - `searchTerm`: The current search term used for filtering funds. + * - `sortBy`: The current sorting order for funds. + * - `modalState`: The state of the modals (edit/create). + * - `fundModalMode`: The mode of the fund modal (edit or create). + * + * ### Methods + * - `handleOpenModal(fund: InterfaceFundInfo | null, mode: 'edit' | 'create')`: Opens the fund modal with the given fund and mode. + * - `handleClick(fundId: string)`: Navigates to the campaign page for the specified fund. + * + * @returns The rendered component. + */ const organizationFunds = (): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'funds', @@ -63,29 +91,18 @@ const organizationFunds = (): JSX.Element => { 'createdAt_DESC', ); - const [modalState, setModalState] = useState<{ - [key in ModalState]: boolean; - }>({ - [ModalState.SAME]: false, - [ModalState.DELETE]: false, - }); + const [modalState, setModalState] = useState(false); const [fundModalMode, setFundModalMode] = useState<'edit' | 'create'>( 'create', ); - const openModal = (modal: ModalState): void => - setModalState((prevState) => ({ ...prevState, [modal]: true })); - - const closeModal = (modal: ModalState): void => - setModalState((prevState) => ({ ...prevState, [modal]: false })); - const handleOpenModal = useCallback( (fund: InterfaceFundInfo | null, mode: 'edit' | 'create'): void => { setFund(fund); setFundModalMode(mode); - openModal(ModalState.SAME); + setModalState(true); }, - [openModal], + [], ); const { @@ -108,14 +125,6 @@ const organizationFunds = (): JSX.Element => { }, }); - const handleDeleteClick = useCallback( - (fund: InterfaceFundInfo): void => { - setFund(fund); - openModal(ModalState.DELETE); - }, - [openModal], - ); - const funds = useMemo(() => fundData?.fundsByOrganization ?? [], [fundData]); const handleClick = (fundId: string): void => { @@ -241,15 +250,6 @@ const organizationFunds = (): JSX.Element => { > - ); }, @@ -369,20 +369,13 @@ const organizationFunds = (): JSX.Element => { isRowSelectable={() => false} /> closeModal(ModalState.SAME)} + isOpen={modalState} + hide={() => setModalState(false)} refetchFunds={refetchFunds} fund={fund} orgId={orgId} mode={fundModalMode} /> - - closeModal(ModalState.DELETE)} - fund={fund} - refetchFunds={refetchFunds} - />
    ); }; diff --git a/src/screens/OrganizationFunds/OrganizationFundsMocks.ts b/src/screens/OrganizationFunds/OrganizationFundsMocks.ts index cd03dc7f31..81e5a0fb64 100644 --- a/src/screens/OrganizationFunds/OrganizationFundsMocks.ts +++ b/src/screens/OrganizationFunds/OrganizationFundsMocks.ts @@ -1,6 +1,5 @@ import { CREATE_FUND_MUTATION, - REMOVE_FUND_MUTATION, UPDATE_FUND_MUTATION, } from 'GraphQl/Mutations/FundMutation'; import { FUND_LIST } from 'GraphQl/Queries/fundQueries'; @@ -169,21 +168,6 @@ export const MOCKS = [ }, }, }, - { - request: { - query: REMOVE_FUND_MUTATION, - variables: { - id: 'fundId', - }, - }, - result: { - data: { - removeFund: { - _id: 'fundId', - }, - }, - }, - }, ]; export const NO_FUNDS = [ @@ -230,15 +214,6 @@ export const MOCKS_ERROR = [ }, error: new Error('Mock graphql error'), }, - { - request: { - query: REMOVE_FUND_MUTATION, - variables: { - id: 'fundId', - }, - }, - error: new Error('Mock graphql error'), - }, { request: { query: UPDATE_FUND_MUTATION, diff --git a/src/screens/OrganizationPeople/AddMember.tsx b/src/screens/OrganizationPeople/AddMember.tsx index 9737ef5c50..4c1f15106e 100644 --- a/src/screens/OrganizationPeople/AddMember.tsx +++ b/src/screens/OrganizationPeople/AddMember.tsx @@ -31,6 +31,7 @@ import type { InterfaceQueryUserListItem, } from 'utils/interfaces'; import styles from './OrganizationPeople.module.css'; +import Avatar from 'components/Avatar/Avatar'; const StyledTableCell = styled(TableCell)(({ theme }) => ({ [`&.${tableCellClasses.head}`]: { @@ -48,6 +49,15 @@ const StyledTableRow = styled(TableRow)(() => ({ }, })); +/** + * AddMember component is used to add new members to the organization by selecting from + * the existing users or creating a new user. + * It uses the following queries and mutations: + * ORGANIZATIONS_LIST, + * ORGANIZATIONS_MEMBER_CONNECTION_LIST, + * USERS_CONNECTION_LIST, + * ADD_MEMBER_MUTATION,SIGNUP_MUTATION. + */ function AddMember(): JSX.Element { const { t: translateOrgPeople } = useTranslation('translation', { keyPrefix: 'organizationPeople', @@ -92,7 +102,7 @@ function AddMember(): JSX.Element { orgid: currentUrl, }, }); - toast.success(tCommon('addedSuccessfully', { item: 'Member' })); + toast.success(tCommon('addedSuccessfully', { item: 'Member' }) as string); memberRefetch({ orgId: currentUrl, }); @@ -184,11 +194,11 @@ function AddMember(): JSX.Element { createUserVariables.lastName ) ) { - toast.error(translateOrgPeople('invalidDetailsMessage')); + toast.error(translateOrgPeople('invalidDetailsMessage') as string); } else if ( createUserVariables.password !== createUserVariables.confirmPassword ) { - toast.error(translateOrgPeople('passwordNotMatch')); + toast.error(translateOrgPeople('passwordNotMatch') as string); } else { try { const registeredUser = await registerMutation({ @@ -287,8 +297,8 @@ function AddMember(): JSX.Element { { openAddUserModal(); @@ -300,8 +310,8 @@ function AddMember(): JSX.Element { { openCreateNewUserModal(); @@ -357,6 +367,9 @@ function AddMember(): JSX.Element { # + + {translateAddMember('profile')} + {translateAddMember('user')} @@ -380,6 +393,24 @@ function AddMember(): JSX.Element { {index + 1} + + {userDetails.user.image ? ( + avatar + ) : ( + + )} + { userEvent.click(screen.getByTestId('existingUser')); await wait(); - expect(screen.getByTestId('addExistingUserModal')).toBeInTheDocument(); + expect( + screen.getAllByTestId('addExistingUserModal').length, + ).toBeGreaterThan(0); await wait(); - userEvent.click(screen.getByTestId('addBtn')); + const addBtn = screen.getAllByTestId('addBtn'); + userEvent.click(addBtn[0]); }); test('Open and search existing user', async () => { @@ -1353,3 +1382,54 @@ describe('Organization People Page', () => { expect(screen.queryByText(/Nothing Found !!/i)).toBeInTheDocument(); }); }); + +test('Open and check if profile image is displayed for existing user', async () => { + window.location.assign('/orgpeople/orgid'); + render( + + + + + + + + + , + ); + + // Wait for the component to finish rendering + await wait(); + + // Click on the dropdown toggle to open the menu + userEvent.click(screen.getByTestId('addMembers')); + await wait(); + + // Click on the "Admins" option in the dropdown menu + userEvent.click(screen.getByTestId('existingUser')); + await wait(); + + expect(screen.getByTestId('addExistingUserModal')).toBeInTheDocument(); + await wait(); + + expect(screen.getAllByTestId('user').length).toBeGreaterThan(0); + await wait(); + + // Check if the image is rendered + expect(screen.getAllByTestId('profileImage').length).toBeGreaterThan(0); + await wait(); + + const images = await screen.findAllByAltText('avatar'); + expect(images.length).toBeGreaterThan(0); + await wait(); + + const avatarImages = await screen.findAllByAltText('Dummy Avatar'); + expect(avatarImages.length).toBeGreaterThan(0); + await wait(); +}); diff --git a/src/screens/OrganizationPeople/OrganizationPeople.tsx b/src/screens/OrganizationPeople/OrganizationPeople.tsx index 24b8f0a2ad..1d230ed058 100644 --- a/src/screens/OrganizationPeople/OrganizationPeople.tsx +++ b/src/screens/OrganizationPeople/OrganizationPeople.tsx @@ -22,6 +22,12 @@ import type { GridColDef, GridCellParams } from '@mui/x-data-grid'; import { Stack } from '@mui/material'; import Avatar from 'components/Avatar/Avatar'; +/** + * OrganizationPeople component is used to display the list of members, admins and users of the organization. + * It also provides the functionality to search the members, admins and users by their full name. + * It also provides the functionality to remove the members and admins from the organization. + * @returns JSX.Element which contains the list of members, admins and users of the organization. + */ function organizationPeople(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'organizationPeople', @@ -307,10 +313,10 @@ function organizationPeople(): JSX.Element { { @@ -322,10 +328,10 @@ function organizationPeople(): JSX.Element { { @@ -335,10 +341,10 @@ function organizationPeople(): JSX.Element { { diff --git a/src/screens/OrganizationTags/OrganizationTags.module.css b/src/screens/OrganizationTags/OrganizationTags.module.css new file mode 100644 index 0000000000..7251a79d0d --- /dev/null +++ b/src/screens/OrganizationTags/OrganizationTags.module.css @@ -0,0 +1,141 @@ +.btnsContainer { + display: flex; + margin: 2rem 0; +} + +.btnsContainer .btnsBlock { + display: flex; + width: max-content; +} + +.btnsContainer .btnsBlock button { + margin-left: 1rem; + display: flex; + justify-content: center; + align-items: center; +} + +.btnsContainer .input { + flex: 1; + position: relative; + max-width: 60%; + justify-content: space-between; +} + +.btnsContainer input { + outline: 1px solid var(--bs-gray-400); +} + +.btnsContainer .input button { + width: 52px; +} + +@media (max-width: 1120px) { + .contract { + padding-left: calc(250px + 2rem + 1.5rem); + } + + .listBox .itemCard { + width: 100%; + } +} + +@media (max-width: 1020px) { + .btnsContainer { + flex-direction: column; + margin: 1.5rem 0; + } + + .btnsContainer .btnsBlock { + margin: 1.5rem 0 0 0; + justify-content: space-between; + } + + .btnsContainer .btnsBlock button { + margin: 0; + } + + .btnsContainer .btnsBlock div button { + margin-right: 1.5rem; + } +} + +/* For mobile devices */ + +@media (max-width: 520px) { + .btnsContainer { + margin-bottom: 0; + } + + .btnsContainer .btnsBlock { + display: block; + margin-top: 1rem; + margin-right: 0; + } + + .btnsContainer .btnsBlock div { + flex: 1; + } + + .btnsContainer .btnsBlock div[title='Sort organizations'] { + margin-right: 0.5rem; + } + + .btnsContainer .btnsBlock button { + margin-bottom: 1rem; + margin-right: 0; + width: 100%; + } +} + +.errorContainer { + min-height: 100vh; +} + +.errorMessage { + margin-top: 25%; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; +} + +.errorIcon { + transform: scale(1.5); + color: var(--bs-danger); + margin-bottom: 1rem; +} + +.tableHeader { + background-color: var(--bs-primary); + color: var(--bs-white); + font-size: 1rem; +} +.rowBackground { + background-color: var(--bs-white); + max-height: 120px; +} + +.subTagsLink { + color: var(--bs-blue); + font-weight: 500; + cursor: pointer; +} + +.subTagsLink i { + visibility: hidden; +} + +.subTagsLink:hover { + font-weight: 600; + text-decoration: underline; +} + +.subTagsLink:hover i { + visibility: visible; +} + +.tagsBreadCrumbs { + color: var(--bs-gray); + cursor: pointer; +} diff --git a/src/screens/OrganizationTags/OrganizationTags.test.tsx b/src/screens/OrganizationTags/OrganizationTags.test.tsx new file mode 100644 index 0000000000..923a26d982 --- /dev/null +++ b/src/screens/OrganizationTags/OrganizationTags.test.tsx @@ -0,0 +1,246 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import type { RenderResult } from '@testing-library/react'; +import { + act, + cleanup, + render, + screen, + waitFor, + waitForElementToBeRemoved, +} from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import 'jest-location-mock'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; +import { toast } from 'react-toastify'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18n from 'utils/i18nForTest'; +import OrganizationTags from './OrganizationTags'; +import { MOCKS, MOCKS_ERROR } from './OrganizationTagsMocks'; +import type { ApolloLink } from '@apollo/client'; + +const translations = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.organizationTags ?? {}, + ), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const link = new StaticMockLink(MOCKS, true); +const link2 = new StaticMockLink(MOCKS_ERROR, true); + +async function wait(ms = 500): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +const renderOrganizationTags = (link: ApolloLink): RenderResult => { + return render( + + + + + + } /> +
    } + /> +
    } + /> + + + + + , + ); +}; + +describe('Organisation Tags Page', () => { + beforeEach(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId' }), + })); + }); + + afterEach(() => { + jest.clearAllMocks(); + cleanup(); + }); + + test('Component loads correctly', async () => { + const { getByText } = renderOrganizationTags(link); + + await wait(); + + await waitFor(() => { + expect(getByText(translations.createTag)).toBeInTheDocument(); + }); + }); + + test('render error component on unsuccessful userTags query', async () => { + const { queryByText } = renderOrganizationTags(link2); + + await wait(); + + await waitFor(() => { + expect(queryByText(translations.create)).not.toBeInTheDocument(); + }); + }); + + test('opens and closes the create tag modal', async () => { + renderOrganizationTags(link); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('createTagBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('createTagBtn')); + + await waitFor(() => { + return expect( + screen.findByTestId('closeCreateTagModal'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('closeCreateTagModal')); + + await waitForElementToBeRemoved(() => + screen.queryByTestId('closeCreateTagModal'), + ); + }); + + test('opens and closes the remove tag modal', async () => { + renderOrganizationTags(link); + + await wait(); + + await waitFor(() => { + expect(screen.getAllByTestId('removeUserTagBtn')[0]).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('removeUserTagBtn')[0]); + + await waitFor(() => { + return expect( + screen.findByTestId('removeUserTagModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('removeUserTagModalCloseBtn')); + + await waitForElementToBeRemoved(() => + screen.queryByTestId('removeUserTagModalCloseBtn'), + ); + }); + + test('navigates to sub tags screen after clicking on a tag', async () => { + renderOrganizationTags(link); + + await wait(); + + await waitFor(() => { + expect(screen.getAllByTestId('tagName')[0]).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('tagName')[0]); + + await waitFor(() => { + expect(screen.getByTestId('subTagsScreen')).toBeInTheDocument(); + }); + }); + + test('navigates to manage tag page after clicking manage tag option', async () => { + renderOrganizationTags(link); + + await wait(); + + await waitFor(() => { + expect(screen.getAllByTestId('manageTagBtn')[0]).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('manageTagBtn')[0]); + + await waitFor(() => { + expect(screen.getByTestId('manageTagScreen')).toBeInTheDocument(); + }); + }); + + test('paginates between different pages', async () => { + renderOrganizationTags(link); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('nextPagBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('nextPagBtn')); + + await waitFor(() => { + expect(screen.getAllByTestId('tagName')[0]).toHaveTextContent('6'); + }); + + await waitFor(() => { + expect(screen.getByTestId('previousPageBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('previousPageBtn')); + + await waitFor(() => { + expect(screen.getAllByTestId('tagName')[0]).toHaveTextContent('1'); + }); + }); + + test('creates a new user tag', async () => { + renderOrganizationTags(link); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('createTagBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('createTagBtn')); + + userEvent.type( + screen.getByPlaceholderText(translations.tagNamePlaceholder), + '7', + ); + + userEvent.click(screen.getByTestId('createTagSubmitBtn')); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.tagCreationSuccess); + }); + }); + + test('removes a user tag', async () => { + renderOrganizationTags(link); + + await wait(); + + await waitFor(() => { + expect(screen.getAllByTestId('removeUserTagBtn')[0]).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('removeUserTagBtn')[0]); + + userEvent.click(screen.getByTestId('removeUserTagSubmitBtn')); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.tagRemovalSuccess); + }); + }); +}); diff --git a/src/screens/OrganizationTags/OrganizationTags.tsx b/src/screens/OrganizationTags/OrganizationTags.tsx new file mode 100644 index 0000000000..e4bf0604e9 --- /dev/null +++ b/src/screens/OrganizationTags/OrganizationTags.tsx @@ -0,0 +1,515 @@ +import { useMutation, useQuery, type ApolloError } from '@apollo/client'; +import { Search, WarningAmberRounded } from '@mui/icons-material'; +import SortIcon from '@mui/icons-material/Sort'; +import Loader from 'components/Loader/Loader'; +import IconComponent from 'components/IconComponent/IconComponent'; +import { useNavigate, useParams, Link } from 'react-router-dom'; +import type { ChangeEvent } from 'react'; +import React, { useState } from 'react'; +import { Form } from 'react-bootstrap'; +import Button from 'react-bootstrap/Button'; +import Dropdown from 'react-bootstrap/Dropdown'; +import Modal from 'react-bootstrap/Modal'; +import Row from 'react-bootstrap/Row'; +import { useTranslation } from 'react-i18next'; +import { toast } from 'react-toastify'; +import type { InterfaceQueryOrganizationUserTags } from 'utils/interfaces'; +import styles from './OrganizationTags.module.css'; +import { DataGrid } from '@mui/x-data-grid'; +import { dataGridStyle } from 'utils/organizationTagsUtils'; +import type { GridCellParams, GridColDef } from '@mui/x-data-grid'; +import { Stack } from '@mui/material'; +import { ORGANIZATION_USER_TAGS_LIST } from 'GraphQl/Queries/OrganizationQueries'; +import { + CREATE_USER_TAG, + REMOVE_USER_TAG, +} from 'GraphQl/Mutations/TagMutations'; + +/** + * Component that renders the Organization Tags screen when the app navigates to '/orgtags/:orgId'. + * + * This component does not accept any props and is responsible for displaying + * the content associated with the corresponding route. + */ + +function OrganizationTags(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'organizationTags', + }); + const { t: tCommon } = useTranslation('common'); + + const [createTagModalIsOpen, setCreateTagModalIsOpen] = useState(false); + + const { orgId } = useParams(); + const navigate = useNavigate(); + const [after, setAfter] = useState(null); + const [before, setBefore] = useState(null); + const [first, setFirst] = useState(5); + const [last, setLast] = useState(null); + const [tagSerialNumber, setTagSerialNumber] = useState(0); + + const [tagName, setTagName] = useState(''); + + const [removeUserTagId, setRemoveUserTagId] = useState(null); + const [removeTagModalIsOpen, setRemoveTagModalIsOpen] = useState(false); + + const showCreateTagModal = (): void => { + setTagName(''); + setCreateTagModalIsOpen(true); + }; + + const hideCreateTagModal = (): void => { + setCreateTagModalIsOpen(false); + }; + + const { + data: orgUserTagsData, + loading: orgUserTagsLoading, + error: orgUserTagsError, + refetch: orgUserTagsRefetch, + }: { + data?: { + organizations: InterfaceQueryOrganizationUserTags[]; + }; + loading: boolean; + error?: ApolloError; + refetch: () => void; + } = useQuery(ORGANIZATION_USER_TAGS_LIST, { + variables: { + id: orgId, + after: after, + before: before, + first: first, + last: last, + }, + }); + + const [create, { loading: createUserTagLoading }] = + useMutation(CREATE_USER_TAG); + + const createTag = async (e: ChangeEvent): Promise => { + e.preventDefault(); + + try { + const { data } = await create({ + variables: { + name: tagName, + organizationId: orgId, + }, + }); + + if (data) { + toast.success(t('tagCreationSuccess') as string); + orgUserTagsRefetch(); + setTagName(''); + setCreateTagModalIsOpen(false); + } + } catch (error: unknown) { + /* istanbul ignore next */ + if (error instanceof Error) { + toast.error(error.message); + } + } + }; + + const [removeUserTag] = useMutation(REMOVE_USER_TAG); + const handleRemoveUserTag = async (): Promise => { + try { + await removeUserTag({ + variables: { + id: removeUserTagId, + }, + }); + + orgUserTagsRefetch(); + toggleRemoveUserTagModal(); + toast.success(t('tagRemovalSuccess') as string); + } catch (error: unknown) { + /* istanbul ignore next */ + if (error instanceof Error) { + toast.error(error.message); + } + } + }; + + if (createUserTagLoading || orgUserTagsLoading) { + return ; + } + + if (orgUserTagsError) { + return ( +
    +
    + +
    + Error occured while loading Organization Tags Data +
    + {orgUserTagsError.message} +
    +
    +
    + ); + } + + const handleNextPage = (): void => { + setAfter(orgUserTagsData?.organizations[0].userTags.pageInfo.endCursor); + setBefore(null); + setFirst(5); + setLast(null); + setTagSerialNumber(tagSerialNumber + 1); + }; + const handlePreviousPage = (): void => { + setBefore(orgUserTagsData?.organizations[0].userTags.pageInfo.startCursor); + setAfter(null); + setFirst(null); + setLast(5); + setTagSerialNumber(tagSerialNumber - 1); + }; + + const userTagsList = orgUserTagsData?.organizations[0].userTags.edges.map( + (edge) => edge.node, + ); + + const redirectToManageTag = (tagId: string): void => { + navigate(`/orgtags/${orgId}/managetag/${tagId}`); + }; + + const redirectToSubTags = (tagId: string): void => { + navigate(`/orgtags/${orgId}/subTags/${tagId}`); + }; + + const toggleRemoveUserTagModal = (): void => { + if (removeTagModalIsOpen) setRemoveUserTagId(null); + setRemoveTagModalIsOpen(!removeTagModalIsOpen); + }; + + const columns: GridColDef[] = [ + { + field: 'id', + headerName: '#', + minWidth: 100, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return
    {tagSerialNumber * 5 + params.row.id}
    ; + }, + }, + { + field: 'tagName', + headerName: 'Tag Name', + flex: 1, + minWidth: 100, + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( +
    redirectToSubTags(params.row._id)} + > + {params.row.name} + + +
    + ); + }, + }, + { + field: 'totalSubTags', + headerName: 'Total Sub Tags', + flex: 1, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( + + {params.row.childTags.totalCount} + + ); + }, + }, + { + field: 'totalAssignedUsers', + headerName: 'Total Assigned Users', + flex: 1, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( + + {params.row.usersAssignedTo.totalCount} + + ); + }, + }, + { + field: 'actions', + headerName: 'Actions', + flex: 1, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( +
    + + + +
    + ); + }, + }, + ]; + + return ( + <> + +
    +
    +
    + + +
    +
    + +
    + +
    + +
    +
    +
    + +
    + +
    + {'Tags'} +
    +
    + row._id} + slots={{ + noRowsOverlay: /* istanbul ignore next */ () => ( + + {t('noTagsFound')} + + ), + }} + sx={dataGridStyle} + getRowClassName={() => `${styles.rowBackground}`} + autoHeight + rowHeight={65} + rows={userTagsList?.map((fund, index) => ({ + id: index + 1, + ...fund, + }))} + columns={columns} + isRowSelectable={() => false} + /> +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    + + {/* Create Tag Modal */} + + + {t('tagDetails')} + +
    + + {t('tagName')} + { + setTagName(e.target.value); + }} + /> + + + + + + +
    +
    + + {/* Remove User Tag Modal */} + + + + {t('removeUserTag')} + + + {t('removeUserTagMessage')} + + + + + + + ); +} + +export default OrganizationTags; diff --git a/src/screens/OrganizationTags/OrganizationTagsMocks.ts b/src/screens/OrganizationTags/OrganizationTagsMocks.ts new file mode 100644 index 0000000000..3700c66c46 --- /dev/null +++ b/src/screens/OrganizationTags/OrganizationTagsMocks.ts @@ -0,0 +1,291 @@ +import { + CREATE_USER_TAG, + REMOVE_USER_TAG, +} from 'GraphQl/Mutations/TagMutations'; +import { ORGANIZATION_USER_TAGS_LIST } from 'GraphQl/Queries/OrganizationQueries'; + +export const MOCKS = [ + { + request: { + query: ORGANIZATION_USER_TAGS_LIST, + variables: { + id: '123', + after: null, + before: null, + first: 5, + last: null, + }, + }, + result: { + data: { + organizations: [ + { + userTags: { + edges: [ + { + node: { + _id: '1', + name: 'userTag 1', + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 5, + }, + }, + cursor: '1', + }, + { + node: { + _id: '2', + name: 'userTag 2', + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 0, + }, + }, + cursor: '2', + }, + { + node: { + _id: '3', + name: 'userTag 3', + usersAssignedTo: { + totalCount: 0, + }, + childTags: { + totalCount: 5, + }, + }, + cursor: '3', + }, + { + node: { + _id: '4', + name: 'userTag 4', + usersAssignedTo: { + totalCount: 0, + }, + childTags: { + totalCount: 0, + }, + }, + cursor: '4', + }, + { + node: { + _id: '5', + name: 'userTag 5', + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 5, + }, + }, + cursor: '5', + }, + ], + pageInfo: { + startCursor: '1', + endCursor: '5', + hasNextPage: true, + hasPreviousPage: false, + }, + totalCount: 6, + }, + }, + ], + }, + }, + }, + { + request: { + query: ORGANIZATION_USER_TAGS_LIST, + variables: { + id: '123', + after: '5', + before: null, + first: 5, + last: null, + }, + }, + result: { + data: { + organizations: [ + { + userTags: { + edges: [ + { + node: { + _id: '6', + name: 'userTag 6', + usersAssignedTo: { + totalCount: 0, + }, + childTags: { + totalCount: 0, + }, + }, + cursor: '6', + }, + ], + pageInfo: { + startCursor: '6', + endCursor: '6', + hasNextPage: false, + hasPreviousPage: true, + }, + totalCount: 6, + }, + }, + ], + }, + }, + }, + { + request: { + query: ORGANIZATION_USER_TAGS_LIST, + variables: { + id: '123', + after: null, + before: '6', + first: null, + last: 5, + }, + }, + result: { + data: { + organizations: [ + { + userTags: { + edges: [ + { + node: { + _id: '1', + name: 'userTag 1', + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 5, + }, + }, + cursor: '1', + }, + { + node: { + _id: '2', + name: 'userTag 2', + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 0, + }, + }, + cursor: '2', + }, + { + node: { + _id: '3', + name: 'userTag 3', + usersAssignedTo: { + totalCount: 0, + }, + childTags: { + totalCount: 5, + }, + }, + cursor: '3', + }, + { + node: { + _id: '4', + name: 'userTag 4', + usersAssignedTo: { + totalCount: 0, + }, + childTags: { + totalCount: 0, + }, + }, + cursor: '4', + }, + { + node: { + _id: '5', + name: 'userTag 5', + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 5, + }, + }, + cursor: '5', + }, + ], + pageInfo: { + startCursor: '1', + endCursor: '5', + hasNextPage: true, + hasPreviousPage: false, + }, + totalCount: 6, + }, + }, + ], + }, + }, + }, + { + request: { + query: CREATE_USER_TAG, + variables: { + name: '7', + organizationId: '123', + }, + }, + result: { + data: { + createUserTag: { + _id: '7', + }, + }, + }, + }, + { + request: { + query: REMOVE_USER_TAG, + variables: { + id: '1', + }, + }, + result: { + data: { + removeUserTag: { + _id: '1', + }, + }, + }, + }, +]; + +export const MOCKS_ERROR = [ + { + request: { + query: ORGANIZATION_USER_TAGS_LIST, + variables: { + id: '123', + after: null, + before: null, + first: 5, + last: null, + }, + }, + error: new Error('Mock Graphql Error'), + }, +]; diff --git a/src/screens/OrganizationVenues/OrganizationVenues.tsx b/src/screens/OrganizationVenues/OrganizationVenues.tsx index 6c08733e17..c2c3afe7e4 100644 --- a/src/screens/OrganizationVenues/OrganizationVenues.tsx +++ b/src/screens/OrganizationVenues/OrganizationVenues.tsx @@ -15,13 +15,21 @@ import { DELETE_VENUE_MUTATION } from 'GraphQl/Mutations/VenueMutations'; import type { InterfaceQueryVenueListItem } from 'utils/interfaces'; import VenueCard from 'components/Venues/VenueCard'; +/** + * Component to manage and display the list of organization venues. + * Handles searching, sorting, and CRUD operations for venues. + */ function organizationVenues(): JSX.Element { + // Translation hooks for i18n support const { t } = useTranslation('translation', { keyPrefix: 'organizationVenues', }); const { t: tCommon } = useTranslation('common'); + // Setting the document title using the translation hook document.title = t('title'); + + // State hooks for managing component state const [venueModal, setVenueModal] = useState(false); const [venueModalMode, setVenueModalMode] = useState<'edit' | 'create'>( 'create', @@ -33,11 +41,13 @@ function organizationVenues(): JSX.Element { useState(null); const [venues, setVenues] = useState([]); + // Getting the organization ID from the URL parameters const { orgId } = useParams(); if (!orgId) { return ; } + // GraphQL query for fetching venue data const { data: venueData, loading: venueLoading, @@ -54,8 +64,13 @@ function organizationVenues(): JSX.Element { }, }); + // GraphQL mutation for deleting a venue const [deleteVenue] = useMutation(DELETE_VENUE_MUTATION); + /** + * Handles the deletion of a venue by ID. + * @param venueId - The ID of the venue to delete. + */ const handleDelete = async (venueId: string): Promise => { try { await deleteVenue({ @@ -68,36 +83,57 @@ function organizationVenues(): JSX.Element { } }; + /** + * Updates the search term state when the user types in the search input. + * @param event - The input change event. + */ const handleSearchChange = ( event: React.ChangeEvent, ): void => { setSearchTerm(event.target.value); }; + /** + * Updates the sort order state when the user selects a sort option. + * @param order - The order to sort venues by (highest or lowest capacity). + */ const handleSortChange = (order: 'highest' | 'lowest'): void => { setSortOrder(order); }; + /** + * Toggles the visibility of the venue modal. + */ const toggleVenueModal = (): void => { setVenueModal(!venueModal); }; + /** + * Shows the edit venue modal with the selected venue data. + * @param venueItem - The venue data to edit. + */ const showEditVenueModal = (venueItem: InterfaceQueryVenueListItem): void => { setVenueModalMode('edit'); setEditVenueData(venueItem); toggleVenueModal(); }; + /** + * Shows the create venue modal. + */ const showCreateVenueModal = (): void => { setVenueModalMode('create'); setEditVenueData(null); toggleVenueModal(); }; + + // Error handling for venue data fetch /* istanbul ignore next */ if (venueError) { errorHandler(t, venueError); } + // Updating venues state when venue data changes useEffect(() => { if (venueData && venueData.getVenueByOrgId) { setVenues(venueData.getVenueByOrgId); diff --git a/src/screens/PageNotFound/PageNotFound.tsx b/src/screens/PageNotFound/PageNotFound.tsx index 92f4a98f7e..037aeecbab 100644 --- a/src/screens/PageNotFound/PageNotFound.tsx +++ b/src/screens/PageNotFound/PageNotFound.tsx @@ -4,17 +4,26 @@ import { useTranslation } from 'react-i18next'; import useLocalStorage from 'utils/useLocalstorage'; import styles from './PageNotFound.module.css'; -import Logo from 'assets/images/talawa-logo-200x200.png'; +import Logo from 'assets/images/talawa-logo-600x600.png'; +/** + * The `PageNotFound` component displays a 404 error page when a user navigates to a non-existent route. + * It shows a message indicating that the page was not found and provides a link to redirect users back + * to the appropriate home page based on their admin status. + * + */ const PageNotFound = (): JSX.Element => { + // Translation hooks for internationalization const { t } = useTranslation('translation', { keyPrefix: 'pageNotFound', }); const { t: tCommon } = useTranslation('common'); const { t: tErrors } = useTranslation('errors'); + // Set the document title to the translated title for the 404 page document.title = t('title'); + // Get the admin status from local storage const { getItem } = useLocalStorage(); const adminFor = getItem('AdminFor'); @@ -23,6 +32,7 @@ const PageNotFound = (): JSX.Element => {
    Logo + {/* Display a message based on admin status */} {adminFor != undefined ? (

    {tCommon('talawaAdminPortal')} @@ -31,10 +41,13 @@ const PageNotFound = (): JSX.Element => {

    {t('talawaUser')}

    )}
    + {/* Display the 404 error code */}

    {t('404')}

    + {/* Display a not found message */}

    {tErrors('notFoundMsg')}

    + {/* Provide a link to redirect users based on admin status */} {adminFor != undefined ? ( {t('backToHome')} diff --git a/src/screens/Requests/Requests.test.tsx b/src/screens/Requests/Requests.test.tsx index bf1a533870..4606fdae08 100644 --- a/src/screens/Requests/Requests.test.tsx +++ b/src/screens/Requests/Requests.test.tsx @@ -1,6 +1,6 @@ -import React from 'react'; +import React, { act } from 'react'; import { MockedProvider } from '@apollo/react-testing'; -import { act, render, screen } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; import 'jest-localstorage-mock'; import 'jest-location-mock'; import { I18nextProvider } from 'react-i18next'; diff --git a/src/screens/Requests/Requests.tsx b/src/screens/Requests/Requests.tsx index a779bd414c..38bc51195e 100644 --- a/src/screens/Requests/Requests.tsx +++ b/src/screens/Requests/Requests.tsx @@ -26,14 +26,23 @@ interface InterfaceRequestsListItem { }; } +/** + * The `Requests` component fetches and displays a paginated list of membership requests + * for an organization, with functionality for searching, filtering, and infinite scrolling. + * + */ const Requests = (): JSX.Element => { + // Translation hooks for internationalization const { t } = useTranslation('translation', { keyPrefix: 'requests' }); const { t: tCommon } = useTranslation('common'); + // Set the document title to the translated title for the requests page document.title = t('title'); + // Hook for managing local storage const { getItem } = useLocalStorage(); + // Define constants and state variables const perPageResult = 8; const [isLoading, setIsLoading] = useState(true); const [hasMore, setHasMore] = useState(true); @@ -47,6 +56,7 @@ const Requests = (): JSX.Element => { const { orgId = '' } = useParams(); const organizationId = orgId; + // Query to fetch membership requests const { data, loading, fetchMore, refetch } = useQuery(MEMBERSHIP_REQUEST, { variables: { id: organizationId, @@ -57,6 +67,7 @@ const Requests = (): JSX.Element => { notifyOnNetworkStatusChange: true, }); + // Query to fetch the list of organizations const { data: orgsData } = useQuery(ORGANIZATION_CONNECTION_LIST); const [displayedRequests, setDisplayedRequests] = useState( data?.organizations[0]?.membershipRequests || [], @@ -77,25 +88,25 @@ const Requests = (): JSX.Element => { setDisplayedRequests(membershipRequests); }, [data]); - // To clear the search when the component is unmounted + // Clear the search field when the component is unmounted useEffect(() => { return () => { setSearchByName(''); }; }, []); - // Warn if there is no organization + // Show a warning if there are no organizations useEffect(() => { if (!orgsData) { return; } if (orgsData.organizationsConnection.length === 0) { - toast.warning(t('noOrgError')); + toast.warning(t('noOrgError') as string); } }, [orgsData]); - // Send to orgList page if user is not admin + // Redirect to orgList page if the user is not an admin useEffect(() => { if (userRole != 'ADMIN' && userRole != 'SUPERADMIN') { window.location.assign('/orglist'); @@ -111,6 +122,11 @@ const Requests = (): JSX.Element => { } }, [loading]); + /** + * Handles the search input change and refetches the data based on the search value. + * + * @param value - The search term entered by the user. + */ const handleSearch = (value: string): void => { setSearchByName(value); if (value === '') { @@ -124,6 +140,11 @@ const Requests = (): JSX.Element => { }); }; + /** + * Handles search input when the Enter key is pressed. + * + * @param e - The keyboard event. + */ const handleSearchByEnter = ( e: React.KeyboardEvent, ): void => { @@ -133,6 +154,9 @@ const Requests = (): JSX.Element => { } }; + /** + * Handles the search button click to trigger the search. + */ const handleSearchByBtnClick = (): void => { const inputElement = document.getElementById( 'searchRequests', @@ -141,6 +165,9 @@ const Requests = (): JSX.Element => { handleSearch(inputValue); }; + /** + * Resets search and refetches the data. + */ const resetAndRefetch = (): void => { refetch({ first: perPageResult, @@ -149,6 +176,10 @@ const Requests = (): JSX.Element => { }); setHasMore(true); }; + + /** + * Loads more requests when scrolling to the bottom of the page. + */ /* istanbul ignore next */ const loadMoreRequests = (): void => { setIsLoadingMore(true); @@ -188,6 +219,7 @@ const Requests = (): JSX.Element => { }); }; + // Header titles for the table const headerTitles: string[] = [ t('sl_no'), tCommon('name'), diff --git a/src/screens/SubTags/SubTags.module.css b/src/screens/SubTags/SubTags.module.css new file mode 100644 index 0000000000..2fed58ec52 --- /dev/null +++ b/src/screens/SubTags/SubTags.module.css @@ -0,0 +1,137 @@ +.btnsContainer { + display: flex; + margin: 2rem 0; +} + +.btnsContainer .btnsBlock { + display: flex; + width: max-content; +} + +.btnsContainer .btnsBlock button { + margin-left: 1rem; + display: flex; + justify-content: center; + align-items: center; +} + +.btnsContainer .input { + flex: 1; + position: relative; + max-width: 60%; + justify-content: space-between; +} + +.btnsContainer input { + outline: 1px solid var(--bs-gray-400); +} + +.btnsContainer .input button { + width: 52px; +} + +@media (max-width: 1020px) { + .btnsContainer { + flex-direction: column; + margin: 1.5rem 0; + } + + .btnsContainer .btnsBlock { + margin: 1.5rem 0 0 0; + justify-content: space-between; + } + + .btnsContainer .btnsBlock button { + margin: 0; + } + + .btnsContainer .btnsBlock div button { + margin-right: 1.5rem; + } +} + +/* For mobile devices */ + +@media (max-width: 520px) { + .btnsContainer { + margin-bottom: 0; + } + + .btnsContainer .btnsBlock { + display: block; + margin-top: 1rem; + margin-right: 0; + } + + .btnsContainer .btnsBlock div { + flex: 1; + } + + .btnsContainer .btnsBlock div[title='Sort organizations'] { + margin-right: 0.5rem; + } + + .btnsContainer .btnsBlock button { + margin-bottom: 1rem; + margin-right: 0; + width: 100%; + } +} + +.errorContainer { + min-height: 100vh; +} + +.errorMessage { + margin-top: 25%; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; +} + +.errorIcon { + transform: scale(1.5); + color: var(--bs-danger); + margin-bottom: 1rem; +} + +.tableHeader { + background-color: var(--bs-primary); + color: var(--bs-white); + font-size: 1rem; +} +.rowBackground { + background-color: var(--bs-white); + max-height: 120px; +} + +.subTagsLink { + color: var(--bs-blue); + font-weight: 500; + cursor: pointer; +} + +.subTagsLink i { + visibility: hidden; +} + +.subTagsLink:hover { + font-weight: 600; + text-decoration: underline; +} + +.subTagsLink:hover i { + visibility: visible; +} + +.tagsBreadCrumbs { + color: var(--bs-gray); + cursor: pointer; +} + +.tagsBreadCrumbs:hover { + color: var(--bs-blue); + font-weight: 600; + text-decoration: underline; +} diff --git a/src/screens/SubTags/SubTags.test.tsx b/src/screens/SubTags/SubTags.test.tsx new file mode 100644 index 0000000000..1780027639 --- /dev/null +++ b/src/screens/SubTags/SubTags.test.tsx @@ -0,0 +1,325 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import type { RenderResult } from '@testing-library/react'; +import { + act, + cleanup, + render, + screen, + waitFor, + waitForElementToBeRemoved, +} from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import 'jest-location-mock'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; +import { toast } from 'react-toastify'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18n from 'utils/i18nForTest'; +import SubTags from './SubTags'; +import { + MOCKS, + MOCKS_ERROR_SUB_TAGS, + MOCKS_ERROR_TAG_ANCESTORS, +} from './SubTagsMocks'; +import { InMemoryCache, type ApolloLink } from '@apollo/client'; + +const translations = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.organizationTags ?? {}, + ), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const link = new StaticMockLink(MOCKS, true); +const link2 = new StaticMockLink(MOCKS_ERROR_SUB_TAGS, true); +const link3 = new StaticMockLink(MOCKS_ERROR_TAG_ANCESTORS, true); + +async function wait(ms = 500): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +const cache = new InMemoryCache({ + typePolicies: { + Query: { + fields: { + getUserTag: { + keyArgs: false, + merge(existing = {}, incoming) { + return incoming; + }, + }, + }, + }, + }, +}); + +const renderSubTags = (link: ApolloLink): RenderResult => { + return render( + + + + + +
    } + /> +
    } + /> + } + /> + + + + + , + ); +}; + +describe('Organisation Tags Page', () => { + beforeEach(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId' }), + })); + cache.reset(); + }); + + afterEach(() => { + jest.clearAllMocks(); + cleanup(); + }); + + test('Component loads correctly', async () => { + const { getByText } = renderSubTags(link); + + await wait(); + + await waitFor(() => { + expect(getByText(translations.addChildTag)).toBeInTheDocument(); + }); + }); + + test('render error component on unsuccessful subtags query', async () => { + const { queryByText } = renderSubTags(link2); + + await wait(); + + await waitFor(() => { + expect(queryByText(translations.addChildTag)).not.toBeInTheDocument(); + }); + }); + + test('renders error component on unsuccessful userTag ancestors query', async () => { + const { queryByText } = renderSubTags(link3); + + await wait(); + + await waitFor(() => { + expect(queryByText(translations.addChildTag)).not.toBeInTheDocument(); + }); + }); + + test('opens and closes the create tag modal', async () => { + renderSubTags(link); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('addSubTagBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('addSubTagBtn')); + + await waitFor(() => { + return expect( + screen.findByTestId('addSubTagModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('addSubTagModalCloseBtn')); + + await waitForElementToBeRemoved(() => + screen.queryByTestId('addSubTagModalCloseBtn'), + ); + }); + + test('opens and closes the remove tag modal', async () => { + renderSubTags(link); + + await wait(); + + await waitFor(() => { + expect(screen.getAllByTestId('removeUserTagBtn')[0]).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('removeUserTagBtn')[0]); + + await waitFor(() => { + return expect( + screen.findByTestId('removeUserTagModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('removeUserTagModalCloseBtn')); + + await waitForElementToBeRemoved(() => + screen.queryByTestId('removeUserTagModalCloseBtn'), + ); + }); + + test('navigates to manage tag screen after clicking manage tag option', async () => { + renderSubTags(link); + + await wait(); + + await waitFor(() => { + expect(screen.getAllByTestId('manageTagBtn')[0]).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('manageTagBtn')[0]); + + await waitFor(() => { + expect(screen.getByTestId('manageTagScreen')).toBeInTheDocument(); + }); + }); + + test('navigates to sub tags screen after clicking on a tag', async () => { + renderSubTags(link); + + await wait(); + + await waitFor(() => { + expect(screen.getAllByTestId('tagName')[0]).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('tagName')[0]); + + await waitFor(() => { + expect(screen.getByTestId('addSubTagBtn')).toBeInTheDocument(); + }); + }); + + test('navigates to the different sub tag screen screen after clicking a tag in the breadcrumbs', async () => { + renderSubTags(link); + + await wait(); + + await waitFor(() => { + expect(screen.getAllByTestId('redirectToSubTags')[0]).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('redirectToSubTags')[0]); + + await waitFor(() => { + expect(screen.getByTestId('addSubTagBtn')).toBeInTheDocument(); + }); + }); + + test('navigates to organization tags screen screen after clicking tha all tags option in the breadcrumbs', async () => { + renderSubTags(link); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('allTagsBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('allTagsBtn')); + + await waitFor(() => { + expect(screen.getByTestId('orgtagsScreen')).toBeInTheDocument(); + }); + }); + + test('navigates to manage tags screen for the current tag after clicking tha manageCurrentTag button', async () => { + renderSubTags(link); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('manageCurrentTagBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('manageCurrentTagBtn')); + + await waitFor(() => { + expect(screen.getByTestId('manageTagScreen')).toBeInTheDocument(); + }); + }); + + test('paginates between different pages', async () => { + renderSubTags(link); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('nextPagBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('nextPagBtn')); + + await waitFor(() => { + expect(screen.getAllByTestId('tagName')[0]).toHaveTextContent('subTag 6'); + }); + + await waitFor(() => { + expect(screen.getByTestId('previousPageBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('previousPageBtn')); + + await waitFor(() => { + expect(screen.getAllByTestId('tagName')[0]).toHaveTextContent('subTag 1'); + }); + }); + + test('adds a new sub tag to the current tag', async () => { + renderSubTags(link); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('addSubTagBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('addSubTagBtn')); + + userEvent.type( + screen.getByPlaceholderText(translations.tagNamePlaceholder), + 'subTag 7', + ); + + userEvent.click(screen.getByTestId('addSubTagSubmitBtn')); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.tagCreationSuccess); + }); + }); + + test('removes a sub tag', async () => { + renderSubTags(link); + + await wait(); + + await waitFor(() => { + expect(screen.getAllByTestId('removeUserTagBtn')[0]).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('removeUserTagBtn')[0]); + + userEvent.click(screen.getByTestId('removeUserTagSubmitBtn')); + + await waitFor(() => { + expect(toast.success).toBeCalledWith(translations.tagRemovalSuccess); + }); + }); +}); diff --git a/src/screens/SubTags/SubTags.tsx b/src/screens/SubTags/SubTags.tsx new file mode 100644 index 0000000000..b381c9f816 --- /dev/null +++ b/src/screens/SubTags/SubTags.tsx @@ -0,0 +1,572 @@ +import { useMutation, useQuery, type ApolloError } from '@apollo/client'; +import { Search, WarningAmberRounded } from '@mui/icons-material'; +import SortIcon from '@mui/icons-material/Sort'; +import Loader from 'components/Loader/Loader'; +import IconComponent from 'components/IconComponent/IconComponent'; +import { useNavigate, useParams, Link } from 'react-router-dom'; +import type { ChangeEvent } from 'react'; +import React, { useState } from 'react'; +import { Form } from 'react-bootstrap'; +import Button from 'react-bootstrap/Button'; +import Dropdown from 'react-bootstrap/Dropdown'; +import Modal from 'react-bootstrap/Modal'; +import Row from 'react-bootstrap/Row'; +import { useTranslation } from 'react-i18next'; +import { toast } from 'react-toastify'; +import type { InterfaceQueryUserTagChildTags } from 'utils/interfaces'; +import styles from './SubTags.module.css'; +import { DataGrid } from '@mui/x-data-grid'; +import { dataGridStyle } from 'utils/organizationTagsUtils'; +import type { GridCellParams, GridColDef } from '@mui/x-data-grid'; +import { Stack } from '@mui/material'; +import { + CREATE_USER_TAG, + REMOVE_USER_TAG, +} from 'GraphQl/Mutations/TagMutations'; +import { + USER_TAG_ANCESTORS, + USER_TAG_SUB_TAGS, +} from 'GraphQl/Queries/userTagQueries'; + +/** + * Component that renders the SubTags screen when the app navigates to '/orgtags/:orgId/subtags/:tagId'. + * + * This component does not accept any props and is responsible for displaying + * the content associated with the corresponding route. + */ + +function SubTags(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'organizationTags', + }); + const { t: tCommon } = useTranslation('common'); + + const [addSubTagModalIsOpen, setAddSubTagModalIsOpen] = useState(false); + + const { orgId, tagId: parentTagId } = useParams(); + + const navigate = useNavigate(); + + const [after, setAfter] = useState(null); + const [before, setBefore] = useState(null); + const [first, setFirst] = useState(5); + const [last, setLast] = useState(null); + + const [tagName, setTagName] = useState(''); + + const [removeUserTagId, setRemoveUserTagId] = useState(null); + const [removeUserTagModalIsOpen, setRemoveUserTagModalIsOpen] = + useState(false); + + const showAddSubTagModal = (): void => { + setAddSubTagModalIsOpen(true); + }; + + const hideAddSubTagModal = (): void => { + setAddSubTagModalIsOpen(false); + setTagName(''); + }; + + const { + data: subTagsData, + loading: subTagsLoading, + error: subTagsError, + refetch: subTagsRefetch, + }: { + data?: { + getUserTag: InterfaceQueryUserTagChildTags; + }; + loading: boolean; + error?: ApolloError; + refetch: () => void; + } = useQuery(USER_TAG_SUB_TAGS, { + variables: { + id: parentTagId, + after: after, + before: before, + first: first, + last: last, + }, + }); + + const { + data: orgUserTagAncestorsData, + loading: orgUserTagsAncestorsLoading, + error: orgUserTagsAncestorsError, + }: { + data?: { + getUserTagAncestors: { + _id: string; + name: string; + }[]; + }; + loading: boolean; + error?: ApolloError; + refetch: () => void; + } = useQuery(USER_TAG_ANCESTORS, { + variables: { + id: parentTagId, + }, + }); + + const [create, { loading: createUserTagLoading }] = + useMutation(CREATE_USER_TAG); + + const addSubTag = async (e: ChangeEvent): Promise => { + e.preventDefault(); + + try { + const { data } = await create({ + variables: { + name: tagName, + organizationId: orgId, + parentTagId, + }, + }); + + /* istanbul ignore next */ + if (data) { + toast.success(t('tagCreationSuccess') as string); + subTagsRefetch(); + setTagName(''); + setAddSubTagModalIsOpen(false); + } + } catch (error: unknown) { + /* istanbul ignore next */ + if (error instanceof Error) { + toast.error(error.message); + } + } + }; + + const [removeUserTag] = useMutation(REMOVE_USER_TAG); + const handleRemoveUserTag = async (): Promise => { + try { + await removeUserTag({ + variables: { + id: removeUserTagId, + }, + }); + + subTagsRefetch(); + toggleRemoveUserTagModal(); + toast.success(t('tagRemovalSuccess') as string); + } catch (error: unknown) { + /* istanbul ignore next */ + if (error instanceof Error) { + toast.error(error.message); + } + } + }; + + if (createUserTagLoading || subTagsLoading || orgUserTagsAncestorsLoading) { + return ; + } + + const handleNextPage = (): void => { + setAfter(subTagsData?.getUserTag.childTags.pageInfo.endCursor); + setBefore(null); + setFirst(5); + setLast(null); + }; + + const handlePreviousPage = (): void => { + setBefore(subTagsData?.getUserTag.childTags.pageInfo.startCursor); + setAfter(null); + setFirst(null); + setLast(5); + }; + + if (subTagsError || orgUserTagsAncestorsError) { + return ( +
    +
    + +
    + Error occured while loading{' '} + {subTagsError ? 'sub tags' : 'tag ancestors'} +
    + {subTagsError + ? subTagsError.message + : orgUserTagsAncestorsError?.message} +
    +
    +
    + ); + } + + const userTagsList = subTagsData?.getUserTag.childTags.edges.map( + (edge) => edge.node, + ); + + const orgUserTagAncestors = orgUserTagAncestorsData?.getUserTagAncestors; + + const redirectToManageTag = (tagId: string): void => { + navigate(`/orgtags/${orgId}/manageTag/${tagId}`); + }; + + const redirectToSubTags = (tagId: string): void => { + navigate(`/orgtags/${orgId}/subtags/${tagId}`); + }; + + const toggleRemoveUserTagModal = (): void => { + if (removeUserTagModalIsOpen) { + setRemoveUserTagId(null); + } + setRemoveUserTagModalIsOpen(!removeUserTagModalIsOpen); + }; + + const columns: GridColDef[] = [ + { + field: 'id', + headerName: '#', + minWidth: 100, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return
    {params.row.id}
    ; + }, + }, + { + field: 'tagName', + headerName: 'Tag Name', + flex: 1, + minWidth: 100, + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( +
    redirectToSubTags(params.row._id as string)} + > + {params.row.name} + + +
    + ); + }, + }, + { + field: 'totalSubTags', + headerName: 'Total Sub Tags', + flex: 1, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( + + {params.row.childTags.totalCount} + + ); + }, + }, + { + field: 'totalAssignedUsers', + headerName: 'Total Assigned Users', + flex: 1, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( + + {params.row.usersAssignedTo.totalCount} + + ); + }, + }, + { + field: 'actions', + headerName: 'Actions', + flex: 1, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( +
    + + + +
    + ); + }, + }, + ]; + + return ( + <> + +
    +
    +
    + + +
    +
    + + + + + +
    +
    + +
    +
    +
    + +
    + +
    navigate(`/orgtags/${orgId}`)} + className={`fs-6 ms-3 my-1 ${styles.tagsBreadCrumbs}`} + data-testid="allTagsBtn" + > + {'Tags'} + +
    + + {orgUserTagAncestors?.map((tag, index) => ( +
    redirectToSubTags(tag._id as string)} + data-testid="redirectToSubTags" + > + {tag.name} + + {orgUserTagAncestors.length - 1 !== index && ( + + )} +
    + ))} +
    + row._id} + slots={{ + noRowsOverlay: /* istanbul ignore next */ () => ( + + {t('noTagsFound')} + + ), + }} + sx={dataGridStyle} + getRowClassName={() => `${styles.rowBackground}`} + autoHeight + rowHeight={65} + rows={userTagsList?.map((fund, index) => ({ + id: index + 1, + ...fund, + }))} + columns={columns} + isRowSelectable={() => false} + /> +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    + + {/* Create Tag Modal */} + + + {t('tagDetails')} + +
    + + {t('tagName')} + { + setTagName(e.target.value); + }} + /> + + + + + + +
    +
    + + {/* Remove User Tag Modal */} + + + + {t('removeUserTag')} + + + {t('removeUserTagMessage')} + + + + + + + ); +} + +export default SubTags; diff --git a/src/screens/SubTags/SubTagsMocks.ts b/src/screens/SubTags/SubTagsMocks.ts new file mode 100644 index 0000000000..757f3f42ad --- /dev/null +++ b/src/screens/SubTags/SubTagsMocks.ts @@ -0,0 +1,415 @@ +import { + CREATE_USER_TAG, + REMOVE_USER_TAG, +} from 'GraphQl/Mutations/TagMutations'; +import { + USER_TAG_ANCESTORS, + USER_TAG_SUB_TAGS, +} from 'GraphQl/Queries/userTagQueries'; + +export const MOCKS = [ + { + request: { + query: USER_TAG_SUB_TAGS, + variables: { + id: 'tag1', + after: null, + before: null, + first: 5, + last: null, + }, + }, + result: { + data: { + getUserTag: { + name: 'tag1', + childTags: { + edges: [ + { + node: { + _id: '1', + name: 'subTag 1', + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 5, + }, + }, + cursor: '1', + }, + { + node: { + _id: '2', + name: 'subTag 2', + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 0, + }, + }, + cursor: '2', + }, + { + node: { + _id: '3', + name: 'subTag 3', + usersAssignedTo: { + totalCount: 0, + }, + childTags: { + totalCount: 5, + }, + }, + cursor: '3', + }, + { + node: { + _id: '4', + name: 'subTag 4', + usersAssignedTo: { + totalCount: 0, + }, + childTags: { + totalCount: 0, + }, + }, + cursor: '4', + }, + { + node: { + _id: '5', + name: 'subTag 5', + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 5, + }, + }, + cursor: '5', + }, + ], + pageInfo: { + startCursor: '1', + endCursor: '5', + hasNextPage: true, + hasPreviousPage: false, + }, + totalCount: 6, + }, + }, + }, + }, + }, + { + request: { + query: USER_TAG_SUB_TAGS, + variables: { + id: 'tag1', + after: '5', + before: null, + first: 5, + last: null, + }, + }, + result: { + data: { + getUserTag: { + name: 'tag1', + childTags: { + edges: [ + { + node: { + _id: '6', + name: 'subTag 6', + usersAssignedTo: { + totalCount: 0, + }, + childTags: { + totalCount: 0, + }, + }, + cursor: '6', + }, + ], + pageInfo: { + startCursor: '6', + endCursor: '6', + hasNextPage: false, + hasPreviousPage: true, + }, + totalCount: 6, + }, + }, + }, + }, + }, + { + request: { + query: USER_TAG_SUB_TAGS, + variables: { + id: 'tag1', + after: null, + before: '6', + first: null, + last: 5, + }, + }, + result: { + data: { + getUserTag: { + name: 'tag1', + childTags: { + edges: [ + { + node: { + _id: '1', + name: 'subTag 1', + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 5, + }, + }, + cursor: '1', + }, + { + node: { + _id: '2', + name: 'subTag 2', + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 0, + }, + }, + cursor: '2', + }, + { + node: { + _id: '3', + name: 'subTag 3', + usersAssignedTo: { + totalCount: 0, + }, + childTags: { + totalCount: 5, + }, + }, + cursor: '3', + }, + { + node: { + _id: '4', + name: 'subTag 4', + usersAssignedTo: { + totalCount: 0, + }, + childTags: { + totalCount: 0, + }, + }, + cursor: '4', + }, + { + node: { + _id: '5', + name: 'subTag 5', + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 5, + }, + }, + cursor: '5', + }, + ], + pageInfo: { + startCursor: '1', + endCursor: '5', + hasNextPage: true, + hasPreviousPage: false, + }, + totalCount: 6, + }, + }, + }, + }, + }, + { + request: { + query: USER_TAG_SUB_TAGS, + variables: { + id: '1', + after: null, + before: null, + first: 5, + last: null, + }, + }, + result: { + data: { + getUserTag: { + name: 'subTag 1', + childTags: { + edges: [], + pageInfo: { + startCursor: null, + endCursor: null, + hasNextPage: false, + hasPreviousPage: false, + }, + totalCount: 0, + }, + }, + }, + }, + }, + { + request: { + query: USER_TAG_ANCESTORS, + variables: { + id: 'tag1', + }, + }, + result: { + data: { + getUserTagAncestors: [ + { + _id: '1', + name: 'tag1', + }, + ], + }, + }, + }, + { + request: { + query: USER_TAG_ANCESTORS, + variables: { + id: '1', + }, + }, + result: { + data: { + getUserTagAncestors: [ + { + _id: 'tag1', + name: 'tag 1', + }, + { + _id: '1', + name: 'subTag 1', + }, + ], + }, + }, + }, + { + request: { + query: CREATE_USER_TAG, + variables: { + name: 'subTag 7', + organizationId: '123', + parentTagId: 'tag1', + }, + }, + result: { + data: { + createUserTag: { + _id: '7', + }, + }, + }, + }, + { + request: { + query: REMOVE_USER_TAG, + variables: { + id: '1', + }, + }, + result: { + data: { + removeUserTag: { + _id: '1', + }, + }, + }, + }, +]; + +export const MOCKS_ERROR_SUB_TAGS = [ + { + request: { + query: USER_TAG_SUB_TAGS, + variables: { + id: 'tag1', + after: null, + before: null, + first: 5, + last: null, + }, + }, + error: new Error('Mock Graphql Error'), + }, + { + request: { + query: USER_TAG_ANCESTORS, + variables: { + id: 'tag1', + }, + }, + result: { + data: { + getUserTagAncestors: [], + }, + }, + }, +]; + +export const MOCKS_ERROR_TAG_ANCESTORS = [ + { + request: { + query: USER_TAG_SUB_TAGS, + variables: { + id: 'tag1', + after: null, + before: null, + first: 5, + last: null, + }, + }, + result: { + data: { + getUserTag: { + name: 'tag1', + childTags: { + edges: [], + pageInfo: { + startCursor: '1', + endCursor: '5', + hasNextPage: true, + hasPreviousPage: false, + }, + totalCount: 6, + }, + }, + }, + }, + }, + { + request: { + query: USER_TAG_ANCESTORS, + variables: { + id: 'tag1', + }, + }, + error: new Error('Mock Graphql Error'), + }, +]; diff --git a/src/screens/UserPortal/Campaigns/Campaigns.module.css b/src/screens/UserPortal/Campaigns/Campaigns.module.css new file mode 100644 index 0000000000..b535b9981c --- /dev/null +++ b/src/screens/UserPortal/Campaigns/Campaigns.module.css @@ -0,0 +1,137 @@ +.btnsContainer { + display: flex; + margin: 1.5rem 0; +} + +.btnsContainer .input { + flex: 1; + min-width: 18rem; + position: relative; +} + +.btnsContainer input { + outline: 1px solid var(--bs-gray-400); + background-color: white; +} + +.btnsContainer .input button { + width: 52px; +} + +.accordionSummary { + width: 100% !important; + padding-right: 0.75rem; + display: flex; + justify-content: space-between !important; + align-items: center; +} + +.accordionSummary button { + height: 2.25rem; + padding-top: 0.35rem; +} + +.accordionSummary button:hover { + background-color: #31bb6a50 !important; + color: #31bb6b !important; +} + +.titleContainer { + display: flex; + flex-direction: column; + gap: 0.1rem; +} + +.titleContainer h3 { + font-size: 1.25rem; + font-weight: 750; + color: #5e5e5e; + margin-top: 0.2rem; +} + +.subContainer span { + font-size: 0.9rem; + margin-left: 0.5rem; + font-weight: lighter; + color: #707070; +} + +.chipIcon { + height: 0.9rem !important; +} + +.chip { + height: 1.5rem !important; + margin: 0.15rem 0 0 1.25rem; +} + +.active { + background-color: #31bb6a50 !important; +} + +.pending { + background-color: #ffd76950 !important; + color: #bb952bd0 !important; + border-color: #bb952bd0 !important; +} + +.progress { + display: flex; + width: 45rem; +} + +.progressBar { + margin: 0rem 0.75rem; + width: 100%; + font-size: 0.9rem; + height: 1.25rem; +} + +/* Pledge Modal */ + +.pledgeModal { + max-width: 80vw; + margin-top: 2vh; + margin-left: 13vw; +} + +.titlemodal { + color: #707070; + font-weight: 600; + font-size: 32px; + width: 65%; + margin-bottom: 0px; +} + +.modalCloseBtn { + width: 40px; + height: 40px; + padding: 1rem; + display: flex; + justify-content: center; + align-items: center; +} + +.noOutline input { + outline: none; +} + +.greenregbtn { + margin: 1rem 0 0; + margin-top: 15px; + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + padding: 10px 10px; + border-radius: 5px; + background-color: #31bb6b; + width: 100%; + font-size: 16px; + color: white; + outline: none; + font-weight: 600; + cursor: pointer; + transition: + transform 0.2s, + box-shadow 0.2s; + width: 100%; +} diff --git a/src/screens/UserPortal/Campaigns/Campaigns.test.tsx b/src/screens/UserPortal/Campaigns/Campaigns.test.tsx new file mode 100644 index 0000000000..17b7eec4d5 --- /dev/null +++ b/src/screens/UserPortal/Campaigns/Campaigns.test.tsx @@ -0,0 +1,324 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import type { RenderResult } from '@testing-library/react'; +import { + cleanup, + fireEvent, + render, + screen, + waitFor, +} from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18nForTest from 'utils/i18nForTest'; +import type { ApolloLink } from '@apollo/client'; +import useLocalStorage from 'utils/useLocalstorage'; +import Campaigns from './Campaigns'; +import { + EMPTY_MOCKS, + MOCKS, + USER_FUND_CAMPAIGNS_ERROR, +} from './CampaignsMocks'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); +jest.mock('@mui/x-date-pickers/DateTimePicker', () => { + return { + DateTimePicker: jest.requireActual( + '@mui/x-date-pickers/DesktopDateTimePicker', + ).DesktopDateTimePicker, + }; +}); +const { setItem } = useLocalStorage(); + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(USER_FUND_CAMPAIGNS_ERROR); +const link3 = new StaticMockLink(EMPTY_MOCKS); +const cTranslations = JSON.parse( + JSON.stringify( + i18nForTest.getDataByLanguage('en')?.translation.userCampaigns, + ), +); +const pTranslations = JSON.parse( + JSON.stringify(i18nForTest.getDataByLanguage('en')?.translation.pledges), +); + +const renderCampaigns = (link: ApolloLink): RenderResult => { + return render( + + + + + + + } /> +
    } + /> +
    } + /> + + + + + + , + ); +}; + +describe('Testing User Campaigns Screen', () => { + beforeEach(() => { + setItem('userId', 'userId'); + }); + + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId' }), + })); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + afterEach(() => { + cleanup(); + }); + + it('should render the User Campaigns screen', async () => { + renderCampaigns(link1); + await waitFor(() => { + expect(screen.getByTestId('searchCampaigns')).toBeInTheDocument(); + expect(screen.getByText('School Campaign')).toBeInTheDocument(); + expect(screen.getByText('Hospital Campaign')).toBeInTheDocument(); + }); + }); + + it('should redirect to fallback URL if userId is null in LocalStorage', async () => { + setItem('userId', null); + renderCampaigns(link1); + await waitFor(() => { + expect(screen.getByTestId('paramsError')).toBeInTheDocument(); + }); + }); + + it('should redirect to fallback URL if URL params are undefined', async () => { + render( + + + + + + } /> +
    } + /> + + + + + , + ); + await waitFor(() => { + expect(screen.getByTestId('paramsError')).toBeInTheDocument(); + }); + }); + + it('should render the User Campaign screen with error', async () => { + renderCampaigns(link2); + await waitFor(() => { + expect(screen.getByTestId('errorMsg')).toBeInTheDocument(); + }); + }); + + it('renders the empty campaign component', async () => { + renderCampaigns(link3); + await waitFor(() => + expect(screen.getByText(cTranslations.noCampaigns)).toBeInTheDocument(), + ); + }); + + it('Check if All details are rendered correctly', async () => { + renderCampaigns(link1); + + const detailContainer = await screen.findByTestId('detailContainer1'); + const detailContainer2 = await screen.findByTestId('detailContainer2'); + await waitFor(() => { + expect(detailContainer).toBeInTheDocument(); + expect(detailContainer2).toBeInTheDocument(); + expect(detailContainer).toHaveTextContent('School Campaign'); + expect(detailContainer).toHaveTextContent('$22000'); + expect(detailContainer).toHaveTextContent('2024-07-28'); + expect(detailContainer).toHaveTextContent('2025-08-31'); + expect(detailContainer).toHaveTextContent('Active'); + expect(detailContainer2).toHaveTextContent('Hospital Campaign'); + expect(detailContainer2).toHaveTextContent('$9000'); + expect(detailContainer2).toHaveTextContent('2024-07-28'); + expect(detailContainer2).toHaveTextContent('2022-08-30'); + expect(detailContainer2).toHaveTextContent('Ended'); + }); + }); + + it('Sort the Campaigns list by lowest fundingGoal', async () => { + renderCampaigns(link1); + + const searchCampaigns = await screen.findByTestId('searchCampaigns'); + expect(searchCampaigns).toBeInTheDocument(); + + userEvent.click(screen.getByTestId('filter')); + await waitFor(() => { + expect(screen.getByTestId('fundingGoal_ASC')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('fundingGoal_ASC')); + + await waitFor(() => { + expect(screen.getByText('School Campaign')).toBeInTheDocument(); + expect(screen.getByText('Hospital Campaign')).toBeInTheDocument(); + }); + + await waitFor(() => { + const detailContainer = screen.getByTestId('detailContainer2'); + expect(detailContainer).toHaveTextContent('School Campaign'); + expect(detailContainer).toHaveTextContent('$22000'); + expect(detailContainer).toHaveTextContent('2024-07-28'); + expect(detailContainer).toHaveTextContent('2024-08-31'); + }); + }); + + it('Sort the Campaigns list by highest fundingGoal', async () => { + renderCampaigns(link1); + + const searchCampaigns = await screen.findByTestId('searchCampaigns'); + expect(searchCampaigns).toBeInTheDocument(); + + userEvent.click(screen.getByTestId('filter')); + await waitFor(() => { + expect(screen.getByTestId('fundingGoal_DESC')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('fundingGoal_DESC')); + + await waitFor(() => { + expect(screen.getByText('School Campaign')).toBeInTheDocument(); + expect(screen.getByText('Hospital Campaign')).toBeInTheDocument(); + }); + + await waitFor(() => { + const detailContainer = screen.getByTestId('detailContainer1'); + expect(detailContainer).toHaveTextContent('School Campaign'); + expect(detailContainer).toHaveTextContent('$22000'); + expect(detailContainer).toHaveTextContent('2024-07-28'); + expect(detailContainer).toHaveTextContent('2024-08-31'); + }); + }); + + it('Sort the Campaigns list by earliest endDate', async () => { + renderCampaigns(link1); + + const searchCampaigns = await screen.findByTestId('searchCampaigns'); + expect(searchCampaigns).toBeInTheDocument(); + + userEvent.click(screen.getByTestId('filter')); + await waitFor(() => { + expect(screen.getByTestId('endDate_ASC')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('endDate_ASC')); + + await waitFor(() => { + expect(screen.getByText('School Campaign')).toBeInTheDocument(); + expect(screen.getByText('Hospital Campaign')).toBeInTheDocument(); + }); + + await waitFor(() => { + const detailContainer = screen.getByTestId('detailContainer2'); + expect(detailContainer).toHaveTextContent('School Campaign'); + expect(detailContainer).toHaveTextContent('$22000'); + expect(detailContainer).toHaveTextContent('2024-07-28'); + expect(detailContainer).toHaveTextContent('2024-08-31'); + }); + }); + + it('Sort the Campaigns list by latest endDate', async () => { + renderCampaigns(link1); + + const searchCampaigns = await screen.findByTestId('searchCampaigns'); + expect(searchCampaigns).toBeInTheDocument(); + + userEvent.click(screen.getByTestId('filter')); + await waitFor(() => { + expect(screen.getByTestId('endDate_DESC')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('endDate_DESC')); + + await waitFor(() => { + expect(screen.getByText('School Campaign')).toBeInTheDocument(); + expect(screen.getByText('Hospital Campaign')).toBeInTheDocument(); + }); + + await waitFor(() => { + const detailContainer = screen.getByTestId('detailContainer1'); + expect(detailContainer).toHaveTextContent('School Campaign'); + expect(detailContainer).toHaveTextContent('$22000'); + expect(detailContainer).toHaveTextContent('2024-07-28'); + expect(detailContainer).toHaveTextContent('2025-08-31'); + }); + }); + + it('Search the Campaigns list by name', async () => { + renderCampaigns(link1); + + const searchCampaigns = await screen.findByTestId('searchCampaigns'); + expect(searchCampaigns).toBeInTheDocument(); + + fireEvent.change(searchCampaigns, { + target: { value: 'Hospital' }, + }); + + await waitFor(() => { + expect(screen.queryByText('School Campaign')).toBeNull(); + expect(screen.getByText('Hospital Campaign')).toBeInTheDocument(); + }); + }); + + it('open and closes add pledge modal', async () => { + renderCampaigns(link1); + + const addPledgeBtn = await screen.findAllByTestId('addPledgeBtn'); + await waitFor(() => expect(addPledgeBtn[0]).toBeInTheDocument()); + userEvent.click(addPledgeBtn[0]); + + await waitFor(() => + expect(screen.getAllByText(pTranslations.createPledge)).toHaveLength(2), + ); + userEvent.click(screen.getByTestId('pledgeModalCloseBtn')); + await waitFor(() => + expect(screen.queryByTestId('pledgeModalCloseBtn')).toBeNull(), + ); + }); + + it('Redirect to My Pledges screen', async () => { + renderCampaigns(link1); + + const myPledgesBtn = await screen.findByText(cTranslations.myPledges); + expect(myPledgesBtn).toBeInTheDocument(); + userEvent.click(myPledgesBtn); + + await waitFor(() => { + expect(screen.getByTestId('pledgeScreen')).toBeInTheDocument(); + }); + }); +}); diff --git a/src/screens/UserPortal/Campaigns/Campaigns.tsx b/src/screens/UserPortal/Campaigns/Campaigns.tsx new file mode 100644 index 0000000000..e4483f87fe --- /dev/null +++ b/src/screens/UserPortal/Campaigns/Campaigns.tsx @@ -0,0 +1,305 @@ +import React, { useEffect, useState } from 'react'; +import { Dropdown, Form, Button, ProgressBar } from 'react-bootstrap'; +import styles from './Campaigns.module.css'; +import { useTranslation } from 'react-i18next'; +import { Navigate, useNavigate, useParams } from 'react-router-dom'; +import { Circle, Search, Sort, WarningAmberRounded } from '@mui/icons-material'; +import { + Accordion, + AccordionDetails, + AccordionSummary, + Chip, + Stack, +} from '@mui/material'; +import { GridExpandMoreIcon } from '@mui/x-data-grid'; +import useLocalStorage from 'utils/useLocalstorage'; +import PledgeModal from './PledgeModal'; +import { USER_FUND_CAMPAIGNS } from 'GraphQl/Queries/fundQueries'; +import { useQuery } from '@apollo/client'; +import type { InterfaceUserCampaign } from 'utils/interfaces'; +import { currencySymbols } from 'utils/currency'; +import Loader from 'components/Loader/Loader'; + +/** + * The `Campaigns` component displays a list of fundraising campaigns for a specific organization. + * It allows users to search, sort, and view details about each campaign. Users can also add pledges to active campaigns. + * + * @returns The rendered component displaying the campaigns. + */ +const Campaigns = (): JSX.Element => { + // Retrieves translation functions for various namespaces + const { t } = useTranslation('translation', { + keyPrefix: 'userCampaigns', + }); + const { t: tCommon } = useTranslation('common'); + const { t: tErrors } = useTranslation('errors'); + + // Retrieves stored user ID from local storage + const { getItem } = useLocalStorage(); + const userId = getItem('userId'); + + // Extracts organization ID from the URL parameters + const { orgId } = useParams(); + if (!orgId || !userId) { + // Redirects to the homepage if orgId or userId is missing + return ; + } + + // Navigation hook to programmatically navigate between routes + const navigate = useNavigate(); + + // State for managing search term, campaigns, selected campaign, modal state, and sorting order + const [searchTerm, setSearchTerm] = useState(''); + const [campaigns, setCampaigns] = useState([]); + const [selectedCampaign, setSelectedCampaign] = + useState(null); + const [modalState, setModalState] = useState(false); + const [sortBy, setSortBy] = useState< + 'fundingGoal_ASC' | 'fundingGoal_DESC' | 'endDate_ASC' | 'endDate_DESC' + >('endDate_DESC'); + + // Fetches campaigns based on the organization ID, search term, and sorting order + const { + data: campaignData, + loading: campaignLoading, + error: campaignError, + refetch: refetchCampaigns, + }: { + data?: { + getFundraisingCampaigns: InterfaceUserCampaign[]; + }; + loading: boolean; + error?: Error | undefined; + refetch: () => void; + } = useQuery(USER_FUND_CAMPAIGNS, { + variables: { + where: { + organizationId: orgId, + name_contains: searchTerm, + }, + campaignOrderBy: sortBy, + }, + }); + + /** + * Opens the modal for adding a pledge to a selected campaign. + * + * @param campaign - The campaign to which the user wants to add a pledge. + */ + const openModal = (campaign: InterfaceUserCampaign): void => { + setSelectedCampaign(campaign); + setModalState(true); + }; + + /** + * Closes the modal and clears the selected campaign. + */ + const closeModal = (): void => { + setModalState(false); + setSelectedCampaign(null); + }; + + // Updates the campaigns state when the fetched campaign data changes + useEffect(() => { + if (campaignData) { + setCampaigns(campaignData.getFundraisingCampaigns); + } + }, [campaignData]); + + // Renders a loader while campaigns are being fetched + if (campaignLoading) return ; + if (campaignError) { + // Displays an error message if there is an issue loading the campaigns + return ( +
    +
    + +
    + {tErrors('errorLoading', { entity: 'Campaigns' })} +
    + {campaignError.message} +
    +
    +
    + ); + } + + // Renders the campaign list and UI elements for searching, sorting, and adding pledges + return ( + <> +
    + {/* Search input field and button */} +
    + setSearchTerm(e.target.value)} + data-testid="searchCampaigns" + /> + +
    +
    +
    + {/* Dropdown menu for sorting campaigns */} + + + + {tCommon('sort')} + + + setSortBy('fundingGoal_ASC')} + data-testid="fundingGoal_ASC" + > + {t('lowestGoal')} + + setSortBy('fundingGoal_DESC')} + data-testid="fundingGoal_DESC" + > + {t('highestGoal')} + + setSortBy('endDate_DESC')} + data-testid="endDate_DESC" + > + {t('latestEndDate')} + + setSortBy('endDate_ASC')} + data-testid="endDate_ASC" + > + {t('earliestEndDate')} + + + +
    +
    + {/* Button to navigate to the user's pledges */} + +
    +
    +
    + {campaigns.length < 1 ? ( + + {/* Displayed if no campaigns are found */} + {t('noCampaigns')} + + ) : ( + campaigns.map((campaign: InterfaceUserCampaign, index: number) => ( + + }> +
    +
    +
    +

    {campaign.name}

    + } + label={ + new Date(campaign.endDate) < new Date() + ? 'Ended' + : 'Active' + } + variant="outlined" + color="primary" + className={`${styles.chip} ${new Date(campaign.endDate) < new Date() ? styles.pending : styles.active}`} + /> +
    + +
    + + Goal:{' '} + { + currencySymbols[ + campaign.currency as keyof typeof currencySymbols + ] + } + {campaign.fundingGoal} + + Raised: $0 + + Start Date: {campaign.startDate as unknown as string} + + + End Date: {campaign.endDate as unknown as string} + +
    +
    +
    + +
    +
    +
    + + Amount Raised: +
    + $0 + + $1000 +
    +
    +
    + )) + )} + + {/* Modal for adding pledges to campaigns */} + + + ); +}; + +export default Campaigns; diff --git a/src/screens/UserPortal/Campaigns/CampaignsMocks.ts b/src/screens/UserPortal/Campaigns/CampaignsMocks.ts new file mode 100644 index 0000000000..f64401bca5 --- /dev/null +++ b/src/screens/UserPortal/Campaigns/CampaignsMocks.ts @@ -0,0 +1,272 @@ +import { USER_DETAILS } from 'GraphQl/Queries/Queries'; +import { USER_FUND_CAMPAIGNS } from 'GraphQl/Queries/fundQueries'; + +const userDetailsQuery = { + request: { + query: USER_DETAILS, + variables: { + id: 'userId', + }, + }, + result: { + data: { + user: { + user: { + _id: 'userId', + joinedOrganizations: [ + { + _id: '6537904485008f171cf29924', + __typename: 'Organization', + }, + ], + firstName: 'Harve', + lastName: 'Lance', + email: 'testuser1@example.com', + image: null, + createdAt: '2023-04-13T04:53:17.742Z', + birthDate: null, + educationGrade: null, + employmentStatus: null, + gender: null, + maritalStatus: null, + phone: null, + address: { + line1: 'Line1', + countryCode: 'CountryCode', + city: 'CityName', + state: 'State', + __typename: 'Address', + }, + registeredEvents: [], + membershipRequests: [], + __typename: 'User', + }, + appUserProfile: { + _id: '67078abd85008f171cf2991d', + adminFor: [], + isSuperAdmin: false, + appLanguageCode: 'en', + pluginCreationAllowed: true, + createdOrganizations: [], + createdEvents: [], + eventAdmin: [], + __typename: 'AppUserProfile', + }, + __typename: 'UserData', + }, + }, + }, +}; + +export const MOCKS = [ + { + request: { + query: USER_FUND_CAMPAIGNS, + variables: { + where: { + organizationId: 'orgId', + name_contains: '', + }, + campaignOrderBy: 'endDate_DESC', + }, + }, + result: { + data: { + getFundraisingCampaigns: [ + { + _id: 'campaignId1', + startDate: '2024-07-28', + endDate: '2025-08-31', + name: 'School Campaign', + fundingGoal: 22000, + currency: 'USD', + __typename: 'FundraisingCampaign', + }, + { + _id: 'campaignId2', + startDate: '2024-07-28', + endDate: '2022-08-30', + name: 'Hospital Campaign', + fundingGoal: 9000, + currency: 'USD', + __typename: 'FundraisingCampaign', + }, + ], + }, + }, + }, + { + request: { + query: USER_FUND_CAMPAIGNS, + variables: { + where: { + organizationId: 'orgId', + name_contains: '', + }, + campaignOrderBy: 'endDate_ASC', + }, + }, + result: { + data: { + getFundraisingCampaigns: [ + { + _id: 'campaignId2', + startDate: '2024-07-28', + endDate: '2024-08-30', + name: 'Hospital Campaign', + fundingGoal: 9000, + currency: 'USD', + __typename: 'FundraisingCampaign', + }, + { + _id: 'campaignId1', + startDate: '2024-07-28', + endDate: '2024-08-31', + name: 'School Campaign', + fundingGoal: 22000, + currency: 'USD', + __typename: 'FundraisingCampaign', + }, + ], + }, + }, + }, + { + request: { + query: USER_FUND_CAMPAIGNS, + variables: { + where: { + organizationId: 'orgId', + name_contains: '', + }, + campaignOrderBy: 'fundingGoal_ASC', + }, + }, + result: { + data: { + getFundraisingCampaigns: [ + { + _id: 'campaignId2', + startDate: '2024-07-28', + endDate: '2024-08-30', + name: 'Hospital Campaign', + fundingGoal: 9000, + currency: 'USD', + __typename: 'FundraisingCampaign', + }, + { + _id: 'campaignId1', + startDate: '2024-07-28', + endDate: '2024-08-31', + name: 'School Campaign', + fundingGoal: 22000, + currency: 'USD', + __typename: 'FundraisingCampaign', + }, + ], + }, + }, + }, + { + request: { + query: USER_FUND_CAMPAIGNS, + variables: { + where: { + organizationId: 'orgId', + name_contains: '', + }, + campaignOrderBy: 'fundingGoal_DESC', + }, + }, + result: { + data: { + getFundraisingCampaigns: [ + { + _id: 'campaignId1', + startDate: '2024-07-28', + endDate: '2024-08-31', + name: 'School Campaign', + fundingGoal: 22000, + currency: 'USD', + __typename: 'FundraisingCampaign', + }, + { + _id: 'campaignId2', + startDate: '2024-07-28', + endDate: '2024-08-30', + name: 'Hospital Campaign', + fundingGoal: 9000, + currency: 'USD', + __typename: 'FundraisingCampaign', + }, + ], + }, + }, + }, + { + request: { + query: USER_FUND_CAMPAIGNS, + variables: { + where: { + organizationId: 'orgId', + name_contains: 'Hospital', + }, + campaignOrderBy: 'endDate_DESC', + }, + }, + result: { + data: { + getFundraisingCampaigns: [ + { + _id: 'campaignId2', + startDate: '2024-07-28', + endDate: '2024-08-30', + name: 'Hospital Campaign', + fundingGoal: 9000, + currency: 'USD', + __typename: 'FundraisingCampaign', + }, + ], + }, + }, + }, + userDetailsQuery, +]; + +export const EMPTY_MOCKS = [ + { + request: { + query: USER_FUND_CAMPAIGNS, + variables: { + where: { + organizationId: 'orgId', + name_contains: '', + }, + campaignOrderBy: 'endDate_DESC', + }, + }, + result: { + data: { + getFundraisingCampaigns: [], + }, + }, + }, + userDetailsQuery, +]; + +export const USER_FUND_CAMPAIGNS_ERROR = [ + { + request: { + query: USER_FUND_CAMPAIGNS, + variables: { + where: { + organizationId: 'orgId', + name_contains: '', + }, + campaignOrderBy: 'endDate_DESC', + }, + }, + error: new Error('Error fetching campaigns'), + }, + userDetailsQuery, +]; diff --git a/src/screens/UserPortal/Campaigns/PledgeModal.test.tsx b/src/screens/UserPortal/Campaigns/PledgeModal.test.tsx new file mode 100644 index 0000000000..3f299c5c48 --- /dev/null +++ b/src/screens/UserPortal/Campaigns/PledgeModal.test.tsx @@ -0,0 +1,310 @@ +import type { ApolloLink } from '@apollo/client'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import type { RenderResult } from '@testing-library/react'; +import { + cleanup, + fireEvent, + render, + screen, + waitFor, +} from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import i18nForTest from 'utils/i18nForTest'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { toast } from 'react-toastify'; +import type { InterfacePledgeModal } from './PledgeModal'; +import PledgeModal from './PledgeModal'; +import React from 'react'; +import { USER_DETAILS } from 'GraphQl/Queries/Queries'; +import { CREATE_PlEDGE, UPDATE_PLEDGE } from 'GraphQl/Mutations/PledgeMutation'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +jest.mock('@mui/x-date-pickers/DateTimePicker', () => { + return { + DateTimePicker: jest.requireActual( + '@mui/x-date-pickers/DesktopDateTimePicker', + ).DesktopDateTimePicker, + }; +}); + +const pledgeProps: InterfacePledgeModal[] = [ + { + isOpen: true, + hide: jest.fn(), + pledge: { + _id: '1', + amount: 100, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-01-10', + users: [ + { + _id: '1', + firstName: 'John', + lastName: 'Doe', + image: null, + }, + ], + }, + refetchPledge: jest.fn(), + campaignId: 'campaignId', + userId: 'userId', + endDate: new Date(), + mode: 'create', + }, + { + isOpen: true, + hide: jest.fn(), + pledge: { + _id: '1', + amount: 100, + currency: 'USD', + startDate: '2024-01-01', + endDate: '2024-01-10', + users: [ + { + _id: '1', + firstName: 'John', + lastName: 'Doe', + image: null, + }, + ], + }, + refetchPledge: jest.fn(), + campaignId: 'campaignId', + userId: 'userId', + endDate: new Date(), + mode: 'edit', + }, +]; + +const PLEDGE_MODAL_MOCKS = [ + { + request: { + query: USER_DETAILS, + variables: { + id: 'userId', + }, + }, + result: { + data: { + user: { + user: { + _id: 'userId', + joinedOrganizations: [ + { + _id: '6537904485008f171cf29924', + __typename: 'Organization', + }, + ], + firstName: 'Harve', + lastName: 'Lance', + email: 'testuser1@example.com', + image: null, + createdAt: '2023-04-13T04:53:17.742Z', + birthDate: null, + educationGrade: null, + employmentStatus: null, + gender: null, + maritalStatus: null, + phone: null, + address: { + line1: 'Line1', + countryCode: 'CountryCode', + city: 'CityName', + state: 'State', + __typename: 'Address', + }, + registeredEvents: [], + membershipRequests: [], + __typename: 'User', + }, + appUserProfile: { + _id: '67078abd85008f171cf2991d', + adminFor: [], + isSuperAdmin: false, + appLanguageCode: 'en', + pluginCreationAllowed: true, + createdOrganizations: [], + createdEvents: [], + eventAdmin: [], + __typename: 'AppUserProfile', + }, + __typename: 'UserData', + }, + }, + }, + }, + { + request: { + query: UPDATE_PLEDGE, + variables: { + id: '1', + amount: 200, + }, + }, + result: { + data: { + updateFundraisingCampaignPledge: { + _id: '1', + }, + }, + }, + }, + { + request: { + query: CREATE_PlEDGE, + variables: { + campaignId: 'campaignId', + amount: 200, + currency: 'USD', + startDate: '2024-01-02', + endDate: '2024-01-02', + userIds: ['1'], + }, + }, + result: { + data: { + createFundraisingCampaignPledge: { + _id: '3', + }, + }, + }, + }, +]; + +const link1 = new StaticMockLink(PLEDGE_MODAL_MOCKS); +const translations = JSON.parse( + JSON.stringify(i18nForTest.getDataByLanguage('en')?.translation.pledges), +); + +const renderPledgeModal = ( + link: ApolloLink, + props: InterfacePledgeModal, +): RenderResult => { + return render( + + + + + + + + + + + , + ); +}; + +describe('PledgeModal', () => { + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId', fundCampaignId: 'fundCampaignId' }), + })); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + afterEach(() => { + cleanup(); + }); + it('should populate form fields with correct values in edit mode', async () => { + renderPledgeModal(link1, pledgeProps[1]); + await waitFor(() => + expect(screen.getByText(translations.editPledge)).toBeInTheDocument(), + ); + expect(screen.getByTestId('pledgerSelect')).toHaveTextContent('John Doe'); + expect(screen.getByLabelText('Start Date')).toHaveValue('01/01/2024'); + expect(screen.getByLabelText('End Date')).toHaveValue('10/01/2024'); + expect(screen.getByLabelText('Currency')).toHaveTextContent('USD ($)'); + expect(screen.getByLabelText('Amount')).toHaveValue('100'); + }); + + it('should update pledgeAmount when input value changes', async () => { + renderPledgeModal(link1, pledgeProps[1]); + const amountInput = screen.getByLabelText('Amount'); + expect(amountInput).toHaveValue('100'); + fireEvent.change(amountInput, { target: { value: '200' } }); + expect(amountInput).toHaveValue('200'); + }); + + it('should not update pledgeAmount when input value is less than or equal to 0', async () => { + renderPledgeModal(link1, pledgeProps[1]); + const amountInput = screen.getByLabelText('Amount'); + expect(amountInput).toHaveValue('100'); + fireEvent.change(amountInput, { target: { value: '-10' } }); + expect(amountInput).toHaveValue('100'); + }); + + it('should update pledgeStartDate when a new date is selected', async () => { + renderPledgeModal(link1, pledgeProps[1]); + const startDateInput = screen.getByLabelText('Start Date'); + fireEvent.change(startDateInput, { target: { value: '02/01/2024' } }); + expect(startDateInput).toHaveValue('02/01/2024'); + expect(pledgeProps[1].pledge?.startDate).toEqual('2024-01-01'); + }); + + it('pledgeStartDate onChange when its null', async () => { + renderPledgeModal(link1, pledgeProps[1]); + const startDateInput = screen.getByLabelText('Start Date'); + fireEvent.change(startDateInput, { target: { value: null } }); + expect(pledgeProps[1].pledge?.startDate).toEqual('2024-01-01'); + }); + + it('should update pledgeEndDate when a new date is selected', async () => { + renderPledgeModal(link1, pledgeProps[1]); + const startDateInput = screen.getByLabelText('End Date'); + fireEvent.change(startDateInput, { target: { value: '02/01/2024' } }); + expect(startDateInput).toHaveValue('02/01/2024'); + expect(pledgeProps[1].pledge?.endDate).toEqual('2024-01-10'); + }); + + it('pledgeEndDate onChange when its null', async () => { + renderPledgeModal(link1, pledgeProps[1]); + const endDateInput = screen.getByLabelText('End Date'); + fireEvent.change(endDateInput, { target: { value: null } }); + expect(pledgeProps[1].pledge?.endDate).toEqual('2024-01-10'); + }); + + it('should create pledge', async () => { + renderPledgeModal(link1, pledgeProps[0]); + + fireEvent.change(screen.getByLabelText('Amount'), { + target: { value: '200' }, + }); + fireEvent.change(screen.getByLabelText('Start Date'), { + target: { value: '02/01/2024' }, + }); + fireEvent.change(screen.getByLabelText('End Date'), { + target: { value: '02/01/2024' }, + }); + + expect(screen.getByLabelText('Amount')).toHaveValue('200'); + expect(screen.getByLabelText('Start Date')).toHaveValue('02/01/2024'); + expect(screen.getByLabelText('End Date')).toHaveValue('02/01/2024'); + expect(screen.getByTestId('submitPledgeBtn')).toBeInTheDocument(); + + fireEvent.click(screen.getByTestId('submitPledgeBtn')); + + await waitFor(() => { + expect(toast.success).toHaveBeenCalled(); + expect(pledgeProps[0].refetchPledge).toHaveBeenCalled(); + expect(pledgeProps[0].hide).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/screens/UserPortal/Campaigns/PledgeModal.tsx b/src/screens/UserPortal/Campaigns/PledgeModal.tsx new file mode 100644 index 0000000000..d9076f52c8 --- /dev/null +++ b/src/screens/UserPortal/Campaigns/PledgeModal.tsx @@ -0,0 +1,373 @@ +import { DatePicker } from '@mui/x-date-pickers'; +import dayjs, { type Dayjs } from 'dayjs'; +import type { ChangeEvent } from 'react'; +import { Button, Form, Modal } from 'react-bootstrap'; +import { currencyOptions, currencySymbols } from 'utils/currency'; +import type { + InterfaceCreatePledge, + InterfacePledgeInfo, + InterfacePledger, +} from 'utils/interfaces'; +import styles from './Campaigns.module.css'; +import React, { useCallback, useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useMutation, useQuery } from '@apollo/client'; +import { CREATE_PlEDGE, UPDATE_PLEDGE } from 'GraphQl/Mutations/PledgeMutation'; +import { toast } from 'react-toastify'; +import { + Autocomplete, + FormControl, + InputLabel, + MenuItem, + Select, + TextField, +} from '@mui/material'; +import { USER_DETAILS } from 'GraphQl/Queries/Queries'; + +/** + * Interface representing the properties for the `PledgeModal` component. + */ +export interface InterfacePledgeModal { + isOpen: boolean; + hide: () => void; + campaignId: string; + userId: string; + pledge: InterfacePledgeInfo | null; + refetchPledge: () => void; + endDate: Date; + mode: 'create' | 'edit'; +} + +/** + * `PledgeModal` is a React component that allows users to create or edit a pledge for a specific campaign. + * It displays a form with inputs for pledge details such as amount, currency, dates, and users involved in the pledge. + * + * @param isOpen - Determines if the modal is visible or hidden. + * @param hide - Function to close the modal. + * @param campaignId - The ID of the campaign for which the pledge is being made. + * @param userId - The ID of the user making or editing the pledge. + * @param pledge - The current pledge information if in edit mode, or null if creating a new pledge. + * @param refetchPledge - Function to refresh the pledge data after a successful operation. + * @param endDate - The maximum date allowed for the pledge's end date, based on the campaign's end date. + * @param mode - Specifies whether the modal is used for creating a new pledge or editing an existing one. + */ +const PledgeModal: React.FC = ({ + isOpen, + hide, + campaignId, + userId, + pledge, + refetchPledge, + endDate, + mode, +}) => { + // Translation functions to support internationalization + const { t } = useTranslation('translation', { + keyPrefix: 'pledges', + }); + const { t: tCommon } = useTranslation('common'); + + // State to manage the form inputs for the pledge + const [formState, setFormState] = useState({ + pledgeUsers: [], + pledgeAmount: pledge?.amount ?? 0, + pledgeCurrency: pledge?.currency ?? 'USD', + pledgeEndDate: new Date(pledge?.endDate ?? new Date()), + pledgeStartDate: new Date(pledge?.startDate ?? new Date()), + }); + + // State to manage the list of pledgers (users who are part of the pledge) + const [pledgers, setPledgers] = useState([]); + + // Mutation to update an existing pledge + const [updatePledge] = useMutation(UPDATE_PLEDGE); + + // Mutation to create a new pledge + const [createPledge] = useMutation(CREATE_PlEDGE); + + // Effect to update the form state when the pledge prop changes (e.g., when editing a pledge) + useEffect(() => { + setFormState({ + pledgeUsers: pledge?.users ?? [], + pledgeAmount: pledge?.amount ?? 0, + pledgeCurrency: pledge?.currency ?? 'USD', + pledgeEndDate: new Date(pledge?.endDate ?? new Date()), + pledgeStartDate: new Date(pledge?.startDate ?? new Date()), + }); + }, [pledge]); + + // Destructuring the form state for easier access + const { + pledgeUsers, + pledgeAmount, + pledgeCurrency, + pledgeStartDate, + pledgeEndDate, + } = formState; + + // Query to get the user details based on the userId prop + const { data: userData } = useQuery(USER_DETAILS, { + variables: { + id: userId, + }, + }); + + // Effect to update the pledgers state when user data is fetched + useEffect(() => { + if (userData) { + setPledgers([ + { + _id: userData.user.user._id, + firstName: userData.user.user.firstName, + lastName: userData.user.user.lastName, + image: userData.user.user.image, + }, + ]); + } + }, [userData]); + + /** + * Handler function to update an existing pledge. + * It compares the current form state with the existing pledge and updates only the changed fields. + * + * @param e - The form submission event. + * @returns A promise that resolves when the pledge is successfully updated. + */ + /*istanbul ignore next*/ + const updatePledgeHandler = useCallback( + async (e: ChangeEvent): Promise => { + e.preventDefault(); + const startDate = dayjs(pledgeStartDate).format('YYYY-MM-DD'); + const endDate = dayjs(pledgeEndDate).format('YYYY-MM-DD'); + + const updatedFields: { + [key: string]: number | string | string[] | undefined; + } = {}; + // checks if there are changes to the pledge and adds them to the updatedFields object + if (pledgeAmount !== pledge?.amount) { + updatedFields.amount = pledgeAmount; + } + if (pledgeCurrency !== pledge?.currency) { + updatedFields.currency = pledgeCurrency; + } + if (startDate !== dayjs(pledge?.startDate).format('YYYY-MM-DD')) { + updatedFields.startDate = startDate; + } + if (endDate !== dayjs(pledge?.endDate).format('YYYY-MM-DD')) { + updatedFields.endDate = endDate; + } + if (pledgeUsers !== pledge?.users) { + updatedFields.users = pledgeUsers.map((user) => user._id); + } + try { + await updatePledge({ + variables: { + id: pledge?._id, + ...updatedFields, + }, + }); + toast.success(t('pledgeUpdated') as string); + refetchPledge(); + hide(); + } catch (error: unknown) { + toast.error((error as Error).message); + } + }, + [formState, pledge], + ); + + /** + * Handler function to create a new pledge. + * It collects the form data and sends a request to create a pledge with the specified details. + * + * @param e - The form submission event. + * @returns A promise that resolves when the pledge is successfully created. + */ + const createPledgeHandler = useCallback( + async (e: ChangeEvent): Promise => { + try { + e.preventDefault(); + await createPledge({ + variables: { + campaignId, + amount: pledgeAmount, + currency: pledgeCurrency, + startDate: dayjs(pledgeStartDate).format('YYYY-MM-DD'), + endDate: dayjs(pledgeEndDate).format('YYYY-MM-DD'), + userIds: pledgeUsers.map((user) => user._id), + }, + }); + + toast.success(t('pledgeCreated') as string); + refetchPledge(); + setFormState({ + pledgeUsers: [], + pledgeAmount: 0, + pledgeCurrency: 'USD', + pledgeEndDate: new Date(), + pledgeStartDate: new Date(), + }); + hide(); + } catch (error: unknown) { + /*istanbul ignore next*/ + toast.error((error as Error).message); + } + }, + [formState, campaignId], + ); + + return ( + + +

    + {t(mode === 'edit' ? 'editPledge' : 'createPledge')} +

    + +
    + +
    + {/* A Multi-select dropdown enables user to view participating pledgers */} + + option._id === value._id} + filterSelectedOptions={true} + getOptionLabel={(member: InterfacePledger): string => + `${member.firstName} ${member.lastName}` + } + onChange={ + /*istanbul ignore next*/ + (_, newPledgers): void => { + setFormState({ + ...formState, + pledgeUsers: newPledgers, + }); + } + } + renderInput={(params) => ( + + )} + /> + + + {/* Date Calendar Component to select start date of an event */} + { + if (date) { + setFormState({ + ...formState, + pledgeStartDate: date.toDate(), + pledgeEndDate: + pledgeEndDate && + /*istanbul ignore next*/ + (pledgeEndDate < date?.toDate() + ? date.toDate() + : pledgeEndDate), + }); + } + }} + minDate={dayjs(pledgeStartDate)} + maxDate={dayjs(endDate)} + /> + {/* Date Calendar Component to select end Date of an event */} + { + if (date) { + setFormState({ + ...formState, + pledgeEndDate: date.toDate(), + }); + } + }} + minDate={dayjs(pledgeStartDate)} + maxDate={dayjs(endDate)} + /> + + + {/* Dropdown to select the currency in which amount is to be pledged */} + + + {t('currency')} + + + + {/* Input field to enter amount to be pledged */} + + { + if (parseInt(e.target.value) > 0) { + setFormState({ + ...formState, + pledgeAmount: parseInt(e.target.value), + }); + } + }} + /> + + + {/* Button to submit the pledge form */} + +
    +
    +
    + ); +}; +export default PledgeModal; diff --git a/src/screens/UserPortal/Chat/Chat.test.tsx b/src/screens/UserPortal/Chat/Chat.test.tsx index bf41dcbe9b..4a0dfbcf4e 100644 --- a/src/screens/UserPortal/Chat/Chat.test.tsx +++ b/src/screens/UserPortal/Chat/Chat.test.tsx @@ -1,5 +1,5 @@ -import React from 'react'; -import { act, fireEvent, render, screen } from '@testing-library/react'; +import React, { act } from 'react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import { MockedProvider } from '@apollo/react-testing'; import { I18nextProvider, useTranslation } from 'react-i18next'; @@ -2159,7 +2159,7 @@ describe('Testing Chat Screen [User Portal]', () => { }); }); - test('Test create new direct chat', async () => { + test('create new direct chat', async () => { const mock = [ ...USER_JOINED_ORG_MOCK, ...GROUP_CHAT_BY_ID_QUERY_MOCK, @@ -2199,7 +2199,7 @@ describe('Testing Chat Screen [User Portal]', () => { fireEvent.click(closeButton); }); - test('Test create new group chat', async () => { + test('create new group chat', async () => { const mock = [ ...USER_JOINED_ORG_MOCK, ...GROUP_CHAT_BY_ID_QUERY_MOCK, @@ -2259,15 +2259,26 @@ describe('Testing Chat Screen [User Portal]', () => { , ); + screen.debug(); + await waitFor(() => { + const closeMenuBtn = screen.queryByTestId('closeMenu'); + expect(closeMenuBtn).toBeInTheDocument(); + if (closeMenuBtn) { + closeMenuBtn.click(); + } else { + throw new Error('Close menu button not found'); + } + }); - await wait(); - - const closeMenubtn = screen.getByTestId('closeMenu'); - expect(closeMenubtn).toBeInTheDocument(); - closeMenubtn.click(); - const openMenuBtn = screen.getByTestId('openMenu'); - expect(openMenuBtn).toBeInTheDocument(); - openMenuBtn.click(); + await waitFor(() => { + const openMenuBtn = screen.queryByTestId('openMenu'); + expect(openMenuBtn).toBeInTheDocument(); + if (openMenuBtn) { + openMenuBtn.click(); + } else { + throw new Error('Open menu button not found'); + } + }); }); test('Testing sidebar when the screen size is less than or equal to 820px', async () => { @@ -2293,12 +2304,16 @@ describe('Testing Chat Screen [User Portal]', () => { , ); - await wait(); - expect(screen.getByText('My Organizations')).toBeInTheDocument(); - expect(screen.getByText('Talawa User Portal')).toBeInTheDocument(); - - const chatBtn = screen.getByTestId('chatBtn'); - - chatBtn.click(); + screen.debug(); + await waitFor(() => { + expect(screen.getByText('My Organizations')).toBeInTheDocument(); + expect(screen.getByText('Talawa User Portal')).toBeInTheDocument(); + }); + await waitFor(() => { + const chatBtn = screen.getByTestId('chatBtn'); + act(() => { + chatBtn.click(); + }); + }); }); }); diff --git a/src/screens/UserPortal/Chat/Chat.tsx b/src/screens/UserPortal/Chat/Chat.tsx index 2cc14eab58..43e8f5ab61 100644 --- a/src/screens/UserPortal/Chat/Chat.tsx +++ b/src/screens/UserPortal/Chat/Chat.tsx @@ -8,7 +8,7 @@ import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; import ContactCard from 'components/UserPortal/ContactCard/ContactCard'; import ChatRoom from 'components/UserPortal/ChatRoom/ChatRoom'; import useLocalStorage from 'utils/useLocalstorage'; -import { ReactComponent as NewChat } from 'assets/svgs/newChat.svg'; +import NewChat from 'assets/svgs/newChat.svg?react'; import Accordion from 'react-bootstrap/Accordion'; import styles from './Chat.module.css'; import UserSidebar from 'components/UserPortal/UserSidebar/UserSidebar'; @@ -26,7 +26,32 @@ interface InterfaceContactCardProps { type: string; setSelectedChatType: React.Dispatch>; } - +/** + * The `chat` component provides a user interface for interacting with contacts and chat rooms within an organization. + * It features a contact list with search functionality and displays the chat room for the selected contact. + * The component uses GraphQL to fetch and manage contact data, and React state to handle user interactions. + * + * ## Features: + * - **Search Contacts:** Allows users to search for contacts by their first name. + * - **Contact List:** Displays a list of contacts with their details and a profile image. + * - **Chat Room:** Shows the chat room for the selected contact. + * + * ## GraphQL Queries: + * - `ORGANIZATIONS_MEMBER_CONNECTION_LIST`: Fetches a list of members within an organization, with optional filtering based on the first name. + * + * ## Event Handlers: + * - `handleSearch`: Updates the filterName state and refetches the contact data based on the search query. + * - `handleSearchByEnter`: Handles search input when the Enter key is pressed. + * - `handleSearchByBtnClick`: Handles search input when the search button is clicked. + * + * ## Rendering: + * - Displays a search input field and a search button for filtering contacts. + * - Shows a list of contacts with their details and profile images. + * - Renders a chat room component for the selected contact. + * - Displays a loading indicator while contact data is being fetched. + * + * @returns The rendered `chat` component. + */ export default function chat(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'chat', diff --git a/src/screens/UserPortal/Donate/Donate.module.css b/src/screens/UserPortal/Donate/Donate.module.css index 4e21cb08d4..8f19db3ff8 100644 --- a/src/screens/UserPortal/Donate/Donate.module.css +++ b/src/screens/UserPortal/Donate/Donate.module.css @@ -1,25 +1,16 @@ -.containerHeight { - height: 100vh; -} - .mainContainer { width: 50%; flex-grow: 3; - padding: 1rem; - max-height: 100%; - overflow: auto; display: flex; flex-direction: column; background-color: #f2f7ff; } .inputContainer { - margin-top: 3rem; flex: 1; position: relative; } .input { - width: 70%; position: relative; box-shadow: 5px 5px 4px 0px #31bb6b1f; } diff --git a/src/screens/UserPortal/Donate/Donate.test.tsx b/src/screens/UserPortal/Donate/Donate.test.tsx index fc30ba7503..c4d435415e 100644 --- a/src/screens/UserPortal/Donate/Donate.test.tsx +++ b/src/screens/UserPortal/Donate/Donate.test.tsx @@ -1,5 +1,5 @@ -import React from 'react'; -import { act, render, screen } from '@testing-library/react'; +import React, { act } from 'react'; +import { render, screen } from '@testing-library/react'; import { MockedProvider } from '@apollo/react-testing'; import { I18nextProvider } from 'react-i18next'; @@ -16,6 +16,7 @@ import Donate from './Donate'; import userEvent from '@testing-library/user-event'; import useLocalStorage from 'utils/useLocalstorage'; import { DONATE_TO_ORGANIZATION } from 'GraphQl/Mutations/mutations'; +import { toast } from 'react-toastify'; const MOCKS = [ { @@ -136,6 +137,13 @@ jest.mock('react-router-dom', () => ({ useParams: () => ({ orgId: '' }), })); +jest.mock('react-toastify', () => ({ + toast: { + error: jest.fn(), + success: jest.fn(), + }, +})); + describe('Testing Donate Screen [User Portal]', () => { Object.defineProperty(window, 'matchMedia', { writable: true, @@ -280,4 +288,103 @@ describe('Testing Donate Screen [User Portal]', () => { userEvent.click(screen.getByTestId('donateBtn')); await wait(); }); + + test('displays error toast for donation amount below minimum', async () => { + render( + + + + + + + + + , + ); + + await wait(); + + userEvent.type(screen.getByTestId('donationAmount'), '0.5'); + userEvent.click(screen.getByTestId('donateBtn')); + + await wait(); + + expect(toast.error).toHaveBeenCalledWith( + 'Donation amount must be between 1 and 10000000.', + ); + }); + + test('displays error toast for donation amount above maximum', async () => { + render( + + + + + + + + + , + ); + + await wait(); + + userEvent.type(screen.getByTestId('donationAmount'), '10000001'); + userEvent.click(screen.getByTestId('donateBtn')); + + await wait(); + + expect(toast.error).toHaveBeenCalledWith( + 'Donation amount must be between 1 and 10000000.', + ); + }); + + test('displays error toast for empty donation amount', async () => { + render( + + + + + + + + + , + ); + + await wait(); + + userEvent.click(screen.getByTestId('donateBtn')); + + await wait(); + + expect(toast.error).toHaveBeenCalledWith( + 'Please enter a numerical value for the donation amount.', + ); + }); + + test('displays error toast for invalid (non-numeric) donation amount', async () => { + render( + + + + + + + + + , + ); + + await wait(); + + userEvent.type(screen.getByTestId('donationAmount'), 'abc'); + userEvent.click(screen.getByTestId('donateBtn')); + + await wait(); + + expect(toast.error).toHaveBeenCalledWith( + 'Please enter a numerical value for the donation amount.', + ); + }); }); diff --git a/src/screens/UserPortal/Donate/Donate.tsx b/src/screens/UserPortal/Donate/Donate.tsx index 4e39c4e1be..c6e6d918d5 100644 --- a/src/screens/UserPortal/Donate/Donate.tsx +++ b/src/screens/UserPortal/Donate/Donate.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { useParams } from 'react-router-dom'; import { Button, Dropdown, Form, InputGroup } from 'react-bootstrap'; import { toast } from 'react-toastify'; @@ -29,6 +29,39 @@ export interface InterfaceDonationCardProps { updatedAt: string; } +interface InterfaceDonation { + _id: string; + nameOfUser: string; + amount: string; + userId: string; + payPalId: string; + updatedAt: string; +} + +/** + * `donate` component allows users to make donations to an organization and view their previous donations. + * + * This component fetches donation-related data using GraphQL queries and allows users to make donations + * using a mutation. It supports currency selection, donation amount input, and displays a paginated list + * of previous donations. + * + * It includes: + * - An input field for searching donations. + * - A dropdown to select currency. + * - An input field for entering donation amount. + * - A button to submit the donation. + * - A list of previous donations displayed in a paginated format. + * - An organization sidebar for navigation. + * + * ### GraphQL Queries + * - `ORGANIZATION_DONATION_CONNECTION_LIST`: Fetches the list of donations for the organization. + * - `USER_ORGANIZATION_CONNECTION`: Fetches organization details. + * + * ### GraphQL Mutations + * - `DONATE_TO_ORGANIZATION`: Performs the donation action. + * + * @returns The rendered component. + */ export default function donate(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'donate', @@ -39,17 +72,19 @@ export default function donate(): JSX.Element { const userName = getItem('name'); const { orgId: organizationId } = useParams(); - const [amount, setAmount] = React.useState(''); - const [organizationDetails, setOrganizationDetails]: any = React.useState({}); - const [donations, setDonations] = React.useState([]); - const [selectedCurrency, setSelectedCurrency] = React.useState(0); - const [page, setPage] = React.useState(0); - const [rowsPerPage, setRowsPerPage] = React.useState(5); + const [amount, setAmount] = useState(''); + const [organizationDetails, setOrganizationDetails] = useState<{ + name: string; + }>({ name: '' }); + const [donations, setDonations] = useState([]); + const [selectedCurrency, setSelectedCurrency] = useState(0); + const [page, setPage] = useState(0); + const [rowsPerPage, setRowsPerPage] = useState(5); const currencies = ['USD', 'INR', 'EUR']; const { - data: data2, + data: donationData, loading, refetch, } = useQuery(ORGANIZATION_DONATION_CONNECTION_LIST, { @@ -62,10 +97,6 @@ export default function donate(): JSX.Element { const [donate] = useMutation(DONATE_TO_ORGANIZATION); - const navbarProps = { - currentPage: 'donate', - }; - /* istanbul ignore next */ const handleChangePage = ( _event: React.MouseEvent | null, @@ -84,19 +115,41 @@ export default function donate(): JSX.Element { setPage(0); }; - React.useEffect(() => { + useEffect(() => { if (data) { setOrganizationDetails(data.organizationsConnection[0]); } }, [data]); - React.useEffect(() => { - if (data2) { - setDonations(data2.getDonationByOrgIdConnection); + useEffect(() => { + if (donationData) { + setDonations(donationData.getDonationByOrgIdConnection); } - }, [data2]); + }, [donationData]); const donateToOrg = (): void => { + // check if the amount is non empty and is a number + if (amount === '' || Number.isNaN(Number(amount))) { + toast.error(t(`invalidAmount`)); + return; + } + + // check if the amount is non negative and within the range + const minDonation = 1; + const maxDonation = 10000000; + if ( + Number(amount) <= 0 || + Number(amount) < minDonation || + Number(amount) > maxDonation + ) { + toast.error( + t(`donationOutOfRange`, { min: minDonation, max: maxDonation }), + ); + return; + } + + const formattedAmount = Number(amount.trim()); + try { donate({ variables: { @@ -104,13 +157,13 @@ export default function donate(): JSX.Element { createDonationOrgId2: organizationId, payPalId: 'paypalId', nameOfUser: userName, - amount: Number(amount), + amount: formattedAmount, nameOfOrg: organizationDetails.name, }, }); refetch(); - toast.success(t(`success`)); - } catch (error: any) { + toast.success(t(`success`) as string); + } catch (error: unknown) { /* istanbul ignore next */ errorHandler(t, error); } @@ -118,9 +171,8 @@ export default function donate(): JSX.Element { return ( <> -
    -
    -

    {t(`donations`)}

    +
    +
    + + {t('donationAmountDescription')} +
    + + + ); + }, + }, + ]; + + return ( +
    +
    +
    + setSearchTerm(e.target.value)} + data-testid="searchPledges" + /> + +
    +
    + + + + + + {tCommon('sort')} + + + setSortBy('amount_ASC')} + data-testid="amount_ASC" + > + {t('lowestAmount')} + + setSortBy('amount_DESC')} + data-testid="amount_DESC" + > + {t('highestAmount')} + + setSortBy('endDate_DESC')} + data-testid="endDate_DESC" + > + {t('latestEndDate')} + + setSortBy('endDate_ASC')} + data-testid="endDate_ASC" + > + {t('earliestEndDate')} + + + +
    +
    + + row._id} + slots={{ + noRowsOverlay: () => ( + + {t('noPledges')} + + ), + }} + sx={dataGridStyle} + getRowClassName={() => `${styles.rowBackground}`} + autoHeight + rowHeight={65} + rows={pledges.map((pledge) => ({ + _id: pledge._id, + users: pledge.users, + startDate: pledge.startDate, + endDate: pledge.endDate, + amount: pledge.amount, + currency: pledge.currency, + campaign: pledge.campaign, + }))} + columns={columns} + isRowSelectable={() => false} + /> + + closeModal(ModalState.UPDATE)} + campaignId={pledge?.campaign ? pledge?.campaign._id : ''} + userId={userId} + pledge={pledge} + refetchPledge={refetchPledge} + endDate={pledge?.campaign ? pledge?.campaign.endDate : new Date()} + mode={'edit'} + /> + + closeModal(ModalState.DELETE)} + pledge={pledge} + refetchPledge={refetchPledge} + /> + + 4 ? styles.popupExtra : ''}`} + > + {extraUsers.map((user: InterfacePledger, index: number) => ( +
    + {user.image ? ( + pledger + ) : ( +
    + +
    + )} + + {user.firstName + ' ' + user.lastName} + +
    + ))} +
    +
    + ); +}; + +export default Pledges; diff --git a/src/screens/UserPortal/Pledges/PledgesMocks.ts b/src/screens/UserPortal/Pledges/PledgesMocks.ts new file mode 100644 index 0000000000..c7666987ff --- /dev/null +++ b/src/screens/UserPortal/Pledges/PledgesMocks.ts @@ -0,0 +1,596 @@ +import { DELETE_PLEDGE } from 'GraphQl/Mutations/PledgeMutation'; +import { USER_DETAILS } from 'GraphQl/Queries/Queries'; +import { USER_PLEDGES } from 'GraphQl/Queries/fundQueries'; + +const userDetailsQuery = { + request: { + query: USER_DETAILS, + variables: { + id: 'userId', + }, + }, + result: { + data: { + user: { + user: { + _id: 'userId', + joinedOrganizations: [ + { + _id: '6537904485008f171cf29924', + __typename: 'Organization', + }, + ], + firstName: 'Harve', + lastName: 'Lance', + email: 'testuser1@example.com', + image: null, + createdAt: '2023-04-13T04:53:17.742Z', + birthDate: null, + educationGrade: null, + employmentStatus: null, + gender: null, + maritalStatus: null, + phone: null, + address: { + line1: 'Line1', + countryCode: 'CountryCode', + city: 'CityName', + state: 'State', + __typename: 'Address', + }, + registeredEvents: [], + membershipRequests: [], + __typename: 'User', + }, + appUserProfile: { + _id: '67078abd85008f171cf2991d', + adminFor: [], + isSuperAdmin: false, + appLanguageCode: 'en', + pluginCreationAllowed: true, + createdOrganizations: [], + createdEvents: [], + eventAdmin: [], + __typename: 'AppUserProfile', + }, + __typename: 'UserData', + }, + }, + }, +}; + +export const MOCKS = [ + { + request: { + query: USER_PLEDGES, + variables: { + userId: 'userId', + where: { + name_contains: '', + }, + orderBy: 'endDate_DESC', + }, + }, + result: { + data: { + getPledgesByUserId: [ + { + _id: 'pledgeId1', + amount: 700, + startDate: '2024-07-28', + endDate: '2024-08-13', + campaign: { + _id: 'campaignId1', + name: 'Hospital Campaign', + endDate: '2024-08-30', + __typename: 'FundraisingCampaign', + }, + currency: 'USD', + users: [ + { + _id: 'userId', + firstName: 'Harve', + lastName: 'Lance', + image: null, + __typename: 'User', + }, + { + _id: 'userId2', + firstName: 'Deanne', + lastName: 'Marks', + image: null, + __typename: 'User', + }, + { + _id: 'userId3', + firstName: 'Jeramy', + lastName: 'Garcia', + image: null, + __typename: 'User', + }, + { + _id: 'userId4', + firstName: 'Praise', + lastName: 'Norris', + image: null, + __typename: 'User', + }, + ], + __typename: 'FundraisingCampaignPledge', + }, + { + _id: 'pledgeId2', + amount: 100, + startDate: '2024-07-28', + endDate: '2024-08-13', + campaign: { + _id: 'campaignId2', + name: 'School Campaign', + endDate: '2024-08-30', + __typename: 'FundraisingCampaign', + }, + currency: 'USD', + users: [ + { + _id: 'userId5', + firstName: 'John', + lastName: 'Doe', + image: null, + __typename: 'User', + }, + { + _id: 'userId6', + firstName: 'Jane', + lastName: 'Doe', + image: null, + __typename: 'User', + }, + ], + __typename: 'FundraisingCampaignPledge', + }, + ], + }, + }, + }, + { + request: { + query: USER_PLEDGES, + variables: { + userId: 'userId', + where: { + firstName_contains: 'Harve', + }, + orderBy: 'endDate_DESC', + }, + }, + result: { + data: { + getPledgesByUserId: [ + { + _id: 'pledgeId1', + amount: 700, + startDate: '2024-07-28', + endDate: '2024-08-13', + campaign: { + _id: 'campaignId1', + name: 'Hospital Campaign', + endDate: '2024-08-30', + __typename: 'FundraisingCampaign', + }, + currency: 'USD', + users: [ + { + _id: 'userId', + firstName: 'Harve', + lastName: 'Lance', + image: null, + __typename: 'User', + }, + ], + __typename: 'FundraisingCampaignPledge', + }, + ], + }, + }, + }, + { + request: { + query: USER_PLEDGES, + variables: { + userId: 'userId', + where: { + name_contains: 'School', + }, + orderBy: 'endDate_DESC', + }, + }, + result: { + data: { + getPledgesByUserId: [ + { + _id: 'pledgeId2', + amount: 100, + startDate: '2024-07-28', + endDate: '2024-08-13', + campaign: { + _id: 'campaignId2', + name: 'School Campaign', + endDate: '2024-08-30', + __typename: 'FundraisingCampaign', + }, + currency: 'USD', + users: [ + { + _id: 'userId5', + firstName: 'John', + lastName: 'Doe', + image: null, + __typename: 'User', + }, + { + _id: 'userId6', + firstName: 'Jane', + lastName: 'Doe', + image: null, + __typename: 'User', + }, + ], + __typename: 'FundraisingCampaignPledge', + }, + ], + }, + }, + }, + { + request: { + query: USER_PLEDGES, + variables: { + userId: 'userId', + where: { + firstName_contains: '', + }, + orderBy: 'amount_ASC', + }, + }, + result: { + data: { + getPledgesByUserId: [ + { + _id: 'pledgeId2', + amount: 100, + startDate: '2024-07-28', + endDate: '2024-08-13', + campaign: { + _id: 'campaignId2', + name: 'School Campaign', + endDate: '2024-08-30', + __typename: 'FundraisingCampaign', + }, + currency: 'USD', + users: [ + { + _id: 'userId5', + firstName: 'John', + lastName: 'Doe', + image: null, + __typename: 'User', + }, + ], + __typename: 'FundraisingCampaignPledge', + }, + { + _id: 'pledgeId1', + amount: 700, + startDate: '2024-07-28', + endDate: '2024-08-13', + campaign: { + _id: 'campaignId1', + name: 'Hospital Campaign', + endDate: '2024-08-30', + __typename: 'FundraisingCampaign', + }, + currency: 'USD', + users: [ + { + _id: 'userId', + firstName: 'Harve', + lastName: 'Lance', + image: 'image-url', + __typename: 'User', + }, + ], + __typename: 'FundraisingCampaignPledge', + }, + ], + }, + }, + }, + { + request: { + query: USER_PLEDGES, + variables: { + userId: 'userId', + where: { + firstName_contains: '', + }, + orderBy: 'amount_DESC', + }, + }, + result: { + data: { + getPledgesByUserId: [ + { + _id: 'pledgeId1', + amount: 700, + startDate: '2024-07-28', + endDate: '2024-08-13', + campaign: { + _id: 'campaignId1', + name: 'Hospital Campaign', + endDate: '2024-08-30', + __typename: 'FundraisingCampaign', + }, + currency: 'USD', + users: [ + { + _id: 'userId', + firstName: 'Harve', + lastName: 'Lance', + image: 'image-url', + __typename: 'User', + }, + ], + __typename: 'FundraisingCampaignPledge', + }, + { + _id: 'pledgeId2', + amount: 100, + startDate: '2024-07-28', + endDate: '2024-08-13', + campaign: { + _id: 'campaignId2', + name: 'School Campaign', + endDate: '2024-08-30', + __typename: 'FundraisingCampaign', + }, + currency: 'USD', + users: [ + { + _id: 'userId5', + firstName: 'John', + lastName: 'Doe', + image: null, + __typename: 'User', + }, + ], + __typename: 'FundraisingCampaignPledge', + }, + ], + }, + }, + }, + { + request: { + query: USER_PLEDGES, + variables: { + userId: 'userId', + where: { + firstName_contains: '', + }, + orderBy: 'endDate_ASC', + }, + }, + result: { + data: { + getPledgesByUserId: [ + { + _id: 'pledgeId1', + amount: 700, + startDate: '2024-07-28', + endDate: '2024-08-13', + campaign: { + _id: 'campaignId1', + name: 'Hospital Campaign', + endDate: '2024-08-30', + __typename: 'FundraisingCampaign', + }, + currency: 'USD', + users: [ + { + _id: 'userId', + firstName: 'Harve', + lastName: 'Lance', + image: 'image-url', + __typename: 'User', + }, + ], + __typename: 'FundraisingCampaignPledge', + }, + { + _id: 'pledgeId2', + amount: 100, + startDate: '2024-07-28', + endDate: '2024-08-14', + campaign: { + _id: 'campaignId2', + name: 'School Campaign', + endDate: '2024-08-30', + __typename: 'FundraisingCampaign', + }, + currency: 'USD', + users: [ + { + _id: 'userId5', + firstName: 'John', + lastName: 'Doe', + image: null, + __typename: 'User', + }, + ], + __typename: 'FundraisingCampaignPledge', + }, + ], + }, + }, + }, + { + request: { + query: USER_PLEDGES, + variables: { + userId: 'userId', + where: { + firstName_contains: '', + }, + orderBy: 'endDate_DESC', + }, + }, + result: { + data: { + getPledgesByUserId: [ + { + _id: 'pledgeId2', + amount: 100, + startDate: '2024-07-28', + endDate: '2024-08-14', + campaign: { + _id: 'campaignId2', + name: 'School Campaign', + endDate: '2024-08-30', + __typename: 'FundraisingCampaign', + }, + currency: 'USD', + users: [ + { + _id: 'userId5', + firstName: 'John', + lastName: 'Doe', + image: null, + __typename: 'User', + }, + { + _id: 'userId6', + firstName: 'Jane', + lastName: 'Doe', + image: null, + __typename: 'User', + }, + { + _id: 'userId7', + firstName: 'John2', + lastName: 'Doe2', + image: 'image-url3', + __typename: 'User', + }, + { + _id: 'userId8', + firstName: 'Jane2', + lastName: 'Doe2', + image: null, + __typename: 'User', + }, + { + _id: 'userId9', + firstName: 'John3', + lastName: 'Doe3', + image: null, + __typename: 'User', + }, + { + _id: 'userId10', + firstName: 'Jane3', + lastName: 'Doe3', + image: null, + __typename: 'User', + }, + { + _id: 'userId11', + firstName: 'John4', + lastName: 'Doe4', + image: null, + __typename: 'User', + }, + ], + __typename: 'FundraisingCampaignPledge', + }, + { + _id: 'pledgeId1', + amount: 700, + startDate: '2024-07-28', + endDate: '2024-08-13', + campaign: { + _id: 'campaignId1', + name: 'Hospital Campaign', + endDate: '2024-08-30', + __typename: 'FundraisingCampaign', + }, + currency: 'USD', + users: [ + { + _id: 'userId', + firstName: 'Harve', + lastName: 'Lance', + image: 'image-url', + __typename: 'User', + }, + ], + __typename: 'FundraisingCampaignPledge', + }, + ], + }, + }, + }, + { + request: { + query: DELETE_PLEDGE, + variables: { + id: '1', + }, + }, + result: { + data: { + removeFundraisingCampaignPledge: { + _id: '1', + }, + }, + }, + }, + userDetailsQuery, +]; + +export const EMPTY_MOCKS = [ + { + request: { + query: USER_PLEDGES, + variables: { + userId: 'userId', + where: { + firstName_contains: '', + }, + orderBy: 'endDate_DESC', + }, + }, + result: { + data: { + getPledgesByUserId: [], + }, + }, + }, + userDetailsQuery, +]; + +export const USER_PLEDGES_ERROR = [ + { + request: { + query: USER_PLEDGES, + variables: { + userId: 'userId', + where: { + firstName_contains: '', + }, + orderBy: 'endDate_DESC', + }, + }, + error: new Error('Error fetching pledges'), + }, + userDetailsQuery, +]; diff --git a/src/screens/UserPortal/Posts/Posts.test.tsx b/src/screens/UserPortal/Posts/Posts.test.tsx index da499403ea..aa5f03fdcf 100644 --- a/src/screens/UserPortal/Posts/Posts.test.tsx +++ b/src/screens/UserPortal/Posts/Posts.test.tsx @@ -1,7 +1,7 @@ -import React from 'react'; +import React, { act } from 'react'; import { MockedProvider } from '@apollo/react-testing'; import type { RenderResult } from '@testing-library/react'; -import { act, render, screen, waitFor, within } from '@testing-library/react'; +import { render, screen, waitFor, within } from '@testing-library/react'; import { I18nextProvider } from 'react-i18next'; import userEvent from '@testing-library/user-event'; import { @@ -15,6 +15,7 @@ import { StaticMockLink } from 'utils/StaticMockLink'; import i18nForTest from 'utils/i18nForTest'; import Home from './Posts'; import useLocalStorage from 'utils/useLocalstorage'; +import { DELETE_POST_MUTATION } from 'GraphQl/Mutations/mutations'; const { setItem } = useLocalStorage(); @@ -217,6 +218,17 @@ const MOCKS = [ }, }, }, + { + request: { + query: DELETE_POST_MUTATION, + variables: { id: '6411e54835d7ba2344a78e29' }, + }, + result: { + data: { + removePost: { _id: '6411e54835d7ba2344a78e29' }, + }, + }, + }, ]; const link = new StaticMockLink(MOCKS, true); @@ -350,10 +362,11 @@ describe('Testing Home Screen: User Portal', () => { test('Checking if refetch works after deleting this post', async () => { setItem('userId', '640d98d9eb6a743d75341067'); renderHomeScreen(); - await wait(); - - userEvent.click(screen.getAllByTestId('dropdown')[1]); - userEvent.click(screen.getByTestId('deletePost')); + expect(screen.queryAllByTestId('dropdown')).not.toBeNull(); + const dropdowns = await screen.findAllByTestId('dropdown'); + userEvent.click(dropdowns[1]); + const deleteButton = await screen.findByTestId('deletePost'); + userEvent.click(deleteButton); }); }); @@ -380,11 +393,7 @@ describe('HomeScreen with invalid orgId', () => { , ); - - // Wait for the navigation to occur - await waitFor(() => { - const homeEl = screen.getByTestId('homeEl'); - expect(homeEl).toBeInTheDocument(); - }); + const homeEl = await screen.findByTestId('homeEl'); + expect(homeEl).toBeInTheDocument(); }); }); diff --git a/src/screens/UserPortal/Posts/Posts.tsx b/src/screens/UserPortal/Posts/Posts.tsx index e3d3d8556c..256bb5f52f 100644 --- a/src/screens/UserPortal/Posts/Posts.tsx +++ b/src/screens/UserPortal/Posts/Posts.tsx @@ -119,21 +119,35 @@ type InterfacePostNode = { likes: InterfacePostLikes; }; +/** + * `home` component displays the main feed for a user, including posts, promoted content, and options to create a new post. + * + * It utilizes Apollo Client for fetching and managing data through GraphQL queries. The component fetches and displays posts from an organization, promoted advertisements, and handles user interactions for creating new posts. It also manages state for displaying modal dialogs and handling file uploads for new posts. + * + * @returns JSX.Element - The rendered `home` component. + */ export default function home(): JSX.Element { + // Translation hook for localized text const { t } = useTranslation('translation', { keyPrefix: 'home' }); const { t: tCommon } = useTranslation('common'); + + // Custom hook for accessing local storage const { getItem } = useLocalStorage(); const [posts, setPosts] = useState([]); const [pinnedPosts, setPinnedPosts] = useState([]); const [showModal, setShowModal] = useState(false); const [postImg, setPostImg] = useState(''); + + // Fetching the organization ID from URL parameters const { orgId } = useParams(); + // Redirect to user page if organization ID is not available if (!orgId) { return ; } + // Query hooks for fetching posts, advertisements, and user details const { data: promotedPostsData, }: { @@ -147,6 +161,7 @@ export default function home(): JSX.Element { first: 6, }, }); + const { data, refetch, @@ -164,12 +179,14 @@ export default function home(): JSX.Element { const user: InterfaceQueryUserListItem | undefined = userData?.user; + // Effect hook to update posts state when data changes useEffect(() => { if (data) { setPosts(data.organizations[0].posts.edges); } }, [data]); + // Effect hook to update advertisements state when data changes useEffect(() => { if (promotedPostsData && promotedPostsData.organizations) { const ads: Ad[] = @@ -189,6 +206,12 @@ export default function home(): JSX.Element { ); }, [posts]); + /** + * Converts a post node into props for the `PostCard` component. + * + * @param node - The post node to convert. + * @returns The props for the `PostCard` component. + */ const getCardProps = (node: InterfacePostNode): InterfacePostCard => { const { creator, @@ -270,10 +293,16 @@ export default function home(): JSX.Element { return cardProps; }; + /** + * Opens the post creation modal. + */ const handlePostButtonClick = (): void => { setShowModal(true); }; + /** + * Closes the post creation modal. + */ const handleModalClose = (): void => { setShowModal(false); }; diff --git a/src/screens/UserPortal/Settings/Settings.test.tsx b/src/screens/UserPortal/Settings/Settings.test.tsx index eccf59aaab..34aa3711bd 100644 --- a/src/screens/UserPortal/Settings/Settings.test.tsx +++ b/src/screens/UserPortal/Settings/Settings.test.tsx @@ -1,5 +1,5 @@ -import React from 'react'; -import { act, fireEvent, render, screen } from '@testing-library/react'; +import React, { act } from 'react'; +import { fireEvent, render, screen } from '@testing-library/react'; import { MockedProvider } from '@apollo/react-testing'; import { I18nextProvider } from 'react-i18next'; import { UPDATE_USER_MUTATION } from 'GraphQl/Mutations/mutations'; @@ -144,7 +144,7 @@ const resizeWindow = (width: number): void => { }; async function wait(ms = 100): Promise { - await act(() => { + await act(async () => { return new Promise((resolve) => { setTimeout(resolve, ms); }); @@ -152,32 +152,37 @@ async function wait(ms = 100): Promise { } describe('Testing Settings Screen [User Portal]', () => { - Object.defineProperty(window, 'matchMedia', { - writable: true, - value: jest.fn().mockImplementation((query) => ({ - matches: false, - media: query, - onchange: null, - addListener: jest.fn(), // Deprecated - removeListener: jest.fn(), // Deprecated - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - dispatchEvent: jest.fn(), - })), + // Mock implementation of matchMedia + beforeAll(() => { + Object.defineProperty(window, 'matchMedia', { + writable: true, + value: jest.fn().mockImplementation((query) => ({ + matches: false, + media: query, + onchange: null, + addListener: jest.fn(), // Deprecated + removeListener: jest.fn(), // Deprecated + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn(), + })), + }); }); test('Screen should be rendered properly', async () => { - render( - - - - - - - - - , - ); + await act(async () => { + render( + + + + + + + + + , + ); + }); await wait(); @@ -185,17 +190,19 @@ describe('Testing Settings Screen [User Portal]', () => { }); test('input works properly', async () => { - render( - - - - - - - - - , - ); + await act(async () => { + render( + + + + + + + + + , + ); + }); await wait(); @@ -240,17 +247,19 @@ describe('Testing Settings Screen [User Portal]', () => { }); test('resetChangesBtn works properly', async () => { - render( - - - - - - - - - , - ); + await act(async () => { + render( + + + + + + + + + , + ); + }); await wait(); @@ -270,17 +279,19 @@ describe('Testing Settings Screen [User Portal]', () => { }); test('resetChangesBtn works properly when the details are empty', async () => { - render( - - - - - - - - - , - ); + await act(async () => { + render( + + + + + + + + + , + ); + }); await wait(); @@ -300,210 +311,64 @@ describe('Testing Settings Screen [User Portal]', () => { }); test('sidebar', async () => { - render( - - - - - - - - - , - ); + await act(async () => { + render( + + + + + + + + + , + ); + }); await wait(); const closeMenubtn = screen.getByTestId('closeMenu'); expect(closeMenubtn).toBeInTheDocument(); - closeMenubtn.click(); + act(() => closeMenubtn.click()); const openMenuBtn = screen.getByTestId('openMenu'); expect(openMenuBtn).toBeInTheDocument(); - openMenuBtn.click(); + act(() => openMenuBtn.click()); }); test('Testing sidebar when the screen size is less than or equal to 820px', async () => { resizeWindow(800); - render( - - - - - - - - - , - ); - await wait(); - expect(screen.getByText('My Organizations')).toBeInTheDocument(); - expect(screen.getByText('Talawa User Portal')).toBeInTheDocument(); - - const settingsBtn = screen.getByTestId('settingsBtn'); - - settingsBtn.click(); - }); - - test('updateUserDetails Mutation is triggered on button click', async () => { - render( - - - - - - - - - , - ); - - await wait(); - - userEvent.type(screen.getByTestId('inputFirstName'), 'Noble'); - await wait(); - - userEvent.type(screen.getByTestId('inputLastName'), 'Mittal'); - await wait(); - - userEvent.selectOptions(screen.getByTestId('inputGender'), 'OTHER'); - await wait(); - - userEvent.type(screen.getByTestId('inputPhoneNumber'), '+174567890'); - await wait(); - - fireEvent.change(screen.getByLabelText('Birth Date'), { - target: { value: '2024-03-01' }, + await act(async () => { + render( + + + + + + + + + , + ); }); - await wait(); - userEvent.selectOptions(screen.getByTestId('inputGrade'), 'Graduate'); await wait(); - userEvent.selectOptions(screen.getByTestId('inputEmpStatus'), 'Unemployed'); - await wait(); + screen.debug(); - userEvent.selectOptions(screen.getByTestId('inputMaritalStatus'), 'Single'); - await wait(); + const openMenuBtn = screen.queryByTestId('openMenu'); + console.log('Open Menu Button:', openMenuBtn); + expect(openMenuBtn).toBeInTheDocument(); - userEvent.type(screen.getByTestId('inputAddress'), 'random'); - await wait(); + if (openMenuBtn) { + act(() => openMenuBtn.click()); + } - userEvent.type(screen.getByTestId('inputState'), 'random'); - await wait(); + const closeMenuBtn = screen.queryByTestId('closeMenu'); + console.log('Close Menu Button:', closeMenuBtn); + expect(closeMenuBtn).toBeInTheDocument(); - userEvent.click(screen.getByTestId('updateUserBtn')); - await wait(); + if (closeMenuBtn) { + act(() => closeMenuBtn.click()); + } }); - - test('Marital Status dropdown value verification', async () => { - render( - - - - - - - - - , - ); - - await wait(); - - // SINGLE - expect( - screen.queryByRole('option', { name: mockMaritalStatusEnum[0].label }), - ).toBeInTheDocument(); - - userEvent.selectOptions( - // Find the select element - screen.getByTestId('inputMaritalStatus'), - // Find and select the Single option - screen.getByRole('option', { name: mockMaritalStatusEnum[0].label }), - ); - - expect(screen.getByTestId('inputMaritalStatus')).toHaveValue( - mockMaritalStatusEnum[0].value, - ); - - // ENGAGED - expect( - screen.queryByRole('option', { name: mockMaritalStatusEnum[1].label }), - ).toBeInTheDocument(); - - userEvent.selectOptions( - // Find the select element - screen.getByTestId('inputMaritalStatus'), - // Find and select the Engaged option - screen.getByRole('option', { name: mockMaritalStatusEnum[1].label }), - ); - - expect(screen.getByTestId('inputMaritalStatus')).toHaveValue( - mockMaritalStatusEnum[1].value, - ); - - // MARRIED - expect( - screen.queryByRole('option', { name: mockMaritalStatusEnum[2].label }), - ).toBeInTheDocument(); - - userEvent.selectOptions( - // Find the select element - screen.getByTestId('inputMaritalStatus'), - // Find and select the Married option - screen.getByRole('option', { name: mockMaritalStatusEnum[2].label }), - ); - - expect(screen.getByTestId('inputMaritalStatus')).toHaveValue( - mockMaritalStatusEnum[2].value, - ); - - // DIVORCED - expect( - screen.queryByRole('option', { name: mockMaritalStatusEnum[3].label }), - ).toBeInTheDocument(); - - userEvent.selectOptions( - // Find the select element - screen.getByTestId('inputMaritalStatus'), - // Find and select the Divorced option - screen.getByRole('option', { name: mockMaritalStatusEnum[3].label }), - ); - - expect(screen.getByTestId('inputMaritalStatus')).toHaveValue( - mockMaritalStatusEnum[3].value, - ); - - // WIDOWED - expect( - screen.queryByRole('option', { name: mockMaritalStatusEnum[4].label }), - ).toBeInTheDocument(); - - userEvent.selectOptions( - // Find the select element - screen.getByTestId('inputMaritalStatus'), - // Find and select the Widowed option - screen.getByRole('option', { name: mockMaritalStatusEnum[4].label }), - ); - - expect(screen.getByTestId('inputMaritalStatus')).toHaveValue( - mockMaritalStatusEnum[4].value, - ); - - // SEPARATED - expect( - screen.queryByRole('option', { name: mockMaritalStatusEnum[5].label }), - ).toBeInTheDocument(); - - userEvent.selectOptions( - // Find the select element - screen.getByTestId('inputMaritalStatus'), - // Find and select the Separated option - screen.getByRole('option', { name: mockMaritalStatusEnum[5].label }), - ); - - expect(screen.getByTestId('inputMaritalStatus')).toHaveValue( - mockMaritalStatusEnum[5].value, - ); - }, 60000); }); diff --git a/src/screens/UserPortal/Settings/Settings.tsx b/src/screens/UserPortal/Settings/Settings.tsx index 9fb63cd8e1..8b80f8ea1d 100644 --- a/src/screens/UserPortal/Settings/Settings.tsx +++ b/src/screens/UserPortal/Settings/Settings.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import styles from './Settings.module.css'; import { Button, Card, Col, Form, Row } from 'react-bootstrap'; @@ -21,16 +21,24 @@ import DeleteUser from 'components/UserProfileSettings/DeleteUser'; import OtherSettings from 'components/UserProfileSettings/OtherSettings'; import UserSidebar from 'components/UserPortal/UserSidebar/UserSidebar'; import ProfileDropdown from 'components/ProfileDropdown/ProfileDropdown'; -import { create } from 'domain'; +/** + * The Settings component allows users to view and update their profile settings. + * It includes functionality to handle image uploads, reset changes, and save updated user details. + * + * @returns The Settings component. + */ export default function settings(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'settings', }); const { t: tCommon } = useTranslation('common'); - const [hideDrawer, setHideDrawer] = useState(null); + /** + * Handler to adjust sidebar visibility based on window width. + * This function is invoked on window resize and when the component mounts. + */ const handleResize = (): void => { if (window.innerWidth <= 820) { setHideDrawer(!hideDrawer); @@ -46,11 +54,10 @@ export default function settings(): JSX.Element { }, []); const { setItem } = useLocalStorage(); - const { data } = useQuery(CHECK_AUTH, { fetchPolicy: 'network-only' }); const [updateUserDetails] = useMutation(UPDATE_USER_MUTATION); - const [userDetails, setUserDetails] = React.useState({ + const [userDetails, setUserDetails] = useState({ firstName: '', lastName: '', createdAt: '', @@ -67,8 +74,20 @@ export default function settings(): JSX.Element { image: '', }); + /** + * Ref to store the original image URL for comparison during updates. + */ const originalImageState = React.useRef(''); + /** + * Ref to access the file input element for image uploads. + */ const fileInputRef = React.useRef(null); + + /** + * Handles the update of user details. + * This function sends a mutation request to update the user details + * and reloads the page on success. + */ const handleUpdateUserDetails = async (): Promise => { try { let updatedUserDetails = { ...userDetails }; @@ -80,11 +99,12 @@ export default function settings(): JSX.Element { }); /* istanbul ignore next */ if (data) { - toast.success(tCommon('updatedSuccessfully', { item: 'Profile' })); + toast.success( + tCommon('updatedSuccessfully', { item: 'Profile' }) as string, + ); setTimeout(() => { window.location.reload(); }, 500); - const userFullName = `${userDetails.firstName} ${userDetails.lastName}`; setItem('name', userFullName); } @@ -93,6 +113,12 @@ export default function settings(): JSX.Element { } }; + /** + * Handles the change of a specific field in the user details state. + * + * @param fieldName - The name of the field to be updated. + * @param value - The new value for the field. + */ const handleFieldChange = (fieldName: string, value: string): void => { setUserDetails((prevState) => ({ ...prevState, @@ -100,12 +126,18 @@ export default function settings(): JSX.Element { })); }; + /** + * Triggers the file input click event to open the file picker dialog. + */ const handleImageUpload = (): void => { if (fileInputRef.current) { (fileInputRef.current as HTMLInputElement).click(); } }; + /** + * Resets the user details to the values fetched from the server. + */ const handleResetChanges = (): void => { /* istanbul ignore next */ if (data) { @@ -140,7 +172,7 @@ export default function settings(): JSX.Element { } }; - React.useEffect(() => { + useEffect(() => { /* istanbul ignore next */ if (data) { const { @@ -212,11 +244,14 @@ export default function settings(): JSX.Element { }`} >
    -
    +
    +
    +

    {tCommon('settings')}

    +
    -

    {tCommon('settings')}

    - + + -
    +
    + ); + }, + }, + ]; + + return ( + <> + + + {t('addPeople')} + +
    + +
    + {assignToMembers.length === 0 ? ( +
    + {t('noOneSelected')} +
    + ) : ( + assignToMembers.map((member) => ( +
    + {member.firstName} {member.lastName} + removeMember(member._id)} + data-testid="clearSelectedMember" + /> +
    + )) + )} +
    + +
    +
    + + + setMemberToAssignToSearchFirstName(e.target.value.trim()) + } + data-testid="searchByFirstName" + autoComplete="off" + /> +
    +
    + + + setMemberToAssignToSearchLastName(e.target.value.trim()) + } + data-testid="searchByLastName" + autoComplete="off" + /> +
    +
    + + {userTagsMembersToAssignToLoading ? ( +
    + +
    + ) : ( + <> +
    + } + scrollableTarget="addPeopleToTagScrollableDiv" + > + row.id} + slots={{ + noRowsOverlay: /* istanbul ignore next */ () => ( + + {t('noMoreMembersFound')} + + ), + }} + sx={{ + ...dataGridStyle, + '& .MuiDataGrid-topContainer': { + position: 'static', + }, + '& .MuiDataGrid-virtualScrollerContent': { + marginTop: '0', + }, + }} + getRowClassName={() => `${styles.rowBackground}`} + autoHeight + rowHeight={65} + rows={userTagMembersToAssignTo?.map( + (membersToAssignTo, index) => ({ + id: index + 1, + ...membersToAssignTo, + }), + )} + columns={columns} + isRowSelectable={() => false} + /> + +
    + + )} +
    + + + + + +
    + + ); +}; + +export default AddPeopleToTag; diff --git a/src/components/AddPeopleToTag/AddPeopleToTagsMocks.ts b/src/components/AddPeopleToTag/AddPeopleToTagsMocks.ts new file mode 100644 index 0000000000..fbaf812186 --- /dev/null +++ b/src/components/AddPeopleToTag/AddPeopleToTagsMocks.ts @@ -0,0 +1,292 @@ +import { ADD_PEOPLE_TO_TAG } from 'GraphQl/Mutations/TagMutations'; +import { USER_TAGS_MEMBERS_TO_ASSIGN_TO } from 'GraphQl/Queries/userTagQueries'; +import { TAGS_QUERY_DATA_CHUNK_SIZE } from 'utils/organizationTagsUtils'; + +export const MOCKS = [ + { + request: { + query: USER_TAGS_MEMBERS_TO_ASSIGN_TO, + variables: { + id: '1', + first: TAGS_QUERY_DATA_CHUNK_SIZE, + where: { + firstName: { starts_with: '' }, + lastName: { starts_with: '' }, + }, + }, + }, + result: { + data: { + getUsersToAssignTo: { + name: 'tag1', + usersToAssignTo: { + edges: [ + { + node: { + _id: '1', + firstName: 'member', + lastName: '1', + }, + cursor: '1', + }, + { + node: { + _id: '2', + firstName: 'member', + lastName: '2', + }, + cursor: '2', + }, + { + node: { + _id: '3', + firstName: 'member', + lastName: '3', + }, + cursor: '3', + }, + { + node: { + _id: '4', + firstName: 'member', + lastName: '4', + }, + cursor: '4', + }, + { + node: { + _id: '5', + firstName: 'member', + lastName: '5', + }, + cursor: '5', + }, + { + node: { + _id: '6', + firstName: 'member', + lastName: '6', + }, + cursor: '6', + }, + { + node: { + _id: '7', + firstName: 'member', + lastName: '7', + }, + cursor: '7', + }, + { + node: { + _id: '8', + firstName: 'member', + lastName: '8', + }, + cursor: '8', + }, + { + node: { + _id: '9', + firstName: 'member', + lastName: '9', + }, + cursor: '9', + }, + { + node: { + _id: '10', + firstName: 'member', + lastName: '10', + }, + cursor: '10', + }, + ], + pageInfo: { + startCursor: '1', + endCursor: '10', + hasNextPage: true, + hasPreviousPage: false, + }, + totalCount: 12, + }, + }, + }, + }, + }, + { + request: { + query: USER_TAGS_MEMBERS_TO_ASSIGN_TO, + variables: { + id: '1', + first: TAGS_QUERY_DATA_CHUNK_SIZE, + after: '10', + where: { + firstName: { starts_with: '' }, + lastName: { starts_with: '' }, + }, + }, + }, + result: { + data: { + getUsersToAssignTo: { + name: 'tag1', + usersToAssignTo: { + edges: [ + { + node: { + _id: '11', + firstName: 'member', + lastName: '11', + }, + cursor: '11', + }, + { + node: { + _id: '12', + firstName: 'member', + lastName: '12', + }, + cursor: '12', + }, + ], + pageInfo: { + startCursor: '11', + endCursor: '12', + hasNextPage: false, + hasPreviousPage: true, + }, + totalCount: 12, + }, + }, + }, + }, + }, + { + request: { + query: USER_TAGS_MEMBERS_TO_ASSIGN_TO, + variables: { + id: '1', + first: TAGS_QUERY_DATA_CHUNK_SIZE, + where: { + firstName: { starts_with: 'usersToAssignTo' }, + lastName: { starts_with: '' }, + }, + }, + }, + result: { + data: { + getUsersToAssignTo: { + name: 'tag1', + usersToAssignTo: { + edges: [ + { + node: { + _id: '1', + firstName: 'usersToAssignTo', + lastName: 'user1', + }, + cursor: '1', + }, + { + node: { + _id: '2', + firstName: 'usersToAssignTo', + lastName: 'user2', + }, + cursor: '2', + }, + ], + pageInfo: { + startCursor: '1', + endCursor: '2', + hasNextPage: false, + hasPreviousPage: false, + }, + totalCount: 2, + }, + }, + }, + }, + }, + { + request: { + query: USER_TAGS_MEMBERS_TO_ASSIGN_TO, + variables: { + id: '1', + first: TAGS_QUERY_DATA_CHUNK_SIZE, + where: { + firstName: { starts_with: '' }, + lastName: { starts_with: 'userToAssignTo' }, + }, + }, + }, + result: { + data: { + getUsersToAssignTo: { + name: 'tag1', + usersToAssignTo: { + edges: [ + { + node: { + _id: '1', + firstName: 'first', + lastName: 'userToAssignTo', + }, + cursor: '1', + }, + { + node: { + _id: '2', + firstName: 'second', + lastName: 'userToAssignTo', + }, + cursor: '2', + }, + ], + pageInfo: { + startCursor: '1', + endCursor: '2', + hasNextPage: false, + hasPreviousPage: false, + }, + totalCount: 2, + }, + }, + }, + }, + }, + { + request: { + query: ADD_PEOPLE_TO_TAG, + variables: { + tagId: '1', + userIds: ['1', '3', '5'], + }, + }, + result: { + data: { + addPeopleToUserTag: { + _id: '1', + }, + }, + }, + }, +]; + +export const MOCKS_ERROR = [ + { + request: { + query: USER_TAGS_MEMBERS_TO_ASSIGN_TO, + variables: { + id: '1', + first: TAGS_QUERY_DATA_CHUNK_SIZE, + where: { + firstName: { starts_with: '' }, + lastName: { starts_with: '' }, + }, + }, + }, + error: new Error('Mock Graphql Error'), + }, +]; diff --git a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.test.tsx b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.test.tsx index 1bf16ec76b..0646a94819 100644 --- a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.test.tsx +++ b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.test.tsx @@ -249,7 +249,7 @@ describe('Testing Advertisement Register Component', () => { }); await waitFor(() => { - expect(toast.success).toBeCalledWith( + expect(toast.success).toHaveBeenCalledWith( 'Advertisement created successfully.', ); expect(setTimeoutSpy).toHaveBeenCalled(); @@ -340,7 +340,7 @@ describe('Testing Advertisement Register Component', () => { }); await waitFor(() => { - expect(toast.success).toBeCalledWith( + expect(toast.success).toHaveBeenCalledWith( 'Advertisement created successfully.', ); expect(setTimeoutSpy).toHaveBeenCalled(); @@ -465,7 +465,7 @@ describe('Testing Advertisement Register Component', () => { await waitFor(() => { fireEvent.click(getByText(translations.register)); }); - expect(toast.error).toBeCalledWith( + expect(toast.error).toHaveBeenCalledWith( 'End Date should be greater than or equal to Start Date', ); expect(setTimeoutSpy).toHaveBeenCalled(); @@ -592,7 +592,7 @@ describe('Testing Advertisement Register Component', () => { fireEvent.click(getByText(translations.saveChanges)); await waitFor(() => { - expect(toast.error).toBeCalledWith( + expect(toast.error).toHaveBeenCalledWith( 'End Date should be greater than or equal to Start Date', ); }); diff --git a/src/components/AgendaCategory/AgendaCategoryContainer.test.tsx b/src/components/AgendaCategory/AgendaCategoryContainer.test.tsx index 5ddab82aec..d8e27c3cb2 100644 --- a/src/components/AgendaCategory/AgendaCategoryContainer.test.tsx +++ b/src/components/AgendaCategory/AgendaCategoryContainer.test.tsx @@ -269,7 +269,9 @@ describe('Testing Agenda Category Component', () => { userEvent.click(screen.getByTestId('editAgendaCategoryBtn')); await waitFor(() => { - expect(toast.success).toBeCalledWith(translations.agendaCategoryUpdated); + expect(toast.success).toHaveBeenCalledWith( + translations.agendaCategoryUpdated, + ); }); }); @@ -362,7 +364,9 @@ describe('Testing Agenda Category Component', () => { userEvent.click(screen.getByTestId('deleteAgendaCategoryBtn')); await waitFor(() => { - expect(toast.success).toBeCalledWith(translations.agendaCategoryDeleted); + expect(toast.success).toHaveBeenCalledWith( + translations.agendaCategoryDeleted, + ); }); }); diff --git a/src/components/AgendaItems/AgendaItemsContainer.test.tsx b/src/components/AgendaItems/AgendaItemsContainer.test.tsx index 7ceb8b4d08..8b391a2073 100644 --- a/src/components/AgendaItems/AgendaItemsContainer.test.tsx +++ b/src/components/AgendaItems/AgendaItemsContainer.test.tsx @@ -371,7 +371,9 @@ describe('Testing Agenda Items components', () => { userEvent.click(screen.getByTestId('deleteAgendaItemBtn')); await waitFor(() => { - expect(toast.success).toBeCalledWith(translations.agendaItemDeleted); + expect(toast.success).toHaveBeenCalledWith( + translations.agendaItemDeleted, + ); }); }); diff --git a/src/components/Avatar/Avatar.module.css b/src/components/Avatar/Avatar.module.css index 2a3190892f..13fe1bbbc6 100644 --- a/src/components/Avatar/Avatar.module.css +++ b/src/components/Avatar/Avatar.module.css @@ -1,6 +1,6 @@ .imageContainer { - width: 56px; - height: 56px; + width: fit-content; + height: fit-content; display: flex; align-items: center; justify-content: center; diff --git a/src/components/Avatar/Avatar.tsx b/src/components/Avatar/Avatar.tsx index 64b452b0c3..3e2f818e3f 100644 --- a/src/components/Avatar/Avatar.tsx +++ b/src/components/Avatar/Avatar.tsx @@ -41,10 +41,10 @@ const Avatar = ({ size: size || 128, seed: name, radius: radius || 0, - }).toDataUriSync(); + }).toDataUri(); }, [name, size]); - const svg = avatar.toString(); + const svg = avatar?.toString(); return (
    diff --git a/src/components/CheckIn/TableRow.test.tsx b/src/components/CheckIn/TableRow.test.tsx index 14c3d20c29..1a08f40a3d 100644 --- a/src/components/CheckIn/TableRow.test.tsx +++ b/src/components/CheckIn/TableRow.test.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { fireEvent, render, waitFor } from '@testing-library/react'; +import { fireEvent, render } from '@testing-library/react'; import { TableRow } from './TableRow'; import { BrowserRouter } from 'react-router-dom'; import { Provider } from 'react-redux'; @@ -130,4 +130,45 @@ describe('Testing Table Row for CheckIn Table', () => { expect(await findByText('Error checking in')).toBeInTheDocument(); expect(await findByText('Oops')).toBeInTheDocument(); }); + + test('If PDF generation fails, the error message should be shown', async () => { + const props = { + data: { + id: `123`, + name: '', + userId: `user123`, + checkIn: { + _id: '123', + time: '12:00:00', + }, + eventId: `event123`, + }, + refetch: jest.fn(), + }; + + const { findByText } = render( + + + + + + + + + + + + , + ); + + // Mocking the PDF generation function to throw an error + global.URL.createObjectURL = jest.fn(() => 'mockURL'); + global.window.open = jest.fn(); + + fireEvent.click(await findByText('Download Tag')); + + expect( + await findByText('Error generating pdf: Invalid or empty name provided'), + ).toBeInTheDocument(); + }); }); diff --git a/src/components/CheckIn/TableRow.tsx b/src/components/CheckIn/TableRow.tsx index 38d1dda912..b2bd6e11cb 100644 --- a/src/components/CheckIn/TableRow.tsx +++ b/src/components/CheckIn/TableRow.tsx @@ -66,7 +66,11 @@ export const TableRow = ({ */ const generateTag = async (): Promise => { try { - const inputs = [{ name: data.name }]; + const inputs = []; + if (typeof data.name !== 'string' || !data.name.trim()) { + throw new Error('Invalid or empty name provided'); + } + inputs.push({ name: data.name.trim() }); const pdf = await generate({ template: tagTemplate, inputs }); // istanbul ignore next const blob = new Blob([pdf.buffer], { type: 'application/pdf' }); diff --git a/src/components/CheckIn/tagTemplate.ts b/src/components/CheckIn/tagTemplate.ts index 4aa4475e02..acd35fca0d 100644 --- a/src/components/CheckIn/tagTemplate.ts +++ b/src/components/CheckIn/tagTemplate.ts @@ -19,4 +19,4 @@ export const tagTemplate: Template = { ], basePdf: 'data:application/pdf;base64,JVBERi0xLjQKJfbk/N8KMSAwIG9iago8PAovVHlwZSAvQ2F0YWxvZwovVmVyc2lvbiAvMS40Ci9QYWdlcyAyIDAgUgovU3RydWN0VHJlZVJvb3QgMyAwIFIKL01hcmtJbmZvIDQgMCBSCi9MYW5nIChlbikKL1ZpZXdlclByZWZlcmVuY2VzIDUgMCBSCj4+CmVuZG9iago2IDAgb2JqCjw8Ci9DcmVhdG9yIChDYW52YSkKL1Byb2R1Y2VyIChDYW52YSkKL0NyZWF0aW9uRGF0ZSAoRDoyMDIzMDYyMDA3MjgxMyswMCcwMCcpCi9Nb2REYXRlIChEOjIwMjMwNjIwMDcyODEzKzAwJzAwJykKL0tleXdvcmRzIChEQUZjMjhYSXViTSxCQUUycS01WEdhaykKL0F1dGhvciAoRXNoYWFuIEFnZ2Fyd2FsKQovVGl0bGUgKEJsYW5rIE5hbWUgVGFnIGluIEVtZXJhbGQgTWludCBHcmVlbiBBc3BpcmF0aW9uYWwgRWxlZ2FuY2UgU3R5bGUpCj4+CmVuZG9iagoyIDAgb2JqCjw8Ci9UeXBlIC9QYWdlcwovS2lkcyBbNyAwIFJdCi9Db3VudCAxCj4+CmVuZG9iagozIDAgb2JqCjw8Ci9UeXBlIC9TdHJ1Y3RUcmVlUm9vdAovUGFyZW50VHJlZSA4IDAgUgovUGFyZW50VHJlZU5leHRLZXkgMQovSyBbOSAwIFJdCi9JRFRyZWUgMTAgMCBSCj4+CmVuZG9iago0IDAgb2JqCjw8Ci9NYXJrZWQgdHJ1ZQovU3VzcGVjdHMgZmFsc2UKPj4KZW5kb2JqCjUgMCBvYmoKPDwKL0Rpc3BsYXlEb2NUaXRsZSB0cnVlCj4+CmVuZG9iago3IDAgb2JqCjw8Ci9UeXBlIC9QYWdlCi9SZXNvdXJjZXMgMTEgMCBSCi9NZWRpYUJveCBbMC4wIDcuOTIwMDAyNSAyNTIuMCAxNTEuOTJdCi9Db250ZW50cyAxMiAwIFIKL1N0cnVjdFBhcmVudHMgMAovUGFyZW50IDIgMCBSCi9UYWJzIC9TCi9CbGVlZEJveCBbMC4wIDcuOTIwMDAyNSAyNTIuMCAxNTEuOTJdCi9UcmltQm94IFswLjAgNy45MjAwMDI1IDI1Mi4wIDE1MS45Ml0KL0Nyb3BCb3ggWzAuMCA3LjkyMDAwMjUgMjUyLjAgMTUxLjkyXQovUm90YXRlIDAKL0Fubm90cyBbXQo+PgplbmRvYmoKOCAwIG9iago8PAovTGltaXRzIFswIDBdCi9OdW1zIFswIFsxMyAwIFIgMTQgMCBSIDE1IDAgUiAxNiAwIFIgMTcgMCBSIDE4IDAgUiAxOSAwIFJdCl0KPj4KZW5kb2JqCjkgMCBvYmoKPDwKL1R5cGUgL1N0cnVjdEVsZW0KL1MgL0RvY3VtZW50Ci9MYW5nIChlbikKL1AgMyAwIFIKL0sgWzIwIDAgUl0KL0lEIChub2RlMDAwMDE3MzgpCj4+CmVuZG9iagoxMCAwIG9iago8PAovTmFtZXMgWyhub2RlMDAwMDE3MzgpIDkgMCBSIChub2RlMDAwMDE3MzkpIDEzIDAgUiAobm9kZTAwMDAxNzQwKSAyMCAwIFIgKG5vZGUwMDAwMTc0MSkgMjEgMCBSIChub2RlMDAwMDE3NDIpIDIyIDAgUgoobm9kZTAwMDAxNzQzKSAyMyAwIFIgKG5vZGUwMDAwMTc0NCkgMjQgMCBSIChub2RlMDAwMDE3NDUpIDI1IDAgUiAobm9kZTAwMDAxNzQ2KSAyNiAwIFIgKG5vZGUwMDAwMTc0NykgMjcgMCBSCihub2RlMDAwMDE3NjEpIDI4IDAgUiAobm9kZTAwMDAxNzYyKSAyOSAwIFIgKG5vZGUwMDAwMTc2MykgMzAgMCBSIChub2RlMDAwMDE3NjQpIDMxIDAgUiAobm9kZTAwMDAxNzY1KSAzMiAwIFIKKG5vZGUwMDAwMTc2NikgMzMgMCBSIChub2RlMDAwMDE3NjcpIDE0IDAgUiAobm9kZTAwMDAxNzY4KSAzNCAwIFIgKG5vZGUwMDAwMTc2OSkgMzUgMCBSIChub2RlMDAwMDE3NzApIDM2IDAgUgoobm9kZTAwMDAxNzcxKSAxNSAwIFIgKG5vZGUwMDAwMTc3MikgMzcgMCBSIChub2RlMDAwMDE3NzMpIDM4IDAgUiAobm9kZTAwMDAxNzc0KSAzOSAwIFIgKG5vZGUwMDAwMTc3NSkgMTYgMCBSCihub2RlMDAwMDE3NzYpIDE3IDAgUiAobm9kZTAwMDAxNzc3KSA0MCAwIFIgKG5vZGUwMDAwMTc3OCkgMTggMCBSIChub2Rl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Tm9uU3RydWN0Ci9QIDQwIDAgUgovSyBbNTMgMCBSXQovSUQgKG5vZGUwMDAwMTc3OCkKPj4KZW5kb2JqCjE5IDAgb2JqCjw8Ci9UeXBlIC9TdHJ1Y3RFbGVtCi9TIC9Ob25TdHJ1Y3QKL1AgNDQgMCBSCi9LIFs1NCAwIFJdCi9JRCAobm9kZTAwMDAxNzgzKQo+PgplbmRvYmoKMjAgMCBvYmoKPDwKL1R5cGUgL1N0cnVjdEVsZW0KL1MgL0RpdgovUCA5IDAgUgovSyBbMjEgMCBSXQovSUQgKG5vZGUwMDAwMTc0MCkKPj4KZW5kb2JqCjIxIDAgb2JqCjw8Ci9UeXBlIC9TdHJ1Y3RFbGVtCi9TIC9EaXYKL1AgMjAgMCBSCi9LIFsyMiAwIFJdCi9JRCAobm9kZTAwMDAxNzQxKQo+PgplbmRvYmoKMjIgMCBvYmoKPDwKL1R5cGUgL1N0cnVjdEVsZW0KL1MgL0RpdgovUCAyMSAwIFIKL0sgWzIzIDAgUl0KL0lEIChub2RlMDAwMDE3NDIpCj4+CmVuZG9iagoyMyAwIG9iago8PAovVHlwZSAvU3RydWN0RWxlbQovUyAvRGl2Ci9QIDIyIDAgUgovSyBbMjQgMCBSXQovSUQgKG5vZGUwMDAwMTc0MykKPj4KZW5kb2JqCjI0IDAgb2JqCjw8Ci9UeXBlIC9TdHJ1Y3RFbGVtCi9TIC9EaXYKL1AgMjMgMCBSCi9LIFsyNSAwIFJdCi9JRCAobm9kZTAwMDAxNzQ0KQo+PgplbmRvYmoKMjUgMCBvYmoKPDwKL1R5cGUgL1N0cnVjdEVsZW0KL1MgL0RpdgovUCAyNCAwIFIKL0sgWzI2IDAgUl0KL0lEIChub2RlMDAwMDE3NDUpCj4+CmVuZG9iagoyNiAwIG9iago8PAovVHlwZSAvU3RydWN0RWxlbQovUyAvRGl2Ci9QIDI1IDAgUgovSyBbMjcgMCBSXQovSUQgKG5vZGUwMDAwMTc0NikKPj4KZW5kb2JqCjI3IDAgb2JqCjw8Ci9UeXBlIC9TdHJ1Y3RFbGVtCi9TIC9EaXYKL1AgMjYgMCBSCi9LIFsyOCAwIFIgMzEgMCBSIDM0IDAgUiAzNyAwIFIgNDEgMCBSXQovSUQgKG5vZGUwMDAwMTc0NykKPj4KZW5kb2JqCjI4IDAgb2JqCjw8Ci9UeXBlIC9TdHJ1Y3RFbGVtCi9TIC9EaXYKL1AgMjcgMCBSCi9LIFsyOSAwIFJdCi9JRCAobm9kZTAwMDAxNzYxKQo+PgplbmRvYmoKMjkgMCBvYmoKPDwKL1R5cGUgL1N0cnVjdEVsZW0KL1MgL0RpdgovUCAyOCAwIFIKL0sgWzMwIDAgUl0KL0lEIChub2RlMDAwMDE3NjIpCj4+CmVuZG9iagozMCAwIG9iago8PAovVHlwZSAvU3RydWN0RWxlbQovUyAvRGl2Ci9QIDI5IDAgUgovSyBbMTMgMCBSXQovSUQgKG5vZGUwMDAwMTc2MykKPj4KZW5kb2JqCjMxIDAgb2JqCjw8Ci9UeXBlIC9TdHJ1Y3RFbGVtCi9TIC9EaXYKL1AgMjcgMCBSCi9LIFszMiAwIFJdCi9JRCAobm9kZTAwMDAxNzY0KQo+PgplbmRvYmoKMzIgMCBvYmoKPDwKL1R5cGUgL1N0cnVjdEVsZW0KL1MgL0RpdgovUCAzMSAwIFIKL0sgWzMzIDAgUl0KL0lEIChub2RlMDAwMDE3NjUpCj4+CmVuZG9iagozMyAwIG9iago8PAovVHlwZSAvU3RydWN0RWxlbQovUyAvUAovUCAzMiAwIFIKL0sgWzE0IDAgUl0KL0lEIChub2RlMDAwMDE3NjYpCj4+CmVuZG9iagozNCAwIG9iago8PAovVHlwZSAvU3RydWN0RWxlbQovUyAvRGl2Ci9QIDI3IDAgUgovSyBbMzUgMCBSXQovSUQgKG5vZGUwMDAwMTc2OCkKPj4KZW5kb2JqCjM1IDAgb2JqCjw8Ci9UeXBlIC9TdHJ1Y3RFbGVtCi9TIC9EaXYKL1AgMzQgMCBSCi9LIFszNiAwIFJdCi9JRCAobm9kZTAwMDAxNzY5KQo+PgplbmRvYmoKMzYgMCBvYmoKPDwKL1R5cGUgL1N0cnVjdEVsZW0KL1MgL1AKL1AgMzUgMCBSCi9LIFsxNSAwIFJdCi9JRCAobm9kZTAwMDAxNzcwKQo+PgplbmRvYmoKMzcgMCBvYmoKPDwKL1R5cGUgL1N0cnVjdEVsZW0KL1MgL0RpdgovUCAyNyAwIFIKL0sgWzM4IDAgUl0KL0lEIChub2RlMDAwMDE3NzIpCj4+CmVuZG9iagozOCAwIG9iago8PAovVHlwZSAvU3RydWN0RWxlbQovUyAvRGl2Ci9QIDM3IDAgUgovSyBbMzkgMCBSIDQwIDAgUl0KL0lEIChub2RlMDAwMDE3NzMpCj4+CmVuZG9iagozOSAwIG9iago8PAovVHlwZSAvU3RydWN0RWxlbQovUyAvUAovUCAzOCAwIFIKL0sgWzE2IDAgUiAxNyAwIFJdCi9JRCAobm9kZTAwMDAxNzc0KQo+PgplbmRvYmoKNDAgMCBvYmoKPDwKL1R5cGUgL1N0cnVjdEVsZW0KL1MgL1AKL1AgMzggMCBSCi9LIFsxOCAwIFJdCi9JRCAobm9kZTAwMDAxNzc3KQo+PgplbmRvYmoKNDEgMCBvYmoKPDwKL1R5cGUgL1N0cnVjdEVsZW0KL1MgL0RpdgovUCAyNyAwIFIKL0sgWzQyIDAgUl0KL0lEIChub2RlMDAwMDE3NzkpCj4+CmVuZG9iago0MiAwIG9iago8PAovVHlwZSAvU3RydWN0RWxlbQovUyAvRGl2Ci9QIDQxIDAgUgovSyBbNDMgMCBSXQovSUQgKG5vZGUwMDAwMTc4MCkKPj4KZW5kb2JqCjQzIDAgb2JqCjw8Ci9UeXBlIC9TdHJ1Y3RFbGVtCi9TIC9EaXYKL1AgNDIgMCBSCi9LIFs0NCAwIFJdCi9JRCAobm9kZTAwMDAxNzgxKQo+PgplbmRvYmoKNDQgMCBvYmoKPDwKL1R5cGUgL1N0cnVjdEVsZW0KL1MgL1AKL1AgNDMgMCBSCi9LIFsxOSAwIFJdCi9JRCAobm9kZTAwMDAxNzgyKQo+PgplbmRvYmoKNDUgMCBvYmoKPDwKL0czIDU1IDAgUgovRzQgNTYgMCBSCj4+CmVuZG9iago0NiAwIG9iago8PAovTGVuZ3RoIDMwMTg4Ci9UeXBlIC9YT2JqZWN0Ci9TdWJ0eXBlIC9JbWFnZQovV2lkdGggMzQ3Ci9IZWlnaHQgMjMzCi9Db2xvclNwYWNlIC9EZXZpY2VSR0IKL1NNYXNrIDU3IDAgUgovQml0c1BlckNvbXBvbmVudCA4Ci9GaWx0ZXIgL0ZsYXRlRGVjb2RlCj4+CnN0cmVhbQ0KeJzsfQl4FNeVbgmpN6GuajDYY1tIIpPJm8dbJhkyb5LJTIaZJCaYRRvCwTEOjmNi42DAZjGLpNbGamOMgVgJGGMMxo3QvqKltQsB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arVJSZxajbW01KrRlKs9h/BjZkdpqcM8035UbS3VWNRqi6bMzXLBceLFI+QgnL9QSjQ3F284UObxlJW5XMTrMpvcbpMZXofoP5F+JXQNCmVuZHN0cmVhbQplbmRvYmoKeHJlZgowIDY0CjAwMDAwMDAwMDAgNjU1MzUgZg0KMDAwMDAwMDAxNSAwMDAwMCBuDQowMDAwMDAwNDE5IDAwMDAwIG4NCjAwMDAwMDA0NzYgMDAwMDAgbg0KMDAwMDAwMDU4NCAwMDAwMCBuDQowMDAwMDAwNjM0IDAwMDAwIG4NCjAwMDAwMDAxNTIgMDAwMDAgbg0KMDAwMDAwMDY3NyAwMDAwMCBuDQowMDAwMDAwOTYwIDAwMDAwIG4NCjAwMDAwMDEwNTcgMDAwMDAgbg0KMDAwMDAwMTE2MCAwMDAwMCBuDQowMDAwMDAxOTE2IDAwMDAwIG4NCjAwMDAwMDIwNDEgMDAwMDAgbg0KMDAwMDAwMzA5NCAwMDAwMCBuDQowMDAwMDAzMTg2IDAwMDAwIG4NCjAwMDAwMDMyODEgMDAwMDAgbg0KMDAwMDAwMzM3NiAwMDAwMCBuDQowMDAwMDAzNDcxIDAwMDAwIG4NCjAwMDAwMDM1NjYgMDAwMDAgbg0KMDAwMDAwMzY2MSAwMDAwMCBuDQowMDAwMDAzNzU2IDAwMDAwIG4NCjAwMDAwMDM4NDQgMDAwMDAgbg0KMDAwMDAwMzkzMyAwMDAwMCBuDQowMDAwMDA0MDIyIDAwMDAwIG4NCjAwMDAwMDQxMTEgMDAwMDAgbg0KMDAwMDAwNDIwMCAwMDAwMCBuDQowMDAwMDA0Mjg5IDAwMDAwIG4NCjAwMDAwMDQzNzggMDAwMDAgbg0KMDAwMDAwNDQ5NSAwMDAwMCBuDQowMDAwMDA0NTg0IDAwMDAwIG4NCjAwMDAwMDQ2NzMgMDAwMDAgbg0KMDAwMDAwNDc2MiAwMDAwMCBuDQowMDAwMDA0ODUxIDAwMDAwIG4NCjAwMDAwMDQ5NDAgMDAwMDAgbg0KMDAwMDAwNTAyNyAwMDAwMCBuDQowMDAwMDA1MTE2IDAwMDAwIG4NCjAwMDAwMDUyMDUgMDAwMDAgbg0KMDAwMDAwNTI5MiAwMDAwMCBuDQowMDAwMDA1MzgxIDAwMDAwIG4NCjAwMDAwMDU0NzcgMDAwMDAgbg0KMDAwMDAwNTU3MSAwMDAwMCBuDQowMDAwMDA1NjU4IDAwMDAwIG4NCjAwMDAwMDU3NDcgMDAwMDAgbg0KMDAwMDAwNTgzNiAwMDAwMCBuDQowMDAwMDA1OTI1IDAwMDAwIG4NCjAwMDAwMDYwMTIgMDAwMDAgbg0KMDAwMDAwNjA1NiAwMDAwMCBuDQowMDAwMDM2NDMyIDAwMDAwIG4NCjAwMDAwMzY0NjUgMDAwMDAgbg0KMDAwMDAzNjUxNiAwMDAwMCBuDQowMDAwMDM2NTY3IDAwMDAwIG4NCjAwMDAwMzY2MTggMDAwMDAgbg0KMDAwMDAzNjY2OSAwMDAwMCBuDQowMDAwMDM2NzIwIDAwMDAwIG4NCjAwMDAwMzY3NzEgMDAwMDAgbg0KMDAwMDAzNjgyMiAwMDAwMCBuDQowMDAwMDM2ODYyIDAwMDAwIG4NCjAwMDAwMzY5NDEgMDAwMDAgbg0KMDAwMDA0OTMxNiAwMDAwMCBuDQowMDAwMDQ5NDY5IDAwMDAwIG4NCjAwMDAwNTAwMzcgMDAwMDAgbg0KMDAwMDA1MDQ2NSAwMDAwMCBuDQowMDAwMDUwNzIwIDAwMDAwIG4NCjAwMDAwNTA3OTUgMDAwMDAgbg0KdHJhaWxlcgo8PAovUm9vdCAxIDAgUgovSW5mbyA2IDAgUgovSUQgWzwwQ0M3NzdBRDZENEFBMThFRkFGQ0ExODQ3QjI1QkMxQz4gPDBDQzc3N0FENkQ0QUExOEVGQUZDQTE4NDdCMjVCQzFDPl0KL1NpemUgNjQKPj4Kc3RhcnR4cmVmCjU0MDk2CiUlRU9GCg==', -}; +}; \ No newline at end of file diff --git a/src/components/DynamicDropDown/DynamicDropDown.module.css b/src/components/DynamicDropDown/DynamicDropDown.module.css index 0edf85b621..3cd40fe35d 100644 --- a/src/components/DynamicDropDown/DynamicDropDown.module.css +++ b/src/components/DynamicDropDown/DynamicDropDown.module.css @@ -1,6 +1,7 @@ .dropwdownToggle { background-color: #f1f3f6; color: black; + width: 100%; border: none; padding: 0.5rem; text-align: left; diff --git a/src/components/DynamicDropDown/DynamicDropDown.test.tsx b/src/components/DynamicDropDown/DynamicDropDown.test.tsx index c77ac5aebf..dac98ca9e6 100644 --- a/src/components/DynamicDropDown/DynamicDropDown.test.tsx +++ b/src/components/DynamicDropDown/DynamicDropDown.test.tsx @@ -1,27 +1,21 @@ import React from 'react'; -import { render, screen, act, waitFor } from '@testing-library/react'; +import { + render, + screen, + act, + waitFor, + fireEvent, +} from '@testing-library/react'; import DynamicDropDown from './DynamicDropDown'; import { BrowserRouter } from 'react-router-dom'; import { I18nextProvider } from 'react-i18next'; import i18nForTest from 'utils/i18nForTest'; import userEvent from '@testing-library/user-event'; -async function wait(ms = 100): Promise { - await act(() => { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); - }); -} - describe('DynamicDropDown component', () => { - test('renders with name and alt attribute', async () => { - const [formData, setFormData] = [ - { - fieldName: 'TEST', - }, - jest.fn(), - ]; + test('renders and handles selection correctly', async () => { + const formData = { fieldName: 'value2' }; + const setFormData = jest.fn(); render( @@ -30,35 +24,126 @@ describe('DynamicDropDown component', () => { formState={formData} setFormState={setFormData} fieldOptions={[ - { value: 'TEST', label: 'label1' }, - { value: 'value2', label: 'label2' }, + { value: 'TEST', label: 'Label 1' }, + { value: 'value2', label: 'Label 2' }, ]} fieldName="fieldName" /> , ); - const containterElement = screen.getByTestId( - 'fieldname-dropdown-container', - ); - await act(async () => { - userEvent.click(containterElement); - }); - const optionButton = screen.getByTestId('fieldname-dropdown-btn'); + // Verify that the dropdown container is rendered + const containerElement = screen.getByTestId('fieldname-dropdown-container'); + expect(containerElement).toBeInTheDocument(); + // Verify that the dropdown button displays the correct initial label + const dropdownButton = screen.getByTestId('fieldname-dropdown-btn'); + expect(dropdownButton).toHaveTextContent('Label 2'); + + // Open the dropdown menu await act(async () => { - userEvent.click(optionButton); + userEvent.click(dropdownButton); }); + // Select the first option in the dropdown const optionElement = screen.getByTestId('change-fieldname-btn-TEST'); await act(async () => { userEvent.click(optionElement); }); - await wait(); - expect(containterElement).toBeInTheDocument(); + + // Verify that the setFormData function was called with the correct arguments + expect(setFormData).toHaveBeenCalledWith({ fieldName: 'TEST' }); + + // Verify that the dropdown button displays the updated label await waitFor(() => { - expect(optionButton).toHaveTextContent('label1'); + expect(dropdownButton).toHaveTextContent('Label 2'); + }); + }); + test('calls custom handleChange function when provided', async () => { + const formData = { fieldName: 'value1' }; + const setFormData = jest.fn(); + const customHandleChange = jest.fn(); + + render( + + + + + , + ); + + const dropdownButton = screen.getByTestId('fieldname-dropdown-btn'); + await act(async () => { + userEvent.click(dropdownButton); }); + + const optionElement = screen.getByTestId('change-fieldname-btn-value2'); + await act(async () => { + userEvent.click(optionElement); + }); + + expect(customHandleChange).toHaveBeenCalledTimes(1); + expect(customHandleChange).toHaveBeenCalledWith( + expect.objectContaining({ + target: expect.objectContaining({ + name: 'fieldName', + value: 'value2', + }), + }), + ); + expect(setFormData).not.toHaveBeenCalled(); + }); + test('handles keyboard navigation correctly', async () => { + const formData = { fieldName: 'value1' }; + const setFormData = jest.fn(); + + render( + + + + + , + ); + + // Open dropdown + const dropdownButton = screen.getByTestId('fieldname-dropdown-btn'); + await act(async () => { + userEvent.click(dropdownButton); + }); + + // Get dropdown menu + const dropdownMenu = screen.getByTestId('fieldname-dropdown-menu'); + + // Simulate Enter key press + await act(async () => { + fireEvent.keyDown(dropdownMenu, { key: 'Enter' }); + }); + + // Simulate Space key press + await act(async () => { + fireEvent.keyDown(dropdownMenu, { key: ' ' }); + }); + + // Verify the dropdown menu behavior + const option = screen.getByTestId('change-fieldname-btn-value2'); + expect(option).toBeInTheDocument(); }); }); diff --git a/src/components/DynamicDropDown/DynamicDropDown.tsx b/src/components/DynamicDropDown/DynamicDropDown.tsx index fac8b8fd85..05cd064ac2 100644 --- a/src/components/DynamicDropDown/DynamicDropDown.tsx +++ b/src/components/DynamicDropDown/DynamicDropDown.tsx @@ -5,14 +5,15 @@ import styles from './DynamicDropDown.module.css'; /** * Props for the DynamicDropDown component. */ -interface InterfaceChangeDropDownProps { +interface InterfaceChangeDropDownProps { parentContainerStyle?: string; btnStyle?: string; btnTextStyle?: string; - setFormState: React.Dispatch>; - formState: any; - fieldOptions: { value: string; label: string }[]; // Field options for dropdown - fieldName: string; // Field name for labeling + setFormState: React.Dispatch>; + formState: T; + fieldOptions: { value: string; label: string }[]; + fieldName: string; + handleChange?: (e: React.ChangeEvent) => void; } /** @@ -27,57 +28,74 @@ interface InterfaceChangeDropDownProps { * @param formState - Current state of the form, used to determine the selected value. * @param fieldOptions - Options to display in the dropdown. Each option has a value and a label. * @param fieldName - The name of the field, used for labeling and key identification. + * @param handleChange - Optional callback function when selection changes * @returns JSX.Element - The rendered dropdown component. */ -const DynamicDropDown = ({ +const DynamicDropDown = >({ parentContainerStyle = '', btnStyle = '', setFormState, formState, fieldOptions, fieldName, -}: InterfaceChangeDropDownProps): JSX.Element => { - /** - * Updates the form state when a dropdown option is selected. - * - * @param value - The value of the selected option. - */ + handleChange, +}: InterfaceChangeDropDownProps): JSX.Element => { const handleFieldChange = (value: string): void => { - setFormState({ ...formState, [fieldName]: value }); + if (handleChange) { + const event = { + target: { + name: fieldName, + value: value, + }, + } as React.ChangeEvent; + handleChange(event); + } else { + setFormState({ ...formState, [fieldName]: value }); + } }; - /** - * Retrieves the label for a given value from the options. - * - * @param value - The value for which to get the label. - * @returns The label corresponding to the value, or 'None' if not found. - */ const getLabel = (value: string): string => { const selectedOption = fieldOptions.find( (option) => option.value === value, ); - return selectedOption ? selectedOption.label : `None`; + return selectedOption ? selectedOption.label : 'None'; }; return ( - + { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + const focused = document.activeElement; + if (focused instanceof HTMLElement) { + focused.click(); + } + } + }} + > {fieldOptions.map((option, index: number) => ( handleFieldChange(option.value)} data-testid={`change-${fieldName.toLowerCase()}-btn-${option.value}`} + role="option" + aria-selected={option.value === formState[fieldName]} > {option.label} diff --git a/src/components/EventCalendar/EventCalendar.test.tsx b/src/components/EventCalendar/EventCalendar.test.tsx index caca516763..8e2395968a 100644 --- a/src/components/EventCalendar/EventCalendar.test.tsx +++ b/src/components/EventCalendar/EventCalendar.test.tsx @@ -286,13 +286,14 @@ describe('Calendar', () => { // expect(todayCell).toHaveClass(styles.day__today); }); it('Should handle window resize in day view', async () => { + const date = new Date().toISOString().split('T')[0]; const multipleEventData = [ { _id: '1', title: 'Event 1', description: 'This is event 1', - startDate: new Date().toISOString().split('T')[0], - endDate: new Date().toISOString().split('T')[0], + startDate: date, + endDate: date, location: 'Los Angeles', startTime: null, endTime: null, @@ -307,8 +308,8 @@ describe('Calendar', () => { _id: '2', title: 'Event 2', description: 'This is event 2', - startDate: new Date().toISOString().split('T')[0], - endDate: new Date().toISOString().split('T')[0], + startDate: date, + endDate: date, location: 'Los Angeles', startTime: null, endTime: null, @@ -323,8 +324,8 @@ describe('Calendar', () => { _id: '3', title: 'Event 3', description: 'This is event 3', - startDate: new Date().toISOString().split('T')[0], - endDate: new Date().toISOString().split('T')[0], + startDate: date, + endDate: date, location: 'Los Angeles', startTime: '14:00', endTime: '16:00', @@ -339,8 +340,8 @@ describe('Calendar', () => { _id: '4', title: 'Event 4', description: 'This is event 4', - startDate: new Date().toISOString().split('T')[0], - endDate: new Date().toISOString().split('T')[0], + startDate: date, + endDate: date, location: 'Los Angeles', startTime: '14:00', endTime: '16:00', @@ -355,8 +356,8 @@ describe('Calendar', () => { _id: '5', title: 'Event 5', description: 'This is event 5', - startDate: new Date().toISOString().split('T')[0], - endDate: new Date().toISOString().split('T')[0], + startDate: date, + endDate: date, location: 'Los Angeles', startTime: '17:00', endTime: '19:00', @@ -372,14 +373,40 @@ describe('Calendar', () => { - + - , , ); + + // Simulate window resize and check if components respond correctly + await act(async () => { + window.innerWidth = 500; // Set the window width to <= 700 + window.dispatchEvent(new Event('resize')); + }); + + // Check for "View all" button if there are more than 2 events + const viewAllButton = await screen.findAllByTestId('more'); + console.log('hi', viewAllButton); // This will show the buttons found in the test + expect(viewAllButton.length).toBeGreaterThan(0); + + // Simulate clicking the "View all" button to expand the list + fireEvent.click(viewAllButton[0]); + + const event5 = screen.queryByText('Event 5'); + expect(event5).toBeNull(); + + const viewLessButtons = screen.getAllByText('View less'); + expect(viewLessButtons.length).toBeGreaterThan(0); + + // Simulate clicking "View less" to collapse the list + fireEvent.click(viewLessButtons[0]); + const viewAllButtons = screen.getAllByText('View all'); + expect(viewAllButtons.length).toBeGreaterThan(0); + + // Reset the window size to avoid side effects for other tests await act(async () => { - window.innerWidth = 500; + window.innerWidth = 1024; window.dispatchEvent(new Event('resize')); }); }); diff --git a/src/components/EventCalendar/EventCalendar.tsx b/src/components/EventCalendar/EventCalendar.tsx index fb76eb597c..592456f295 100644 --- a/src/components/EventCalendar/EventCalendar.tsx +++ b/src/components/EventCalendar/EventCalendar.tsx @@ -558,6 +558,7 @@ const Calendar: React.FC = ({ /*istanbul ignore next*/ +

    + {eventData.event.title} +

    +

    + {eventData.event.description}

    -

    - Location: {eventData?.event?.location} +

    + Location: {eventData.event.location}

    -

    +

    Registrants:{' '} {eventData?.event?.attendees?.length}

    -
    +
    + Recurring Event:{' '} + + {eventData.event.recurring ? 'Active' : 'Inactive'} + +
    +
    +
    +

    + + {eventData.event.startTime !== null + ? `${formatTime(eventData.event.startTime)}` + : ``} + {' '} + + {formatDate(eventData.event.startDate)}{' '} + +

    +

    {t('to')}

    +

    + + {eventData.event.endTime !== null + ? `${formatTime(eventData.event.endTime)}` + : ``} + {' '} + + {formatDate(eventData.event.endDate)}{' '} + +

    diff --git a/src/components/EventManagement/EventAttendance/Attendance.mocks.ts b/src/components/EventManagement/EventAttendance/Attendance.mocks.ts new file mode 100644 index 0000000000..2dc8c89571 --- /dev/null +++ b/src/components/EventManagement/EventAttendance/Attendance.mocks.ts @@ -0,0 +1,62 @@ +import { EVENT_ATTENDEES } from 'GraphQl/Queries/Queries'; + +export const MOCKS = [ + { + request: { + query: EVENT_ATTENDEES, + variables: {}, // Removed id since it's not required based on error + }, + result: { + data: { + event: { + attendees: [ + { + _id: '6589386a2caa9d8d69087484', + firstName: 'Bruce', + lastName: 'Garza', + gender: null, + birthDate: null, + createdAt: '2023-04-13T10:23:17.742', + eventsAttended: [ + { + __typename: 'Event', + _id: '660fdf7d2c1ef6c7db1649ad', + }, + { + __typename: 'Event', + _id: '660fdd562c1ef6c7db1644f7', + }, + ], + __typename: 'User', + }, + { + _id: '6589386a2caa9d8d69087485', + firstName: 'Jane', + lastName: 'Smith', + gender: null, + birthDate: null, + createdAt: '2023-04-13T10:23:17.742', + eventsAttended: [ + { + __typename: 'Event', + _id: '660fdf7d2c1ef6c7db1649ad', + }, + ], + __typename: 'User', + }, + ], + }, + }, + }, + }, +]; + +export const MOCKS_ERROR = [ + { + request: { + query: EVENT_ATTENDEES, + variables: {}, + }, + error: new Error('An error occurred'), + }, +]; diff --git a/src/components/EventManagement/EventAttendance/AttendedEventList.test.tsx b/src/components/EventManagement/EventAttendance/AttendedEventList.test.tsx new file mode 100644 index 0000000000..2d60081acf --- /dev/null +++ b/src/components/EventManagement/EventAttendance/AttendedEventList.test.tsx @@ -0,0 +1,119 @@ +import React from 'react'; +import { render, waitFor } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import AttendedEventList from './AttendedEventList'; +import { EVENT_DETAILS } from 'GraphQl/Queries/Queries'; +import { BrowserRouter } from 'react-router-dom'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; +import { formatDate } from 'utils/dateFormatter'; + +const mockEvent = { + _id: 'event123', + title: 'Test Event', + description: 'This is a test event description', + startDate: '2023-05-01', + endDate: '2023-05-02', + startTime: '09:00:00', + endTime: '17:00:00', + allDay: false, + location: 'Test Location', + recurring: true, + baseRecurringEvent: { + _id: 'recurringEvent123', + }, + organization: { + _id: 'org456', + members: [ + { _id: 'member1', firstName: 'John', lastName: 'Doe' }, + { _id: 'member2', firstName: 'Jane', lastName: 'Smith' }, + ], + }, + attendees: [{ _id: 'user1' }, { _id: 'user2' }], +}; + +const mocks = [ + { + request: { + query: EVENT_DETAILS, + variables: { id: 'event123' }, + }, + result: { + data: { + event: mockEvent, + }, + }, + }, +]; + +describe('Testing AttendedEventList', () => { + const props = { + eventId: 'event123', + }; + + test('Component renders and displays event details correctly', async () => { + const { queryByText, queryByTitle } = render( + + + + + + + , + ); + + expect(queryByText('Loading...')).toBeInTheDocument(); + + await waitFor(() => { + expect(queryByText('Test Event')).toBeInTheDocument(); + expect(queryByText(formatDate(mockEvent.startDate))).toBeInTheDocument(); + expect(queryByTitle('Event Date')).toBeInTheDocument(); + }); + }); + + test('Component handles error state gracefully', async () => { + const errorMock = [ + { + request: { + query: EVENT_DETAILS, + variables: { id: 'event123' }, + }, + error: new Error('An error occurred'), + }, + ]; + + const { queryByText } = render( + + + + + + + , + ); + + await waitFor(() => { + expect(queryByText('Loading...')).not.toBeInTheDocument(); + // The component doesn't explicitly render an error message, so we just check that the event details are not rendered + expect(queryByText('Test Event')).not.toBeInTheDocument(); + }); + }); + + test('Component renders link with correct URL', async () => { + const { container } = render( + + + + + + + , + ); + + await waitFor(() => { + const link = container.querySelector('a'); + expect(link).not.toBeNull(); + expect(link).toHaveAttribute('href', expect.stringContaining('/event/')); + }); + }); +}); diff --git a/src/components/EventManagement/EventAttendance/AttendedEventList.tsx b/src/components/EventManagement/EventAttendance/AttendedEventList.tsx new file mode 100644 index 0000000000..2d0286feb0 --- /dev/null +++ b/src/components/EventManagement/EventAttendance/AttendedEventList.tsx @@ -0,0 +1,68 @@ +import React from 'react'; +import { TableBody, TableCell, TableRow, Table } from '@mui/material'; +import { EVENT_DETAILS } from 'GraphQl/Queries/Queries'; +import { useQuery } from '@apollo/client'; +import { Link, useParams } from 'react-router-dom'; +import { formatDate } from 'utils/dateFormatter'; +import DateIcon from 'assets/svgs/cardItemDate.svg?react'; +interface InterfaceEventsAttended { + eventId: string; +} +/** + * Component to display a list of events attended by a member + * @param eventId - The ID of the event to display details for + * @returns A table row containing event details with a link to the event + */ +const AttendedEventList: React.FC = ({ eventId }) => { + const { orgId: currentOrg } = useParams(); + const { data, loading, error } = useQuery(EVENT_DETAILS, { + variables: { id: eventId }, + fetchPolicy: 'cache-first', + errorPolicy: 'all', + }); + + if (error || data?.error) { + return

    Error loading event details. Please try again later.

    ; + } + + const event = data?.event ?? null; + + if (loading) return

    Loading...

    ; + return ( + + + + {event && ( + + + + +
    +
    {event.title}
    +
    {formatDate(event.startDate)}
    +
    + +
    +
    + )} +
    +
    +
    + ); +}; +export default AttendedEventList; diff --git a/src/components/EventManagement/EventAttendance/EventAttendance.test.tsx b/src/components/EventManagement/EventAttendance/EventAttendance.test.tsx new file mode 100644 index 0000000000..db44357d07 --- /dev/null +++ b/src/components/EventManagement/EventAttendance/EventAttendance.test.tsx @@ -0,0 +1,147 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import type { RenderResult } from '@testing-library/react'; +import { + render, + screen, + fireEvent, + cleanup, + waitFor, +} from '@testing-library/react'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { I18nextProvider } from 'react-i18next'; +import EventAttendance from './EventAttendance'; +import { store } from 'state/store'; +import userEvent from '@testing-library/user-event'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18n from 'utils/i18nForTest'; +import { MOCKS } from './Attendance.mocks'; + +const link = new StaticMockLink(MOCKS, true); + +async function wait(): Promise { + await waitFor(() => { + return Promise.resolve(); + }); +} +jest.mock('react-chartjs-2', () => ({ + Line: () => null, + Bar: () => null, + Pie: () => null, +})); + +const renderEventAttendance = (): RenderResult => { + return render( + + + + + + + + + , + ); +}; + +describe('Event Attendance Component', () => { + beforeEach(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ eventId: 'event123', orgId: 'org123' }), + })); + }); + + afterEach(() => { + jest.clearAllMocks(); + cleanup(); + }); + + test('Component loads correctly with table headers', async () => { + renderEventAttendance(); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('table-header-row')).toBeInTheDocument(); + expect(screen.getByTestId('header-member-name')).toBeInTheDocument(); + expect(screen.getByTestId('header-status')).toBeInTheDocument(); + }); + }); + + test('Renders attendee data correctly', async () => { + renderEventAttendance(); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('attendee-name-0')).toBeInTheDocument(); + expect(screen.getByTestId('attendee-name-1')).toHaveTextContent( + 'Jane Smith', + ); + }); + }); + + test('Search filters attendees by name correctly', async () => { + renderEventAttendance(); + + await wait(); + + const searchInput = screen.getByTestId('searchByName'); + fireEvent.change(searchInput, { target: { value: 'Bruce' } }); + + await waitFor(() => { + const filteredAttendee = screen.getByTestId('attendee-name-0'); + expect(filteredAttendee).toHaveTextContent('Bruce Garza'); + }); + }); + + test('Sort functionality changes attendee order', async () => { + renderEventAttendance(); + + await wait(); + + const sortDropdown = screen.getByTestId('sort-dropdown'); + userEvent.click(sortDropdown); + userEvent.click(screen.getByText('Sort')); + + await waitFor(() => { + const attendees = screen.getAllByTestId('attendee-name-0'); + expect(attendees[0]).toHaveTextContent('Bruce Garza'); + }); + }); + + test('Date filter shows correct number of attendees', async () => { + renderEventAttendance(); + + await wait(); + + userEvent.click(screen.getByText('Filter: All')); + userEvent.click(screen.getByText('This Month')); + + await waitFor(() => { + expect(screen.getByText('Attendees not Found')).toBeInTheDocument(); + }); + }); + test('Statistics modal opens and closes correctly', async () => { + renderEventAttendance(); + await wait(); + + expect(screen.queryByTestId('attendance-modal')).not.toBeInTheDocument(); + + const statsButton = screen.getByTestId('stats-modal'); + userEvent.click(statsButton); + + await waitFor(() => { + expect(screen.getByTestId('attendance-modal')).toBeInTheDocument(); + }); + + const closeButton = screen.getByTestId('close-button'); + userEvent.click(closeButton); + + await waitFor(() => { + expect(screen.queryByTestId('attendance-modal')).not.toBeInTheDocument(); + }); + }); +}); diff --git a/src/components/EventManagement/EventAttendance/EventAttendance.tsx b/src/components/EventManagement/EventAttendance/EventAttendance.tsx new file mode 100644 index 0000000000..17f063f6b5 --- /dev/null +++ b/src/components/EventManagement/EventAttendance/EventAttendance.tsx @@ -0,0 +1,376 @@ +import React, { useEffect, useMemo, useState } from 'react'; +import { BiSearch as Search } from 'react-icons/bi'; +import { + Paper, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + Tooltip, +} from '@mui/material'; +import { + Button, + Dropdown, + DropdownButton, + Table, + FormControl, +} from 'react-bootstrap'; +import styles from './EventsAttendance.module.css'; +import { useLazyQuery } from '@apollo/client'; +import { EVENT_ATTENDEES } from 'GraphQl/Queries/Queries'; +import { useParams, Link } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; +import { AttendanceStatisticsModal } from './EventStatistics'; +import AttendedEventList from './AttendedEventList'; +import type { InterfaceMember } from './InterfaceEvents'; +enum FilterPeriod { + ThisMonth = 'This Month', + ThisYear = 'This Year', + All = 'All', +} +/** + * Component to manage and display event attendance information + * Includes filtering and sorting functionality for attendees + * @returns JSX element containing the event attendance interface + */ +function EventAttendance(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'eventAttendance', + }); + const { eventId } = useParams<{ eventId: string }>(); + const { orgId: currentUrl } = useParams(); + const [filteredAttendees, setFilteredAttendees] = useState( + [], + ); + const [sortOrder, setSortOrder] = useState<'ascending' | 'descending'>( + 'ascending', + ); + const [filteringBy, setFilteringBy] = useState( + FilterPeriod.All, + ); + const [show, setShow] = useState(false); + + const sortAttendees = (attendees: InterfaceMember[]): InterfaceMember[] => { + return [...attendees].sort((a, b) => { + const nameA = `${a.firstName} ${a.lastName}`.toLowerCase(); + const nameB = `${b.firstName} ${b.lastName}`.toLowerCase(); + return sortOrder === 'ascending' + ? nameA.localeCompare(nameB) + : /*istanbul ignore next*/ + nameB.localeCompare(nameA); + }); + }; + + const filterAttendees = (attendees: InterfaceMember[]): InterfaceMember[] => { + const now = new Date(); + return filteringBy === 'All' + ? attendees + : attendees.filter((attendee) => { + const attendeeDate = new Date(attendee.createdAt); + const isSameYear = attendeeDate.getFullYear() === now.getFullYear(); + return filteringBy === 'This Month' + ? isSameYear && attendeeDate.getMonth() === now.getMonth() + : /*istanbul ignore next*/ + isSameYear; + }); + }; + + const filterAndSortAttendees = ( + attendees: InterfaceMember[], + ): InterfaceMember[] => { + return sortAttendees(filterAttendees(attendees)); + }; + const searchEventAttendees = (value: string): void => { + const searchValueLower = value.toLowerCase().trim(); + + const filtered = (memberData?.event?.attendees ?? []).filter( + (attendee: InterfaceMember) => { + const fullName = + `${attendee.firstName} ${attendee.lastName}`.toLowerCase(); + return ( + attendee.firstName?.toLowerCase().includes(searchValueLower) || + attendee.lastName?.toLowerCase().includes(searchValueLower) || + attendee.email?.toLowerCase().includes(searchValueLower) || + fullName.includes(searchValueLower) + ); + }, + ); + + const finalFiltered = filterAndSortAttendees(filtered); + setFilteredAttendees(finalFiltered); + }; + const showModal = (): void => setShow(true); + const handleClose = (): void => setShow(false); + + const statistics = useMemo(() => { + const totalMembers = filteredAttendees.length; + const membersAttended = filteredAttendees.filter( + (member) => member?.eventsAttended && member.eventsAttended.length > 0, + ).length; + const attendanceRate = + totalMembers > 0 + ? Number(((membersAttended / totalMembers) * 100).toFixed(2)) + : 0; + + return { totalMembers, membersAttended, attendanceRate }; + }, [filteredAttendees]); + + const [getEventAttendees, { data: memberData, loading, error }] = + useLazyQuery(EVENT_ATTENDEES, { + variables: { + id: eventId, + }, + fetchPolicy: 'cache-and-network', + nextFetchPolicy: 'cache-first', + errorPolicy: 'all', + notifyOnNetworkStatusChange: true, + }); + + useEffect(() => { + if (memberData?.event?.attendees) { + const updatedAttendees = filterAndSortAttendees( + memberData.event.attendees, + ); + setFilteredAttendees(updatedAttendees); + } + }, [sortOrder, filteringBy, memberData]); + + useEffect(() => { + getEventAttendees(); + }, [eventId, getEventAttendees]); + + if (loading) return

    {t('loading')}

    ; + /*istanbul ignore next*/ + if (error) return

    {error.message}

    ; + + return ( +
    + +
    +
    + +
    +
    +
    + searchEventAttendees(e.target.value)} + /> + +
    + + + Sort + Filter: {filteringBy} + + } + onSelect={(eventKey) => setFilteringBy(eventKey as FilterPeriod)} + > + This Month + This Year + All + + + Sort + Sort + + } + onSelect={ + /*istanbul ignore next*/ + (eventKey) => setSortOrder(eventKey as 'ascending' | 'descending') + } + > + Ascending + Descending + +
    +
    + {/*

    {totalMembers}

    */} + + + + + + # + + + {t('Member Name')} + + + {t('Status')} + + + {t('Events Attended')} + + + {t('Task Assigned')} + + + + + {filteredAttendees.length === 0 ? ( + + + {t('noAttendees')} + + + ) : ( + filteredAttendees.map( + (member: InterfaceMember, index: number) => ( + + + {index + 1} + + + + {member.firstName} {member.lastName} + + + + {member.__typename === 'User' ? t('Member') : t('Admin')} + + ( + + ), + )} + > + + + {member.eventsAttended + ? member.eventsAttended.length + : /*istanbul ignore next*/ + '0'} + + + + + {member.tagsAssignedWith ? ( + /*istanbul ignore next*/ + member.tagsAssignedWith.edges.map( + /*istanbul ignore next*/ + ( + edge: { node: { name: string } }, + tagIndex: number, + ) =>
    {edge.node.name}
    , + ) + ) : ( +
    None
    + )} +
    +
    + ), + ) + )} +
    +
    +
    +
    + ); +} + +export default EventAttendance; diff --git a/src/components/EventManagement/EventAttendance/EventStatistics.test.tsx b/src/components/EventManagement/EventAttendance/EventStatistics.test.tsx new file mode 100644 index 0000000000..03f4671a5e --- /dev/null +++ b/src/components/EventManagement/EventAttendance/EventStatistics.test.tsx @@ -0,0 +1,358 @@ +import React from 'react'; +import { act, render, screen, waitFor } from '@testing-library/react'; +import { AttendanceStatisticsModal } from './EventStatistics'; +import { MockedProvider } from '@apollo/client/testing'; +import { EVENT_DETAILS, RECURRING_EVENTS } from 'GraphQl/Queries/Queries'; +import userEvent from '@testing-library/user-event'; +import { exportToCSV } from 'utils/chartToPdf'; + +// Mock chart.js to avoid canvas errors +jest.mock('react-chartjs-2', () => ({ + Line: () => null, + Bar: () => null, +})); +// Mock react-router-dom +jest.mock('react-router-dom', () => ({ + useParams: () => ({ + orgId: 'org123', + eventId: 'event123', + }), +})); +jest.mock('utils/chartToPdf', () => ({ + exportToCSV: jest.fn(), +})); +const mocks = [ + { + request: { + query: EVENT_DETAILS, + variables: { id: 'event123' }, + }, + result: { + data: { + event: { + _id: 'event123', + title: 'Test Event', + description: 'Test Description', + startDate: '2023-01-01', + endDate: '2023-01-02', + startTime: '09:00', + endTime: '17:00', + allDay: false, + location: 'Test Location', + recurring: true, + baseRecurringEvent: { _id: 'base123' }, + organization: { + _id: 'org123', + members: [ + { _id: 'user1', firstName: 'John', lastName: 'Doe' }, + { _id: 'user2', firstName: 'Jane', lastName: 'Smith' }, + ], + }, + attendees: [ + { + _id: 'user1', + gender: 'MALE', + }, + { + _id: 'user2', + gender: 'FEMALE', + }, + ], + }, + }, + }, + }, + { + request: { + query: RECURRING_EVENTS, + variables: { baseRecurringEventId: 'base123' }, + }, + result: { + data: { + getRecurringEvents: [ + { + _id: 'event123', + startDate: '2023-01-01', + title: 'Test Event 1', + attendees: [ + { _id: 'user1', gender: 'MALE' }, + { _id: 'user2', gender: 'FEMALE' }, + ], + }, + { + _id: 'event456', + startDate: '2023-01-08', + title: 'Test Event 2', + attendees: [ + { _id: 'user1', gender: 'MALE' }, + { _id: 'user3', gender: 'OTHER' }, + ], + }, + { + _id: 'event789', + startDate: '2023-01-15', + title: 'Test Event 3', + attendees: [ + { _id: 'user2', gender: 'FEMALE' }, + { _id: 'user3', gender: 'OTHER' }, + ], + }, + ], + }, + }, + }, +]; + +const mockMemberData = [ + { + _id: 'user1', + firstName: 'John', + lastName: 'Doe', + gender: 'MALE', + birthDate: new Date('1990-01-01'), + email: 'john@example.com' as `${string}@${string}.${string}`, + createdAt: '2023-01-01', + __typename: 'User', + tagsAssignedWith: { + edges: [], + }, + }, + { + _id: 'user2', + firstName: 'Jane', + lastName: 'Smith', + gender: 'FEMALE', + birthDate: new Date('1985-05-05'), + email: 'jane@example.com' as `${string}@${string}.${string}`, + createdAt: '2023-01-01', + __typename: 'User', + tagsAssignedWith: { + edges: [], + }, + }, +]; + +const mockStatistics = { + totalMembers: 2, + membersAttended: 1, + attendanceRate: 50, +}; + +describe('AttendanceStatisticsModal', () => { + test('renders modal with correct initial state', async () => { + render( + + {}} + statistics={mockStatistics} + memberData={mockMemberData} + t={(key) => key} + /> + , + ); + + await waitFor(() => { + expect(screen.getByTestId('attendance-modal')).toBeInTheDocument(); + expect(screen.getByTestId('gender-button')).toBeInTheDocument(); + expect(screen.getByTestId('age-button')).toBeInTheDocument(); + }); + }); + + test('switches between gender and age demographics', async () => { + render( + + {}} + statistics={mockStatistics} + memberData={mockMemberData} + t={(key) => key} + /> + , + ); + + await waitFor(() => { + const genderButton = screen.getByTestId('gender-button'); + const ageButton = screen.getByTestId('age-button'); + + userEvent.click(ageButton); + expect(ageButton).toHaveClass('btn-success'); + expect(genderButton).toHaveClass('btn-light'); + + userEvent.click(genderButton); + expect(genderButton).toHaveClass('btn-success'); + expect(ageButton).toHaveClass('btn-light'); + }); + }); + + test('handles data demographics export functionality', async () => { + const mockExportToCSV = jest.fn(); + (exportToCSV as jest.Mock).mockImplementation(mockExportToCSV); + + render( + + {}} + statistics={mockStatistics} + memberData={mockMemberData} + t={(key) => key} + /> + , + ); + + await waitFor(() => { + expect( + screen.getByRole('button', { name: 'Export Data' }), + ).toBeInTheDocument(); + }); + + await act(async () => { + const exportButton = screen.getByRole('button', { name: 'Export Data' }); + await userEvent.click(exportButton); + }); + + await act(async () => { + const demographicsExport = screen.getByTestId('demographics-export'); + await userEvent.click(demographicsExport); + }); + + expect(mockExportToCSV).toHaveBeenCalled(); + }); + test('handles data trends export functionality', async () => { + const mockExportToCSV = jest.fn(); + (exportToCSV as jest.Mock).mockImplementation(mockExportToCSV); + + render( + + {}} + statistics={mockStatistics} + memberData={mockMemberData} + t={(key) => key} + /> + , + ); + + await waitFor(() => { + expect( + screen.getByRole('button', { name: 'Export Data' }), + ).toBeInTheDocument(); + }); + + await act(async () => { + const exportButton = screen.getByRole('button', { name: 'Export Data' }); + await userEvent.click(exportButton); + }); + + await act(async () => { + const demographicsExport = screen.getByTestId('trends-export'); + await userEvent.click(demographicsExport); + }); + + expect(mockExportToCSV).toHaveBeenCalled(); + }); + + test('displays recurring event data correctly', async () => { + render( + + {}} + statistics={mockStatistics} + memberData={mockMemberData} + t={(key) => key} + /> + , + ); + + await waitFor(() => { + expect(screen.getByTestId('today-button')).toBeInTheDocument(); + }); + }); + test('handles pagination and today button correctly', async () => { + render( + + {}} + statistics={mockStatistics} + memberData={mockMemberData} + t={(key) => key} + /> + , + ); + + // Wait for initial render + await waitFor(() => { + expect(screen.getByTestId('today-button')).toBeInTheDocument(); + }); + + // Test pagination + await act(async () => { + const nextButton = screen.getByAltText('right-arrow'); + await userEvent.click(nextButton); + }); + + await act(async () => { + const prevButton = screen.getByAltText('left-arrow'); + await userEvent.click(prevButton); + }); + + // Test today button + await act(async () => { + const todayButton = screen.getByTestId('today-button'); + await userEvent.click(todayButton); + }); + + // Verify buttons are present and interactive + expect(screen.getByAltText('right-arrow')).toBeInTheDocument(); + expect(screen.getByAltText('left-arrow')).toBeInTheDocument(); + expect(screen.getByTestId('today-button')).toBeInTheDocument(); + }); + + test('handles pagination in recurring events view', async () => { + render( + + {}} + statistics={mockStatistics} + memberData={mockMemberData} + t={(key) => key} + /> + , + ); + + await waitFor(() => { + const nextButton = screen.getByAltText('right-arrow'); + const prevButton = screen.getByAltText('left-arrow'); + + userEvent.click(nextButton); + userEvent.click(prevButton); + }); + }); + + test('closes modal correctly', async () => { + const handleClose = jest.fn(); + render( + + key} + /> + , + ); + + await waitFor(() => { + const closeButton = screen.getByTestId('close-button'); + userEvent.click(closeButton); + expect(handleClose).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/components/EventManagement/EventAttendance/EventStatistics.tsx b/src/components/EventManagement/EventAttendance/EventStatistics.tsx new file mode 100644 index 0000000000..5dda9e88a8 --- /dev/null +++ b/src/components/EventManagement/EventAttendance/EventStatistics.tsx @@ -0,0 +1,583 @@ +import React, { useEffect, useState, useMemo, useCallback } from 'react'; +import { + Modal, + Button, + ButtonGroup, + Tooltip, + OverlayTrigger, + Dropdown, +} from 'react-bootstrap'; +import 'react-datepicker/dist/react-datepicker.css'; +import { + Chart as ChartJS, + CategoryScale, + LinearScale, + PointElement, + LineElement, + BarElement, + Title, + Tooltip as ChartToolTip, + Legend, +} from 'chart.js'; +import { Bar, Line } from 'react-chartjs-2'; +import { useParams } from 'react-router-dom'; +import { EVENT_DETAILS, RECURRING_EVENTS } from 'GraphQl/Queries/Queries'; +import { useLazyQuery } from '@apollo/client'; +import { exportToCSV } from 'utils/chartToPdf'; +import type { ChartOptions, TooltipItem } from 'chart.js'; +import type { + InterfaceAttendanceStatisticsModalProps, + InterfaceEvent, + InterfaceRecurringEvent, +} from './InterfaceEvents'; +ChartJS.register( + CategoryScale, + LinearScale, + PointElement, + LineElement, + BarElement, + Title, + ChartToolTip, + Legend, +); +/** + * Component to display statistical information about event attendance + * Shows metrics like total attendees, filtering options, and attendance trends + * @returns JSX element with event statistics dashboard + */ + +export const AttendanceStatisticsModal: React.FC< + InterfaceAttendanceStatisticsModalProps +> = ({ show, handleClose, statistics, memberData, t }): JSX.Element => { + const [selectedCategory, setSelectedCategory] = useState('Gender'); + const { orgId, eventId } = useParams(); + const [currentPage, setCurrentPage] = useState(0); + const eventsPerPage = 10; + const [loadEventDetails, { data: eventData }] = useLazyQuery(EVENT_DETAILS); + const [loadRecurringEvents, { data: recurringData }] = + useLazyQuery(RECURRING_EVENTS); + const isEventRecurring = eventData?.event?.recurring; + const currentEventIndex = useMemo(() => { + if (!recurringData?.getRecurringEvents || !eventId) return -1; + return recurringData.getRecurringEvents.findIndex( + (event: InterfaceEvent) => event._id === eventId, + ); + }, [recurringData, eventId]); + useEffect(() => { + if (currentEventIndex >= 0) { + const newPage = Math.floor(currentEventIndex / eventsPerPage); + setCurrentPage(newPage); + } + }, [currentEventIndex, eventsPerPage]); + const filteredRecurringEvents = useMemo( + () => recurringData?.getRecurringEvents || [], + [recurringData], + ); + const totalEvents = filteredRecurringEvents.length; + const totalPages = Math.ceil(totalEvents / eventsPerPage); + + const paginatedRecurringEvents = useMemo(() => { + const startIndex = currentPage * eventsPerPage; + const endIndex = Math.min(startIndex + eventsPerPage, totalEvents); + return filteredRecurringEvents.slice(startIndex, endIndex); + }, [filteredRecurringEvents, currentPage, eventsPerPage, totalEvents]); + + const attendeeCounts = useMemo( + () => + paginatedRecurringEvents.map( + (event: InterfaceEvent) => event.attendees.length, + ), + [paginatedRecurringEvents], + ); + const chartOptions: ChartOptions<'line'> = { + responsive: true, + maintainAspectRatio: false, + animation: false, + scales: { y: { beginAtZero: true } }, + plugins: { + tooltip: { + callbacks: { + label: + /*istanbul ignore next*/ + (context: TooltipItem<'line'>) => { + const label = context.dataset.label || ''; + const value = context.parsed.y; + const isCurrentEvent = + paginatedRecurringEvents[context.dataIndex]._id === eventId; + return isCurrentEvent + ? `${label}: ${value} (Current Event)` + : `${label}: ${value}`; + }, + }, + }, + }, + }; + const eventLabels = useMemo( + () => + paginatedRecurringEvents.map((event: InterfaceEvent) => { + const date = (() => { + try { + const eventDate = new Date(event.startDate); + if (Number.isNaN(eventDate.getTime())) { + /*istanbul ignore next*/ + console.error(`Invalid date for event: ${event._id}`); + /*istanbul ignore next*/ + return 'Invalid date'; + } + return eventDate.toLocaleDateString('en-US', { + month: 'short', + day: 'numeric', + }); + } catch (error) { + /*istanbul ignore next*/ + console.error( + `Error formatting date for event: ${event._id}`, + error, + ); + /*istanbul ignore next*/ + return 'Invalid date'; + } + })(); + // Highlight the current event in the label + return event._id === eventId ? `→ ${date}` : date; + }), + [paginatedRecurringEvents, eventId], + ); + + const maleCounts = useMemo( + () => + paginatedRecurringEvents.map( + (event: InterfaceEvent) => + event.attendees.filter((attendee) => attendee.gender === 'MALE') + .length, + ), + [paginatedRecurringEvents], + ); + + const femaleCounts = useMemo( + () => + paginatedRecurringEvents.map( + (event: InterfaceEvent) => + event.attendees.filter((attendee) => attendee.gender === 'FEMALE') + .length, + ), + [paginatedRecurringEvents], + ); + + const otherCounts = useMemo( + () => + paginatedRecurringEvents.map( + (event: InterfaceEvent) => + event.attendees.filter( + (attendee) => + attendee.gender === 'OTHER' || attendee.gender === null, + ).length, + ), + [paginatedRecurringEvents], + ); + + const chartData = useMemo( + () => ({ + labels: eventLabels, + datasets: [ + { + label: 'Attendee Count', + data: attendeeCounts, + fill: true, + borderColor: '#008000', + pointRadius: paginatedRecurringEvents.map( + (event: InterfaceRecurringEvent) => (event._id === eventId ? 8 : 3), + ), + pointBackgroundColor: paginatedRecurringEvents.map( + (event: InterfaceRecurringEvent) => + event._id === eventId ? '#008000' : 'transparent', + ), + }, + { + label: 'Male Attendees', + data: maleCounts, + fill: false, + borderColor: '#0000FF', + }, + { + label: 'Female Attendees', + data: femaleCounts, + fill: false, + borderColor: '#FF1493', + }, + { + label: 'Other Attendees', + data: otherCounts, + fill: false, + borderColor: '#FFD700', + }, + ], + }), + [eventLabels, attendeeCounts, maleCounts, femaleCounts, otherCounts], + ); + + const handlePreviousPage = useCallback( + /*istanbul ignore next*/ + () => { + setCurrentPage((prevPage) => Math.max(prevPage - 1, 0)); + }, + [], + ); + + const handleNextPage = useCallback( + /*istanbul ignore next*/ + () => { + if (currentPage < totalPages - 1) { + setCurrentPage((prevPage) => prevPage + 1); + } + }, + [currentPage, totalPages], + ); + + const handleDateChange = useCallback((date: Date | null) => { + if (date) { + setCurrentPage(0); + } + }, []); + const categoryLabels = useMemo( + () => + selectedCategory === 'Gender' + ? ['Male', 'Female', 'Other'] + : ['Under 18', '18-40', 'Over 40'], + [selectedCategory], + ); + + const categoryData = useMemo( + () => + selectedCategory === 'Gender' + ? [ + memberData.filter((member) => member.gender === 'MALE').length, + memberData.filter((member) => member.gender === 'FEMALE').length, + memberData.filter( + (member) => + member.gender === 'OTHER' || + member.gender === null || + member.gender === '', + ).length, + ] + : [ + memberData.filter((member) => { + const today = new Date(); + const birthDate = new Date(member.birthDate); + let age = today.getFullYear() - birthDate.getFullYear(); + const monthDiff = today.getMonth() - birthDate.getMonth(); + if ( + monthDiff < 0 || + (monthDiff === 0 && today.getDate() < birthDate.getDate()) + ) { + /*istanbul ignore next*/ + age--; + } + return age < 18; + }).length, + memberData.filter((member) => { + const age = + new Date().getFullYear() - + new Date(member.birthDate).getFullYear(); + return age >= 18 && age <= 40; + }).length, + memberData.filter( + (member) => + new Date().getFullYear() - + new Date(member.birthDate).getFullYear() > + 40, + ).length, + ], + [selectedCategory, memberData], + ); + + const handleCategoryChange = useCallback((category: string): void => { + setSelectedCategory(category); + }, []); + + const exportTrendsToCSV = useCallback(() => { + const headers = [ + 'Date', + 'Attendee Count', + 'Male Attendees', + 'Female Attendees', + 'Other Attendees', + ]; + const data = [ + headers, + ...eventLabels.map((label: string, index: number) => [ + label, + attendeeCounts[index], + maleCounts[index], + femaleCounts[index], + otherCounts[index], + ]), + ]; + exportToCSV(data, 'attendance_trends.csv'); + }, [eventLabels, attendeeCounts, maleCounts, femaleCounts, otherCounts]); + + const exportDemographicsToCSV = useCallback(() => { + const headers = [selectedCategory, 'Count']; + const data = [ + headers, + ...categoryLabels.map((label, index) => [label, categoryData[index]]), + ]; + exportToCSV(data, `${selectedCategory.toLowerCase()}_demographics.csv`); + }, [selectedCategory, categoryLabels, categoryData]); + + /*istanbul ignore next*/ + const handleExport = (eventKey: string | null): void => { + switch (eventKey) { + case 'trends': + try { + exportTrendsToCSV(); + } catch (error) { + console.error('Failed to export trends:', error); + } + break; + case 'demographics': + try { + exportDemographicsToCSV(); + } catch (error) { + console.error('Failed to export demographics:', error); + } + break; + default: + return; + } + }; + useEffect(() => { + if (eventId) { + loadEventDetails({ variables: { id: eventId } }); + } + }, [eventId, loadEventDetails]); + useEffect(() => { + if (eventId && orgId && eventData?.event?.baseRecurringEvent?._id) { + loadRecurringEvents({ + variables: { + baseRecurringEventId: eventData?.event?.baseRecurringEvent?._id, + }, + }); + } + }, [eventId, orgId, eventData, loadRecurringEvents]); + return ( + + + + {t('historical_statistics')} + + + +
    +
    + {isEventRecurring ? ( +
    + +
    +

    Trends

    +
    +
    + Previous Page} + > + + + + Next Page} + > + + +
    +
    + ) : ( +
    +

    + {statistics.totalMembers} +

    +
    +

    Attendance Count

    +
    +
    + )} +
    + + + + + +
    +

    Demography

    +
    +
    +
    +
    + + + + Export Data + + + {isEventRecurring && ( + + Trends + + )} + + Demographics + + + + + +
    + ); +}; diff --git a/src/components/EventManagement/EventAttendance/EventsAttendance.module.css b/src/components/EventManagement/EventAttendance/EventsAttendance.module.css new file mode 100644 index 0000000000..2ee236a4da --- /dev/null +++ b/src/components/EventManagement/EventAttendance/EventsAttendance.module.css @@ -0,0 +1,35 @@ +.input { + display: flex; + width: 100%; + position: relative; +} +.customcell { + background-color: #31bb6b !important; + color: white !important; + font-size: medium !important; + font-weight: 500 !important; + padding-top: 10px !important; + padding-bottom: 10px !important; +} + +.eventsAttended, +.membername { + color: blue; +} +.actionBtn { + /* color:#39a440 !important; */ + background-color: #ffffff !important; +} +.actionBtn:hover, +.actionBtn:focus, +.actionBtn:active { + color: #39a440 !important; +} + +.table-body > .table-row { + background-color: #fff !important; +} + +.table-body > .table-row:nth-child(2n) { + background: #afffe8 !important; +} diff --git a/src/components/EventManagement/EventAttendance/InterfaceEvents.ts b/src/components/EventManagement/EventAttendance/InterfaceEvents.ts new file mode 100644 index 0000000000..7fc75ae4af --- /dev/null +++ b/src/components/EventManagement/EventAttendance/InterfaceEvents.ts @@ -0,0 +1,82 @@ +export interface InterfaceAttendanceStatisticsModalProps { + show: boolean; + handleClose: () => void; + statistics: { + totalMembers: number; + membersAttended: number; + attendanceRate: number; + }; + memberData: InterfaceMember[]; + t: (key: string) => string; +} + +export interface InterfaceMember { + createdAt: string; + firstName: string; + lastName: string; + email: `${string}@${string}.${string}`; + gender: string; + eventsAttended?: { + _id: string; + }[]; + birthDate: Date; + __typename: string; + _id: string; + tagsAssignedWith: { + edges: { + cursor: string; + node: { + name: string; + }; + }[]; + }; +} + +export interface InterfaceEvent { + _id: string; + title: string; + description: string; + startDate: string; + endDate: string; + location: string; + startTime: string; + endTime: string; + allDay: boolean; + recurring: boolean; + recurrenceRule: { + recurrenceStartDate: string; + recurrenceEndDate?: string | null; + frequency: string; + weekDays: string[]; + interval: number; + count?: number; + weekDayOccurenceInMonth?: number; + }; + isRecurringEventException: boolean; + isPublic: boolean; + isRegisterable: boolean; + attendees: { + _id: string; + firstName: string; + lastName: string; + email: string; + gender: string; + birthDate: string; + }[]; + __typename: string; +} + +export interface InterfaceRecurringEvent { + _id: string; + title: string; + startDate: string; + endDate: string; + frequency: InterfaceEvent['recurrenceRule']['frequency']; + interval: InterfaceEvent['recurrenceRule']['interval']; + attendees: { + _id: string; + gender: 'MALE' | 'FEMALE' | 'OTHER' | 'PREFER_NOT_TO_SAY'; + }[]; + isPublic: boolean; + isRegisterable: boolean; +} diff --git a/src/components/EventRegistrantsModal/AddOnSpotAttendee.test.tsx b/src/components/EventRegistrantsModal/AddOnSpotAttendee.test.tsx new file mode 100644 index 0000000000..c0dc20d200 --- /dev/null +++ b/src/components/EventRegistrantsModal/AddOnSpotAttendee.test.tsx @@ -0,0 +1,177 @@ +import React from 'react'; +import { render, fireEvent, screen, waitFor } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { BrowserRouter } from 'react-router-dom'; +import { SIGNUP_MUTATION } from 'GraphQl/Mutations/mutations'; +import AddOnSpotAttendee from './AddOnSpotAttendee'; +import userEvent from '@testing-library/user-event'; +import type { RenderResult } from '@testing-library/react'; +import { toast } from 'react-toastify'; +import { Provider } from 'react-redux'; +import { I18nextProvider } from 'react-i18next'; +import { store } from 'state/store'; +import i18nForTest from '../../utils/i18nForTest'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +const mockProps = { + show: true, + handleClose: jest.fn(), + reloadMembers: jest.fn(), +}; +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ eventId: '123', orgId: '123' }), +})); + +const MOCKS = [ + { + request: { + query: SIGNUP_MUTATION, + variables: { + firstName: 'John', + lastName: 'Doe', + email: 'john@example.com', + phoneNo: '1234567890', + gender: 'Male', + password: '123456', + orgId: '123', + }, + }, + result: { + data: { + signUp: { + user: { + _id: '1', + }, + accessToken: 'mock-access-token', + refreshToken: 'mock-refresh-token', + }, + }, + }, + }, +]; + +const ERROR_MOCKS = [ + { + ...MOCKS[0], + error: new Error('Failed to add attendee'), + }, +]; + +const renderAddOnSpotAttendee = (): RenderResult => { + return render( + + + + + + + + + , + ); +}; + +describe('AddOnSpotAttendee Component', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('renders the component with all form fields', async () => { + renderAddOnSpotAttendee(); + + expect(screen.getByText('On-spot Attendee')).toBeInTheDocument(); + expect(screen.getByLabelText('First Name')).toBeInTheDocument(); + expect(screen.getByLabelText('Last Name')).toBeInTheDocument(); + expect(screen.getByLabelText('Email')).toBeInTheDocument(); + expect(screen.getByLabelText('Phone No.')).toBeInTheDocument(); + expect(screen.getByLabelText('Gender')).toBeInTheDocument(); + }); + + it('handles form input changes correctly', async () => { + renderAddOnSpotAttendee(); + + const firstNameInput = screen.getByLabelText('First Name'); + const lastNameInput = screen.getByLabelText('Last Name'); + const emailInput = screen.getByLabelText('Email'); + + userEvent.type(firstNameInput, 'John'); + userEvent.type(lastNameInput, 'Doe'); + userEvent.type(emailInput, 'john@example.com'); + + expect(firstNameInput).toHaveValue('John'); + expect(lastNameInput).toHaveValue('Doe'); + expect(emailInput).toHaveValue('john@example.com'); + }); + + it('submits form successfully and calls necessary callbacks', async () => { + renderAddOnSpotAttendee(); + + userEvent.type(screen.getByLabelText('First Name'), 'John'); + userEvent.type(screen.getByLabelText('Last Name'), 'Doe'); + userEvent.type(screen.getByLabelText('Email'), 'john@example.com'); + userEvent.type(screen.getByLabelText('Phone No.'), '1234567890'); + const genderSelect = screen.getByLabelText('Gender'); + fireEvent.change(genderSelect, { target: { value: 'Male' } }); + + fireEvent.submit(screen.getByTestId('onspot-attendee-form')); + await waitFor(() => { + expect(toast.success).toHaveBeenCalled(); + expect(mockProps.reloadMembers).toHaveBeenCalled(); + expect(mockProps.handleClose).toHaveBeenCalled(); + }); + }); + + it('displays error when organization ID is missing', async () => { + render( + + + + + , + ); + + fireEvent.submit(screen.getByTestId('onspot-attendee-form')); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); + it('displays error when required fields are missing', async () => { + renderAddOnSpotAttendee(); + + fireEvent.submit(screen.getByTestId('onspot-attendee-form')); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); + + it('handles mutation error appropriately', async () => { + render( + + + + + + + + + , + ); + + userEvent.type(screen.getByLabelText('First Name'), 'John'); + userEvent.type(screen.getByLabelText('Last Name'), 'Doe'); + fireEvent.submit(screen.getByTestId('onspot-attendee-form')); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/components/EventRegistrantsModal/AddOnSpotAttendee.tsx b/src/components/EventRegistrantsModal/AddOnSpotAttendee.tsx new file mode 100644 index 0000000000..6de839ce04 --- /dev/null +++ b/src/components/EventRegistrantsModal/AddOnSpotAttendee.tsx @@ -0,0 +1,209 @@ +import { SIGNUP_MUTATION } from 'GraphQl/Mutations/mutations'; +import React, { useState } from 'react'; +import { Modal, Form, Button, Spinner } from 'react-bootstrap'; +import { useParams } from 'react-router-dom'; +import { useMutation } from '@apollo/client'; +import { toast } from 'react-toastify'; +import 'react-toastify/dist/ReactToastify.css'; +import type { + InterfaceAddOnSpotAttendeeProps, + InterfaceFormData, +} from 'utils/interfaces'; +import { useTranslation } from 'react-i18next'; +import { errorHandler } from 'utils/errorHandler'; +/** + * Modal component for adding on-spot attendees to an event + * @param show - Boolean to control modal visibility + * @param handleClose - Function to handle modal close + * @param reloadMembers - Function to refresh member list after adding attendee + * @returns Modal component with form for adding new attendee + */ +const AddOnSpotAttendee: React.FC = ({ + show, + handleClose, + reloadMembers, +}) => { + const [formData, setFormData] = useState({ + firstName: '', + lastName: '', + email: '', + phoneNo: '', + gender: '', + }); + const { t } = useTranslation('translation', { keyPrefix: 'onSpotAttendee' }); + const { t: tCommon } = useTranslation('common'); + const { orgId } = useParams<{ orgId: string }>(); + const [isSubmitting, setIsSubmitting] = useState(false); + const [addSignUp] = useMutation(SIGNUP_MUTATION); + const validateForm = (): boolean => { + if (!formData.firstName || !formData.lastName || !formData.email) { + toast.error(t('invalidDetailsMessage')); + return false; + } + return true; + }; + + const resetForm = (): void => { + setFormData({ + firstName: '', + lastName: '', + email: '', + phoneNo: '', + gender: '', + }); + }; + + const handleChange = ( + e: React.ChangeEvent< + HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement + >, + ): void => { + const target = e.target as + | HTMLInputElement + | HTMLSelectElement + | HTMLTextAreaElement; + setFormData((prev) => ({ + ...prev, + [target.name]: target.value, + })); + }; + + const handleSubmit = async ( + e: React.FormEvent, + ): Promise => { + e.preventDefault(); + + if (!validateForm()) { + return; + } + + setIsSubmitting(true); + + try { + const response = await addSignUp({ + variables: { + ...formData, + password: '123456', + orgId, + }, + }); + + if (response.data?.signUp) { + toast.success(t('attendeeAddedSuccess')); + resetForm(); + reloadMembers(); + handleClose(); + } + } catch (error) { + /* istanbul ignore next */ + errorHandler(t, error as Error); + } finally { + setIsSubmitting(false); + } + }; + return ( + <> + + + {t('title')} + + +
    +
    + + + {tCommon('firstName')} + + + + + + {tCommon('lastName')} + + + +
    + + {t('phoneNumber')} + + + + + {tCommon('email')} + + + + + {tCommon('gender')} + + + + + + + +
    + +
    +
    +
    + + ); +}; + +export default AddOnSpotAttendee; diff --git a/src/components/EventRegistrantsModal/EventRegistrantsModal.test.tsx b/src/components/EventRegistrantsModal/EventRegistrantsModal.test.tsx index 8a084fef24..8ca76393cd 100644 --- a/src/components/EventRegistrantsModal/EventRegistrantsModal.test.tsx +++ b/src/components/EventRegistrantsModal/EventRegistrantsModal.test.tsx @@ -41,7 +41,19 @@ const queryMockWithRegistrant = [ result: { data: { event: { - attendees: [{ _id: 'user1', firstName: 'John', lastName: 'Doe' }], + attendees: [ + { + _id: 'user1', + firstName: 'John', + lastName: 'Doe', + createdAt: '2023-01-01', + gender: 'Male', + birthDate: '1990-01-01', + eventsAttended: { + _id: 'event123', + }, + }, + ], }, }, }, @@ -64,9 +76,9 @@ const queryMockOrgMembers = [ _id: 'user1', firstName: 'John', lastName: 'Doe', - email: 'johndoe@palisadoes.com', - image: '', - createdAt: '12/12/22', + image: null, + email: 'johndoe@example.com', + createdAt: '2023-01-01', organizationsBlockedBy: [], }, ], @@ -76,6 +88,24 @@ const queryMockOrgMembers = [ }, }, ]; +const queryMockWithoutOrgMembers = [ + { + request: { + query: MEMBERS_LIST, + variables: { id: 'org123' }, + }, + result: { + data: { + organizations: [ + { + _id: 'org123', + members: [], + }, + ], + }, + }, + }, +]; const successfulAddRegistrantMock = [ { @@ -287,7 +317,7 @@ describe('Testing Event Registrants Modal', () => { }); test('Delete attendee mutation must fail properly', async () => { - const { queryByText, queryByTestId } = render( + const { queryByText, getByTestId } = render( { await waitFor(() => expect(queryByText('John Doe')).toBeInTheDocument()); - fireEvent.click(queryByTestId('CancelIcon') as Element); + const deleteButton = getByTestId('CancelIcon'); + fireEvent.click(deleteButton); await waitFor(() => expect(queryByText('Removing the attendee...')).toBeInTheDocument(), @@ -325,4 +356,48 @@ describe('Testing Event Registrants Modal', () => { expect(queryByText('Error removing attendee')).toBeInTheDocument(), ); }); + test('Autocomplete functionality works correctly', async () => { + const { getByTitle, getByText, getByPlaceholderText } = render( + + + + + + + + + + + + , + ); + + // Wait for loading state to finish + await waitFor(() => { + const autocomplete = getByPlaceholderText( + 'Choose the user that you want to add', + ); + expect(autocomplete).toBeInTheDocument(); + }); + + // Test empty state with no options + const autocomplete = getByPlaceholderText( + 'Choose the user that you want to add', + ); + fireEvent.change(autocomplete, { target: { value: 'NonexistentUser' } }); + + await waitFor(() => { + expect(getByText('No Registrations found')).toBeInTheDocument(); + expect(getByText('Add Onspot Registration')).toBeInTheDocument(); + }); + + // Test clicking "Add Onspot Registration" + fireEvent.click(getByText('Add Onspot Registration')); + expect(getByText('Add Onspot Registration')).toBeInTheDocument(); + const closeButton = getByTitle('Close'); + fireEvent.click(closeButton); + }); }); diff --git a/src/components/EventRegistrantsModal/EventRegistrantsModal.tsx b/src/components/EventRegistrantsModal/EventRegistrantsModal.tsx index bd2adc8a2c..d48d3b7439 100644 --- a/src/components/EventRegistrantsModal/EventRegistrantsModal.tsx +++ b/src/components/EventRegistrantsModal/EventRegistrantsModal.tsx @@ -14,6 +14,7 @@ import Stack from '@mui/material/Stack'; import TextField from '@mui/material/TextField'; import Autocomplete from '@mui/material/Autocomplete'; import { useTranslation } from 'react-i18next'; +import AddOnSpotAttendee from './AddOnSpotAttendee'; // Props for the EventRegistrantsModal component type ModalPropType = { @@ -43,6 +44,7 @@ interface InterfaceUser { export const EventRegistrantsModal = (props: ModalPropType): JSX.Element => { const { eventId, orgId, handleClose, show } = props; const [member, setMember] = useState(null); + const [open, setOpen] = useState(false); // Hooks for mutation operations const [addRegistrantMutation] = useMutation(ADD_EVENT_ATTENDEE); @@ -125,6 +127,19 @@ export const EventRegistrantsModal = (props: ModalPropType): JSX.Element => { return ( <> + setOpen(false) + } + reloadMembers={ + /*istanbul ignore next */ + () => { + attendeesRefetch(); + } + } + /> Event Registrants @@ -153,6 +168,19 @@ export const EventRegistrantsModal = (props: ModalPropType): JSX.Element => { onChange={(_, newMember): void => { setMember(newMember); }} + noOptionsText={ +
    +

    No Registrations found

    + { + setOpen(true); + }} + > + Add Onspot Registration + +
    + } options={memberData.organizations[0].members} getOptionLabel={(member: InterfaceUser): string => `${member.firstName} ${member.lastName}` @@ -160,6 +188,7 @@ export const EventRegistrantsModal = (props: ModalPropType): JSX.Element => { renderInput={(params): React.ReactNode => ( diff --git a/src/components/IconComponent/IconComponent.test.tsx b/src/components/IconComponent/IconComponent.test.tsx index 686a8e6f75..3ba6ccd84d 100644 --- a/src/components/IconComponent/IconComponent.test.tsx +++ b/src/components/IconComponent/IconComponent.test.tsx @@ -83,6 +83,10 @@ const screenTestIdMap: Record> = { name: 'My Pledges', testId: 'Icon-Component-My-Pledges', }, + Volunteer: { + name: 'Volunteer', + testId: 'Icon-Component-Volunteer', + }, default: { name: 'default', testId: 'Icon-Component-DefaultIcon', diff --git a/src/components/IconComponent/IconComponent.tsx b/src/components/IconComponent/IconComponent.tsx index 4708dc7966..8430aca131 100644 --- a/src/components/IconComponent/IconComponent.tsx +++ b/src/components/IconComponent/IconComponent.tsx @@ -19,6 +19,7 @@ import PostsIcon from 'assets/svgs/posts.svg?react'; import SettingsIcon from 'assets/svgs/settings.svg?react'; import VenueIcon from 'assets/svgs/venues.svg?react'; import RequestsIcon from 'assets/svgs/requests.svg?react'; +import { MdOutlineVolunteerActivism } from 'react-icons/md'; import React from 'react'; @@ -133,6 +134,15 @@ const iconComponent = (props: InterfaceIconComponent): JSX.Element => { stroke={props.fill} /> ); + case 'Volunteer': + return ( + + ); default: return ( { + test('Component should be rendered properly', () => { + render(); + + expect(screen.getByTestId('infiniteScrollLoader')).toBeInTheDocument(); + expect( + screen.getByTestId('infiniteScrollLoaderSpinner'), + ).toBeInTheDocument(); + }); +}); diff --git a/src/components/InfiniteScrollLoader/InfiniteScrollLoader.tsx b/src/components/InfiniteScrollLoader/InfiniteScrollLoader.tsx new file mode 100644 index 0000000000..7846889cdb --- /dev/null +++ b/src/components/InfiniteScrollLoader/InfiniteScrollLoader.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import styles from './InfiniteScrollLoader.module.css'; + +/** + * A Loader for infinite scroll. + */ + +const InfiniteScrollLoader = (): JSX.Element => { + return ( +
    +
    +
    + ); +}; + +export default InfiniteScrollLoader; diff --git a/src/components/LeftDrawer/LeftDrawer.module.css b/src/components/LeftDrawer/LeftDrawer.module.css index a9d330339f..86948b9930 100644 --- a/src/components/LeftDrawer/LeftDrawer.module.css +++ b/src/components/LeftDrawer/LeftDrawer.module.css @@ -7,7 +7,7 @@ display: flex; flex-direction: column; padding: 1rem 1rem 0 1rem; - background-color: var(--bs-white); + background-color: #f6f8fc; transition: 0.5s; font-family: var(--bs-leftDrawer-font-family); } diff --git a/src/components/LeftDrawerOrg/LeftDrawerOrg.module.css b/src/components/LeftDrawerOrg/LeftDrawerOrg.module.css index e792ef34bb..6296b1aa73 100644 --- a/src/components/LeftDrawerOrg/LeftDrawerOrg.module.css +++ b/src/components/LeftDrawerOrg/LeftDrawerOrg.module.css @@ -8,7 +8,7 @@ display: flex; flex-direction: column; padding: 0.8rem 0rem 0 1rem; - background-color: var(--bs-white); + background-color: #f6f8fc; transition: 0.5s; font-family: var(--bs-leftDrawer-font-family); } @@ -105,7 +105,7 @@ } .leftDrawer .organizationContainer .profileContainer { - background-color: #31bb6b33; + background-color: #e0e9ff; padding-right: 10px; } @@ -155,7 +155,7 @@ .leftDrawer .profileContainer .profileText .secondaryText { font-size: 0.8rem; font-weight: 400; - color: var(--bs-secondary); + /* color: var(--bs-secondary); */ display: block; text-transform: capitalize; } diff --git a/src/components/LeftDrawerOrg/LeftDrawerOrg.test.tsx b/src/components/LeftDrawerOrg/LeftDrawerOrg.test.tsx index 2a0ef3815d..71f3593499 100644 --- a/src/components/LeftDrawerOrg/LeftDrawerOrg.test.tsx +++ b/src/components/LeftDrawerOrg/LeftDrawerOrg.test.tsx @@ -3,7 +3,7 @@ import { fireEvent, render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import 'jest-localstorage-mock'; import { I18nextProvider } from 'react-i18next'; -import { BrowserRouter } from 'react-router-dom'; +import { BrowserRouter, MemoryRouter } from 'react-router-dom'; import i18nForTest from 'utils/i18nForTest'; import type { InterfaceLeftDrawerProps } from './LeftDrawerOrg'; @@ -21,6 +21,10 @@ const { setItem } = useLocalStorage(); const props: InterfaceLeftDrawerProps = { orgId: '123', targets: [ + { + name: 'Admin Profile', + url: '/member/123', + }, { name: 'Dashboard', url: '/orgdash/123', @@ -215,6 +219,20 @@ const MOCKS_EMPTY = [ }, ]; +const MOCKS_EMPTY_ORGID = [ + { + request: { + query: ORGANIZATIONS_LIST, + variables: { id: '' }, + }, + result: { + data: { + organizations: [], + }, + }, + }, +]; + const defaultScreens = [ 'Dashboard', 'People', @@ -264,6 +282,7 @@ afterEach(() => { const link = new StaticMockLink(MOCKS, true); const linkImage = new StaticMockLink(MOCKS_WITH_IMAGE, true); const linkEmpty = new StaticMockLink(MOCKS_EMPTY, true); +const linkEmptyOrgId = new StaticMockLink(MOCKS_EMPTY_ORGID, true); describe('Testing LeftDrawerOrg component for SUPERADMIN', () => { test('Component should be rendered properly', async () => { @@ -308,6 +327,29 @@ describe('Testing LeftDrawerOrg component for SUPERADMIN', () => { expect(screen.getByTestId(/orgBtn/i)).toBeInTheDocument(); }); + test('Should not show org not found error when viewing admin profile', async () => { + setItem('UserImage', ''); + setItem('SuperAdmin', true); + setItem('FirstName', 'John'); + setItem('LastName', 'Doe'); + setItem('id', '123'); + render( + + + + + + + + + , + ); + await wait(); + expect( + screen.queryByText(/Error occured while loading Organization data/i), + ).not.toBeInTheDocument(); + }); + test('Testing Menu Buttons', async () => { setItem('UserImage', ''); setItem('SuperAdmin', true); diff --git a/src/components/LeftDrawerOrg/LeftDrawerOrg.tsx b/src/components/LeftDrawerOrg/LeftDrawerOrg.tsx index 3a3ba378cf..a687351c98 100644 --- a/src/components/LeftDrawerOrg/LeftDrawerOrg.tsx +++ b/src/components/LeftDrawerOrg/LeftDrawerOrg.tsx @@ -3,16 +3,17 @@ import { WarningAmberOutlined } from '@mui/icons-material'; import { ORGANIZATIONS_LIST } from 'GraphQl/Queries/Queries'; import CollapsibleDropdown from 'components/CollapsibleDropdown/CollapsibleDropdown'; import IconComponent from 'components/IconComponent/IconComponent'; -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useMemo, useState } from 'react'; import Button from 'react-bootstrap/Button'; import { useTranslation } from 'react-i18next'; -import { NavLink } from 'react-router-dom'; +import { NavLink, useLocation } from 'react-router-dom'; import type { TargetsType } from 'state/reducers/routesReducer'; import type { InterfaceQueryOrganizationsListObject } from 'utils/interfaces'; import AngleRightIcon from 'assets/svgs/angleRight.svg?react'; import TalawaLogo from 'assets/svgs/talawa.svg?react'; import styles from './LeftDrawerOrg.module.css'; import Avatar from 'components/Avatar/Avatar'; +import useLocalStorage from 'utils/useLocalstorage'; export interface InterfaceLeftDrawerProps { orgId: string; @@ -38,10 +39,20 @@ const leftDrawerOrg = ({ }: InterfaceLeftDrawerProps): JSX.Element => { const { t: tCommon } = useTranslation('common'); const { t: tErrors } = useTranslation('errors'); + const location = useLocation(); + const { getItem } = useLocalStorage(); + const userId = getItem('id'); + const getIdFromPath = (pathname: string): string => { + if (!pathname) return ''; + const segments = pathname.split('/'); + // Index 2 (third segment) represents the ID in paths like /member/{userId} + return segments.length > 2 ? segments[2] : ''; + }; + const [isProfilePage, setIsProfilePage] = useState(false); const [showDropdown, setShowDropdown] = useState(false); - - const [organization, setOrganization] = - useState(); + const [organization, setOrganization] = useState< + InterfaceQueryOrganizationsListObject | undefined + >(undefined); const { data, loading, @@ -54,11 +65,24 @@ const leftDrawerOrg = ({ variables: { id: orgId }, }); + // Get the ID from the current path + const pathId = useMemo( + () => getIdFromPath(location.pathname), + [location.pathname], + ); + // Check if the current page is admin profile page + useEffect(() => { + // if param id is equal to userId, then it is a profile page + setIsProfilePage(pathId === userId); + }, [location, userId]); + // Set organization data when query data is available useEffect(() => { let isMounted = true; if (data && isMounted) { setOrganization(data?.organizations[0]); + } else { + setOrganization(undefined); } return () => { isMounted = false; @@ -104,7 +128,7 @@ const leftDrawerOrg = ({ /> ) : organization == undefined ? ( - <> + !isProfilePage && ( - + ) ) : ( {t('removeMemberMsg')} {/* Button to cancel the removal action */} - {/* Button to confirm the removal action */}
    + )) + )} +
    + +
    + + setTagSearchName(e.target.value.trim())} + data-testid="searchByName" + autoComplete="off" + /> +
    + +
    + {t('allTags')} +
    + {orgUserTagsLoading ? ( +
    + +
    + ) : ( + <> +
    + } + scrollableTarget="scrollableDiv" + > + {userTagsList?.map((tag) => ( +
    +
    + +
    + + {/* Ancestor tags breadcrumbs positioned at the end of TagNode */} + {tag.parentTag && ( +
    + <>{'('} + {tag.ancestorTags?.map((ancestorTag) => ( + + {ancestorTag.name} + + + ))} + <>{')'} +
    + )} +
    + ))} +
    +
    + + )} + + + + + + + + + + ); +}; + +export default TagActions; diff --git a/src/components/TagActions/TagActionsMocks.ts b/src/components/TagActions/TagActionsMocks.ts new file mode 100644 index 0000000000..f22458fa53 --- /dev/null +++ b/src/components/TagActions/TagActionsMocks.ts @@ -0,0 +1,706 @@ +import { + ASSIGN_TO_TAGS, + REMOVE_FROM_TAGS, +} from 'GraphQl/Mutations/TagMutations'; +import { ORGANIZATION_USER_TAGS_LIST } from 'GraphQl/Queries/OrganizationQueries'; +import { USER_TAG_SUB_TAGS } from 'GraphQl/Queries/userTagQueries'; +import { TAGS_QUERY_DATA_CHUNK_SIZE } from 'utils/organizationTagsUtils'; + +export const MOCKS = [ + { + request: { + query: ORGANIZATION_USER_TAGS_LIST, + variables: { + id: '123', + first: TAGS_QUERY_DATA_CHUNK_SIZE, + where: { name: { starts_with: '' } }, + }, + }, + result: { + data: { + organizations: [ + { + userTags: { + edges: [ + { + node: { + _id: '1', + name: 'userTag 1', + parentTag: null, + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 11, + }, + ancestorTags: [], + }, + cursor: '1', + }, + { + node: { + _id: '2', + name: 'userTag 2', + parentTag: null, + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 0, + }, + ancestorTags: [], + }, + cursor: '2', + }, + { + node: { + _id: '3', + name: 'userTag 3', + parentTag: null, + usersAssignedTo: { + totalCount: 0, + }, + childTags: { + totalCount: 5, + }, + ancestorTags: [], + }, + cursor: '3', + }, + { + node: { + _id: '4', + name: 'userTag 4', + parentTag: null, + usersAssignedTo: { + totalCount: 0, + }, + childTags: { + totalCount: 0, + }, + ancestorTags: [], + }, + cursor: '4', + }, + { + node: { + _id: '5', + name: 'userTag 5', + parentTag: null, + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 5, + }, + ancestorTags: [], + }, + cursor: '5', + }, + { + node: { + _id: '6', + name: 'userTag 6', + parentTag: null, + usersAssignedTo: { + totalCount: 6, + }, + childTags: { + totalCount: 6, + }, + ancestorTags: [], + }, + cursor: '6', + }, + { + node: { + _id: '7', + name: 'userTag 7', + parentTag: null, + usersAssignedTo: { + totalCount: 7, + }, + childTags: { + totalCount: 7, + }, + ancestorTags: [], + }, + cursor: '7', + }, + { + node: { + _id: '8', + name: 'userTag 8', + parentTag: null, + usersAssignedTo: { + totalCount: 8, + }, + childTags: { + totalCount: 8, + }, + ancestorTags: [], + }, + cursor: '8', + }, + { + node: { + _id: '9', + name: 'userTag 9', + parentTag: null, + usersAssignedTo: { + totalCount: 9, + }, + childTags: { + totalCount: 9, + }, + ancestorTags: [], + }, + cursor: '9', + }, + { + node: { + _id: '10', + name: 'userTag 10', + parentTag: null, + usersAssignedTo: { + totalCount: 10, + }, + childTags: { + totalCount: 10, + }, + ancestorTags: [], + }, + cursor: '10', + }, + ], + pageInfo: { + startCursor: '1', + endCursor: '10', + hasNextPage: true, + hasPreviousPage: false, + }, + totalCount: 12, + }, + }, + ], + }, + }, + }, + { + request: { + query: ORGANIZATION_USER_TAGS_LIST, + variables: { + id: '123', + first: TAGS_QUERY_DATA_CHUNK_SIZE, + after: '10', + where: { name: { starts_with: '' } }, + }, + }, + result: { + data: { + organizations: [ + { + userTags: { + edges: [ + { + node: { + _id: '11', + name: 'userTag 11', + parentTag: null, + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 5, + }, + ancestorTags: [], + }, + cursor: '11', + }, + { + node: { + _id: '12', + name: 'userTag 12', + parentTag: null, + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 0, + }, + ancestorTags: [], + }, + cursor: '12', + }, + ], + pageInfo: { + startCursor: '11', + endCursor: '12', + hasNextPage: false, + hasPreviousPage: true, + }, + totalCount: 12, + }, + }, + ], + }, + }, + }, + { + request: { + query: ORGANIZATION_USER_TAGS_LIST, + variables: { + id: '123', + first: TAGS_QUERY_DATA_CHUNK_SIZE, + where: { name: { starts_with: 'searchUserTag' } }, + }, + }, + result: { + data: { + organizations: [ + { + userTags: { + edges: [ + { + node: { + _id: '1', + name: 'searchUserTag 1', + parentTag: { + _id: '1', + }, + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 5, + }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], + }, + cursor: '1', + }, + { + node: { + _id: '2', + name: 'searchUserTag 2', + parentTag: { + _id: '1', + }, + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 0, + }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], + }, + cursor: '2', + }, + ], + pageInfo: { + startCursor: '1', + endCursor: '2', + hasNextPage: false, + hasPreviousPage: false, + }, + totalCount: 2, + }, + }, + ], + }, + }, + }, + { + request: { + query: USER_TAG_SUB_TAGS, + variables: { + id: '1', + first: TAGS_QUERY_DATA_CHUNK_SIZE, + }, + }, + result: { + data: { + getChildTags: { + name: 'userTag 1', + childTags: { + edges: [ + { + node: { + _id: 'subTag1', + name: 'subTag 1', + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 5, + }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], + }, + cursor: 'subTag1', + }, + { + node: { + _id: 'subTag2', + name: 'subTag 2', + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 0, + }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], + }, + cursor: 'subTag2', + }, + { + node: { + _id: 'subTag3', + name: 'subTag 3', + usersAssignedTo: { + totalCount: 0, + }, + childTags: { + totalCount: 5, + }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], + }, + cursor: 'subTag3', + }, + { + node: { + _id: 'subTag4', + name: 'subTag 4', + usersAssignedTo: { + totalCount: 0, + }, + childTags: { + totalCount: 0, + }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], + }, + cursor: 'subTag4', + }, + { + node: { + _id: 'subTag5', + name: 'subTag 5', + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 5, + }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], + }, + cursor: 'subTag5', + }, + { + node: { + _id: 'subTag6', + name: 'subTag 6', + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 5, + }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], + }, + cursor: 'subTag6', + }, + { + node: { + _id: 'subTag7', + name: 'subTag 7', + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 5, + }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], + }, + cursor: 'subTag7', + }, + { + node: { + _id: 'subTag8', + name: 'subTag 8', + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 5, + }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], + }, + cursor: 'subTag8', + }, + { + node: { + _id: 'subTag9', + name: 'subTag 9', + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 5, + }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], + }, + cursor: 'subTag9', + }, + { + node: { + _id: 'subTag10', + name: 'subTag 10', + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 5, + }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], + }, + cursor: 'subTag10', + }, + ], + pageInfo: { + startCursor: 'subTag1', + endCursor: 'subTag10', + hasNextPage: true, + hasPreviousPage: false, + }, + totalCount: 11, + }, + ancestorTags: [], + }, + }, + }, + }, + { + request: { + query: USER_TAG_SUB_TAGS, + variables: { + id: '1', + after: 'subTag10', + first: TAGS_QUERY_DATA_CHUNK_SIZE, + }, + }, + result: { + data: { + getChildTags: { + name: 'userTag 1', + childTags: { + edges: [ + { + node: { + _id: 'subTag11', + name: 'subTag 11', + usersAssignedTo: { + totalCount: 0, + }, + childTags: { + totalCount: 0, + }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], + }, + cursor: 'subTag11', + }, + ], + pageInfo: { + startCursor: 'subTag11', + endCursor: 'subTag11', + hasNextPage: false, + hasPreviousPage: true, + }, + totalCount: 11, + }, + ancestorTags: [], + }, + }, + }, + }, + { + request: { + query: ASSIGN_TO_TAGS, + variables: { + currentTagId: '1', + selectedTagIds: ['2', '3'], + }, + }, + result: { + data: { + assignToUserTags: { + _id: '1', + }, + }, + }, + }, + { + request: { + query: REMOVE_FROM_TAGS, + variables: { + currentTagId: '1', + selectedTagIds: ['2'], + }, + }, + result: { + data: { + removeFromUserTags: { + _id: '1', + }, + }, + }, + }, +]; + +export const MOCKS_ERROR_ORGANIZATION_TAGS_QUERY = [ + { + request: { + query: ORGANIZATION_USER_TAGS_LIST, + variables: { + id: '123', + first: TAGS_QUERY_DATA_CHUNK_SIZE, + where: { name: { starts_with: '' } }, + }, + }, + error: new Error('Mock Graphql Error for organization root tags query'), + }, +]; + +export const MOCKS_ERROR_SUBTAGS_QUERY = [ + { + request: { + query: ORGANIZATION_USER_TAGS_LIST, + variables: { + id: '123', + first: TAGS_QUERY_DATA_CHUNK_SIZE, + where: { name: { starts_with: '' } }, + }, + }, + result: { + data: { + organizations: [ + { + userTags: { + edges: [ + { + node: { + _id: '1', + name: 'userTag 1', + parentTag: null, + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 11, + }, + ancestorTags: [], + }, + cursor: '1', + }, + { + node: { + _id: '2', + name: 'userTag 2', + parentTag: null, + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 0, + }, + ancestorTags: [], + }, + cursor: '2', + }, + ], + pageInfo: { + startCursor: '1', + endCursor: '2', + hasNextPage: false, + hasPreviousPage: false, + }, + totalCount: 2, + }, + }, + ], + }, + }, + }, + { + request: { + query: USER_TAG_SUB_TAGS, + variables: { + id: '1', + first: TAGS_QUERY_DATA_CHUNK_SIZE, + }, + }, + error: new Error('Mock Graphql Error for subTags query'), + }, +]; diff --git a/src/components/TagActions/TagNode.tsx b/src/components/TagActions/TagNode.tsx new file mode 100644 index 0000000000..4a085ecaf9 --- /dev/null +++ b/src/components/TagActions/TagNode.tsx @@ -0,0 +1,199 @@ +import { useQuery } from '@apollo/client'; +import { USER_TAG_SUB_TAGS } from 'GraphQl/Queries/userTagQueries'; +import React, { useState } from 'react'; +import type { + InterfaceQueryUserTagChildTags, + InterfaceTagData, +} from 'utils/interfaces'; +import type { InterfaceOrganizationSubTagsQuery } from 'utils/organizationTagsUtils'; +import { TAGS_QUERY_DATA_CHUNK_SIZE } from 'utils/organizationTagsUtils'; +import styles from './TagActions.module.css'; +import InfiniteScroll from 'react-infinite-scroll-component'; +import InfiniteScrollLoader from 'components/InfiniteScrollLoader/InfiniteScrollLoader'; +import { WarningAmberRounded } from '@mui/icons-material'; +import type { TFunction } from 'i18next'; + +/** + * Props for the `TagNode` component. + */ +interface InterfaceTagNodeProps { + tag: InterfaceTagData; + checkedTags: Set; + toggleTagSelection: (tag: InterfaceTagData, isSelected: boolean) => void; + t: TFunction<'translation', 'manageTag'>; +} + +/** + * Renders the Tags which can be expanded to list subtags. + */ +const TagNode: React.FC = ({ + tag, + checkedTags, + toggleTagSelection, + t, +}) => { + const [expanded, setExpanded] = useState(false); + + const { + data: subTagsData, + loading: subTagsLoading, + error: subTagsError, + fetchMore: fetchMoreSubTags, + }: InterfaceOrganizationSubTagsQuery = useQuery(USER_TAG_SUB_TAGS, { + variables: { + id: tag._id, + first: TAGS_QUERY_DATA_CHUNK_SIZE, + }, + skip: !expanded, + }); + + const loadMoreSubTags = (): void => { + fetchMoreSubTags({ + variables: { + first: TAGS_QUERY_DATA_CHUNK_SIZE, + after: subTagsData?.getChildTags.childTags.pageInfo.endCursor, + }, + updateQuery: ( + prevResult: { getChildTags: InterfaceQueryUserTagChildTags }, + { + fetchMoreResult, + }: { + fetchMoreResult?: { getChildTags: InterfaceQueryUserTagChildTags }; + }, + ) => { + if (!fetchMoreResult) /* istanbul ignore next */ return prevResult; + + return { + getChildTags: { + ...fetchMoreResult.getChildTags, + childTags: { + ...fetchMoreResult.getChildTags.childTags, + edges: [ + ...prevResult.getChildTags.childTags.edges, + ...fetchMoreResult.getChildTags.childTags.edges, + ], + }, + }, + }; + }, + }); + }; + + if (subTagsError) { + return ( +
    +
    + +
    + {t('errorOccurredWhileLoadingSubTags')} +
    +
    +
    + ); + } + + const subTagsList = + subTagsData?.getChildTags.childTags.edges.map((edge) => edge.node) ?? + /* istanbul ignore next */ []; + + const handleTagClick = (): void => { + setExpanded(!expanded); + }; + + const handleCheckboxChange = ( + e: React.ChangeEvent, + ): void => { + toggleTagSelection(tag, e.target.checked); + }; + + return ( +
    +
    + {tag.childTags.totalCount ? ( + <> + + {expanded ? '▼' : '▶'} + + + {' '} + + ) : ( + <> + + + {' '} + + )} + + {tag.name} +
    + + {expanded && subTagsLoading && ( +
    +
    +
    +
    +
    + )} + {expanded && subTagsList?.length && ( +
    +
    + } + scrollableTarget={`subTagsScrollableDiv${tag._id}`} + > + {subTagsList.map((tag: InterfaceTagData) => ( +
    + +
    + ))} +
    +
    +
    + )} +
    + ); +}; + +export default TagNode; diff --git a/src/components/UpdateSession/UpdateSession.css b/src/components/UpdateSession/UpdateSession.css new file mode 100644 index 0000000000..073bbf973d --- /dev/null +++ b/src/components/UpdateSession/UpdateSession.css @@ -0,0 +1,96 @@ +/* Card styles */ +.update-timeout-card { + width: 700px; + background: #ffffff; + border: none; + border-radius: 16px; + filter: drop-shadow(0px 4px 15.3px rgba(0, 0, 0, 0.08)); + padding: 20px; +} + +.update-timeout-card-header { + background: none; + padding: 16px; + border-bottom: none; +} + +.update-timeout-card-title { + font-family: 'Lato', sans-serif; + font-weight: 600; + font-size: 24px; + color: #000000; +} + +.update-timeout-card-body { + padding: 20px; +} + +.update-timeout-current { + font-family: 'Lato', sans-serif; + font-weight: 400; + font-size: 16px; + color: #000000; + margin-bottom: 20px; /* Increased margin to create more space */ +} + +.update-timeout-label { + font-family: 'Lato', sans-serif; + font-weight: 400; + font-size: 16px; + color: #000000; + margin-bottom: 10px; /* Keep the same margin to maintain spacing with the slider */ +} + +.update-timeout-labels-container { + display: flex; + flex-direction: column; + align-items: start; +} + +.update-timeout-value { + color: #14ae5c; + font-weight: bold; +} + +.update-timeout-slider-labels { + display: flex; + justify-content: space-between; + font-size: 0.9rem; + color: #757575; +} + +.update-timeout-button-container { + display: flex; + justify-content: right; + margin-top: 20px; +} + +.update-timeout-button { + width: 112px; + height: 36px; + background: #31bb6b; + border-radius: 6px; + font-family: 'Lato', sans-serif; + font-weight: 500; + font-size: 16px; + color: #ffffff; + display: flex; + align-items: center; + justify-content: center; + border: none; + box-shadow: none; +} + +.update-timeout-button:hover { + background-color: #28a745; + border-color: #28a745; + box-shadow: none; +} + +.update-timeout-button:active { + transform: scale(0.98); +} + +.update-timeout-slider-container { + position: relative; +} diff --git a/src/components/UpdateSession/UpdateSession.test.tsx b/src/components/UpdateSession/UpdateSession.test.tsx new file mode 100644 index 0000000000..ce0a868820 --- /dev/null +++ b/src/components/UpdateSession/UpdateSession.test.tsx @@ -0,0 +1,346 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/client/testing'; +import { + render, + screen, + act, + within, + fireEvent, + waitFor, +} from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import 'jest-localstorage-mock'; +import 'jest-location-mock'; +import { I18nextProvider } from 'react-i18next'; +import { BrowserRouter } from 'react-router-dom'; +import { toast } from 'react-toastify'; +import UpdateTimeout from './UpdateSession'; +import i18n from 'utils/i18nForTest'; +import { GET_COMMUNITY_SESSION_TIMEOUT_DATA } from 'GraphQl/Queries/Queries'; +import { UPDATE_SESSION_TIMEOUT } from 'GraphQl/Mutations/mutations'; +import { errorHandler } from 'utils/errorHandler'; + +const MOCKS = [ + { + request: { + query: GET_COMMUNITY_SESSION_TIMEOUT_DATA, + }, + result: { + data: { + getCommunityData: { + timeout: 30, + }, + }, + }, + }, + { + request: { + query: GET_COMMUNITY_SESSION_TIMEOUT_DATA, + }, + result: { + data: { + getCommunityData: null, + }, + }, + }, + { + request: { + query: UPDATE_SESSION_TIMEOUT, + variables: { + timeout: 30, + }, + }, + result: { + data: { + updateSessionTimeout: true, + }, + }, + }, +]; + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }, +})); + +jest.mock('utils/errorHandler', () => ({ + errorHandler: jest.fn(), +})); + +describe('Testing UpdateTimeout Component', () => { + let consoleWarnSpy: jest.SpyInstance; + + beforeEach(() => { + consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + test('Should handle minimum slider value correctly', async () => { + const mockOnValueChange = jest.fn(); + + render( + + + , + ); + + const slider = await screen.findByTestId('slider-thumb'); + + // Simulate dragging to minimum value + userEvent.click(slider, { + // Simulate clicking on the slider to focus + clientX: -999, // Adjust the clientX to simulate different slider positions + }); + + expect(mockOnValueChange).toHaveBeenCalledWith(15); // Adjust based on slider min value + }); + + test('Should handle maximum slider value correctly', async () => { + const mockOnValueChange = jest.fn(); + + render( + + + , + ); + + const slider = await screen.findByTestId('slider-thumb'); + + // Simulate dragging to maximum value + userEvent.click(slider, { + // Simulate clicking on the slider to focus + clientX: 999, // Adjust the clientX to simulate different slider positions + }); + + expect(mockOnValueChange).toHaveBeenCalledWith(60); // Adjust based on slider max value + }); + + test('Should not update value if an invalid value is passed', async () => { + const mockOnValueChange = jest.fn(); + + render( + + + , + ); + + const slider = await screen.findByTestId('slider-thumb'); + + // Simulate invalid value handling + userEvent.click(slider, { + // Simulate clicking on the slider to focus + clientX: 0, // Adjust the clientX to simulate different slider positions + }); + + // Ensure onValueChange is not called with invalid values + expect(mockOnValueChange).not.toHaveBeenCalled(); + }); + + test('Should update slider value on user interaction', async () => { + const mockOnValueChange = jest.fn(); + + render( + + + , + ); + + // Wait for the slider to be present + const slider = await screen.findByTestId('slider-thumb'); + + // Simulate slider interaction + userEvent.type(slider, '45'); // Simulate typing value + + // Assert that the callback was called with the expected value + expect(mockOnValueChange).toHaveBeenCalledWith(expect.any(Number)); // Adjust as needed + }); + + test('Components should render properly', async () => { + render( + + + + + + + , + ); + + await wait(); + + // Use getAllByText to get all elements with "Update Timeout" text + const updateTimeoutElements = screen.getAllByText(/Update Timeout/i); + expect(updateTimeoutElements).toHaveLength(1); // Check if there are exactly 2 elements with this text + + expect(screen.getByText(/Current Timeout/i)).toBeInTheDocument(); + expect(screen.getByText(/15 min/i)).toBeInTheDocument(); + + // Locate the parent element first + const sliderLabelsContainer = screen.getByTestId('slider-labels'); + + // Use within to query inside the parent element + const sliderLabels = within(sliderLabelsContainer); + + // Check for the specific text within the parent element + expect(sliderLabels.getByText('30 min')).toBeInTheDocument(); + + expect(screen.getByText(/45 min/i)).toBeInTheDocument(); + expect(screen.getByText(/60 min/i)).toBeInTheDocument(); + expect(screen.getByRole('button', { name: /Update/i })).toBeInTheDocument(); + }); + + test('Should update session timeout', async () => { + render( + + + + + + + , + ); + + await wait(); + + const submitButton = screen.getByTestId('update-button'); + userEvent.click(submitButton); + + // Wait for the toast success call + + await wait(); + + expect(toast.success).toHaveBeenCalledWith( + expect.stringContaining('Successfully updated the Profile Details.'), + ); + }); + + test('Should handle query errors', async () => { + const errorMocks = [ + { + request: { + query: GET_COMMUNITY_SESSION_TIMEOUT_DATA, + }, + error: new Error('An error occurred'), + }, + ]; + + render( + + + + + + + , + ); + + await wait(); + + expect(errorHandler).toHaveBeenCalled(); + }); + + test('Should handle update errors', async () => { + const errorMocks = [ + { + request: { + query: GET_COMMUNITY_SESSION_TIMEOUT_DATA, + }, + result: { + data: { + getCommunityData: { + timeout: 30, + }, + }, + }, + }, + { + request: { + query: GET_COMMUNITY_SESSION_TIMEOUT_DATA, + }, + result: { + data: { + getCommunityData: null, + }, + }, + }, + { + request: { + query: UPDATE_SESSION_TIMEOUT, + variables: { timeout: 30 }, + }, + error: new Error('An error occurred'), + }, + ]; + + render( + + + + + + + , + ); + + await wait(); + + const submitButton = screen.getByTestId('update-button'); + userEvent.click(submitButton); + + await wait(); + + expect(errorHandler).toHaveBeenCalled(); + }); + + test('Should handle null community object gracefully', async () => { + render( + + + + + + + , + ); + + await wait(); + + // Assertions to verify the component handles null community object correctly + // Use getAllByText to get all elements with "Update Timeout" text + const updateTimeoutElements = screen.getAllByText(/Update Timeout/i); + expect(updateTimeoutElements).toHaveLength(1); // Check if there are exactly 2 elements with this text + + expect(screen.getByText(/Current Timeout/i)).toBeInTheDocument(); + + // Locate the parent element first + const sliderLabelsContainer = screen.getByTestId('slider-labels'); + + // Use within to query inside the parent element + const sliderLabels = within(sliderLabelsContainer); + + // Check for the specific text within the parent element + expect(sliderLabels.getByText('15 min')).toBeInTheDocument(); + + expect(screen.getByText(/30 min/i)).toBeInTheDocument(); + expect(screen.getByText(/45 min/i)).toBeInTheDocument(); + expect(screen.getByText(/60 min/i)).toBeInTheDocument(); + expect(screen.getByRole('button', { name: /Update/i })).toBeInTheDocument(); + + // Check if the component displays a default value or handles the null state appropriately + expect(screen.getByText(/No timeout set/i)).toBeInTheDocument(); + }); +}); diff --git a/src/components/UpdateSession/UpdateSession.tsx b/src/components/UpdateSession/UpdateSession.tsx new file mode 100644 index 0000000000..f49970ebaa --- /dev/null +++ b/src/components/UpdateSession/UpdateSession.tsx @@ -0,0 +1,202 @@ +import React, { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Card, Button, Form } from 'react-bootstrap'; +import Box from '@mui/material/Box'; +import Slider from '@mui/material/Slider'; +import { useMutation, useQuery } from '@apollo/client'; +import { GET_COMMUNITY_SESSION_TIMEOUT_DATA } from 'GraphQl/Queries/Queries'; +import { toast } from 'react-toastify'; +import { errorHandler } from 'utils/errorHandler'; +import { UPDATE_SESSION_TIMEOUT } from 'GraphQl/Mutations/mutations'; +import './UpdateSession.css'; +import Loader from 'components/Loader/Loader'; + +/** + * Component for updating the session timeout for a community. + * + * This component fetches the current session timeout value from the server + * and allows the user to update it using a slider. + * + * The component also handles form submission, making a mutation request to update the session timeout. + * + * @returns JSX.Element - The rendered component. + */ + +interface TestInterfaceUpdateTimeoutProps { + onValueChange?: (value: number) => void; +} + +const UpdateTimeout: React.FC = ({ + onValueChange, +}): JSX.Element => { + const { t } = useTranslation('translation', { + keyPrefix: 'communityProfile', + }); + + const [timeout, setTimeout] = useState(30); + const [communityTimeout, setCommunityTimeout] = useState( + 30, + ); // Timeout from database for the community + + const { + data, + loading, + error: queryError, + } = useQuery(GET_COMMUNITY_SESSION_TIMEOUT_DATA); + const [uploadSessionTimeout] = useMutation(UPDATE_SESSION_TIMEOUT); + + type TimeoutDataType = { + timeout: number; + }; + + /** + * Effect that fetches the current session timeout from the server and sets the initial state. + * If there is an error in fetching the data, it is handled using the error handler. + */ + React.useEffect(() => { + if (queryError) { + errorHandler(t, queryError as Error); + } + + const SessionTimeoutData: TimeoutDataType | undefined = + data?.getCommunityData; + + if (SessionTimeoutData && SessionTimeoutData.timeout !== null) { + setCommunityTimeout(SessionTimeoutData.timeout); + setTimeout(SessionTimeoutData.timeout); + } else { + setCommunityTimeout(undefined); // Handle null or undefined data + } + }, [data, queryError]); + + /** + * Handles changes to the slider value and updates the timeout state. + * + * @param e - The event triggered by slider movement. + */ + const handleOnChange = ( + e: Event | React.ChangeEvent, + ): void => { + if ('target' in e && e.target) { + const target = e.target as HTMLInputElement; + // Ensure the value is a number and not NaN + const value = parseInt(target.value, 10); + if (!Number.isNaN(value)) { + setTimeout(value); + if (onValueChange) { + onValueChange(value); + } + } else { + console.warn('Invalid timeout value:', target.value); + } + } + }; + + /** + * Handles form submission to update the session timeout. + * It makes a mutation request to update the timeout value on the server. + * If the update is successful, a success toast is shown, and the state is updated. + * + * @param e - The event triggered by form submission. + */ + const handleOnSubmit = async ( + e: React.FormEvent, + ): Promise => { + e.preventDefault(); + try { + await uploadSessionTimeout({ + variables: { + timeout: timeout, + }, + }); + + toast.success(t('profileChangedMsg')); + setCommunityTimeout(timeout); + } catch (error: unknown) { + /* istanbul ignore next */ + errorHandler(t, error as Error); + } + }; + + // Show a loader while the data is being fetched + if (loading) { + return ; + } + + return ( + <> + + +
    Login Session Timeout
    +
    + +
    +
    + + Current Timeout: + + {communityTimeout !== undefined + ? ` ${communityTimeout} minutes` + : ' No timeout set'} + + + + + Update Timeout + +
    + + + + + +
    + 15 min + 30 min + 45 min + 60 min +
    +
    + +
    +
    +
    +
    + + ); +}; + +export default UpdateTimeout; diff --git a/src/components/UserPortal/ChatRoom/ChatRoom.module.css b/src/components/UserPortal/ChatRoom/ChatRoom.module.css index f6aa3e374b..5fc98351cd 100644 --- a/src/components/UserPortal/ChatRoom/ChatRoom.module.css +++ b/src/components/UserPortal/ChatRoom/ChatRoom.module.css @@ -24,6 +24,7 @@ padding-bottom: 5px; align-items: center; margin-top: 5px; + gap: 10px; } .contactImage { @@ -53,6 +54,9 @@ width: fit-content; max-width: 75%; min-width: 80px; + padding-bottom: 0; + display: flex; + justify-content: space-between; } .messageSent { @@ -65,6 +69,49 @@ background-color: rgba(196, 255, 211, 0.3); min-width: 80px; padding-bottom: 0; + display: flex; + justify-content: space-between; +} + +.userDetails { + display: flex; + align-items: center; + font-size: 14px; + gap: 6px; +} + +.userDetails .userImage { + height: 20px; + width: 20px; +} + +.replyTo { + border-left: 4px solid pink; + display: flex; + justify-content: space-between; + background-color: rgb(249, 249, 250); + padding: 6px 0px 4px 4px; + border-radius: 6px 6px 6px 6px; +} + +.replyToMessageContainer { + padding-left: 4px; +} + +.replyToMessageContainer p { + margin: 4px 0px 0px; +} + +.replyToMessage { + border-left: 4px solid pink; + border-radius: 6px; + margin: 6px 0px; + padding: 6px; + background-color: #dbf6db; +} + +.messageReceived .replyToMessage { + background-color: #f2f2f2; } .messageTime { @@ -73,10 +120,15 @@ align-items: flex-end; justify-content: flex-end; margin-bottom: 0px; + margin-left: 6px; } .messageContent { - margin-bottom: 0px; + margin-bottom: 0.5px; + display: flex; + align-items: flex-start; + flex-direction: column; + justify-content: center; } .createChat { @@ -108,3 +160,91 @@ font-size: 12px; font-weight: 600; } + +.messageAttributes { + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: flex-end; +} + +.customToggle { + display: none; +} + +.customToggle, +.closeBtn { + padding: 0; + background: none; + border: none; + --bs-btn-active-bg: none; +} +.customToggle svg { + color: black; + font-size: 12px; +} + +.customToggle::after, +.closeBtn::after { + content: none; +} + +.closeBtn svg { + color: black; + font-size: 18px; +} + +.closeBtn { + padding: 2px 10px; +} + +.closeBtn:hover { + background-color: transparent; + border-color: transparent; +} + +.customToggle:hover, +.customToggle:focus, +.customToggle:active { + background: none; + border: none; +} + +.messageReceived:hover .customToggle { + display: block; +} + +.messageSent:hover .customToggle { + display: block; +} + +.messageSent:hover, +.messageReceived:hover { + padding: 0px 6px; +} + +.messageSent:target { + scroll-margin-top: 100px; + animation-name: test; + animation-duration: 1s; +} + +.messageReceived:target { + scroll-margin-top: 100px; + animation-name: test; + animation-duration: 1s; +} + +@keyframes test { + from { + background-color: white; + } + to { + background-color: rgb(82, 83, 81); + } +} + +a { + color: currentColor; + width: 100%; +} diff --git a/src/components/UserPortal/ChatRoom/ChatRoom.test.tsx b/src/components/UserPortal/ChatRoom/ChatRoom.test.tsx index c4fd4eadaf..c808485132 100644 --- a/src/components/UserPortal/ChatRoom/ChatRoom.test.tsx +++ b/src/components/UserPortal/ChatRoom/ChatRoom.test.tsx @@ -6,34 +6,24 @@ import { screen, fireEvent, waitFor, - findAllByTestId, } from '@testing-library/react'; -import { MockedProvider } from '@apollo/react-testing'; +import { MockSubscriptionLink, MockedProvider } from '@apollo/react-testing'; import { I18nextProvider } from 'react-i18next'; - import { BrowserRouter } from 'react-router-dom'; import { Provider } from 'react-redux'; import { store } from 'state/store'; import i18nForTest from 'utils/i18nForTest'; -import { StaticMockLink } from 'utils/StaticMockLink'; +import { CHATS_LIST, CHAT_BY_ID } from 'GraphQl/Queries/PlugInQueries'; import { - DIRECT_CHAT_BY_ID, - GROUP_CHAT_BY_ID, -} from 'GraphQl/Queries/PlugInQueries'; -import { - MESSAGE_SENT_TO_DIRECT_CHAT, - MESSAGE_SENT_TO_GROUP_CHAT, - SEND_MESSAGE_TO_DIRECT_CHAT, - SEND_MESSAGE_TO_GROUP_CHAT, + MESSAGE_SENT_TO_CHAT, + SEND_MESSAGE_TO_CHAT, } from 'GraphQl/Mutations/OrganizationMutations'; -import userEvent from '@testing-library/user-event'; import ChatRoom from './ChatRoom'; import { useLocalStorage } from 'utils/useLocalstorage'; +import { StaticMockLink } from 'utils/StaticMockLink'; const { setItem } = useLocalStorage(); -const link = new StaticMockLink([], true); - async function wait(ms = 100): Promise { await act(() => { return new Promise((resolve) => { @@ -42,75 +32,24 @@ async function wait(ms = 100): Promise { }); } -const SEND_MESSAGE_TO_DIRECT_CHAT_MOCK = { - request: { - query: SEND_MESSAGE_TO_DIRECT_CHAT, - variables: { - messageContent: 'Hello', - chatId: '1', - }, - }, - result: { - data: { - sendMessageToDirectChat: { - _id: '', - createdAt: '', - messageContent: '', - receiver: { - _id: '', - firstName: '', - lastName: '', - }, - sender: { - _id: '', - firstName: '', - lastName: '', - }, - updatedAt: '', - }, - }, - }, -}; - -const SEND_MESSAGE_TO_GROUP_CHAT_MOCK = { - request: { - query: SEND_MESSAGE_TO_GROUP_CHAT, - variables: { - messageContent: 'Test message', - chatId: '1', - }, - }, - result: { - data: { - sendMessageToGroupChat: { - _id: '', - createdAt: '', - messageContent: '', - sender: { - _id: '', - firstName: '', - lastName: '', - }, - updatedAt: '', - }, - }, - }, -}; - -const MESSAGE_SENT_TO_GROUP_CHAT_MOCK = [ +const MESSAGE_SENT_TO_CHAT_MOCK = [ { request: { - query: MESSAGE_SENT_TO_GROUP_CHAT, + query: MESSAGE_SENT_TO_CHAT, variables: { userId: null, }, }, result: { data: { - messageSentToGroupChat: { + messageSentToChat: { _id: '668ec1f1364e03ac47a151', createdAt: '2024-07-10T17:16:33.248Z', + chatMessageBelongsTo: { + _id: '1', + }, messageContent: 'Test ', + replyTo: null, sender: { _id: '64378abd85008f171cf2990d', firstName: 'Wilt', @@ -124,41 +63,21 @@ const MESSAGE_SENT_TO_GROUP_CHAT_MOCK = [ }, { request: { - query: MESSAGE_SENT_TO_GROUP_CHAT, + query: MESSAGE_SENT_TO_CHAT, variables: { userId: '2', }, }, result: { data: { - messageSentToGroupChat: { + messageSentToChat: { _id: '668ec1f1df364e03ac47a151', createdAt: '2024-07-10T17:16:33.248Z', messageContent: 'Test ', - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - image: '', + chatMessageBelongsTo: { + _id: '1', }, - updatedAt: '2024-07-10', - }, - }, - }, - }, - { - request: { - query: MESSAGE_SENT_TO_GROUP_CHAT, - variables: { - userId: '1', - }, - }, - result: { - data: { - messageSentToGroupChat: { - _id: '668ec1f13603ac4697a151', - createdAt: '2024-07-10T17:16:33.248Z', - messageContent: 'Test ', + replyTo: null, sender: { _id: '64378abd85008f171cf2990d', firstName: 'Wilt', @@ -170,88 +89,23 @@ const MESSAGE_SENT_TO_GROUP_CHAT_MOCK = [ }, }, }, -]; - -const MESSAGE_SENT_TO_DIRECT_CHAT_MOCK = [ { request: { - query: MESSAGE_SENT_TO_DIRECT_CHAT, + query: MESSAGE_SENT_TO_CHAT, variables: { userId: '1', }, }, result: { data: { - messageSentToDirectChat: { - _id: '668ec1f1364e03ac4697a151', - createdAt: '2024-07-10T17:16:33.248Z', - messageContent: 'Test ', - receiver: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - image: '', - }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - image: '', - }, - updatedAt: '2024-07-10', - }, - }, - }, - }, - { - request: { - query: MESSAGE_SENT_TO_DIRECT_CHAT, - variables: { - userId: '2', - }, - }, - result: { - data: { - messageSentToDirectChat: { - _id: '668ec1f1364e03ac4697vgfa151', - createdAt: '2024-07-10T17:16:33.248Z', - messageContent: 'Test ', - receiver: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - image: '', - }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - image: '', - }, - updatedAt: '2024-07-10', - }, - }, - }, - }, - { - request: { - query: MESSAGE_SENT_TO_DIRECT_CHAT, - variables: { - userId: null, - }, - }, - result: { - data: { - messageSentToDirectChat: { - _id: '6ec1f1364e03ac4697a151', + messageSentToChat: { + _id: '668ec1f13603ac4697a151', createdAt: '2024-07-10T17:16:33.248Z', messageContent: 'Test ', - receiver: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - image: '', + chatMessageBelongsTo: { + _id: '1', }, + replyTo: null, sender: { _id: '64378abd85008f171cf2990d', firstName: 'Wilt', @@ -265,31 +119,37 @@ const MESSAGE_SENT_TO_DIRECT_CHAT_MOCK = [ }, ]; -const DIRECT_CHAT_BY_ID_QUERY_MOCK = [ +const CHAT_BY_ID_QUERY_MOCK = [ { request: { - query: DIRECT_CHAT_BY_ID, + query: CHAT_BY_ID, variables: { id: '1', }, }, result: { data: { - directChatById: { + chatById: { _id: '1', createdAt: '2345678903456', + isGroup: false, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: null, + name: '', messages: [ { - _id: '345678', + _id: '4', createdAt: '345678908765', messageContent: 'Hello', - receiver: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, + replyTo: null, sender: { _id: '2', firstName: 'Test', @@ -321,28 +181,34 @@ const DIRECT_CHAT_BY_ID_QUERY_MOCK = [ }, { request: { - query: DIRECT_CHAT_BY_ID, + query: CHAT_BY_ID, variables: { id: '1', }, }, result: { data: { - directChatById: { + chatById: { _id: '1', + isGroup: false, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: null, + name: '', createdAt: '2345678903456', messages: [ { - _id: '345678', + _id: '4', createdAt: '345678908765', messageContent: 'Hello', - receiver: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, + replyTo: null, sender: { _id: '2', firstName: 'Test', @@ -374,28 +240,34 @@ const DIRECT_CHAT_BY_ID_QUERY_MOCK = [ }, { request: { - query: DIRECT_CHAT_BY_ID, + query: CHAT_BY_ID, variables: { - id: '2', + id: '', }, }, result: { data: { - directChatById: { - _id: '65844efc814dd4003db811c4', + chatById: { + _id: '1', + isGroup: false, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: null, + name: '', createdAt: '2345678903456', messages: [ { - _id: '345678', + _id: '4', createdAt: '345678908765', messageContent: 'Hello', - receiver: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, + replyTo: null, sender: { _id: '2', firstName: 'Test', @@ -425,148 +297,513 @@ const DIRECT_CHAT_BY_ID_QUERY_MOCK = [ }, }, }, +]; + +const CHATS_LIST_MOCK = [ { request: { - query: DIRECT_CHAT_BY_ID, + query: CHATS_LIST, variables: { - id: '', + id: null, }, }, result: { data: { - directChatById: { - _id: '65844efc814dd4003db811c4', - createdAt: '2345678903456', - messages: [ - { - _id: '345678', - createdAt: '345678908765', - messageContent: 'Hello', - receiver: { + chatsByUserId: [ + { + _id: '65844efc814dd40fgh03db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', + }, + createdAt: '2345678903456', + name: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + replyTo: null, + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { _id: '1', firstName: 'Disha', lastName: 'Talreja', email: 'disha@example.com', image: '', }, - sender: { + { _id: '2', firstName: 'Test', lastName: 'User', email: 'test@example.com', image: '', }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + { + _id: '65844efc814ddgh4003db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', }, - ], - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, - { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@example.com', - image: '', + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', }, - ], - }, + createdAt: '2345678903456', + name: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + replyTo: null, + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + ], }, }, }, -]; - -const GROUP_CHAT_BY_ID_QUERY_MOCK = [ { request: { - query: GROUP_CHAT_BY_ID, + query: CHATS_LIST, variables: { - id: '1', + id: '', }, }, result: { data: { - groupChatById: { - _id: '65844efc814dd4003db811c4', - createdAt: '2345678903456', - title: 'Test Group Chat', - messages: [ - { - _id: '345678', - createdAt: '345678908765', - messageContent: 'Hello', - sender: { + chatsByUserId: [ + { + _id: '65844ghjefc814dd4003db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', + }, + createdAt: '2345678903456', + name: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + replyTo: null, + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { _id: '2', firstName: 'Test', lastName: 'User', email: 'test@example.com', image: '', }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + { + _id: 'ujhgtrdtyuiop', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', }, - ], - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, - { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@example.com', - image: '', - }, - { - _id: '3', - firstName: 'Test', - lastName: 'User1', - email: 'test1@example.com', - image: '', - }, - { - _id: '4', - firstName: 'Test', - lastName: 'User2', - email: 'test2@example.com', - image: '', + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', }, - { - _id: '5', - firstName: 'Test', - lastName: 'User4', - email: 'test4@example.com', - image: '', - }, - ], - }, + createdAt: '2345678903456', + name: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + replyTo: null, + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + ], }, }, }, { request: { - query: GROUP_CHAT_BY_ID, + query: CHATS_LIST, variables: { id: '1', }, }, result: { data: { - groupChatById: { - _id: '1', + chatsByUserId: [ + { + _id: '65844efc814dhjmkdftyd4003db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', + }, + createdAt: '2345678903456', + name: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + replyTo: null, + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + { + _id: '65844ewsedrffc814dd4003db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', + }, + createdAt: '2345678903456', + name: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + replyTo: null, + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + ], + }, + }, + }, +]; + +const GROUP_CHAT_BY_ID_QUERY_MOCK = [ + { + request: { + query: CHAT_BY_ID, + variables: { + id: '', + }, + }, + result: { + data: { + chatById: { + _id: '65844efc814dd4003db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', + }, createdAt: '2345678903456', - title: 'Test Group Chat', + name: 'Test Group Chat', messages: [ { - _id: '345678', + _id: '2', createdAt: '345678908765', messageContent: 'Hello', + replyTo: null, sender: { _id: '2', firstName: 'Test', @@ -619,22 +856,37 @@ const GROUP_CHAT_BY_ID_QUERY_MOCK = [ }, { request: { - query: GROUP_CHAT_BY_ID, + query: CHAT_BY_ID, variables: { - id: '2', + id: '1', }, }, result: { data: { - groupChatById: { + chatById: { _id: '65844efc814dd4003db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', + }, createdAt: '2345678903456', - title: 'Test Group Chat', + name: 'Test Group Chat', messages: [ { - _id: '345678', + _id: '1', createdAt: '345678908765', messageContent: 'Hello', + replyTo: null, sender: { _id: '2', firstName: 'Test', @@ -687,22 +939,37 @@ const GROUP_CHAT_BY_ID_QUERY_MOCK = [ }, { request: { - query: GROUP_CHAT_BY_ID, + query: CHAT_BY_ID, variables: { - id: '', + id: '1', }, }, result: { data: { - groupChatById: { + chatById: { _id: '65844efc814dd4003db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', + }, createdAt: '2345678903456', - title: 'Test Group Chat', + name: 'Test Group Chat', messages: [ { - _id: '345678', + _id: '1', createdAt: '345678908765', messageContent: 'Hello', + replyTo: null, sender: { _id: '2', firstName: 'Test', @@ -755,22 +1022,187 @@ const GROUP_CHAT_BY_ID_QUERY_MOCK = [ }, ]; +const SEND_MESSAGE_TO_CHAT_MOCK = [ + { + request: { + query: SEND_MESSAGE_TO_CHAT, + variables: { + chatId: '1', + replyTo: '4', + messageContent: 'Test reply message', + }, + }, + result: { + data: { + sendMessageToChat: { + _id: '668ec1f1364e03ac47a151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + replyTo: null, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, + { + request: { + query: SEND_MESSAGE_TO_CHAT, + variables: { + chatId: '1', + replyTo: '4', + messageContent: 'Test reply message', + }, + }, + result: { + data: { + sendMessageToChat: { + _id: '668ec1f1364e03ac47a151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + replyTo: null, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, + { + request: { + query: SEND_MESSAGE_TO_CHAT, + variables: { + chatId: '1', + replyTo: '1', + messageContent: 'Test reply message', + }, + }, + result: { + data: { + sendMessageToChat: { + _id: '668ec1f1364e03ac47a151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + replyTo: null, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, + { + request: { + query: SEND_MESSAGE_TO_CHAT, + variables: { + chatId: '1', + replyTo: undefined, + messageContent: 'Hello', + }, + }, + result: { + data: { + sendMessageToChat: { + _id: '668ec1f1364e03ac47a151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + replyTo: null, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, + { + request: { + query: SEND_MESSAGE_TO_CHAT, + variables: { + chatId: '1', + replyTo: '345678', + messageContent: 'Test reply message', + }, + }, + result: { + data: { + sendMessageToChat: { + _id: '668ec1f1364e03ac47a151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + replyTo: null, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, + { + request: { + query: SEND_MESSAGE_TO_CHAT, + variables: { + chatId: '1', + replyTo: undefined, + messageContent: 'Test message', + }, + }, + result: { + data: { + sendMessageToChat: { + _id: '668ec1f1364e03ac47a151', + createdAt: '2024-07-10T17:16:33.248Z', + messageContent: 'Test ', + replyTo: null, + sender: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: '', + }, + updatedAt: '2024-07-10', + }, + }, + }, + }, +]; + describe('Testing Chatroom Component [User Portal]', () => { window.HTMLElement.prototype.scrollIntoView = jest.fn(); test('Chat room should display fallback content if no chat is active', async () => { const mocks = [ - ...DIRECT_CHAT_BY_ID_QUERY_MOCK, - ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, - ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, - ...GROUP_CHAT_BY_ID_QUERY_MOCK, + ...MESSAGE_SENT_TO_CHAT_MOCK, + ...CHAT_BY_ID_QUERY_MOCK, + ...CHATS_LIST_MOCK, + ...SEND_MESSAGE_TO_CHAT_MOCK, ]; render( - + @@ -781,18 +1213,19 @@ describe('Testing Chatroom Component [User Portal]', () => { }); test('Selected contact is direct chat', async () => { + const link = new MockSubscriptionLink(); const mocks = [ - ...DIRECT_CHAT_BY_ID_QUERY_MOCK, - ...GROUP_CHAT_BY_ID_QUERY_MOCK, - ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, - ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ...MESSAGE_SENT_TO_CHAT_MOCK, + ...CHAT_BY_ID_QUERY_MOCK, + ...CHATS_LIST_MOCK, + ...SEND_MESSAGE_TO_CHAT_MOCK, ]; render( - + - + @@ -804,18 +1237,19 @@ describe('Testing Chatroom Component [User Portal]', () => { test('send message direct chat', async () => { setItem('userId', '2'); const mocks = [ - SEND_MESSAGE_TO_DIRECT_CHAT_MOCK, - ...DIRECT_CHAT_BY_ID_QUERY_MOCK, + ...MESSAGE_SENT_TO_CHAT_MOCK, + ...CHAT_BY_ID_QUERY_MOCK, + ...CHATS_LIST_MOCK, ...GROUP_CHAT_BY_ID_QUERY_MOCK, - ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, - ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ...SEND_MESSAGE_TO_CHAT_MOCK, ]; + const link2 = new StaticMockLink(mocks, true); render( - + - + @@ -841,21 +1275,148 @@ describe('Testing Chatroom Component [User Portal]', () => { await waitFor(() => { expect(input.value).toBeFalsy(); }); + + const messages = await screen.findAllByTestId('message'); + + console.log('MESSAGES', messages); + + expect(messages.length).not.toBe(0); + + act(() => { + fireEvent.mouseOver(messages[0]); + }); + + await waitFor(async () => { + expect(await screen.findByTestId('moreOptions')).toBeInTheDocument(); + }); + + const moreOptionsBtn = await screen.findByTestId('dropdown'); + act(() => { + fireEvent.click(moreOptionsBtn); + }); + + const replyBtn = await screen.findByTestId('replyBtn'); + + act(() => { + fireEvent.click(replyBtn); + }); + + const replyMsg = await screen.findByTestId('replyMsg'); + + await waitFor(() => { + expect(replyMsg).toBeInTheDocument(); + }); + + act(() => { + fireEvent.change(input, { target: { value: 'Test reply message' } }); + }); + expect(input.value).toBe('Test reply message'); + + act(() => { + fireEvent.click(sendBtn); + }); + + await wait(400); }); - test('Selected contact is group chat', async () => { + test('send message direct chat when userId is different', async () => { + setItem('userId', '8'); const mocks = [ - ...DIRECT_CHAT_BY_ID_QUERY_MOCK, ...GROUP_CHAT_BY_ID_QUERY_MOCK, - ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, - ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ...MESSAGE_SENT_TO_CHAT_MOCK, + ...CHAT_BY_ID_QUERY_MOCK, + ...CHATS_LIST_MOCK, + ...SEND_MESSAGE_TO_CHAT_MOCK, + ]; + const link2 = new StaticMockLink(mocks, true); + render( + + + + + + + + + , + ); + await wait(); + + const input = (await screen.findByTestId( + 'messageInput', + )) as HTMLInputElement; + + act(() => { + fireEvent.change(input, { target: { value: 'Hello' } }); + }); + expect(input.value).toBe('Hello'); + + const sendBtn = await screen.findByTestId('sendMessage'); + + expect(sendBtn).toBeInTheDocument(); + act(() => { + fireEvent.click(sendBtn); + }); + await waitFor(() => { + expect(input.value).toBeFalsy(); + }); + + const messages = await screen.findAllByTestId('message'); + + console.log('MESSAGES', messages); + + expect(messages.length).not.toBe(0); + + act(() => { + fireEvent.mouseOver(messages[0]); + }); + + await waitFor(async () => { + expect(await screen.findByTestId('moreOptions')).toBeInTheDocument(); + }); + + const moreOptionsBtn = await screen.findByTestId('dropdown'); + act(() => { + fireEvent.click(moreOptionsBtn); + }); + + const replyBtn = await screen.findByTestId('replyBtn'); + + act(() => { + fireEvent.click(replyBtn); + }); + + const replyMsg = await screen.findByTestId('replyMsg'); + + await waitFor(() => { + expect(replyMsg).toBeInTheDocument(); + }); + + act(() => { + fireEvent.change(input, { target: { value: 'Test reply message' } }); + }); + expect(input.value).toBe('Test reply message'); + + act(() => { + fireEvent.click(sendBtn); + }); + + await wait(400); + }); + + test('Selected contact is group chat', async () => { + const mocks = [ + ...MESSAGE_SENT_TO_CHAT_MOCK, + ...CHAT_BY_ID_QUERY_MOCK, + ...CHATS_LIST_MOCK, + ...SEND_MESSAGE_TO_CHAT_MOCK, ]; render( - + @@ -866,18 +1427,98 @@ describe('Testing Chatroom Component [User Portal]', () => { test('send message group chat', async () => { const mocks = [ - SEND_MESSAGE_TO_GROUP_CHAT_MOCK, - ...DIRECT_CHAT_BY_ID_QUERY_MOCK, - ...GROUP_CHAT_BY_ID_QUERY_MOCK, - ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, - ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ...MESSAGE_SENT_TO_CHAT_MOCK, + ...CHAT_BY_ID_QUERY_MOCK, + ...CHATS_LIST_MOCK, + ...SEND_MESSAGE_TO_CHAT_MOCK, ]; render( - + + + + + , + ); + await wait(); + + const input = (await screen.findByTestId( + 'messageInput', + )) as HTMLInputElement; + + act(() => { + fireEvent.change(input, { target: { value: 'Test message' } }); + }); + expect(input.value).toBe('Test message'); + + const sendBtn = await screen.findByTestId('sendMessage'); + + expect(sendBtn).toBeInTheDocument(); + act(() => { + fireEvent.click(sendBtn); + }); + await waitFor(() => { + expect(input.value).toBeFalsy(); + }); + + const messages = await screen.findAllByTestId('message'); + + expect(messages.length).not.toBe(0); + + act(() => { + fireEvent.mouseOver(messages[0]); + }); + + expect(await screen.findByTestId('moreOptions')).toBeInTheDocument(); + + const moreOptionsBtn = await screen.findByTestId('dropdown'); + act(() => { + fireEvent.click(moreOptionsBtn); + }); + + const replyBtn = await screen.findByTestId('replyBtn'); + + act(() => { + fireEvent.click(replyBtn); + }); + + const replyMsg = await screen.findByTestId('replyMsg'); + + await waitFor(() => { + expect(replyMsg).toBeInTheDocument(); + }); + + act(() => { + fireEvent.change(input, { target: { value: 'Test reply message' } }); + }); + expect(input.value).toBe('Test reply message'); + + const closeReplyBtn = await screen.findByTestId('closeReply'); + + expect(closeReplyBtn).toBeInTheDocument(); + + fireEvent.click(closeReplyBtn); + + await wait(500); + }); + + test('reply to message', async () => { + const mocks = [ + ...MESSAGE_SENT_TO_CHAT_MOCK, + ...CHAT_BY_ID_QUERY_MOCK, + ...CHATS_LIST_MOCK, + ...SEND_MESSAGE_TO_CHAT_MOCK, + ]; + const link2 = new StaticMockLink(mocks, true); + render( + + + + + @@ -903,5 +1544,43 @@ describe('Testing Chatroom Component [User Portal]', () => { await waitFor(() => { expect(input.value).toBeFalsy(); }); + + const messages = await screen.findAllByTestId('message'); + + expect(messages.length).not.toBe(0); + + act(() => { + fireEvent.mouseOver(messages[0]); + }); + + expect(await screen.findByTestId('moreOptions')).toBeInTheDocument(); + + const moreOptionsBtn = await screen.findByTestId('dropdown'); + act(() => { + fireEvent.click(moreOptionsBtn); + }); + + const replyBtn = await screen.findByTestId('replyBtn'); + + act(() => { + fireEvent.click(replyBtn); + }); + + const replyMsg = await screen.findByTestId('replyMsg'); + + await waitFor(() => { + expect(replyMsg).toBeInTheDocument(); + }); + + act(() => { + fireEvent.change(input, { target: { value: 'Test reply message' } }); + }); + expect(input.value).toBe('Test reply message'); + + act(() => { + fireEvent.click(sendBtn); + }); + + await wait(400); }); }); diff --git a/src/components/UserPortal/ChatRoom/ChatRoom.tsx b/src/components/UserPortal/ChatRoom/ChatRoom.tsx index dd36a93d8f..c23244a314 100644 --- a/src/components/UserPortal/ChatRoom/ChatRoom.tsx +++ b/src/components/UserPortal/ChatRoom/ChatRoom.tsx @@ -1,27 +1,22 @@ import React, { useEffect, useRef, useState } from 'react'; import type { ChangeEvent } from 'react'; import SendIcon from '@mui/icons-material/Send'; -import { Button, Form, InputGroup } from 'react-bootstrap'; +import { Button, Dropdown, Form, InputGroup } from 'react-bootstrap'; import styles from './ChatRoom.module.css'; import PermContactCalendarIcon from '@mui/icons-material/PermContactCalendar'; import { useTranslation } from 'react-i18next'; -import { - DIRECT_CHAT_BY_ID, - GROUP_CHAT_BY_ID, -} from 'GraphQl/Queries/PlugInQueries'; +import { CHAT_BY_ID } from 'GraphQl/Queries/PlugInQueries'; import { useMutation, useQuery, useSubscription } from '@apollo/client'; import { - MESSAGE_SENT_TO_DIRECT_CHAT, - MESSAGE_SENT_TO_GROUP_CHAT, - SEND_MESSAGE_TO_DIRECT_CHAT, - SEND_MESSAGE_TO_GROUP_CHAT, + MESSAGE_SENT_TO_CHAT, + SEND_MESSAGE_TO_CHAT, } from 'GraphQl/Mutations/OrganizationMutations'; import useLocalStorage from 'utils/useLocalstorage'; import Avatar from 'components/Avatar/Avatar'; +import { MoreVert, Close } from '@mui/icons-material'; interface InterfaceChatRoomProps { selectedContact: string; - selectedChatType: string; } /** @@ -45,32 +40,34 @@ type DirectMessage = { lastName: string; image: string; }; + replyTo: + | { + _id: string; + createdAt: Date; + sender: { + _id: string; + firstName: string; + lastName: string; + image: string; + }; + messageContent: string; + receiver: { + _id: string; + firstName: string; + lastName: string; + }; + } + | undefined; messageContent: string; - receiver: { - _id: string; - firstName: string; - lastName: string; - }; + type: string; }; type Chat = { _id: string; - messages: { - _id: string; - createdAt: Date; - sender: { - _id: string; - firstName: string; - lastName: string; - image: string; - }; - messageContent: string; - receiver: { - _id: string; - firstName: string; - lastName: string; - }; - }[]; + isGroup: boolean; + name?: string; + image?: string; + messages: DirectMessage[]; users: { _id: string; firstName: string; @@ -97,8 +94,9 @@ export default function chatRoom(props: InterfaceChatRoomProps): JSX.Element { const [chatTitle, setChatTitle] = useState(''); const [chatSubtitle, setChatSubtitle] = useState(''); const [newMessage, setNewMessage] = useState(''); - const [directChat, setDirectChat] = useState(); - const [groupChat, setGroupChat] = useState(); + const [chat, setChat] = useState(); + const [replyToDirectMessage, setReplyToDirectMessage] = + useState(null); /** * Handles changes to the new message input field. @@ -112,145 +110,65 @@ export default function chatRoom(props: InterfaceChatRoomProps): JSX.Element { setNewMessage(newMessageValue); }; - const [sendMessageToDirectChat] = useMutation(SEND_MESSAGE_TO_DIRECT_CHAT, { + const [sendMessageToChat] = useMutation(SEND_MESSAGE_TO_CHAT, { variables: { chatId: props.selectedContact, + replyTo: replyToDirectMessage?._id, messageContent: newMessage, }, }); - const [sendMessageToGroupChat] = useMutation(SEND_MESSAGE_TO_GROUP_CHAT, { - variables: { - chatId: props.selectedContact, - messageContent: newMessage, - }, - }); - - const { - data: chatData, - loading: chatLoading, - refetch: chatRefetch, - } = useQuery(DIRECT_CHAT_BY_ID, { - variables: { - id: props.selectedContact, - }, - }); - - const { - data: chatDataGorup, - loading: groupChatLoading, - refetch: groupChatRefresh, - } = useQuery(GROUP_CHAT_BY_ID, { + const { data: chatData, refetch: chatRefetch } = useQuery(CHAT_BY_ID, { variables: { id: props.selectedContact, }, }); useEffect(() => { - if (props.selectedChatType == 'direct') { - chatRefetch(); - } else if (props.selectedChatType == 'group') { - groupChatRefresh(); - } + chatRefetch(); }, [props.selectedContact]); useEffect(() => { - if ( - props.selectedChatType === 'direct' && - chatData && - isMountedRef.current - ) { - const directChatData = chatData.directChatById; - setDirectChat(directChatData); - const otherUser = directChatData.users.find( - (user: any) => user._id !== userId, - ); - if (otherUser) { - setChatTitle(`${otherUser.firstName} ${otherUser.lastName}`); - setChatSubtitle(otherUser.email); + if (chatData) { + const chat = chatData.chatById; + setChat(chat); + if (chat.isGroup) { + setChatTitle(chat.name); + setChatSubtitle(`${chat.users.length} members`); + } else { + const otherUser = chat.users.find( + (user: { _id: string }) => user._id !== userId, + ); + if (otherUser) { + setChatTitle(`${otherUser.firstName} ${otherUser.lastName}`); + setChatSubtitle(otherUser.email); + } } } }, [chatData]); - useEffect(() => { - if ( - props.selectedChatType === 'group' && - chatDataGorup && - isMountedRef.current - ) { - const groupChatData = chatDataGorup.groupChatById; - setGroupChat(groupChatData); - setChatTitle(groupChatData.title); - setChatSubtitle(`${groupChatData.users.length} members`); - } - }, [chatDataGorup]); - const sendMessage = async (): Promise => { - console.log(props.selectedChatType); - if (props.selectedChatType === 'direct') { - await sendMessageToDirectChat(); - await chatRefetch(); - } else if (props.selectedChatType === 'group') { - const data = await sendMessageToGroupChat(); - await groupChatRefresh(); - } + await sendMessageToChat(); + await chatRefetch(); + setReplyToDirectMessage(null); setNewMessage(''); }; - useSubscription(MESSAGE_SENT_TO_DIRECT_CHAT, { + useSubscription(MESSAGE_SENT_TO_CHAT, { variables: { userId: userId, }, - onData: (directMessageSubscriptionData) => { - console.log( - directMessageSubscriptionData?.data.data.messageSentToDirectChat - .directChatMessageBelongsTo['_id'], - props.selectedContact, - ); + onData: (messageSubscriptionData) => { if ( - directMessageSubscriptionData?.data.data.messageSentToDirectChat && - directMessageSubscriptionData?.data.data.messageSentToDirectChat - .directChatMessageBelongsTo['_id'] == props.selectedContact + messageSubscriptionData?.data.data.messageSentToChat && + messageSubscriptionData?.data.data.messageSentToChat + .chatMessageBelongsTo['_id'] == props.selectedContact ) { - const updatedChat = directChat - ? JSON.parse(JSON.stringify(directChat)) - : { messages: [] }; - updatedChat?.messages.push( - directMessageSubscriptionData?.data.data.messageSentToDirectChat, - ); - setDirectChat(updatedChat); chatRefetch(); - } - }, - }); - - useSubscription(MESSAGE_SENT_TO_GROUP_CHAT, { - variables: { - userId: userId, - }, - onData: (groupMessageSubscriptionData) => { - if ( - groupMessageSubscriptionData?.data.data.messageSentToGroupChat && - groupMessageSubscriptionData?.data.data.messageSentToGroupChat - .groupChatMessageBelongsTo['_id'] == props.selectedContact - ) { - const updatedChat = groupChat - ? JSON.parse(JSON.stringify(groupChat)) - : { messages: [] }; - updatedChat?.messages.push( - groupMessageSubscriptionData.data.data.messageSentToGroupChat, - ); - setGroupChat(updatedChat); - groupChatRefresh({ - id: props.selectedContact, - }); } else { - groupChatRefresh({ - id: groupMessageSubscriptionData?.data.data.messageSentToGroupChat - .groupChatMessageBelongsTo['_id'], - }); - groupChatRefresh({ - id: props.selectedContact, + chatRefetch({ + id: messageSubscriptionData?.data.data.messageSentToChat + .chatMessageBelongsTo['_id'], }); } }, @@ -285,128 +203,155 @@ export default function chatRoom(props: InterfaceChatRoomProps): JSX.Element { />

    {chatTitle}

    -

    - {chatSubtitle}{' '} - {props.selectedChatType == 'direct' ? '' : 'members'} -

    +

    {chatSubtitle}

    - {!!( - directChat?.messages.length || groupChat?.messages.length - ) && ( + {!!chat?.messages.length && ( )}
    + {!!replyToDirectMessage?._id && ( +
    +
    +
    + + + {replyToDirectMessage.sender.firstName + + ' ' + + replyToDirectMessage.sender.lastName} + +
    +

    {replyToDirectMessage.messageContent}

    +
    + + +
    + )} { props = { ...props, selectedContact: '1', + isGroup: true, }; render( diff --git a/src/components/UserPortal/ContactCard/ContactCard.tsx b/src/components/UserPortal/ContactCard/ContactCard.tsx index cd135a9e01..ef6bf2c9d5 100644 --- a/src/components/UserPortal/ContactCard/ContactCard.tsx +++ b/src/components/UserPortal/ContactCard/ContactCard.tsx @@ -5,12 +5,10 @@ import Avatar from 'components/Avatar/Avatar'; interface InterfaceContactCardProps { id: string; title: string; - subtitle: string; image: string; selectedContact: string; setSelectedContact: React.Dispatch>; - type: string; - setSelectedChatType: React.Dispatch>; + isGroup: boolean; } /** @@ -33,18 +31,9 @@ interface InterfaceContactCardProps { * @returns The rendered contact card component. */ function contactCard(props: InterfaceContactCardProps): JSX.Element { - // Full name of the contact - - /** - * Updates the selected contact and its name when the card is clicked. - */ - const handleSelectedContactChange = (): void => { props.setSelectedContact(props.id); - props.setSelectedChatType(props.type); }; - - // State to track if the contact card is selected const [isSelected, setIsSelected] = React.useState( props.selectedContact === props.id, ); @@ -78,7 +67,6 @@ function contactCard(props: InterfaceContactCardProps): JSX.Element { )}
    {props.title} - {props.subtitle}
    diff --git a/src/components/UserPortal/CreateDirectChat/CreateDirectChat.test.tsx b/src/components/UserPortal/CreateDirectChat/CreateDirectChat.test.tsx index 338b890a2a..d8b3466207 100644 --- a/src/components/UserPortal/CreateDirectChat/CreateDirectChat.test.tsx +++ b/src/components/UserPortal/CreateDirectChat/CreateDirectChat.test.tsx @@ -7,909 +7,21 @@ import { waitFor, } from '@testing-library/react'; import { MockedProvider } from '@apollo/react-testing'; -import { I18nextProvider, useTranslation } from 'react-i18next'; - -import { - DIRECT_CHATS_LIST, - USERS_CONNECTION_LIST, -} from 'GraphQl/Queries/Queries'; +import { I18nextProvider } from 'react-i18next'; +import { USERS_CONNECTION_LIST } from 'GraphQl/Queries/Queries'; import { BrowserRouter } from 'react-router-dom'; import { Provider } from 'react-redux'; -import { store } from 'state/store'; -import i18nForTest from 'utils/i18nForTest'; -import Chat from '../../../screens/UserPortal/Chat/Chat'; -import { - CREATE_DIRECT_CHAT, - MESSAGE_SENT_TO_DIRECT_CHAT, - MESSAGE_SENT_TO_GROUP_CHAT, -} from 'GraphQl/Mutations/OrganizationMutations'; -import { - DIRECT_CHAT_BY_ID, - GROUP_CHAT_BY_ID, - GROUP_CHAT_LIST, -} from 'GraphQl/Queries/PlugInQueries'; -import useLocalStorage from 'utils/useLocalstorage'; - -const { setItem } = useLocalStorage(); - -const MOCKS = [ - { - request: { - query: GROUP_CHAT_LIST, - variables: { - id: null, - }, - }, - result: { - data: { - groupChatsByUserId: [ - { - _id: '1', - creator: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - }, - messages: { - _id: '1', - createdAt: '', - messageContent: 'Hello', - sender: { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@email.com', - }, - }, - title: 'Test GroupChat', - organization: { - _id: '1', - name: 'Test Org', - }, - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@email.com', - image: 'img', - }, - ], - }, - { - _id: '2', - creator: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - }, - messages: { - _id: '1', - createdAt: '', - messageContent: 'Hello', - sender: { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@email.com', - }, - }, - title: 'Test GroupChat', - organization: { - _id: '1', - name: 'Test Org', - }, - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@email.com', - image: 'img', - }, - ], - }, - ], - }, - }, - }, - { - request: { - query: GROUP_CHAT_LIST, - variables: { - id: '1', - }, - }, - result: { - data: { - groupChatsByUserId: [ - { - _id: '1', - creator: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - }, - messages: { - _id: '1', - createdAt: '', - messageContent: 'Hello', - sender: { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@email.com', - }, - }, - title: 'Test GroupChat', - organization: { - _id: '1', - name: 'Test Org', - }, - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@email.com', - image: 'img', - }, - ], - }, - { - _id: '2', - creator: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - }, - messages: { - _id: '1', - createdAt: '', - messageContent: 'Hello', - sender: { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@email.com', - }, - }, - title: 'Test GroupChat', - organization: { - _id: '1', - name: 'Test Org', - }, - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@email.com', - image: 'img', - }, - ], - }, - ], - }, - }, - }, - { - request: { - query: GROUP_CHAT_LIST, - variables: { - id: null, - }, - }, - result: { - data: { - groupChatsByUserId: [ - { - _id: '1', - creator: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - }, - messages: { - _id: '1', - createdAt: '', - messageContent: 'Hello', - sender: { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@email.com', - }, - }, - title: 'Test GroupChat', - organization: { - _id: '1', - name: 'Test Org', - }, - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@email.com', - image: 'img', - }, - ], - }, - { - _id: '1', - creator: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - }, - messages: { - _id: '1', - createdAt: '', - messageContent: 'Hello', - sender: { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@email.com', - }, - }, - title: 'Test GroupChat', - organization: { - _id: '1', - name: 'Test Org', - }, - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@email.com', - image: 'img', - }, - ], - }, - ], - }, - }, - }, - { - request: { - query: DIRECT_CHATS_LIST, - variables: { - id: null, - }, - }, - result: { - data: { - directChatsByUserID: [ - { - _id: '666c88dd92e995354d98527c', - creator: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - __typename: 'User', - }, - messages: [ - { - _id: '668930bae43ce54e6e302cf1', - createdAt: '2024-07-06T11:55:38.933Z', - messageContent: 'hJnkank', - receiver: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - __typename: 'User', - }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - __typename: 'User', - }, - __typename: 'DirectChatMessage', - }, - ], - organization: { - _id: '6737904485008f171cf29924', - name: 'Unity Foundation', - __typename: 'Organization', - }, - users: [ - { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - image: null, - __typename: 'User', - }, - { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - image: null, - __typename: 'User', - }, - ], - __typename: 'DirectChat', - }, - { - _id: '666f09c892e995354d98a5ee', - creator: { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - __typename: 'User', - }, - messages: [ - { - _id: '6676932692e995354d98ab7f', - createdAt: '2024-06-22T09:02:30.776Z', - messageContent: 'hii', - receiver: { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - __typename: 'User', - }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - __typename: 'User', - }, - __typename: 'DirectChatMessage', - }, - ], - organization: { - _id: '6737904485008f171cf29924', - name: 'Unity Foundation', - __typename: 'Organization', - }, - users: [ - { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - image: null, - __typename: 'User', - }, - { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - image: null, - __typename: 'User', - }, - ], - __typename: 'DirectChat', - }, - ], - }, - }, - }, - { - request: { - query: DIRECT_CHATS_LIST, - variables: { - id: '1', - }, - }, - result: { - data: { - directChatsByUserID: [ - { - _id: '666c88dd92e995354d98527c', - creator: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - __typename: 'User', - }, - messages: [ - { - _id: '668930bae43ce54e6e302cf1', - createdAt: '2024-07-06T11:55:38.933Z', - messageContent: 'hJnkank', - receiver: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - __typename: 'User', - }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - __typename: 'User', - }, - __typename: 'DirectChatMessage', - }, - ], - organization: { - _id: '6737904485008f171cf29924', - name: 'Unity Foundation', - __typename: 'Organization', - }, - users: [ - { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - image: null, - __typename: 'User', - }, - { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - image: null, - __typename: 'User', - }, - ], - __typename: 'DirectChat', - }, - { - _id: '666f09c892e995354d98a5ee', - creator: { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - __typename: 'User', - }, - messages: [ - { - _id: '6676932692e995354d98ab7f', - createdAt: '2024-06-22T09:02:30.776Z', - messageContent: 'hii', - receiver: { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - __typename: 'User', - }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - __typename: 'User', - }, - __typename: 'DirectChatMessage', - }, - ], - organization: { - _id: '6737904485008f171cf29924', - name: 'Unity Foundation', - __typename: 'Organization', - }, - users: [ - { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - image: null, - __typename: 'User', - }, - { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - image: null, - __typename: 'User', - }, - ], - __typename: 'DirectChat', - }, - ], - }, - }, - }, - { - request: { - query: DIRECT_CHATS_LIST, - variables: { - id: '1', - }, - }, - result: { - data: { - directChatsByUserID: [ - { - _id: '666c88dd92e995354d98527c', - creator: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - __typename: 'User', - }, - messages: [ - { - _id: '668930bae43ce54e6e302cf1', - createdAt: '2024-07-06T11:55:38.933Z', - messageContent: 'hJnkank', - receiver: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - __typename: 'User', - }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - __typename: 'User', - }, - __typename: 'DirectChatMessage', - }, - ], - organization: { - _id: '6737904485008f171cf29924', - name: 'Unity Foundation', - __typename: 'Organization', - }, - users: [ - { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - image: null, - __typename: 'User', - }, - { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - image: null, - __typename: 'User', - }, - ], - __typename: 'DirectChat', - }, - { - _id: '666f09c892e995354d98a5ee', - creator: { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - __typename: 'User', - }, - messages: [ - { - _id: '6676932692e995354d98ab7f', - createdAt: '2024-06-22T09:02:30.776Z', - messageContent: 'hii', - receiver: { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - __typename: 'User', - }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - __typename: 'User', - }, - __typename: 'DirectChatMessage', - }, - ], - organization: { - _id: '6737904485008f171cf29924', - name: 'Unity Foundation', - __typename: 'Organization', - }, - users: [ - { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - image: null, - __typename: 'User', - }, - { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - image: null, - __typename: 'User', - }, - ], - __typename: 'DirectChat', - }, - ], - }, - }, - }, - { - request: { - query: DIRECT_CHATS_LIST, - variables: { - id: '1', - }, - }, - result: { - data: { - directChatsByUserID: [ - { - _id: '666c88dd92e995354d98527c', - creator: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - __typename: 'User', - }, - messages: [ - { - _id: '668930bae43ce54e6e302cf1', - createdAt: '2024-07-06T11:55:38.933Z', - messageContent: 'hJnkank', - receiver: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - __typename: 'User', - }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - __typename: 'User', - }, - __typename: 'DirectChatMessage', - }, - ], - organization: { - _id: '6737904485008f171cf29924', - name: 'Unity Foundation', - __typename: 'Organization', - }, - users: [ - { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - image: null, - __typename: 'User', - }, - { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - image: null, - __typename: 'User', - }, - ], - __typename: 'DirectChat', - }, - { - _id: '666f09c892e995354d98a5ee', - creator: { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - __typename: 'User', - }, - messages: [ - { - _id: '6676932692e995354d98ab7f', - createdAt: '2024-06-22T09:02:30.776Z', - messageContent: 'hii', - receiver: { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - __typename: 'User', - }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - __typename: 'User', - }, - __typename: 'DirectChatMessage', - }, - ], - organization: { - _id: '6737904485008f171cf29924', - name: 'Unity Foundation', - __typename: 'Organization', - }, - users: [ - { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - image: null, - __typename: 'User', - }, - { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - image: null, - __typename: 'User', - }, - ], - __typename: 'DirectChat', - }, - ], - }, - }, - }, - { - request: { - query: DIRECT_CHATS_LIST, - variables: { - id: '', - }, - }, - result: { - data: { - directChatsByUserID: [ - { - _id: '666c88dd92e995354d98527c', - creator: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - __typename: 'User', - }, - messages: [ - { - _id: '668930bae43ce54e6e302cf1', - createdAt: '2024-07-06T11:55:38.933Z', - messageContent: 'hJnkank', - receiver: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - __typename: 'User', - }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - __typename: 'User', - }, - __typename: 'DirectChatMessage', - }, - ], - organization: { - _id: '6737904485008f171cf29924', - name: 'Unity Foundation', - __typename: 'Organization', - }, - users: [ - { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - image: null, - __typename: 'User', - }, - { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - image: null, - __typename: 'User', - }, - ], - __typename: 'DirectChat', - }, - { - _id: '666f09c892e995354d98a5ee', - creator: { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - __typename: 'User', - }, - messages: [ - { - _id: '6676932692e995354d98ab7f', - createdAt: '2024-06-22T09:02:30.776Z', - messageContent: 'hii', - receiver: { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - __typename: 'User', - }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - __typename: 'User', - }, - __typename: 'DirectChatMessage', - }, - ], - organization: { - _id: '6737904485008f171cf29924', - name: 'Unity Foundation', - __typename: 'Organization', - }, - users: [ - { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - image: null, - __typename: 'User', - }, - { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - image: null, - __typename: 'User', - }, - ], - __typename: 'DirectChat', - }, - ], - }, - }, - }, -]; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import Chat from '../../../screens/UserPortal/Chat/Chat'; +import { + CREATE_CHAT, + MESSAGE_SENT_TO_CHAT, +} from 'GraphQl/Mutations/OrganizationMutations'; +import { CHATS_LIST, CHAT_BY_ID } from 'GraphQl/Queries/PlugInQueries'; +import useLocalStorage from 'utils/useLocalstorage'; + +const { setItem } = useLocalStorage(); const UserConnectionListMock = [ { @@ -1206,99 +318,24 @@ const UserConnectionListMock = [ }, }, }, - { - request: { - query: USERS_CONNECTION_LIST, - variables: { - firstName_contains: '', - lastName_contains: '', - }, - }, - result: { - data: { - users: { - user: [ - { - firstName: 'Disha', - lastName: 'Talreja', - image: 'img', - _id: '1', - email: 'disha@email.com', - createdAt: '', - appUserProfile: { - _id: '12', - isSuperAdmin: 'false', - createdOrganizations: { - _id: '345678', - }, - createdEvents: { - _id: '34567890', - }, - }, - organizationsBlockedBy: [], - joinedOrganizations: [], - }, - { - firstName: 'Disha', - lastName: 'Talreja', - image: 'img', - _id: '1', - email: 'disha@email.com', - createdAt: '', - appUserProfile: { - _id: '12', - isSuperAdmin: 'false', - createdOrganizations: { - _id: '345678', - }, - createdEvents: { - _id: '34567890', - }, - }, - organizationsBlockedBy: [], - joinedOrganizations: [], - }, - { - firstName: 'Disha', - lastName: 'Talreja', - image: 'img', - _id: '1', - email: 'disha@email.com', - createdAt: '', - appUserProfile: { - _id: '12', - isSuperAdmin: 'false', - createdOrganizations: { - _id: '345678', - }, - createdEvents: { - _id: '34567890', - }, - }, - organizationsBlockedBy: [], - joinedOrganizations: [], - }, - ], - }, - }, - }, - }, ]; -const MESSAGE_SENT_TO_GROUP_CHAT_MOCK = [ +const MESSAGE_SENT_TO_CHAT_MOCK = [ { request: { - query: MESSAGE_SENT_TO_GROUP_CHAT, + query: MESSAGE_SENT_TO_CHAT, variables: { userId: null, }, }, result: { data: { - messageSentToGroupChat: { + messageSentToChat: { _id: '668ec1f1364e03ac47a151', createdAt: '2024-07-10T17:16:33.248Z', messageContent: 'Test ', + type: 'STRING', + replyTo: null, sender: { _id: '64378abd85008f171cf2990d', firstName: 'Wilt', @@ -1312,17 +349,19 @@ const MESSAGE_SENT_TO_GROUP_CHAT_MOCK = [ }, { request: { - query: MESSAGE_SENT_TO_GROUP_CHAT, + query: MESSAGE_SENT_TO_CHAT, variables: { userId: '2', }, }, result: { data: { - messageSentToGroupChat: { + messageSentToChat: { _id: '668ec1f1df364e03ac47a151', createdAt: '2024-07-10T17:16:33.248Z', messageContent: 'Test ', + replyTo: null, + type: 'STRING', sender: { _id: '64378abd85008f171cf2990d', firstName: 'Wilt', @@ -1336,17 +375,19 @@ const MESSAGE_SENT_TO_GROUP_CHAT_MOCK = [ }, { request: { - query: MESSAGE_SENT_TO_GROUP_CHAT, + query: MESSAGE_SENT_TO_CHAT, variables: { userId: '1', }, }, result: { data: { - messageSentToGroupChat: { + messageSentToChat: { _id: '668ec1f13603ac4697a151', createdAt: '2024-07-10T17:16:33.248Z', messageContent: 'Test ', + replyTo: null, + type: 'STRING', sender: { _id: '64378abd85008f171cf2990d', firstName: 'Wilt', @@ -1360,124 +401,98 @@ const MESSAGE_SENT_TO_GROUP_CHAT_MOCK = [ }, ]; -const MESSAGE_SENT_TO_DIRECT_CHAT_MOCK = [ - { - request: { - query: MESSAGE_SENT_TO_DIRECT_CHAT, - variables: { - userId: '1', - }, - }, - result: { - data: { - messageSentToDirectChat: { - _id: '668ec1f1364e03ac4697a151', - createdAt: '2024-07-10T17:16:33.248Z', - messageContent: 'Test ', - receiver: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - image: '', - }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - image: '', - }, - updatedAt: '2024-07-10', - }, - }, - }, - }, +const CHAT_BY_ID_QUERY_MOCK = [ { request: { - query: MESSAGE_SENT_TO_DIRECT_CHAT, + query: CHAT_BY_ID, variables: { - userId: '2', + id: '1', }, }, result: { data: { - messageSentToDirectChat: { - _id: '668ec1f1364e03ac4697vgfa151', - createdAt: '2024-07-10T17:16:33.248Z', - messageContent: 'Test ', - receiver: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - image: '', - }, - sender: { + chatById: { + _id: '1', + createdAt: '2345678903456', + isGroup: false, + creator: { _id: '64378abd85008f171cf2990d', firstName: 'Wilt', lastName: 'Shepherd', - image: '', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', }, - updatedAt: '2024-07-10', + organization: null, + name: '', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + replyTo: null, + type: 'STRING', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + ], }, }, }, }, { request: { - query: MESSAGE_SENT_TO_DIRECT_CHAT, + query: CHAT_BY_ID, variables: { - userId: null, + id: '1', }, }, result: { data: { - messageSentToDirectChat: { - _id: '6ec1f1364e03ac4697a151', - createdAt: '2024-07-10T17:16:33.248Z', - messageContent: 'Test ', - receiver: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - image: '', - }, - sender: { + chatById: { + _id: '1', + isGroup: false, + creator: { _id: '64378abd85008f171cf2990d', firstName: 'Wilt', lastName: 'Shepherd', - image: '', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', }, - updatedAt: '2024-07-10', - }, - }, - }, - }, -]; - -const DIRECT_CHAT_BY_ID_QUERY_MOCK = [ - { - request: { - query: DIRECT_CHAT_BY_ID, - variables: { - id: '1', - }, - }, - result: { - data: { - directChatById: { - _id: '1', + organization: null, + name: '', createdAt: '2345678903456', messages: [ { _id: '345678', createdAt: '345678908765', messageContent: 'Hello', - receiver: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, + replyTo: null, + type: 'STRING', sender: { _id: '2', firstName: 'Test', @@ -1509,28 +524,35 @@ const DIRECT_CHAT_BY_ID_QUERY_MOCK = [ }, { request: { - query: DIRECT_CHAT_BY_ID, + query: CHAT_BY_ID, variables: { - id: '1', + id: '', }, }, result: { data: { - directChatById: { + chatById: { _id: '1', + isGroup: false, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: null, + name: '', createdAt: '2345678903456', messages: [ { _id: '345678', createdAt: '345678908765', messageContent: 'Hello', - receiver: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, + replyTo: null, + type: 'STRING', sender: { _id: '2', firstName: 'Test', @@ -1560,390 +582,678 @@ const DIRECT_CHAT_BY_ID_QUERY_MOCK = [ }, }, }, +]; + +const CHATS_LIST_MOCK = [ + { + request: { + query: CHATS_LIST, + variables: { + id: null, + }, + }, + result: { + data: { + chatsByUserId: [ + { + _id: '65844efc814dd40fgh03db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', + }, + createdAt: '2345678903456', + name: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + replyTo: null, + type: 'STRING', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + { + _id: '65844efc814ddgh4003db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', + }, + createdAt: '2345678903456', + name: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + replyTo: null, + type: 'STRING', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + ], + }, + }, + }, { request: { - query: DIRECT_CHAT_BY_ID, + query: CHATS_LIST, variables: { id: '', }, }, result: { data: { - directChatById: { - _id: '1', - createdAt: '2345678903456', - messages: [ - { - _id: '345678', - createdAt: '345678908765', - messageContent: 'Hello', - receiver: { + chatsByUserId: [ + { + _id: '65844ghjefc814dd4003db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', + }, + createdAt: '2345678903456', + name: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + replyTo: null, + type: 'STRING', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { _id: '1', firstName: 'Disha', lastName: 'Talreja', email: 'disha@example.com', image: '', }, - sender: { + { _id: '2', firstName: 'Test', lastName: 'User', email: 'test@example.com', image: '', }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + { + _id: 'ujhgtrdtyuiop', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', }, - ], - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, - { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@example.com', - image: '', + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', }, - ], - }, - }, - }, - }, - { - request: { - query: DIRECT_CHAT_BY_ID, - variables: { - id: '2', - }, - }, - result: { - data: { - directChatById: { - _id: '65844efc814dd4003db811c4', - createdAt: '2345678903456', - messages: [ - { - _id: '345678', - createdAt: '345678908765', - messageContent: 'Hello', - receiver: { + createdAt: '2345678903456', + name: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + replyTo: null, + type: 'STRING', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { _id: '1', firstName: 'Disha', lastName: 'Talreja', email: 'disha@example.com', image: '', }, - sender: { + { _id: '2', firstName: 'Test', lastName: 'User', email: 'test@example.com', image: '', }, - }, - ], - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, - { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@example.com', - image: '', - }, - ], - }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + ], }, }, }, { request: { - query: DIRECT_CHAT_BY_ID, + query: CHATS_LIST, variables: { - id: null, + id: '1', }, }, result: { data: { - directChatById: { - _id: '65844efc814dd4003db811c4', - createdAt: '2345678903456', - messages: [ - { - _id: '345678', - createdAt: '345678908765', - messageContent: 'Hello', - receiver: { + chatsByUserId: [ + { + _id: '65844efc814dhjmkdftyd4003db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', + }, + createdAt: '2345678903456', + name: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + replyTo: null, + type: 'STRING', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { _id: '1', firstName: 'Disha', lastName: 'Talreja', email: 'disha@example.com', image: '', }, - sender: { + { _id: '2', firstName: 'Test', lastName: 'User', email: 'test@example.com', image: '', }, - }, - ], - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, - { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@example.com', - image: '', - }, - ], - }, - }, - }, - }, -]; - -const GROUP_CHAT_BY_ID_QUERY_MOCK = [ - { - request: { - query: GROUP_CHAT_BY_ID, - variables: { - id: '1', - }, - }, - result: { - data: { - groupChatById: { - _id: '65844efc814dd4003db811c4', - createdAt: '2345678903456', - title: 'Test Group Chat', - messages: [ - { - _id: '345678', - createdAt: '345678908765', - messageContent: 'Hello', - sender: { - _id: '2', + { + _id: '3', firstName: 'Test', - lastName: 'User', - email: 'test@example.com', + lastName: 'User1', + email: 'test1@example.com', image: '', }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + { + _id: '65844ewsedrffc814dd4003db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', }, - ], - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, - { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@example.com', - image: '', - }, - { - _id: '3', - firstName: 'Test', - lastName: 'User1', - email: 'test1@example.com', - image: '', - }, - { - _id: '4', - firstName: 'Test', - lastName: 'User2', - email: 'test2@example.com', - image: '', - }, - { - _id: '5', - firstName: 'Test', - lastName: 'User4', - email: 'test4@example.com', - image: '', + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', }, - ], - }, + createdAt: '2345678903456', + name: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + replyTo: null, + type: 'STRING', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + ], }, }, }, { request: { - query: GROUP_CHAT_BY_ID, + query: CHATS_LIST, variables: { id: '1', }, }, result: { data: { - groupChatById: { - _id: '65844efc814dd4003db811c4', - createdAt: '2345678903456', - title: 'Test Group Chat', - messages: [ - { - _id: '345678', - createdAt: '345678908765', - messageContent: 'Hello', - sender: { + chatsByUserId: [ + { + _id: '65844efc814dhjmkdftyd4003db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', + }, + createdAt: '2345678903456', + name: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + replyTo: null, + type: 'STRING', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { _id: '2', firstName: 'Test', lastName: 'User', email: 'test@example.com', image: '', }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + { + _id: '65844ewsedrffc814dd4003db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', }, - ], - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, - { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@example.com', - image: '', - }, - { - _id: '3', - firstName: 'Test', - lastName: 'User1', - email: 'test1@example.com', - image: '', - }, - { - _id: '4', - firstName: 'Test', - lastName: 'User2', - email: 'test2@example.com', - image: '', - }, - { - _id: '5', - firstName: 'Test', - lastName: 'User4', - email: 'test4@example.com', - image: '', + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', }, - ], - }, - }, - }, - }, - { - request: { - query: GROUP_CHAT_BY_ID, - variables: { - id: '', - }, - }, - result: { - data: { - groupChatById: { - _id: '1', - createdAt: '2345678903456', - title: 'Test Group Chat', - messages: [ - { - _id: '345678', - createdAt: '345678908765', - messageContent: 'Hello', - sender: { + createdAt: '2345678903456', + name: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + replyTo: null, + type: 'STRING', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { _id: '2', firstName: 'Test', lastName: 'User', email: 'test@example.com', image: '', }, - }, - ], - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, - { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@example.com', - image: '', - }, - { - _id: '3', - firstName: 'Test', - lastName: 'User1', - email: 'test1@example.com', - image: '', - }, - { - _id: '4', - firstName: 'Test', - lastName: 'User2', - email: 'test2@example.com', - image: '', - }, - { - _id: '5', - firstName: 'Test', - lastName: 'User4', - email: 'test4@example.com', - image: '', - }, - ], - }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + ], }, }, }, +]; + +const GROUP_CHAT_BY_ID_QUERY_MOCK = [ { request: { - query: GROUP_CHAT_BY_ID, + query: CHAT_BY_ID, variables: { - id: '2', + id: '', }, }, result: { data: { - groupChatById: { + chatById: { _id: '65844efc814dd4003db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', + }, createdAt: '2345678903456', - title: 'Test Group Chat', + name: 'Test Group Chat', messages: [ { _id: '345678', createdAt: '345678908765', messageContent: 'Hello', + replyTo: null, + type: 'STRING', sender: { _id: '2', firstName: 'Test', @@ -1994,24 +1304,42 @@ const GROUP_CHAT_BY_ID_QUERY_MOCK = [ }, }, }, +]; + +const CREATE_CHAT_MUTATION_MOCK = [ { request: { - query: GROUP_CHAT_BY_ID, + query: CREATE_CHAT, variables: { - id: null, + organizationId: undefined, + userIds: ['1', '6589389d2caa9d8d69087487'], + isGroup: false, }, }, result: { data: { - groupChatById: { - _id: '65844efc814dd4003db811c4', + createChat: { + _id: '1', createdAt: '2345678903456', - title: 'Test Group Chat', + isGroup: false, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: null, + name: '', messages: [ { _id: '345678', createdAt: '345678908765', messageContent: 'Hello', + replyTo: null, + type: 'STRING', sender: { _id: '2', firstName: 'Test', @@ -2036,27 +1364,6 @@ const GROUP_CHAT_BY_ID_QUERY_MOCK = [ email: 'test@example.com', image: '', }, - { - _id: '3', - firstName: 'Test', - lastName: 'User1', - email: 'test1@example.com', - image: '', - }, - { - _id: '4', - firstName: 'Test', - lastName: 'User2', - email: 'test2@example.com', - image: '', - }, - { - _id: '5', - firstName: 'Test', - lastName: 'User4', - email: 'test4@example.com', - image: '', - }, ], }, }, @@ -2064,24 +1371,6 @@ const GROUP_CHAT_BY_ID_QUERY_MOCK = [ }, ]; -const CREATE_DIRECT_CHAT_MOCK = { - request: { - query: CREATE_DIRECT_CHAT, - variables: { - userIds: ['1', '6589389d2caa9d8d69087487'], - organizationId: undefined, - }, - }, - result: { - data: { - createDirectChat: { - _id: '669394c180e96b740ba1c0ce', - __typename: 'DirectChat', - }, - }, - }, -}; - async function wait(ms = 100): Promise { await act(() => { return new Promise((resolve) => { @@ -2107,14 +1396,14 @@ describe('Testing Create Direct Chat Modal [User Portal]', () => { })), }); - test('open and close create new direct chat modal', async () => { + test('Open and close create new direct chat modal', async () => { const mock = [ ...GROUP_CHAT_BY_ID_QUERY_MOCK, - ...DIRECT_CHAT_BY_ID_QUERY_MOCK, - ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, - ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ...MESSAGE_SENT_TO_CHAT_MOCK, ...UserConnectionListMock, - ...MOCKS, + ...CHATS_LIST_MOCK, + ...CHAT_BY_ID_QUERY_MOCK, + ...CREATE_CHAT_MUTATION_MOCK, ]; render( @@ -2160,13 +1449,12 @@ describe('Testing Create Direct Chat Modal [User Portal]', () => { test('create new direct chat', async () => { setItem('userId', '1'); const mock = [ - CREATE_DIRECT_CHAT_MOCK, ...GROUP_CHAT_BY_ID_QUERY_MOCK, - ...DIRECT_CHAT_BY_ID_QUERY_MOCK, - ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, - ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ...MESSAGE_SENT_TO_CHAT_MOCK, ...UserConnectionListMock, - ...MOCKS, + ...CHATS_LIST_MOCK, + ...CHAT_BY_ID_QUERY_MOCK, + ...CREATE_CHAT_MUTATION_MOCK, ]; render( @@ -2200,5 +1488,9 @@ describe('Testing Create Direct Chat Modal [User Portal]', () => { expect(closeButton).toBeInTheDocument(); fireEvent.click(closeButton); + + await new Promise(process.nextTick); + + await wait(); }); }); diff --git a/src/components/UserPortal/CreateDirectChat/CreateDirectChat.tsx b/src/components/UserPortal/CreateDirectChat/CreateDirectChat.tsx index 2f16dd4b0f..24c853fcdd 100644 --- a/src/components/UserPortal/CreateDirectChat/CreateDirectChat.tsx +++ b/src/components/UserPortal/CreateDirectChat/CreateDirectChat.tsx @@ -5,7 +5,7 @@ import styles from './CreateDirectChat.module.css'; import type { ApolloQueryResult } from '@apollo/client'; import { useMutation, useQuery } from '@apollo/client'; import useLocalStorage from 'utils/useLocalstorage'; -import { CREATE_DIRECT_CHAT } from 'GraphQl/Mutations/OrganizationMutations'; +import { CREATE_CHAT } from 'GraphQl/Mutations/OrganizationMutations'; import Table from '@mui/material/Table'; import TableCell, { tableCellClasses } from '@mui/material/TableCell'; import TableContainer from '@mui/material/TableContainer'; @@ -16,33 +16,24 @@ import type { InterfaceQueryUserListItem } from 'utils/interfaces'; import { USERS_CONNECTION_LIST } from 'GraphQl/Queries/Queries'; import Loader from 'components/Loader/Loader'; import { Search } from '@mui/icons-material'; -import { useTranslation } from 'react-i18next'; import { useParams } from 'react-router-dom'; -/** - * Props for the CreateDirectChat component. - */ interface InterfaceCreateDirectChatProps { toggleCreateDirectChatModal: () => void; createDirectChatModalisOpen: boolean; - /** - * Function to refetch the contact list. - * - * @param variables - Optional variables to filter the contact list. - * @returns Promise with ApolloQueryResult. - */ - contactRefetch: ( + chatsListRefetch: ( variables?: | Partial<{ - id: any; + id: string; }> | undefined, - ) => Promise>; + ) => Promise>; } /** * Styled table cell with custom styles. */ + const StyledTableCell = styled(TableCell)(({ theme }) => ({ [`&.${tableCellClasses.head}`]: { backgroundColor: ['#31bb6b', '!important'], @@ -56,6 +47,7 @@ const StyledTableCell = styled(TableCell)(({ theme }) => ({ /** * Styled table row with custom styles. */ + const StyledTableRow = styled(TableRow)(() => ({ '&:last-child td, &:last-child th': { border: 0, @@ -64,44 +56,28 @@ const StyledTableRow = styled(TableRow)(() => ({ const { getItem } = useLocalStorage(); -/** - * Component for creating a direct chat with a selected user. - * - * @param props - The props for the CreateDirectChat component. - * @returns JSX.Element - */ -export default function groupChat({ +export default function createDirectChatModal({ toggleCreateDirectChatModal, createDirectChatModalisOpen, - contactRefetch, + chatsListRefetch, }: InterfaceCreateDirectChatProps): JSX.Element { - const { t } = useTranslation('translation', { - keyPrefix: 'userChat', - }); - const { orgId: organizationId } = useParams(); const userId: string | null = getItem('userId'); const [userName, setUserName] = useState(''); - const [createDirectChat] = useMutation(CREATE_DIRECT_CHAT); + const [createChat] = useMutation(CREATE_CHAT); - /** - * Handles the creation of a direct chat with a selected user. - * - * @param id - The ID of the user to start a direct chat with. - * @returns Promise - */ const handleCreateDirectChat = async (id: string): Promise => { - console.log(organizationId); - await createDirectChat({ + await createChat({ variables: { organizationId, userIds: [userId, id], + isGroup: false, }, }); - contactRefetch(); + await chatsListRefetch(); toggleCreateDirectChatModal(); }; @@ -116,12 +92,6 @@ export default function groupChat({ }, }); - /** - * Handles changes in the user search input and refetches the user list. - * - * @param e - The form event. - * @returns void - */ const handleUserModalSearchChange = (e: React.FormEvent): void => { e.preventDefault(); /* istanbul ignore next */ diff --git a/src/components/UserPortal/CreateGroupChat/CreateGroupChat.test.tsx b/src/components/UserPortal/CreateGroupChat/CreateGroupChat.test.tsx index 77447dc29c..055985d5fb 100644 --- a/src/components/UserPortal/CreateGroupChat/CreateGroupChat.test.tsx +++ b/src/components/UserPortal/CreateGroupChat/CreateGroupChat.test.tsx @@ -5,12 +5,12 @@ import { render, screen, waitFor, + within, } from '@testing-library/react'; import { MockedProvider } from '@apollo/react-testing'; import { I18nextProvider } from 'react-i18next'; import { - DIRECT_CHATS_LIST, USERS_CONNECTION_LIST, USER_JOINED_ORGANIZATIONS, } from 'GraphQl/Queries/Queries'; @@ -18,915 +18,175 @@ import { BrowserRouter } from 'react-router-dom'; import { Provider } from 'react-redux'; import { store } from 'state/store'; import i18nForTest from 'utils/i18nForTest'; -import { StaticMockLink } from 'utils/StaticMockLink'; import Chat from '../../../screens/UserPortal/Chat/Chat'; import { - CREATE_GROUP_CHAT, - MESSAGE_SENT_TO_DIRECT_CHAT, - MESSAGE_SENT_TO_GROUP_CHAT, + CREATE_CHAT, + MESSAGE_SENT_TO_CHAT, } from 'GraphQl/Mutations/OrganizationMutations'; -import { - DIRECT_CHAT_BY_ID, - GROUP_CHAT_BY_ID, - GROUP_CHAT_LIST, -} from 'GraphQl/Queries/PlugInQueries'; +import { CHATS_LIST, CHAT_BY_ID } from 'GraphQl/Queries/PlugInQueries'; import useLocalStorage from 'utils/useLocalstorage'; +import userEvent from '@testing-library/user-event'; const { setItem } = useLocalStorage(); -const MOCKS = [ - { - request: { - query: GROUP_CHAT_LIST, - variables: { - id: null, - }, - }, - result: { - data: { - groupChatsByUserId: [ - { - _id: '1', - creator: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - }, - messages: { - _id: '1', - createdAt: '', - messageContent: 'Hello', - sender: { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@email.com', - }, - }, - title: 'Test GroupChat', - organization: { - _id: '1', - name: 'Test Org', - }, - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@email.com', - image: 'img', - }, - ], - }, - { - _id: '2', - creator: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - }, - messages: { - _id: '1', - createdAt: '', - messageContent: 'Hello', - sender: { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@email.com', - }, - }, - title: 'Test GroupChat', - organization: { - _id: '1', - name: 'Test Org', - }, - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@email.com', - image: 'img', - }, - ], - }, - ], - }, - }, - }, +const USER_JOINED_ORG_MOCK = [ { request: { - query: GROUP_CHAT_LIST, + query: USER_JOINED_ORGANIZATIONS, variables: { id: '1', }, }, result: { data: { - groupChatsByUserId: [ - { - _id: '1', - creator: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - }, - messages: { - _id: '1', - createdAt: '', - messageContent: 'Hello', - sender: { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@email.com', - }, - }, - title: 'Test GroupChat', - organization: { - _id: '1', - name: 'Test Org', - }, - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@email.com', - image: 'img', - }, - ], - }, - { - _id: '2', - creator: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - }, - messages: { - _id: '1', - createdAt: '', - messageContent: 'Hello', - sender: { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@email.com', - }, - }, - title: 'Test GroupChat', - organization: { - _id: '1', - name: 'Test Org', - }, - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@email.com', - image: 'img', - }, - ], - }, - ], - }, - }, - }, - { - request: { - query: GROUP_CHAT_LIST, - variables: { - id: null, - }, - }, - result: { - data: { - groupChatsByUserId: [ - { - _id: '1', - creator: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - }, - messages: { - _id: '1', - createdAt: '', - messageContent: 'Hello', - sender: { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@email.com', - }, - }, - title: 'Test GroupChat', - organization: { - _id: '1', - name: 'Test Org', - }, - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@email.com', - image: 'img', - }, - ], - }, - { - _id: '2', - creator: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - }, - messages: { - _id: '1', - createdAt: '', - messageContent: 'Hello', - sender: { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@email.com', - }, - }, - title: 'Test GroupChat', - organization: { - _id: '1', - name: 'Test Org', - }, - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@email.com', - image: 'img', - }, - ], - }, - ], - }, - }, - }, - { - request: { - query: DIRECT_CHATS_LIST, - variables: { - id: null, - }, - }, - result: { - data: { - directChatsByUserID: [ + users: [ { - _id: '666c88dd92e995354d98527c', - creator: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - __typename: 'User', - }, - messages: [ - { - _id: '668930bae43ce54e6e302cf1', - createdAt: '2024-07-06T11:55:38.933Z', - messageContent: 'hJnkank', - receiver: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - __typename: 'User', + user: { + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + name: 'Test Org 1', + image: '', + description: 'New Desc', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + createdAt: '1234567890', + userRegistrationRequired: true, + creator: { + __typename: 'User', + firstName: 'John', + lastName: 'Doe', + }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - __typename: 'User', - }, - __typename: 'DirectChatMessage', - }, - ], - organization: { - _id: '6737904485008f171cf29924', - name: 'Unity Foundation', - __typename: 'Organization', - }, - users: [ - { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - image: null, - __typename: 'User', - }, - { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - image: null, - __typename: 'User', - }, - ], - __typename: 'DirectChat', - }, - { - _id: '666f09c892e995354d98a5ee', - creator: { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - __typename: 'User', - }, - messages: [ - { - _id: '6676932692e995354d98ab7f', - createdAt: '2024-06-22T09:02:30.776Z', - messageContent: 'hii', - receiver: { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - __typename: 'User', - }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - __typename: 'User', - }, - __typename: 'DirectChatMessage', - }, - ], - organization: { - _id: '6737904485008f171cf29924', - name: 'Unity Foundation', - __typename: 'Organization', - }, - users: [ - { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - image: null, - __typename: 'User', - }, - { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - image: null, - __typename: 'User', - }, - ], - __typename: 'DirectChat', - }, - ], - }, - }, - }, - { - request: { - query: DIRECT_CHATS_LIST, - variables: { - id: '1', - }, - }, - result: { - data: { - directChatsByUserID: [ - { - _id: '666c88dd92e995354d98527c', - creator: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - __typename: 'User', - }, - messages: [ - { - _id: '668930bae43ce54e6e302cf1', - createdAt: '2024-07-06T11:55:38.933Z', - messageContent: 'hJnkank', - receiver: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - __typename: 'User', - }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - __typename: 'User', - }, - __typename: 'DirectChatMessage', - }, - ], - organization: { - _id: '6737904485008f171cf29924', - name: 'Unity Foundation', - __typename: 'Organization', - }, - users: [ - { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - image: null, - __typename: 'User', - }, - { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - image: null, - __typename: 'User', - }, - ], - __typename: 'DirectChat', - }, - { - _id: '666f09c892e995354d98a5ee', - creator: { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - __typename: 'User', - }, - messages: [ - { - _id: '6676932692e995354d98ab7f', - createdAt: '2024-06-22T09:02:30.776Z', - messageContent: 'hii', - receiver: { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - __typename: 'User', - }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - __typename: 'User', - }, - __typename: 'DirectChatMessage', - }, - ], - organization: { - _id: '6737904485008f171cf29924', - name: 'Unity Foundation', - __typename: 'Organization', - }, - users: [ - { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - image: null, - __typename: 'User', - }, - { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - image: null, - __typename: 'User', - }, - ], - __typename: 'DirectChat', - }, - ], - }, - }, - }, - { - request: { - query: DIRECT_CHATS_LIST, - variables: { - id: '1', - }, - }, - result: { - data: { - directChatsByUserID: [ - { - _id: '666c88dd92e995354d98527c', - creator: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - __typename: 'User', - }, - messages: [ - { - _id: '668930bae43ce54e6e302cf1', - createdAt: '2024-07-06T11:55:38.933Z', - messageContent: 'hJnkank', - receiver: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - __typename: 'User', - }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - __typename: 'User', - }, - __typename: 'DirectChatMessage', - }, - ], - organization: { - _id: '6737904485008f171cf29924', - name: 'Unity Foundation', - __typename: 'Organization', - }, - users: [ - { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - image: null, - __typename: 'User', - }, - { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - image: null, - __typename: 'User', - }, - ], - __typename: 'DirectChat', - }, - { - _id: '666f09c892e995354d98a5ee', - creator: { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - __typename: 'User', - }, - messages: [ - { - _id: '6676932692e995354d98ab7f', - createdAt: '2024-06-22T09:02:30.776Z', - messageContent: 'hii', - receiver: { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - __typename: 'User', - }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - __typename: 'User', - }, - __typename: 'DirectChatMessage', - }, - ], - organization: { - _id: '6737904485008f171cf29924', - name: 'Unity Foundation', - __typename: 'Organization', - }, - users: [ - { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - image: null, - __typename: 'User', - }, - { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - image: null, - __typename: 'User', - }, - ], - __typename: 'DirectChat', - }, - ], - }, - }, - }, - { - request: { - query: DIRECT_CHATS_LIST, - variables: { - id: '1', - }, - }, - result: { - data: { - directChatsByUserID: [ - { - _id: '666c88dd92e995354d98527c', - creator: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - __typename: 'User', - }, - messages: [ - { - _id: '668930bae43ce54e6e302cf1', - createdAt: '2024-07-06T11:55:38.933Z', - messageContent: 'hJnkank', - receiver: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - __typename: 'User', - }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - __typename: 'User', - }, - __typename: 'DirectChatMessage', - }, - ], - organization: { - _id: '6737904485008f171cf29924', - name: 'Unity Foundation', - __typename: 'Organization', - }, - users: [ - { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - image: null, - __typename: 'User', - }, - { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - image: null, - __typename: 'User', - }, - ], - __typename: 'DirectChat', - }, - { - _id: '666f09c892e995354d98a5ee', - creator: { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - __typename: 'User', - }, - messages: [ - { - _id: '6676932692e995354d98ab7f', - createdAt: '2024-06-22T09:02:30.776Z', - messageContent: 'hii', - receiver: { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - __typename: 'User', - }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - __typename: 'User', - }, - __typename: 'DirectChatMessage', - }, - ], - organization: { - _id: '6737904485008f171cf29924', - name: 'Unity Foundation', - __typename: 'Organization', - }, - users: [ - { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - image: null, - __typename: 'User', - }, - { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - image: null, - __typename: 'User', - }, - ], - __typename: 'DirectChat', - }, - ], - }, - }, - }, - { - request: { - query: DIRECT_CHATS_LIST, - variables: { - id: '', - }, - }, - result: { - data: { - directChatsByUserID: [ - { - _id: '666c88dd92e995354d98527c', - creator: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - __typename: 'User', - }, - messages: [ - { - _id: '668930bae43ce54e6e302cf1', - createdAt: '2024-07-06T11:55:38.933Z', - messageContent: 'hJnkank', - receiver: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - __typename: 'User', - }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - __typename: 'User', - }, - __typename: 'DirectChatMessage', - }, - ], - organization: { - _id: '6737904485008f171cf29924', - name: 'Unity Foundation', - __typename: 'Organization', - }, - users: [ - { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - image: null, - __typename: 'User', - }, - { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - image: null, - __typename: 'User', - }, - ], - __typename: 'DirectChat', - }, - { - _id: '666f09c892e995354d98a5ee', - creator: { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - __typename: 'User', - }, - messages: [ - { - _id: '6676932692e995354d98ab7f', - createdAt: '2024-06-22T09:02:30.776Z', - messageContent: 'hii', - receiver: { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - __typename: 'User', + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + name: 'Test Org 1', + image: '', + description: 'New Desc', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + createdAt: '1234567890', + userRegistrationRequired: true, + creator: { + __typename: 'User', + firstName: 'John', + lastName: 'Doe', + }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - __typename: 'User', + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + name: 'Test Org 1', + image: '', + description: 'New Desc', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + createdAt: '1234567890', + userRegistrationRequired: true, + creator: { + __typename: 'User', + firstName: 'John', + lastName: 'Doe', + }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], }, - __typename: 'DirectChatMessage', - }, - ], - organization: { - _id: '6737904485008f171cf29924', - name: 'Unity Foundation', - __typename: 'Organization', - }, - users: [ - { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - image: null, - __typename: 'User', - }, - { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - image: null, - __typename: 'User', - }, - ], - __typename: 'DirectChat', - }, - ], - }, - }, - }, -]; - -const USER_JOINED_ORG_MOCK = [ - { - request: { - query: USER_JOINED_ORGANIZATIONS, - variables: { - id: '1', - }, - }, - result: { - data: { - users: [ - { - user: { - joinedOrganizations: [ { __typename: 'Organization', _id: '6401ff65ce8e8406b8f07af2', @@ -998,6 +258,54 @@ const USER_JOINED_ORG_MOCK = [ { __typename: 'Organization', _id: '6401ff65ce8e8406b8f07af2', + name: 'Test org', + image: '', + description: 'New Desc', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + createdAt: '1234567890', + userRegistrationRequired: true, + creator: { + __typename: 'User', + firstName: 'John', + lastName: 'Doe', + }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + }, + { + __typename: 'Organization', + _id: 'qsxhgjhbmnbkhlk,njgjfhgv', name: 'Any Organization', image: '', description: 'New Desc', @@ -1065,7 +373,55 @@ const USER_JOINED_ORG_MOCK = [ joinedOrganizations: [ { __typename: 'Organization', - _id: '6401ff65ce8e8406b8f07af2', + _id: '6401ff65ce8e8406b8fhgjhnm07af2', + name: 'Test org', + image: '', + description: 'New Desc', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + createdAt: '1234567890', + userRegistrationRequired: true, + creator: { + __typename: 'User', + firstName: 'John', + lastName: 'Doe', + }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + }, + { + __typename: 'Organization', + _id: '6401ff65ce8egfhbn8406b8f07af2', name: 'Any Organization', image: '', description: 'New Desc', @@ -1133,7 +489,55 @@ const USER_JOINED_ORG_MOCK = [ joinedOrganizations: [ { __typename: 'Organization', - _id: '6401ff65ce8e8406b8f07af2', + _id: '6401ff65fghce8e8406b8f07af2', + name: 'Test org', + image: '', + description: 'New Desc', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + createdAt: '1234567890', + userRegistrationRequired: true, + creator: { + __typename: 'User', + firstName: 'John', + lastName: 'Doe', + }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + }, + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8jygjgf07af2', name: 'Any Organization', image: '', description: 'New Desc', @@ -1199,6 +603,54 @@ const USER_JOINED_ORG_MOCK = [ { user: { joinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65cehgh8e8406b8f07af2', + name: 'Test org', + image: '', + description: 'New Desc', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + createdAt: '1234567890', + userRegistrationRequired: true, + creator: { + __typename: 'User', + firstName: 'John', + lastName: 'Doe', + }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + }, { __typename: 'Organization', _id: '6401ff65ce8e8406b8f07af2', @@ -1269,7 +721,55 @@ const USER_JOINED_ORG_MOCK = [ joinedOrganizations: [ { __typename: 'Organization', - _id: '6401ff65ce8e8406b8f07af2', + _id: '6401ff65ce8e8406nbmnmb8f07af2', + name: 'Test org', + image: '', + description: 'New Desc', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + createdAt: '1234567890', + userRegistrationRequired: true, + creator: { + __typename: 'User', + firstName: 'John', + lastName: 'Doe', + }, + members: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + admins: [ + { + _id: '45gj5678jk45678fvgbhnr4rtgh', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + membershipRequests: [ + { + _id: '56gheqyr7deyfuiwfewifruy8', + user: { + _id: '45ydeg2yet721rtgdu32ry', + }, + }, + ], + }, + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8fnnmm07af2', name: 'Any Organization', image: '', description: 'New Desc', @@ -1472,6 +972,83 @@ const UserConnectionListMock = [ }, }, }, + { + request: { + query: USERS_CONNECTION_LIST, + variables: { + firstName_contains: '', + lastName_contains: '', + }, + }, + result: { + data: { + users: { + user: [ + { + firstName: 'Disha', + lastName: 'Talreja', + image: 'img', + _id: '1', + email: 'disha@email.com', + createdAt: '', + appUserProfile: { + _id: '12', + isSuperAdmin: 'false', + createdOrganizations: { + _id: '345678', + }, + createdEvents: { + _id: '34567890', + }, + }, + organizationsBlockedBy: [], + joinedOrganizations: [], + }, + { + firstName: 'Disha', + lastName: 'Talreja', + image: 'img', + _id: '1', + email: 'disha@email.com', + createdAt: '', + appUserProfile: { + _id: '12', + isSuperAdmin: 'false', + createdOrganizations: { + _id: '345678', + }, + createdEvents: { + _id: '34567890', + }, + }, + organizationsBlockedBy: [], + joinedOrganizations: [], + }, + { + firstName: 'Disha', + lastName: 'Talreja', + image: 'img', + _id: '1', + email: 'disha@email.com', + createdAt: '', + appUserProfile: { + _id: '12', + isSuperAdmin: 'false', + createdOrganizations: { + _id: '345678', + }, + createdEvents: { + _id: '34567890', + }, + }, + organizationsBlockedBy: [], + joinedOrganizations: [], + }, + ], + }, + }, + }, + }, { request: { query: USERS_CONNECTION_LIST, @@ -1597,202 +1174,46 @@ const UserConnectionListMock = [ image: null, email: 'testsuperadmin@example.com', createdAt: '2023-04-13T04:53:17.742Z', - __typename: 'User', - }, - __typename: 'Organization', - }, - ], - __typename: 'User', - }, - appUserProfile: { - _id: '64378abd85308f171cf2993d', - adminFor: [], - isSuperAdmin: false, - createdOrganizations: [], - createdEvents: [], - eventAdmin: [], - __typename: 'AppUserProfile', - }, - __typename: 'UserData', - }, - ], - }, - }, - }, - { - request: { - query: USERS_CONNECTION_LIST, - variables: { - firstName_contains: '', - lastName_contains: '', - }, - }, - result: { - data: { - users: { - user: [ - { - firstName: 'Disha', - lastName: 'Talreja', - image: 'img', - _id: '1', - email: 'disha@email.com', - createdAt: '', - appUserProfile: { - _id: '12', - isSuperAdmin: 'false', - createdOrganizations: { - _id: '345678', - }, - createdEvents: { - _id: '34567890', - }, - }, - organizationsBlockedBy: [], - joinedOrganizations: [], - }, - { - firstName: 'Disha', - lastName: 'Talreja', - image: 'img', - _id: '2', - email: 'disha@email.com', - createdAt: '', - appUserProfile: { - _id: '12', - isSuperAdmin: 'false', - createdOrganizations: { - _id: '345678', - }, - createdEvents: { - _id: '34567890', - }, - }, - organizationsBlockedBy: [], - joinedOrganizations: [], - }, - { - firstName: 'Disha', - lastName: 'Talreja', - image: 'img', - _id: '3', - email: 'disha@email.com', - createdAt: '', - appUserProfile: { - _id: '12', - isSuperAdmin: 'false', - createdOrganizations: { - _id: '345678', - }, - createdEvents: { - _id: '34567890', - }, - }, - organizationsBlockedBy: [], - joinedOrganizations: [], - }, - ], - }, - }, - }, - }, -]; - -const MESSAGE_SENT_TO_GROUP_CHAT_MOCK = [ - { - request: { - query: MESSAGE_SENT_TO_GROUP_CHAT, - variables: { - userId: null, - }, - }, - result: { - data: { - messageSentToGroupChat: { - _id: '668ec1f1364e03ac47a151', - createdAt: '2024-07-10T17:16:33.248Z', - messageContent: 'Test ', - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - image: '', - }, - updatedAt: '2024-07-10', - }, - }, - }, - }, - { - request: { - query: MESSAGE_SENT_TO_GROUP_CHAT, - variables: { - userId: '2', - }, - }, - result: { - data: { - messageSentToGroupChat: { - _id: '668ec1f1df364e03ac47a151', - createdAt: '2024-07-10T17:16:33.248Z', - messageContent: 'Test ', - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - image: '', - }, - updatedAt: '2024-07-10', - }, - }, - }, - }, - { - request: { - query: MESSAGE_SENT_TO_GROUP_CHAT, - variables: { - userId: '1', - }, - }, - result: { - data: { - messageSentToGroupChat: { - _id: '668ec1f13603ac4697a151', - createdAt: '2024-07-10T17:16:33.248Z', - messageContent: 'Test ', - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - image: '', + __typename: 'User', + }, + __typename: 'Organization', + }, + ], + __typename: 'User', + }, + appUserProfile: { + _id: '64378abd85308f171cf2993d', + adminFor: [], + isSuperAdmin: false, + createdOrganizations: [], + createdEvents: [], + eventAdmin: [], + __typename: 'AppUserProfile', + }, + __typename: 'UserData', }, - updatedAt: '2024-07-10', - }, + ], }, }, }, ]; -const MESSAGE_SENT_TO_DIRECT_CHAT_MOCK = [ +const MESSAGE_SENT_TO_CHAT_MOCK = [ { request: { - query: MESSAGE_SENT_TO_DIRECT_CHAT, + query: MESSAGE_SENT_TO_CHAT, variables: { - userId: '1', + userId: null, }, }, result: { data: { - messageSentToDirectChat: { - _id: '668ec1f1364e03ac4697a151', + messageSentToChat: { + _id: '668ec1f1364e03ac47a151', createdAt: '2024-07-10T17:16:33.248Z', messageContent: 'Test ', - receiver: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - image: '', - }, + type: 'STRING', + replyTo: null, sender: { _id: '64378abd85008f171cf2990d', firstName: 'Wilt', @@ -1806,23 +1227,19 @@ const MESSAGE_SENT_TO_DIRECT_CHAT_MOCK = [ }, { request: { - query: MESSAGE_SENT_TO_DIRECT_CHAT, + query: MESSAGE_SENT_TO_CHAT, variables: { userId: '2', }, }, result: { data: { - messageSentToDirectChat: { - _id: '668ec1f1364e03ac4697vgfa151', + messageSentToChat: { + _id: '668ec1f1df364e03ac47a151', createdAt: '2024-07-10T17:16:33.248Z', messageContent: 'Test ', - receiver: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - image: '', - }, + replyTo: null, + type: 'STRING', sender: { _id: '64378abd85008f171cf2990d', firstName: 'Wilt', @@ -1836,23 +1253,19 @@ const MESSAGE_SENT_TO_DIRECT_CHAT_MOCK = [ }, { request: { - query: MESSAGE_SENT_TO_DIRECT_CHAT, + query: MESSAGE_SENT_TO_CHAT, variables: { - userId: null, + userId: '1', }, }, result: { data: { - messageSentToDirectChat: { - _id: '6ec1f1364e03ac4697a151', + messageSentToChat: { + _id: '668ec1f13603ac4697a151', createdAt: '2024-07-10T17:16:33.248Z', messageContent: 'Test ', - receiver: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - image: '', - }, + replyTo: null, + type: 'STRING', sender: { _id: '64378abd85008f171cf2990d', firstName: 'Wilt', @@ -1866,31 +1279,38 @@ const MESSAGE_SENT_TO_DIRECT_CHAT_MOCK = [ }, ]; -const DIRECT_CHAT_BY_ID_QUERY_MOCK = [ +const CHAT_BY_ID_QUERY_MOCK = [ { request: { - query: DIRECT_CHAT_BY_ID, + query: CHAT_BY_ID, variables: { id: '1', }, }, result: { data: { - directChatById: { + chatById: { _id: '1', createdAt: '2345678903456', + isGroup: false, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: null, + name: '', messages: [ { _id: '345678', createdAt: '345678908765', messageContent: 'Hello', - receiver: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, + replyTo: null, + type: 'STRING', sender: { _id: '2', firstName: 'Test', @@ -1922,28 +1342,35 @@ const DIRECT_CHAT_BY_ID_QUERY_MOCK = [ }, { request: { - query: DIRECT_CHAT_BY_ID, + query: CHAT_BY_ID, variables: { id: '1', }, }, result: { data: { - directChatById: { + chatById: { _id: '1', + isGroup: false, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: null, + name: '', createdAt: '2345678903456', messages: [ { _id: '345678', createdAt: '345678908765', messageContent: 'Hello', - receiver: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, + replyTo: null, + type: 'STRING', sender: { _id: '2', firstName: 'Test', @@ -1975,28 +1402,35 @@ const DIRECT_CHAT_BY_ID_QUERY_MOCK = [ }, { request: { - query: DIRECT_CHAT_BY_ID, + query: CHAT_BY_ID, variables: { id: '', }, }, result: { data: { - directChatById: { + chatById: { _id: '1', + isGroup: false, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: null, + name: '', createdAt: '2345678903456', messages: [ { _id: '345678', createdAt: '345678908765', messageContent: 'Hello', - receiver: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, + replyTo: null, + type: 'STRING', sender: { _id: '2', firstName: 'Test', @@ -2026,269 +1460,520 @@ const DIRECT_CHAT_BY_ID_QUERY_MOCK = [ }, }, }, +]; + +const CHATS_LIST_MOCK = [ { request: { - query: DIRECT_CHAT_BY_ID, + query: CHATS_LIST, variables: { - id: '2', + id: null, }, }, result: { data: { - directChatById: { - _id: '65844efc814dd4003db811c4', - createdAt: '2345678903456', - messages: [ - { - _id: '345678', - createdAt: '345678908765', - messageContent: 'Hello', - receiver: { + chatsByUserId: [ + { + _id: '65844efc814dd40fgh03db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', + }, + createdAt: '2345678903456', + name: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + replyTo: null, + type: 'STRING', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { _id: '1', firstName: 'Disha', lastName: 'Talreja', email: 'disha@example.com', image: '', }, - sender: { + { _id: '2', firstName: 'Test', lastName: 'User', email: 'test@example.com', image: '', }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + { + _id: '65844efc814ddgh4003db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', }, - ], - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, - { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@example.com', - image: '', + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', }, - ], - }, + createdAt: '2345678903456', + name: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + replyTo: null, + type: 'STRING', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + ], }, }, }, { request: { - query: DIRECT_CHAT_BY_ID, + query: CHATS_LIST, variables: { - id: null, + id: '', }, }, result: { data: { - directChatById: { - _id: '65844efc814dd4003db811c4', - createdAt: '2345678903456', - messages: [ - { - _id: '345678', - createdAt: '345678908765', - messageContent: 'Hello', - receiver: { + chatsByUserId: [ + { + _id: '65844ghjefc814dd4003db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', + }, + createdAt: '2345678903456', + name: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + replyTo: null, + type: 'STRING', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { _id: '1', firstName: 'Disha', lastName: 'Talreja', email: 'disha@example.com', image: '', }, - sender: { + { _id: '2', firstName: 'Test', lastName: 'User', email: 'test@example.com', image: '', }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + { + _id: 'ujhgtrdtyuiop', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', }, - ], - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, - { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@example.com', - image: '', + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', }, - ], - }, - }, - }, - }, -]; - -const GROUP_CHAT_BY_ID_QUERY_MOCK = [ - { - request: { - query: GROUP_CHAT_BY_ID, - variables: { - id: '1', - }, - }, - result: { - data: { - groupChatById: { - _id: '65844efc814dd4003db811c4', - createdAt: '2345678903456', - title: 'Test Group Chat', - messages: [ - { - _id: '345678', - createdAt: '345678908765', - messageContent: 'Hello', - sender: { + createdAt: '2345678903456', + name: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + replyTo: null, + type: 'STRING', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { _id: '2', firstName: 'Test', lastName: 'User', email: 'test@example.com', image: '', }, - }, - ], - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, - { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@example.com', - image: '', - }, - { - _id: '3', - firstName: 'Test', - lastName: 'User1', - email: 'test1@example.com', - image: '', - }, - { - _id: '4', - firstName: 'Test', - lastName: 'User2', - email: 'test2@example.com', - image: '', - }, - { - _id: '5', - firstName: 'Test', - lastName: 'User4', - email: 'test4@example.com', - image: '', - }, - ], - }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + ], }, }, }, { request: { - query: GROUP_CHAT_BY_ID, + query: CHATS_LIST, variables: { id: '1', }, }, result: { data: { - groupChatById: { - _id: '65844efc814dd4003db811c4', - createdAt: '2345678903456', - title: 'Test Group Chat', - messages: [ - { - _id: '345678', - createdAt: '345678908765', - messageContent: 'Hello', - sender: { + chatsByUserId: [ + { + _id: '65844efc814dhjmkdftyd4003db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', + }, + createdAt: '2345678903456', + name: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + replyTo: null, + type: 'STRING', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { _id: '2', firstName: 'Test', lastName: 'User', email: 'test@example.com', image: '', }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + { + _id: '65844ewsedrffc814dd4003db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', }, - ], - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, - { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@example.com', - image: '', - }, - { - _id: '3', - firstName: 'Test', - lastName: 'User1', - email: 'test1@example.com', - image: '', - }, - { - _id: '4', - firstName: 'Test', - lastName: 'User2', - email: 'test2@example.com', - image: '', - }, - { - _id: '5', - firstName: 'Test', - lastName: 'User4', - email: 'test4@example.com', - image: '', + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', }, - ], - }, + createdAt: '2345678903456', + name: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + replyTo: null, + type: 'STRING', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + ], }, }, }, +]; + +const GROUP_CHAT_BY_ID_QUERY_MOCK = [ { request: { - query: GROUP_CHAT_BY_ID, + query: CHAT_BY_ID, variables: { id: '', }, }, result: { data: { - groupChatById: { - _id: '1', + chatById: { + _id: '65844efc814dd4003db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', + }, createdAt: '2345678903456', - title: 'Test Group Chat', + name: 'Test Group Chat', messages: [ { _id: '345678', createdAt: '345678908765', messageContent: 'Hello', + replyTo: null, + type: 'STRING', sender: { _id: '2', firstName: 'Test', @@ -2339,24 +2024,46 @@ const GROUP_CHAT_BY_ID_QUERY_MOCK = [ }, }, }, +]; + +const CREATE_CHAT_MUTATION = [ { request: { - query: GROUP_CHAT_BY_ID, + query: CREATE_CHAT, variables: { - id: '2', + organizationId: '6401ff65ce8e8406b8jygjgf07af2', + userIds: [null], + name: 'Test Group', + isGroup: true, }, }, result: { data: { - groupChatById: { + createChat: { _id: '65844efc814dd4003db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', + }, createdAt: '2345678903456', - title: 'Test Group Chat', + name: 'Test Group Chat', messages: [ { _id: '345678', createdAt: '345678908765', messageContent: 'Hello', + replyTo: null, + type: 'STRING', sender: { _id: '2', firstName: 'Test', @@ -2409,22 +2116,41 @@ const GROUP_CHAT_BY_ID_QUERY_MOCK = [ }, { request: { - query: GROUP_CHAT_BY_ID, + query: CREATE_CHAT, variables: { - id: null, + organizationId: '', + userIds: [null], + name: 'Test Group', + isGroup: true, }, }, result: { data: { - groupChatById: { + createChat: { _id: '65844efc814dd4003db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', + }, createdAt: '2345678903456', - title: 'Test Group Chat', + name: 'Test Group Chat', messages: [ { _id: '345678', createdAt: '345678908765', messageContent: 'Hello', + replyTo: null, + type: 'STRING', sender: { _id: '2', firstName: 'Test', @@ -2477,47 +2203,6 @@ const GROUP_CHAT_BY_ID_QUERY_MOCK = [ }, ]; -const CREATE_GROUP_CHAT_MOCK = [ - { - request: { - query: CREATE_GROUP_CHAT, - variables: { - organizationId: '6401ff65ce8e8406b8f07af2', - userIds: [null], - title: 'Test Group', - }, - }, - result: { - data: { - createGroupChat: { - _id: '669394c180e96b740ba1c0ce', - __typename: 'GroupChat', - }, - }, - }, - }, - { - request: { - query: CREATE_GROUP_CHAT, - variables: { - organizationId: '', - userIds: [null], - title: 'Test Group', - }, - }, - result: { - data: { - createGroupChat: { - _id: '669394c180e96b740ba1c0ce', - __typename: 'GroupChat', - }, - }, - }, - }, -]; - -const link = new StaticMockLink(MOCKS, true); - async function wait(ms = 100): Promise { await act(() => { return new Promise((resolve) => { @@ -2526,7 +2211,7 @@ async function wait(ms = 100): Promise { }); } -describe('Testing Create Direct Chat Modal [User Portal]', () => { +describe('Testing Create Group Chat Modal [User Portal]', () => { window.HTMLElement.prototype.scrollIntoView = jest.fn(); Object.defineProperty(window, 'matchMedia', { @@ -2547,11 +2232,12 @@ describe('Testing Create Direct Chat Modal [User Portal]', () => { const mock = [ ...USER_JOINED_ORG_MOCK, ...GROUP_CHAT_BY_ID_QUERY_MOCK, - ...DIRECT_CHAT_BY_ID_QUERY_MOCK, - ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, - ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ...MESSAGE_SENT_TO_CHAT_MOCK, + ...CHAT_BY_ID_QUERY_MOCK, + ...CHATS_LIST_MOCK, ...UserConnectionListMock, - ...MOCKS, + ...CREATE_CHAT_MUTATION, + ...CHATS_LIST_MOCK, ]; render( @@ -2582,14 +2268,14 @@ describe('Testing Create Direct Chat Modal [User Portal]', () => { test('create new group chat', async () => { const mock = [ - ...CREATE_GROUP_CHAT_MOCK, ...USER_JOINED_ORG_MOCK, ...GROUP_CHAT_BY_ID_QUERY_MOCK, - ...DIRECT_CHAT_BY_ID_QUERY_MOCK, - ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, - ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ...MESSAGE_SENT_TO_CHAT_MOCK, + ...CHAT_BY_ID_QUERY_MOCK, + ...CHATS_LIST_MOCK, ...UserConnectionListMock, - ...MOCKS, + ...CREATE_CHAT_MUTATION, + ...CHATS_LIST_MOCK, ]; render( @@ -2631,12 +2317,35 @@ describe('Testing Create Direct Chat Modal [User Portal]', () => { expect(groupTitleInput.value).toBe('Test Group'); }); - const orgSelect = screen.getByLabelText('Select Organization'); + const selectLabel = /select organization/i; + const orgSelect = await screen.findByLabelText('Select Organization'); + // console.log(prettyDOM(document)); + + // act(() => { + // fireEvent.change(orgSelect, { + // target: { value: '6401ff65ce8e8406b8f07af2' }, + // }); + // }) + // fireEvent.change(orgSelect, { + // target: { value: '6401ff65ce8e8406b8f07af2' }, + // }); - fireEvent.change(orgSelect, { - target: { value: '6401ff65ce8e8406b8f07af2' }, + // act(() => { + userEvent.click(orgSelect); + + const optionsPopupEl = await screen.findByRole('listbox', { + name: selectLabel, }); + userEvent.click(within(optionsPopupEl).getByText(/any organization/i)); + // }); + + // await waitFor(async () => { + // const option = await screen.findAllByText('Any Organization'); + + // console.log("option", option); + // }); + const nextBtn = await screen.findByTestId('nextBtn'); act(() => { @@ -2652,22 +2361,22 @@ describe('Testing Create Direct Chat Modal [User Portal]', () => { fireEvent.click(await screen.findByTestId('createBtn')); }); - await waitFor(() => { - expect(createBtn).not.toBeInTheDocument(); - }); + // await waitFor(() => { + // expect(createBtn).not.toBeInTheDocument(); + // }); }, 3000); test('add and remove user', async () => { setItem('userId', '1'); const mock = [ ...USER_JOINED_ORG_MOCK, - ...CREATE_GROUP_CHAT_MOCK, ...GROUP_CHAT_BY_ID_QUERY_MOCK, - ...DIRECT_CHAT_BY_ID_QUERY_MOCK, - ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, - ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ...MESSAGE_SENT_TO_CHAT_MOCK, + ...CHAT_BY_ID_QUERY_MOCK, + ...CHATS_LIST_MOCK, ...UserConnectionListMock, - ...MOCKS, + ...CREATE_CHAT_MUTATION, + ...CHATS_LIST_MOCK, ]; render( diff --git a/src/components/UserPortal/CreateGroupChat/CreateGroupChat.tsx b/src/components/UserPortal/CreateGroupChat/CreateGroupChat.tsx index 3c0af847fb..e293675a03 100644 --- a/src/components/UserPortal/CreateGroupChat/CreateGroupChat.tsx +++ b/src/components/UserPortal/CreateGroupChat/CreateGroupChat.tsx @@ -1,15 +1,10 @@ import { FormControl, - FormControlLabel, - FormHelperText, InputLabel, MenuItem, Paper, - RadioGroup, Select, - FormLabel, TableBody, - Radio, } from '@mui/material'; import type { SelectChangeEvent } from '@mui/material/Select'; import React, { useEffect, useState } from 'react'; @@ -19,7 +14,7 @@ import type { ApolloQueryResult } from '@apollo/client'; import { useMutation, useQuery } from '@apollo/client'; import { USER_JOINED_ORGANIZATIONS } from 'GraphQl/Queries/OrganizationQueries'; import useLocalStorage from 'utils/useLocalstorage'; -import { CREATE_GROUP_CHAT } from 'GraphQl/Mutations/OrganizationMutations'; +import { CREATE_CHAT } from 'GraphQl/Mutations/OrganizationMutations'; import Table from '@mui/material/Table'; import TableCell, { tableCellClasses } from '@mui/material/TableCell'; import TableContainer from '@mui/material/TableContainer'; @@ -29,20 +24,18 @@ import { styled } from '@mui/material/styles'; import type { InterfaceQueryUserListItem } from 'utils/interfaces'; import { USERS_CONNECTION_LIST } from 'GraphQl/Queries/Queries'; import Loader from 'components/Loader/Loader'; -import { LocalPoliceTwoTone, Search } from '@mui/icons-material'; -import { style } from '@mui/system'; -import { useTranslation } from 'react-i18next'; +import { Search } from '@mui/icons-material'; interface InterfaceCreateGroupChatProps { toggleCreateGroupChatModal: () => void; createGroupChatModalisOpen: boolean; - groupChatListRefetch: ( + chatsListRefetch: ( variables?: | Partial<{ - id: any; + id: string; }> | undefined, - ) => Promise>; + ) => Promise>; } interface InterfaceOrganization { @@ -69,6 +62,10 @@ interface InterfaceOrganization { }[]; } +/** + * Styled table cell with custom styles. + */ + const StyledTableCell = styled(TableCell)(({ theme }) => ({ [`&.${tableCellClasses.head}`]: { backgroundColor: ['#31bb6b', '!important'], @@ -79,6 +76,10 @@ const StyledTableCell = styled(TableCell)(({ theme }) => ({ }, })); +/** + * Styled table row with custom styles. + */ + const StyledTableRow = styled(TableRow)(() => ({ '&:last-child td, &:last-child th': { border: 0, @@ -87,30 +88,19 @@ const StyledTableRow = styled(TableRow)(() => ({ const { getItem } = useLocalStorage(); -/** - * - * @param toggleCreateGroupChatModal - function to toggle the create group chat modal - * @param createGroupChatModalisOpen - boolean to check if the create group chat modal is open - * @param groupChatListRefetch - function to refetch the group chat list - * @returns - returns the create group chat modal - */ export default function CreateGroupChat({ toggleCreateGroupChatModal, createGroupChatModalisOpen, - groupChatListRefetch, + chatsListRefetch, }: InterfaceCreateGroupChatProps): JSX.Element { - const { t } = useTranslation('translation', { - keyPrefix: 'userChat', - }); - const userId: string | null = getItem('userId'); - const [createGroupChat] = useMutation(CREATE_GROUP_CHAT); + const [createChat] = useMutation(CREATE_CHAT); const [organizations, setOrganizations] = useState([]); const [selectedOrganization, setSelectedOrganization] = useState(''); const [title, setTitle] = useState(''); - let [userIds, setUserIds] = useState([]); + const [userIds, setUserIds] = useState([]); const [addUserModalisOpen, setAddUserModalisOpen] = useState(false); @@ -121,7 +111,7 @@ export default function CreateGroupChat({ const toggleAddUserModal = /* istanbul ignore next */ (): void => setAddUserModalisOpen(!addUserModalisOpen); - const handleChange = (event: React.ChangeEvent): void => { + const handleChange = (event: SelectChangeEvent): void => { setSelectedOrganization(event.target.value as string); }; @@ -133,7 +123,6 @@ export default function CreateGroupChat({ ); function reset(): void { - setOrganizations([]); setTitle(''); setUserIds([]); setSelectedOrganization(''); @@ -144,14 +133,15 @@ export default function CreateGroupChat({ }, [userIds]); async function handleCreateGroupChat(): Promise { - const groupChat = await createGroupChat({ + await createChat({ variables: { organizationId: selectedOrganization, userIds: [userId, ...userIds], - title, + name: title, + isGroup: true, }, }); - groupChatListRefetch(); + chatsListRefetch(); toggleAddUserModal(); toggleCreateGroupChatModal(); reset(); @@ -206,50 +196,29 @@ export default function CreateGroupChat({
    - - Select Organization - + Select Organization + - {organizations && - organizations.length && - organizations.map((organization: InterfaceOrganization) => ( - - {`${organization.name}(${organization.address?.city},${organization.address?.state},${organization.address?.countryCode})`} - - ))} - - */} + + Group name { - userIds = userIds.filter( + const updatedUserIds = userIds.filter( (id) => id !== userDetails.user._id, ); - setUserIds(userIds); + setUserIds(updatedUserIds); }} data-testid="removeBtn" > diff --git a/src/components/UserPortal/OrganizationCard/OrganizationCard.test.tsx b/src/components/UserPortal/OrganizationCard/OrganizationCard.test.tsx index ba13fe346d..77516ddc7a 100644 --- a/src/components/UserPortal/OrganizationCard/OrganizationCard.test.tsx +++ b/src/components/UserPortal/OrganizationCard/OrganizationCard.test.tsx @@ -1,5 +1,6 @@ -import React, { act } from 'react'; -import { fireEvent, render, screen } from '@testing-library/react'; +import React from 'react'; +import { act, fireEvent, render, screen } from '@testing-library/react'; + import { MockedProvider } from '@apollo/react-testing'; import { I18nextProvider } from 'react-i18next'; @@ -225,6 +226,38 @@ describe('Testing OrganizationCard Component [User Portal]', () => { await wait(); }); + test('Visit organization', async () => { + const cardProps = { + ...props, + id: '3', + image: 'organizationImage', + userRegistrationRequired: true, + membershipRequestStatus: 'accepted', + }; + + render( + + + + + + + + + , + ); + + await wait(); + + expect(screen.getByTestId('manageBtn')).toBeInTheDocument(); + + fireEvent.click(screen.getByTestId('manageBtn')); + + await wait(); + + expect(window.location.pathname).toBe(`/user/organization/${cardProps.id}`); + }); + test('Send membership request', async () => { props = { ...props, diff --git a/src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.test.tsx b/src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.test.tsx index c08240462a..cddac285fd 100644 --- a/src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.test.tsx +++ b/src/components/UserPortal/OrganizationSidebar/OrganizationSidebar.test.tsx @@ -31,13 +31,14 @@ const MOCKS = [ _id: 1, title: 'Event', description: 'Event Test', - startDate: '', - endDate: '', + startDate: '2024-01-01', + endDate: '2024-01-02', location: 'New Delhi', startTime: '02:00', endTime: '06:00', allDay: false, recurring: false, + attendees: [], recurrenceRule: null, isRecurringEventException: false, isPublic: true, diff --git a/src/components/UserPortal/PostCard/PostCard.test.tsx b/src/components/UserPortal/PostCard/PostCard.test.tsx index f7d9217308..1b7708b384 100644 --- a/src/components/UserPortal/PostCard/PostCard.test.tsx +++ b/src/components/UserPortal/PostCard/PostCard.test.tsx @@ -338,7 +338,7 @@ describe('Testing PostCard Component [User Portal]', () => { userEvent.click(screen.getByTestId('editPostBtn')); await wait(); - expect(toast.success).toBeCalledWith('Post updated Successfully'); + expect(toast.success).toHaveBeenCalledWith('Post updated Successfully'); }); test('Delete post should work properly', async () => { @@ -388,7 +388,9 @@ describe('Testing PostCard Component [User Portal]', () => { userEvent.click(screen.getByTestId('deletePost')); await wait(); - expect(toast.success).toBeCalledWith('Successfully deleted the Post.'); + expect(toast.success).toHaveBeenCalledWith( + 'Successfully deleted the Post.', + ); }); test('Component should be rendered properly if user has liked the post', async () => { diff --git a/src/components/UserPortal/Register/Register.test.tsx b/src/components/UserPortal/Register/Register.test.tsx index f9929a0588..1883d60da3 100644 --- a/src/components/UserPortal/Register/Register.test.tsx +++ b/src/components/UserPortal/Register/Register.test.tsx @@ -104,7 +104,7 @@ describe('Testing Register Component [User Portal]', () => { userEvent.click(screen.getByTestId('setLoginBtn')); - expect(setCurrentMode).toBeCalledWith('login'); + expect(setCurrentMode).toHaveBeenCalledWith('login'); }); test('Expect toast.error to be called if email input is empty', async () => { @@ -124,7 +124,7 @@ describe('Testing Register Component [User Portal]', () => { userEvent.click(screen.getByTestId('registerBtn')); - expect(toast.error).toBeCalledWith('Please enter valid details.'); + expect(toast.error).toHaveBeenCalledWith('Please enter valid details.'); }); test('Expect toast.error to be called if password input is empty', async () => { @@ -145,7 +145,7 @@ describe('Testing Register Component [User Portal]', () => { userEvent.type(screen.getByTestId('emailInput'), formData.email); userEvent.click(screen.getByTestId('registerBtn')); - expect(toast.error).toBeCalledWith('Please enter valid details.'); + expect(toast.error).toHaveBeenCalledWith('Please enter valid details.'); }); test('Expect toast.error to be called if first name input is empty', async () => { @@ -169,7 +169,7 @@ describe('Testing Register Component [User Portal]', () => { userEvent.click(screen.getByTestId('registerBtn')); - expect(toast.error).toBeCalledWith('Please enter valid details.'); + expect(toast.error).toHaveBeenCalledWith('Please enter valid details.'); }); test('Expect toast.error to be called if last name input is empty', async () => { @@ -195,7 +195,7 @@ describe('Testing Register Component [User Portal]', () => { userEvent.click(screen.getByTestId('registerBtn')); - expect(toast.error).toBeCalledWith('Please enter valid details.'); + expect(toast.error).toHaveBeenCalledWith('Please enter valid details.'); }); test("Expect toast.error to be called if confirmPassword doesn't match with password", async () => { @@ -223,7 +223,7 @@ describe('Testing Register Component [User Portal]', () => { userEvent.click(screen.getByTestId('registerBtn')); - expect(toast.error).toBeCalledWith( + expect(toast.error).toHaveBeenCalledWith( "Password doesn't match. Confirm Password and try again.", ); }); @@ -260,7 +260,7 @@ describe('Testing Register Component [User Portal]', () => { await wait(); - expect(toast.success).toBeCalledWith( + expect(toast.success).toHaveBeenCalledWith( 'Successfully registered. Please wait for admin to approve your request.', ); }); diff --git a/src/components/UserPortal/StartPostModal/StartPostModal.test.tsx b/src/components/UserPortal/StartPostModal/StartPostModal.test.tsx index 5c436705cd..c34f3a2e9e 100644 --- a/src/components/UserPortal/StartPostModal/StartPostModal.test.tsx +++ b/src/components/UserPortal/StartPostModal/StartPostModal.test.tsx @@ -129,7 +129,9 @@ describe('Testing StartPostModal Component: User Portal', () => { await wait(); userEvent.click(screen.getByTestId('createPostBtn')); - expect(toastSpy).toBeCalledWith("Can't create a post with an empty body."); + expect(toastSpy).toHaveBeenCalledWith( + "Can't create a post with an empty body.", + ); }); test('On valid post submission Info toast should be shown', async () => { @@ -142,8 +144,10 @@ describe('Testing StartPostModal Component: User Portal', () => { userEvent.click(screen.getByTestId('createPostBtn')); - expect(toast.error).not.toBeCalledWith(); - expect(toast.info).toBeCalledWith('Processing your post. Please wait.'); + expect(toast.error).not.toHaveBeenCalledWith(); + expect(toast.info).toHaveBeenCalledWith( + 'Processing your post. Please wait.', + ); // await wait(); // expect(toast.success).toBeCalledWith( // 'Your post is now visible in the feed.', diff --git a/src/components/UserPortal/UserProfile/EventsAttendedByUser.test.tsx b/src/components/UserPortal/UserProfile/EventsAttendedByUser.test.tsx new file mode 100644 index 0000000000..82b173e399 --- /dev/null +++ b/src/components/UserPortal/UserProfile/EventsAttendedByUser.test.tsx @@ -0,0 +1,120 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import { EventsAttendedByUser } from './EventsAttendedByUser'; +import { MockedProvider } from '@apollo/client/testing'; +import { EVENT_DETAILS } from 'GraphQl/Queries/Queries'; + +const mockT = (key: string, params?: Record): string => { + if (params) { + return Object.entries(params).reduce( + (acc, [key, value]) => acc.replace(`{{${key}}}`, value), + key, + ); + } + return key; +}; + +const mocks = [ + { + request: { + query: EVENT_DETAILS, + variables: { id: '1' }, + }, + result: { + data: { + event: { + _id: '1', + title: 'Event 1', + startDate: '2023-01-01', + recurring: false, + attendees: [], + organization: { _id: 'org1' }, + }, + }, + }, + }, + { + request: { + query: EVENT_DETAILS, + variables: { id: '2' }, + }, + result: { + data: { + event: { + _id: '2', + title: 'Event 2', + startDate: '2023-01-01', + recurring: false, + attendees: [], + organization: { _id: 'org1' }, + }, + }, + }, + }, +]; + +describe('EventsAttendedByUser Component', () => { + const mockUserWithEvents = { + userDetails: { + firstName: 'John', + lastName: 'Doe', + createdAt: '2023-01-01', + gender: 'Male', + email: 'john@example.com', + phoneNumber: '1234567890', + birthDate: '1990-01-01', + grade: 'A', + empStatus: 'Employed', + maritalStatus: 'Single', + address: '123 Street', + state: 'State', + country: 'Country', + image: 'image.jpg', + eventsAttended: [{ _id: '1' }, { _id: '2' }], + }, + t: mockT, + }; + + const mockUserWithoutEvents = { + userDetails: { + firstName: 'Jane', + lastName: 'Doe', + createdAt: '2023-01-01', + gender: 'Female', + email: 'jane@example.com', + phoneNumber: '0987654321', + birthDate: '1990-01-01', + grade: 'B', + empStatus: 'Unemployed', + maritalStatus: 'Single', + address: '456 Street', + state: 'State', + country: 'Country', + image: 'image.jpg', + eventsAttended: [], + }, + t: mockT, + }; + + test('renders the component with events', () => { + render( + + + , + ); + + expect(screen.getByText('eventAttended')).toBeInTheDocument(); + expect(screen.getAllByTestId('usereventsCard')).toHaveLength(2); + }); + + test('renders no events message when user has no events', () => { + render( + + + , + ); + + expect(screen.getByText('noeventsAttended')).toBeInTheDocument(); + expect(screen.queryByTestId('usereventsCard')).not.toBeInTheDocument(); + }); +}); diff --git a/src/components/UserPortal/UserProfile/EventsAttendedByUser.tsx b/src/components/UserPortal/UserProfile/EventsAttendedByUser.tsx new file mode 100644 index 0000000000..13ab9f5f5a --- /dev/null +++ b/src/components/UserPortal/UserProfile/EventsAttendedByUser.tsx @@ -0,0 +1,57 @@ +import React from 'react'; +import { Card } from 'react-bootstrap'; +import styles from './common.module.css'; +import EventsAttendedByMember from 'components/MemberDetail/EventsAttendedByMember'; +/** + * Component to display events attended by a user in card format + * @param userDetails - User information including attended events + * @param t - Translation function + * @returns Card component containing list of attended events + */ +interface InterfaceUser { + userDetails: { + firstName: string; + lastName: string; + createdAt: string; + gender: string; + email: string; + phoneNumber: string; + birthDate: string; + grade: string; + empStatus: string; + maritalStatus: string; + address: string; + state: string; + country: string; + image: string; + eventsAttended: { _id: string }[]; + }; + t: (key: string) => string; +} +export const EventsAttendedByUser: React.FC = ({ + userDetails, + t, +}) => { + return ( + +
    +
    {t('eventAttended')}
    +
    + + {!userDetails.eventsAttended?.length ? ( +
    +
    {t('noeventsAttended')}
    +
    + ) : ( + userDetails.eventsAttended.map((event: { _id: string }) => ( + + + + )) + )} +
    +
    + ); +}; + +export default EventsAttendedByUser; diff --git a/src/components/UserPortal/UserProfile/UserAddressFields.test.tsx b/src/components/UserPortal/UserProfile/UserAddressFields.test.tsx new file mode 100644 index 0000000000..7aff734bc6 --- /dev/null +++ b/src/components/UserPortal/UserProfile/UserAddressFields.test.tsx @@ -0,0 +1,87 @@ +import React from 'react'; +import { render, screen, fireEvent } from '@testing-library/react'; +import { UserAddressFields } from './UserAddressFields'; +import { countryOptions } from 'utils/formEnumFields'; + +describe('UserAddressFields', () => { + const mockProps = { + tCommon: (key: string) => `translated_${key}`, + t: (key: string) => `translated_${key}`, + handleFieldChange: jest.fn(), + userDetails: { + address: '123 Test Street', + state: 'Test State', + country: 'US', + }, + }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + test('renders all form fields correctly', () => { + render(); + + expect(screen.getByTestId('inputAddress')).toBeInTheDocument(); + expect(screen.getByTestId('inputState')).toBeInTheDocument(); + expect(screen.getByTestId('inputCountry')).toBeInTheDocument(); + }); + + test('displays correct labels with translations', () => { + render(); + + expect(screen.getByText('translated_address')).toBeInTheDocument(); + expect(screen.getByText('translated_state')).toBeInTheDocument(); + expect(screen.getByText('translated_country')).toBeInTheDocument(); + }); + + test('handles address input change', () => { + render(); + + const addressInput = screen.getByTestId('inputAddress'); + fireEvent.change(addressInput, { target: { value: 'New Address' } }); + + expect(mockProps.handleFieldChange).toHaveBeenCalledWith( + 'address', + 'New Address', + ); + }); + + test('handles state input change', () => { + render(); + + const stateInput = screen.getByTestId('inputState'); + fireEvent.change(stateInput, { target: { value: 'New State' } }); + + expect(mockProps.handleFieldChange).toHaveBeenCalledWith( + 'state', + 'New State', + ); + }); + + test('handles country selection change', () => { + render(); + + const countrySelect = screen.getByTestId('inputCountry'); + fireEvent.change(countrySelect, { target: { value: 'CA' } }); + + expect(mockProps.handleFieldChange).toHaveBeenCalledWith('country', 'CA'); + }); + + test('renders all country options', () => { + render(); + + const countrySelect = screen.getByTestId('inputCountry'); + const options = countrySelect.getElementsByTagName('option'); + + expect(options.length).toBe(countryOptions.length + 1); // +1 for disabled option + }); + + test('displays initial values correctly', () => { + render(); + + expect(screen.getByTestId('inputAddress')).toHaveValue('123 Test Street'); + expect(screen.getByTestId('inputState')).toHaveValue('Test State'); + expect(screen.getByTestId('inputCountry')).toHaveValue('US'); + }); +}); diff --git a/src/components/UserPortal/UserProfile/UserAddressFields.tsx b/src/components/UserPortal/UserProfile/UserAddressFields.tsx new file mode 100644 index 0000000000..732209f3b0 --- /dev/null +++ b/src/components/UserPortal/UserProfile/UserAddressFields.tsx @@ -0,0 +1,94 @@ +import React from 'react'; +import { countryOptions } from 'utils/formEnumFields'; +import { Col, Form, Row } from 'react-bootstrap'; +import styles from './common.module.css'; + +interface InterfaceUserAddressFieldsProps { + tCommon: (key: string) => string; + t: (key: string) => string; + handleFieldChange: (field: string, value: string) => void; + userDetails: { + address: string; + state: string; + country: string; + }; +} +/** + * Form component containing address-related input fields for user profile + * Includes fields for address, city, state, and country + * @param {Object} props - Component props + * @param {function} props.tCommon - Translation function for common strings + * @param {function} props.t - Translation function for component-specific strings + * @param {function} props.handleFieldChange - Callback for field value changes + * @param {Object} props.userDetails - User's address information + * @returns Form group with address input fields + */ +export const UserAddressFields: React.FC = ({ + tCommon, + t, + handleFieldChange, + userDetails, +}) => { + return ( + + + + {tCommon('address')} + + handleFieldChange('address', e.target.value)} + className={styles.cardControl} + data-testid="inputAddress" + /> + + + + {t('state')} + + handleFieldChange('state', e.target.value)} + className={styles.cardControl} + data-testid="inputState" + /> + + + + {t('country')} + + handleFieldChange('country', e.target.value)} + className={styles.cardControl} + data-testid="inputCountry" + > + + {[...countryOptions] + .sort((a, b) => a.label.localeCompare(b.label)) + .map((country) => ( + + ))} + + + + ); +}; + +export default UserAddressFields; diff --git a/src/components/UserPortal/UserProfile/common.module.css b/src/components/UserPortal/UserProfile/common.module.css new file mode 100644 index 0000000000..a8125dcb3a --- /dev/null +++ b/src/components/UserPortal/UserProfile/common.module.css @@ -0,0 +1,39 @@ +.cardHeader .cardTitle { + font-size: 1.2rem; + font-weight: 600; +} +.scrollableCardBody { + max-height: min(220px, 50vh); + overflow-y: auto; + scroll-behavior: smooth; +} +.cardHeader { + padding: 1.25rem 1rem 1rem 1rem; + border-bottom: 1px solid var(--bs-gray-200); + display: flex; + justify-content: space-between; + align-items: center; +} + +.cardBody { + padding: 1.25rem 1rem 1.5rem 1rem; + display: flex; + flex-direction: column; + overflow-y: scroll; +} + +.cardLabel { + font-weight: bold; + padding-bottom: 1px; + font-size: 14px; + color: #707070; + margin-bottom: 10px; +} + +.cardControl { + margin-bottom: 20px; +} + +.cardButton { + width: fit-content; +} diff --git a/src/components/UserPortal/UserSidebar/UserSidebar.test.tsx b/src/components/UserPortal/UserSidebar/UserSidebar.test.tsx index 7218bc745c..79d603614f 100644 --- a/src/components/UserPortal/UserSidebar/UserSidebar.test.tsx +++ b/src/components/UserPortal/UserSidebar/UserSidebar.test.tsx @@ -1,9 +1,9 @@ import React, { act } from 'react'; import type { RenderResult } from '@testing-library/react'; -import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import { fireEvent, render, screen } from '@testing-library/react'; import { MockedProvider } from '@apollo/react-testing'; import { I18nextProvider } from 'react-i18next'; - +import styles from './UserSidebar.module.css'; import { USER_DETAILS, USER_JOINED_ORGANIZATIONS, @@ -363,40 +363,57 @@ const renderUserSidebar = ( ); }; -describe('Testing UserSidebar Component [User Portal]', () => { +describe('UserSidebar Component Tests in User Portal', () => { beforeEach(() => { jest.clearAllMocks(); }); - test('Component should be rendered properly', async () => { + test('UserSidebar component renders correctly with user data present', async () => { await act(async () => { renderUserSidebar('properId', link); await wait(); }); + expect(screen.getByText('Talawa User Portal')).toBeInTheDocument(); }); - test('Component should be rendered properly when userImage is present', async () => { + test('Displays the logo and title text of the User Portal', async () => { await act(async () => { - renderUserSidebar('imagePresent', link); + renderUserSidebar('properId', link); await wait(); }); + expect(screen.getByText('Talawa User Portal')).toBeInTheDocument(); + expect(screen.getByTestId('leftDrawerContainer')).toBeVisible(); }); - test('Component should be rendered properly when organizationImage is present', async () => { + test('UserSidebar renders correctly when joinedOrganizations list is empty', async () => { + await act(async () => { + renderUserSidebar('orgEmpty', link); + await wait(); + }); + expect(screen.getByText('My Organizations')).toBeInTheDocument(); + }); + + test('Renders UserSidebar component with organization image when present', async () => { await act(async () => { renderUserSidebar('imagePresent', link); await wait(); }); + expect(screen.getByText('Settings')).toBeInTheDocument(); }); - test('Component should be rendered properly when joinedOrganizations list is empty', async () => { + test('User profile data renders with all expected navigation links visible', async () => { await act(async () => { - renderUserSidebar('orgEmpty', link); + renderUserSidebar('properId', link); await wait(); }); + + const expectedLinks = ['My Organizations', 'Settings', 'Chat']; + expectedLinks.forEach((link) => { + expect(screen.getByText(link)).toBeInTheDocument(); + }); }); - test('Testing Drawer when the screen size is less than or equal to 820px', async () => { + test('UserSidebar renders correctly on smaller screens and toggles drawer visibility', async () => { await act(async () => { resizeWindow(800); render( @@ -411,28 +428,124 @@ describe('Testing UserSidebar Component [User Portal]', () => { , ); }); - expect(screen.getByText('My Organizations')).toBeInTheDocument(); - expect(screen.getByText('Settings')).toBeInTheDocument(); - expect(screen.getByText('Talawa User Portal')).toBeInTheDocument(); - const settingsBtn = screen.getByText('Settings'); + const orgsBtn = screen.getByTestId('orgsBtn'); + act(() => orgsBtn.click()); + expect(props.setHideDrawer).toHaveBeenCalledWith(true); + }); - const orgsBtn = screen.getAllByTestId(/orgsBtn/i); + test('Active route button style changes correctly upon click', async () => { + await act(async () => { + renderUserSidebar('properId', link); + await wait(); + }); - act(() => { - orgsBtn[0].click(); + const orgsBtn = screen.getByTestId('orgsBtn'); + const settingsBtn = screen.getByTestId('settingsBtn'); + + fireEvent.click(orgsBtn); + expect(orgsBtn).toHaveClass('text-white btn btn-success'); + fireEvent.click(settingsBtn); + expect(settingsBtn).toHaveClass('text-white btn btn-success'); + }); + + test('Translation hook displays expected text in UserSidebar', async () => { + await act(async () => { + renderUserSidebar('properId', link); + await wait(); + }); + expect( + screen.getByText(i18nForTest.t('common:settings')), + ).toBeInTheDocument(); + }); + + test('handleLinkClick function closes the sidebar on mobile view when a link is clicked', async () => { + resizeWindow(800); + await act(async () => { + renderUserSidebar('properId', link); + await wait(); }); - await waitFor(() => - expect( - orgsBtn[0].className.includes('text-white btn btn-success'), - ).toBeTruthy(), - ); - act(() => { - settingsBtn.click(); + const chatBtn = screen.getByTestId('chatBtn'); + fireEvent.click(chatBtn); + expect(props.setHideDrawer).toHaveBeenCalledWith(true); + }); + + describe('UserSidebar Drawer Visibility Tests on Smaller Screens', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + test('Clicking a link closes the drawer when window width is 820px or less', () => { + act(() => { + window.innerWidth = 820; + window.dispatchEvent(new Event('resize')); + }); + + render( + + + + + + + + + , + ); + + const linkElement = screen.getByText('My Organizations'); // Adjust text if different + fireEvent.click(linkElement); + + expect(props.setHideDrawer).toHaveBeenCalledWith(true); + }); + + describe('UserSidebar Drawer State Tests', () => { + test('Drawer visibility changes based on hideDrawer prop', () => { + const { rerender } = render( + + + + + + + + + , + ); + + expect(screen.getByTestId('leftDrawerContainer')).toHaveClass( + styles.hideElemByDefault, + ); + + rerender( + + + + + + + + + , + ); + expect(screen.getByTestId('leftDrawerContainer')).toHaveClass( + styles.inactiveDrawer, + ); + + rerender( + + + + + + + + + , + ); + expect(screen.getByTestId('leftDrawerContainer')).toHaveClass( + styles.activeDrawer, + ); + }); }); - await waitFor(() => - expect( - settingsBtn.className.includes('text-white btn btn-success'), - ).toBeTruthy(), - ); }); }); diff --git a/src/components/UsersTableItem/UserTableItem.test.tsx b/src/components/UsersTableItem/UserTableItem.test.tsx index e87b41f7f2..687165b78d 100644 --- a/src/components/UsersTableItem/UserTableItem.test.tsx +++ b/src/components/UsersTableItem/UserTableItem.test.tsx @@ -499,12 +499,12 @@ describe('Testing User Table Item', () => { fireEvent.click(searchBtn); // Click on Creator Link fireEvent.click(screen.getByTestId(`creatorabc`)); - expect(toast.success).toBeCalledWith('Profile Page Coming Soon !'); + expect(toast.success).toHaveBeenCalledWith('Profile Page Coming Soon !'); // Click on Organization Link fireEvent.click(screen.getByText(/Joined Organization 1/i)); - expect(window.location.replace).toBeCalledWith('/orgdash/abc'); - expect(mockNavgatePush).toBeCalledWith('/orgdash/abc'); + expect(window.location.replace).toHaveBeenCalledWith('/orgdash/abc'); + expect(mockNavgatePush).toHaveBeenCalledWith('/orgdash/abc'); fireEvent.click(screen.getByTestId(`closeJoinedOrgsBtn${123}`)); }); @@ -693,7 +693,7 @@ describe('Testing User Table Item', () => { expect(screen.getByTestId('removeUserFromOrgBtnmno')).toBeInTheDocument(); // Click on Creator Link fireEvent.click(screen.getByTestId(`creatorxyz`)); - expect(toast.success).toBeCalledWith('Profile Page Coming Soon !'); + expect(toast.success).toHaveBeenCalledWith('Profile Page Coming Soon !'); // Search for Blocked Organization 1 const searchBtn = screen.getByTestId(`searchBtnOrgsBlockedBy`); @@ -720,8 +720,8 @@ describe('Testing User Table Item', () => { // Click on Organization Link fireEvent.click(screen.getByText(/XYZ/i)); - expect(window.location.replace).toBeCalledWith('/orgdash/xyz'); - expect(mockNavgatePush).toBeCalledWith('/orgdash/xyz'); + expect(window.location.replace).toHaveBeenCalledWith('/orgdash/xyz'); + expect(mockNavgatePush).toHaveBeenCalledWith('/orgdash/xyz'); fireEvent.click(screen.getByTestId(`closeBlockedByOrgsBtn${123}`)); }); diff --git a/src/screens/CommunityProfile/CommunityProfile.tsx b/src/screens/CommunityProfile/CommunityProfile.tsx index 02f8b8aca4..d96c923eb3 100644 --- a/src/screens/CommunityProfile/CommunityProfile.tsx +++ b/src/screens/CommunityProfile/CommunityProfile.tsx @@ -20,6 +20,7 @@ import { import convertToBase64 from 'utils/convertToBase64'; import styles from './CommunityProfile.module.css'; import { errorHandler } from 'utils/errorHandler'; +import UpdateSession from '../../components/UpdateSession/UpdateSession'; /** * `CommunityProfile` component allows users to view and update their community profile details. @@ -208,212 +209,218 @@ const CommunityProfile = (): JSX.Element => { } return ( - -
    -
    {t('editProfile')}
    -
    - -
    {t('communityProfileInfo')}
    - - - - {t('communityName')} - - - - - - {t('wesiteLink')} - - - - - {t('logo')} - - - {t('social')} - {/* Social media inputs */} -
    - Facebook Logo + <> + +
    +
    {t('editProfile')}
    +
    + +
    {t('communityProfileInfo')}
    + + + + {t('communityName')} + -
    -
    - Instagram Logo - -
    -
    - X Logo - -
    -
    - LinkedIn Logo + + + + {t('wesiteLink')} + -
    -
    - Github Logo + + + {t('logo')} , + ): Promise => { + setProfileVariable((prevInput) => ({ + ...prevInput, + logo: '', + })); + const target = e.target as HTMLInputElement; + const file = target.files?.[0]; + const base64file = file && (await convertToBase64(file)); + setProfileVariable({ + ...profileVariable, + logoUrl: base64file ?? '', + }); + }} + className="mb-3" autoComplete="off" + required /> -
    -
    - Youtube Logo - -
    -
    - Reddit Logo - -
    -
    - Slack Logo - -
    -
    -
    - - -
    - -
    -
    + + +
    + + + + + + ); }; diff --git a/src/screens/EventManagement/EventManagement.test.tsx b/src/screens/EventManagement/EventManagement.test.tsx index fb851ec72f..a119caad42 100644 --- a/src/screens/EventManagement/EventManagement.test.tsx +++ b/src/screens/EventManagement/EventManagement.test.tsx @@ -61,17 +61,6 @@ describe('Event Management', () => { jest.clearAllMocks(); }); - test('Testing Event Management Screen', async () => { - renderEventManagement(); - - const dashboardTab = await screen.findByTestId('eventDashboadTab'); - expect(dashboardTab).toBeInTheDocument(); - - const dashboardButton = screen.getByTestId('dashboardBtn'); - userEvent.click(dashboardButton); - - expect(dashboardTab).toBeInTheDocument(); - }); test('Testing back button navigation when userType is SuperAdmin', async () => { setItem('SuperAdmin', true); renderEventManagement(); @@ -92,23 +81,63 @@ describe('Event Management', () => { const registrantsTab = screen.getByTestId('eventRegistrantsTab'); expect(registrantsTab).toBeInTheDocument(); - - const eventActionsButton = screen.getByTestId('eventActionsBtn'); + const eventAttendanceButton = screen.getByTestId('attendanceBtn'); + userEvent.click(eventAttendanceButton); + const eventAttendanceTab = screen.getByTestId('eventAttendanceTab'); + expect(eventAttendanceTab).toBeInTheDocument(); + const eventActionsButton = screen.getByTestId('actionsBtn'); userEvent.click(eventActionsButton); const eventActionsTab = screen.getByTestId('eventActionsTab'); expect(eventActionsTab).toBeInTheDocument(); - const eventAgendasButton = screen.getByTestId('eventAgendasBtn'); + const eventAgendasButton = screen.getByTestId('agendasBtn'); userEvent.click(eventAgendasButton); const eventAgendasTab = screen.getByTestId('eventAgendasTab'); expect(eventAgendasTab).toBeInTheDocument(); - const eventStatsButton = screen.getByTestId('eventStatsBtn'); + const eventStatsButton = screen.getByTestId('statisticsBtn'); userEvent.click(eventStatsButton); const eventStatsTab = screen.getByTestId('eventStatsTab'); expect(eventStatsTab).toBeInTheDocument(); + + const volunteerButton = screen.getByTestId('volunteersBtn'); + userEvent.click(volunteerButton); + + const eventVolunteersTab = screen.getByTestId('eventVolunteersTab'); + expect(eventVolunteersTab).toBeInTheDocument(); + }); + test('renders nothing when invalid tab is selected', () => { + render( + + + + + + } + /> + + + + + , + ); + + // Force an invalid tab state + const setTab = jest.fn(); + React.useState = jest.fn().mockReturnValue(['invalidTab', setTab]); + + // Verify nothing is rendered + expect(screen.queryByTestId('eventDashboardTab')).toBeInTheDocument(); + expect(screen.queryByTestId('eventRegistrantsTab')).not.toBeInTheDocument(); + expect(screen.queryByTestId('eventAttendanceTab')).not.toBeInTheDocument(); + expect(screen.queryByTestId('eventActionsTab')).not.toBeInTheDocument(); + expect(screen.queryByTestId('eventVolunteersTab')).not.toBeInTheDocument(); + expect(screen.queryByTestId('eventAgendasTab')).not.toBeInTheDocument(); + expect(screen.queryByTestId('eventStatsTab')).not.toBeInTheDocument(); }); }); diff --git a/src/screens/EventManagement/EventManagement.tsx b/src/screens/EventManagement/EventManagement.tsx index 8a5b685855..2e5cdbd419 100644 --- a/src/screens/EventManagement/EventManagement.tsx +++ b/src/screens/EventManagement/EventManagement.tsx @@ -5,15 +5,18 @@ import { Navigate, useNavigate, useParams } from 'react-router-dom'; import { FaChevronLeft, FaTasks } from 'react-icons/fa'; import { MdOutlineDashboard } from 'react-icons/md'; import EventRegistrantsIcon from 'assets/svgs/people.svg?react'; -import { IoMdStats } from 'react-icons/io'; +import { BsPersonCheck } from 'react-icons/bs'; +import { IoMdStats, IoIosHand } from 'react-icons/io'; import EventAgendaItemsIcon from 'assets/svgs/agenda-items.svg?react'; import { useTranslation } from 'react-i18next'; import { Button, Dropdown } from 'react-bootstrap'; + import EventDashboard from 'components/EventManagement/Dashboard/EventDashboard'; import OrganizationActionItems from 'screens/OrganizationActionItems/OrganizationActionItems'; +import VolunteerContainer from 'screens/EventVolunteers/VolunteerContainer'; import EventAgendaItems from 'components/EventManagement/EventAgendaItems/EventAgendaItems'; import useLocalStorage from 'utils/useLocalstorage'; - +import EventAttendance from 'components/EventManagement/EventAttendance/EventAttendance'; /** * List of tabs for the event dashboard. * @@ -32,15 +35,23 @@ const eventDashboardTabs: { icon: , }, { - value: 'eventActions', - icon: , + value: 'attendance', + icon: , }, { - value: 'eventAgendas', + value: 'agendas', icon: , }, { - value: 'eventStats', + value: 'actions', + icon: , + }, + { + value: 'volunteers', + icon: , + }, + { + value: 'statistics', icon: , }, ]; @@ -51,9 +62,11 @@ const eventDashboardTabs: { type TabOptions = | 'dashboard' | 'registrants' - | 'eventActions' - | 'eventAgendas' - | 'eventStats'; + | 'attendance' + | 'agendas' + | 'actions' + | 'volunteers' + | 'statistics'; /** * `EventManagement` component handles the display and navigation of different event management sections. @@ -64,6 +77,8 @@ type TabOptions = * - Handling event actions * - Reviewing event agendas * - Viewing event statistics + * - Managing event volunteers + * - Managing event attendance * * @returns JSX.Element - The `EventManagement` component. * @@ -124,13 +139,12 @@ const EventManagement = (): JSX.Element => { const translatedText = t(value); const className = selected - ? 'px-4 d-flex align-items-center shadow' - : 'text-secondary bg-white px-4 d-flex align-items-center rounded shadow'; + ? 'px-4 d-flex align-items-center rounded-3 shadow-sm' + : 'text-secondary bg-white px-4 d-flex align-items-center rounded-3 shadow-sm'; const props = { variant, className, style: { height: '2.5rem' }, - size: 'sm' as 'sm' | 'lg', onClick: () => setTab(value), 'data-testid': `${value}Btn`, }; @@ -145,9 +159,11 @@ const EventManagement = (): JSX.Element => { const handleBack = (): void => { /*istanbul ignore next*/ - userRole === 'USER' - ? navigate(`/user/events/${orgId}`) - : navigate(`/orgevents/${orgId}`); + if (userRole === 'USER') { + navigate(`/user/events/${orgId}`); + } else { + navigate(`/orgevents/${orgId}`); + } }; return ( @@ -158,7 +174,7 @@ const EventManagement = (): JSX.Element => { + + + ); + }, + }, + ]; + + return ( +
    + {/* Header with search, filter and Create Button */} +
    +
    + { + setSearchValue(e.target.value); + debouncedSearch(e.target.value); + }} + data-testid="searchBy" + /> + +
    +
    +
    + + + + {tCommon('sort')} + + + setSortBy('createdAt_DESC')} + data-testid="createdAt_DESC" + > + {t('latest')} + + setSortBy('createdAt_ASC')} + data-testid="createdAt_ASC" + > + {t('earliest')} + + + +
    +
    +
    + + {/* Table with Volunteer Membership Requests */} + + {requests.length > 0 ? ( + row._id} + sx={dataGridStyle} + getRowClassName={() => `${styles.rowBackground}`} + autoHeight + rowHeight={65} + rows={requests.map((request, index) => ({ + id: index + 1, + ...request, + }))} + columns={columns} + isRowSelectable={() => false} + /> + ) : ( +
    +
    {t('noRequests')}
    +
    + )} +
    + ); +} + +export default requests; diff --git a/src/screens/EventVolunteers/VolunteerContainer.test.tsx b/src/screens/EventVolunteers/VolunteerContainer.test.tsx new file mode 100644 index 0000000000..928d04195c --- /dev/null +++ b/src/screens/EventVolunteers/VolunteerContainer.test.tsx @@ -0,0 +1,94 @@ +import React from 'react'; +import type { RenderResult } from '@testing-library/react'; +import { render, screen, waitFor } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider } from 'react-i18next'; +import i18n from 'utils/i18n'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import VolunteerContainer from './VolunteerContainer'; +import userEvent from '@testing-library/user-event'; +import { MOCKS } from './Volunteers/Volunteers.mocks'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { LocalizationProvider } from '@mui/x-date-pickers'; + +const link1 = new StaticMockLink(MOCKS); + +const renderVolunteerContainer = (): RenderResult => { + return render( + + + + + + + } + /> + paramsError
    } + /> + + + + + + , + ); +}; + +describe('Testing Volunteer Container', () => { + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId', eventId: 'eventId' }), + })); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('should redirect to fallback URL if URL params are undefined', async () => { + render( + + + + + + } /> +
    } + /> + + + + + , + ); + + await waitFor(() => { + expect(screen.getByTestId('paramsError')).toBeInTheDocument(); + }); + }); + + test('Testing Volunteer Container Screen -> Toggle screens', async () => { + renderVolunteerContainer(); + + const groupRadio = await screen.findByTestId('groupsRadio'); + expect(groupRadio).toBeInTheDocument(); + userEvent.click(groupRadio); + + const requestsRadio = await screen.findByTestId('requestsRadio'); + expect(requestsRadio).toBeInTheDocument(); + userEvent.click(requestsRadio); + + const individualRadio = await screen.findByTestId('individualRadio'); + expect(individualRadio).toBeInTheDocument(); + userEvent.click(individualRadio); + }); +}); diff --git a/src/screens/EventVolunteers/VolunteerContainer.tsx b/src/screens/EventVolunteers/VolunteerContainer.tsx new file mode 100644 index 0000000000..1a425a706e --- /dev/null +++ b/src/screens/EventVolunteers/VolunteerContainer.tsx @@ -0,0 +1,113 @@ +import React, { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Navigate, useParams } from 'react-router-dom'; +import styles from './EventVolunteers.module.css'; +import { HiUserGroup, HiUser } from 'react-icons/hi2'; +import Volunteers from './Volunteers/Volunteers'; +import VolunteerGroups from './VolunteerGroups/VolunteerGroups'; +import { FaRegFile } from 'react-icons/fa6'; +import Requests from './Requests/Requests'; + +/** + * Container Component for Volunteer or VolunteerGroups as per selection. + * + * This component allows users switch between Volunteers and VolunteerGroups. + * + * @returns The rendered component. + */ +function volunteerContainer(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'eventVolunteers', + }); + + // Get the organization ID and event ID from URL parameters + const { orgId, eventId } = useParams(); + + if (!orgId || !eventId) { + return ; + } + + const [dataType, setDataType] = useState<'individual' | 'group' | 'requests'>( + 'individual', + ); + + return ( +
    +
    + + {t( + `${dataType === 'group' ? 'volunteerGroups' : dataType === 'individual' ? 'volunteers' : 'requests'}`, + )} + +
    +
    + setDataType('individual')} + /> + + + setDataType('group')} + checked={dataType === 'group'} + /> + + + setDataType('requests')} + checked={dataType === 'requests'} + /> + +
    +
    +
    + + {dataType === 'individual' ? ( + + ) : dataType === 'group' ? ( + + ) : ( + + )} +
    + ); +} + +export default volunteerContainer; diff --git a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupDeleteModal.test.tsx b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupDeleteModal.test.tsx new file mode 100644 index 0000000000..05c2dab5ff --- /dev/null +++ b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupDeleteModal.test.tsx @@ -0,0 +1,141 @@ +import React from 'react'; +import type { ApolloLink } from '@apollo/client'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import type { RenderResult } from '@testing-library/react'; +import { render, screen, waitFor } from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import i18n from 'utils/i18nForTest'; +import { MOCKS, MOCKS_ERROR } from './VolunteerGroups.mocks'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { toast } from 'react-toastify'; +import type { InterfaceDeleteVolunteerGroupModal } from './VolunteerGroupDeleteModal'; +import VolunteerGroupDeleteModal from './VolunteerGroupDeleteModal'; +import userEvent from '@testing-library/user-event'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(MOCKS_ERROR); +const t = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.eventVolunteers ?? {}, + ), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const itemProps: InterfaceDeleteVolunteerGroupModal[] = [ + { + isOpen: true, + hide: jest.fn(), + refetchGroups: jest.fn(), + group: { + _id: 'groupId', + name: 'Group 1', + description: 'desc', + volunteersRequired: null, + createdAt: '2024-10-25T16:16:32.978Z', + creator: { + _id: 'creatorId1', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + leader: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: 'img-url', + }, + volunteers: [ + { + _id: 'volunteerId1', + user: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + }, + ], + assignments: [], + event: { + _id: 'eventId', + }, + }, + }, +]; + +const renderGroupDeleteModal = ( + link: ApolloLink, + props: InterfaceDeleteVolunteerGroupModal, +): RenderResult => { + return render( + + + + + + + + + + + , + ); +}; + +describe('Testing Group Delete Modal', () => { + it('Delete Group', async () => { + renderGroupDeleteModal(link1, itemProps[0]); + expect(screen.getByText(t.deleteGroup)).toBeInTheDocument(); + + const yesBtn = screen.getByTestId('deleteyesbtn'); + expect(yesBtn).toBeInTheDocument(); + userEvent.click(yesBtn); + + await waitFor(() => { + expect(itemProps[0].refetchGroups).toHaveBeenCalled(); + expect(itemProps[0].hide).toHaveBeenCalled(); + expect(toast.success).toHaveBeenCalledWith(t.volunteerGroupDeleted); + }); + }); + + it('Close Delete Modal', async () => { + renderGroupDeleteModal(link1, itemProps[0]); + expect(screen.getByText(t.deleteGroup)).toBeInTheDocument(); + + const noBtn = screen.getByTestId('deletenobtn'); + expect(noBtn).toBeInTheDocument(); + userEvent.click(noBtn); + + await waitFor(() => { + expect(itemProps[0].hide).toHaveBeenCalled(); + }); + }); + + it('Delete Group -> Error', async () => { + renderGroupDeleteModal(link2, itemProps[0]); + expect(screen.getByText(t.deleteGroup)).toBeInTheDocument(); + + const yesBtn = screen.getByTestId('deleteyesbtn'); + expect(yesBtn).toBeInTheDocument(); + userEvent.click(yesBtn); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupDeleteModal.tsx b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupDeleteModal.tsx new file mode 100644 index 0000000000..33132bfd33 --- /dev/null +++ b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupDeleteModal.tsx @@ -0,0 +1,100 @@ +import { Button, Modal } from 'react-bootstrap'; +import styles from '../EventVolunteers.module.css'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { useMutation } from '@apollo/client'; +import type { InterfaceVolunteerGroupInfo } from 'utils/interfaces'; +import { toast } from 'react-toastify'; +import { DELETE_VOLUNTEER_GROUP } from 'GraphQl/Mutations/EventVolunteerMutation'; + +export interface InterfaceDeleteVolunteerGroupModal { + isOpen: boolean; + hide: () => void; + group: InterfaceVolunteerGroupInfo | null; + refetchGroups: () => void; +} + +/** + * A modal dialog for confirming the deletion of a volunteer group. + * + * @param isOpen - Indicates whether the modal is open. + * @param hide - Function to close the modal. + * @param group - The volunteer group to be deleted. + * @param refetchGroups - Function to refetch the volunteer groups after deletion. + * + * @returns The rendered modal component. + * + * + * The `VolunteerGroupDeleteModal` component displays a confirmation dialog when a user attempts to delete a volunteer group. + * It allows the user to either confirm or cancel the deletion. + * On confirmation, the `deleteVolunteerGroup` mutation is called to remove the volunteer group from the database, + * and the `refetchGroups` function is invoked to update the list of volunteer groups. + * A success or error toast notification is shown based on the result of the deletion operation. + * + * The modal includes: + * - A header with a title and a close button. + * - A body with a message asking for confirmation. + * - A footer with "Yes" and "No" buttons to confirm or cancel the deletion. + * + * The `deleteVolunteerGroup` mutation is used to perform the deletion operation. + */ + +const VolunteerGroupDeleteModal: React.FC< + InterfaceDeleteVolunteerGroupModal +> = ({ isOpen, hide, group, refetchGroups }) => { + const { t } = useTranslation('translation', { + keyPrefix: 'eventVolunteers', + }); + const { t: tCommon } = useTranslation('common'); + + const [deleteVolunteerGroup] = useMutation(DELETE_VOLUNTEER_GROUP); + + const deleteHandler = async (): Promise => { + try { + await deleteVolunteerGroup({ + variables: { + id: group?._id, + }, + }); + refetchGroups(); + hide(); + toast.success(t('volunteerGroupDeleted')); + } catch (error: unknown) { + toast.error((error as Error).message); + } + }; + return ( + <> + + +

    {t('deleteGroup')}

    + +
    + +

    {t('deleteVolunteerGroupMsg')}

    +
    + + + + +
    + + ); +}; +export default VolunteerGroupDeleteModal; diff --git a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupModal.test.tsx b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupModal.test.tsx new file mode 100644 index 0000000000..2fc0b2e348 --- /dev/null +++ b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupModal.test.tsx @@ -0,0 +1,349 @@ +import React from 'react'; +import type { ApolloLink } from '@apollo/client'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import type { RenderResult } from '@testing-library/react'; +import { + fireEvent, + render, + screen, + waitFor, + within, +} from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import i18n from 'utils/i18nForTest'; +import { MOCKS, MOCKS_ERROR } from './VolunteerGroups.mocks'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { toast } from 'react-toastify'; +import type { InterfaceVolunteerGroupModal } from './VolunteerGroupModal'; +import GroupModal from './VolunteerGroupModal'; +import userEvent from '@testing-library/user-event'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(MOCKS_ERROR); +const t = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.eventVolunteers ?? {}, + ), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const itemProps: InterfaceVolunteerGroupModal[] = [ + { + isOpen: true, + hide: jest.fn(), + eventId: 'eventId', + orgId: 'orgId', + refetchGroups: jest.fn(), + mode: 'create', + group: null, + }, + { + isOpen: true, + hide: jest.fn(), + eventId: 'eventId', + orgId: 'orgId', + refetchGroups: jest.fn(), + mode: 'edit', + group: { + _id: 'groupId', + name: 'Group 1', + description: 'desc', + volunteersRequired: 2, + createdAt: '2024-10-25T16:16:32.978Z', + creator: { + _id: 'creatorId1', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + leader: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: 'img-url', + }, + volunteers: [ + { + _id: 'volunteerId1', + user: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + }, + ], + assignments: [], + event: { + _id: 'eventId', + }, + }, + }, + { + isOpen: true, + hide: jest.fn(), + eventId: 'eventId', + orgId: 'orgId', + refetchGroups: jest.fn(), + mode: 'edit', + group: { + _id: 'groupId', + name: 'Group 1', + description: null, + volunteersRequired: null, + createdAt: '2024-10-25T16:16:32.978Z', + creator: { + _id: 'creatorId1', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + leader: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: 'img-url', + }, + volunteers: [], + assignments: [], + event: { + _id: 'eventId', + }, + }, + }, +]; + +const renderGroupModal = ( + link: ApolloLink, + props: InterfaceVolunteerGroupModal, +): RenderResult => { + return render( + + + + + + + + + + + , + ); +}; + +describe('Testing VolunteerGroupModal', () => { + it('GroupModal -> Create', async () => { + renderGroupModal(link1, itemProps[0]); + expect(screen.getAllByText(t.createGroup)).toHaveLength(2); + + const nameInput = screen.getByLabelText(`${t.name} *`); + expect(nameInput).toBeInTheDocument(); + fireEvent.change(nameInput, { target: { value: 'Group 1' } }); + expect(nameInput).toHaveValue('Group 1'); + + const descInput = screen.getByLabelText(t.description); + expect(descInput).toBeInTheDocument(); + fireEvent.change(descInput, { target: { value: 'desc' } }); + expect(descInput).toHaveValue('desc'); + + const vrInput = screen.getByLabelText(t.volunteersRequired); + expect(vrInput).toBeInTheDocument(); + fireEvent.change(vrInput, { target: { value: '10' } }); + expect(vrInput).toHaveValue('10'); + + // Select Leader + const memberSelect = await screen.findByTestId('leaderSelect'); + expect(memberSelect).toBeInTheDocument(); + const memberInputField = within(memberSelect).getByRole('combobox'); + fireEvent.mouseDown(memberInputField); + + const memberOption = await screen.findByText('Harve Lance'); + expect(memberOption).toBeInTheDocument(); + fireEvent.click(memberOption); + + // Select Volunteers + const volunteerSelect = await screen.findByTestId('volunteerSelect'); + expect(volunteerSelect).toBeInTheDocument(); + const volunteerInputField = within(volunteerSelect).getByRole('combobox'); + fireEvent.mouseDown(volunteerInputField); + + const volunteerOption = await screen.findByText('John Doe'); + expect(volunteerOption).toBeInTheDocument(); + fireEvent.click(volunteerOption); + + const submitBtn = screen.getByTestId('submitBtn'); + expect(submitBtn).toBeInTheDocument(); + userEvent.click(submitBtn); + + waitFor(() => { + expect(toast.success).toHaveBeenCalledWith(t.volunteerGroupCreated); + expect(itemProps[0].refetchGroups).toHaveBeenCalled(); + expect(itemProps[0].hide).toHaveBeenCalled(); + }); + }); + + it('GroupModal -> Create -> Error', async () => { + renderGroupModal(link2, itemProps[0]); + expect(screen.getAllByText(t.createGroup)).toHaveLength(2); + + const nameInput = screen.getByLabelText(`${t.name} *`); + expect(nameInput).toBeInTheDocument(); + fireEvent.change(nameInput, { target: { value: 'Group 1' } }); + expect(nameInput).toHaveValue('Group 1'); + + const descInput = screen.getByLabelText(t.description); + expect(descInput).toBeInTheDocument(); + fireEvent.change(descInput, { target: { value: 'desc' } }); + expect(descInput).toHaveValue('desc'); + + const vrInput = screen.getByLabelText(t.volunteersRequired); + expect(vrInput).toBeInTheDocument(); + fireEvent.change(vrInput, { target: { value: '10' } }); + expect(vrInput).toHaveValue('10'); + + // Select Leader + const memberSelect = await screen.findByTestId('leaderSelect'); + expect(memberSelect).toBeInTheDocument(); + const memberInputField = within(memberSelect).getByRole('combobox'); + fireEvent.mouseDown(memberInputField); + + const memberOption = await screen.findByText('Harve Lance'); + expect(memberOption).toBeInTheDocument(); + fireEvent.click(memberOption); + + // Select Volunteers + const volunteerSelect = await screen.findByTestId('volunteerSelect'); + expect(volunteerSelect).toBeInTheDocument(); + const volunteerInputField = within(volunteerSelect).getByRole('combobox'); + fireEvent.mouseDown(volunteerInputField); + + const volunteerOption = await screen.findByText('John Doe'); + expect(volunteerOption).toBeInTheDocument(); + fireEvent.click(volunteerOption); + + const submitBtn = screen.getByTestId('submitBtn'); + expect(submitBtn).toBeInTheDocument(); + userEvent.click(submitBtn); + + waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); + + it('GroupModal -> Update', async () => { + renderGroupModal(link1, itemProps[1]); + expect(screen.getAllByText(t.updateGroup)).toHaveLength(2); + + const nameInput = screen.getByLabelText(`${t.name} *`); + expect(nameInput).toBeInTheDocument(); + fireEvent.change(nameInput, { target: { value: 'Group 2' } }); + expect(nameInput).toHaveValue('Group 2'); + + const descInput = screen.getByLabelText(t.description); + expect(descInput).toBeInTheDocument(); + fireEvent.change(descInput, { target: { value: 'desc new' } }); + expect(descInput).toHaveValue('desc new'); + + const vrInput = screen.getByLabelText(t.volunteersRequired); + expect(vrInput).toBeInTheDocument(); + fireEvent.change(vrInput, { target: { value: '10' } }); + expect(vrInput).toHaveValue('10'); + + const submitBtn = screen.getByTestId('submitBtn'); + expect(submitBtn).toBeInTheDocument(); + userEvent.click(submitBtn); + + await waitFor(() => { + expect(toast.success).toHaveBeenCalledWith(t.volunteerGroupUpdated); + expect(itemProps[1].refetchGroups).toHaveBeenCalled(); + expect(itemProps[1].hide).toHaveBeenCalled(); + }); + }); + + it('GroupModal -> Details -> Update -> Error', async () => { + renderGroupModal(link2, itemProps[1]); + expect(screen.getAllByText(t.updateGroup)).toHaveLength(2); + + const nameInput = screen.getByLabelText(`${t.name} *`); + expect(nameInput).toBeInTheDocument(); + fireEvent.change(nameInput, { target: { value: 'Group 2' } }); + expect(nameInput).toHaveValue('Group 2'); + + const descInput = screen.getByLabelText(t.description); + expect(descInput).toBeInTheDocument(); + fireEvent.change(descInput, { target: { value: 'desc new' } }); + expect(descInput).toHaveValue('desc new'); + + const vrInput = screen.getByLabelText(t.volunteersRequired); + expect(vrInput).toBeInTheDocument(); + fireEvent.change(vrInput, { target: { value: '10' } }); + expect(vrInput).toHaveValue('10'); + + const submitBtn = screen.getByTestId('submitBtn'); + expect(submitBtn).toBeInTheDocument(); + userEvent.click(submitBtn); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); + + it('Try adding different values for volunteersRequired', async () => { + renderGroupModal(link1, itemProps[2]); + expect(screen.getAllByText(t.updateGroup)).toHaveLength(2); + + const vrInput = screen.getByLabelText(t.volunteersRequired); + expect(vrInput).toBeInTheDocument(); + fireEvent.change(vrInput, { target: { value: '-1' } }); + + await waitFor(() => { + expect(vrInput).toHaveValue(''); + }); + + userEvent.clear(vrInput); + userEvent.type(vrInput, '1{backspace}'); + + await waitFor(() => { + expect(vrInput).toHaveValue(''); + }); + + fireEvent.change(vrInput, { target: { value: '0' } }); + await waitFor(() => { + expect(vrInput).toHaveValue(''); + }); + + fireEvent.change(vrInput, { target: { value: '19' } }); + await waitFor(() => { + expect(vrInput).toHaveValue('19'); + }); + }); + + it('GroupModal -> Update -> No values updated', async () => { + renderGroupModal(link1, itemProps[1]); + expect(screen.getAllByText(t.updateGroup)).toHaveLength(2); + + const submitBtn = screen.getByTestId('submitBtn'); + expect(submitBtn).toBeInTheDocument(); + userEvent.click(submitBtn); + + await waitFor(() => { + expect(toast.success).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupModal.tsx b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupModal.tsx new file mode 100644 index 0000000000..5bfb1eff2b --- /dev/null +++ b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupModal.tsx @@ -0,0 +1,341 @@ +import type { ChangeEvent } from 'react'; +import { Button, Form, Modal } from 'react-bootstrap'; +import type { + InterfaceCreateVolunteerGroup, + InterfaceUserInfo, + InterfaceVolunteerGroupInfo, +} from 'utils/interfaces'; +import styles from '../EventVolunteers.module.css'; +import React, { useCallback, useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useMutation, useQuery } from '@apollo/client'; +import { toast } from 'react-toastify'; +import { Autocomplete, FormControl, TextField } from '@mui/material'; + +import { MEMBERS_LIST } from 'GraphQl/Queries/Queries'; +import { + CREATE_VOLUNTEER_GROUP, + UPDATE_VOLUNTEER_GROUP, +} from 'GraphQl/Mutations/EventVolunteerMutation'; + +export interface InterfaceVolunteerGroupModal { + isOpen: boolean; + hide: () => void; + eventId: string; + orgId: string; + group: InterfaceVolunteerGroupInfo | null; + refetchGroups: () => void; + mode: 'create' | 'edit'; +} + +/** + * A modal dialog for creating or editing a volunteer group. + * + * @param isOpen - Indicates whether the modal is open. + * @param hide - Function to close the modal. + * @param eventId - The ID of the event associated with volunteer group. + * @param orgId - The ID of the organization associated with volunteer group. + * @param group - The volunteer group object to be edited. + * @param refetchGroups - Function to refetch the volunteer groups after creation or update. + * @param mode - The mode of the modal (create or edit). + * @returns The rendered modal component. + * + * The `VolunteerGroupModal` component displays a form within a modal dialog for creating or editing a Volunteer Group. + * It includes fields for entering the group name, description, volunteersRequired, and selecting volunteers/leaders. + * + * The modal includes: + * - A header with a title indicating the current mode (create or edit) and a close button. + * - A form with: + * - An input field for entering the group name. + * - A textarea for entering the group description. + * - A multi-select dropdown for selecting leader. + * - A multi-select dropdown for selecting volunteers. + * - An input field for entering the number of volunteers required. + * - A submit button to create or update the pledge. + * + * On form submission, the component either: + * - Calls `updatePledge` mutation to update an existing pledge, or + * - Calls `createPledge` mutation to create a new pledge. + * + * Success or error messages are displayed using toast notifications based on the result of the mutation. + */ + +const VolunteerGroupModal: React.FC = ({ + isOpen, + hide, + eventId, + orgId, + group, + refetchGroups, + mode, +}) => { + const { t } = useTranslation('translation', { + keyPrefix: 'eventVolunteers', + }); + const { t: tCommon } = useTranslation('common'); + + const [formState, setFormState] = useState({ + name: group?.name ?? '', + description: group?.description ?? '', + leader: group?.leader ?? null, + volunteerUsers: group?.volunteers.map((volunteer) => volunteer.user) ?? [], + volunteersRequired: group?.volunteersRequired ?? null, + }); + const [members, setMembers] = useState([]); + + const [updateVolunteerGroup] = useMutation(UPDATE_VOLUNTEER_GROUP); + const [createVolunteerGroup] = useMutation(CREATE_VOLUNTEER_GROUP); + + const { data: memberData } = useQuery(MEMBERS_LIST, { + variables: { id: orgId }, + }); + + useEffect(() => { + setFormState({ + name: group?.name ?? '', + description: group?.description ?? '', + leader: group?.leader ?? null, + volunteerUsers: + group?.volunteers.map((volunteer) => volunteer.user) ?? [], + volunteersRequired: group?.volunteersRequired ?? null, + }); + }, [group]); + + useEffect(() => { + if (memberData) { + setMembers(memberData.organizations[0].members); + } + }, [memberData]); + + const { name, description, leader, volunteerUsers, volunteersRequired } = + formState; + + const updateGroupHandler = useCallback( + async (e: ChangeEvent): Promise => { + e.preventDefault(); + + const updatedFields: { + [key: string]: number | string | undefined | null; + } = {}; + + if (name !== group?.name) { + updatedFields.name = name; + } + if (description !== group?.description) { + updatedFields.description = description; + } + if (volunteersRequired !== group?.volunteersRequired) { + updatedFields.volunteersRequired = volunteersRequired; + } + try { + await updateVolunteerGroup({ + variables: { + id: group?._id, + data: { ...updatedFields, eventId }, + }, + }); + toast.success(t('volunteerGroupUpdated')); + refetchGroups(); + hide(); + } catch (error: unknown) { + toast.error((error as Error).message); + } + }, + [formState, group], + ); + + // Function to create a new volunteer group + const createGroupHandler = useCallback( + async (e: ChangeEvent): Promise => { + try { + e.preventDefault(); + await createVolunteerGroup({ + variables: { + data: { + eventId, + leaderId: leader?._id, + name, + description, + volunteersRequired, + volunteerUserIds: volunteerUsers.map((user) => user._id), + }, + }, + }); + + toast.success(t('volunteerGroupCreated')); + refetchGroups(); + setFormState({ + name: '', + description: '', + leader: null, + volunteerUsers: [], + volunteersRequired: null, + }); + hide(); + } catch (error: unknown) { + toast.error((error as Error).message); + } + }, + [formState, eventId], + ); + + return ( + + +

    + {t(mode === 'edit' ? 'updateGroup' : 'createGroup')} +

    + +
    + +
    + {/* Input field to enter the group name */} + + + + setFormState({ ...formState, name: e.target.value }) + } + /> + + + {/* Input field to enter the group description */} + + + + setFormState({ ...formState, description: e.target.value }) + } + /> + + + {/* A dropdown to select leader for volunteer group */} + + option._id === value._id} + filterSelectedOptions={true} + getOptionLabel={(member: InterfaceUserInfo): string => + `${member.firstName} ${member.lastName}` + } + onChange={ + /*istanbul ignore next*/ + (_, newLeader): void => { + if (newLeader) { + setFormState({ + ...formState, + leader: newLeader, + volunteerUsers: [...volunteerUsers, newLeader], + }); + } else { + setFormState({ + ...formState, + leader: null, + volunteerUsers: volunteerUsers.filter( + (user) => user._id !== leader?._id, + ), + }); + } + } + } + renderInput={(params) => ( + + )} + /> + + + {/* A Multi-select dropdown to select more than one volunteer */} + + option._id === value._id} + filterSelectedOptions={true} + getOptionLabel={(member: InterfaceUserInfo): string => + `${member.firstName} ${member.lastName}` + } + disabled={mode === 'edit'} + onChange={ + /*istanbul ignore next*/ + (_, newUsers): void => { + setFormState({ + ...formState, + volunteerUsers: newUsers, + }); + } + } + renderInput={(params) => ( + + )} + /> + + + + { + if (parseInt(e.target.value) > 0) { + setFormState({ + ...formState, + volunteersRequired: parseInt(e.target.value), + }); + } else if (e.target.value === '') { + setFormState({ + ...formState, + volunteersRequired: null, + }); + } + }} + /> + + + + {/* Button to submit the volunteer group form */} + +
    +
    +
    + ); +}; +export default VolunteerGroupModal; diff --git a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupViewModal.test.tsx b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupViewModal.test.tsx new file mode 100644 index 0000000000..94c34923a2 --- /dev/null +++ b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupViewModal.test.tsx @@ -0,0 +1,126 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import type { RenderResult } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import i18n from 'utils/i18nForTest'; +import type { InterfaceVolunteerGroupViewModal } from './VolunteerGroupViewModal'; +import VolunteerGroupViewModal from './VolunteerGroupViewModal'; + +const t = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.eventVolunteers ?? {}, + ), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const itemProps: InterfaceVolunteerGroupViewModal[] = [ + { + isOpen: true, + hide: jest.fn(), + group: { + _id: 'groupId', + name: 'Group 1', + description: 'desc', + volunteersRequired: null, + createdAt: '2024-10-25T16:16:32.978Z', + creator: { + _id: 'creatorId1', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + leader: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + volunteers: [ + { + _id: 'volunteerId1', + user: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + }, + ], + assignments: [], + event: { + _id: 'eventId', + }, + }, + }, + { + isOpen: true, + hide: jest.fn(), + group: { + _id: 'groupId', + name: 'Group 1', + description: null, + volunteersRequired: 10, + createdAt: '2024-10-25T16:16:32.978Z', + creator: { + _id: 'creatorId1', + firstName: 'Wilt', + lastName: 'Shepherd', + image: 'img--url', + }, + leader: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: 'img-url', + }, + volunteers: [], + assignments: [], + event: { + _id: 'eventId', + }, + }, + }, +]; + +const renderGroupViewModal = ( + props: InterfaceVolunteerGroupViewModal, +): RenderResult => { + return render( + + + + + + + + + + + , + ); +}; + +describe('Testing VolunteerGroupViewModal', () => { + it('Render VolunteerGroupViewModal (variation 1)', async () => { + renderGroupViewModal(itemProps[0]); + expect(screen.getByText(t.groupDetails)).toBeInTheDocument(); + expect(screen.getByTestId('leader_avatar')).toBeInTheDocument(); + expect(screen.getByTestId('creator_avatar')).toBeInTheDocument(); + }); + + it('Render VolunteerGroupViewModal (variation 2)', async () => { + renderGroupViewModal(itemProps[1]); + expect(screen.getByText(t.groupDetails)).toBeInTheDocument(); + expect(screen.getByTestId('leader_image')).toBeInTheDocument(); + expect(screen.getByTestId('creator_image')).toBeInTheDocument(); + }); +}); diff --git a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupViewModal.tsx b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupViewModal.tsx new file mode 100644 index 0000000000..70994bd4e5 --- /dev/null +++ b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupViewModal.tsx @@ -0,0 +1,235 @@ +import { Button, Form, Modal } from 'react-bootstrap'; +import type { InterfaceVolunteerGroupInfo } from 'utils/interfaces'; +import styles from '../EventVolunteers.module.css'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { + FormControl, + Paper, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + TextField, +} from '@mui/material'; +import Avatar from 'components/Avatar/Avatar'; + +export interface InterfaceVolunteerGroupViewModal { + isOpen: boolean; + hide: () => void; + group: InterfaceVolunteerGroupInfo; +} + +/** + * A modal dialog for viewing volunteer group information for an event. + * + * @param isOpen - Indicates whether the modal is open. + * @param hide - Function to close the modal. + * @param group - The volunteer group to display in the modal. + * + * @returns The rendered modal component. + * + * The `VolunteerGroupViewModal` component displays all the fields of a volunteer group in a modal dialog. + * + * The modal includes: + * - A header with a title and a close button. + * - fields for volunteer name, status, hours volunteered, groups, and assignments. + */ + +const VolunteerGroupViewModal: React.FC = ({ + isOpen, + hide, + group, +}) => { + const { t } = useTranslation('translation', { + keyPrefix: 'eventVolunteers', + }); + const { t: tCommon } = useTranslation('common'); + + const { leader, creator, name, volunteersRequired, description, volunteers } = + group; + + return ( + + +

    {t('groupDetails')}

    + +
    + +
    + {/* Group name & Volunteers Required */} + + + + + {description && ( + + + + )} + + {/* Input field to enter the group description */} + {description && ( + + + + + + )} + + + + {leader.image ? ( + Volunteer + ) : ( +
    + +
    + )} + + ), + }} + /> +
    + + + + {creator.image ? ( + Volunteer + ) : ( +
    + +
    + )} + + ), + }} + /> +
    +
    + {/* Table for Associated Volunteers */} + {volunteers && volunteers.length > 0 && ( + + + Volunteers + + + + + + + Sr. No. + Name + + + + {volunteers.map((volunteer, index) => { + const { firstName, lastName } = volunteer.user; + return ( + + + {index + 1} + + + {firstName + ' ' + lastName} + + + ); + })} + +
    +
    +
    + )} +
    +
    +
    + ); +}; +export default VolunteerGroupViewModal; diff --git a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.mocks.ts b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.mocks.ts new file mode 100644 index 0000000000..b8cc52e875 --- /dev/null +++ b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.mocks.ts @@ -0,0 +1,452 @@ +import { + CREATE_VOLUNTEER_GROUP, + DELETE_VOLUNTEER_GROUP, + UPDATE_VOLUNTEER_GROUP, +} from 'GraphQl/Mutations/EventVolunteerMutation'; +import { EVENT_VOLUNTEER_GROUP_LIST } from 'GraphQl/Queries/EventVolunteerQueries'; +import { MEMBERS_LIST } from 'GraphQl/Queries/Queries'; + +const group1 = { + _id: 'groupId1', + name: 'Group 1', + description: 'desc', + volunteersRequired: null, + createdAt: '2024-10-25T16:16:32.978Z', + creator: { + _id: 'creatorId1', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + leader: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: 'img-url', + }, + volunteers: [ + { + _id: 'volunteerId1', + user: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + }, + ], + assignments: [], + event: { + _id: 'eventId', + }, +}; + +const group2 = { + _id: 'groupId2', + name: 'Group 2', + description: 'desc', + volunteersRequired: null, + createdAt: '2024-10-27T15:25:13.044Z', + creator: { + _id: 'creatorId2', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + leader: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + volunteers: [ + { + _id: 'volunteerId2', + user: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + }, + ], + assignments: [], + event: { + _id: 'eventId', + }, +}; + +const group3 = { + _id: 'groupId3', + name: 'Group 3', + description: 'desc', + volunteersRequired: null, + createdAt: '2024-10-27T15:34:15.889Z', + creator: { + _id: 'creatorId3', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + leader: { + _id: 'userId1', + firstName: 'Bruce', + lastName: 'Garza', + image: null, + }, + volunteers: [ + { + _id: 'volunteerId3', + user: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + }, + ], + assignments: [], + event: { + _id: 'eventId', + }, +}; + +export const MOCKS = [ + { + request: { + query: EVENT_VOLUNTEER_GROUP_LIST, + variables: { + where: { + eventId: 'eventId', + leaderName: null, + name_contains: '', + }, + orderBy: null, + }, + }, + result: { + data: { + getEventVolunteerGroups: [group1, group2, group3], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_GROUP_LIST, + variables: { + where: { + eventId: 'eventId', + leaderName: null, + name_contains: '', + }, + orderBy: 'volunteers_DESC', + }, + }, + result: { + data: { + getEventVolunteerGroups: [group1, group2], + }, + }, + }, + + { + request: { + query: EVENT_VOLUNTEER_GROUP_LIST, + variables: { + where: { + eventId: 'eventId', + leaderName: null, + name_contains: '', + }, + orderBy: 'volunteers_ASC', + }, + }, + result: { + data: { + getEventVolunteerGroups: [group2, group1], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_GROUP_LIST, + variables: { + where: { + eventId: 'eventId', + leaderName: null, + name_contains: '1', + }, + orderBy: null, + }, + }, + result: { + data: { + getEventVolunteerGroups: [group1], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_GROUP_LIST, + variables: { + where: { + eventId: 'eventId', + leaderName: '', + name_contains: null, + }, + orderBy: null, + }, + }, + result: { + data: { + getEventVolunteerGroups: [group1, group2, group3], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_GROUP_LIST, + variables: { + where: { + eventId: 'eventId', + leaderName: 'Bruce', + name_contains: null, + }, + orderBy: null, + }, + }, + result: { + data: { + getEventVolunteerGroups: [group3], + }, + }, + }, + { + request: { + query: MEMBERS_LIST, + variables: { + id: 'orgId', + }, + }, + result: { + data: { + organizations: [ + { + _id: 'orgId', + members: [ + { + _id: 'userId', + firstName: 'Harve', + lastName: 'Lance', + email: 'harve@example.com', + image: '', + organizationsBlockedBy: [], + createdAt: '2024-02-14', + }, + { + _id: 'userId2', + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@example.com', + image: '', + organizationsBlockedBy: [], + createdAt: '2024-02-14', + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: CREATE_VOLUNTEER_GROUP, + variables: { + data: { + eventId: 'eventId', + leaderId: 'userId', + name: 'Group 1', + description: 'desc', + volunteerUserIds: ['userId', 'userId2'], + volunteersRequired: 10, + }, + }, + }, + result: { + data: { + createEventVolunteerGroup: { + _id: 'groupId', + }, + }, + }, + }, + { + request: { + query: DELETE_VOLUNTEER_GROUP, + variables: { + id: 'groupId', + }, + }, + result: { + data: { + removeEventVolunteerGroup: { + _id: 'groupId', + }, + }, + }, + }, + { + request: { + query: UPDATE_VOLUNTEER_GROUP, + variables: { + id: 'groupId', + data: { + eventId: 'eventId', + name: 'Group 2', + description: 'desc new', + volunteersRequired: 10, + }, + }, + }, + result: { + data: { + updateEventVolunteerGroup: { + _id: 'groupId', + }, + }, + }, + }, + { + request: { + query: UPDATE_VOLUNTEER_GROUP, + variables: { + id: 'groupId', + data: { + eventId: 'eventId', + }, + }, + }, + result: { + data: { + updateEventVolunteerGroup: { + _id: 'groupId', + }, + }, + }, + }, +]; + +export const MOCKS_EMPTY = [ + { + request: { + query: EVENT_VOLUNTEER_GROUP_LIST, + variables: { + where: { + eventId: 'eventId', + leaderName: null, + name_contains: '', + }, + orderBy: null, + }, + }, + result: { + data: { + getEventVolunteerGroups: [], + }, + }, + }, +]; + +export const MOCKS_ERROR = [ + { + request: { + query: EVENT_VOLUNTEER_GROUP_LIST, + variables: { + where: { + eventId: 'eventId', + leaderName: null, + name_contains: '', + }, + orderBy: null, + }, + }, + error: new Error('An error occurred'), + }, + { + request: { + query: DELETE_VOLUNTEER_GROUP, + variables: { + id: 'groupId', + }, + }, + error: new Error('An error occurred'), + }, + { + request: { + query: MEMBERS_LIST, + variables: { + id: 'orgId', + }, + }, + result: { + data: { + organizations: [ + { + _id: 'orgId', + members: [ + { + _id: 'userId', + firstName: 'Harve', + lastName: 'Lance', + email: 'harve@example.com', + image: '', + organizationsBlockedBy: [], + createdAt: '2024-02-14', + }, + { + _id: 'userId2', + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@example.com', + image: '', + organizationsBlockedBy: [], + createdAt: '2024-02-14', + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: CREATE_VOLUNTEER_GROUP, + variables: { + data: { + eventId: 'eventId', + leaderId: 'userId', + name: 'Group 1', + description: 'desc', + volunteerUserIds: ['userId', 'userId2'], + volunteersRequired: 10, + }, + }, + }, + error: new Error('An error occurred'), + }, + { + request: { + query: UPDATE_VOLUNTEER_GROUP, + variables: { + id: 'groupId', + data: { + eventId: 'eventId', + name: 'Group 2', + description: 'desc new', + volunteersRequired: 10, + }, + }, + }, + error: new Error('An error occurred'), + }, +]; diff --git a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.test.tsx b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.test.tsx new file mode 100644 index 0000000000..0dcba34a3a --- /dev/null +++ b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.test.tsx @@ -0,0 +1,232 @@ +import React, { act } from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import type { RenderResult } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18n from 'utils/i18nForTest'; +import VolunteerGroups from './VolunteerGroups'; +import type { ApolloLink } from '@apollo/client'; +import { MOCKS, MOCKS_EMPTY, MOCKS_ERROR } from './VolunteerGroups.mocks'; + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(MOCKS_ERROR); +const link3 = new StaticMockLink(MOCKS_EMPTY); +const t = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.eventVolunteers ?? {}, + ), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const debounceWait = async (ms = 300): Promise => { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +}; + +const renderVolunteerGroups = (link: ApolloLink): RenderResult => { + return render( + + + + + + + } + /> +
    } + /> + + + + + + , + ); +}; + +describe('Testing VolunteerGroups Screen', () => { + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId', eventId: 'eventId' }), + })); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('should redirect to fallback URL if URL params are undefined', async () => { + render( + + + + + + } /> +
    } + /> + + + + + , + ); + + await waitFor(() => { + expect(screen.getByTestId('paramsError')).toBeInTheDocument(); + }); + }); + + it('should render Groups screen', async () => { + renderVolunteerGroups(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + }); + + it('Check Sorting Functionality', async () => { + renderVolunteerGroups(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + let sortBtn = await screen.findByTestId('sort'); + expect(sortBtn).toBeInTheDocument(); + + // Sort by members_DESC + fireEvent.click(sortBtn); + const volunteersDESC = await screen.findByTestId('volunteers_DESC'); + expect(volunteersDESC).toBeInTheDocument(); + fireEvent.click(volunteersDESC); + + let groupName = await screen.findAllByTestId('groupName'); + expect(groupName[0]).toHaveTextContent('Group 1'); + + // Sort by members_ASC + sortBtn = await screen.findByTestId('sort'); + expect(sortBtn).toBeInTheDocument(); + fireEvent.click(sortBtn); + const volunteersASC = await screen.findByTestId('volunteers_ASC'); + expect(volunteersASC).toBeInTheDocument(); + fireEvent.click(volunteersASC); + + groupName = await screen.findAllByTestId('groupName'); + expect(groupName[0]).toHaveTextContent('Group 2'); + }); + + it('Search by Groups', async () => { + renderVolunteerGroups(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + const searchToggle = await screen.findByTestId('searchByToggle'); + expect(searchToggle).toBeInTheDocument(); + userEvent.click(searchToggle); + + const searchByGroup = await screen.findByTestId('group'); + expect(searchByGroup).toBeInTheDocument(); + userEvent.click(searchByGroup); + + userEvent.type(searchInput, '1'); + await debounceWait(); + + const groupName = await screen.findAllByTestId('groupName'); + expect(groupName[0]).toHaveTextContent('Group 1'); + }); + + it('Search by Leader', async () => { + renderVolunteerGroups(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + const searchToggle = await screen.findByTestId('searchByToggle'); + expect(searchToggle).toBeInTheDocument(); + userEvent.click(searchToggle); + + const searchByLeader = await screen.findByTestId('leader'); + expect(searchByLeader).toBeInTheDocument(); + userEvent.click(searchByLeader); + + // Search by name on press of ENTER + userEvent.type(searchInput, 'Bruce'); + await debounceWait(); + + const groupName = await screen.findAllByTestId('groupName'); + expect(groupName[0]).toHaveTextContent('Group 1'); + }); + + it('should render screen with No Groups', async () => { + renderVolunteerGroups(link3); + + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + expect(screen.getByText(t.noVolunteerGroups)).toBeInTheDocument(); + }); + }); + + it('Error while fetching groups data', async () => { + renderVolunteerGroups(link2); + + await waitFor(() => { + expect(screen.getByTestId('errorMsg')).toBeInTheDocument(); + }); + }); + + it('Open and close ViewModal', async () => { + renderVolunteerGroups(link1); + + const viewGroupBtn = await screen.findAllByTestId('viewGroupBtn'); + userEvent.click(viewGroupBtn[0]); + + expect(await screen.findByText(t.groupDetails)).toBeInTheDocument(); + userEvent.click(await screen.findByTestId('volunteerViewModalCloseBtn')); + }); + + it('Open and Close Delete Modal', async () => { + renderVolunteerGroups(link1); + + const deleteGroupBtn = await screen.findAllByTestId('deleteGroupBtn'); + userEvent.click(deleteGroupBtn[0]); + + expect(await screen.findByText(t.deleteGroup)).toBeInTheDocument(); + userEvent.click(await screen.findByTestId('modalCloseBtn')); + }); + + it('Open and close GroupModal (Edit)', async () => { + renderVolunteerGroups(link1); + + const editGroupBtn = await screen.findAllByTestId('editGroupBtn'); + userEvent.click(editGroupBtn[0]); + + expect(await screen.findAllByText(t.updateGroup)).toHaveLength(2); + userEvent.click(await screen.findByTestId('modalCloseBtn')); + }); + + it('Open and close GroupModal (Create)', async () => { + renderVolunteerGroups(link1); + + const createGroupBtn = await screen.findByTestId('createGroupBtn'); + userEvent.click(createGroupBtn); + + expect(await screen.findAllByText(t.createGroup)).toHaveLength(2); + userEvent.click(await screen.findByTestId('modalCloseBtn')); + }); +}); diff --git a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.tsx b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.tsx new file mode 100644 index 0000000000..fa98abc9f2 --- /dev/null +++ b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.tsx @@ -0,0 +1,444 @@ +import React, { useCallback, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Button, Dropdown, Form } from 'react-bootstrap'; +import { Navigate, useParams } from 'react-router-dom'; + +import { Search, Sort, WarningAmberRounded } from '@mui/icons-material'; + +import { useQuery } from '@apollo/client'; + +import type { InterfaceVolunteerGroupInfo } from 'utils/interfaces'; +import Loader from 'components/Loader/Loader'; +import { + DataGrid, + type GridCellParams, + type GridColDef, +} from '@mui/x-data-grid'; +import { debounce, Stack } from '@mui/material'; +import Avatar from 'components/Avatar/Avatar'; +import styles from '../EventVolunteers.module.css'; +import { EVENT_VOLUNTEER_GROUP_LIST } from 'GraphQl/Queries/EventVolunteerQueries'; +import VolunteerGroupModal from './VolunteerGroupModal'; +import VolunteerGroupDeleteModal from './VolunteerGroupDeleteModal'; +import VolunteerGroupViewModal from './VolunteerGroupViewModal'; + +enum ModalState { + SAME = 'same', + DELETE = 'delete', + VIEW = 'view', +} + +const dataGridStyle = { + '&.MuiDataGrid-root .MuiDataGrid-cell:focus-within': { + outline: 'none !important', + }, + '&.MuiDataGrid-root .MuiDataGrid-columnHeader:focus-within': { + outline: 'none', + }, + '& .MuiDataGrid-row:hover': { + backgroundColor: 'transparent', + }, + '& .MuiDataGrid-row.Mui-hovered': { + backgroundColor: 'transparent', + }, + '& .MuiDataGrid-root': { + borderRadius: '0.5rem', + }, + '& .MuiDataGrid-main': { + borderRadius: '0.5rem', + }, +}; + +/** + * Component for managing volunteer groups for an event. + * This component allows users to view, filter, sort, and create action items. It also provides a modal for creating and editing action items. + * @returns The rendered component. + */ +function volunteerGroups(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'eventVolunteers', + }); + const { t: tCommon } = useTranslation('common'); + const { t: tErrors } = useTranslation('errors'); + + // Get the organization ID from URL parameters + const { orgId, eventId } = useParams(); + + if (!orgId || !eventId) { + return ; + } + + const [group, setGroup] = useState(null); + const [modalMode, setModalMode] = useState<'create' | 'edit'>('create'); + const [searchValue, setSearchValue] = useState(''); + const [searchTerm, setSearchTerm] = useState(''); + const [sortBy, setSortBy] = useState< + 'volunteers_ASC' | 'volunteers_DESC' | null + >(null); + const [searchBy, setSearchBy] = useState<'leader' | 'group'>('group'); + const [modalState, setModalState] = useState<{ + [key in ModalState]: boolean; + }>({ + [ModalState.SAME]: false, + [ModalState.DELETE]: false, + [ModalState.VIEW]: false, + }); + + /** + * Query to fetch the list of volunteer groups for the event. + */ + const { + data: groupsData, + loading: groupsLoading, + error: groupsError, + refetch: refetchGroups, + }: { + data?: { + getEventVolunteerGroups: InterfaceVolunteerGroupInfo[]; + }; + loading: boolean; + error?: Error | undefined; + refetch: () => void; + } = useQuery(EVENT_VOLUNTEER_GROUP_LIST, { + variables: { + where: { + eventId: eventId, + leaderName: searchBy === 'leader' ? searchTerm : null, + name_contains: searchBy === 'group' ? searchTerm : null, + }, + orderBy: sortBy, + }, + }); + + const openModal = (modal: ModalState): void => + setModalState((prevState) => ({ ...prevState, [modal]: true })); + + const closeModal = (modal: ModalState): void => + setModalState((prevState) => ({ ...prevState, [modal]: false })); + + const handleModalClick = useCallback( + (group: InterfaceVolunteerGroupInfo | null, modal: ModalState): void => { + if (modal === ModalState.SAME) { + setModalMode(group ? 'edit' : 'create'); + } + setGroup(group); + openModal(modal); + }, + [openModal], + ); + + const debouncedSearch = useMemo( + () => debounce((value: string) => setSearchTerm(value), 300), + [], + ); + + const groups = useMemo( + () => groupsData?.getEventVolunteerGroups || [], + [groupsData], + ); + + if (groupsLoading) { + return ; + } + + if (groupsError) { + return ( +
    + +
    + {tErrors('errorLoading', { entity: 'Volunteer Groups' })} +
    +
    + ); + } + + const columns: GridColDef[] = [ + { + field: 'group', + headerName: 'Group', + flex: 1, + align: 'left', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( +
    + {params.row.name} +
    + ); + }, + }, + { + field: 'leader', + headerName: 'Leader', + flex: 1, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + const { _id, firstName, lastName, image } = params.row.leader; + return ( +
    + {image ? ( + Assignee + ) : ( +
    + +
    + )} + {firstName + ' ' + lastName} +
    + ); + }, + }, + { + field: 'actions', + headerName: 'Actions Completed', + flex: 1, + align: 'center', + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( +
    + {params.row.assignments.length} +
    + ); + }, + }, + { + field: 'volunteers', + headerName: 'No. of Volunteers', + flex: 1, + align: 'center', + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( +
    + {params.row.volunteers.length} +
    + ); + }, + }, + { + field: 'options', + headerName: 'Options', + align: 'center', + flex: 1, + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( + <> + + + + + ); + }, + }, + ]; + + return ( +
    + {/* Header with search, filter and Create Button */} +
    +
    + { + setSearchValue(e.target.value); + debouncedSearch(e.target.value); + }} + data-testid="searchBy" + /> + +
    +
    +
    + + + + {tCommon('searchBy', { item: '' })} + + + setSearchBy('leader')} + data-testid="leader" + > + {t('leader')} + + setSearchBy('group')} + data-testid="group" + > + {t('group')} + + + + + + + {tCommon('sort')} + + + setSortBy('volunteers_DESC')} + data-testid="volunteers_DESC" + > + {t('mostVolunteers')} + + setSortBy('volunteers_ASC')} + data-testid="volunteers_ASC" + > + {t('leastVolunteers')} + + + +
    +
    + +
    +
    +
    + + {/* Table with Volunteer Groups */} + row._id} + slots={{ + noRowsOverlay: () => ( + + {t('noVolunteerGroups')} + + ), + }} + sx={dataGridStyle} + getRowClassName={() => `${styles.rowBackground}`} + autoHeight + rowHeight={65} + rows={groups.map((group, index) => ({ + id: index + 1, + ...group, + }))} + columns={columns} + isRowSelectable={() => false} + /> + + closeModal(ModalState.SAME)} + refetchGroups={refetchGroups} + eventId={eventId} + orgId={orgId} + group={group} + mode={modalMode} + /> + + {group && ( + <> + closeModal(ModalState.VIEW)} + group={group} + /> + + closeModal(ModalState.DELETE)} + refetchGroups={refetchGroups} + group={group} + /> + + )} +
    + ); +} + +export default volunteerGroups; diff --git a/src/screens/EventVolunteers/Volunteers/VolunteerCreateModal.test.tsx b/src/screens/EventVolunteers/Volunteers/VolunteerCreateModal.test.tsx new file mode 100644 index 0000000000..cac8fe94f0 --- /dev/null +++ b/src/screens/EventVolunteers/Volunteers/VolunteerCreateModal.test.tsx @@ -0,0 +1,122 @@ +import React from 'react'; +import type { ApolloLink } from '@apollo/client'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import type { RenderResult } from '@testing-library/react'; +import { + fireEvent, + render, + screen, + waitFor, + within, +} from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import i18n from 'utils/i18nForTest'; +import { MOCKS, MOCKS_ERROR } from './Volunteers.mocks'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { toast } from 'react-toastify'; +import type { InterfaceVolunteerCreateModal } from './VolunteerCreateModal'; +import VolunteerCreateModal from './VolunteerCreateModal'; +import userEvent from '@testing-library/user-event'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(MOCKS_ERROR); +const t = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.eventVolunteers ?? {}, + ), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const itemProps: InterfaceVolunteerCreateModal[] = [ + { + isOpen: true, + hide: jest.fn(), + eventId: 'eventId', + orgId: 'orgId', + refetchVolunteers: jest.fn(), + }, +]; + +const renderCreateModal = ( + link: ApolloLink, + props: InterfaceVolunteerCreateModal, +): RenderResult => { + return render( + + + + + + + + + + + , + ); +}; + +describe('Testing VolunteerCreateModal', () => { + it('VolunteerCreateModal -> Create', async () => { + renderCreateModal(link1, itemProps[0]); + expect(screen.getAllByText(t.addVolunteer)).toHaveLength(2); + + // Select Volunteers + const membersSelect = await screen.findByTestId('membersSelect'); + expect(membersSelect).toBeInTheDocument(); + const volunteerInputField = within(membersSelect).getByRole('combobox'); + fireEvent.mouseDown(volunteerInputField); + + const volunteerOption = await screen.findByText('John Doe'); + expect(volunteerOption).toBeInTheDocument(); + fireEvent.click(volunteerOption); + + const submitBtn = screen.getByTestId('submitBtn'); + expect(submitBtn).toBeInTheDocument(); + userEvent.click(submitBtn); + + await waitFor(() => { + expect(toast.success).toHaveBeenCalledWith(t.volunteerAdded); + expect(itemProps[0].refetchVolunteers).toHaveBeenCalled(); + expect(itemProps[0].hide).toHaveBeenCalled(); + }); + }); + + it('VolunteerCreateModal -> Create -> Error', async () => { + renderCreateModal(link2, itemProps[0]); + expect(screen.getAllByText(t.addVolunteer)).toHaveLength(2); + + // Select Volunteers + const membersSelect = await screen.findByTestId('membersSelect'); + expect(membersSelect).toBeInTheDocument(); + const volunteerInputField = within(membersSelect).getByRole('combobox'); + fireEvent.mouseDown(volunteerInputField); + + const volunteerOption = await screen.findByText('John Doe'); + expect(volunteerOption).toBeInTheDocument(); + fireEvent.click(volunteerOption); + + const submitBtn = screen.getByTestId('submitBtn'); + expect(submitBtn).toBeInTheDocument(); + userEvent.click(submitBtn); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/screens/EventVolunteers/Volunteers/VolunteerCreateModal.tsx b/src/screens/EventVolunteers/Volunteers/VolunteerCreateModal.tsx new file mode 100644 index 0000000000..6b4a1e3f0c --- /dev/null +++ b/src/screens/EventVolunteers/Volunteers/VolunteerCreateModal.tsx @@ -0,0 +1,152 @@ +import type { ChangeEvent } from 'react'; +import { Button, Form, Modal } from 'react-bootstrap'; +import type { InterfaceUserInfo } from 'utils/interfaces'; +import styles from '../EventVolunteers.module.css'; +import React, { useCallback, useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useMutation, useQuery } from '@apollo/client'; +import { toast } from 'react-toastify'; +import { Autocomplete, TextField } from '@mui/material'; + +import { MEMBERS_LIST } from 'GraphQl/Queries/Queries'; +import { ADD_VOLUNTEER } from 'GraphQl/Mutations/EventVolunteerMutation'; + +export interface InterfaceVolunteerCreateModal { + isOpen: boolean; + hide: () => void; + eventId: string; + orgId: string; + refetchVolunteers: () => void; +} + +/** + * A modal dialog for add a volunteer for an event. + * + * @param isOpen - Indicates whether the modal is open. + * @param hide - Function to close the modal. + * @param eventId - The ID of the event associated with volunteer. + * @param orgId - The ID of the organization associated with volunteer. + * @param refetchVolunteers - Function to refetch the volunteers after adding a volunteer. + * + * @returns The rendered modal component. + * + * The `VolunteerCreateModal` component displays a form within a modal dialog for adding a volunteer. + * It includes fields for selecting user. + * + * The modal includes: + * - A header with a title and a close button. + * - A form with: + * - A multi-select dropdown for selecting user be added as volunteer. + * - A submit button to create or update the pledge. + * + * On form submission, the component: + * - Calls `addVolunteer` mutation to add a new Volunteer. + * + * Success or error messages are displayed using toast notifications based on the result of the mutation. + */ + +const VolunteerCreateModal: React.FC = ({ + isOpen, + hide, + eventId, + orgId, + refetchVolunteers, +}) => { + const { t } = useTranslation('translation', { + keyPrefix: 'eventVolunteers', + }); + + const [userId, setUserId] = useState(''); + const [members, setMembers] = useState([]); + const [addVolunteer] = useMutation(ADD_VOLUNTEER); + + const { data: memberData } = useQuery(MEMBERS_LIST, { + variables: { id: orgId }, + }); + + useEffect(() => { + if (memberData) { + setMembers(memberData.organizations[0].members); + } + }, [memberData]); + + // Function to add a volunteer for an event + const addVolunteerHandler = useCallback( + async (e: ChangeEvent): Promise => { + try { + e.preventDefault(); + await addVolunteer({ + variables: { + data: { + eventId, + userId, + }, + }, + }); + + toast.success(t('volunteerAdded')); + refetchVolunteers(); + setUserId(''); + hide(); + } catch (error: unknown) { + toast.error((error as Error).message); + } + }, + [userId, eventId], + ); + + return ( + + +

    {t('addVolunteer')}

    + +
    + +
    + {/* A Multi-select dropdown enables admin to invite a member as volunteer */} + + option._id === value._id} + filterSelectedOptions={true} + getOptionLabel={(member: InterfaceUserInfo): string => + `${member.firstName} ${member.lastName}` + } + onChange={ + /*istanbul ignore next*/ + (_, newVolunteer): void => { + setUserId(newVolunteer?._id ?? ''); + } + } + renderInput={(params) => } + /> + + + {/* Button to submit the volunteer form */} + +
    +
    +
    + ); +}; +export default VolunteerCreateModal; diff --git a/src/screens/EventVolunteers/Volunteers/VolunteerDeleteModal.test.tsx b/src/screens/EventVolunteers/Volunteers/VolunteerDeleteModal.test.tsx new file mode 100644 index 0000000000..dd9d6d5985 --- /dev/null +++ b/src/screens/EventVolunteers/Volunteers/VolunteerDeleteModal.test.tsx @@ -0,0 +1,129 @@ +import React from 'react'; +import type { ApolloLink } from '@apollo/client'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import type { RenderResult } from '@testing-library/react'; +import { render, screen, waitFor } from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import i18n from 'utils/i18nForTest'; +import { MOCKS, MOCKS_ERROR } from './Volunteers.mocks'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { toast } from 'react-toastify'; +import type { InterfaceDeleteVolunteerModal } from './VolunteerDeleteModal'; +import VolunteerDeleteModal from './VolunteerDeleteModal'; +import userEvent from '@testing-library/user-event'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(MOCKS_ERROR); +const t = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.eventVolunteers ?? {}, + ), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const itemProps: InterfaceDeleteVolunteerModal[] = [ + { + isOpen: true, + hide: jest.fn(), + refetchVolunteers: jest.fn(), + volunteer: { + _id: 'volunteerId1', + hasAccepted: true, + hoursVolunteered: 10, + user: { + _id: 'userId1', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + assignments: [], + groups: [ + { + _id: 'groupId1', + name: 'group1', + volunteers: [ + { + _id: 'volunteerId1', + }, + ], + }, + ], + }, + }, +]; + +const renderVolunteerDeleteModal = ( + link: ApolloLink, + props: InterfaceDeleteVolunteerModal, +): RenderResult => { + return render( + + + + + + + + + + + , + ); +}; + +describe('Testing Volunteer Delete Modal', () => { + it('Delete Volunteer', async () => { + renderVolunteerDeleteModal(link1, itemProps[0]); + expect(screen.getByText(t.removeVolunteer)).toBeInTheDocument(); + + const yesBtn = screen.getByTestId('deleteyesbtn'); + expect(yesBtn).toBeInTheDocument(); + userEvent.click(yesBtn); + + await waitFor(() => { + expect(itemProps[0].refetchVolunteers).toHaveBeenCalled(); + expect(itemProps[0].hide).toHaveBeenCalled(); + expect(toast.success).toHaveBeenCalledWith(t.volunteerRemoved); + }); + }); + + it('Close Delete Modal', async () => { + renderVolunteerDeleteModal(link1, itemProps[0]); + expect(screen.getByText(t.removeVolunteer)).toBeInTheDocument(); + + const noBtn = screen.getByTestId('deletenobtn'); + expect(noBtn).toBeInTheDocument(); + userEvent.click(noBtn); + + await waitFor(() => { + expect(itemProps[0].hide).toHaveBeenCalled(); + }); + }); + + it('Delete Volunteer -> Error', async () => { + renderVolunteerDeleteModal(link2, itemProps[0]); + expect(screen.getByText(t.removeVolunteer)).toBeInTheDocument(); + + const yesBtn = screen.getByTestId('deleteyesbtn'); + expect(yesBtn).toBeInTheDocument(); + userEvent.click(yesBtn); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/screens/EventVolunteers/Volunteers/VolunteerDeleteModal.tsx b/src/screens/EventVolunteers/Volunteers/VolunteerDeleteModal.tsx new file mode 100644 index 0000000000..8f253fdf50 --- /dev/null +++ b/src/screens/EventVolunteers/Volunteers/VolunteerDeleteModal.tsx @@ -0,0 +1,103 @@ +import { Button, Modal } from 'react-bootstrap'; +import styles from '../EventVolunteers.module.css'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { useMutation } from '@apollo/client'; +import type { InterfaceEventVolunteerInfo } from 'utils/interfaces'; +import { toast } from 'react-toastify'; +import { DELETE_VOLUNTEER } from 'GraphQl/Mutations/EventVolunteerMutation'; + +export interface InterfaceDeleteVolunteerModal { + isOpen: boolean; + hide: () => void; + volunteer: InterfaceEventVolunteerInfo; + refetchVolunteers: () => void; +} + +/** + * A modal dialog for confirming the deletion of a volunteer. + * + * @param isOpen - Indicates whether the modal is open. + * @param hide - Function to close the modal. + * @param volunteer - The volunteer object to be deleted. + * @param refetchVolunteers - Function to refetch the volunteers after deletion. + * + * @returns The rendered modal component. + * + * + * The `VolunteerDeleteModal` component displays a confirmation dialog when a user attempts to delete a volunteer. + * It allows the user to either confirm or cancel the deletion. + * On confirmation, the `deleteVolunteer` mutation is called to remove the pledge from the database, + * and the `refetchVolunteers` function is invoked to update the list of volunteers. + * A success or error toast notification is shown based on the result of the deletion operation. + * + * The modal includes: + * - A header with a title and a close button. + * - A body with a message asking for confirmation. + * - A footer with "Yes" and "No" buttons to confirm or cancel the deletion. + * + * The `deleteVolunteer` mutation is used to perform the deletion operation. + */ + +const VolunteerDeleteModal: React.FC = ({ + isOpen, + hide, + volunteer, + refetchVolunteers, +}) => { + const { t } = useTranslation('translation', { + keyPrefix: 'eventVolunteers', + }); + const { t: tCommon } = useTranslation('common'); + + const [deleteVolunteer] = useMutation(DELETE_VOLUNTEER); + + const deleteHandler = async (): Promise => { + try { + await deleteVolunteer({ + variables: { + id: volunteer._id, + }, + }); + refetchVolunteers(); + hide(); + toast.success(t('volunteerRemoved')); + } catch (error: unknown) { + toast.error((error as Error).message); + } + }; + return ( + <> + + +

    {t('removeVolunteer')}

    + +
    + +

    {t('removeVolunteerMsg')}

    +
    + + + + +
    + + ); +}; +export default VolunteerDeleteModal; diff --git a/src/screens/EventVolunteers/Volunteers/VolunteerViewModal.test.tsx b/src/screens/EventVolunteers/Volunteers/VolunteerViewModal.test.tsx new file mode 100644 index 0000000000..155dba8464 --- /dev/null +++ b/src/screens/EventVolunteers/Volunteers/VolunteerViewModal.test.tsx @@ -0,0 +1,101 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import type { RenderResult } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import i18n from 'utils/i18nForTest'; +import type { InterfaceVolunteerViewModal } from './VolunteerViewModal'; +import VolunteerViewModal from './VolunteerViewModal'; + +const t = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.eventVolunteers ?? {}, + ), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const itemProps: InterfaceVolunteerViewModal[] = [ + { + isOpen: true, + hide: jest.fn(), + volunteer: { + _id: 'volunteerId1', + hasAccepted: true, + hoursVolunteered: 10, + user: { + _id: 'userId1', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + assignments: [], + groups: [ + { + _id: 'groupId1', + name: 'group1', + volunteers: [ + { + _id: 'volunteerId1', + }, + ], + }, + ], + }, + }, + { + isOpen: true, + hide: jest.fn(), + volunteer: { + _id: 'volunteerId2', + hasAccepted: false, + hoursVolunteered: null, + user: { + _id: 'userId3', + firstName: 'Bruce', + lastName: 'Graza', + image: 'img-url', + }, + assignments: [], + groups: [], + }, + }, +]; + +const renderVolunteerViewModal = ( + props: InterfaceVolunteerViewModal, +): RenderResult => { + return render( + + + + + + + + + + + , + ); +}; + +describe('Testing VolunteerViewModal', () => { + it('Render VolunteerViewModal (variation 1)', async () => { + renderVolunteerViewModal(itemProps[0]); + expect(screen.getByText(t.volunteerDetails)).toBeInTheDocument(); + expect(screen.getByTestId('volunteer_avatar')).toBeInTheDocument(); + }); + + it('Render VolunteerViewModal (variation 2)', async () => { + renderVolunteerViewModal(itemProps[1]); + expect(screen.getByText(t.volunteerDetails)).toBeInTheDocument(); + expect(screen.getByTestId('volunteer_image')).toBeInTheDocument(); + }); +}); diff --git a/src/screens/EventVolunteers/Volunteers/VolunteerViewModal.tsx b/src/screens/EventVolunteers/Volunteers/VolunteerViewModal.tsx new file mode 100644 index 0000000000..0904d34b9c --- /dev/null +++ b/src/screens/EventVolunteers/Volunteers/VolunteerViewModal.tsx @@ -0,0 +1,202 @@ +import { Button, Form, Modal } from 'react-bootstrap'; +import type { InterfaceEventVolunteerInfo } from 'utils/interfaces'; +import styles from '../EventVolunteers.module.css'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { + FormControl, + Paper, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + TextField, +} from '@mui/material'; +import Avatar from 'components/Avatar/Avatar'; +import { HistoryToggleOff, TaskAlt } from '@mui/icons-material'; + +export interface InterfaceVolunteerViewModal { + isOpen: boolean; + hide: () => void; + volunteer: InterfaceEventVolunteerInfo; +} + +/** + * A modal dialog for viewing volunteer information for an event. + * + * @param isOpen - Indicates whether the modal is open. + * @param hide - Function to close the modal. + * @param volunteer - The volunteer object to be displayed. + * + * @returns The rendered modal component. + * + * The `VolunteerViewModal` component displays all the fields of a volunteer in a modal dialog. + * + * The modal includes: + * - A header with a title and a close button. + * - fields for volunteer name, status, hours volunteered, groups, and assignments. + */ + +const VolunteerViewModal: React.FC = ({ + isOpen, + hide, + volunteer, +}) => { + const { t } = useTranslation('translation', { + keyPrefix: 'eventVolunteers', + }); + const { t: tCommon } = useTranslation('common'); + + const { user, hasAccepted, hoursVolunteered, groups } = volunteer; + + return ( + + +

    {t('volunteerDetails')}

    + +
    + +
    + {/* Volunteer Name & Avatar */} + + + + {user.image ? ( + Volunteer + ) : ( +
    + +
    + )} + + ), + }} + /> +
    +
    + {/* Status and hours volunteered */} + + + {hasAccepted ? ( + + ) : ( + + )} + + ), + style: { + color: hasAccepted ? 'green' : '#ed6c02', + }, + }} + inputProps={{ + style: { + WebkitTextFillColor: hasAccepted ? 'green' : '#ed6c02', + }, + }} + disabled + /> + + + + {/* Table for Associated Volunteer Groups */} + {groups && groups.length > 0 && ( + + + Volunteer Groups Joined + + + + + + + Sr. No. + Group Name + + No. of Members + + + + + {groups.map((group, index) => { + const { _id, name, volunteers } = group; + return ( + + + {index + 1} + + + {name} + + + {volunteers.length} + + + ); + })} + +
    +
    +
    + )} +
    +
    +
    + ); +}; +export default VolunteerViewModal; diff --git a/src/screens/EventVolunteers/Volunteers/Volunteers.mocks.ts b/src/screens/EventVolunteers/Volunteers/Volunteers.mocks.ts new file mode 100644 index 0000000000..72c927b8ff --- /dev/null +++ b/src/screens/EventVolunteers/Volunteers/Volunteers.mocks.ts @@ -0,0 +1,303 @@ +import { + ADD_VOLUNTEER, + DELETE_VOLUNTEER, +} from 'GraphQl/Mutations/EventVolunteerMutation'; +import { EVENT_VOLUNTEER_LIST } from 'GraphQl/Queries/EventVolunteerQueries'; +import { MEMBERS_LIST } from 'GraphQl/Queries/Queries'; + +const volunteer1 = { + _id: 'volunteerId1', + hasAccepted: true, + hoursVolunteered: 10, + user: { + _id: 'userId1', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + assignments: [], + groups: [ + { + _id: 'groupId1', + name: 'group1', + volunteers: [ + { + _id: 'volunteerId1', + }, + ], + }, + ], +}; + +const volunteer2 = { + _id: 'volunteerId2', + hasAccepted: false, + hoursVolunteered: null, + user: { + _id: 'userId3', + firstName: 'Bruce', + lastName: 'Graza', + image: 'img-url', + }, + assignments: [], + groups: [], +}; + +export const MOCKS = [ + { + request: { + query: EVENT_VOLUNTEER_LIST, + variables: { + where: { eventId: 'eventId', name_contains: '' }, + orderBy: null, + }, + }, + result: { + data: { + getEventVolunteers: [volunteer1, volunteer2], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_LIST, + variables: { + where: { eventId: 'eventId', name_contains: '' }, + orderBy: 'hoursVolunteered_ASC', + }, + }, + result: { + data: { + getEventVolunteers: [volunteer2, volunteer1], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_LIST, + variables: { + where: { eventId: 'eventId', name_contains: '' }, + orderBy: 'hoursVolunteered_DESC', + }, + }, + result: { + data: { + getEventVolunteers: [volunteer1, volunteer2], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_LIST, + variables: { + where: { eventId: 'eventId', name_contains: 'T' }, + orderBy: null, + }, + }, + result: { + data: { + getEventVolunteers: [volunteer1], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_LIST, + variables: { + where: { eventId: 'eventId', name_contains: '', hasAccepted: false }, + orderBy: null, + }, + }, + result: { + data: { + getEventVolunteers: [volunteer2], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_LIST, + variables: { + where: { eventId: 'eventId', name_contains: '', hasAccepted: false }, + orderBy: null, + }, + }, + result: { + data: { + getEventVolunteers: [volunteer2], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_LIST, + variables: { + where: { eventId: 'eventId', name_contains: '', hasAccepted: true }, + orderBy: null, + }, + }, + result: { + data: { + getEventVolunteers: [volunteer1], + }, + }, + }, + { + request: { + query: DELETE_VOLUNTEER, + variables: { + id: 'volunteerId1', + }, + }, + result: { + data: { + removeEventVolunteer: { + _id: 'volunteerId1', + }, + }, + }, + }, + { + request: { + query: MEMBERS_LIST, + variables: { + id: 'orgId', + }, + }, + result: { + data: { + organizations: [ + { + _id: 'orgId', + members: [ + { + _id: 'userId2', + firstName: 'Harve', + lastName: 'Lance', + email: 'harve@example.com', + image: '', + organizationsBlockedBy: [], + createdAt: '2024-02-14', + }, + { + _id: 'userId3', + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@example.com', + image: '', + organizationsBlockedBy: [], + createdAt: '2024-02-14', + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: ADD_VOLUNTEER, + variables: { + data: { + eventId: 'eventId', + userId: 'userId3', + }, + }, + }, + result: { + data: { + createEventVolunteer: { + _id: 'volunteerId1', + }, + }, + }, + }, +]; + +export const MOCKS_ERROR = [ + { + request: { + query: EVENT_VOLUNTEER_LIST, + variables: { + where: { eventId: 'eventId', name_contains: '' }, + orderBy: null, + }, + }, + error: new Error('An error occurred'), + }, + { + request: { + query: DELETE_VOLUNTEER, + variables: { + id: 'volunteerId1', + }, + }, + error: new Error('An error occurred'), + }, + { + request: { + query: MEMBERS_LIST, + variables: { + id: 'orgId', + }, + }, + result: { + data: { + organizations: [ + { + _id: 'orgId', + members: [ + { + _id: 'userId2', + firstName: 'Harve', + lastName: 'Lance', + email: 'harve@example.com', + image: '', + organizationsBlockedBy: [], + createdAt: '2024-02-14', + }, + { + _id: 'userId3', + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@example.com', + image: '', + organizationsBlockedBy: [], + createdAt: '2024-02-14', + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: ADD_VOLUNTEER, + variables: { + data: { + eventId: 'eventId', + userId: 'userId3', + }, + }, + }, + error: new Error('An error occurred'), + }, +]; + +export const MOCKS_EMPTY = [ + { + request: { + query: EVENT_VOLUNTEER_LIST, + variables: { + where: { eventId: 'eventId', name_contains: '' }, + orderBy: null, + }, + }, + result: { + data: { + getEventVolunteers: [], + }, + }, + }, +]; diff --git a/src/screens/EventVolunteers/Volunteers/Volunteers.test.tsx b/src/screens/EventVolunteers/Volunteers/Volunteers.test.tsx new file mode 100644 index 0000000000..2af25b0b84 --- /dev/null +++ b/src/screens/EventVolunteers/Volunteers/Volunteers.test.tsx @@ -0,0 +1,245 @@ +import React, { act } from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import type { RenderResult } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18n from 'utils/i18nForTest'; +import Volunteers from './Volunteers'; +import type { ApolloLink } from '@apollo/client'; +import { MOCKS, MOCKS_EMPTY, MOCKS_ERROR } from './Volunteers.mocks'; + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(MOCKS_ERROR); +const link3 = new StaticMockLink(MOCKS_EMPTY); +const t = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.eventVolunteers ?? {}, + ), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const debounceWait = async (ms = 300): Promise => { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +}; + +const renderVolunteers = (link: ApolloLink): RenderResult => { + return render( + + + + + + + } /> +
    } + /> + + + + + + , + ); +}; + +describe('Testing Volunteers Screen', () => { + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId', eventId: 'eventId' }), + })); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('should redirect to fallback URL if URL params are undefined', async () => { + render( + + + + + + } /> +
    } + /> + + + + + , + ); + + await waitFor(() => { + expect(screen.getByTestId('paramsError')).toBeInTheDocument(); + }); + }); + + it('should render Volunteers screen', async () => { + renderVolunteers(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + }); + + it('Check Sorting Functionality', async () => { + renderVolunteers(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + let sortBtn = await screen.findByTestId('sort'); + expect(sortBtn).toBeInTheDocument(); + + // Sort by hoursVolunteered_DESC + fireEvent.click(sortBtn); + const hoursVolunteeredDESC = await screen.findByTestId( + 'hoursVolunteered_DESC', + ); + expect(hoursVolunteeredDESC).toBeInTheDocument(); + fireEvent.click(hoursVolunteeredDESC); + + let volunteerName = await screen.findAllByTestId('volunteerName'); + expect(volunteerName[0]).toHaveTextContent('Teresa Bradley'); + + // Sort by hoursVolunteered_ASC + sortBtn = await screen.findByTestId('sort'); + expect(sortBtn).toBeInTheDocument(); + fireEvent.click(sortBtn); + const hoursVolunteeredASC = await screen.findByTestId( + 'hoursVolunteered_ASC', + ); + expect(hoursVolunteeredASC).toBeInTheDocument(); + fireEvent.click(hoursVolunteeredASC); + + volunteerName = await screen.findAllByTestId('volunteerName'); + expect(volunteerName[0]).toHaveTextContent('Bruce Graza'); + }); + + it('Filter Volunteers by status (All)', async () => { + renderVolunteers(link1); + + const filterBtn = await screen.findByTestId('filter'); + expect(filterBtn).toBeInTheDocument(); + + // Filter by All + fireEvent.click(filterBtn); + await waitFor(() => { + expect(screen.getByTestId('statusAll')).toBeInTheDocument(); + }); + fireEvent.click(screen.getByTestId('statusAll')); + + const volunteerName = await screen.findAllByTestId('volunteerName'); + expect(volunteerName).toHaveLength(2); + }); + + it('Filter Volunteers by status (Pending)', async () => { + renderVolunteers(link1); + + const filterBtn = await screen.findByTestId('filter'); + expect(filterBtn).toBeInTheDocument(); + + // Filter by Pending + fireEvent.click(filterBtn); + await waitFor(() => { + expect(screen.getByTestId('statusPending')).toBeInTheDocument(); + }); + fireEvent.click(screen.getByTestId('statusPending')); + + const volunteerName = await screen.findAllByTestId('volunteerName'); + expect(volunteerName[0]).toHaveTextContent('Bruce Graza'); + }); + + it('Filter Volunteers by status (Accepted)', async () => { + renderVolunteers(link1); + + const filterBtn = await screen.findByTestId('filter'); + expect(filterBtn).toBeInTheDocument(); + + // Filter by Accepted + fireEvent.click(filterBtn); + await waitFor(() => { + expect(screen.getByTestId('statusAccepted')).toBeInTheDocument(); + }); + fireEvent.click(screen.getByTestId('statusAccepted')); + + const volunteerName = await screen.findAllByTestId('volunteerName'); + expect(volunteerName[0]).toHaveTextContent('Teresa Bradley'); + }); + + it('Search', async () => { + renderVolunteers(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + userEvent.type(searchInput, 'T'); + await debounceWait(); + + const volunteerName = await screen.findAllByTestId('volunteerName'); + expect(volunteerName[0]).toHaveTextContent('Teresa Bradley'); + }); + + it('should render screen with No Volunteers', async () => { + renderVolunteers(link3); + + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + expect(screen.getByText(t.noVolunteers)).toBeInTheDocument(); + }); + }); + + it('Error while fetching volunteers data', async () => { + renderVolunteers(link2); + + await waitFor(() => { + expect(screen.getByTestId('errorMsg')).toBeInTheDocument(); + }); + }); + + it('Open and close Volunteer Modal (View)', async () => { + renderVolunteers(link1); + + const viewItemBtn = await screen.findAllByTestId('viewItemBtn'); + userEvent.click(viewItemBtn[0]); + + expect(await screen.findByText(t.volunteerDetails)).toBeInTheDocument(); + userEvent.click(await screen.findByTestId('modalCloseBtn')); + }); + + it('Open and Close Volunteer Modal (Delete)', async () => { + renderVolunteers(link1); + + const deleteItemBtn = await screen.findAllByTestId('deleteItemBtn'); + userEvent.click(deleteItemBtn[0]); + + expect(await screen.findByText(t.removeVolunteer)).toBeInTheDocument(); + userEvent.click(await screen.findByTestId('modalCloseBtn')); + }); + + it('Open and close Volunteer Modal (Create)', async () => { + renderVolunteers(link1); + + const addVolunteerBtn = await screen.findByTestId('addVolunteerBtn'); + userEvent.click(addVolunteerBtn); + + expect(await screen.findAllByText(t.addVolunteer)).toHaveLength(2); + userEvent.click(await screen.findByTestId('modalCloseBtn')); + }); +}); diff --git a/src/screens/EventVolunteers/Volunteers/Volunteers.tsx b/src/screens/EventVolunteers/Volunteers/Volunteers.tsx new file mode 100644 index 0000000000..770bd35ef4 --- /dev/null +++ b/src/screens/EventVolunteers/Volunteers/Volunteers.tsx @@ -0,0 +1,462 @@ +import React, { useCallback, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Button, Dropdown, Form } from 'react-bootstrap'; +import { Navigate, useParams } from 'react-router-dom'; + +import { + Circle, + FilterAltOutlined, + Search, + Sort, + WarningAmberRounded, +} from '@mui/icons-material'; + +import { useQuery } from '@apollo/client'; +import Loader from 'components/Loader/Loader'; +import { + DataGrid, + type GridCellParams, + type GridColDef, +} from '@mui/x-data-grid'; +import { Chip, debounce, Stack } from '@mui/material'; +import Avatar from 'components/Avatar/Avatar'; +import styles from '../EventVolunteers.module.css'; +import { EVENT_VOLUNTEER_LIST } from 'GraphQl/Queries/EventVolunteerQueries'; +import type { InterfaceEventVolunteerInfo } from 'utils/interfaces'; +import VolunteerCreateModal from './VolunteerCreateModal'; +import VolunteerDeleteModal from './VolunteerDeleteModal'; +import VolunteerViewModal from './VolunteerViewModal'; + +enum VolunteerStatus { + All = 'all', + Pending = 'pending', + Accepted = 'accepted', +} + +enum ModalState { + ADD = 'add', + DELETE = 'delete', + VIEW = 'view', +} + +const dataGridStyle = { + '&.MuiDataGrid-root .MuiDataGrid-cell:focus-within': { + outline: 'none !important', + }, + '&.MuiDataGrid-root .MuiDataGrid-columnHeader:focus-within': { + outline: 'none', + }, + '& .MuiDataGrid-row:hover': { + backgroundColor: 'transparent', + }, + '& .MuiDataGrid-row.Mui-hovered': { + backgroundColor: 'transparent', + }, + '& .MuiDataGrid-root': { + borderRadius: '0.5rem', + }, + '& .MuiDataGrid-main': { + borderRadius: '0.5rem', + }, +}; + +/** + * Component for managing and displaying event volunteers realted to an event. + * + * This component allows users to view, filter, sort, and create volunteers. It also handles fetching and displaying related data such as volunteer acceptance status, etc. + * + * @returns The rendered component. + */ +function volunteers(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'eventVolunteers', + }); + const { t: tCommon } = useTranslation('common'); + const { t: tErrors } = useTranslation('errors'); + + // Get the organization ID from URL parameters + const { orgId, eventId } = useParams(); + + if (!orgId || !eventId) { + return ; + } + + const [volunteer, setVolunteer] = + useState(null); + const [searchValue, setSearchValue] = useState(''); + const [searchTerm, setSearchTerm] = useState(''); + const [sortBy, setSortBy] = useState< + 'hoursVolunteered_ASC' | 'hoursVolunteered_DESC' | null + >(null); + const [status, setStatus] = useState(VolunteerStatus.All); + const [modalState, setModalState] = useState<{ + [key in ModalState]: boolean; + }>({ + [ModalState.ADD]: false, + [ModalState.DELETE]: false, + [ModalState.VIEW]: false, + }); + + const openModal = (modal: ModalState): void => { + setModalState((prevState) => ({ ...prevState, [modal]: true })); + }; + + const closeModal = (modal: ModalState): void => { + setModalState((prevState) => ({ ...prevState, [modal]: false })); + }; + + const handleOpenModal = useCallback( + ( + volunteer: InterfaceEventVolunteerInfo | null, + modalType: ModalState, + ): void => { + setVolunteer(volunteer); + openModal(modalType); + }, + [openModal], + ); + + /** + * Query to fetch event volunteers for the event. + */ + const { + data: volunteersData, + loading: volunteersLoading, + error: volunteersError, + refetch: refetchVolunteers, + }: { + data?: { + getEventVolunteers: InterfaceEventVolunteerInfo[]; + }; + loading: boolean; + error?: Error | undefined; + refetch: () => void; + } = useQuery(EVENT_VOLUNTEER_LIST, { + variables: { + where: { + eventId: eventId, + hasAccepted: + status === VolunteerStatus.All + ? undefined + : status === VolunteerStatus.Accepted, + name_contains: searchTerm, + }, + orderBy: sortBy, + }, + }); + + const debouncedSearch = useMemo( + () => debounce((value: string) => setSearchTerm(value), 300), + [], + ); + + const volunteers = useMemo( + () => volunteersData?.getEventVolunteers || [], + [volunteersData], + ); + + if (volunteersLoading) { + return ; + } + + if (volunteersError) { + return ( +
    + +
    + {tErrors('errorLoading', { entity: 'Volunteers' })} +
    +
    + ); + } + + const columns: GridColDef[] = [ + { + field: 'volunteer', + headerName: 'Volunteer', + flex: 1, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + const { _id, firstName, lastName, image } = params.row.user; + return ( +
    + {image ? ( + volunteer + ) : ( +
    + +
    + )} + {firstName + ' ' + lastName} +
    + ); + }, + }, + { + field: 'status', + headerName: 'Status', + flex: 1, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( + } + label={params.row.hasAccepted ? 'Accepted' : 'Pending'} + variant="outlined" + color="primary" + className={`${styles.chip} ${params.row.hasAccepted ? styles.active : styles.pending}`} + /> + ); + }, + }, + { + field: 'hours', + headerName: 'Hours Volunteered', + flex: 1, + align: 'center', + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( +
    + {params.row.hoursVolunteered ?? '-'} +
    + ); + }, + }, + { + field: 'actionItem', + headerName: 'Actions Completed', + align: 'center', + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + flex: 1, + renderCell: (params: GridCellParams) => { + return ( +
    + {params.row.assignments.length} +
    + ); + }, + }, + { + field: 'options', + headerName: 'Options', + align: 'center', + flex: 1, + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( + <> + + + + ); + }, + }, + ]; + + return ( +
    + {/* Header with search, filter and Create Button */} +
    +
    + { + setSearchValue(e.target.value); + debouncedSearch(e.target.value); + }} + data-testid="searchBy" + /> + +
    +
    +
    + + + + {tCommon('sort')} + + + setSortBy('hoursVolunteered_DESC')} + data-testid="hoursVolunteered_DESC" + > + {t('mostHoursVolunteered')} + + setSortBy('hoursVolunteered_ASC')} + data-testid="hoursVolunteered_ASC" + > + {t('leastHoursVolunteered')} + + + + + + + {t('status')} + + + setStatus(VolunteerStatus.All)} + data-testid="statusAll" + > + {tCommon('all')} + + setStatus(VolunteerStatus.Pending)} + data-testid="statusPending" + > + {tCommon('pending')} + + setStatus(VolunteerStatus.Accepted)} + data-testid="statusAccepted" + > + {t('accepted')} + + + +
    +
    + +
    +
    +
    + + {/* Table with Volunteers */} + row._id} + slots={{ + noRowsOverlay: () => ( + + {t('noVolunteers')} + + ), + }} + sx={dataGridStyle} + getRowClassName={() => `${styles.rowBackground}`} + autoHeight + rowHeight={65} + rows={volunteers.map((volunteer, index) => ({ + id: index + 1, + ...volunteer, + }))} + columns={columns} + isRowSelectable={() => false} + /> + + closeModal(ModalState.ADD)} + eventId={eventId} + orgId={orgId} + refetchVolunteers={refetchVolunteers} + /> + + {volunteer && ( + <> + closeModal(ModalState.VIEW)} + volunteer={volunteer} + /> + closeModal(ModalState.DELETE)} + volunteer={volunteer} + refetchVolunteers={refetchVolunteers} + /> + + )} +
    + ); +} + +export default volunteers; diff --git a/src/screens/FundCampaignPledge/FundCampaignPledge.tsx b/src/screens/FundCampaignPledge/FundCampaignPledge.tsx index f7e339dc89..d14ee9de06 100644 --- a/src/screens/FundCampaignPledge/FundCampaignPledge.tsx +++ b/src/screens/FundCampaignPledge/FundCampaignPledge.tsx @@ -18,7 +18,7 @@ import Avatar from 'components/Avatar/Avatar'; import type { GridCellParams, GridColDef } from '@mui/x-data-grid'; import type { InterfacePledgeInfo, - InterfacePledger, + InterfaceUserInfo, InterfaceQueryFundCampaignsPledges, } from 'utils/interfaces'; import ProgressBar from 'react-bootstrap/ProgressBar'; @@ -84,7 +84,7 @@ const fundCampaignPledge = (): JSX.Element => { }); const [anchor, setAnchor] = useState(null); - const [extraUsers, setExtraUsers] = useState([]); + const [extraUsers, setExtraUsers] = useState([]); const [progressIndicator, setProgressIndicator] = useState< 'raised' | 'pledged' >('pledged'); @@ -189,7 +189,7 @@ const fundCampaignPledge = (): JSX.Element => { const handleClick = ( event: React.MouseEvent, - users: InterfacePledger[], + users: InterfaceUserInfo[], ): void => { setExtraUsers(users); setAnchor(anchor ? null : event.currentTarget); @@ -226,7 +226,7 @@ const fundCampaignPledge = (): JSX.Element => {
    {params.row.users .slice(0, 2) - .map((user: InterfacePledger, index: number) => ( + .map((user: InterfaceUserInfo, index: number) => (
    {user.image ? ( { disablePortal className={`${styles.popup} ${extraUsers.length > 4 ? styles.popupExtra : ''}`} > - {extraUsers.map((user: InterfacePledger, index: number) => ( + {extraUsers.map((user: InterfaceUserInfo, index: number) => (
    = ({ pledgeEndDate: new Date(pledge?.endDate ?? new Date()), pledgeStartDate: new Date(pledge?.startDate ?? new Date()), }); - const [pledgers, setPledgers] = useState([]); + const [pledgers, setPledgers] = useState([]); const [updatePledge] = useMutation(UPDATE_PLEDGE); const [createPledge] = useMutation(CREATE_PlEDGE); @@ -235,7 +235,7 @@ const PledgeModal: React.FC = ({ value={pledgeUsers} isOptionEqualToValue={(option, value) => option._id === value._id} filterSelectedOptions={true} - getOptionLabel={(member: InterfacePledger): string => + getOptionLabel={(member: InterfaceUserInfo): string => `${member.firstName} ${member.lastName}` } onChange={ diff --git a/src/screens/Leaderboard/Leaderboard.mocks.ts b/src/screens/Leaderboard/Leaderboard.mocks.ts new file mode 100644 index 0000000000..b6b22c832a --- /dev/null +++ b/src/screens/Leaderboard/Leaderboard.mocks.ts @@ -0,0 +1,198 @@ +import { VOLUNTEER_RANKING } from 'GraphQl/Queries/EventVolunteerQueries'; + +const rank1 = { + rank: 1, + hoursVolunteered: 5, + user: { + _id: 'userId1', + lastName: 'Bradley', + firstName: 'Teresa', + image: 'image-url', + email: 'testuser4@example.com', + }, +}; + +const rank2 = { + rank: 2, + hoursVolunteered: 4, + user: { + _id: 'userId2', + lastName: 'Garza', + firstName: 'Bruce', + image: null, + email: 'testuser5@example.com', + }, +}; + +const rank3 = { + rank: 3, + hoursVolunteered: 3, + user: { + _id: 'userId3', + lastName: 'Doe', + firstName: 'John', + image: null, + email: 'testuser6@example.com', + }, +}; + +const rank4 = { + rank: 4, + hoursVolunteered: 2, + user: { + _id: 'userId4', + lastName: 'Doe', + firstName: 'Jane', + image: null, + email: 'testuser7@example.com', + }, +}; + +export const MOCKS = [ + { + request: { + query: VOLUNTEER_RANKING, + variables: { + orgId: 'orgId', + where: { + orderBy: 'hours_DESC', + timeFrame: 'allTime', + nameContains: '', + }, + }, + }, + result: { + data: { + getVolunteerRanks: [rank1, rank2, rank3, rank4], + }, + }, + }, + { + request: { + query: VOLUNTEER_RANKING, + variables: { + orgId: 'orgId', + where: { + orderBy: 'hours_ASC', + timeFrame: 'allTime', + nameContains: '', + }, + }, + }, + result: { + data: { + getVolunteerRanks: [rank4, rank3, rank2, rank1], + }, + }, + }, + { + request: { + query: VOLUNTEER_RANKING, + variables: { + orgId: 'orgId', + where: { + orderBy: 'hours_DESC', + timeFrame: 'weekly', + nameContains: '', + }, + }, + }, + result: { + data: { + getVolunteerRanks: [rank1], + }, + }, + }, + { + request: { + query: VOLUNTEER_RANKING, + variables: { + orgId: 'orgId', + where: { + orderBy: 'hours_DESC', + timeFrame: 'monthly', + nameContains: '', + }, + }, + }, + result: { + data: { + getVolunteerRanks: [rank1, rank2], + }, + }, + }, + { + request: { + query: VOLUNTEER_RANKING, + variables: { + orgId: 'orgId', + where: { + orderBy: 'hours_DESC', + timeFrame: 'yearly', + nameContains: '', + }, + }, + }, + result: { + data: { + getVolunteerRanks: [rank1, rank2, rank3], + }, + }, + }, + { + request: { + query: VOLUNTEER_RANKING, + variables: { + orgId: 'orgId', + where: { + orderBy: 'hours_DESC', + timeFrame: 'allTime', + nameContains: 'T', + }, + }, + }, + result: { + data: { + getVolunteerRanks: [rank1], + }, + }, + }, +]; + +export const EMPTY_MOCKS = [ + { + request: { + query: VOLUNTEER_RANKING, + variables: { + orgId: 'orgId', + where: { + orderBy: 'hours_DESC', + timeFrame: 'allTime', + nameContains: '', + }, + }, + }, + result: { + data: { + getVolunteerRanks: [], + }, + }, + }, +]; + +export const ERROR_MOCKS = [ + { + request: { + query: VOLUNTEER_RANKING, + variables: { + orgId: 'orgId', + where: { + orderBy: 'hours_DESC', + timeFrame: 'allTime', + nameContains: '', + }, + }, + }, + error: new Error('Mock Graphql VOLUNTEER_RANKING Error'), + }, +]; diff --git a/src/screens/Leaderboard/Leaderboard.test.tsx b/src/screens/Leaderboard/Leaderboard.test.tsx new file mode 100644 index 0000000000..d2f12a9052 --- /dev/null +++ b/src/screens/Leaderboard/Leaderboard.test.tsx @@ -0,0 +1,264 @@ +import React, { act } from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import type { RenderResult } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18n from 'utils/i18nForTest'; +import Leaderboard from './Leaderboard'; +import type { ApolloLink } from '@apollo/client'; +import { MOCKS, EMPTY_MOCKS, ERROR_MOCKS } from './Leaderboard.mocks'; + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(ERROR_MOCKS); +const link3 = new StaticMockLink(EMPTY_MOCKS); +const t = { + ...JSON.parse( + JSON.stringify(i18n.getDataByLanguage('en')?.translation.leaderboard ?? {}), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const debounceWait = async (ms = 300): Promise => { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +}; + +const renderLeaderboard = (link: ApolloLink): RenderResult => { + return render( + + + + + + + } /> + } + /> +
    } + /> + + + + + + , + ); +}; + +describe('Testing Leaderboard Screen', () => { + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId' }), + })); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('should redirect to fallback URL if URL params are undefined', async () => { + render( + + + + + + } /> +
    } + /> + + + + + , + ); + await waitFor(() => { + expect(screen.getByTestId('paramsError')).toBeInTheDocument(); + }); + }); + + it('should render Leaderboard screen', async () => { + renderLeaderboard(link1); + + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + }); + }); + + it('Check Sorting Functionality', async () => { + renderLeaderboard(link1); + + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + }); + + const sortBtn = await screen.findByTestId('sort'); + expect(sortBtn).toBeInTheDocument(); + + // Sort by hours_DESC + fireEvent.click(sortBtn); + const hoursDesc = await screen.findByTestId('hours_DESC'); + expect(hoursDesc).toBeInTheDocument(); + fireEvent.click(hoursDesc); + + let userName = await screen.findAllByTestId('userName'); + expect(userName[0]).toHaveTextContent('Teresa Bradley'); + + // Sort by hours_ASC + expect(sortBtn).toBeInTheDocument(); + fireEvent.click(sortBtn); + const hoursAsc = await screen.findByTestId('hours_ASC'); + expect(hoursAsc).toBeInTheDocument(); + fireEvent.click(hoursAsc); + + userName = await screen.findAllByTestId('userName'); + expect(userName[0]).toHaveTextContent('Jane Doe'); + }); + + it('Check Timeframe filter Functionality (All Time)', async () => { + renderLeaderboard(link1); + + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + }); + + // Filter by allTime + const filter = await screen.findByTestId('timeFrame'); + expect(filter).toBeInTheDocument(); + + fireEvent.click(filter); + const timeFrameAll = await screen.findByTestId('timeFrameAll'); + expect(timeFrameAll).toBeInTheDocument(); + + fireEvent.click(timeFrameAll); + const userName = await screen.findAllByTestId('userName'); + expect(userName).toHaveLength(4); + }); + + it('Check Timeframe filter Functionality (Weekly)', async () => { + renderLeaderboard(link1); + + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + }); + + const filter = await screen.findByTestId('timeFrame'); + expect(filter).toBeInTheDocument(); + + // Filter by weekly + expect(filter).toBeInTheDocument(); + fireEvent.click(filter); + + const timeFrameWeekly = await screen.findByTestId('timeFrameWeekly'); + expect(timeFrameWeekly).toBeInTheDocument(); + fireEvent.click(timeFrameWeekly); + + const userName = await screen.findAllByTestId('userName'); + expect(userName).toHaveLength(1); + }); + + it('Check Timeframe filter Functionality (Monthly)', async () => { + renderLeaderboard(link1); + + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + }); + + // Filter by monthly + const filter = await screen.findByTestId('timeFrame'); + expect(filter).toBeInTheDocument(); + fireEvent.click(filter); + + const timeFrameMonthly = await screen.findByTestId('timeFrameMonthly'); + expect(timeFrameMonthly).toBeInTheDocument(); + fireEvent.click(timeFrameMonthly); + + const userName = await screen.findAllByTestId('userName'); + expect(userName).toHaveLength(2); + }); + + it('Check Timeframe filter Functionality (Yearly)', async () => { + renderLeaderboard(link1); + + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + }); + + // Filter by yearly + const filter = await screen.findByTestId('timeFrame'); + expect(filter).toBeInTheDocument(); + fireEvent.click(filter); + + const timeFrameYearly = await screen.findByTestId('timeFrameYearly'); + expect(timeFrameYearly).toBeInTheDocument(); + fireEvent.click(timeFrameYearly); + + const userName = await screen.findAllByTestId('userName'); + expect(userName).toHaveLength(3); + }); + + it('Search Volunteers', async () => { + renderLeaderboard(link1); + + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + // Search by name on press of ENTER + userEvent.type(searchInput, 'T'); + await debounceWait(); + + await waitFor(() => { + const userName = screen.getAllByTestId('userName'); + expect(userName).toHaveLength(1); + }); + }); + + it('OnClick of Member navigate to Member Screen', async () => { + renderLeaderboard(link1); + + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + const userName = screen.getAllByTestId('userName'); + userEvent.click(userName[0]); + + await waitFor(() => { + expect(screen.getByTestId('memberScreen')).toBeInTheDocument(); + }); + }); + + it('should render Leaderboard screen with No Volunteers', async () => { + renderLeaderboard(link3); + + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + expect(screen.getByText(t.noVolunteers)).toBeInTheDocument(); + }); + }); + + it('Error while fetching volunteer data', async () => { + renderLeaderboard(link2); + + await waitFor(() => { + expect(screen.getByTestId('errorMsg')).toBeInTheDocument(); + }); + }); +}); diff --git a/src/screens/Leaderboard/Leaderboard.tsx b/src/screens/Leaderboard/Leaderboard.tsx new file mode 100644 index 0000000000..c5ad7a2efe --- /dev/null +++ b/src/screens/Leaderboard/Leaderboard.tsx @@ -0,0 +1,372 @@ +import React, { useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Button, Dropdown, Form } from 'react-bootstrap'; +import { Navigate, useNavigate, useParams } from 'react-router-dom'; + +import { + FilterAltOutlined, + Search, + Sort, + WarningAmberRounded, +} from '@mui/icons-material'; +import gold from 'assets/images/gold.png'; +import silver from 'assets/images/silver.png'; +import bronze from 'assets/images/bronze.png'; + +import type { InterfaceVolunteerRank } from 'utils/interfaces'; +import styles from '../OrganizationActionItems/OrganizationActionItems.module.css'; +import Loader from 'components/Loader/Loader'; +import { + DataGrid, + type GridCellParams, + type GridColDef, +} from '@mui/x-data-grid'; +import { debounce, Stack } from '@mui/material'; +import Avatar from 'components/Avatar/Avatar'; +import { VOLUNTEER_RANKING } from 'GraphQl/Queries/EventVolunteerQueries'; +import { useQuery } from '@apollo/client'; + +enum TimeFrame { + All = 'allTime', + Weekly = 'weekly', + Monthly = 'monthly', + Yearly = 'yearly', +} + +const dataGridStyle = { + '&.MuiDataGrid-root .MuiDataGrid-cell:focus-within': { + outline: 'none !important', + }, + '&.MuiDataGrid-root .MuiDataGrid-columnHeader:focus-within': { + outline: 'none', + }, + '& .MuiDataGrid-row:hover': { + backgroundColor: 'transparent', + }, + '& .MuiDataGrid-row.Mui-hovered': { + backgroundColor: 'transparent', + }, + '& .MuiDataGrid-root': { + borderRadius: '0.5rem', + }, + '& .MuiDataGrid-main': { + borderRadius: '0.5rem', + }, +}; + +/** + * Component to display the leaderboard of volunteers. + * + * This component shows a leaderboard of volunteers ranked by hours contributed, + * with features for filtering by time frame and sorting by hours. It displays + * volunteer details including rank, name, email, and hours volunteered. + * + * @returns The rendered component. + */ +function leaderboard(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'leaderboard', + }); + const { t: tCommon } = useTranslation('common'); + const { t: tErrors } = useTranslation('errors'); + + // Get the organization ID from URL parameters + const { orgId } = useParams(); + + if (!orgId) { + return ; + } + + const navigate = useNavigate(); + const [searchValue, setSearchValue] = useState(''); + const [searchTerm, setSearchTerm] = useState(''); + const [sortBy, setSortBy] = useState<'hours_ASC' | 'hours_DESC'>( + 'hours_DESC', + ); + const [timeFrame, setTimeFrame] = useState(TimeFrame.All); + + /** + * Query to fetch volunteer rankings. + */ + const { + data: rankingsData, + loading: rankingsLoading, + error: rankingsError, + }: { + data?: { + getVolunteerRanks: InterfaceVolunteerRank[]; + }; + loading: boolean; + error?: Error | undefined; + } = useQuery(VOLUNTEER_RANKING, { + variables: { + orgId, + where: { + orderBy: sortBy, + timeFrame: timeFrame, + nameContains: searchTerm, + }, + }, + }); + + const debouncedSearch = useMemo( + () => debounce((value: string) => setSearchTerm(value), 300), + [], + ); + + const rankings = useMemo( + () => rankingsData?.getVolunteerRanks || [], + [rankingsData], + ); + + if (rankingsLoading) { + return ; + } + + if (rankingsError) { + return ( +
    + +
    + {tErrors('errorLoading', { entity: 'Volunteer Rankings' })} +
    +
    + ); + } + + const columns: GridColDef[] = [ + { + field: 'rank', + headerName: 'Rank', + flex: 1, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + if (params.row.rank === 1) { + return ( + <> + gold + + ); + } else if (params.row.rank === 2) { + return ( + <> + silver + + ); + } else if (params.row.rank === 3) { + return ( + <> + bronze + + ); + } else return <>{params.row.rank}; + }, + }, + { + field: 'volunteer', + headerName: 'Volunteer', + flex: 2, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + const { _id, firstName, lastName, image } = params.row.user; + + return ( + <> +
    + navigate(`/member/${orgId}`, { state: { id: _id } }) + } + data-testid="userName" + > + {image ? ( + User + ) : ( +
    + +
    + )} + {firstName + ' ' + lastName} +
    + + ); + }, + }, + { + field: 'email', + headerName: 'Email', + flex: 2, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( +
    + {params.row.user.email} +
    + ); + }, + }, + { + field: 'hoursVolunteered', + headerName: 'Hours Volunteered', + flex: 2, + align: 'center', + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return
    {params.row.hoursVolunteered}
    ; + }, + }, + ]; + + return ( +
    + {/* Header with search, filter and Create Button */} +
    +
    + { + setSearchValue(e.target.value); + debouncedSearch(e.target.value); + }} + data-testid="searchBy" + /> + +
    +
    +
    + + + + {tCommon('sort')} + + + setSortBy('hours_DESC')} + data-testid="hours_DESC" + > + {t('mostHours')} + + setSortBy('hours_ASC')} + data-testid="hours_ASC" + > + {t('leastHours')} + + + + + + + {t('timeFrame')} + + + setTimeFrame(TimeFrame.All)} + data-testid="timeFrameAll" + > + {t('allTime')} + + setTimeFrame(TimeFrame.Weekly)} + data-testid="timeFrameWeekly" + > + {t('weekly')} + + setTimeFrame(TimeFrame.Monthly)} + data-testid="timeFrameMonthly" + > + {t('monthly')} + + setTimeFrame(TimeFrame.Yearly)} + data-testid="timeFrameYearly" + > + {t('yearly')} + + + +
    +
    +
    + + {/* Table with Action Items */} + row.user._id} + slots={{ + noRowsOverlay: () => ( + + {t('noVolunteers')} + + ), + }} + sx={dataGridStyle} + getRowClassName={() => `${styles.rowBackground}`} + autoHeight + rowHeight={65} + rows={rankings.map((ranking, index) => ({ + id: index + 1, + ...ranking, + }))} + columns={columns} + isRowSelectable={() => false} + /> +
    + ); +} + +export default leaderboard; diff --git a/src/screens/LoginPage/LoginPage.test.tsx b/src/screens/LoginPage/LoginPage.test.tsx index 3733a454dd..698c83d42e 100644 --- a/src/screens/LoginPage/LoginPage.test.tsx +++ b/src/screens/LoginPage/LoginPage.test.tsx @@ -50,8 +50,8 @@ const MOCKS = [ request: { query: SIGNUP_MUTATION, variables: { - firstName: 'John', - lastName: 'Doe', + firstName: 'John Patrick ', + lastName: 'Doe ', email: 'johndoe@gmail.com', password: 'johnDoe', }, diff --git a/src/screens/LoginPage/LoginPage.tsx b/src/screens/LoginPage/LoginPage.tsx index 7d007a7112..7703266afa 100644 --- a/src/screens/LoginPage/LoginPage.tsx +++ b/src/screens/LoginPage/LoginPage.tsx @@ -33,6 +33,7 @@ import { socialMediaLinks } from '../../constants'; import styles from './LoginPage.module.css'; import type { InterfaceQueryOrganizationListObject } from 'utils/interfaces'; import { Autocomplete, TextField } from '@mui/material'; +import useSession from 'utils/useSession'; import i18n from 'utils/i18n'; /** @@ -41,6 +42,7 @@ import i18n from 'utils/i18n'; * register form. * */ + const loginPage = (): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'loginPage' }); const { t: tCommon } = useTranslation('common'); @@ -110,6 +112,7 @@ const loginPage = (): JSX.Element => { const isLoggedIn = getItem('IsLoggedIn'); if (isLoggedIn == 'TRUE') { navigate(getItem('userId') !== null ? '/user/organizations' : '/orglist'); + extendSession(); } }, []); @@ -126,7 +129,7 @@ const loginPage = (): JSX.Element => { const [signup, { loading: signinLoading }] = useMutation(SIGNUP_MUTATION); const [recaptcha] = useMutation(RECAPTCHA_MUTATION); const { data: orgData } = useQuery(ORGANIZATION_LIST); - + const { startSession, extendSession } = useSession(); useEffect(() => { if (orgData) { const options = orgData.organizations.map( @@ -173,7 +176,7 @@ const loginPage = (): JSX.Element => { }); return data.recaptcha; - } catch (error) { + } catch { /* istanbul ignore next */ toast.error(t('captchaError') as string); } @@ -201,8 +204,11 @@ const loginPage = (): JSX.Element => { toast.error(t('Please_check_the_captcha') as string); return; } - const isValidatedString = (value: string): boolean => - /^[a-zA-Z]+$/.test(value); + + const isValidName = (value: string): boolean => { + // Allow letters, spaces, and hyphens, but not consecutive spaces or hyphens + return /^[a-zA-Z]+(?:[-\s][a-zA-Z]+)*$/.test(value.trim()); + }; const validatePassword = (password: string): boolean => { const lengthCheck = new RegExp('^.{6,}$'); @@ -216,10 +222,10 @@ const loginPage = (): JSX.Element => { }; if ( - isValidatedString(signfirstName) && - isValidatedString(signlastName) && - signfirstName.length > 1 && - signlastName.length > 1 && + isValidName(signfirstName) && + isValidName(signlastName) && + signfirstName.trim().length > 1 && + signlastName.trim().length > 1 && signEmail.length >= 8 && signPassword.length > 1 && validatePassword(signPassword) @@ -261,10 +267,10 @@ const loginPage = (): JSX.Element => { toast.warn(t('passwordMismatches') as string); } } else { - if (!isValidatedString(signfirstName)) { + if (!isValidName(signfirstName)) { toast.warn(t('firstName_invalid') as string); } - if (!isValidatedString(signlastName)) { + if (!isValidName(signlastName)) { toast.warn(t('lastName_invalid') as string); } if (!validatePassword(signPassword)) { @@ -325,6 +331,7 @@ const loginPage = (): JSX.Element => { } navigate(role === 'admin' ? '/orglist' : '/user/organizations'); + startSession(); } else { toast.warn(tErrors('notFound') as string); } diff --git a/src/screens/ManageTag/EditUserTagModal.tsx b/src/screens/ManageTag/EditUserTagModal.tsx new file mode 100644 index 0000000000..5fa8ae2771 --- /dev/null +++ b/src/screens/ManageTag/EditUserTagModal.tsx @@ -0,0 +1,89 @@ +import type { TFunction } from 'i18next'; +import type { FormEvent } from 'react'; +import React from 'react'; +import { Button, Form, Modal } from 'react-bootstrap'; + +/** + * Edit UserTag Modal component for the Manage Tag screen. + */ + +export interface InterfaceEditUserTagModalProps { + editUserTagModalIsOpen: boolean; + hideEditUserTagModal: () => void; + newTagName: string; + setNewTagName: (state: React.SetStateAction) => void; + handleEditUserTag: (e: FormEvent) => Promise; + t: TFunction<'translation', 'manageTag'>; + tCommon: TFunction<'common', undefined>; +} + +const EditUserTagModal: React.FC = ({ + editUserTagModalIsOpen, + hideEditUserTagModal, + newTagName, + handleEditUserTag, + setNewTagName, + t, + tCommon, +}) => { + return ( + <> + + + {t('tagDetails')} + +
    ): void => { + e.preventDefault(); + if (newTagName.trim()) { + handleEditUserTag(e); + } + }} + > + + {t('tagName')} + { + setNewTagName(e.target.value); + }} + /> + + + + + + +
    +
    + + ); +}; + +export default EditUserTagModal; diff --git a/src/screens/ManageTag/ManageTag.module.css b/src/screens/ManageTag/ManageTag.module.css index db1886099a..deecd4a9b7 100644 --- a/src/screens/ManageTag/ManageTag.module.css +++ b/src/screens/ManageTag/ManageTag.module.css @@ -117,3 +117,11 @@ font-weight: 600; text-decoration: underline; } + +.manageTagScrollableDiv { + scrollbar-width: thin; + scrollbar-color: var(--bs-gray-400) var(--bs-white); + + max-height: calc(100vh - 18rem); + overflow: auto; +} diff --git a/src/screens/ManageTag/ManageTag.test.tsx b/src/screens/ManageTag/ManageTag.test.tsx index 38ebba7402..598a15cc9a 100644 --- a/src/screens/ManageTag/ManageTag.test.tsx +++ b/src/screens/ManageTag/ManageTag.test.tsx @@ -4,6 +4,7 @@ import type { RenderResult } from '@testing-library/react'; import { act, cleanup, + fireEvent, render, screen, waitFor, @@ -19,12 +20,8 @@ import { store } from 'state/store'; import { StaticMockLink } from 'utils/StaticMockLink'; import i18n from 'utils/i18nForTest'; import ManageTag from './ManageTag'; -import { - MOCKS, - MOCKS_ERROR_ASSIGNED_MEMBERS, - MOCKS_ERROR_TAG_ANCESTORS, -} from './ManageTagMocks'; -import { InMemoryCache, type ApolloLink } from '@apollo/client'; +import { MOCKS, MOCKS_ERROR_ASSIGNED_MEMBERS } from './ManageTagMocks'; +import { type ApolloLink } from '@apollo/client'; const translations = { ...JSON.parse( @@ -36,7 +33,6 @@ const translations = { const link = new StaticMockLink(MOCKS, true); const link2 = new StaticMockLink(MOCKS_ERROR_ASSIGNED_MEMBERS, true); -const link3 = new StaticMockLink(MOCKS_ERROR_TAG_ANCESTORS, true); async function wait(ms = 500): Promise { await act(() => { @@ -49,28 +45,24 @@ async function wait(ms = 500): Promise { jest.mock('react-toastify', () => ({ toast: { success: jest.fn(), + info: jest.fn(), error: jest.fn(), }, })); -const cache = new InMemoryCache({ - typePolicies: { - Query: { - fields: { - getUserTag: { - keyArgs: false, - merge(existing = {}, incoming) { - return incoming; - }, - }, - }, - }, - }, +/* eslint-disable @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports */ +jest.mock('../../components/AddPeopleToTag/AddPeopleToTag', () => { + return require('./ManageTagMockComponents/MockAddPeopleToTag').default; +}); + +jest.mock('../../components/TagActions/TagActions', () => { + return require('./ManageTagMockComponents/MockTagActions').default; }); +/* eslint-enable @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports */ const renderManageTag = (link: ApolloLink): RenderResult => { return render( - + @@ -80,11 +72,11 @@ const renderManageTag = (link: ApolloLink): RenderResult => { element={
    } /> } />
    } /> { ); }; -describe('Organisation Tags Page', () => { +describe('Manage Tag Page', () => { beforeEach(() => { jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useParams: () => ({ orgId: 'orgId' }), })); - cache.reset(); }); afterEach(() => { @@ -133,57 +124,141 @@ describe('Organisation Tags Page', () => { }); }); - test('renders error component on unsuccessful userTag ancestors query', async () => { - const { queryByText } = renderManageTag(link3); + test('opens and closes the add people to tag modal', async () => { + renderManageTag(link); + + await waitFor(() => { + expect(screen.getByTestId('addPeopleToTagBtn')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('addPeopleToTagBtn')); + + await waitFor(() => { + expect(screen.getByTestId('addPeopleToTagModal')).toBeInTheDocument(); + }); + + userEvent.click(screen.getByTestId('closeAddPeopleToTagModal')); + + await waitFor(() => { + expect( + screen.queryByTestId('addPeopleToTagModal'), + ).not.toBeInTheDocument(); + }); + }); + + test('opens and closes the unassign tag modal', async () => { + renderManageTag(link); await wait(); await waitFor(() => { - expect(queryByText(translations.addPeopleToTag)).not.toBeInTheDocument(); + expect(screen.getAllByTestId('unassignTagBtn')[0]).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('unassignTagBtn')[0]); + + await waitFor(() => { + return expect( + screen.findByTestId('unassignTagModalCloseBtn'), + ).resolves.toBeInTheDocument(); }); + userEvent.click(screen.getByTestId('unassignTagModalCloseBtn')); + + await waitForElementToBeRemoved(() => + screen.queryByTestId('unassignTagModalCloseBtn'), + ); }); - test('opens and closes the add people to tag modal', async () => { + test('opens and closes the assignToTags modal', async () => { + renderManageTag(link); + + // Wait for the assignToTags button to be present + await waitFor(() => { + expect(screen.getByTestId('assignToTags')).toBeInTheDocument(); + }); + + // Click the assignToTags button to open the modal + userEvent.click(screen.getByTestId('assignToTags')); + + // Wait for the close button in the modal to be present + await waitFor(() => { + expect(screen.getByTestId('closeTagActionsModalBtn')).toBeInTheDocument(); + }); + + // Click the close button to close the modal + userEvent.click(screen.getByTestId('closeTagActionsModalBtn')); + + // Wait for the modal to be removed from the document + await waitFor(() => { + expect(screen.queryByTestId('tagActionsModal')).not.toBeInTheDocument(); + }); + }); + + test('opens and closes the removeFromTags modal', async () => { + renderManageTag(link); + + // Wait for the removeFromTags button to be present + await waitFor(() => { + expect(screen.getByTestId('removeFromTags')).toBeInTheDocument(); + }); + + // Click the removeFromTags button to open the modal + userEvent.click(screen.getByTestId('removeFromTags')); + + // Wait for the close button in the modal to be present + await waitFor(() => { + expect(screen.getByTestId('closeTagActionsModalBtn')).toBeInTheDocument(); + }); + + // Click the close button to close the modal + userEvent.click(screen.getByTestId('closeTagActionsModalBtn')); + + // Wait for the modal to be removed from the document + await waitFor(() => { + expect(screen.queryByTestId('tagActionsModal')).not.toBeInTheDocument(); + }); + }); + + test('opens and closes the edit tag modal', async () => { renderManageTag(link); await wait(); await waitFor(() => { - expect(screen.getByTestId('addPeopleToTagBtn')).toBeInTheDocument(); + expect(screen.getByTestId('editUserTag')).toBeInTheDocument(); }); - userEvent.click(screen.getByTestId('addPeopleToTagBtn')); + userEvent.click(screen.getByTestId('editUserTag')); await waitFor(() => { return expect( - screen.findByTestId('closeAddPeopleToTagModal'), + screen.findByTestId('closeEditTagModalBtn'), ).resolves.toBeInTheDocument(); }); - userEvent.click(screen.getByTestId('closeAddPeopleToTagModal')); + userEvent.click(screen.getByTestId('closeEditTagModalBtn')); await waitForElementToBeRemoved(() => - screen.queryByTestId('closeAddPeopleToTagModal'), + screen.queryByTestId('closeEditTagModalBtn'), ); }); - test('opens and closes the unassign tag modal', async () => { + test('opens and closes the remove tag modal', async () => { renderManageTag(link); await wait(); await waitFor(() => { - expect(screen.getAllByTestId('unassignTagBtn')[0]).toBeInTheDocument(); + expect(screen.getByTestId('removeTag')).toBeInTheDocument(); }); - userEvent.click(screen.getAllByTestId('unassignTagBtn')[0]); + userEvent.click(screen.getByTestId('removeTag')); await waitFor(() => { return expect( - screen.findByTestId('unassignTagModalCloseBtn'), + screen.findByTestId('removeUserTagModalCloseBtn'), ).resolves.toBeInTheDocument(); }); - userEvent.click(screen.getByTestId('unassignTagModalCloseBtn')); + userEvent.click(screen.getByTestId('removeUserTagModalCloseBtn')); await waitForElementToBeRemoved(() => - screen.queryByTestId('unassignTagModalCloseBtn'), + screen.queryByTestId('removeUserTagModalCloseBtn'), ); }); @@ -249,31 +324,112 @@ describe('Organisation Tags Page', () => { }); }); - test('paginates between different pages', async () => { + test('searchs for tags where the name matches the provided search input', async () => { renderManageTag(link); await wait(); await waitFor(() => { - expect(screen.getByTestId('nextPagBtn')).toBeInTheDocument(); + expect( + screen.getByPlaceholderText(translations.searchByName), + ).toBeInTheDocument(); }); - userEvent.click(screen.getByTestId('nextPagBtn')); + const input = screen.getByPlaceholderText(translations.searchByName); + fireEvent.change(input, { target: { value: 'assigned user' } }); + // should render the two users from the mock data + // where firstName starts with "assigned" and lastName starts with "user" + await waitFor(() => { + const buttons = screen.getAllByTestId('viewProfileBtn'); + expect(buttons.length).toEqual(2); + }); + }); + + test('fetches the tags by the sort order, i.e. latest or oldest first', async () => { + renderManageTag(link); + + await wait(); + + await waitFor(() => { + expect( + screen.getByPlaceholderText(translations.searchByName), + ).toBeInTheDocument(); + }); + const input = screen.getByPlaceholderText(translations.searchByName); + fireEvent.change(input, { target: { value: 'assigned user' } }); + + // should render the two searched tags from the mock data + // where name starts with "searchUserTag" + await waitFor(() => { + expect(screen.getAllByTestId('memberName')[0]).toHaveTextContent( + 'assigned user1', + ); + }); + + // now change the sorting order + await waitFor(() => { + expect(screen.getByTestId('sortPeople')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('sortPeople')); + + await waitFor(() => { + expect(screen.getByTestId('oldest')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('oldest')); + + // returns the tags in reverse order await waitFor(() => { expect(screen.getAllByTestId('memberName')[0]).toHaveTextContent( - 'member 6', + 'assigned user2', ); }); await waitFor(() => { - expect(screen.getByTestId('previousPageBtn')).toBeInTheDocument(); + expect(screen.getByTestId('sortPeople')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('sortPeople')); + + await waitFor(() => { + expect(screen.getByTestId('latest')).toBeInTheDocument(); }); - userEvent.click(screen.getByTestId('previousPageBtn')); + userEvent.click(screen.getByTestId('latest')); + // reverse the order again await waitFor(() => { expect(screen.getAllByTestId('memberName')[0]).toHaveTextContent( - 'member 1', + 'assigned user1', + ); + }); + }); + + test('Fetches more assigned members with infinite scroll', async () => { + const { getByText } = renderManageTag(link); + + await wait(); + + await waitFor(() => { + expect(getByText(translations.addPeopleToTag)).toBeInTheDocument(); + }); + + const manageTagScrollableDiv = screen.getByTestId('manageTagScrollableDiv'); + + // Get the initial number of tags loaded + const initialAssignedMembersDataLength = + screen.getAllByTestId('viewProfileBtn').length; + + // Set scroll position to the bottom + fireEvent.scroll(manageTagScrollableDiv, { + target: { scrollY: manageTagScrollableDiv.scrollHeight }, + }); + + await waitFor(() => { + const finalAssignedMembersDataLength = + screen.getAllByTestId('viewProfileBtn').length; + expect(finalAssignedMembersDataLength).toBeGreaterThan( + initialAssignedMembersDataLength, ); + + expect(getByText(translations.addPeopleToTag)).toBeInTheDocument(); }); }); @@ -290,7 +446,62 @@ describe('Organisation Tags Page', () => { userEvent.click(screen.getByTestId('unassignTagModalSubmitBtn')); await waitFor(() => { - expect(toast.success).toBeCalledWith(translations.successfullyUnassigned); + expect(toast.success).toHaveBeenCalledWith( + translations.successfullyUnassigned, + ); + }); + }); + + test('successfully edits the tag name', async () => { + renderManageTag(link); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('editUserTag')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('editUserTag')); + + userEvent.click(screen.getByTestId('editTagSubmitBtn')); + + await waitFor(() => { + expect(toast.info).toHaveBeenCalledWith(translations.changeNameToEdit); + }); + + const tagNameInput = screen.getByTestId('tagNameInput'); + await userEvent.clear(tagNameInput); + await userEvent.type(tagNameInput, 'tag 1 edited'); + expect(tagNameInput).toHaveValue('tag 1 edited'); + + userEvent.click(screen.getByTestId('editTagSubmitBtn')); + + await waitFor(() => { + expect(toast.success).toHaveBeenCalledWith( + translations.tagUpdationSuccess, + ); + }); + }); + + test('successfully removes the tag and redirects to orgTags page', async () => { + renderManageTag(link); + + await wait(); + + await waitFor(() => { + expect(screen.getByTestId('removeTag')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('removeTag')); + + userEvent.click(screen.getByTestId('removeUserTagSubmitBtn')); + + await waitFor(() => { + expect(toast.success).toHaveBeenCalledWith( + translations.tagRemovalSuccess, + ); + }); + + await waitFor(() => { + expect(screen.getByTestId('organizationTagsScreen')).toBeInTheDocument(); }); }); }); diff --git a/src/screens/ManageTag/ManageTag.tsx b/src/screens/ManageTag/ManageTag.tsx index 86a44fb169..428dad7981 100644 --- a/src/screens/ManageTag/ManageTag.tsx +++ b/src/screens/ManageTag/ManageTag.tsx @@ -1,5 +1,6 @@ -import React, { useState } from 'react'; -import { useMutation, useQuery, type ApolloError } from '@apollo/client'; +import type { FormEvent } from 'react'; +import React, { useEffect, useState } from 'react'; +import { useMutation, useQuery } from '@apollo/client'; import { Search, WarningAmberRounded } from '@mui/icons-material'; import SortIcon from '@mui/icons-material/Sort'; import Loader from 'components/Loader/Loader'; @@ -8,27 +9,39 @@ import { useNavigate, useParams, Link } from 'react-router-dom'; import { Col, Form } from 'react-bootstrap'; import Button from 'react-bootstrap/Button'; import Dropdown from 'react-bootstrap/Dropdown'; -import Modal from 'react-bootstrap/Modal'; import Row from 'react-bootstrap/Row'; import { useTranslation } from 'react-i18next'; import { toast } from 'react-toastify'; import type { InterfaceQueryUserTagsAssignedMembers } from 'utils/interfaces'; -import styles from './ManageTag.module.css'; +import styles from '../../style/app.module.css'; import { DataGrid } from '@mui/x-data-grid'; -import { dataGridStyle } from 'utils/organizationTagsUtils'; +import type { + InterfaceTagAssignedMembersQuery, + SortedByType, + TagActionType, +} from 'utils/organizationTagsUtils'; +import { + TAGS_QUERY_DATA_CHUNK_SIZE, + dataGridStyle, +} from 'utils/organizationTagsUtils'; import type { GridCellParams, GridColDef } from '@mui/x-data-grid'; import { Stack } from '@mui/material'; -import { UNASSIGN_USER_TAG } from 'GraphQl/Mutations/TagMutations'; import { - USER_TAG_ANCESTORS, - USER_TAGS_ASSIGNED_MEMBERS, -} from 'GraphQl/Queries/userTagQueries'; + REMOVE_USER_TAG, + UNASSIGN_USER_TAG, + UPDATE_USER_TAG, +} from 'GraphQl/Mutations/TagMutations'; +import { USER_TAGS_ASSIGNED_MEMBERS } from 'GraphQl/Queries/userTagQueries'; +import AddPeopleToTag from 'components/AddPeopleToTag/AddPeopleToTag'; +import TagActions from 'components/TagActions/TagActions'; +import InfiniteScroll from 'react-infinite-scroll-component'; +import InfiniteScrollLoader from 'components/InfiniteScrollLoader/InfiniteScrollLoader'; +import EditUserTagModal from './EditUserTagModal'; +import RemoveUserTagModal from './RemoveUserTagModal'; +import UnassignUserTagModal from './UnassignUserTagModal'; /** - * Component that renders the Manage Tag screen when the app navigates to '/orgtags/:orgId/managetag/:tagId'. - * - * This component does not accept any props and is responsible for displaying - * the content associated with the corresponding route. + * Component that renders the Manage Tag screen when the app navigates to '/orgtags/:orgId/manageTag/:tagId'. */ function ManageTag(): JSX.Element { @@ -36,73 +49,119 @@ function ManageTag(): JSX.Element { keyPrefix: 'manageTag', }); const { t: tCommon } = useTranslation('common'); - - const [addPeopleToTagModalIsOpen, setAddPeopleToTagModalIsOpen] = - useState(false); - const [unassignTagModalIsOpen, setUnassignTagModalIsOpen] = useState(false); - const { orgId, tagId: currentTagId } = useParams(); const navigate = useNavigate(); - const [after, setAfter] = useState(null); - const [before, setBefore] = useState(null); - const [first, setFirst] = useState(5); - const [last, setLast] = useState(null); + const [unassignUserTagModalIsOpen, setUnassignUserTagModalIsOpen] = + useState(false); + const [addPeopleToTagModalIsOpen, setAddPeopleToTagModalIsOpen] = + useState(false); + const [tagActionsModalIsOpen, setTagActionsModalIsOpen] = useState(false); + const [editUserTagModalIsOpen, setEditUserTagModalIsOpen] = useState(false); + const [removeUserTagModalIsOpen, setRemoveUserTagModalIsOpen] = + useState(false); const [unassignUserId, setUnassignUserId] = useState(null); - + const [assignedMemberSearchInput, setAssignedMemberSearchInput] = + useState(''); + const [assignedMemberSearchFirstName, setAssignedMemberSearchFirstName] = + useState(''); + const [assignedMemberSearchLastName, setAssignedMemberSearchLastName] = + useState(''); + const [assignedMemberSortOrder, setAssignedMemberSortOrder] = + useState('DESCENDING'); + // a state to specify whether we're assigning to tags or removing from tags + const [tagActionType, setTagActionType] = + useState('assignToTags'); + + const toggleRemoveUserTagModal = (): void => { + setRemoveUserTagModalIsOpen(!removeUserTagModalIsOpen); + }; const showAddPeopleToTagModal = (): void => { setAddPeopleToTagModalIsOpen(true); }; - const hideAddPeopleToTagModal = (): void => { setAddPeopleToTagModalIsOpen(false); }; + const showTagActionsModal = (): void => { + setTagActionsModalIsOpen(true); + }; + const hideTagActionsModal = (): void => { + setTagActionsModalIsOpen(false); + }; + const showEditUserTagModal = (): void => { + setEditUserTagModalIsOpen(true); + }; + const hideEditUserTagModal = (): void => { + setEditUserTagModalIsOpen(false); + }; const { data: userTagAssignedMembersData, loading: userTagAssignedMembersLoading, error: userTagAssignedMembersError, refetch: userTagAssignedMembersRefetch, - }: { - data?: { - getUserTag: InterfaceQueryUserTagsAssignedMembers; - }; - loading: boolean; - error?: ApolloError; - refetch: () => void; - } = useQuery(USER_TAGS_ASSIGNED_MEMBERS, { + fetchMore: fetchMoreAssignedMembers, + }: InterfaceTagAssignedMembersQuery = useQuery(USER_TAGS_ASSIGNED_MEMBERS, { variables: { id: currentTagId, - after: after, - before: before, - first: first, - last: last, + first: TAGS_QUERY_DATA_CHUNK_SIZE, + where: { + firstName: { starts_with: assignedMemberSearchFirstName }, + lastName: { starts_with: assignedMemberSearchLastName }, + }, + sortedBy: { id: assignedMemberSortOrder }, }, + fetchPolicy: 'no-cache', }); - const { - data: orgUserTagAncestorsData, - loading: orgUserTagsAncestorsLoading, - error: orgUserTagsAncestorsError, - }: { - data?: { - getUserTagAncestors: { - _id: string; - name: string; - }[]; - }; - loading: boolean; - error?: ApolloError; - refetch: () => void; - } = useQuery(USER_TAG_ANCESTORS, { - variables: { - id: currentTagId, - }, - }); + const loadMoreAssignedMembers = (): void => { + fetchMoreAssignedMembers({ + variables: { + first: TAGS_QUERY_DATA_CHUNK_SIZE, + after: + userTagAssignedMembersData?.getAssignedUsers.usersAssignedTo.pageInfo + .endCursor, + }, + updateQuery: ( + prevResult: { getAssignedUsers: InterfaceQueryUserTagsAssignedMembers }, + { + fetchMoreResult, + }: { + fetchMoreResult: { + getAssignedUsers: InterfaceQueryUserTagsAssignedMembers; + }; + }, + ) => { + if (!fetchMoreResult) /* istanbul ignore next */ return prevResult; + + return { + getAssignedUsers: { + ...fetchMoreResult.getAssignedUsers, + usersAssignedTo: { + ...fetchMoreResult.getAssignedUsers.usersAssignedTo, + edges: [ + ...prevResult.getAssignedUsers.usersAssignedTo.edges, + ...fetchMoreResult.getAssignedUsers.usersAssignedTo.edges, + ], + }, + }, + }; + }, + }); + }; + + useEffect(() => { + const [firstName, ...lastNameParts] = assignedMemberSearchInput + .trim() + .split(/\s+/); + const lastName = lastNameParts.join(' '); // Joins everything after the first word + setAssignedMemberSearchFirstName(firstName); + setAssignedMemberSearchLastName(lastName); + }, [assignedMemberSearchInput]); const [unassignUserTag] = useMutation(UNASSIGN_USER_TAG); - const handleUnassignTag = async (): Promise => { + const handleUnassignUserTag = async (): Promise => { try { await unassignUserTag({ variables: { @@ -112,7 +171,7 @@ function ManageTag(): JSX.Element { }); userTagAssignedMembersRefetch(); - toggleUnassignTagModal(); + toggleUnassignUserTagModal(); toast.success(t('successfullyUnassigned') as string); } catch (error: unknown) { /* istanbul ignore next */ @@ -122,22 +181,74 @@ function ManageTag(): JSX.Element { } }; - if (userTagAssignedMembersLoading || orgUserTagsAncestorsLoading) { - return ; - } + const [edit] = useMutation(UPDATE_USER_TAG); + + const [newTagName, setNewTagName] = useState(''); + const currentTagName = + userTagAssignedMembersData?.getAssignedUsers.name ?? ''; + + useEffect(() => { + setNewTagName(userTagAssignedMembersData?.getAssignedUsers.name ?? ''); + }, [userTagAssignedMembersData]); + + const handleEditUserTag = async ( + e: FormEvent, + ): Promise => { + e.preventDefault(); + + if (newTagName === currentTagName) { + toast.info(t('changeNameToEdit')); + return; + } - if (userTagAssignedMembersError || orgUserTagsAncestorsError) { + try { + const { data } = await edit({ + variables: { + tagId: currentTagId, + name: newTagName, + }, + }); + + if (data) { + toast.success(t('tagUpdationSuccess')); + userTagAssignedMembersRefetch(); + setEditUserTagModalIsOpen(false); + } + } catch (error: unknown) { + /* istanbul ignore next */ + if (error instanceof Error) { + toast.error(error.message); + } + } + }; + + const [removeUserTag] = useMutation(REMOVE_USER_TAG); + const handleRemoveUserTag = async (): Promise => { + try { + await removeUserTag({ + variables: { + id: currentTagId, + }, + }); + + navigate(`/orgtags/${orgId}`); + toggleRemoveUserTagModal(); + toast.success(t('tagRemovalSuccess') as string); + } catch (error: unknown) { + /* istanbul ignore next */ + if (error instanceof Error) { + toast.error(error.message); + } + } + }; + + if (userTagAssignedMembersError) { return (
    - Error occured while loading{' '} - {userTagAssignedMembersError ? 'assigned users' : 'tag ancestors'} -
    - {userTagAssignedMembersError - ? userTagAssignedMembersError.message - : orgUserTagsAncestorsError?.message} + Error occured while loading assigned users
    @@ -145,43 +256,31 @@ function ManageTag(): JSX.Element { } const userTagAssignedMembers = - userTagAssignedMembersData?.getUserTag.usersAssignedTo.edges.map( + userTagAssignedMembersData?.getAssignedUsers.usersAssignedTo.edges.map( (edge) => edge.node, - ); + ) ?? /* istanbul ignore next */ []; - const orgUserTagAncestors = orgUserTagAncestorsData?.getUserTagAncestors; + // get the ancestorTags array and push the current tag in it + // used for the tag breadcrumbs + const orgUserTagAncestors = [ + ...(userTagAssignedMembersData?.getAssignedUsers.ancestorTags ?? []), + { + _id: currentTagId, + name: currentTagName, + }, + ]; const redirectToSubTags = (tagId: string): void => { navigate(`/orgtags/${orgId}/subTags/${tagId}`); }; - const redirectToManageTag = (tagId: string): void => { - navigate(`/orgtags/${orgId}/managetag/${tagId}`); - }; - - const handleNextPage = (): void => { - setAfter( - userTagAssignedMembersData?.getUserTag.usersAssignedTo.pageInfo.endCursor, - ); - setBefore(null); - setFirst(5); - setLast(null); + navigate(`/orgtags/${orgId}/manageTag/${tagId}`); }; - const handlePreviousPage = (): void => { - setBefore( - userTagAssignedMembersData?.getUserTag.usersAssignedTo.pageInfo - .startCursor, - ); - setAfter(null); - setFirst(null); - setLast(5); - }; - - const toggleUnassignTagModal = (): void => { - if (unassignTagModalIsOpen) { + const toggleUnassignUserTagModal = (): void => { + if (unassignUserTagModalIsOpen) { setUnassignUserId(null); } - setUnassignTagModalIsOpen(!unassignTagModalIsOpen); + setUnassignUserTagModalIsOpen(!unassignUserTagModalIsOpen); }; const columns: GridColDef[] = [ @@ -223,23 +322,23 @@ function ManageTag(): JSX.Element { headerClassName: `${styles.tableHeader}`, renderCell: (params: GridCellParams) => { return ( -
    +
    -
    {t('viewProfile')}
    +
    + {t('viewProfile')} +
    -
    - - -
    +
    - - -
    -
    - -
    - -
    navigate(`/orgtags/${orgId}`)} - className={`fs-6 ms-3 my-1 ${styles.tagsBreadCrumbs}`} - data-testid="allTagsBtn" - > - {'Tags'} - -
    - - {orgUserTagAncestors?.map((tag, index) => ( + {userTagAssignedMembersLoading ? ( + + ) : ( + + +
    +
    + +
    redirectToManageTag(tag._id as string)} - data-testid="redirectToManageTag" + onClick={() => navigate(`/orgtags/${orgId}`)} + className={`fs-6 ms-3 my-1 ${styles.tagsBreadCrumbs}`} + data-testid="allTagsBtn" > - {tag.name} - - {orgUserTagAncestors.length - 1 !== index && ( - /* istanbul ignore next */ - - )} + {'Tags'} +
    - ))} -
    - row._id} - slots={{ - noRowsOverlay: /* istanbul ignore next */ () => ( - ( +
    redirectToManageTag(tag._id as string)} + data-testid="redirectToManageTag" > - {t('noAssignedMembersFound')} - - ), - }} - sx={dataGridStyle} - getRowClassName={() => `${styles.rowBackground}`} - autoHeight - rowHeight={65} - rows={userTagAssignedMembers?.map((assignedMembers, index) => ({ - id: index + 1, - ...assignedMembers, - }))} - columns={columns} - isRowSelectable={() => false} - /> - -
    -
    - + {tag.name} + {orgUserTagAncestors.length - 1 !== index && ( + /* istanbul ignore next */ + + )} +
    + ))}
    -
    - -
    -
    - - - -
    -
    {'Actions'}
    -
    -
    -
    - {'Email Users'} + row.id} + slots={{ + noRowsOverlay: /* istanbul ignore next */ () => ( + + {t('noAssignedMembersFound')} + + ), + }} + sx={dataGridStyle} + getRowClassName={() => `${styles.rowBackground}`} + autoHeight + rowHeight={65} + rows={userTagAssignedMembers?.map( + (assignedMembers, index) => ({ + id: index + 1, + ...assignedMembers, + }), + )} + columns={columns} + isRowSelectable={() => false} + /> +
    -
    -
    -
    -
    - {'Add to tags'} + + +
    +
    {'Actions'}
    -
    - {'Remove from tags'} +
    +
    { + setTagActionType('assignToTags'); + showTagActionsModal(); + }} + className="my-2 btn btn-primary btn-sm w-75" + data-testid="assignToTags" + > + {t('assignToTags')} +
    +
    { + setTagActionType('removeFromTags'); + showTagActionsModal(); + }} + className="mb-1 btn btn-danger btn-sm w-75" + data-testid="removeFromTags" + > + {t('removeFromTags')} +
    +
    +
    + {tCommon('edit')} +
    +
    + {tCommon('remove')} +
    -
    - - + + + )}
    {/* Add People To Tag Modal */} - - - {t('addPeople')} - -
    - - - - - - -
    -
    - - {/* Unassign Tag Modal */} - - - - {t('unassignUserTag')} - - - {t('unassignUserTagMessage')} - - - - - + + {/* Assign People To Tags Modal */} + + {/* Unassign User Tag Modal */} + + {/* Edit User Tag Modal */} + + {/* Remove User Tag Modal */} + ); } - export default ManageTag; diff --git a/src/screens/ManageTag/ManageTagMockComponents/MockAddPeopleToTag.tsx b/src/screens/ManageTag/ManageTagMockComponents/MockAddPeopleToTag.tsx new file mode 100644 index 0000000000..7e62c47f86 --- /dev/null +++ b/src/screens/ManageTag/ManageTagMockComponents/MockAddPeopleToTag.tsx @@ -0,0 +1,42 @@ +import React from 'react'; +import type { InterfaceAddPeopleToTagProps } from '../../../components/AddPeopleToTag/AddPeopleToTag'; + +/** + * Component that mocks the AddPeopleToTag component for the Manage Tag screen. + */ + +const TEST_IDS = { + MODAL: 'addPeopleToTagModal', + CLOSE_BUTTON: 'closeAddPeopleToTagModal', +} as const; +const MockAddPeopleToTag: React.FC = ({ + addPeopleToTagModalIsOpen, + hideAddPeopleToTagModal, +}) => { + return ( + <> + {addPeopleToTagModalIsOpen && ( +
    + + +
    + )} + + ); +}; + +export default MockAddPeopleToTag; diff --git a/src/screens/ManageTag/ManageTagMockComponents/MockTagActions.tsx b/src/screens/ManageTag/ManageTagMockComponents/MockTagActions.tsx new file mode 100644 index 0000000000..3d2d6cc880 --- /dev/null +++ b/src/screens/ManageTag/ManageTagMockComponents/MockTagActions.tsx @@ -0,0 +1,37 @@ +import React from 'react'; +import type { InterfaceTagActionsProps } from '../../../components/TagActions/TagActions'; + +/** + * Component that mocks the TagActions component for the Manage Tag screen. + */ + +const MockTagActions: React.FC = ({ + tagActionsModalIsOpen, + hideTagActionsModal, +}) => { + return ( + <> + {tagActionsModalIsOpen && ( +
    +

    + Tag Actions +

    + +
    + )} + + ); +}; + +export default MockTagActions; diff --git a/src/screens/ManageTag/ManageTagMocks.ts b/src/screens/ManageTag/ManageTagMocks.ts index c42c4a9e5f..5ce1e62595 100644 --- a/src/screens/ManageTag/ManageTagMocks.ts +++ b/src/screens/ManageTag/ManageTagMocks.ts @@ -1,8 +1,10 @@ -import { UNASSIGN_USER_TAG } from 'GraphQl/Mutations/TagMutations'; import { - USER_TAG_ANCESTORS, - USER_TAGS_ASSIGNED_MEMBERS, -} from 'GraphQl/Queries/userTagQueries'; + REMOVE_USER_TAG, + UNASSIGN_USER_TAG, + UPDATE_USER_TAG, +} from 'GraphQl/Mutations/TagMutations'; +import { USER_TAGS_ASSIGNED_MEMBERS } from 'GraphQl/Queries/userTagQueries'; +import { TAGS_QUERY_DATA_CHUNK_SIZE } from 'utils/organizationTagsUtils'; export const MOCKS = [ { @@ -10,15 +12,17 @@ export const MOCKS = [ query: USER_TAGS_ASSIGNED_MEMBERS, variables: { id: '1', - after: null, - before: null, - first: 5, - last: null, + first: TAGS_QUERY_DATA_CHUNK_SIZE, + where: { + firstName: { starts_with: '' }, + lastName: { starts_with: '' }, + }, + sortedBy: { id: 'DESCENDING' }, }, }, result: { data: { - getUserTag: { + getAssignedUsers: { name: 'tag1', usersAssignedTo: { edges: [ @@ -62,15 +66,56 @@ export const MOCKS = [ }, cursor: '5', }, + { + node: { + _id: '6', + firstName: 'member', + lastName: '6', + }, + cursor: '6', + }, + { + node: { + _id: '7', + firstName: 'member', + lastName: '7', + }, + cursor: '7', + }, + { + node: { + _id: '8', + firstName: 'member', + lastName: '8', + }, + cursor: '8', + }, + { + node: { + _id: '9', + firstName: 'member', + lastName: '9', + }, + cursor: '9', + }, + { + node: { + _id: '10', + firstName: 'member', + lastName: '10', + }, + cursor: '10', + }, ], pageInfo: { startCursor: '1', - endCursor: '5', + endCursor: '10', hasNextPage: true, hasPreviousPage: false, }, - totalCount: 6, + totalCount: 12, }, + ancestorTags: [], }, }, }, @@ -80,35 +125,47 @@ export const MOCKS = [ query: USER_TAGS_ASSIGNED_MEMBERS, variables: { id: '1', - after: '5', - before: null, - first: 5, - last: null, + first: TAGS_QUERY_DATA_CHUNK_SIZE, + after: '10', + where: { + firstName: { starts_with: '' }, + lastName: { starts_with: '' }, + }, + sortedBy: { id: 'DESCENDING' }, }, }, result: { data: { - getUserTag: { + getAssignedUsers: { name: 'tag1', usersAssignedTo: { edges: [ { node: { - _id: '6', + _id: '11', firstName: 'member', - lastName: '6', + lastName: '11', }, - cursor: '6', + cursor: '11', + }, + { + node: { + _id: '12', + firstName: 'member', + lastName: '12', + }, + cursor: '12', }, ], pageInfo: { - startCursor: '6', - endCursor: '6', + startCursor: '11', + endCursor: '12', hasNextPage: false, hasPreviousPage: true, }, - totalCount: 6, + totalCount: 12, }, + ancestorTags: [], }, }, }, @@ -118,86 +175,96 @@ export const MOCKS = [ query: USER_TAGS_ASSIGNED_MEMBERS, variables: { id: '1', - after: null, - before: '6', - first: null, - last: 5, + first: TAGS_QUERY_DATA_CHUNK_SIZE, + where: { + firstName: { starts_with: 'assigned' }, + lastName: { starts_with: 'user' }, + }, + sortedBy: { id: 'DESCENDING' }, }, }, result: { data: { - getUserTag: { + getAssignedUsers: { name: 'tag1', usersAssignedTo: { edges: [ { node: { _id: '1', - firstName: 'member', - lastName: '1', + firstName: 'assigned', + lastName: 'user1', }, cursor: '1', }, { node: { _id: '2', - firstName: 'member', - lastName: '2', + firstName: 'assigned', + lastName: 'user2', }, cursor: '2', }, - { - node: { - _id: '3', - firstName: 'member', - lastName: '3', - }, - cursor: '3', - }, - { - node: { - _id: '4', - firstName: 'member', - lastName: '4', - }, - cursor: '4', - }, - { - node: { - _id: '5', - firstName: 'member', - lastName: '5', - }, - cursor: '5', - }, ], pageInfo: { startCursor: '1', - endCursor: '5', - hasNextPage: true, + endCursor: '2', + hasNextPage: false, hasPreviousPage: false, }, - totalCount: 6, + totalCount: 2, }, + ancestorTags: [], }, }, }, }, { request: { - query: USER_TAG_ANCESTORS, + query: USER_TAGS_ASSIGNED_MEMBERS, variables: { id: '1', + first: TAGS_QUERY_DATA_CHUNK_SIZE, + where: { + firstName: { starts_with: 'assigned' }, + lastName: { starts_with: 'user' }, + }, + sortedBy: { id: 'ASCENDING' }, }, }, result: { data: { - getUserTagAncestors: [ - { - _id: '1', - name: 'tag1', + getAssignedUsers: { + name: 'tag1', + usersAssignedTo: { + edges: [ + { + node: { + _id: '2', + firstName: 'assigned', + lastName: 'user2', + }, + cursor: '2', + }, + { + node: { + _id: '1', + firstName: 'assigned', + lastName: 'user1', + }, + cursor: '1', + }, + ], + pageInfo: { + startCursor: '2', + endCursor: '1', + hasNextPage: false, + hasPreviousPage: false, + }, + totalCount: 2, }, - ], + ancestorTags: [], + }, }, }, }, @@ -217,72 +284,51 @@ export const MOCKS = [ }, }, }, -]; - -export const MOCKS_ERROR_ASSIGNED_MEMBERS = [ - { - request: { - query: USER_TAGS_ASSIGNED_MEMBERS, - variables: { - id: '1', - after: null, - before: null, - first: 5, - last: null, - }, - }, - error: new Error('Mock Graphql Error'), - }, { request: { - query: USER_TAG_ANCESTORS, + query: UPDATE_USER_TAG, variables: { - id: '1', + tagId: '1', + name: 'tag 1 edited', }, }, result: { data: { - getUserTagAncestors: [], + updateUserTag: { + _id: '1', + }, }, }, }, -]; - -export const MOCKS_ERROR_TAG_ANCESTORS = [ { request: { - query: USER_TAGS_ASSIGNED_MEMBERS, + query: REMOVE_USER_TAG, variables: { id: '1', - after: null, - before: null, - first: 5, - last: null, }, }, result: { data: { - getUserTag: { - name: 'tag1', - usersAssignedTo: { - edges: [], - pageInfo: { - startCursor: '1', - endCursor: '5', - hasNextPage: true, - hasPreviousPage: false, - }, - totalCount: 6, - }, + removeUserTag: { + _id: '1', }, }, }, }, +]; + +export const MOCKS_ERROR_ASSIGNED_MEMBERS = [ { request: { - query: USER_TAG_ANCESTORS, + query: USER_TAGS_ASSIGNED_MEMBERS, variables: { id: '1', + first: TAGS_QUERY_DATA_CHUNK_SIZE, + where: { + firstName: { starts_with: '' }, + lastName: { starts_with: '' }, + }, + sortedBy: { id: 'DESCENDING' }, }, }, error: new Error('Mock Graphql Error'), diff --git a/src/screens/ManageTag/RemoveUserTagModal.tsx b/src/screens/ManageTag/RemoveUserTagModal.tsx new file mode 100644 index 0000000000..dc000f443c --- /dev/null +++ b/src/screens/ManageTag/RemoveUserTagModal.tsx @@ -0,0 +1,72 @@ +import type { TFunction } from 'i18next'; +import React from 'react'; +import { Button, Modal } from 'react-bootstrap'; + +/** + * Remove UserTag Modal component for the Manage Tag screen. + */ + +export interface InterfaceRemoveUserTagModalProps { + removeUserTagModalIsOpen: boolean; + toggleRemoveUserTagModal: () => void; + handleRemoveUserTag: () => Promise; + t: TFunction<'translation', 'manageTag'>; + tCommon: TFunction<'common', undefined>; +} + +const RemoveUserTagModal: React.FC = ({ + removeUserTagModalIsOpen, + toggleRemoveUserTagModal, + handleRemoveUserTag, + t, + tCommon, +}) => { + return ( + <> + + + + {t('removeUserTag')} + + + + {t('removeUserTagMessage')} + + + + + + + + ); +}; + +export default RemoveUserTagModal; diff --git a/src/screens/ManageTag/UnassignUserTagModal.tsx b/src/screens/ManageTag/UnassignUserTagModal.tsx new file mode 100644 index 0000000000..9d926790c3 --- /dev/null +++ b/src/screens/ManageTag/UnassignUserTagModal.tsx @@ -0,0 +1,80 @@ +import type { TFunction } from 'i18next'; +import React from 'react'; +import { Button, Modal } from 'react-bootstrap'; + +/** + * Unassign UserTag Modal component for the Manage Tag screen. + */ + +export interface InterfaceUnassignUserTagModalProps { + unassignUserTagModalIsOpen: boolean; + toggleUnassignUserTagModal: () => void; + handleUnassignUserTag: () => Promise; + t: TFunction<'translation', 'manageTag' | 'memberDetail'>; + tCommon: TFunction<'common', undefined>; +} + +const UnassignUserTagModal: React.FC = ({ + unassignUserTagModalIsOpen, + toggleUnassignUserTagModal, + handleUnassignUserTag, + t, + tCommon, +}) => { + return ( + <> + + + + {t('unassignUserTag')} + + + {t('unassignUserTagMessage')} + + + + + + + ); +}; + +export default UnassignUserTagModal; diff --git a/src/screens/MemberDetail/MemberDetail.module.css b/src/screens/MemberDetail/MemberDetail.module.css index 603e55d1d9..7b421adcf8 100644 --- a/src/screens/MemberDetail/MemberDetail.module.css +++ b/src/screens/MemberDetail/MemberDetail.module.css @@ -10,6 +10,30 @@ height: 100%; } +.editIcon { + position: absolute; + top: 10px; + left: 20px; + cursor: pointer; +} +.selectWrapper { + position: relative; +} + +.selectWithChevron { + appearance: none; + padding-right: 30px; +} + +.selectWrapper::after { + content: '\25BC'; + position: absolute; + top: 50%; + right: 10px; + transform: translateY(-50%); + pointer-events: none; +} + .sidebar:after { content: ''; background-color: #f7f7f7; @@ -55,6 +79,10 @@ width: 60%; } +.contact { + width: 100%; +} + .sidebarsticky > input { text-decoration: none; margin-bottom: 50px; @@ -88,6 +116,10 @@ border-bottom: 3px solid #31bb6b; width: 60%; } +.cardBody { + height: 35vh; + overflow-y: scroll; +} .admindetails { display: flex; @@ -238,7 +270,6 @@ padding: 10px 10px; border-radius: 5px; background-color: #31bb6b; - width: 100%; font-size: 16px; color: white; outline: none; @@ -247,7 +278,23 @@ transition: transform 0.2s, box-shadow 0.2s; - width: 100%; +} +.whiteregbtn { + margin: 1rem 0 0; + margin-right: 2px; + margin-top: 10px; + border: 1px solid #31bb6b; + padding: 10px 10px; + border-radius: 5px; + background-color: white; + font-size: 16px; + color: #31bb6b; + outline: none; + font-weight: 600; + cursor: pointer; + transition: + transform 0.2s, + box-shadow 0.2s; } .loader, @@ -453,11 +500,112 @@ border-top-left-radius: 16px; border-top-right-radius: 16px; } +.eventContainer { + display: flex; + align-items: start; +} + +.eventDetailsBox { + position: relative; + box-sizing: border-box; + background: #ffffff; + width: 66%; + box-shadow: 0 3px 8px rgba(0, 0, 0, 0.1); + border-radius: 20px; + margin-bottom: 0; + margin-top: 20px; +} +.ctacards { + padding: 20px; + width: 100%; + display: flex; + margin: 0 4px; + justify-content: space-between; + box-shadow: 0 3px 8px rgba(0, 0, 0, 0.1); + align-items: center; + border-radius: 20px; +} +.ctacards span { + color: rgb(181, 181, 181); + font-size: small; +} +/* .eventDetailsBox::before { + content: ''; + position: absolute; + top: 0; + height: 100%; + width: 6px; + background-color: #31bb6b; + border-radius: 20px; +} */ + +.time { + display: flex; + justify-content: space-between; + padding: 15px; + padding-bottom: 0px; + width: 33%; + + box-sizing: border-box; + background: #ffffff; + box-shadow: 0 3px 8px rgba(0, 0, 0, 0.1); + border-radius: 20px; + margin-bottom: 0; + margin-top: 20px; + margin-left: 10px; +} + +.startTime, +.endTime { + display: flex; + font-size: 20px; +} + +.to { + padding-right: 10px; +} + +.startDate, +.endDate { + color: #808080; + font-size: 14px; +} + +.titlename { + font-weight: 600; + font-size: 25px; + padding: 15px; + padding-bottom: 0px; + width: 50%; +} + +.description { + color: #737373; + font-weight: 300; + font-size: 14px; + word-wrap: break-word; + padding: 15px; + padding-bottom: 0px; +} + +.toporgloc { + font-size: 16px; + padding: 15px; + padding-bottom: 0px; +} + +.toporgloc span { + color: #737373; +} .inputColor { background: #f1f3f6; } - +.cardHeader { + display: flex; + justify-content: space-between; + align-items: center; +} .width60 { width: 60%; } @@ -465,6 +613,9 @@ .maxWidth40 { max-width: 40%; } +.maxWidth50 { + max-width: 50%; +} .allRound { border-radius: 16px; @@ -521,3 +672,15 @@ input::file-selector-button { .Outline { outline: 1px solid var(--bs-gray-400); } + +.tagLink { + font-weight: 600; + color: var(--bs-gray-700); + cursor: pointer; +} + +.tagLink:hover { + font-weight: 800; + color: var(--bs-blue); + text-decoration: underline; +} diff --git a/src/screens/MemberDetail/MemberDetail.test.tsx b/src/screens/MemberDetail/MemberDetail.test.tsx index 7b3707754c..b0514701f5 100644 --- a/src/screens/MemberDetail/MemberDetail.test.tsx +++ b/src/screens/MemberDetail/MemberDetail.test.tsx @@ -1,306 +1,49 @@ import React from 'react'; +import type { RenderResult } from '@testing-library/react'; import { act, + cleanup, fireEvent, render, screen, waitFor, + waitForElementToBeRemoved, } from '@testing-library/react'; import { MockedProvider } from '@apollo/react-testing'; import userEvent from '@testing-library/user-event'; -import { BrowserRouter } from 'react-router-dom'; +import { BrowserRouter, MemoryRouter, Route, Routes } from 'react-router-dom'; import { Provider } from 'react-redux'; import { store } from 'state/store'; import { I18nextProvider } from 'react-i18next'; -import { USER_DETAILS } from 'GraphQl/Queries/Queries'; import i18nForTest from 'utils/i18nForTest'; import { StaticMockLink } from 'utils/StaticMockLink'; import MemberDetail, { getLanguageName, prettyDate } from './MemberDetail'; +import { MOCKS1, MOCKS2, MOCKS3 } from './MemberDetailMocks'; +import type { ApolloLink } from '@apollo/client'; import { toast } from 'react-toastify'; -const MOCKS1 = [ - { - request: { - query: USER_DETAILS, - variables: { - id: 'rishav-jha-mech', - }, - }, - result: { - data: { - user: { - __typename: 'UserData', - appUserProfile: { - _id: '1', - __typename: 'AppUserProfile', - adminFor: [ - { - __typename: 'Organization', - _id: '65e0df0906dd1228350cfd4a', - }, - { - __typename: 'Organization', - _id: '65e0e2abb92c9f3e29503d4e', - }, - ], - isSuperAdmin: false, - appLanguageCode: 'en', - createdEvents: [ - { - __typename: 'Event', - _id: '65e32a5b2a1f4288ca1f086a', - }, - ], - createdOrganizations: [ - { - __typename: 'Organization', - _id: '65e0df0906dd1228350cfd4a', - }, - { - __typename: 'Organization', - _id: '65e0e2abb92c9f3e29503d4e', - }, - ], - eventAdmin: [ - { - __typename: 'Event', - _id: '65e32a5b2a1f4288ca1f086a', - }, - ], - pluginCreationAllowed: true, - }, - user: { - _id: '1', - __typename: 'User', - createdAt: '2024-02-26T10:36:33.098Z', - email: 'adi790u@gmail.com', - firstName: 'Aditya', - image: null, - lastName: 'Agarwal', - gender: '', - birthDate: '2024-03-14', - educationGrade: '', - employmentStatus: '', - maritalStatus: '', - address: { - line1: '', - countryCode: '', - city: '', - state: '', - }, - phone: { - mobile: '', - }, - joinedOrganizations: [ - { - __typename: 'Organization', - _id: '65e0df0906dd1228350cfd4a', - }, - { - __typename: 'Organization', - _id: '65e0e2abb92c9f3e29503d4e', - }, - ], - membershipRequests: [], - organizationsBlockedBy: [], - registeredEvents: [ - { - __typename: 'Event', - _id: '65e32a5b2a1f4288ca1f086a', - }, - ], - }, - }, - }, - }, - }, -]; - -const MOCKS2 = [ - { - request: { - query: USER_DETAILS, - variables: { - id: 'rishav-jha-mech', - }, - }, - result: { - data: { - user: { - __typename: 'UserData', - appUserProfile: { - _id: '1', - __typename: 'AppUserProfile', - adminFor: [], - isSuperAdmin: false, - appLanguageCode: 'en', - createdEvents: [ - { - __typename: 'Event', - _id: '65e32a5b2a1f4288ca1f086a', - }, - ], - createdOrganizations: [ - { - __typename: 'Organization', - _id: '65e0df0906dd1228350cfd4a', - }, - { - __typename: 'Organization', - _id: '65e0e2abb92c9f3e29503d4e', - }, - ], - eventAdmin: [ - { - __typename: 'Event', - _id: '65e32a5b2a1f4288ca1f086a', - }, - ], - pluginCreationAllowed: true, - }, - user: { - _id: '1', - __typename: 'User', - createdAt: '2024-02-26T10:36:33.098Z', - email: 'adi790u@gmail.com', - firstName: 'Aditya', - image: 'https://placeholder.com/200x200', - lastName: 'Agarwal', - gender: '', - birthDate: '2024-03-14', - educationGrade: '', - employmentStatus: '', - maritalStatus: '', - address: { - line1: '', - countryCode: '', - city: '', - state: '', - }, - phone: { - mobile: '', - }, - joinedOrganizations: [ - { - __typename: 'Organization', - _id: '65e0df0906dd1228350cfd4a', - }, - { - __typename: 'Organization', - _id: '65e0e2abb92c9f3e29503d4e', - }, - ], - membershipRequests: [], - organizationsBlockedBy: [], - registeredEvents: [ - { - __typename: 'Event', - _id: '65e32a5b2a1f4288ca1f086a', - }, - ], - }, - }, - }, - }, - }, -]; -const MOCKS3 = [ - { - request: { - query: USER_DETAILS, - variables: { - id: 'rishav-jha-mech', - }, - }, - result: { - data: { - user: { - __typename: 'UserData', - appUserProfile: { - _id: '1', - __typename: 'AppUserProfile', - adminFor: [], - isSuperAdmin: true, - appLanguageCode: 'en', - createdEvents: [ - { - __typename: 'Event', - _id: '65e32a5b2a1f4288ca1f086a', - }, - ], - createdOrganizations: [ - { - __typename: 'Organization', - _id: '65e0df0906dd1228350cfd4a', - }, - { - __typename: 'Organization', - _id: '65e0e2abb92c9f3e29503d4e', - }, - ], - eventAdmin: [ - { - __typename: 'Event', - _id: '65e32a5b2a1f4288ca1f086a', - }, - ], - pluginCreationAllowed: true, - }, - user: { - _id: '1', - __typename: 'User', - createdAt: '2024-02-26T10:36:33.098Z', - email: 'adi790u@gmail.com', - firstName: 'Aditya', - image: 'https://placeholder.com/200x200', - lastName: 'Agarwal', - gender: '', - birthDate: '2024-03-14', - educationGrade: '', - employmentStatus: '', - maritalStatus: '', - address: { - line1: '', - countryCode: '', - city: '', - state: '', - }, - phone: { - mobile: '', - }, - joinedOrganizations: [ - { - __typename: 'Organization', - _id: '65e0df0906dd1228350cfd4a', - }, - { - __typename: 'Organization', - _id: '65e0e2abb92c9f3e29503d4e', - }, - ], - membershipRequests: [], - organizationsBlockedBy: [], - registeredEvents: [ - { - __typename: 'Event', - _id: '65e32a5b2a1f4288ca1f086a', - }, - ], - }, - }, - }, - }, - }, -]; - const link1 = new StaticMockLink(MOCKS1, true); const link2 = new StaticMockLink(MOCKS2, true); const link3 = new StaticMockLink(MOCKS3, true); -async function wait(ms = 20): Promise { +async function wait(ms = 500): Promise { await act(() => new Promise((resolve) => setTimeout(resolve, ms))); } +const translations = { + ...JSON.parse( + JSON.stringify( + i18nForTest.getDataByLanguage('en')?.translation.memberDetail ?? {}, + ), + ), + ...JSON.parse( + JSON.stringify(i18nForTest.getDataByLanguage('en')?.common ?? {}), + ), + ...JSON.parse( + JSON.stringify(i18nForTest.getDataByLanguage('en')?.errors ?? {}), + ), +}; + jest.mock('@mui/x-date-pickers/DateTimePicker', () => { return { DateTimePicker: jest.requireActual( @@ -309,41 +52,65 @@ jest.mock('@mui/x-date-pickers/DateTimePicker', () => { }; }); -jest.mock('react-toastify'); +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +const props = { + id: 'rishav-jha-mech', +}; + +const renderMemberDetailScreen = (link: ApolloLink): RenderResult => { + return render( + + + + + + } + /> +
    } + /> + + + + + , + ); +}; describe('MemberDetail', () => { global.alert = jest.fn(); + afterEach(() => { + jest.clearAllMocks(); + cleanup(); + }); + test('should render the elements', async () => { - const props = { - id: 'rishav-jha-mech', - }; + renderMemberDetailScreen(link1); - render( - - - - - - - - - , - ); + await wait(); expect(screen.queryByText('Loading data...')).not.toBeInTheDocument(); - await wait(); expect(screen.getAllByText(/Email/i)).toBeTruthy(); expect(screen.getAllByText(/First name/i)).toBeTruthy(); expect(screen.getAllByText(/Last name/i)).toBeTruthy(); - expect(screen.getAllByText(/Language/i)).toBeTruthy(); - expect(screen.getByText(/Plugin creation allowed/i)).toBeInTheDocument(); - expect(screen.getAllByText(/Joined on/i)).toBeTruthy(); - expect(screen.getAllByText(/Joined On/i)).toHaveLength(1); - expect(screen.getAllByText(/Personal Information/i)).toHaveLength(1); + // expect(screen.getAllByText(/Language/i)).toBeTruthy(); + // expect(screen.getByText(/Plugin creation allowed/i)).toBeInTheDocument(); + // expect(screen.getAllByText(/Joined on/i)).toBeTruthy(); + // expect(screen.getAllByText(/Joined On/i)).toHaveLength(1); expect(screen.getAllByText(/Profile Details/i)).toHaveLength(1); - expect(screen.getAllByText(/Actions/i)).toHaveLength(1); + // expect(screen.getAllByText(/Actions/i)).toHaveLength(1); expect(screen.getAllByText(/Contact Information/i)).toHaveLength(1); + expect(screen.getAllByText(/Events Attended/i)).toHaveLength(2); }); test('prettyDate function should work properly', () => { @@ -365,10 +132,6 @@ describe('MemberDetail', () => { }); test('should render props and text elements test for the page component', async () => { - const props = { - id: '1', - }; - const formData = { firstName: 'Ansh', lastName: 'Goyal', @@ -381,19 +144,11 @@ describe('MemberDetail', () => { phoneNumber: '1234567890', birthDate: '03/28/2022', }; - render( - - - - - - - - - , - ); - expect(screen.queryByText('Loading data...')).not.toBeInTheDocument(); + renderMemberDetailScreen(link2); + await wait(); + + expect(screen.queryByText('Loading data...')).not.toBeInTheDocument(); expect(screen.getAllByText(/Email/i)).toBeTruthy(); expect(screen.getByText('User')).toBeInTheDocument(); const birthDateDatePicker = screen.getByTestId('birthDate'); @@ -401,26 +156,42 @@ describe('MemberDetail', () => { target: { value: formData.birthDate }, }); + userEvent.clear(screen.getByPlaceholderText(/First Name/i)); userEvent.type( screen.getByPlaceholderText(/First Name/i), formData.firstName, ); + + userEvent.clear(screen.getByPlaceholderText(/Last Name/i)); userEvent.type( screen.getByPlaceholderText(/Last Name/i), formData.lastName, ); + + userEvent.clear(screen.getByPlaceholderText(/Address/i)); userEvent.type(screen.getByPlaceholderText(/Address/i), formData.address); + + userEvent.clear(screen.getByPlaceholderText(/Country Code/i)); userEvent.type( screen.getByPlaceholderText(/Country Code/i), formData.countryCode, ); + + userEvent.clear(screen.getByPlaceholderText(/State/i)); userEvent.type(screen.getByPlaceholderText(/State/i), formData.state); + + userEvent.clear(screen.getByPlaceholderText(/City/i)); userEvent.type(screen.getByPlaceholderText(/City/i), formData.city); + + userEvent.clear(screen.getByPlaceholderText(/Email/i)); userEvent.type(screen.getByPlaceholderText(/Email/i), formData.email); + + userEvent.clear(screen.getByPlaceholderText(/Phone/i)); userEvent.type(screen.getByPlaceholderText(/Phone/i), formData.phoneNumber); - userEvent.click(screen.getByPlaceholderText(/pluginCreationAllowed/i)); - userEvent.selectOptions(screen.getByTestId('applangcode'), 'Français'); - userEvent.upload(screen.getByLabelText(/Display Image:/i), formData.image); + + // userEvent.click(screen.getByPlaceholderText(/pluginCreationAllowed/i)); + // userEvent.selectOptions(screen.getByTestId('applangcode'), 'Français'); + // userEvent.upload(screen.getByLabelText(/Display Image:/i), formData.image); await wait(); userEvent.click(screen.getByText(/Save Changes/i)); @@ -436,97 +207,26 @@ describe('MemberDetail', () => { expect(screen.getByPlaceholderText(/First Name/i)).toBeInTheDocument(); expect(screen.getByPlaceholderText(/Last Name/i)).toBeInTheDocument(); expect(screen.getByPlaceholderText(/Email/i)).toBeInTheDocument(); - expect(screen.getByText(/Display Image/i)).toBeInTheDocument(); - }); - - test('should display warnings for blank form submission', async () => { - jest.spyOn(toast, 'warning'); - const props = { - id: '1', - toggleStateValue: jest.fn(), - }; - - render( - - - - - - - - - , - ); - - await wait(); - - userEvent.click(screen.getByText(/Save Changes/i)); - - expect(toast.warning).toHaveBeenCalledWith('First Name cannot be blank!'); - expect(toast.warning).toHaveBeenCalledWith('Last Name cannot be blank!'); - expect(toast.warning).toHaveBeenCalledWith('Email cannot be blank!'); + // expect(screen.getByText(/Display Image/i)).toBeInTheDocument(); }); test('display admin', async () => { - const props = { - id: 'rishav-jha-mech', - }; - - render( - - - - - - - - - , - ); - - expect(screen.queryByText('Loading data...')).not.toBeInTheDocument(); + renderMemberDetailScreen(link1); await wait(); + expect(screen.queryByText('Loading data...')).not.toBeInTheDocument(); expect(screen.getByText('Admin')).toBeInTheDocument(); }); - test('display super admin', async () => { - const props = { - id: 'rishav-jha-mech', - }; - render( - - - - - - - - - , - ); - - expect(screen.queryByText('Loading data...')).not.toBeInTheDocument(); + test('display super admin', async () => { + renderMemberDetailScreen(link3); await wait(); + expect(screen.queryByText('Loading data...')).not.toBeInTheDocument(); expect(screen.getByText('Super Admin')).toBeInTheDocument(); }); test('Should display dicebear image if image is null', async () => { - const props = { - id: 'rishav-jha-mech', - from: 'orglist', - }; + renderMemberDetailScreen(link1); - render( - - - - - - - - - , - ); expect(screen.queryByText('Loading data...')).not.toBeInTheDocument(); const dicebearUrl = `mocked-data-uri`; @@ -537,22 +237,7 @@ describe('MemberDetail', () => { }); test('Should display image if image is present', async () => { - const props = { - id: 'rishav-jha-mech', - from: 'orglist', - }; - - render( - - - - - - - - - , - ); + renderMemberDetailScreen(link2); expect(screen.queryByText('Loading data...')).not.toBeInTheDocument(); @@ -562,25 +247,25 @@ describe('MemberDetail', () => { expect(userImage.getAttribute('src')).toBe(user?.image); }); - test('should call setState with 2 when button is clicked', async () => { - const props = { - id: 'rishav-jha-mech', - }; - render( - - - - - - - - - , - ); + test('resetChangesBtn works properly', async () => { + renderMemberDetailScreen(link1); - expect(screen.queryByText('Loading data...')).not.toBeInTheDocument(); + await waitFor(() => { + expect(screen.getByPlaceholderText(/Address/i)).toBeInTheDocument(); + }); + + userEvent.type(screen.getByPlaceholderText(/Address/i), 'random'); + userEvent.type(screen.getByPlaceholderText(/State/i), 'random'); - waitFor(() => userEvent.click(screen.getByText(/Edit Profile/i))); + userEvent.click(screen.getByTestId('resetChangesBtn')); + await wait(); + expect(screen.getByPlaceholderText(/First Name/i)).toHaveValue('Aditya'); + expect(screen.getByPlaceholderText(/Last Name/i)).toHaveValue('Agarwal'); + expect(screen.getByPlaceholderText(/Phone/i)).toHaveValue(''); + expect(screen.getByPlaceholderText(/Address/i)).toHaveValue(''); + expect(screen.getByPlaceholderText(/State/i)).toHaveValue(''); + expect(screen.getByPlaceholderText(/Country Code/i)).toHaveValue(''); + expect(screen.getByTestId('birthDate')).toHaveValue('03/14/2024'); }); test('should be redirected to / if member id is undefined', async () => { @@ -597,4 +282,119 @@ describe('MemberDetail', () => { ); expect(window.location.pathname).toEqual('/'); }); + + test('renders events attended card correctly and show a message', async () => { + renderMemberDetailScreen(link3); + await waitFor(() => { + expect(screen.getByText('Events Attended')).toBeInTheDocument(); + }); + // Check for empty state immediately + expect(screen.getByText('No Events Attended')).toBeInTheDocument(); + }); + + test('opens "Events Attended List" modal when View All button is clicked', async () => { + renderMemberDetailScreen(link2); + + await wait(); + + // Find and click the "View All" button + const viewAllButton = screen.getByText('View All'); + userEvent.click(viewAllButton); + + // Check if the modal with the title "Events Attended List" is now visible + const modalTitle = await screen.findByText('Events Attended List'); + expect(modalTitle).toBeInTheDocument(); + }); + + test('lists all the tags assigned to the user', async () => { + renderMemberDetailScreen(link1); + + await wait(); + + await waitFor(() => { + expect(screen.getAllByTestId('tagName')).toHaveLength(10); + }); + }); + + test('navigates to manage tag screen after clicking manage tag option', async () => { + renderMemberDetailScreen(link1); + + await wait(); + + await waitFor(() => { + expect(screen.getAllByTestId('tagName')[0]).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('tagName')[0]); + + await waitFor(() => { + expect(screen.getByTestId('manageTagScreen')).toBeInTheDocument(); + }); + }); + + test('loads more assigned tags with infinite scroll', async () => { + renderMemberDetailScreen(link1); + + await wait(); + + // now scroll to the bottom of the div + const tagsAssignedScrollableDiv = screen.getByTestId( + 'tagsAssignedScrollableDiv', + ); + + // Get the initial number of tags loaded + const initialTagsAssignedLength = screen.getAllByTestId('tagName').length; + + // Set scroll position to the bottom + fireEvent.scroll(tagsAssignedScrollableDiv, { + target: { scrollY: tagsAssignedScrollableDiv.scrollHeight }, + }); + + await waitFor(() => { + const finalTagsAssignedLength = screen.getAllByTestId('tagName').length; + expect(finalTagsAssignedLength).toBeGreaterThan( + initialTagsAssignedLength, + ); + }); + }); + + test('opens and closes the unassign tag modal', async () => { + renderMemberDetailScreen(link1); + + await wait(); + + await waitFor(() => { + expect(screen.getAllByTestId('unassignTagBtn')[0]).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('unassignTagBtn')[0]); + + await waitFor(() => { + return expect( + screen.findByTestId('unassignTagModalCloseBtn'), + ).resolves.toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('unassignTagModalCloseBtn')); + + await waitForElementToBeRemoved(() => + screen.queryByTestId('unassignTagModalCloseBtn'), + ); + }); + + test('unassigns a tag from a member', async () => { + renderMemberDetailScreen(link1); + + await wait(); + + await waitFor(() => { + expect(screen.getAllByTestId('unassignTagBtn')[0]).toBeInTheDocument(); + }); + userEvent.click(screen.getAllByTestId('unassignTagBtn')[0]); + + userEvent.click(screen.getByTestId('unassignTagModalSubmitBtn')); + + await waitFor(() => { + expect(toast.success).toHaveBeenCalledWith( + translations.successfullyUnassigned, + ); + }); + }); }); diff --git a/src/screens/MemberDetail/MemberDetail.tsx b/src/screens/MemberDetail/MemberDetail.tsx index 6d92ccbb4a..cd552c80a0 100644 --- a/src/screens/MemberDetail/MemberDetail.tsx +++ b/src/screens/MemberDetail/MemberDetail.tsx @@ -2,25 +2,22 @@ import React, { useEffect, useRef, useState } from 'react'; import { useMutation, useQuery } from '@apollo/client'; import Button from 'react-bootstrap/Button'; import { useTranslation } from 'react-i18next'; -import { useLocation } from 'react-router-dom'; -import { USER_DETAILS } from 'GraphQl/Queries/Queries'; +import { useLocation, useNavigate, useParams } from 'react-router-dom'; import styles from './MemberDetail.module.css'; import { languages } from 'utils/languages'; import { UPDATE_USER_MUTATION } from 'GraphQl/Mutations/mutations'; +import { USER_DETAILS } from 'GraphQl/Queries/Queries'; import { toast } from 'react-toastify'; import { errorHandler } from 'utils/errorHandler'; +import { Card, Row, Col } from 'react-bootstrap'; import Loader from 'components/Loader/Loader'; import useLocalStorage from 'utils/useLocalstorage'; import Avatar from 'components/Avatar/Avatar'; -import { - CalendarIcon, - DatePicker, - LocalizationProvider, -} from '@mui/x-date-pickers'; +import EventsAttendedByMember from '../../components/MemberDetail/EventsAttendedByMember'; +import MemberAttendedEventsModal from '../../components/MemberDetail/EventsAttendedMemberModal'; +import { DatePicker, LocalizationProvider } from '@mui/x-date-pickers'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; -import { Form } from 'react-bootstrap'; import convertToBase64 from 'utils/convertToBase64'; -import sanitizeHtml from 'sanitize-html'; import type { Dayjs } from 'dayjs'; import dayjs from 'dayjs'; import { @@ -30,9 +27,16 @@ import { employmentStatusEnum, } from 'utils/formEnumFields'; import DynamicDropDown from 'components/DynamicDropDown/DynamicDropDown'; +import type { InterfaceEvent } from 'components/EventManagement/EventAttendance/InterfaceEvents'; +import type { InterfaceTagData } from 'utils/interfaces'; +import InfiniteScroll from 'react-infinite-scroll-component'; +import InfiniteScrollLoader from 'components/InfiniteScrollLoader/InfiniteScrollLoader'; +import UnassignUserTagModal from 'screens/ManageTag/UnassignUserTagModal'; +import { UNASSIGN_USER_TAG } from 'GraphQl/Mutations/TagMutations'; +import { TAGS_QUERY_DATA_CHUNK_SIZE } from 'utils/organizationTagsUtils'; type MemberDetailProps = { - id?: string; // This is the userId + id?: string; }; /** @@ -48,11 +52,20 @@ const MemberDetail: React.FC = ({ id }): JSX.Element => { const { t } = useTranslation('translation', { keyPrefix: 'memberDetail', }); + const fileInputRef = useRef(null); const { t: tCommon } = useTranslation('common'); const location = useLocation(); const isMounted = useRef(true); const { getItem, setItem } = useLocalStorage(); + const [show, setShow] = useState(false); const currentUrl = location.state?.id || getItem('id') || id; + + const { orgId } = useParams(); + const navigate = useNavigate(); + + const [unassignUserTagModalIsOpen, setUnassignUserTagModalIsOpen] = + useState(false); + document.title = t('title'); const [formState, setFormState] = useState({ firstName: '', @@ -72,24 +85,33 @@ const MemberDetail: React.FC = ({ id }): JSX.Element => { country: '', pluginCreationAllowed: false, }); - // Handle date change const handleDateChange = (date: Dayjs | null): void => { if (date) { + setisUpdated(true); setFormState((prevState) => ({ ...prevState, - birthDate: dayjs(date).format('YYYY-MM-DD'), // Convert Dayjs object to JavaScript Date object + birthDate: dayjs(date).format('YYYY-MM-DD'), })); } }; + + /*istanbul ignore next*/ + const handleEditIconClick = (): void => { + fileInputRef.current?.click(); + }; const [updateUser] = useMutation(UPDATE_USER_MUTATION); - const { data: user, loading: loading } = useQuery(USER_DETAILS, { - variables: { id: currentUrl }, // For testing we are sending the id as a prop + const { + data: user, + loading, + refetch: refetchUserDetails, + fetchMore: fetchMoreAssignedTags, + } = useQuery(USER_DETAILS, { + variables: { id: currentUrl, first: TAGS_QUERY_DATA_CHUNK_SIZE }, }); const userData = user?.user; - + const [isUpdated, setisUpdated] = useState(false); useEffect(() => { - if (userData && isMounted) { - // console.log(userData); + if (userData && isMounted.current) { setFormState({ ...formState, firstName: userData?.user?.firstName, @@ -97,7 +119,7 @@ const MemberDetail: React.FC = ({ id }): JSX.Element => { email: userData?.user?.email, appLanguageCode: userData?.appUserProfile?.appLanguageCode, gender: userData?.user?.gender, - birthDate: userData?.user?.birthDate || '2020-03-14', + birthDate: userData?.user?.birthDate || ' ', grade: userData?.user?.educationGrade, empStatus: userData?.user?.employmentStatus, maritalStatus: userData?.user?.maritalStatus, @@ -111,7 +133,6 @@ const MemberDetail: React.FC = ({ id }): JSX.Element => { }); } }, [userData, user]); - useEffect(() => { // check component is mounted or not return () => { @@ -119,75 +140,120 @@ const MemberDetail: React.FC = ({ id }): JSX.Element => { }; }, []); - const handleChange = (e: React.ChangeEvent): void => { - const { name, value } = e.target; - // setFormState({ - // ...formState, - // [name]: value, - // }); - // console.log(name, value); - setFormState((prevState) => ({ - ...prevState, - [name]: value, - })); - // console.log(formState); + const tagsAssigned = + userData?.user?.tagsAssignedWith.edges.map( + (edge: { node: InterfaceTagData; cursor: string }) => edge.node, + ) ?? /* istanbul ignore next */ []; + + const loadMoreAssignedTags = (): void => { + fetchMoreAssignedTags({ + variables: { + first: TAGS_QUERY_DATA_CHUNK_SIZE, + after: + user?.user?.user?.tagsAssignedWith?.pageInfo?.endCursor ?? + /* istanbul ignore next */ + null, + }, + updateQuery: (prevResult, { fetchMoreResult }) => { + if (!fetchMoreResult) /* istanbul ignore next */ return prevResult; + + return { + user: { + ...prevResult.user, + user: { + ...prevResult.user.user, + tagsAssignedWith: { + edges: [ + ...prevResult.user.user.tagsAssignedWith.edges, + ...fetchMoreResult.user.user.tagsAssignedWith.edges, + ], + pageInfo: fetchMoreResult.user.user.tagsAssignedWith.pageInfo, + totalCount: fetchMoreResult.user.user.tagsAssignedWith.pageInfo, + }, + }, + }, + }; + }, + }); + }; + + const [unassignUserTag] = useMutation(UNASSIGN_USER_TAG); + const [unassignTagId, setUnassignTagId] = useState(null); + + const handleUnassignUserTag = async (): Promise => { + try { + await unassignUserTag({ + variables: { + tagId: unassignTagId, + userId: currentUrl, + }, + }); + + refetchUserDetails(); + toggleUnassignUserTagModal(); + toast.success(t('successfullyUnassigned')); + } catch (error: unknown) { + /* istanbul ignore next */ + if (error instanceof Error) { + toast.error(error.message); + } + } }; - // const handlePhoneChange = (e: React.ChangeEvent): void => { - // const { name, value } = e.target; - // setFormState({ - // ...formState, - // phoneNumber: { - // ...formState.phoneNumber, - // [name]: value, - // }, - // }); - // // console.log(formState); - // }; + const toggleUnassignUserTagModal = (): void => { + if (unassignUserTagModalIsOpen) { + setUnassignTagId(null); + } + setUnassignUserTagModalIsOpen(!unassignUserTagModalIsOpen); + }; - const handleToggleChange = (e: React.ChangeEvent): void => { - // console.log(e.target.checked); - const { name, checked } = e.target; - setFormState((prevState) => ({ - ...prevState, - [name]: checked, - })); - // console.log(formState); + const handleChange = async ( + e: React.ChangeEvent, + ): Promise => { + const { name, value } = e.target; + /*istanbul ignore next*/ + if ( + name === 'photo' && + 'files' in e.target && + e.target.files && + e.target.files[0] + ) { + const file = e.target.files[0]; + const base64 = await convertToBase64(file); + setFormState((prevState) => ({ + ...prevState, + image: base64 as string, + })); + } else { + setFormState((prevState) => ({ + ...prevState, + [name]: value, + })); + } + setisUpdated(true); + }; + const handleEventsAttendedModal = (): void => { + setShow(!show); }; const loginLink = async (): Promise => { try { - // console.log(formState); const firstName = formState.firstName; const lastName = formState.lastName; const email = formState.email; // const appLanguageCode = formState.appLanguageCode; const image = formState.image; // const gender = formState.gender; - let toSubmit = true; - if (firstName.trim().length == 0 || !firstName) { - toast.warning('First Name cannot be blank!'); - toSubmit = false; - } - if (lastName.trim().length == 0 || !lastName) { - toast.warning('Last Name cannot be blank!'); - toSubmit = false; - } - if (email.trim().length == 0 || !email) { - toast.warning('Email cannot be blank!'); - toSubmit = false; - } - if (!toSubmit) return; try { const { data } = await updateUser({ variables: { - //! Currently only some fields are supported by the api id: currentUrl, ...formState, }, }); /* istanbul ignore next */ if (data) { + setisUpdated(false); if (getItem('id') === currentUrl) { setItem('FirstName', firstName); setItem('LastName', lastName); @@ -208,346 +274,471 @@ const MemberDetail: React.FC = ({ id }): JSX.Element => { } } }; + const resetChanges = (): void => { + /*istanbul ignore next*/ + setFormState({ + firstName: userData?.user?.firstName || '', + lastName: userData?.user?.lastName || '', + email: userData?.user?.email || '', + appLanguageCode: userData?.appUserProfile?.appLanguageCode || '', + image: userData?.user?.image || '', + gender: userData?.user?.gender || '', + empStatus: userData?.user?.employmentStatus || '', + maritalStatus: userData?.user?.maritalStatus || '', + phoneNumber: userData?.user?.phone?.mobile || '', + address: userData?.user?.address?.line1 || '', + country: userData?.user?.address?.countryCode || '', + city: userData?.user?.address?.city || '', + state: userData?.user?.address?.state || '', + birthDate: userData?.user?.birthDate || '', + grade: userData?.user?.educationGrade || '', + pluginCreationAllowed: + userData?.appUserProfile?.pluginCreationAllowed || false, + }); + setisUpdated(false); + }; if (loading) { return ; } - const sanitizedSrc = sanitizeHtml(formState.image, { - allowedTags: ['img'], - allowedAttributes: { - img: ['src', 'alt'], - }, - }); - return ( -
    -
    -
    - {/* Personal */} -
    -
    + )} + + + + +

    {t('personalDetailsHeading')}

    + +
    + +
    + {formState?.image ? ( +
    + User + e.key === 'Enter' && handleEditIconClick() + } + /> +
    + ) : ( +
    + + +
    + )} +
    -
    -
    -

    {tCommon('firstName')}

    + + + -
    -
    -

    {tCommon('lastName')}

    + + + -
    -
    -

    {t('gender')}

    -
    - -
    -
    -
    -

    {t('birthDate')}

    -
    - -
    -
    -
    -

    {t('educationGrade')}

    + + + -
    -
    -

    {t('employmentStatus')}

    + + + + + + + -
    -
    -

    {t('maritalStatus')}

    + + + -
    -

    -

    -
    -
    - {/* Contact Info */} -
    -
    -

    {t('contactInfoHeading')}

    -
    -
    -
    -

    {t('phone')}

    - -
    -
    -

    {tCommon('email')}

    + + + + + + + + +

    {t('contactInfoHeading')}

    +
    + + + + -
    -
    -

    {tCommon('address')}

    + + + -
    -
    -

    {t('countryCode')}

    + + + -
    -
    -

    {t('city')}

    + + + -
    -
    -

    {t('state')}

    + + + -
    -
    -
    -
    -
    - {/* Personal */} -
    -
    + + + + + + + + + {isUpdated && ( + + +
    -
    -
    - {formState.image ? ( - - ) : ( - <> - - - )} -
    -
    -

    {formState?.firstName}

    -
    -

    - {userData?.appUserProfile?.isSuperAdmin - ? 'Super Admin' - : userData?.appUserProfile?.adminFor.length > 0 - ? 'Admin' - : 'User'} -

    -
    -

    {formState.email}

    -

    - - Joined on {prettyDate(userData?.user?.createdAt)} -

    -
    -
    -
    - - {/* Actions */} -
    -
    +
    -
    -
    -
    - -

    - {`${t('pluginCreationAllowed')} (API not supported yet)`} -

    -
    + {tCommon('saveChanges')} + + + + )} + + + + + + +

    + {t('tagsAssigned')} +

    +
    + + {!tagsAssigned.length ? ( +
    + {t('noTagsAssigned')}
    -
    -
    -
    - + {'Unassign'} + +
    + {index + 1 !== tagsAssigned.length && ( +
    + )}
    -
    -
    - - -
    -
    -
    -
    -
    + ))} + + )} + + + + + + + +

    + {t('eventsAttended')} +

    -
    -
    -
    -
    + + + {!userData?.user.eventsAttended?.length ? ( +
    + {t('noeventsAttended')} +
    + ) : ( + userData.user.eventsAttended.map( + (event: InterfaceEvent, index: number) => ( + + + + ), + ) + )} +
    + + + + + {/* Unassign User Tag Modal */} + ); }; + export const prettyDate = (param: string): string => { const date = new Date(param); if (date?.toDateString() === 'Invalid Date') { @@ -567,4 +758,5 @@ export const getLanguageName = (code: string): string => { }); return language; }; + export default MemberDetail; diff --git a/src/screens/MemberDetail/MemberDetailMocks.ts b/src/screens/MemberDetail/MemberDetailMocks.ts new file mode 100644 index 0000000000..df72ee703c --- /dev/null +++ b/src/screens/MemberDetail/MemberDetailMocks.ts @@ -0,0 +1,536 @@ +import { UNASSIGN_USER_TAG } from 'GraphQl/Mutations/TagMutations'; +import { USER_DETAILS } from 'GraphQl/Queries/Queries'; +import { TAGS_QUERY_DATA_CHUNK_SIZE } from 'utils/organizationTagsUtils'; + +export const MOCKS1 = [ + { + request: { + query: USER_DETAILS, + variables: { + id: 'rishav-jha-mech', + first: TAGS_QUERY_DATA_CHUNK_SIZE, + }, + }, + result: { + data: { + user: { + __typename: 'UserData', + appUserProfile: { + _id: '1', + __typename: 'AppUserProfile', + adminFor: [ + { + __typename: 'Organization', + _id: '65e0df0906dd1228350cfd4a', + }, + { + __typename: 'Organization', + _id: '65e0e2abb92c9f3e29503d4e', + }, + ], + isSuperAdmin: false, + appLanguageCode: 'en', + createdEvents: [ + { + __typename: 'Event', + _id: '65e32a5b2a1f4288ca1f086a', + }, + ], + createdOrganizations: [ + { + __typename: 'Organization', + _id: '65e0df0906dd1228350cfd4a', + }, + { + __typename: 'Organization', + _id: '65e0e2abb92c9f3e29503d4e', + }, + ], + eventAdmin: [ + { + __typename: 'Event', + _id: '65e32a5b2a1f4288ca1f086a', + }, + ], + pluginCreationAllowed: true, + }, + user: { + _id: '1', + __typename: 'User', + createdAt: '2024-02-26T10:36:33.098Z', + email: 'adi790u@gmail.com', + firstName: 'Aditya', + image: null, + lastName: 'Agarwal', + gender: '', + birthDate: '2024-03-14', + educationGrade: '', + employmentStatus: '', + maritalStatus: '', + address: { + line1: '', + countryCode: '', + city: '', + state: '', + }, + phone: { + mobile: '', + }, + eventsAttended: [], + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '65e0df0906dd1228350cfd4a', + }, + { + __typename: 'Organization', + _id: '65e0e2abb92c9f3e29503d4e', + }, + ], + tagsAssignedWith: { + edges: [ + { + node: { + _id: '1', + name: 'userTag 1', + parentTag: null, + }, + cursor: '1', + }, + { + node: { + _id: '2', + name: 'userTag 2', + parentTag: null, + }, + cursor: '2', + }, + { + node: { + _id: '3', + name: 'userTag 3', + parentTag: null, + }, + cursor: '3', + }, + { + node: { + _id: '4', + name: 'userTag 4', + parentTag: null, + }, + cursor: '4', + }, + { + node: { + _id: '5', + name: 'userTag 5', + parentTag: null, + }, + cursor: '5', + }, + { + node: { + _id: '6', + name: 'userTag 6', + parentTag: null, + }, + cursor: '6', + }, + { + node: { + _id: '7', + name: 'userTag 7', + parentTag: null, + }, + cursor: '7', + }, + { + node: { + _id: '8', + name: 'userTag 8', + parentTag: null, + }, + cursor: '8', + }, + { + node: { + _id: '9', + name: 'userTag 9', + parentTag: null, + }, + cursor: '9', + }, + { + node: { + _id: '10', + name: 'userTag 10', + parentTag: null, + }, + cursor: '10', + }, + ], + pageInfo: { + startCursor: '1', + endCursor: '10', + hasNextPage: true, + hasPreviousPage: false, + }, + totalCount: 12, + }, + membershipRequests: [], + organizationsBlockedBy: [], + registeredEvents: [ + { + __typename: 'Event', + _id: '65e32a5b2a1f4288ca1f086a', + }, + ], + }, + }, + }, + }, + }, + { + request: { + query: USER_DETAILS, + variables: { + id: 'rishav-jha-mech', + first: TAGS_QUERY_DATA_CHUNK_SIZE, + after: '10', + }, + }, + result: { + data: { + user: { + __typename: 'UserData', + appUserProfile: { + _id: '1', + __typename: 'AppUserProfile', + adminFor: [ + { + __typename: 'Organization', + _id: '65e0df0906dd1228350cfd4a', + }, + { + __typename: 'Organization', + _id: '65e0e2abb92c9f3e29503d4e', + }, + ], + isSuperAdmin: false, + appLanguageCode: 'en', + createdEvents: [ + { + __typename: 'Event', + _id: '65e32a5b2a1f4288ca1f086a', + }, + ], + createdOrganizations: [ + { + __typename: 'Organization', + _id: '65e0df0906dd1228350cfd4a', + }, + { + __typename: 'Organization', + _id: '65e0e2abb92c9f3e29503d4e', + }, + ], + eventAdmin: [ + { + __typename: 'Event', + _id: '65e32a5b2a1f4288ca1f086a', + }, + ], + pluginCreationAllowed: true, + }, + user: { + _id: '1', + __typename: 'User', + createdAt: '2024-02-26T10:36:33.098Z', + email: 'adi790u@gmail.com', + firstName: 'Aditya', + image: null, + lastName: 'Agarwal', + gender: '', + birthDate: '2024-03-14', + educationGrade: '', + employmentStatus: '', + maritalStatus: '', + address: { + line1: '', + countryCode: '', + city: '', + state: '', + }, + phone: { + mobile: '', + }, + eventsAttended: [], + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '65e0df0906dd1228350cfd4a', + }, + { + __typename: 'Organization', + _id: '65e0e2abb92c9f3e29503d4e', + }, + ], + tagsAssignedWith: { + edges: [ + { + node: { + _id: '11', + name: 'userTag 11', + parentTag: null, + }, + cursor: '11', + }, + { + node: { + _id: '12', + name: 'subTag 1', + parentTag: { _id: '1' }, + }, + cursor: '12', + }, + ], + pageInfo: { + startCursor: '11', + endCursor: '12', + hasNextPage: false, + hasPreviousPage: true, + }, + totalCount: 12, + }, + membershipRequests: [], + organizationsBlockedBy: [], + registeredEvents: [ + { + __typename: 'Event', + _id: '65e32a5b2a1f4288ca1f086a', + }, + ], + }, + }, + }, + }, + }, + { + request: { + query: UNASSIGN_USER_TAG, + variables: { + tagId: '1', + userId: 'rishav-jha-mech', + }, + }, + result: { + data: { + unassignUserTag: { + _id: '1', + }, + }, + }, + }, +]; + +export const MOCKS2 = [ + { + request: { + query: USER_DETAILS, + variables: { + id: 'rishav-jha-mech', + first: TAGS_QUERY_DATA_CHUNK_SIZE, + }, + }, + result: { + data: { + user: { + __typename: 'UserData', + appUserProfile: { + _id: '1', + __typename: 'AppUserProfile', + adminFor: [], + isSuperAdmin: false, + appLanguageCode: 'en', + createdEvents: [ + { + __typename: 'Event', + _id: '65e32a5b2a1f4288ca1f086a', + }, + ], + createdOrganizations: [ + { + __typename: 'Organization', + _id: '65e0df0906dd1228350cfd4a', + }, + { + __typename: 'Organization', + _id: '65e0e2abb92c9f3e29503d4e', + }, + ], + eventAdmin: [ + { + __typename: 'Event', + _id: '65e32a5b2a1f4288ca1f086a', + }, + ], + pluginCreationAllowed: true, + }, + user: { + _id: '1', + __typename: 'User', + createdAt: '2024-02-26T10:36:33.098Z', + email: 'adi790u@gmail.com', + firstName: 'Aditya', + image: 'https://placeholder.com/200x200', + lastName: 'Agarwal', + gender: '', + birthDate: '2024-03-14', + educationGrade: '', + employmentStatus: '', + maritalStatus: '', + address: { + line1: '', + countryCode: '', + city: '', + state: '', + }, + phone: { + mobile: '', + }, + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '65e0df0906dd1228350cfd4a', + }, + { + __typename: 'Organization', + _id: '65e0e2abb92c9f3e29503d4e', + }, + ], + tagsAssignedWith: { + edges: [], + pageInfo: { + startCursor: null, + endCursor: null, + hasNextPage: false, + hasPreviousPage: false, + }, + totalCount: 0, + }, + eventsAttended: [{ _id: 'event1' }, { _id: 'event2' }], + membershipRequests: [], + organizationsBlockedBy: [], + registeredEvents: [ + { + __typename: 'Event', + _id: '65e32a5b2a1f4288ca1f086a', + }, + ], + }, + }, + }, + }, + }, +]; +export const MOCKS3 = [ + { + request: { + query: USER_DETAILS, + variables: { + id: 'rishav-jha-mech', + first: TAGS_QUERY_DATA_CHUNK_SIZE, + }, + }, + result: { + data: { + user: { + __typename: 'UserData', + appUserProfile: { + _id: '1', + __typename: 'AppUserProfile', + adminFor: [], + isSuperAdmin: true, + appLanguageCode: 'en', + createdEvents: [ + { + __typename: 'Event', + _id: '65e32a5b2a1f4288ca1f086a', + }, + ], + createdOrganizations: [ + { + __typename: 'Organization', + _id: '65e0df0906dd1228350cfd4a', + }, + { + __typename: 'Organization', + _id: '65e0e2abb92c9f3e29503d4e', + }, + ], + eventAdmin: [ + { + __typename: 'Event', + _id: '65e32a5b2a1f4288ca1f086a', + }, + ], + pluginCreationAllowed: true, + }, + user: { + _id: '1', + __typename: 'User', + createdAt: '2024-02-26T10:36:33.098Z', + email: 'adi790u@gmail.com', + firstName: 'Aditya', + image: 'https://placeholder.com/200x200', + lastName: 'Agarwal', + gender: '', + birthDate: '2024-03-14', + educationGrade: '', + employmentStatus: '', + maritalStatus: '', + address: { + line1: '', + countryCode: '', + city: '', + state: '', + }, + phone: { + mobile: '', + }, + tagsAssignedWith: { + edges: [], + pageInfo: { + startCursor: null, + endCursor: null, + hasNextPage: false, + hasPreviousPage: false, + }, + totalCount: 0, + }, + eventsAttended: [], + joinedOrganizations: [ + { + __typename: 'Organization', + _id: '65e0df0906dd1228350cfd4a', + }, + { + __typename: 'Organization', + _id: '65e0e2abb92c9f3e29503d4e', + }, + ], + membershipRequests: [], + organizationsBlockedBy: [], + registeredEvents: [ + { + __typename: 'Event', + _id: '65e32a5b2a1f4288ca1f086a', + }, + ], + }, + }, + }, + }, + }, +]; diff --git a/src/screens/OrganizationActionItems/ItemDeleteModal.test.tsx b/src/screens/OrganizationActionItems/ItemDeleteModal.test.tsx index 3d45e12a25..fffeebfd7f 100644 --- a/src/screens/OrganizationActionItems/ItemDeleteModal.test.tsx +++ b/src/screens/OrganizationActionItems/ItemDeleteModal.test.tsx @@ -38,11 +38,14 @@ const itemProps: InterfaceItemDeleteModalProps = { actionItemsRefetch: jest.fn(), actionItem: { _id: 'actionItemId1', - assignee: { + assignee: null, + assigneeGroup: null, + assigneeType: 'User', + assigneeUser: { _id: 'userId1', firstName: 'John', lastName: 'Doe', - image: null, + image: undefined, }, actionItemCategory: { _id: 'actionItemCategoryId1', @@ -55,12 +58,12 @@ const itemProps: InterfaceItemDeleteModalProps = { completionDate: new Date('2044-09-03'), isCompleted: true, event: null, - allotedHours: 24, + allottedHours: 24, assigner: { _id: 'userId2', firstName: 'Wilt', lastName: 'Shepherd', - image: null, + image: undefined, }, creator: { _id: 'userId2', diff --git a/src/screens/OrganizationActionItems/ItemModal.test.tsx b/src/screens/OrganizationActionItems/ItemModal.test.tsx index 6901e16291..a58496e6df 100644 --- a/src/screens/OrganizationActionItems/ItemModal.test.tsx +++ b/src/screens/OrganizationActionItems/ItemModal.test.tsx @@ -47,6 +47,7 @@ const itemProps: InterfaceItemModalProps[] = [ isOpen: true, hide: jest.fn(), orgId: 'orgId', + eventId: undefined, actionItemsRefetch: jest.fn(), editMode: false, actionItem: null, @@ -55,11 +56,24 @@ const itemProps: InterfaceItemModalProps[] = [ isOpen: true, hide: jest.fn(), orgId: 'orgId', + eventId: 'eventId', + actionItemsRefetch: jest.fn(), + editMode: false, + actionItem: null, + }, + { + isOpen: true, + hide: jest.fn(), + orgId: 'orgId', + eventId: undefined, actionItemsRefetch: jest.fn(), editMode: true, actionItem: { _id: 'actionItemId1', - assignee: { + assignee: null, + assigneeGroup: null, + assigneeType: 'User', + assigneeUser: { _id: 'userId1', firstName: 'Harve', lastName: 'Lance', @@ -76,12 +90,12 @@ const itemProps: InterfaceItemModalProps[] = [ completionDate: new Date('2044-09-03'), isCompleted: true, event: null, - allotedHours: 24, + allottedHours: 24, assigner: { _id: 'userId2', firstName: 'Wilt', lastName: 'Shepherd', - image: null, + image: undefined, }, creator: { _id: 'userId2', @@ -94,11 +108,15 @@ const itemProps: InterfaceItemModalProps[] = [ isOpen: true, hide: jest.fn(), orgId: 'orgId', + eventId: undefined, actionItemsRefetch: jest.fn(), editMode: true, actionItem: { _id: 'actionItemId2', - assignee: { + assignee: null, + assigneeGroup: null, + assigneeType: 'User', + assigneeUser: { _id: 'userId2', firstName: 'Wilt', lastName: 'Shepherd', @@ -115,7 +133,134 @@ const itemProps: InterfaceItemModalProps[] = [ completionDate: new Date('2044-10-03'), isCompleted: false, event: null, - allotedHours: null, + allottedHours: null, + assigner: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + image: 'wilt-image', + }, + creator: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + }, + { + isOpen: true, + hide: jest.fn(), + orgId: 'orgId', + eventId: 'eventId', + actionItemsRefetch: jest.fn(), + editMode: true, + actionItem: { + _id: 'actionItemId2', + assigneeType: 'EventVolunteer', + assignee: { + _id: 'volunteerId1', + hasAccepted: true, + hoursVolunteered: 0, + user: { + _id: 'userId1', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + assignments: [], + groups: [], + }, + assigneeGroup: null, + assigneeUser: null, + actionItemCategory: { + _id: 'categoryId2', + name: 'Category 2', + }, + preCompletionNotes: 'Notes 2', + postCompletionNotes: null, + assignmentDate: new Date('2024-08-27'), + dueDate: new Date('2044-09-30'), + completionDate: new Date('2044-10-03'), + isCompleted: false, + event: { + _id: 'eventId', + title: 'Event 1', + }, + allottedHours: null, + assigner: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + image: 'wilt-image', + }, + creator: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + }, + { + isOpen: true, + hide: jest.fn(), + orgId: 'orgId', + eventId: 'eventId', + actionItemsRefetch: jest.fn(), + editMode: true, + actionItem: { + _id: 'actionItemId2', + assigneeType: 'EventVolunteerGroup', + assigneeGroup: { + _id: 'groupId1', + name: 'group1', + description: 'desc', + volunteersRequired: 10, + createdAt: '2024-10-27T15:34:15.889Z', + creator: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + leader: { + _id: 'userId1', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + volunteers: [ + { + _id: 'volunteerId1', + user: { + _id: 'userId1', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + }, + ], + assignments: [], + event: { + _id: 'eventId', + }, + }, + assignee: null, + assigneeUser: null, + actionItemCategory: { + _id: 'categoryId2', + name: 'Category 2', + }, + preCompletionNotes: 'Notes 2', + postCompletionNotes: null, + assignmentDate: new Date('2024-08-27'), + dueDate: new Date('2044-09-30'), + completionDate: new Date('2044-10-03'), + isCompleted: false, + event: { + _id: 'eventId', + title: 'Event 1', + }, + allottedHours: null, assigner: { _id: 'userId2', firstName: 'Wilt', @@ -151,7 +296,7 @@ const renderItemModal = ( }; describe('Testing ItemModal', () => { - it('Create Action Item', async () => { + it('Create Action Item (for Member)', async () => { renderItemModal(link1, itemProps[0]); expect(screen.getAllByText(t.createActionItem)).toHaveLength(2); @@ -181,12 +326,12 @@ describe('Testing ItemModal', () => { }); // Select Allotted Hours (try all options) - const allotedHours = screen.getByLabelText(t.allotedHours); - const allotedHoursOptions = ['', '-1', '9']; + const allottedHours = screen.getByLabelText(t.allottedHours); + const allottedHoursOptions = ['', '-1', '9']; - allotedHoursOptions.forEach((option) => { - fireEvent.change(allotedHours, { target: { value: option } }); - expect(allotedHours).toHaveValue(parseInt(option) > 0 ? option : ''); + allottedHoursOptions.forEach((option) => { + fireEvent.change(allottedHours, { target: { value: option } }); + expect(allottedHours).toHaveValue(parseInt(option) > 0 ? option : ''); }); // Add Pre Completion Notes @@ -206,8 +351,132 @@ describe('Testing ItemModal', () => { }); }); - it('Update Action Item (completed)', async () => { + it('Create Action Item (for Volunteer)', async () => { + renderItemModal(link1, itemProps[1]); + expect(screen.getAllByText(t.createActionItem)).toHaveLength(2); + + // Select Category 1 + const categorySelect = await screen.findByTestId('categorySelect'); + expect(categorySelect).toBeInTheDocument(); + const inputField = within(categorySelect).getByRole('combobox'); + fireEvent.mouseDown(inputField); + + const categoryOption = await screen.findByText('Category 1'); + expect(categoryOption).toBeInTheDocument(); + fireEvent.click(categoryOption); + + // Select Volunteer Role + const groupRadio = await screen.findByText(t.groups); + const individualRadio = await screen.findByText(t.individuals); + expect(groupRadio).toBeInTheDocument(); + expect(individualRadio).toBeInTheDocument(); + fireEvent.click(individualRadio); + + // Select Individual Volunteer + const volunteerSelect = await screen.findByTestId('volunteerSelect'); + expect(volunteerSelect).toBeInTheDocument(); + const volunteerInputField = within(volunteerSelect).getByRole('combobox'); + fireEvent.mouseDown(volunteerInputField); + + const volunteerOption = await screen.findByText('Teresa Bradley'); + expect(volunteerOption).toBeInTheDocument(); + fireEvent.click(volunteerOption); + + // Select Due Date + fireEvent.change(screen.getByLabelText(t.dueDate), { + target: { value: '02/01/2044' }, + }); + + // Select Allotted Hours (try all options) + const allottedHours = screen.getByLabelText(t.allottedHours); + const allottedHoursOptions = ['', '-1', '9']; + + allottedHoursOptions.forEach((option) => { + fireEvent.change(allottedHours, { target: { value: option } }); + expect(allottedHours).toHaveValue(parseInt(option) > 0 ? option : ''); + }); + + // Add Pre Completion Notes + fireEvent.change(screen.getByLabelText(t.preCompletionNotes), { + target: { value: 'Notes' }, + }); + + // Click Submit + const submitButton = screen.getByTestId('submitBtn'); + expect(submitButton).toBeInTheDocument(); + fireEvent.click(submitButton); + + await waitFor(() => { + expect(itemProps[1].actionItemsRefetch).toHaveBeenCalled(); + expect(itemProps[1].hide).toHaveBeenCalled(); + expect(toast.success).toHaveBeenCalledWith(t.successfulCreation); + }); + }); + + it('Create Action Item (for Group)', async () => { renderItemModal(link1, itemProps[1]); + expect(screen.getAllByText(t.createActionItem)).toHaveLength(2); + + // Select Category 1 + const categorySelect = await screen.findByTestId('categorySelect'); + expect(categorySelect).toBeInTheDocument(); + const inputField = within(categorySelect).getByRole('combobox'); + fireEvent.mouseDown(inputField); + + const categoryOption = await screen.findByText('Category 1'); + expect(categoryOption).toBeInTheDocument(); + fireEvent.click(categoryOption); + + // Select Volunteer Role + const groupRadio = await screen.findByText(t.groups); + const individualRadio = await screen.findByText(t.individuals); + expect(groupRadio).toBeInTheDocument(); + expect(individualRadio).toBeInTheDocument(); + fireEvent.click(groupRadio); + + // Select Individual Volunteer + const groupSelect = await screen.findByTestId('volunteerGroupSelect'); + expect(groupSelect).toBeInTheDocument(); + const groupInputField = within(groupSelect).getByRole('combobox'); + fireEvent.mouseDown(groupInputField); + + const groupOption = await screen.findByText('group1'); + expect(groupOption).toBeInTheDocument(); + fireEvent.click(groupOption); + + // Select Due Date + fireEvent.change(screen.getByLabelText(t.dueDate), { + target: { value: '02/01/2044' }, + }); + + // Select Allotted Hours (try all options) + const allottedHours = screen.getByLabelText(t.allottedHours); + const allottedHoursOptions = ['', '-1', '9']; + + allottedHoursOptions.forEach((option) => { + fireEvent.change(allottedHours, { target: { value: option } }); + expect(allottedHours).toHaveValue(parseInt(option) > 0 ? option : ''); + }); + + // Add Pre Completion Notes + fireEvent.change(screen.getByLabelText(t.preCompletionNotes), { + target: { value: 'Notes' }, + }); + + // Click Submit + const submitButton = screen.getByTestId('submitBtn'); + expect(submitButton).toBeInTheDocument(); + fireEvent.click(submitButton); + + await waitFor(() => { + expect(itemProps[1].actionItemsRefetch).toHaveBeenCalled(); + expect(itemProps[1].hide).toHaveBeenCalled(); + expect(toast.success).toHaveBeenCalledWith(t.successfulCreation); + }); + }); + + it('Update Action Item (completed)', async () => { + renderItemModal(link1, itemProps[2]); expect(screen.getAllByText(t.updateActionItem)).toHaveLength(2); // Update Category @@ -221,12 +490,12 @@ describe('Testing ItemModal', () => { fireEvent.click(categoryOption); // Update Allotted Hours (try all options) - const allotedHours = screen.getByLabelText(t.allotedHours); - const allotedHoursOptions = ['', '-1', '19']; + const allottedHours = screen.getByLabelText(t.allottedHours); + const allottedHoursOptions = ['', '-1', '19']; - allotedHoursOptions.forEach((option) => { - fireEvent.change(allotedHours, { target: { value: option } }); - expect(allotedHours).toHaveValue(parseInt(option) > 0 ? option : ''); + allottedHoursOptions.forEach((option) => { + fireEvent.change(allottedHours, { target: { value: option } }); + expect(allottedHours).toHaveValue(parseInt(option) > 0 ? option : ''); }); // Update Post Completion Notes @@ -240,14 +509,170 @@ describe('Testing ItemModal', () => { fireEvent.click(submitButton); await waitFor(() => { - expect(itemProps[1].actionItemsRefetch).toHaveBeenCalled(); - expect(itemProps[1].hide).toHaveBeenCalled(); + expect(itemProps[2].actionItemsRefetch).toHaveBeenCalled(); + expect(itemProps[2].hide).toHaveBeenCalled(); + expect(toast.success).toHaveBeenCalledWith(t.successfulUpdation); + }); + }); + + it('Update Action Item (Volunteer)', async () => { + renderItemModal(link1, itemProps[4]); + expect(screen.getAllByText(t.updateActionItem)).toHaveLength(2); + + // Update Category + const categorySelect = await screen.findByTestId('categorySelect'); + expect(categorySelect).toBeInTheDocument(); + const inputField = within(categorySelect).getByRole('combobox'); + fireEvent.mouseDown(inputField); + + const categoryOption = await screen.findByText('Category 1'); + expect(categoryOption).toBeInTheDocument(); + fireEvent.click(categoryOption); + + // Select Volunteer Role + const groupRadio = await screen.findByText(t.groups); + const individualRadio = await screen.findByText(t.individuals); + expect(groupRadio).toBeInTheDocument(); + expect(individualRadio).toBeInTheDocument(); + fireEvent.click(individualRadio); + + // Select Individual Volunteer + const volunteerSelect = await screen.findByTestId('volunteerSelect'); + expect(volunteerSelect).toBeInTheDocument(); + const volunteerInputField = within(volunteerSelect).getByRole('combobox'); + fireEvent.mouseDown(volunteerInputField); + + const volunteerOption = await screen.findByText('Bruce Graza'); + expect(volunteerOption).toBeInTheDocument(); + fireEvent.click(volunteerOption); + + // Update Allotted Hours (try all options) + const allottedHours = screen.getByLabelText(t.allottedHours); + const allottedHoursOptions = ['', '-1', '19']; + + allottedHoursOptions.forEach((option) => { + fireEvent.change(allottedHours, { target: { value: option } }); + expect(allottedHours).toHaveValue(parseInt(option) > 0 ? option : ''); + }); + + // Click Submit + const submitButton = screen.getByTestId('submitBtn'); + expect(submitButton).toBeInTheDocument(); + fireEvent.click(submitButton); + + await waitFor(() => { + expect(itemProps[4].actionItemsRefetch).toHaveBeenCalled(); + expect(itemProps[4].hide).toHaveBeenCalled(); + expect(toast.success).toHaveBeenCalledWith(t.successfulUpdation); + }); + }); + + it('Update Action Item (Group)', async () => { + renderItemModal(link1, itemProps[5]); + expect(screen.getAllByText(t.updateActionItem)).toHaveLength(2); + + // Update Category + const categorySelect = await screen.findByTestId('categorySelect'); + expect(categorySelect).toBeInTheDocument(); + const inputField = within(categorySelect).getByRole('combobox'); + fireEvent.mouseDown(inputField); + + const categoryOption = await screen.findByText('Category 1'); + expect(categoryOption).toBeInTheDocument(); + fireEvent.click(categoryOption); + + // Select Volunteer Role + const groupRadio = await screen.findByText(t.groups); + const individualRadio = await screen.findByText(t.individuals); + expect(groupRadio).toBeInTheDocument(); + expect(individualRadio).toBeInTheDocument(); + fireEvent.click(groupRadio); + + // Select Individual Volunteer + const groupSelect = await screen.findByTestId('volunteerGroupSelect'); + expect(groupSelect).toBeInTheDocument(); + const groupInputField = within(groupSelect).getByRole('combobox'); + fireEvent.mouseDown(groupInputField); + + const groupOption = await screen.findByText('group2'); + expect(groupOption).toBeInTheDocument(); + fireEvent.click(groupOption); + + // Update Allotted Hours (try all options) + const allottedHours = screen.getByLabelText(t.allottedHours); + const allottedHoursOptions = ['', '-1', '19']; + + allottedHoursOptions.forEach((option) => { + fireEvent.change(allottedHours, { target: { value: option } }); + expect(allottedHours).toHaveValue(parseInt(option) > 0 ? option : ''); + }); + + // Click Submit + const submitButton = screen.getByTestId('submitBtn'); + expect(submitButton).toBeInTheDocument(); + fireEvent.click(submitButton); + + await waitFor(() => { + expect(itemProps[5].actionItemsRefetch).toHaveBeenCalled(); + expect(itemProps[5].hide).toHaveBeenCalled(); + expect(toast.success).toHaveBeenCalledWith(t.successfulUpdation); + }); + }); + + it('Update Action Item (Volunteer -> Group)', async () => { + renderItemModal(link1, itemProps[4]); + expect(screen.getAllByText(t.updateActionItem)).toHaveLength(2); + + // Update Category + const categorySelect = await screen.findByTestId('categorySelect'); + expect(categorySelect).toBeInTheDocument(); + const inputField = within(categorySelect).getByRole('combobox'); + fireEvent.mouseDown(inputField); + + const categoryOption = await screen.findByText('Category 1'); + expect(categoryOption).toBeInTheDocument(); + fireEvent.click(categoryOption); + + // Select Volunteer Role + const groupRadio = await screen.findByText(t.groups); + const individualRadio = await screen.findByText(t.individuals); + expect(groupRadio).toBeInTheDocument(); + expect(individualRadio).toBeInTheDocument(); + fireEvent.click(groupRadio); + + // Select Individual Volunteer + const groupSelect = await screen.findByTestId('volunteerGroupSelect'); + expect(groupSelect).toBeInTheDocument(); + const groupInputField = within(groupSelect).getByRole('combobox'); + fireEvent.mouseDown(groupInputField); + + const groupOption = await screen.findByText('group2'); + expect(groupOption).toBeInTheDocument(); + fireEvent.click(groupOption); + + // Update Allotted Hours (try all options) + const allottedHours = screen.getByLabelText(t.allottedHours); + const allottedHoursOptions = ['', '-1', '19']; + + allottedHoursOptions.forEach((option) => { + fireEvent.change(allottedHours, { target: { value: option } }); + expect(allottedHours).toHaveValue(parseInt(option) > 0 ? option : ''); + }); + + // Click Submit + const submitButton = screen.getByTestId('submitBtn'); + expect(submitButton).toBeInTheDocument(); + fireEvent.click(submitButton); + + await waitFor(() => { + expect(itemProps[4].actionItemsRefetch).toHaveBeenCalled(); + expect(itemProps[4].hide).toHaveBeenCalled(); expect(toast.success).toHaveBeenCalledWith(t.successfulUpdation); }); }); it('Update Action Item (not completed)', async () => { - renderItemModal(link1, itemProps[2]); + renderItemModal(link1, itemProps[3]); expect(screen.getAllByText(t.updateActionItem)).toHaveLength(2); // Update Category @@ -271,12 +696,12 @@ describe('Testing ItemModal', () => { fireEvent.click(memberOption); // Update Allotted Hours (try all options) - const allotedHours = screen.getByLabelText(t.allotedHours); - const allotedHoursOptions = ['', '-1', '19']; + const allottedHours = screen.getByLabelText(t.allottedHours); + const allottedHoursOptions = ['', '-1', '19']; - allotedHoursOptions.forEach((option) => { - fireEvent.change(allotedHours, { target: { value: option } }); - expect(allotedHours).toHaveValue(parseInt(option) > 0 ? option : ''); + allottedHoursOptions.forEach((option) => { + fireEvent.change(allottedHours, { target: { value: option } }); + expect(allottedHours).toHaveValue(parseInt(option) > 0 ? option : ''); }); // Update Due Date @@ -295,8 +720,8 @@ describe('Testing ItemModal', () => { fireEvent.click(submitButton); await waitFor(() => { - expect(itemProps[2].actionItemsRefetch).toHaveBeenCalled(); - expect(itemProps[2].hide).toHaveBeenCalled(); + expect(itemProps[3].actionItemsRefetch).toHaveBeenCalled(); + expect(itemProps[3].hide).toHaveBeenCalled(); expect(toast.success).toHaveBeenCalledWith(t.successfulUpdation); }); }); @@ -304,27 +729,27 @@ describe('Testing ItemModal', () => { it('Try adding negative Allotted Hours', async () => { renderItemModal(link1, itemProps[0]); expect(screen.getAllByText(t.createActionItem)).toHaveLength(2); - const allotedHours = screen.getByLabelText(t.allotedHours); - fireEvent.change(allotedHours, { target: { value: '-1' } }); + const allottedHours = screen.getByLabelText(t.allottedHours); + fireEvent.change(allottedHours, { target: { value: '-1' } }); await waitFor(() => { - expect(allotedHours).toHaveValue(''); + expect(allottedHours).toHaveValue(''); }); - fireEvent.change(allotedHours, { target: { value: '' } }); + fireEvent.change(allottedHours, { target: { value: '' } }); await waitFor(() => { - expect(allotedHours).toHaveValue(''); + expect(allottedHours).toHaveValue(''); }); - fireEvent.change(allotedHours, { target: { value: '0' } }); + fireEvent.change(allottedHours, { target: { value: '0' } }); await waitFor(() => { - expect(allotedHours).toHaveValue('0'); + expect(allottedHours).toHaveValue('0'); }); - fireEvent.change(allotedHours, { target: { value: '19' } }); + fireEvent.change(allottedHours, { target: { value: '19' } }); await waitFor(() => { - expect(allotedHours).toHaveValue('19'); + expect(allottedHours).toHaveValue('19'); }); }); @@ -341,7 +766,7 @@ describe('Testing ItemModal', () => { }); it('No Fields Updated while Updating', async () => { - renderItemModal(link2, itemProps[1]); + renderItemModal(link2, itemProps[2]); // Click Submit const submitButton = screen.getByTestId('submitBtn'); expect(submitButton).toBeInTheDocument(); @@ -353,7 +778,7 @@ describe('Testing ItemModal', () => { }); it('should fail to Update Action Item', async () => { - renderItemModal(link2, itemProps[1]); + renderItemModal(link2, itemProps[2]); expect(screen.getAllByText(t.updateActionItem)).toHaveLength(2); // Update Post Completion Notes diff --git a/src/screens/OrganizationActionItems/ItemModal.tsx b/src/screens/OrganizationActionItems/ItemModal.tsx index d7a38ee0df..b7555af121 100644 --- a/src/screens/OrganizationActionItems/ItemModal.tsx +++ b/src/screens/OrganizationActionItems/ItemModal.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useMemo, useState } from 'react'; import { Modal, Form, Button } from 'react-bootstrap'; import type { ChangeEvent, FC } from 'react'; -import styles from './OrganizationActionItems.module.css'; +import styles from '../../style/app.module.css'; import { DatePicker } from '@mui/x-date-pickers'; import dayjs from 'dayjs'; import type { Dayjs } from 'dayjs'; @@ -10,8 +10,10 @@ import type { InterfaceActionItemCategoryInfo, InterfaceActionItemCategoryList, InterfaceActionItemInfo, + InterfaceEventVolunteerInfo, InterfaceMemberInfo, InterfaceMembersList, + InterfaceVolunteerGroupInfo, } from 'utils/interfaces'; import { useTranslation } from 'react-i18next'; import { toast } from 'react-toastify'; @@ -21,20 +23,26 @@ import { UPDATE_ACTION_ITEM_MUTATION, } from 'GraphQl/Mutations/ActionItemMutations'; import { ACTION_ITEM_CATEGORY_LIST } from 'GraphQl/Queries/ActionItemCategoryQueries'; -import { MEMBERS_LIST } from 'GraphQl/Queries/Queries'; import { Autocomplete, FormControl, TextField } from '@mui/material'; +import { + EVENT_VOLUNTEER_GROUP_LIST, + EVENT_VOLUNTEER_LIST, +} from 'GraphQl/Queries/EventVolunteerQueries'; +import { HiUser, HiUserGroup } from 'react-icons/hi2'; +import { MEMBERS_LIST } from 'GraphQl/Queries/Queries'; /** * Interface for the form state used in the `ItemModal` component. */ interface InterfaceFormStateType { dueDate: Date; + assigneeType: 'EventVolunteer' | 'EventVolunteerGroup' | 'User'; actionItemCategoryId: string; assigneeId: string; eventId?: string; preCompletionNotes: string; postCompletionNotes: string | null; - allotedHours: number | null; + allottedHours: number | null; isCompleted: boolean; } @@ -45,6 +53,7 @@ export interface InterfaceItemModalProps { isOpen: boolean; hide: () => void; orgId: string; + eventId: string | undefined; actionItemsRefetch: () => void; actionItem: InterfaceActionItemInfo | null; editMode: boolean; @@ -62,10 +71,15 @@ const initializeFormState = ( ): InterfaceFormStateType => ({ dueDate: actionItem?.dueDate || new Date(), actionItemCategoryId: actionItem?.actionItemCategory?._id || '', - assigneeId: actionItem?.assignee._id || '', + assigneeId: + actionItem?.assignee?._id || + actionItem?.assigneeGroup?._id || + actionItem?.assigneeUser?._id || + '', + assigneeType: actionItem?.assigneeType || 'User', preCompletionNotes: actionItem?.preCompletionNotes || '', postCompletionNotes: actionItem?.postCompletionNotes || null, - allotedHours: actionItem?.allotedHours || null, + allottedHours: actionItem?.allottedHours || null, isCompleted: actionItem?.isCompleted || false, }); @@ -79,6 +93,7 @@ const ItemModal: FC = ({ isOpen, hide, orgId, + eventId, actionItem, editMode, actionItemsRefetch, @@ -89,7 +104,15 @@ const ItemModal: FC = ({ const [actionItemCategory, setActionItemCategory] = useState(null); - const [assignee, setAssignee] = useState(null); + const [assignee, setAssignee] = useState( + null, + ); + const [assigneeGroup, setAssigneeGroup] = + useState(null); + + const [assigneeUser, setAssigneeUser] = useState( + null, + ); const [formState, setFormState] = useState( initializeFormState(actionItem), @@ -97,11 +120,12 @@ const ItemModal: FC = ({ const { dueDate, + assigneeType, actionItemCategoryId, assigneeId, preCompletionNotes, postCompletionNotes, - allotedHours, + allottedHours, isCompleted, } = formState; @@ -119,6 +143,41 @@ const ItemModal: FC = ({ }, }); + /** + * Query to fetch event volunteers for the event. + */ + const { + data: volunteersData, + }: { + data?: { + getEventVolunteers: InterfaceEventVolunteerInfo[]; + }; + } = useQuery(EVENT_VOLUNTEER_LIST, { + variables: { + where: { + eventId: eventId, + hasAccepted: true, + }, + }, + }); + + /** + * Query to fetch the list of volunteer groups for the event. + */ + const { + data: groupsData, + }: { + data?: { + getEventVolunteerGroups: InterfaceVolunteerGroupInfo[]; + }; + } = useQuery(EVENT_VOLUNTEER_GROUP_LIST, { + variables: { + where: { + eventId: eventId, + }, + }, + }); + /** * Query to fetch members of the organization. */ @@ -130,16 +189,26 @@ const ItemModal: FC = ({ variables: { id: orgId }, }); - const actionItemCategories = useMemo( - () => actionItemCategoriesData?.actionItemCategoriesByOrganization || [], - [actionItemCategoriesData], - ); - const members = useMemo( () => membersData?.organizations[0].members || [], [membersData], ); + const volunteers = useMemo( + () => volunteersData?.getEventVolunteers || [], + [volunteersData], + ); + + const groups = useMemo( + () => groupsData?.getEventVolunteerGroups || [], + [groupsData], + ); + + const actionItemCategories = useMemo( + () => actionItemCategoriesData?.actionItemCategoriesByOrganization || [], + [actionItemCategoriesData], + ); + /** * Mutation to create & update a new action item. */ @@ -171,13 +240,16 @@ const ItemModal: FC = ({ ): Promise => { e.preventDefault(); try { + const dDate = dayjs(dueDate).format('YYYY-MM-DD'); await createActionItem({ variables: { - assigneeId: assignee?._id, + dDate: dDate, + assigneeId: assigneeId, + assigneeType: assigneeType, actionItemCategoryId: actionItemCategory?._id, preCompletionNotes: preCompletionNotes, - allotedHours: allotedHours, - dueDate: dayjs(dueDate).format('YYYY-MM-DD'), + allottedHours: allottedHours, + ...(eventId && { eventId }), }, }); @@ -211,10 +283,32 @@ const ItemModal: FC = ({ if (actionItemCategoryId !== actionItem?.actionItemCategory?._id) { updatedFields.actionItemCategoryId = actionItemCategoryId; } - if (assigneeId !== actionItem?.assignee._id) { + + if ( + assigneeId !== actionItem?.assignee?._id && + assigneeType === 'EventVolunteer' + ) { updatedFields.assigneeId = assigneeId; } + if ( + assigneeId !== actionItem?.assigneeGroup?._id && + assigneeType === 'EventVolunteerGroup' + ) { + updatedFields.assigneeId = assigneeId; + } + + if ( + assigneeId !== actionItem?.assigneeUser?._id && + assigneeType === 'User' + ) { + updatedFields.assigneeId = assigneeId; + } + + if (assigneeType !== actionItem?.assigneeType) { + updatedFields.assigneeType = assigneeType; + } + if (preCompletionNotes !== actionItem?.preCompletionNotes) { updatedFields.preCompletionNotes = preCompletionNotes; } @@ -223,8 +317,8 @@ const ItemModal: FC = ({ updatedFields.postCompletionNotes = postCompletionNotes; } - if (allotedHours !== actionItem?.allotedHours) { - updatedFields.allotedHours = allotedHours; + if (allottedHours !== actionItem?.allottedHours) { + updatedFields.allottedHours = allottedHours; } if (dueDate !== actionItem?.dueDate) { @@ -240,6 +334,7 @@ const ItemModal: FC = ({ variables: { actionItemId: actionItem?._id, assigneeId: assigneeId, + assigneeType: assigneeType, ...updatedFields, }, }); @@ -261,9 +356,19 @@ const ItemModal: FC = ({ ) || null, ); setAssignee( - members.find((member) => member._id === actionItem?.assignee._id) || null, + volunteers.find( + (volunteer) => volunteer._id === actionItem?.assignee?._id, + ) || null, + ); + setAssigneeGroup( + groups.find((group) => group._id === actionItem?.assigneeGroup?._id) || + null, ); - }, [actionItem, actionItemCategories, members]); + setAssigneeUser( + members.find((member) => member._id === actionItem?.assigneeUser?._id) || + null, + ); + }, [actionItem, actionItemCategories, volunteers, groups, members]); return ( @@ -274,7 +379,7 @@ const ItemModal: FC = ({
    )} @@ -172,10 +192,10 @@ const ItemViewModal: FC = ({ isOpen, hide, item }) => { /> diff --git a/src/screens/OrganizationActionItems/OrganizationActionItem.mocks.ts b/src/screens/OrganizationActionItems/OrganizationActionItem.mocks.ts index 0a324d39ac..d7d661fc9d 100644 --- a/src/screens/OrganizationActionItems/OrganizationActionItem.mocks.ts +++ b/src/screens/OrganizationActionItems/OrganizationActionItem.mocks.ts @@ -4,147 +4,19 @@ import { DELETE_ACTION_ITEM_MUTATION, UPDATE_ACTION_ITEM_MUTATION, } from 'GraphQl/Mutations/ActionItemMutations'; -import { - ACTION_ITEM_CATEGORY_LIST, - ACTION_ITEM_LIST, - MEMBERS_LIST, -} from 'GraphQl/Queries/Queries'; -import { act } from 'react-dom/test-utils'; - -const baseActionItem = { - assigner: { - _id: 'userId2', - firstName: 'Wilt', - lastName: 'Shepherd', - image: null, - }, - creator: { - _id: 'userId2', - firstName: 'Wilt', - lastName: 'Shepherd', - __typename: 'User', - }, -}; - -const actionItem1 = { - _id: 'actionItemId1', - assignee: { - _id: 'userId1', - firstName: 'John', - lastName: 'Doe', - image: null, - }, - actionItemCategory: { - _id: 'actionItemCategoryId1', - name: 'Category 1', - }, - preCompletionNotes: 'Notes 1', - postCompletionNotes: 'Cmp Notes 1', - assignmentDate: '2024-08-27', - dueDate: '2044-08-30', - completionDate: '2044-09-03', - isCompleted: true, - event: null, - allotedHours: 24, - ...baseActionItem, -}; - -const actionItem2 = { - _id: 'actionItemId2', - assignee: { - _id: 'userId1', - firstName: 'Jane', - lastName: 'Doe', - image: 'image-url', - }, - actionItemCategory: { - _id: 'actionItemCategoryId2', - name: 'Category 2', - }, - preCompletionNotes: 'Notes 2', - postCompletionNotes: null, - assignmentDate: '2024-08-27', - dueDate: '2044-09-30', - completionDate: '2044-10-03', - isCompleted: false, - event: null, - allotedHours: null, - ...baseActionItem, -}; - -const memberListQuery = { - request: { - query: MEMBERS_LIST, - variables: { id: 'orgId' }, - }, - result: { - data: { - organizations: [ - { - _id: 'orgId', - members: [ - { - _id: 'userId1', - firstName: 'Harve', - lastName: 'Lance', - email: 'harve@example.com', - image: '', - organizationsBlockedBy: [], - createdAt: '2024-02-14', - }, - { - _id: 'userId2', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'wilt@example.com', - image: '', - organizationsBlockedBy: [], - createdAt: '2024-02-14', - }, - ], - }, - ], - }, - }, -}; +import { ACTION_ITEM_LIST } from 'GraphQl/Queries/Queries'; -const actionItemCategoryListQuery = { - request: { - query: ACTION_ITEM_CATEGORY_LIST, - variables: { - organizationId: 'orgId', - where: { is_disabled: false }, - }, - }, - result: { - data: { - actionItemCategoriesByOrganization: [ - { - _id: 'categoryId1', - name: 'Category 1', - isDisabled: false, - createdAt: '2024-08-26', - creator: { - _id: 'creatorId1', - firstName: 'Wilt', - lastName: 'Shepherd', - }, - }, - { - _id: 'categoryId2', - name: 'Category 2', - isDisabled: true, - createdAt: '2024-08-25', - creator: { - _id: 'creatorId2', - firstName: 'John', - lastName: 'Doe', - }, - }, - ], - }, - }, -}; +import { + actionItemCategoryListQuery, + groupListQuery, + itemWithGroup, + itemWithUser, + itemWithUserImage, + itemWithVolunteer, + itemWithVolunteerImage, + memberListQuery, + volunteerListQuery, +} from './testObject.mocks'; export const MOCKS = [ { @@ -160,7 +32,13 @@ export const MOCKS = [ }, result: { data: { - actionItemsByOrganization: [actionItem1, actionItem2], + actionItemsByOrganization: [ + itemWithVolunteer, + itemWithUser, + itemWithGroup, + itemWithVolunteerImage, + itemWithUserImage, + ], }, }, }, @@ -177,7 +55,7 @@ export const MOCKS = [ }, result: { data: { - actionItemsByOrganization: [actionItem1, actionItem2], + actionItemsByOrganization: [itemWithVolunteer, itemWithUser], }, }, }, @@ -194,7 +72,7 @@ export const MOCKS = [ }, result: { data: { - actionItemsByOrganization: [actionItem1, actionItem2], + actionItemsByOrganization: [itemWithVolunteer, itemWithUser], }, }, }, @@ -211,7 +89,7 @@ export const MOCKS = [ }, result: { data: { - actionItemsByOrganization: [actionItem2, actionItem1], + actionItemsByOrganization: [itemWithUser, itemWithVolunteer], }, }, }, @@ -229,7 +107,7 @@ export const MOCKS = [ }, result: { data: { - actionItemsByOrganization: [actionItem1], + actionItemsByOrganization: [itemWithVolunteer], }, }, }, @@ -247,7 +125,7 @@ export const MOCKS = [ }, result: { data: { - actionItemsByOrganization: [actionItem2], + actionItemsByOrganization: [itemWithUser], }, }, }, @@ -264,7 +142,7 @@ export const MOCKS = [ }, result: { data: { - actionItemsByOrganization: [actionItem1], + actionItemsByOrganization: [itemWithVolunteer], }, }, }, @@ -281,7 +159,7 @@ export const MOCKS = [ }, result: { data: { - actionItemsByOrganization: [actionItem1], + actionItemsByOrganization: [itemWithVolunteer], }, }, }, @@ -306,6 +184,7 @@ export const MOCKS = [ variables: { actionItemId: 'actionItemId1', assigneeId: 'userId1', + assigneeType: 'User', postCompletionNotes: '', isCompleted: false, }, @@ -324,9 +203,29 @@ export const MOCKS = [ variables: { actionItemId: 'actionItemId1', assigneeId: 'userId1', + assigneeType: 'User', actionItemCategoryId: 'categoryId2', postCompletionNotes: 'Cmp Notes 2', - allotedHours: 19, + allottedHours: 19, + }, + }, + result: { + data: { + updateActionItem: { + _id: 'actionItemId1', + }, + }, + }, + }, + { + request: { + query: UPDATE_ACTION_ITEM_MUTATION, + variables: { + actionItemId: 'actionItemId1', + assigneeId: 'volunteerGroupId1', + assigneeType: 'EventVolunteerGroup', + postCompletionNotes: 'Cmp Notes 1', + isCompleted: true, }, }, result: { @@ -343,9 +242,10 @@ export const MOCKS = [ variables: { actionItemId: 'actionItemId2', assigneeId: 'userId1', + assigneeType: 'User', actionItemCategoryId: 'categoryId1', preCompletionNotes: 'Notes 3', - allotedHours: 19, + allottedHours: 19, dueDate: '2044-01-02', }, }, @@ -375,15 +275,116 @@ export const MOCKS = [ }, }, }, + { + request: { + query: UPDATE_ACTION_ITEM_MUTATION, + variables: { + actionItemId: 'actionItemId2', + assigneeId: 'volunteerId2', + assigneeType: 'EventVolunteer', + actionItemCategoryId: 'categoryId1', + allottedHours: 19, + }, + }, + result: { + data: { + updateActionItem: { + _id: 'actionItemId1', + }, + }, + }, + }, + { + request: { + query: UPDATE_ACTION_ITEM_MUTATION, + variables: { + actionItemId: 'actionItemId2', + assigneeId: 'groupId2', + assigneeType: 'EventVolunteerGroup', + actionItemCategoryId: 'categoryId1', + allottedHours: 19, + }, + }, + result: { + data: { + updateActionItem: { + _id: 'actionItemId1', + }, + }, + }, + }, { request: { query: CREATE_ACTION_ITEM_MUTATION, variables: { assigneeId: 'userId1', + assigneeType: 'User', actionItemCategoryId: 'categoryId1', preCompletionNotes: 'Notes', - allotedHours: 9, - dueDate: '2044-01-02', + allottedHours: 9, + dDate: '2044-01-02', + }, + }, + result: { + data: { + createActionItem: { + _id: 'actionItemId1', + }, + }, + }, + }, + { + request: { + query: CREATE_ACTION_ITEM_MUTATION, + variables: { + assigneeId: 'userId1', + assigneeType: 'User', + actionItemCategoryId: 'categoryId1', + preCompletionNotes: 'Notes', + allottedHours: 9, + dDate: '2044-01-02', + }, + }, + result: { + data: { + createActionItem: { + _id: 'actionItemId1', + }, + }, + }, + }, + { + request: { + query: CREATE_ACTION_ITEM_MUTATION, + variables: { + assigneeId: 'volunteerId1', + assigneeType: 'EventVolunteer', + actionItemCategoryId: 'categoryId1', + preCompletionNotes: 'Notes', + allottedHours: 9, + dDate: '2044-01-02', + eventId: 'eventId', + }, + }, + result: { + data: { + createActionItem: { + _id: 'actionItemId1', + }, + }, + }, + }, + { + request: { + query: CREATE_ACTION_ITEM_MUTATION, + variables: { + assigneeId: 'groupId1', + assigneeType: 'EventVolunteerGroup', + actionItemCategoryId: 'categoryId1', + preCompletionNotes: 'Notes', + allottedHours: 9, + dDate: '2044-01-02', + eventId: 'eventId', }, }, result: { @@ -396,6 +397,8 @@ export const MOCKS = [ }, memberListQuery, actionItemCategoryListQuery, + ...volunteerListQuery, + ...groupListQuery, ]; export const MOCKS_ERROR = [ @@ -426,7 +429,8 @@ export const MOCKS_ERROR = [ query: UPDATE_ACTION_ITEM_MUTATION, variables: { actionItemId: 'actionItemId1', - assigneeId: 'userId1', + assigneeId: 'volunteerId1', + assigneeType: 'EventVolunteer', postCompletionNotes: '', isCompleted: false, }, @@ -437,9 +441,11 @@ export const MOCKS_ERROR = [ request: { query: CREATE_ACTION_ITEM_MUTATION, variables: { + assigneeId: '', + assigneeType: 'User', preCompletionNotes: '', - allotedHours: null, - dueDate: dayjs().format('YYYY-MM-DD'), + allottedHours: null, + dDate: dayjs().format('YYYY-MM-DD'), }, }, error: new Error('Mock Graphql Error'), @@ -450,6 +456,7 @@ export const MOCKS_ERROR = [ variables: { actionItemId: 'actionItemId1', assigneeId: 'userId1', + assigneeType: 'User', postCompletionNotes: 'Cmp Notes 2', }, }, @@ -457,6 +464,8 @@ export const MOCKS_ERROR = [ }, memberListQuery, actionItemCategoryListQuery, + ...volunteerListQuery, + ...groupListQuery, ]; export const MOCKS_EMPTY = [ @@ -479,4 +488,6 @@ export const MOCKS_EMPTY = [ }, memberListQuery, actionItemCategoryListQuery, + ...volunteerListQuery, + ...groupListQuery, ]; diff --git a/src/screens/OrganizationActionItems/OrganizationActionItems.module.css b/src/screens/OrganizationActionItems/OrganizationActionItems.module.css index 48720ac902..ac86e19f3f 100644 --- a/src/screens/OrganizationActionItems/OrganizationActionItems.module.css +++ b/src/screens/OrganizationActionItems/OrganizationActionItems.module.css @@ -1,4 +1,4 @@ -.actionItemsContainer { +actionItemsContainer { height: 90vh; } @@ -231,3 +231,61 @@ hr { width: 28px; height: 26px; } + +/* Toggle Btn */ +.toggleGroup { + width: 50%; + min-width: 20rem; + margin: 0.5rem 0rem; +} + +.toggleBtn { + padding: 0rem; + height: 2rem; + display: flex; + justify-content: center; + align-items: center; +} + +.toggleBtn:hover { + color: #31bb6b !important; +} + +input[type='radio']:checked + label { + background-color: #31bb6a50 !important; +} + +input[type='radio']:checked + label:hover { + color: black !important; +} /* Toggle Btn */ +.toggleGroup { + width: 50%; + min-width: 20rem; + margin: 0.5rem 0rem; +} + +.toggleBtn { + padding: 0rem; + height: 2rem; + display: flex; + justify-content: center; + align-items: center; +} + +.toggleBtn:hover { + color: #31bb6b !important; +} + +input[type='radio']:checked + label { + background-color: #31bb6a50 !important; +} + +input[type='radio']:checked + label:hover { + color: black !important; +} + +.rankings { + aspect-ratio: 1; + border-radius: 50%; + width: 50px; +} diff --git a/src/screens/OrganizationActionItems/OrganizationActionItems.test.tsx b/src/screens/OrganizationActionItems/OrganizationActionItems.test.tsx index c163ff9546..44e11baa35 100644 --- a/src/screens/OrganizationActionItems/OrganizationActionItems.test.tsx +++ b/src/screens/OrganizationActionItems/OrganizationActionItems.test.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { act } from 'react'; import { MockedProvider } from '@apollo/react-testing'; import { LocalizationProvider } from '@mui/x-date-pickers'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; @@ -47,6 +47,14 @@ const t = { ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), }; +const debounceWait = async (ms = 300): Promise => { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +}; + const renderOrganizationActionItems = (link: ApolloLink): RenderResult => { return render( @@ -114,8 +122,8 @@ describe('Testing Organization Action Items Screen', () => { renderOrganizationActionItems(link1); await waitFor(() => { expect(screen.getByTestId('searchBy')).toBeInTheDocument(); - expect(screen.getByText('John Doe')).toBeInTheDocument(); - expect(screen.getByText('Jane Doe')).toBeInTheDocument(); + expect(screen.getAllByText('John Doe')).toHaveLength(2); + expect(screen.getAllByText('Jane Doe')).toHaveLength(2); }); }); @@ -171,8 +179,8 @@ describe('Testing Organization Action Items Screen', () => { fireEvent.click(screen.getByTestId('statusAll')); await waitFor(() => { - expect(screen.getByText('Category 1')).toBeInTheDocument(); - expect(screen.getByText('Category 2')).toBeInTheDocument(); + expect(screen.getAllByText('Category 1')).toHaveLength(3); + expect(screen.getAllByText('Category 2')).toHaveLength(2); }); // Filter by Pending @@ -301,7 +309,8 @@ describe('Testing Organization Action Items Screen', () => { expect(searchInput).toBeInTheDocument(); userEvent.type(searchInput, 'John'); - userEvent.click(screen.getByTestId('searchBtn')); + await debounceWait(); + await waitFor(() => { expect(screen.getByText('Category 1')).toBeInTheDocument(); expect(screen.queryByText('Category 2')).toBeNull(); @@ -325,35 +334,8 @@ describe('Testing Organization Action Items Screen', () => { expect(searchInput).toBeInTheDocument(); userEvent.type(searchInput, 'Category 1'); - userEvent.click(screen.getByTestId('searchBtn')); - await waitFor(() => { - expect(screen.getByText('Category 1')).toBeInTheDocument(); - expect(screen.queryByText('Category 2')).toBeNull(); - }); - }); + await debounceWait(); - it('Search action items by name and clear the input by backspace', async () => { - renderOrganizationActionItems(link1); - - const searchInput = await screen.findByTestId('searchBy'); - expect(searchInput).toBeInTheDocument(); - - // Clear the search input by backspace - userEvent.type(searchInput, 'A{backspace}'); - await waitFor(() => { - expect(screen.getByText('Category 1')).toBeInTheDocument(); - expect(screen.getByText('Category 2')).toBeInTheDocument(); - }); - }); - - it('Search action items by name on press of ENTER', async () => { - renderOrganizationActionItems(link1); - - const searchInput = await screen.findByTestId('searchBy'); - expect(searchInput).toBeInTheDocument(); - - userEvent.type(searchInput, 'John'); - userEvent.type(searchInput, '{enter}'); await waitFor(() => { expect(screen.getByText('Category 1')).toBeInTheDocument(); expect(screen.queryByText('Category 2')).toBeNull(); diff --git a/src/screens/OrganizationActionItems/OrganizationActionItems.tsx b/src/screens/OrganizationActionItems/OrganizationActionItems.tsx index ba48f212e0..f1a8044d01 100644 --- a/src/screens/OrganizationActionItems/OrganizationActionItems.tsx +++ b/src/screens/OrganizationActionItems/OrganizationActionItems.tsx @@ -19,14 +19,14 @@ import type { InterfaceActionItemInfo, InterfaceActionItemList, } from 'utils/interfaces'; -import styles from './OrganizationActionItems.module.css'; +import styles from '../../style/app.module.css'; import Loader from 'components/Loader/Loader'; import { DataGrid, type GridCellParams, type GridColDef, } from '@mui/x-data-grid'; -import { Chip, Stack } from '@mui/material'; +import { Chip, debounce, Stack } from '@mui/material'; import ItemViewModal from './ItemViewModal'; import ItemModal from './ItemModal'; import ItemDeleteModal from './ItemDeleteModal'; @@ -46,27 +46,6 @@ enum ModalState { STATUS = 'status', } -const dataGridStyle = { - '&.MuiDataGrid-root .MuiDataGrid-cell:focus-within': { - outline: 'none !important', - }, - '&.MuiDataGrid-root .MuiDataGrid-columnHeader:focus-within': { - outline: 'none', - }, - '& .MuiDataGrid-row:hover': { - backgroundColor: 'transparent', - }, - '& .MuiDataGrid-row.Mui-hovered': { - backgroundColor: 'transparent', - }, - '& .MuiDataGrid-root': { - borderRadius: '0.5rem', - }, - '& .MuiDataGrid-main': { - borderRadius: '0.5rem', - }, -}; - /** * Component for managing and displaying action items within an organization. * @@ -157,6 +136,11 @@ function organizationActionItems(): JSX.Element { [actionItemsData], ); + const debouncedSearch = useMemo( + () => debounce((value: string) => setSearchTerm(value), 300), + [], + ); + if (actionItemsLoading) { return ; } @@ -167,8 +151,6 @@ function organizationActionItems(): JSX.Element {
    {tErrors('errorLoading', { entity: 'Action Items' })} -
    - {`${actionItemsError.message}`}
    ); @@ -185,32 +167,58 @@ function organizationActionItems(): JSX.Element { sortable: false, headerClassName: `${styles.tableHeader}`, renderCell: (params: GridCellParams) => { - const { _id, firstName, lastName, image } = params.row.assignee; + const { _id, firstName, lastName, image } = + params.row.assigneeUser || params.row.assignee?.user || {}; + return ( -
    - {image ? ( - Assignee + <> + {params.row.assigneeType !== 'EventVolunteerGroup' ? ( + <> +
    + {image ? ( + Assignee + ) : ( +
    + +
    + )} + {firstName + ' ' + lastName} +
    + ) : ( -
    - -
    + <> +
    +
    + +
    + {params.row.assigneeGroup?.name as string} +
    + )} - {params.row.assignee.firstName + ' ' + params.row.assignee.lastName} -
    + ); }, }, @@ -255,8 +263,8 @@ function organizationActionItems(): JSX.Element { }, }, { - field: 'allotedHours', - headerName: 'Alloted Hours', + field: 'allottedHours', + headerName: 'Allotted Hours', align: 'center', headerAlign: 'center', sortable: false, @@ -264,7 +272,9 @@ function organizationActionItems(): JSX.Element { flex: 1, renderCell: (params: GridCellParams) => { return ( -
    {params.row.allotedHours ?? '-'}
    +
    + {params.row.allottedHours ?? '-'} +
    ); }, }, @@ -297,10 +307,10 @@ function organizationActionItems(): JSX.Element { return ( <>
    -
    -
    +
    +
    handleModalClick(null, ModalState.SAME)} - style={{ marginTop: '11px' }} + className={styles.createButton} data-testid="createActionItemBtn" > @@ -497,7 +502,29 @@ function organizationActionItems(): JSX.Element { ), }} - sx={dataGridStyle} + sx={{ + borderRadius: '20px', + backgroundColor: 'EAEBEF)', + '& .MuiDataGrid-row': { + backgroundColor: '#eff1f7', + '&:focus-within': { + // outline: '2px solid #000', + outlineOffset: '-2px', + }, + }, + '& .MuiDataGrid-row:hover': { + backgroundColor: '#EAEBEF', + boxShadow: '0 0 0 1px rgba(0, 0, 0, 0.1)', + }, + '& .MuiDataGrid-row.Mui-hovered': { + backgroundColor: '#EAEBEF', + boxShadow: '0 0 0 1px rgba(0, 0, 0, 0.1)', + }, + '& .MuiDataGrid-cell:focus': { + // outline: '2px solid #000', + // outlineOffset: '-2px', + }, + }} getRowClassName={() => `${styles.rowBackground}`} autoHeight rowHeight={65} @@ -514,32 +541,35 @@ function organizationActionItems(): JSX.Element { isOpen={modalState[ModalState.SAME]} hide={() => closeModal(ModalState.SAME)} orgId={orgId} + eventId={eventId} actionItemsRefetch={actionItemsRefetch} actionItem={actionItem} editMode={modalMode === 'edit'} /> - closeModal(ModalState.DELETE)} - actionItem={actionItem} - actionItemsRefetch={actionItemsRefetch} - /> - - closeModal(ModalState.STATUS)} - actionItemsRefetch={actionItemsRefetch} - /> - {/* View Modal */} {actionItem && ( - closeModal(ModalState.VIEW)} - item={actionItem} - /> + <> + closeModal(ModalState.VIEW)} + item={actionItem} + /> + + closeModal(ModalState.STATUS)} + actionItemsRefetch={actionItemsRefetch} + /> + + closeModal(ModalState.DELETE)} + actionItem={actionItem} + actionItemsRefetch={actionItemsRefetch} + /> + )}
    ); diff --git a/src/screens/OrganizationActionItems/testObject.mocks.ts b/src/screens/OrganizationActionItems/testObject.mocks.ts new file mode 100644 index 0000000000..d43f574e8c --- /dev/null +++ b/src/screens/OrganizationActionItems/testObject.mocks.ts @@ -0,0 +1,402 @@ +import { + EVENT_VOLUNTEER_GROUP_LIST, + EVENT_VOLUNTEER_LIST, +} from 'GraphQl/Queries/EventVolunteerQueries'; +import { + ACTION_ITEM_CATEGORY_LIST, + MEMBERS_LIST, +} from 'GraphQl/Queries/Queries'; +import type { InterfaceActionItemInfo } from 'utils/interfaces'; + +export const actionItemCategory1 = { + _id: 'actionItemCategoryId1', + name: 'Category 1', +}; + +export const actionItemCategory2 = { + _id: 'actionItemCategoryId2', + name: 'Category 2', +}; + +export const baseActionItem = { + assigner: { + _id: 'userId', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + creator: { + _id: 'userId', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + __typename: 'User', + }, +}; + +export const itemWithVolunteer: InterfaceActionItemInfo = { + _id: 'actionItemId1', + assigneeType: 'EventVolunteer', + assignee: { + _id: 'volunteerId1', + hasAccepted: true, + hoursVolunteered: 12, + assignments: [], + groups: [], + user: { + _id: 'userId1', + firstName: 'John', + lastName: 'Doe', + image: null, + }, + }, + assigneeUser: null, + assigneeGroup: null, + preCompletionNotes: 'Notes 1', + postCompletionNotes: 'Cmp Notes 1', + assignmentDate: new Date('2024-08-27'), + dueDate: new Date('2044-08-30'), + completionDate: new Date('2044-09-03'), + isCompleted: true, + event: null, + allottedHours: 24, + actionItemCategory: actionItemCategory1, + ...baseActionItem, +}; + +export const itemWithVolunteerImage: InterfaceActionItemInfo = { + _id: 'actionItemId1b', + assigneeType: 'EventVolunteer', + assignee: { + _id: 'volunteerId1', + hasAccepted: true, + hoursVolunteered: 12, + assignments: [], + groups: [], + user: { + _id: 'userId1', + firstName: 'John', + lastName: 'Doe', + image: 'user-image', + }, + }, + assigneeUser: null, + assigneeGroup: null, + preCompletionNotes: 'Notes 1', + postCompletionNotes: 'Cmp Notes 1', + assignmentDate: new Date('2024-08-27'), + dueDate: new Date('2044-08-30'), + completionDate: new Date('2044-09-03'), + isCompleted: true, + event: null, + allottedHours: 24, + actionItemCategory: actionItemCategory1, + ...baseActionItem, +}; + +export const itemWithUser: InterfaceActionItemInfo = { + _id: 'actionItemId2', + assigneeType: 'User', + assigneeUser: { + _id: 'userId1', + firstName: 'Jane', + lastName: 'Doe', + image: null, + }, + assignee: null, + assigneeGroup: null, + preCompletionNotes: 'Notes 2', + postCompletionNotes: null, + assignmentDate: new Date('2024-08-27'), + dueDate: new Date('2044-09-30'), + completionDate: new Date('2044-10-03'), + isCompleted: false, + event: null, + allottedHours: null, + actionItemCategory: actionItemCategory2, + ...baseActionItem, +}; + +export const itemWithUserImage: InterfaceActionItemInfo = { + _id: 'actionItemId2b', + assigneeType: 'User', + assigneeUser: { + _id: 'userId1', + firstName: 'Jane', + lastName: 'Doe', + image: 'user-image', + }, + assignee: null, + assigneeGroup: null, + preCompletionNotes: 'Notes 2', + postCompletionNotes: null, + assignmentDate: new Date('2024-08-27'), + dueDate: new Date('2044-09-30'), + completionDate: new Date('2044-10-03'), + isCompleted: false, + event: null, + allottedHours: null, + actionItemCategory: actionItemCategory2, + ...baseActionItem, +}; + +export const itemWithGroup: InterfaceActionItemInfo = { + _id: 'actionItemId3', + assigneeType: 'EventVolunteerGroup', + assigneeUser: null, + assignee: null, + assigneeGroup: { + _id: 'volunteerGroupId1', + name: 'Group 1', + description: 'Group 1 Description', + volunteersRequired: 10, + event: { + _id: 'eventId1', + }, + assignments: [], + volunteers: [], + createdAt: '2024-08-27', + creator: { + _id: 'userId1', + firstName: 'John', + lastName: 'Doe', + image: null, + }, + leader: { + _id: 'userId1', + firstName: 'John', + lastName: 'Doe', + image: null, + }, + }, + preCompletionNotes: 'Notes 1', + postCompletionNotes: 'Cmp Notes 1', + assignmentDate: new Date('2024-08-27'), + dueDate: new Date('2044-08-30'), + completionDate: new Date('2044-09-03'), + isCompleted: true, + event: null, + allottedHours: 24, + actionItemCategory: actionItemCategory1, + ...baseActionItem, +}; + +export const memberListQuery = { + request: { + query: MEMBERS_LIST, + variables: { id: 'orgId' }, + }, + result: { + data: { + organizations: [ + { + _id: 'orgId', + members: [ + { + _id: 'userId1', + firstName: 'Harve', + lastName: 'Lance', + email: 'harve@example.com', + image: '', + organizationsBlockedBy: [], + createdAt: '2024-02-14', + }, + { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + email: 'wilt@example.com', + image: '', + organizationsBlockedBy: [], + createdAt: '2024-02-14', + }, + ], + }, + ], + }, + }, +}; + +export const volunteerListQuery = [ + { + request: { + query: EVENT_VOLUNTEER_LIST, + variables: { where: { eventId: 'eventId', hasAccepted: true } }, + }, + result: { + data: { + getEventVolunteers: [ + { + _id: 'volunteerId1', + hasAccepted: true, + hoursVolunteered: 0, + user: { + _id: 'userId1', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + assignments: [], + groups: [ + { + _id: 'groupId1', + name: 'group1', + volunteers: [ + { + _id: 'volunteerId1', + }, + ], + }, + ], + }, + { + _id: 'volunteerId2', + hasAccepted: true, + hoursVolunteered: 0, + user: { + _id: 'userId3', + firstName: 'Bruce', + lastName: 'Graza', + image: null, + }, + assignments: [], + groups: [], + }, + ], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_LIST, + variables: { where: { hasAccepted: true } }, + }, + result: { + data: { + getEventVolunteers: [], + }, + }, + }, +]; + +export const groupListQuery = [ + { + request: { + query: EVENT_VOLUNTEER_GROUP_LIST, + variables: { where: { eventId: 'eventId' } }, + }, + result: { + data: { + getEventVolunteerGroups: [ + { + _id: 'groupId1', + name: 'group1', + description: 'desc', + volunteersRequired: 10, + createdAt: '2024-10-27T15:34:15.889Z', + creator: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + leader: { + _id: 'userId1', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + volunteers: [ + { + _id: 'volunteerId1', + user: { + _id: 'userId1', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + }, + ], + assignments: [], + event: { + _id: 'eventId', + }, + }, + { + _id: 'groupId2', + name: 'group2', + description: 'desc', + volunteersRequired: 10, + createdAt: '2024-10-27T15:34:15.889Z', + creator: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + leader: { + _id: 'userId1', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + volunteers: [], + assignments: [], + event: { + _id: 'eventId', + }, + }, + ], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_GROUP_LIST, + variables: { where: { eventId: undefined } }, + }, + result: { + data: { + getEventVolunteerGroups: [], + }, + }, + }, +]; + +export const actionItemCategoryListQuery = { + request: { + query: ACTION_ITEM_CATEGORY_LIST, + variables: { + organizationId: 'orgId', + where: { is_disabled: false }, + }, + }, + result: { + data: { + actionItemCategoriesByOrganization: [ + { + _id: 'categoryId1', + name: 'Category 1', + isDisabled: false, + createdAt: '2024-08-26', + creator: { + _id: 'creatorId1', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + { + _id: 'categoryId2', + name: 'Category 2', + isDisabled: true, + createdAt: '2024-08-25', + creator: { + _id: 'creatorId2', + firstName: 'John', + lastName: 'Doe', + }, + }, + ], + }, + }, +}; diff --git a/src/screens/OrganizationDashboard/OrganizationDashboard.module.css b/src/screens/OrganizationDashboard/OrganizationDashboard.module.css index f9423de686..3ffe274196 100644 --- a/src/screens/OrganizationDashboard/OrganizationDashboard.module.css +++ b/src/screens/OrganizationDashboard/OrganizationDashboard.module.css @@ -27,3 +27,9 @@ justify-content: center; align-items: center; } + +.rankings { + aspect-ratio: 1; + border-radius: 50%; + width: 35px; +} diff --git a/src/screens/OrganizationDashboard/OrganizationDashboard.test.tsx b/src/screens/OrganizationDashboard/OrganizationDashboard.test.tsx index dde6b3120f..88db2aa737 100644 --- a/src/screens/OrganizationDashboard/OrganizationDashboard.test.tsx +++ b/src/screens/OrganizationDashboard/OrganizationDashboard.test.tsx @@ -1,202 +1,277 @@ +import React from 'react'; import { MockedProvider } from '@apollo/react-testing'; -import { fireEvent, render, screen } from '@testing-library/react'; -import 'jest-location-mock'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import type { RenderResult } from '@testing-library/react'; +import { render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import { I18nextProvider } from 'react-i18next'; import { Provider } from 'react-redux'; -import { BrowserRouter } from 'react-router-dom'; - -import userEvent from '@testing-library/user-event'; -import { toast } from 'react-toastify'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; import { store } from 'state/store'; import { StaticMockLink } from 'utils/StaticMockLink'; -import i18nForTest from 'utils/i18nForTest'; -import useLocalStorage from 'utils/useLocalstorage'; +import i18n from 'utils/i18nForTest'; import OrganizationDashboard from './OrganizationDashboard'; -import { EMPTY_MOCKS, ERROR_MOCKS, MOCKS } from './OrganizationDashboardMocks'; -import React, { act } from 'react'; -const { setItem } = useLocalStorage(); -import type { InterfaceQueryOrganizationEventListItem } from 'utils/interfaces'; - -async function wait(ms = 100): Promise { - await act(() => { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); - }); -} -const link1 = new StaticMockLink(MOCKS, true); -const link2 = new StaticMockLink(EMPTY_MOCKS, true); -const link3 = new StaticMockLink(ERROR_MOCKS, true); +import type { ApolloLink } from '@apollo/client'; +import { MOCKS, EMPTY_MOCKS, ERROR_MOCKS } from './OrganizationDashboardMocks'; +import { toast } from 'react-toastify'; jest.mock('react-toastify', () => ({ toast: { success: jest.fn(), - warn: jest.fn(), error: jest.fn(), }, })); -const mockNavgate = jest.fn(); -let mockId: string | undefined = undefined; -jest.mock('react-router-dom', () => ({ - ...jest.requireActual('react-router-dom'), - useNavigate: () => mockNavgate, - useParams: () => ({ orgId: mockId }), -})); -beforeEach(() => { - setItem('FirstName', 'John'); - setItem('LastName', 'Doe'); - setItem( - 'UserImage', - 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(ERROR_MOCKS); +const link3 = new StaticMockLink(EMPTY_MOCKS); +const t = { + ...JSON.parse( + JSON.stringify(i18n.getDataByLanguage('en')?.translation.dashboard ?? {}), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const renderOrganizationDashboard = (link: ApolloLink): RenderResult => { + return render( + + + + + + + } + /> +
    } + /> +
    } + /> +
    } + /> +
    } + /> +
    } + /> +
    } + /> +
    } + /> +
    } + /> + + + + + + , ); -}); +}; -afterEach(() => { - jest.clearAllMocks(); - localStorage.clear(); -}); +describe('Testing Organization Dashboard Screen', () => { + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId' }), + })); + }); -describe('Organisation Dashboard Page', () => { - test('Should render props and text elements test for the screen', async () => { - await act(async () => { - render( - - - - - - - - - , - ); + afterAll(() => { + jest.clearAllMocks(); + }); + + it('should redirect to fallback URL if URL params are undefined', async () => { + render( + + + + + + } /> +
  • } + /> + + + + + , + ); + await waitFor(() => { + expect(screen.getByTestId('paramsError')).toBeInTheDocument(); }); + }); + + it('should render Organization Dashboard screen', async () => { + renderOrganizationDashboard(link1); - await wait(); - expect(screen.getByText('Members')).toBeInTheDocument(); - expect(screen.getByText('Admins')).toBeInTheDocument(); - expect(screen.getAllByText('Posts')).toHaveLength(1); - expect(screen.getAllByText('Events')).toHaveLength(1); - expect(screen.getByText('Blocked Users')).toBeInTheDocument(); - expect(screen.getByText('Requests')).toBeInTheDocument(); - expect(screen.getByText('Upcoming Events')).toBeInTheDocument(); - expect(screen.getByText('Latest Posts')).toBeInTheDocument(); - expect(screen.getByText('Membership requests')).toBeInTheDocument(); - - // Checking if posts are rendered + // Dashboard cards + const membersBtn = await screen.findByText(t.members); + expect(membersBtn).toBeInTheDocument(); + expect(screen.getByText(t.admins)).toBeInTheDocument(); + expect(screen.getByText(t.posts)).toBeInTheDocument(); + expect(screen.getByText(t.events)).toBeInTheDocument(); + expect(screen.getByText(t.blockedUsers)).toBeInTheDocument(); + + // Upcoming events + expect(screen.getByText(t.upcomingEvents)).toBeInTheDocument(); + expect(screen.getByText('Event 1')).toBeInTheDocument(); + + // Latest posts + expect(screen.getByText(t.latestPosts)).toBeInTheDocument(); expect(screen.getByText('postone')).toBeInTheDocument(); - // Checking if membership requests are rendered + // Membership requests + expect(screen.getByText(t.membershipRequests)).toBeInTheDocument(); expect(screen.getByText('Jane Doe')).toBeInTheDocument(); - const peopleBtn = screen.getByText('Members'); - const adminBtn = screen.getByText('Admins'); - const postBtn = screen.getAllByText('Posts'); - const eventBtn = screen.getAllByText('Events'); - const blockUserBtn = screen.getByText('Blocked Users'); - const requestBtn = screen.getByText('Requests'); - userEvent.click(peopleBtn); - userEvent.click(adminBtn); - userEvent.click(postBtn[0]); - userEvent.click(eventBtn[0]); - userEvent.click(postBtn[0]); - userEvent.click(eventBtn[0]); - userEvent.click(blockUserBtn); - userEvent.click(requestBtn); - }); - - test('Testing buttons and checking empty events, posts and membership requests', async () => { - await act(async () => { - render( - - - - - - - - - , - ); - }); + // Volunteer rankings + expect(screen.getByText(t.volunteerRankings)).toBeInTheDocument(); + expect(screen.getByText('Teresa Bradley')).toBeInTheDocument(); + }); - await wait(); - const viewEventsBtn = screen.getByTestId('viewAllEvents'); - const viewPostsBtn = screen.getByTestId('viewAllPosts'); - const viewMSBtn = screen.getByTestId('viewAllMembershipRequests'); - - userEvent.click(viewEventsBtn); - userEvent.click(viewPostsBtn); - fireEvent.click(viewMSBtn); - expect(toast.success).toBeCalledWith('Coming soon!'); - - expect( - screen.getByText(/No membership requests present/i), - ).toBeInTheDocument(); - expect(screen.getByText(/No upcoming events/i)).toBeInTheDocument(); - expect(screen.getByText(/No Posts Present/i)).toBeInTheDocument(); - }); - - test('Testing error scenario', async () => { - await act(async () => { - render( - - - - - - - - - , - ); - }); + it('Click People Card', async () => { + renderOrganizationDashboard(link1); + const membersBtn = await screen.findByText(t.members); + expect(membersBtn).toBeInTheDocument(); - await wait(); - expect(mockNavgate).toHaveBeenCalledWith('/orglist'); - }); - test('upcomingEvents cardItem component should render when length>0', async () => { - mockId = '123'; - await act(async () => { - render( - - - - - - - - - , - ); - }); - screen.getByTestId('cardItem'); - }); - - test('event data should get updated using useState function', async () => { - mockId = '123'; - const mockSetState = jest.spyOn(React, 'useState'); - jest.doMock('react', () => ({ - ...jest.requireActual('react'), - useState: (initial: InterfaceQueryOrganizationEventListItem[]) => [ - initial, - mockSetState, - ], - })); - await act(async () => { - render( - - - - - - - - - , - ); + userEvent.click(membersBtn); + await waitFor(() => { + expect(screen.getByTestId('orgpeople')).toBeInTheDocument(); }); - expect(mockSetState).toHaveBeenCalled(); + }); + + it('Click Admin Card', async () => { + renderOrganizationDashboard(link1); + const adminsBtn = await screen.findByText(t.admins); + expect(adminsBtn).toBeInTheDocument(); + }); +}); + +it('Click Post Card', async () => { + renderOrganizationDashboard(link1); + const postsBtn = await screen.findByText(t.posts); + expect(postsBtn).toBeInTheDocument(); + + userEvent.click(postsBtn); + await waitFor(() => { + expect(screen.getByTestId('orgpost')).toBeInTheDocument(); + }); +}); + +it('Click Events Card', async () => { + renderOrganizationDashboard(link1); + const eventsBtn = await screen.findByText(t.events); + expect(eventsBtn).toBeInTheDocument(); + + userEvent.click(eventsBtn); + await waitFor(() => { + expect(screen.getByTestId('orgevents')).toBeInTheDocument(); + }); +}); + +it('Click Blocked Users Card', async () => { + renderOrganizationDashboard(link1); + const blockedUsersBtn = await screen.findByText(t.blockedUsers); + expect(blockedUsersBtn).toBeInTheDocument(); + + userEvent.click(blockedUsersBtn); + await waitFor(() => { + expect(screen.getByTestId('blockuser')).toBeInTheDocument(); + }); +}); + +it('Click Requests Card', async () => { + renderOrganizationDashboard(link1); + const requestsBtn = await screen.findByText(t.requests); + expect(requestsBtn).toBeInTheDocument(); + + userEvent.click(requestsBtn); + await waitFor(() => { + expect(screen.getByTestId('requests')).toBeInTheDocument(); + }); +}); + +it('Click View All Events', async () => { + renderOrganizationDashboard(link1); + const viewAllBtn = await screen.findAllByText(t.viewAll); + expect(viewAllBtn[0]).toBeInTheDocument(); + + userEvent.click(viewAllBtn[0]); + await waitFor(() => { + expect(screen.getByTestId('orgevents')).toBeInTheDocument(); + }); +}); + +it('Click View All Posts', async () => { + renderOrganizationDashboard(link1); + const viewAllBtn = await screen.findAllByText(t.viewAll); + expect(viewAllBtn[1]).toBeInTheDocument(); + + userEvent.click(viewAllBtn[1]); + await waitFor(() => { + expect(screen.getByTestId('orgpost')).toBeInTheDocument(); + }); +}); + +it('Click View All Requests', async () => { + renderOrganizationDashboard(link1); + const viewAllBtn = await screen.findAllByText(t.viewAll); + expect(viewAllBtn[2]).toBeInTheDocument(); + + userEvent.click(viewAllBtn[2]); + await waitFor(() => { + expect(toast.success).toHaveBeenCalled(); + }); +}); + +it('Click View All Leaderboard', async () => { + renderOrganizationDashboard(link1); + const viewAllBtn = await screen.findAllByText(t.viewAll); + expect(viewAllBtn[3]).toBeInTheDocument(); + + userEvent.click(viewAllBtn[3]); + await waitFor(() => { + expect(screen.getByTestId('leaderboard')).toBeInTheDocument(); + }); +}); + +it('should render Organization Dashboard screen with empty data', async () => { + renderOrganizationDashboard(link3); + + await waitFor(() => { + expect(screen.getByText(t.noUpcomingEvents)).toBeInTheDocument(); + expect(screen.getByText(t.noPostsPresent)).toBeInTheDocument(); + expect(screen.getByText(t.noMembershipRequests)).toBeInTheDocument(); + expect(screen.getByText(t.noVolunteers)).toBeInTheDocument(); + }); +}); + +it('should redirectt to / if error occurs', async () => { + renderOrganizationDashboard(link2); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + expect(screen.getByTestId('paramsError')).toBeInTheDocument(); }); }); diff --git a/src/screens/OrganizationDashboard/OrganizationDashboard.tsx b/src/screens/OrganizationDashboard/OrganizationDashboard.tsx index 6927e4f874..ebea874d2e 100644 --- a/src/screens/OrganizationDashboard/OrganizationDashboard.tsx +++ b/src/screens/OrganizationDashboard/OrganizationDashboard.tsx @@ -1,5 +1,5 @@ import { useQuery } from '@apollo/client'; -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useMemo, useState } from 'react'; import { Button, Card } from 'react-bootstrap'; import Col from 'react-bootstrap/Col'; import Row from 'react-bootstrap/Row'; @@ -20,14 +20,19 @@ import CardItem from 'components/OrganizationDashCards/CardItem'; import CardItemLoading from 'components/OrganizationDashCards/CardItemLoading'; import DashBoardCard from 'components/OrganizationDashCards/DashboardCard'; import DashboardCardLoading from 'components/OrganizationDashCards/DashboardCardLoading'; -import { useNavigate, useParams } from 'react-router-dom'; +import { Navigate, useNavigate, useParams } from 'react-router-dom'; +import gold from 'assets/images/gold.png'; +import silver from 'assets/images/silver.png'; +import bronze from 'assets/images/bronze.png'; import { toast } from 'react-toastify'; import type { InterfaceQueryOrganizationEventListItem, InterfaceQueryOrganizationPostListItem, InterfaceQueryOrganizationsListObject, + InterfaceVolunteerRank, } from 'utils/interfaces'; import styles from './OrganizationDashboard.module.css'; +import { VOLUNTEER_RANKING } from 'GraphQl/Queries/EventVolunteerQueries'; /** * Component for displaying the organization dashboard. @@ -39,12 +44,19 @@ import styles from './OrganizationDashboard.module.css'; function organizationDashboard(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'dashboard' }); const { t: tCommon } = useTranslation('common'); + const { t: tErrors } = useTranslation('errors'); document.title = t('title'); - const { orgId: currentUrl } = useParams(); - const peopleLink = `/orgpeople/${currentUrl}`; - const postsLink = `/orgpost/${currentUrl}`; - const eventsLink = `/orgevents/${currentUrl}`; - const blockUserLink = `/blockuser/${currentUrl}`; + const { orgId } = useParams(); + + if (!orgId) { + return ; + } + + const leaderboardLink = `/leaderboard/${orgId}`; + const peopleLink = `/orgpeople/${orgId}`; + const postsLink = `/orgpost/${orgId}`; + const eventsLink = `/orgevents/${orgId}`; + const blockUserLink = `/blockuser/${orgId}`; const requestLink = '/requests'; const navigate = useNavigate(); @@ -66,9 +78,38 @@ function organizationDashboard(): JSX.Element { loading: boolean; error?: ApolloError; } = useQuery(ORGANIZATIONS_LIST, { - variables: { id: currentUrl }, + variables: { id: orgId }, + }); + + /** + * Query to fetch vvolunteer rankings. + */ + const { + data: rankingsData, + loading: rankingsLoading, + error: errorRankings, + }: { + data?: { + getVolunteerRanks: InterfaceVolunteerRank[]; + }; + loading: boolean; + error?: ApolloError; + } = useQuery(VOLUNTEER_RANKING, { + variables: { + orgId, + where: { + orderBy: 'hours_DESC', + timeFrame: 'allTime', + limit: 3, + }, + }, }); + const rankings = useMemo( + () => rankingsData?.getVolunteerRanks || [], + [rankingsData], + ); + /** * Query to fetch posts for the organization. */ @@ -83,7 +124,7 @@ function organizationDashboard(): JSX.Element { loading: boolean; error?: ApolloError; } = useQuery(ORGANIZATION_POST_LIST, { - variables: { id: currentUrl, first: 10 }, + variables: { id: orgId, first: 10 }, }); /** @@ -95,7 +136,7 @@ function organizationDashboard(): JSX.Element { error: errorEvent, } = useQuery(ORGANIZATION_EVENT_CONNECTION_LIST, { variables: { - organization_id: currentUrl, + organization_id: orgId, }, }); @@ -122,11 +163,11 @@ function organizationDashboard(): JSX.Element { * UseEffect to handle errors and navigate if necessary. */ useEffect(() => { - if (errorOrg || errorPost || errorEvent) { - console.log('error', errorPost?.message); - navigate('/orglist'); + if (errorOrg || errorPost || errorEvent || errorRankings) { + toast.error(tErrors('errorLoading', { entity: '' })); + navigate('/'); } - }, [errorOrg, errorPost, errorEvent]); + }, [errorOrg, errorPost, errorEvent, errorRankings]); return ( <> @@ -136,7 +177,12 @@ function organizationDashboard(): JSX.Element { {[...Array(6)].map((_, index) => { return ( - + ); @@ -164,9 +210,12 @@ function organizationDashboard(): JSX.Element { sm={4} role="button" className="mb-4" - onClick={(): void => { - navigate(peopleLink); - }} + onClick={ + /*istanbul ignore next*/ + (): void => { + navigate(peopleLink); + } + } > {loadingEvent ? ( [...Array(4)].map((_, index) => { - return ; + return ; }) ) : upcomingEvents.length == 0 ? (
    @@ -295,7 +344,7 @@ function organizationDashboard(): JSX.Element { {loadingPost ? ( [...Array(4)].map((_, index) => { - return ; + return ; }) ) : postData?.organizations[0].posts.totalCount == 0 ? ( /* eslint-disable */ @@ -325,44 +374,109 @@ function organizationDashboard(): JSX.Element { - -
    -
    {t('membershipRequests')}
    - -
    - - {loadingOrgData ? ( - [...Array(4)].map((_, index) => { - return ; - }) - ) : data?.organizations[0].membershipRequests.length == 0 ? ( -
    -
    {t('noMembershipRequests')}
    + + +
    +
    + {t('membershipRequests')}
    - ) : ( - data?.organizations[0]?.membershipRequests - .slice(0, 8) - .map((request) => { + +
    + + {loadingOrgData ? ( + [...Array(4)].map((_, index) => { + return ; + }) + ) : data?.organizations[0].membershipRequests.length == 0 ? ( +
    +
    {t('noMembershipRequests')}
    +
    + ) : ( + data?.organizations[0]?.membershipRequests + .slice(0, 8) + .map((request) => { + return ( + + ); + }) + )} +
    +
    +
    + + +
    +
    {t('volunteerRankings')}
    + +
    + + {rankingsLoading ? ( + [...Array(3)].map((_, index) => { + return ; + }) + ) : rankings.length == 0 ? ( +
    +
    {t('noVolunteers')}
    +
    + ) : ( + rankings.map(({ rank, user, hoursVolunteered }, index) => { return ( - +
    +
    +
    + {rank <= 3 ? ( + gold + ) : ( + rank + )} +
    +
    {`${user.firstName} ${user.lastName}`}
    +
    - {hoursVolunteered} hours
    +
    + {index < 2 &&
    } +
    ); }) - )} -
    -
    + )} + + +
    diff --git a/src/screens/OrganizationDashboard/OrganizationDashboardMocks.ts b/src/screens/OrganizationDashboard/OrganizationDashboardMocks.ts index 26e5441f92..af1e9a799b 100644 --- a/src/screens/OrganizationDashboard/OrganizationDashboardMocks.ts +++ b/src/screens/OrganizationDashboard/OrganizationDashboardMocks.ts @@ -1,3 +1,4 @@ +import { VOLUNTEER_RANKING } from 'GraphQl/Queries/EventVolunteerQueries'; import { ORGANIZATIONS_LIST, ORGANIZATION_EVENT_CONNECTION_LIST, @@ -8,12 +9,13 @@ export const MOCKS = [ { request: { query: ORGANIZATIONS_LIST, + variables: { id: 'orgId' }, }, result: { data: { organizations: [ { - _id: 123, + _id: 'orgId', image: '', name: 'Dummy Organization', description: 'This is a Dummy Organization', @@ -53,7 +55,7 @@ export const MOCKS = [ ], membershipRequests: [ { - _id: '456', + _id: 'requestId1', user: { firstName: 'Jane', lastName: 'Doe', @@ -77,7 +79,7 @@ export const MOCKS = [ { request: { query: ORGANIZATION_POST_LIST, - variables: { first: 10 }, + variables: { id: 'orgId', first: 10 }, }, result: { data: { @@ -87,7 +89,7 @@ export const MOCKS = [ edges: [ { node: { - _id: '6411e53835d7ba2344a78e21', + _id: 'postId1', title: 'postone', text: 'This is the first post', imageUrl: null, @@ -105,11 +107,11 @@ export const MOCKS = [ pinned: true, likedBy: [], }, - cursor: '6411e53835d7ba2344a78e21', + cursor: 'postId1', }, { node: { - _id: '6411e54835d7ba2344a78e29', + _id: 'postId2', title: 'posttwo', text: 'Tis is the post two', imageUrl: null, @@ -127,11 +129,11 @@ export const MOCKS = [ likedBy: [], comments: [], }, - cursor: '6411e54835d7ba2344a78e29', + cursor: 'postId2', }, { node: { - _id: '6411e54835d7ba2344a78e30', + _id: 'postId3', title: 'posttwo', text: 'Tis is the post two', imageUrl: null, @@ -149,11 +151,11 @@ export const MOCKS = [ likedBy: [], comments: [], }, - cursor: '6411e54835d7ba2344a78e30', + cursor: 'postId3', }, { node: { - _id: '6411e54835d7ba2344a78e31', + _id: 'postId4', title: 'posttwo', text: 'Tis is the post two', imageUrl: null, @@ -171,12 +173,12 @@ export const MOCKS = [ likedBy: [], comments: [], }, - cursor: '6411e54835d7ba2344a78e31', + cursor: 'postId4', }, ], pageInfo: { - startCursor: '6411e53835d7ba2344a78e21', - endCursor: '6411e54835d7ba2344a78e31', + startCursor: 'postId1', + endCursor: 'postId4', hasNextPage: false, hasPreviousPage: false, }, @@ -191,15 +193,15 @@ export const MOCKS = [ request: { query: ORGANIZATION_EVENT_CONNECTION_LIST, variables: { - organization_id: '123', + organization_id: 'orgId', }, }, result: { data: { eventsByOrganizationConnection: [ { - _id: '1', - title: 'Sample Event', + _id: 'eventId1', + title: 'Event 1', description: 'Sample Description', startDate: '2025-10-29T00:00:00.000Z', endDate: '2023-10-29T23:59:59.000Z', @@ -208,14 +210,27 @@ export const MOCKS = [ endTime: '17:00:00', allDay: false, recurring: false, + attendees: [ + { + _id: 'userId1', + createdAt: '2023-01-01T00:00:00.000Z', + firstName: 'John', + lastName: 'Doe', + gender: 'Male', + eventsAttended: { + _id: 'eventId1', + endDate: '2023-10-29T23:59:59.000Z', + }, + }, + ], recurrenceRule: null, isRecurringEventException: false, isPublic: true, isRegisterable: true, }, { - _id: '2', - title: 'Sample Event', + _id: 'eventId2', + title: 'Event 2', description: 'Sample Description', startDate: '2022-10-29T00:00:00.000Z', endDate: '2023-10-29T23:59:59.000Z', @@ -223,6 +238,19 @@ export const MOCKS = [ startTime: '08:00:00', endTime: '17:00:00', allDay: false, + attendees: [ + { + _id: 'userId1', + createdAt: '2023-01-01T00:00:00.000Z', + firstName: 'John', + lastName: 'Doe', + gender: 'Male', + eventsAttended: { + _id: 'eventId1', + endDate: '2023-10-29T23:59:59.000Z', + }, + }, + ], recurring: false, recurrenceRule: null, isRecurringEventException: false, @@ -233,12 +261,76 @@ export const MOCKS = [ }, }, }, + { + request: { + query: VOLUNTEER_RANKING, + variables: { + orgId: 'orgId', + where: { + orderBy: 'hours_DESC', + timeFrame: 'allTime', + limit: 3, + }, + }, + }, + result: { + data: { + getVolunteerRanks: [ + { + rank: 1, + hoursVolunteered: 5, + user: { + _id: 'userId1', + lastName: 'Bradley', + firstName: 'Teresa', + image: null, + email: 'testuser4@example.com', + }, + }, + { + rank: 2, + hoursVolunteered: 4, + user: { + _id: 'userId2', + lastName: 'Garza', + firstName: 'Bruce', + image: null, + email: 'testuser5@example.com', + }, + }, + { + rank: 3, + hoursVolunteered: 3, + user: { + _id: 'userId3', + lastName: 'John', + firstName: 'Doe', + image: null, + email: 'testuser6@example.com', + }, + }, + { + rank: 4, + hoursVolunteered: 2, + user: { + _id: 'userId4', + lastName: 'Jane', + firstName: 'Doe', + image: null, + email: 'testuser7@example.com', + }, + }, + ], + }, + }, + }, ]; export const EMPTY_MOCKS = [ { request: { query: ORGANIZATIONS_LIST, + variables: { id: 'orgId' }, }, result: { data: { @@ -299,7 +391,7 @@ export const EMPTY_MOCKS = [ { request: { query: ORGANIZATION_POST_LIST, - variables: { first: 10 }, + variables: { id: 'orgId', first: 10 }, }, result: { data: { @@ -323,6 +415,9 @@ export const EMPTY_MOCKS = [ { request: { query: ORGANIZATION_EVENT_CONNECTION_LIST, + variables: { + organization_id: 'orgId', + }, }, result: { data: { @@ -330,25 +425,62 @@ export const EMPTY_MOCKS = [ }, }, }, + { + request: { + query: VOLUNTEER_RANKING, + variables: { + orgId: '123', + where: { + orderBy: 'hours_DESC', + timeFrame: 'allTime', + limit: 3, + }, + }, + }, + result: { + data: { + getVolunteerRanks: [], + }, + }, + }, ]; export const ERROR_MOCKS = [ { request: { query: ORGANIZATIONS_LIST, + variables: { id: 'orgId' }, }, error: new Error('Mock Graphql ORGANIZATIONS_LIST Error'), }, { request: { query: ORGANIZATION_POST_LIST, + variables: { id: 'orgId', first: 10 }, }, error: new Error('Mock Graphql ORGANIZATION_POST_LIST Error'), }, { request: { query: ORGANIZATION_EVENT_CONNECTION_LIST, + variables: { + organization_id: 'orgId', + }, }, error: new Error('Mock Graphql ORGANIZATION_EVENT_LIST Error'), }, + { + request: { + query: VOLUNTEER_RANKING, + variables: { + orgId: '123', + where: { + orderBy: 'hours_DESC', + timeFrame: 'allTime', + limit: 3, + }, + }, + }, + error: new Error('Mock Graphql VOLUNTEER_RANKING Error'), + }, ]; diff --git a/src/screens/OrganizationEvents/OrganizationEvents.test.tsx b/src/screens/OrganizationEvents/OrganizationEvents.test.tsx index 6c0491e2b2..09e896e031 100644 --- a/src/screens/OrganizationEvents/OrganizationEvents.test.tsx +++ b/src/screens/OrganizationEvents/OrganizationEvents.test.tsx @@ -282,7 +282,7 @@ describe('Organisation Events Page', () => { userEvent.click(screen.getByTestId('createEventBtn')); await waitFor(() => { - expect(toast.success).toBeCalledWith(translations.eventCreated); + expect(toast.success).toHaveBeenCalledWith(translations.eventCreated); }); await waitFor(() => { @@ -371,9 +371,9 @@ describe('Organisation Events Page', () => { expect(screen.getByTestId('registrableCheck')).toBeChecked(); userEvent.click(screen.getByTestId('createEventBtn')); - expect(toast.warning).toBeCalledWith('Title can not be blank!'); - expect(toast.warning).toBeCalledWith('Description can not be blank!'); - expect(toast.warning).toBeCalledWith('Location can not be blank!'); + expect(toast.warning).toHaveBeenCalledWith('Title can not be blank!'); + expect(toast.warning).toHaveBeenCalledWith('Description can not be blank!'); + expect(toast.warning).toHaveBeenCalledWith('Location can not be blank!'); userEvent.click(screen.getByTestId('createEventModalCloseBtn')); @@ -452,7 +452,7 @@ describe('Organisation Events Page', () => { userEvent.click(screen.getByTestId('createEventBtn')); await waitFor(() => { - expect(toast.success).toBeCalledWith(translations.eventCreated); + expect(toast.success).toHaveBeenCalledWith(translations.eventCreated); }); await waitFor(() => { diff --git a/src/screens/OrganizationPeople/AddMember.tsx b/src/screens/OrganizationPeople/AddMember.tsx index 4c1f15106e..750d831abf 100644 --- a/src/screens/OrganizationPeople/AddMember.tsx +++ b/src/screens/OrganizationPeople/AddMember.tsx @@ -1,5 +1,5 @@ import { useLazyQuery, useMutation, useQuery } from '@apollo/client'; -import { Search } from '@mui/icons-material'; +import { Check, Close, Search } from '@mui/icons-material'; import EmailOutlinedIcon from '@mui/icons-material/EmailOutlined'; import Paper from '@mui/material/Paper'; import Table from '@mui/material/Table'; @@ -30,13 +30,13 @@ import type { InterfaceQueryOrganizationsListObject, InterfaceQueryUserListItem, } from 'utils/interfaces'; -import styles from './OrganizationPeople.module.css'; +import styles from '../../style/app.module.css'; import Avatar from 'components/Avatar/Avatar'; -const StyledTableCell = styled(TableCell)(({ theme }) => ({ +const StyledTableCell = styled(TableCell)(() => ({ [`&.${tableCellClasses.head}`]: { - backgroundColor: ['#31bb6b', '!important'], - color: theme.palette.common.white, + backgroundColor: 'var(--table-head-bg, blue)', + color: 'var(--table-header-color, black)', }, [`&.${tableCellClasses.body}`]: { fontSize: 14, @@ -77,7 +77,7 @@ function AddMember(): JSX.Element { setAddUserModalIsOpen(true); } - const toggleDialogModal = /* istanbul ignore next */ (): void => + const toggleDialogModal = (): void => setAddUserModalIsOpen(!addUserModalisOpen); const [createNewUserModalisOpen, setCreateNewUserModalIsOpen] = @@ -89,7 +89,7 @@ function AddMember(): JSX.Element { function closeCreateNewUserModal(): void { setCreateNewUserModalIsOpen(false); } - const toggleCreateNewUserModal = /* istanbul ignore next */ (): void => + const toggleCreateNewUserModal = (): void => setCreateNewUserModalIsOpen(!addUserModalisOpen); const [addMember] = useMutation(ADD_MEMBER_MUTATION); @@ -216,7 +216,6 @@ function AddMember(): JSX.Element { closeCreateNewUserModal(); - /* istanbul ignore next */ setCreateUserVariables({ firstName: '', lastName: '', @@ -225,52 +224,40 @@ function AddMember(): JSX.Element { confirmPassword: '', }); } catch (error: unknown) { - /* istanbul ignore next */ errorHandler(translateOrgPeople, error); } } }; - /* istanbul ignore next */ const handleFirstName = (e: ChangeEvent): void => { const firstName = e.target.value; - setCreateUserVariables({ ...createUserVariables, firstName }); }; - /* istanbul ignore next */ const handleLastName = (e: ChangeEvent): void => { const lastName = e.target.value; - setCreateUserVariables({ ...createUserVariables, lastName }); }; - /* istanbul ignore next */ const handleEmailChange = (e: ChangeEvent): void => { const email = e.target.value; - setCreateUserVariables({ ...createUserVariables, email }); }; - /* istanbul ignore next */ const handlePasswordChange = (e: ChangeEvent): void => { const password = e.target.value; - setCreateUserVariables({ ...createUserVariables, password }); }; - /* istanbul ignore next */ const handleConfirmPasswordChange = ( e: ChangeEvent, ): void => { const confirmPassword = e.target.value; - setCreateUserVariables({ ...createUserVariables, confirmPassword }); }; const handleUserModalSearchChange = (e: React.FormEvent): void => { e.preventDefault(); - /* istanbul ignore next */ const [firstName, lastName] = userName.split(' '); const newFilterData = { @@ -322,6 +309,7 @@ function AddMember(): JSX.Element { + {/* Existing User Modal */} {allUsersLoading ? ( - <> - - + ) : ( <>
    @@ -356,9 +342,9 @@ function AddMember(): JSX.Element {
    @@ -413,7 +399,7 @@ function AddMember(): JSX.Element { + Add @@ -446,6 +434,7 @@ function AddMember(): JSX.Element {
    + {/* New User Modal */} @@ -559,7 +547,12 @@ function AddMember(): JSX.Element { variant="danger" onClick={closeCreateNewUserModal} data-testid="closeBtn" + style={{ + backgroundColor: 'var(--delete-button-bg)', + color: 'var(--delete-button-color)', + }} > + {translateOrgPeople('cancel')}
    @@ -578,18 +576,3 @@ function AddMember(): JSX.Element { } export default AddMember; -// | typeof ORGANIZATIONS_MEMBER_CONNECTION_LIST -// | typeof ORGANIZATIONS_LIST -// | typeof USER_LIST_FOR_TABLE -// | typeof ADD_MEMBER_MUTATION; -// { -// id?: string; -// orgId?: string; -// orgid?: string; -// fristNameContains?: string; -// lastNameContains?: string; -// firstName_contains?: string; -// lastName_contains?: string; -// id_not_in?: string[]; -// userid?: string; -// }; diff --git a/src/screens/OrganizationPeople/OrganizationPeople.module.css b/src/screens/OrganizationPeople/OrganizationPeople.module.css deleted file mode 100644 index 5ff4b0d297..0000000000 --- a/src/screens/OrganizationPeople/OrganizationPeople.module.css +++ /dev/null @@ -1,121 +0,0 @@ -@media screen and (max-width: 575.5px) { - .mainpageright { - width: 98%; - } -} -.modalContent { - width: 670px; - max-width: 680px; -} -.dropdown { - background-color: white; - border: 1px solid #31bb6b; - position: relative; - display: inline-block; - margin-top: 10px; - margin-bottom: 10px; - color: #31bb6b; -} -.input { - flex: 1; - position: relative; -} - -.btnsContainer { - display: flex; - margin: 2.5rem 0 2.5rem 0; -} - -.btnsContainer .btnsBlock { - display: flex; -} - -.btnsContainer .btnsBlock button { - margin-left: 1rem; - display: flex; - justify-content: center; - align-items: center; -} - -.btnsContainer .input { - flex: 1; - position: relative; -} - -/* input { - outline: 1px solid var(--bs-gray-400); -} */ - -.btnsContainer .input button { - width: 52px; -} - -.inputField { - margin-top: 10px; - margin-bottom: 10px; - background-color: white; - box-shadow: 0 1px 1px #31bb6b; -} -.inputFieldModal { - margin-bottom: 10px; - background-color: white; - box-shadow: 0 1px 1px #31bb6b; -} -.inputField > button { - padding-top: 10px; - padding-bottom: 10px; -} -.TableImage { - object-fit: cover; - width: 50px !important; - height: 50px !important; - border-radius: 100% !important; -} -.tableHead { - background-color: #31bb6b !important; - color: white; - border-radius: 20px !important; - padding: 20px; - margin-top: 20px; -} - -.tableHead :nth-first-child() { - border-top-left-radius: 20px; -} - -.mainpageright > hr { - margin-top: 10px; - width: 100%; - margin-left: -15px; - margin-right: -15px; - margin-bottom: 20px; -} -.rowBackground { - background-color: var(--bs-white); -} -.tableHeader { - background-color: var(--bs-primary); - color: var(--bs-white); - font-size: 16px; -} - -@-webkit-keyframes load8 { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } -} -@keyframes load8 { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } -} diff --git a/src/screens/OrganizationPeople/OrganizationPeople.tsx b/src/screens/OrganizationPeople/OrganizationPeople.tsx index 1d230ed058..36efdba63c 100644 --- a/src/screens/OrganizationPeople/OrganizationPeople.tsx +++ b/src/screens/OrganizationPeople/OrganizationPeople.tsx @@ -1,5 +1,5 @@ import { useLazyQuery } from '@apollo/client'; -import { Search, Sort } from '@mui/icons-material'; +import { Delete, Search, Sort } from '@mui/icons-material'; import { ORGANIZATIONS_LIST, ORGANIZATIONS_MEMBER_CONNECTION_LIST, @@ -16,7 +16,7 @@ import { useTranslation } from 'react-i18next'; import { Link, useLocation, useParams } from 'react-router-dom'; import { toast } from 'react-toastify'; import AddMember from './AddMember'; -import styles from './OrganizationPeople.module.css'; +import styles from '../../style/app.module.css'; import { DataGrid } from '@mui/x-data-grid'; import type { GridColDef, GridCellParams } from '@mui/x-data-grid'; import { Stack } from '@mui/material'; @@ -214,7 +214,7 @@ function organizationPeople(): JSX.Element { {params.row?.firstName + ' ' + params.row?.lastName} @@ -258,15 +258,19 @@ function organizationPeople(): JSX.Element { ) : ( ); }, @@ -292,11 +296,10 @@ function organizationPeople(): JSX.Element { />
    @@ -316,6 +319,7 @@ function organizationPeople(): JSX.Element { d-inline id="userslist" data-value="userslist" + className={styles.dropdownItem} data-name="displaylist" data-testid="users" defaultChecked={state == 2 ? true : false} @@ -331,6 +335,7 @@ function organizationPeople(): JSX.Element { d-inline id="memberslist" data-value="memberslist" + className={styles.dropdownItem} data-name="displaylist" data-testid="members" defaultChecked={state == 0 ? true : false} @@ -338,20 +343,25 @@ function organizationPeople(): JSX.Element { setState(0); }} > - + + {tCommon('members')} + { setState(1); }} > - + + {tCommon('admins')} + @@ -370,7 +380,6 @@ function organizationPeople(): JSX.Element { disableColumnMenu columnBufferPx={5} hideFooter={true} - className={`${styles.datagrid}`} getRowId={(row) => row._id} slots={{ noRowsOverlay: () => ( @@ -384,17 +393,26 @@ function organizationPeople(): JSX.Element { ), }} sx={{ - '&.MuiDataGrid-root .MuiDataGrid-cell:focus-within': { - outline: 'none !important', - }, - '&.MuiDataGrid-root .MuiDataGrid-columnHeader:focus-within': { - outline: 'none', + borderRadius: '20px', + backgroundColor: '#EAEBEF', + '& .MuiDataGrid-row': { + backgroundColor: '#eff1f7', + '&:focus-within': { + outline: '2px solid #000', + outlineOffset: '-2px', + }, }, '& .MuiDataGrid-row:hover': { - backgroundColor: 'transparent', + backgroundColor: '#EAEBEF', + boxShadow: '0 0 0 1px rgba(0, 0, 0, 0.1)', }, '& .MuiDataGrid-row.Mui-hovered': { - backgroundColor: 'transparent', + backgroundColor: '#EAEBEF', + boxShadow: '0 0 0 1px rgba(0, 0, 0, 0.1)', + }, + '& .MuiDataGrid-cell:focus': { + outline: '2px solid #000', + outlineOffset: '-2px', }, }} getRowClassName={() => `${styles.rowBackground}`} diff --git a/src/screens/OrganizationTags/OrganizationTags.module.css b/src/screens/OrganizationTags/OrganizationTags.module.css deleted file mode 100644 index 7251a79d0d..0000000000 --- a/src/screens/OrganizationTags/OrganizationTags.module.css +++ /dev/null @@ -1,141 +0,0 @@ -.btnsContainer { - display: flex; - margin: 2rem 0; -} - -.btnsContainer .btnsBlock { - display: flex; - width: max-content; -} - -.btnsContainer .btnsBlock button { - margin-left: 1rem; - display: flex; - justify-content: center; - align-items: center; -} - -.btnsContainer .input { - flex: 1; - position: relative; - max-width: 60%; - justify-content: space-between; -} - -.btnsContainer input { - outline: 1px solid var(--bs-gray-400); -} - -.btnsContainer .input button { - width: 52px; -} - -@media (max-width: 1120px) { - .contract { - padding-left: calc(250px + 2rem + 1.5rem); - } - - .listBox .itemCard { - width: 100%; - } -} - -@media (max-width: 1020px) { - .btnsContainer { - flex-direction: column; - margin: 1.5rem 0; - } - - .btnsContainer .btnsBlock { - margin: 1.5rem 0 0 0; - justify-content: space-between; - } - - .btnsContainer .btnsBlock button { - margin: 0; - } - - .btnsContainer .btnsBlock div button { - margin-right: 1.5rem; - } -} - -/* For mobile devices */ - -@media (max-width: 520px) { - .btnsContainer { - margin-bottom: 0; - } - - .btnsContainer .btnsBlock { - display: block; - margin-top: 1rem; - margin-right: 0; - } - - .btnsContainer .btnsBlock div { - flex: 1; - } - - .btnsContainer .btnsBlock div[title='Sort organizations'] { - margin-right: 0.5rem; - } - - .btnsContainer .btnsBlock button { - margin-bottom: 1rem; - margin-right: 0; - width: 100%; - } -} - -.errorContainer { - min-height: 100vh; -} - -.errorMessage { - margin-top: 25%; - display: flex; - justify-content: center; - align-items: center; - flex-direction: column; -} - -.errorIcon { - transform: scale(1.5); - color: var(--bs-danger); - margin-bottom: 1rem; -} - -.tableHeader { - background-color: var(--bs-primary); - color: var(--bs-white); - font-size: 1rem; -} -.rowBackground { - background-color: var(--bs-white); - max-height: 120px; -} - -.subTagsLink { - color: var(--bs-blue); - font-weight: 500; - cursor: pointer; -} - -.subTagsLink i { - visibility: hidden; -} - -.subTagsLink:hover { - font-weight: 600; - text-decoration: underline; -} - -.subTagsLink:hover i { - visibility: visible; -} - -.tagsBreadCrumbs { - color: var(--bs-gray); - cursor: pointer; -} diff --git a/src/screens/OrganizationTags/OrganizationTags.test.tsx b/src/screens/OrganizationTags/OrganizationTags.test.tsx index 923a26d982..0d426d20ac 100644 --- a/src/screens/OrganizationTags/OrganizationTags.test.tsx +++ b/src/screens/OrganizationTags/OrganizationTags.test.tsx @@ -4,6 +4,7 @@ import type { RenderResult } from '@testing-library/react'; import { act, cleanup, + fireEvent, render, screen, waitFor, @@ -59,11 +60,11 @@ const renderOrganizationTags = (link: ApolloLink): RenderResult => { } />
    } />
    } /> @@ -87,7 +88,7 @@ describe('Organisation Tags Page', () => { cleanup(); }); - test('Component loads correctly', async () => { + test('component loads correctly', async () => { const { getByText } = renderOrganizationTags(link); await wait(); @@ -103,7 +104,7 @@ describe('Organisation Tags Page', () => { await wait(); await waitFor(() => { - expect(queryByText(translations.create)).not.toBeInTheDocument(); + expect(queryByText(translations.createTag)).not.toBeInTheDocument(); }); }); @@ -129,118 +130,170 @@ describe('Organisation Tags Page', () => { ); }); - test('opens and closes the remove tag modal', async () => { + test('navigates to sub tags screen after clicking on a tag', async () => { renderOrganizationTags(link); await wait(); await waitFor(() => { - expect(screen.getAllByTestId('removeUserTagBtn')[0]).toBeInTheDocument(); + expect(screen.getAllByTestId('tagName')[0]).toBeInTheDocument(); }); - userEvent.click(screen.getAllByTestId('removeUserTagBtn')[0]); + userEvent.click(screen.getAllByTestId('tagName')[0]); await waitFor(() => { - return expect( - screen.findByTestId('removeUserTagModalCloseBtn'), - ).resolves.toBeInTheDocument(); + expect(screen.getByTestId('subTagsScreen')).toBeInTheDocument(); }); - userEvent.click(screen.getByTestId('removeUserTagModalCloseBtn')); - - await waitForElementToBeRemoved(() => - screen.queryByTestId('removeUserTagModalCloseBtn'), - ); }); - test('navigates to sub tags screen after clicking on a tag', async () => { + test('navigates to manage tag page after clicking manage tag option', async () => { renderOrganizationTags(link); await wait(); await waitFor(() => { - expect(screen.getAllByTestId('tagName')[0]).toBeInTheDocument(); + expect(screen.getAllByTestId('manageTagBtn')[0]).toBeInTheDocument(); }); - userEvent.click(screen.getAllByTestId('tagName')[0]); + userEvent.click(screen.getAllByTestId('manageTagBtn')[0]); await waitFor(() => { - expect(screen.getByTestId('subTagsScreen')).toBeInTheDocument(); + expect(screen.getByTestId('manageTagScreen')).toBeInTheDocument(); }); }); - test('navigates to manage tag page after clicking manage tag option', async () => { + test('searchs for tags where the name matches the provided search input', async () => { renderOrganizationTags(link); await wait(); await waitFor(() => { - expect(screen.getAllByTestId('manageTagBtn')[0]).toBeInTheDocument(); + expect( + screen.getByPlaceholderText(translations.searchByName), + ).toBeInTheDocument(); }); - userEvent.click(screen.getAllByTestId('manageTagBtn')[0]); + const input = screen.getByPlaceholderText(translations.searchByName); + fireEvent.change(input, { target: { value: 'searchUserTag' } }); + // should render the two searched tags from the mock data + // where name starts with "searchUserTag" await waitFor(() => { - expect(screen.getByTestId('manageTagScreen')).toBeInTheDocument(); + const buttons = screen.getAllByTestId('manageTagBtn'); + expect(buttons.length).toEqual(2); }); }); - test('paginates between different pages', async () => { + test('fetches the tags by the sort order, i.e. latest or oldest first', async () => { renderOrganizationTags(link); await wait(); await waitFor(() => { - expect(screen.getByTestId('nextPagBtn')).toBeInTheDocument(); + expect( + screen.getByPlaceholderText(translations.searchByName), + ).toBeInTheDocument(); + }); + const input = screen.getByPlaceholderText(translations.searchByName); + fireEvent.change(input, { target: { value: 'searchUserTag' } }); + + // should render the two searched tags from the mock data + // where name starts with "searchUserTag" + await waitFor(() => { + expect(screen.getAllByTestId('tagName')[0]).toHaveTextContent( + 'searchUserTag 1', + ); + }); + + // now change the sorting order + await waitFor(() => { + expect(screen.getByTestId('sortTags')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('sortTags')); + + await waitFor(() => { + expect(screen.getByTestId('oldest')).toBeInTheDocument(); }); - userEvent.click(screen.getByTestId('nextPagBtn')); + userEvent.click(screen.getByTestId('oldest')); + // returns the tags in reverse order await waitFor(() => { - expect(screen.getAllByTestId('tagName')[0]).toHaveTextContent('6'); + expect(screen.getAllByTestId('tagName')[0]).toHaveTextContent( + 'searchUserTag 2', + ); }); await waitFor(() => { - expect(screen.getByTestId('previousPageBtn')).toBeInTheDocument(); + expect(screen.getByTestId('sortTags')).toBeInTheDocument(); }); - userEvent.click(screen.getByTestId('previousPageBtn')); + userEvent.click(screen.getByTestId('sortTags')); await waitFor(() => { - expect(screen.getAllByTestId('tagName')[0]).toHaveTextContent('1'); + expect(screen.getByTestId('latest')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('latest')); + + // reverse the order again + await waitFor(() => { + expect(screen.getAllByTestId('tagName')[0]).toHaveTextContent( + 'searchUserTag 1', + ); }); }); - test('creates a new user tag', async () => { - renderOrganizationTags(link); + test('fetches more tags with infinite scroll', async () => { + const { getByText } = renderOrganizationTags(link); await wait(); await waitFor(() => { - expect(screen.getByTestId('createTagBtn')).toBeInTheDocument(); + expect(getByText(translations.createTag)).toBeInTheDocument(); }); - userEvent.click(screen.getByTestId('createTagBtn')); - userEvent.type( - screen.getByPlaceholderText(translations.tagNamePlaceholder), - '7', + const orgUserTagsScrollableDiv = screen.getByTestId( + 'orgUserTagsScrollableDiv', ); - userEvent.click(screen.getByTestId('createTagSubmitBtn')); + // Get the initial number of tags loaded + const initialTagsDataLength = screen.getAllByTestId('manageTagBtn').length; + + // Set scroll position to the bottom + fireEvent.scroll(orgUserTagsScrollableDiv, { + target: { scrollY: orgUserTagsScrollableDiv.scrollHeight }, + }); await waitFor(() => { - expect(toast.success).toBeCalledWith(translations.tagCreationSuccess); + const finalTagsDataLength = screen.getAllByTestId('manageTagBtn').length; + expect(finalTagsDataLength).toBeGreaterThan(initialTagsDataLength); + + expect(getByText(translations.createTag)).toBeInTheDocument(); }); }); - test('removes a user tag', async () => { + test('creates a new user tag', async () => { renderOrganizationTags(link); await wait(); await waitFor(() => { - expect(screen.getAllByTestId('removeUserTagBtn')[0]).toBeInTheDocument(); + expect(screen.getByTestId('createTagBtn')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('createTagBtn')); + + userEvent.click(screen.getByTestId('createTagSubmitBtn')); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalledWith(translations.enterTagName); }); - userEvent.click(screen.getAllByTestId('removeUserTagBtn')[0]); - userEvent.click(screen.getByTestId('removeUserTagSubmitBtn')); + userEvent.type( + screen.getByPlaceholderText(translations.tagNamePlaceholder), + 'userTag 12', + ); + + userEvent.click(screen.getByTestId('createTagSubmitBtn')); await waitFor(() => { - expect(toast.success).toBeCalledWith(translations.tagRemovalSuccess); + expect(toast.success).toHaveBeenCalledWith( + translations.tagCreationSuccess, + ); }); }); }); diff --git a/src/screens/OrganizationTags/OrganizationTags.tsx b/src/screens/OrganizationTags/OrganizationTags.tsx index e4bf0604e9..55134b75ac 100644 --- a/src/screens/OrganizationTags/OrganizationTags.tsx +++ b/src/screens/OrganizationTags/OrganizationTags.tsx @@ -1,11 +1,10 @@ -import { useMutation, useQuery, type ApolloError } from '@apollo/client'; -import { Search, WarningAmberRounded } from '@mui/icons-material'; +import { useMutation, useQuery } from '@apollo/client'; +import { WarningAmberRounded } from '@mui/icons-material'; import SortIcon from '@mui/icons-material/Sort'; import Loader from 'components/Loader/Loader'; -import IconComponent from 'components/IconComponent/IconComponent'; import { useNavigate, useParams, Link } from 'react-router-dom'; import type { ChangeEvent } from 'react'; -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { Form } from 'react-bootstrap'; import Button from 'react-bootstrap/Button'; import Dropdown from 'react-bootstrap/Dropdown'; @@ -13,17 +12,24 @@ import Modal from 'react-bootstrap/Modal'; import Row from 'react-bootstrap/Row'; import { useTranslation } from 'react-i18next'; import { toast } from 'react-toastify'; -import type { InterfaceQueryOrganizationUserTags } from 'utils/interfaces'; -import styles from './OrganizationTags.module.css'; +import IconComponent from 'components/IconComponent/IconComponent'; +import type { + InterfaceQueryOrganizationUserTags, + InterfaceTagData, +} from 'utils/interfaces'; +import styles from '../../style/app.module.css'; import { DataGrid } from '@mui/x-data-grid'; -import { dataGridStyle } from 'utils/organizationTagsUtils'; +import type { + InterfaceOrganizationTagsQuery, + SortedByType, +} from 'utils/organizationTagsUtils'; +import { TAGS_QUERY_DATA_CHUNK_SIZE } from 'utils/organizationTagsUtils'; import type { GridCellParams, GridColDef } from '@mui/x-data-grid'; import { Stack } from '@mui/material'; import { ORGANIZATION_USER_TAGS_LIST } from 'GraphQl/Queries/OrganizationQueries'; -import { - CREATE_USER_TAG, - REMOVE_USER_TAG, -} from 'GraphQl/Mutations/TagMutations'; +import { CREATE_USER_TAG } from 'GraphQl/Mutations/TagMutations'; +import InfiniteScroll from 'react-infinite-scroll-component'; +import InfiniteScrollLoader from 'components/InfiniteScrollLoader/InfiniteScrollLoader'; /** * Component that renders the Organization Tags screen when the app navigates to '/orgtags/:orgId'. @@ -40,19 +46,14 @@ function OrganizationTags(): JSX.Element { const [createTagModalIsOpen, setCreateTagModalIsOpen] = useState(false); + const [tagSearchName, setTagSearchName] = useState(''); + const [tagSortOrder, setTagSortOrder] = useState('DESCENDING'); + const { orgId } = useParams(); const navigate = useNavigate(); - const [after, setAfter] = useState(null); - const [before, setBefore] = useState(null); - const [first, setFirst] = useState(5); - const [last, setLast] = useState(null); - const [tagSerialNumber, setTagSerialNumber] = useState(0); const [tagName, setTagName] = useState(''); - const [removeUserTagId, setRemoveUserTagId] = useState(null); - const [removeTagModalIsOpen, setRemoveTagModalIsOpen] = useState(false); - const showCreateTagModal = (): void => { setTagName(''); setCreateTagModalIsOpen(true); @@ -67,29 +68,71 @@ function OrganizationTags(): JSX.Element { loading: orgUserTagsLoading, error: orgUserTagsError, refetch: orgUserTagsRefetch, - }: { - data?: { - organizations: InterfaceQueryOrganizationUserTags[]; - }; - loading: boolean; - error?: ApolloError; - refetch: () => void; - } = useQuery(ORGANIZATION_USER_TAGS_LIST, { + fetchMore: orgUserTagsFetchMore, + }: InterfaceOrganizationTagsQuery = useQuery(ORGANIZATION_USER_TAGS_LIST, { variables: { id: orgId, - after: after, - before: before, - first: first, - last: last, + first: TAGS_QUERY_DATA_CHUNK_SIZE, + where: { name: { starts_with: tagSearchName } }, + sortedBy: { id: tagSortOrder }, }, }); + const loadMoreUserTags = (): void => { + orgUserTagsFetchMore({ + variables: { + first: TAGS_QUERY_DATA_CHUNK_SIZE, + after: + orgUserTagsData?.organizations?.[0]?.userTags?.pageInfo?.endCursor ?? + /* istanbul ignore next */ + null, + }, + updateQuery: ( + prevResult: { organizations: InterfaceQueryOrganizationUserTags[] }, + { + fetchMoreResult, + }: { + fetchMoreResult?: { + organizations: InterfaceQueryOrganizationUserTags[]; + }; + }, + ) => { + if (!fetchMoreResult) /* istanbul ignore next */ return prevResult; + + return { + organizations: [ + { + ...prevResult.organizations[0], + userTags: { + ...prevResult.organizations[0].userTags, + edges: [ + ...prevResult.organizations[0].userTags.edges, + ...fetchMoreResult.organizations[0].userTags.edges, + ], + pageInfo: fetchMoreResult.organizations[0].userTags.pageInfo, + }, + }, + ], + }; + }, + }); + }; + + useEffect(() => { + orgUserTagsRefetch(); + }, []); + const [create, { loading: createUserTagLoading }] = useMutation(CREATE_USER_TAG); const createTag = async (e: ChangeEvent): Promise => { e.preventDefault(); + if (!tagName.trim()) { + toast.error(t('enterTagName')); + return; + } + try { const { data } = await create({ variables: { @@ -99,7 +142,7 @@ function OrganizationTags(): JSX.Element { }); if (data) { - toast.success(t('tagCreationSuccess') as string); + toast.success(t('tagCreationSuccess')); orgUserTagsRefetch(); setTagName(''); setCreateTagModalIsOpen(false); @@ -112,30 +155,6 @@ function OrganizationTags(): JSX.Element { } }; - const [removeUserTag] = useMutation(REMOVE_USER_TAG); - const handleRemoveUserTag = async (): Promise => { - try { - await removeUserTag({ - variables: { - id: removeUserTagId, - }, - }); - - orgUserTagsRefetch(); - toggleRemoveUserTagModal(); - toast.success(t('tagRemovalSuccess') as string); - } catch (error: unknown) { - /* istanbul ignore next */ - if (error instanceof Error) { - toast.error(error.message); - } - } - }; - - if (createUserTagLoading || orgUserTagsLoading) { - return ; - } - if (orgUserTagsError) { return (
    @@ -151,38 +170,18 @@ function OrganizationTags(): JSX.Element { ); } - const handleNextPage = (): void => { - setAfter(orgUserTagsData?.organizations[0].userTags.pageInfo.endCursor); - setBefore(null); - setFirst(5); - setLast(null); - setTagSerialNumber(tagSerialNumber + 1); - }; - const handlePreviousPage = (): void => { - setBefore(orgUserTagsData?.organizations[0].userTags.pageInfo.startCursor); - setAfter(null); - setFirst(null); - setLast(5); - setTagSerialNumber(tagSerialNumber - 1); - }; - const userTagsList = orgUserTagsData?.organizations[0].userTags.edges.map( (edge) => edge.node, ); const redirectToManageTag = (tagId: string): void => { - navigate(`/orgtags/${orgId}/managetag/${tagId}`); + navigate(`/orgtags/${orgId}/manageTag/${tagId}`); }; const redirectToSubTags = (tagId: string): void => { navigate(`/orgtags/${orgId}/subTags/${tagId}`); }; - const toggleRemoveUserTagModal = (): void => { - if (removeTagModalIsOpen) setRemoveUserTagId(null); - setRemoveTagModalIsOpen(!removeTagModalIsOpen); - }; - const columns: GridColDef[] = [ { field: 'id', @@ -193,7 +192,7 @@ function OrganizationTags(): JSX.Element { headerClassName: `${styles.tableHeader}`, sortable: false, renderCell: (params: GridCellParams) => { - return
    {tagSerialNumber * 5 + params.row.id}
    ; + return
    {params.row.id}
    ; }, }, { @@ -203,16 +202,29 @@ function OrganizationTags(): JSX.Element { minWidth: 100, sortable: false, headerClassName: `${styles.tableHeader}`, - renderCell: (params: GridCellParams) => { + renderCell: (params: GridCellParams) => { return ( -
    redirectToSubTags(params.row._id)} - > - {params.row.name} - - +
    + {params.row.parentTag && + params.row.ancestorTags?.map((tag) => ( +
    + {tag.name} + +
    + ))} + +
    redirectToSubTags(params.row._id)} + > + {params.row.name} + +
    ); }, @@ -230,7 +242,7 @@ function OrganizationTags(): JSX.Element { return ( {params.row.childTags.totalCount} @@ -250,7 +262,7 @@ function OrganizationTags(): JSX.Element { return ( {params.row.usersAssignedTo.totalCount} @@ -268,28 +280,15 @@ function OrganizationTags(): JSX.Element { headerClassName: `${styles.tableHeader}`, renderCell: (params: GridCellParams) => { return ( -
    - - - -
    + ); }, }, @@ -301,21 +300,16 @@ function OrganizationTags(): JSX.Element {
    + setTagSearchName(e.target.value.trim())} autoComplete="off" - required /> -
    - {tCommon('sort')} + {tagSortOrder === 'DESCENDING' + ? tCommon('Latest') + : tCommon('Oldest')} - + setTagSortOrder('DESCENDING')} + > {tCommon('Latest')} - + setTagSortOrder('ASCENDING')} + > {tCommon('Oldest')}
    - +
    + +
    -
    -
    -
    - + {orgUserTagsLoading || createUserTagLoading ? ( + + ) : ( +
    +
    +
    + +
    + +
    + {'Tags'} +
    -
    - {'Tags'} +
    + } + scrollableTarget="orgUserTagsScrollableDiv" + > + row.id} + slots={{ + noRowsOverlay: /* istanbul ignore next */ () => ( + + {t('noTagsFound')} + + ), + }} + sx={{ + borderRadius: '20px', + backgroundColor: '#EAEBEF', + '& .MuiDataGrid-row': { + backgroundColor: '#eff1f7', + '&:focus-within': { + // outline: '2px solid #000', + outlineOffset: '-2px', + }, + }, + '& .MuiDataGrid-row:hover': { + backgroundColor: '#EAEBEF', + boxShadow: '0 0 0 1px rgba(0, 0, 0, 0.1)', + }, + '& .MuiDataGrid-row.Mui-hovered': { + backgroundColor: '#EAEBEF', + boxShadow: '0 0 0 1px rgba(0, 0, 0, 0.1)', + }, + '& .MuiDataGrid-cell:focus': { + // outline: '2px solid #000', + outlineOffset: '-2px', + }, + }} + getRowClassName={() => `${styles.rowBackground}`} + autoHeight + rowHeight={65} + rows={userTagsList?.map((userTag, index) => ({ + id: index + 1, + ...userTag, + }))} + columns={columns} + isRowSelectable={() => false} + /> +
    - row._id} - slots={{ - noRowsOverlay: /* istanbul ignore next */ () => ( - - {t('noTagsFound')} - - ), - }} - sx={dataGridStyle} - getRowClassName={() => `${styles.rowBackground}`} - autoHeight - rowHeight={65} - rows={userTagsList?.map((fund, index) => ({ - id: index + 1, - ...fund, - }))} - columns={columns} - isRowSelectable={() => false} - /> -
    -
    - -
    -
    - -
    -
    - -
    + )}
    @@ -429,11 +450,11 @@ function OrganizationTags(): JSX.Element { centered > - {t('tagDetails')} + {t('tagDetails')}
    @@ -458,6 +479,7 @@ function OrganizationTags(): JSX.Element { variant="secondary" onClick={(): void => hideCreateTagModal()} data-testid="closeCreateTagModal" + className={styles.closeButton} > {tCommon('cancel')} @@ -465,49 +487,13 @@ function OrganizationTags(): JSX.Element { type="submit" value="invite" data-testid="createTagSubmitBtn" + className={styles.addButton} > {tCommon('create')} - - {/* Remove User Tag Modal */} - - - - {t('removeUserTag')} - - - {t('removeUserTagMessage')} - - - - - ); } diff --git a/src/screens/OrganizationTags/OrganizationTagsMocks.ts b/src/screens/OrganizationTags/OrganizationTagsMocks.ts index 3700c66c46..0fe48ca97f 100644 --- a/src/screens/OrganizationTags/OrganizationTagsMocks.ts +++ b/src/screens/OrganizationTags/OrganizationTagsMocks.ts @@ -1,8 +1,6 @@ -import { - CREATE_USER_TAG, - REMOVE_USER_TAG, -} from 'GraphQl/Mutations/TagMutations'; +import { CREATE_USER_TAG } from 'GraphQl/Mutations/TagMutations'; import { ORGANIZATION_USER_TAGS_LIST } from 'GraphQl/Queries/OrganizationQueries'; +import { TAGS_QUERY_DATA_CHUNK_SIZE } from 'utils/organizationTagsUtils'; export const MOCKS = [ { @@ -10,10 +8,9 @@ export const MOCKS = [ query: ORGANIZATION_USER_TAGS_LIST, variables: { id: '123', - after: null, - before: null, - first: 5, - last: null, + first: TAGS_QUERY_DATA_CHUNK_SIZE, + where: { name: { starts_with: '' } }, + sortedBy: { id: 'DESCENDING' }, }, }, result: { @@ -26,12 +23,14 @@ export const MOCKS = [ node: { _id: '1', name: 'userTag 1', + parentTag: null, usersAssignedTo: { totalCount: 5, }, childTags: { - totalCount: 5, + totalCount: 11, }, + ancestorTags: [], }, cursor: '1', }, @@ -39,12 +38,14 @@ export const MOCKS = [ node: { _id: '2', name: 'userTag 2', + parentTag: null, usersAssignedTo: { totalCount: 5, }, childTags: { totalCount: 0, }, + ancestorTags: [], }, cursor: '2', }, @@ -52,12 +53,14 @@ export const MOCKS = [ node: { _id: '3', name: 'userTag 3', + parentTag: null, usersAssignedTo: { totalCount: 0, }, childTags: { totalCount: 5, }, + ancestorTags: [], }, cursor: '3', }, @@ -65,12 +68,14 @@ export const MOCKS = [ node: { _id: '4', name: 'userTag 4', + parentTag: null, usersAssignedTo: { totalCount: 0, }, childTags: { totalCount: 0, }, + ancestorTags: [], }, cursor: '4', }, @@ -78,23 +83,100 @@ export const MOCKS = [ node: { _id: '5', name: 'userTag 5', + parentTag: null, usersAssignedTo: { totalCount: 5, }, childTags: { totalCount: 5, }, + ancestorTags: [], }, cursor: '5', }, + { + node: { + _id: '6', + name: 'userTag 6', + parentTag: null, + usersAssignedTo: { + totalCount: 6, + }, + childTags: { + totalCount: 6, + }, + ancestorTags: [], + }, + cursor: '6', + }, + { + node: { + _id: '7', + name: 'userTag 7', + parentTag: null, + usersAssignedTo: { + totalCount: 7, + }, + childTags: { + totalCount: 7, + }, + ancestorTags: [], + }, + cursor: '7', + }, + { + node: { + _id: '8', + name: 'userTag 8', + parentTag: null, + usersAssignedTo: { + totalCount: 8, + }, + childTags: { + totalCount: 8, + }, + ancestorTags: [], + }, + cursor: '8', + }, + { + node: { + _id: '9', + name: 'userTag 9', + parentTag: null, + usersAssignedTo: { + totalCount: 9, + }, + childTags: { + totalCount: 9, + }, + ancestorTags: [], + }, + cursor: '9', + }, + { + node: { + _id: '10', + name: 'userTag 10', + parentTag: null, + usersAssignedTo: { + totalCount: 10, + }, + childTags: { + totalCount: 10, + }, + ancestorTags: [], + }, + cursor: '10', + }, ], pageInfo: { startCursor: '1', - endCursor: '5', + endCursor: '10', hasNextPage: true, hasPreviousPage: false, }, - totalCount: 6, + totalCount: 12, }, }, ], @@ -106,10 +188,10 @@ export const MOCKS = [ query: ORGANIZATION_USER_TAGS_LIST, variables: { id: '123', - after: '5', - before: null, - first: 5, - last: null, + first: TAGS_QUERY_DATA_CHUNK_SIZE, + after: '10', + where: { name: { starts_with: '' } }, + sortedBy: { id: 'DESCENDING' }, }, }, result: { @@ -120,25 +202,42 @@ export const MOCKS = [ edges: [ { node: { - _id: '6', - name: 'userTag 6', + _id: '11', + name: 'userTag 11', + parentTag: null, usersAssignedTo: { - totalCount: 0, + totalCount: 5, + }, + childTags: { + totalCount: 5, + }, + ancestorTags: [], + }, + cursor: '11', + }, + { + node: { + _id: '12', + name: 'userTag 12', + parentTag: null, + usersAssignedTo: { + totalCount: 5, }, childTags: { totalCount: 0, }, + ancestorTags: [], }, - cursor: '6', + cursor: '12', }, ], pageInfo: { - startCursor: '6', - endCursor: '6', + startCursor: '11', + endCursor: '12', hasNextPage: false, hasPreviousPage: true, }, - totalCount: 6, + totalCount: 12, }, }, ], @@ -150,10 +249,9 @@ export const MOCKS = [ query: ORGANIZATION_USER_TAGS_LIST, variables: { id: '123', - after: null, - before: '6', - first: null, - last: 5, + first: TAGS_QUERY_DATA_CHUNK_SIZE, + where: { name: { starts_with: 'searchUserTag' } }, + sortedBy: { id: 'DESCENDING' }, }, }, result: { @@ -164,77 +262,130 @@ export const MOCKS = [ edges: [ { node: { - _id: '1', - name: 'userTag 1', + _id: 'searchUserTag1', + name: 'searchUserTag 1', + parentTag: { + _id: '1', + }, usersAssignedTo: { totalCount: 5, }, childTags: { totalCount: 5, }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], }, - cursor: '1', + cursor: 'searchUserTag1', }, { node: { - _id: '2', - name: 'userTag 2', + _id: 'searchUserTag2', + name: 'searchUserTag 2', + parentTag: { + _id: '1', + }, usersAssignedTo: { totalCount: 5, }, childTags: { totalCount: 0, }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], }, - cursor: '2', + cursor: 'searchUserTag2', }, + ], + pageInfo: { + startCursor: 'searchUserTag1', + endCursor: 'searchUserTag2', + hasNextPage: false, + hasPreviousPage: false, + }, + totalCount: 2, + }, + }, + ], + }, + }, + }, + { + request: { + query: ORGANIZATION_USER_TAGS_LIST, + variables: { + id: '123', + first: TAGS_QUERY_DATA_CHUNK_SIZE, + where: { name: { starts_with: 'searchUserTag' } }, + sortedBy: { id: 'ASCENDING' }, + }, + }, + result: { + data: { + organizations: [ + { + userTags: { + edges: [ { node: { - _id: '3', - name: 'userTag 3', + _id: 'searchUserTag2', + name: 'searchUserTag 2', + parentTag: { + _id: '1', + }, usersAssignedTo: { - totalCount: 0, + totalCount: 5, }, childTags: { totalCount: 5, }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], }, - cursor: '3', + cursor: 'searchUserTag2', }, { node: { - _id: '4', - name: 'userTag 4', - usersAssignedTo: { - totalCount: 0, - }, - childTags: { - totalCount: 0, + _id: 'searchUserTag1', + name: 'searchUserTag 1', + parentTag: { + _id: '1', }, - }, - cursor: '4', - }, - { - node: { - _id: '5', - name: 'userTag 5', usersAssignedTo: { totalCount: 5, }, childTags: { - totalCount: 5, + totalCount: 0, }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], }, - cursor: '5', + cursor: 'searchUserTag1', }, ], pageInfo: { - startCursor: '1', - endCursor: '5', - hasNextPage: true, + startCursor: 'searchUserTag2', + endCursor: 'searchUserTag1', + hasNextPage: false, hasPreviousPage: false, }, - totalCount: 6, + totalCount: 2, }, }, ], @@ -245,29 +396,14 @@ export const MOCKS = [ request: { query: CREATE_USER_TAG, variables: { - name: '7', + name: 'userTag 12', organizationId: '123', }, }, result: { data: { createUserTag: { - _id: '7', - }, - }, - }, - }, - { - request: { - query: REMOVE_USER_TAG, - variables: { - id: '1', - }, - }, - result: { - data: { - removeUserTag: { - _id: '1', + _id: '12', }, }, }, @@ -280,10 +416,9 @@ export const MOCKS_ERROR = [ query: ORGANIZATION_USER_TAGS_LIST, variables: { id: '123', - after: null, - before: null, - first: 5, - last: null, + first: TAGS_QUERY_DATA_CHUNK_SIZE, + where: { name: { starts_with: '' } }, + sortedBy: { id: 'DESCENDING' }, }, }, error: new Error('Mock Graphql Error'), diff --git a/src/screens/SubTags/SubTags.module.css b/src/screens/SubTags/SubTags.module.css index 2fed58ec52..0a210bdfa4 100644 --- a/src/screens/SubTags/SubTags.module.css +++ b/src/screens/SubTags/SubTags.module.css @@ -135,3 +135,11 @@ font-weight: 600; text-decoration: underline; } + +.subTagsScrollableDiv { + scrollbar-width: auto; + scrollbar-color: var(--bs-gray-400) var(--bs-white); + + max-height: calc(100vh - 18rem); + overflow: auto; +} diff --git a/src/screens/SubTags/SubTags.test.tsx b/src/screens/SubTags/SubTags.test.tsx index 1780027639..145d31109d 100644 --- a/src/screens/SubTags/SubTags.test.tsx +++ b/src/screens/SubTags/SubTags.test.tsx @@ -4,6 +4,7 @@ import type { RenderResult } from '@testing-library/react'; import { act, cleanup, + fireEvent, render, screen, waitFor, @@ -19,11 +20,7 @@ import { store } from 'state/store'; import { StaticMockLink } from 'utils/StaticMockLink'; import i18n from 'utils/i18nForTest'; import SubTags from './SubTags'; -import { - MOCKS, - MOCKS_ERROR_SUB_TAGS, - MOCKS_ERROR_TAG_ANCESTORS, -} from './SubTagsMocks'; +import { MOCKS, MOCKS_ERROR_SUB_TAGS } from './SubTagsMocks'; import { InMemoryCache, type ApolloLink } from '@apollo/client'; const translations = { @@ -38,7 +35,6 @@ const translations = { const link = new StaticMockLink(MOCKS, true); const link2 = new StaticMockLink(MOCKS_ERROR_SUB_TAGS, true); -const link3 = new StaticMockLink(MOCKS_ERROR_TAG_ANCESTORS, true); async function wait(ms = 500): Promise { await act(() => { @@ -60,9 +56,21 @@ const cache = new InMemoryCache({ Query: { fields: { getUserTag: { - keyArgs: false, merge(existing = {}, incoming) { - return incoming; + const merged = { + ...existing, + ...incoming, + childTags: { + ...existing.childTags, + ...incoming.childTags, + edges: [ + ...(existing.childTags?.edges || []), + ...(incoming.childTags?.edges || []), + ], + }, + }; + + return merged; }, }, }, @@ -72,8 +80,8 @@ const cache = new InMemoryCache({ const renderSubTags = (link: ApolloLink): RenderResult => { return render( - - + + @@ -82,11 +90,11 @@ const renderSubTags = (link: ApolloLink): RenderResult => { element={
    } />
    } /> } /> @@ -131,16 +139,6 @@ describe('Organisation Tags Page', () => { }); }); - test('renders error component on unsuccessful userTag ancestors query', async () => { - const { queryByText } = renderSubTags(link3); - - await wait(); - - await waitFor(() => { - expect(queryByText(translations.addChildTag)).not.toBeInTheDocument(); - }); - }); - test('opens and closes the create tag modal', async () => { renderSubTags(link); @@ -163,28 +161,6 @@ describe('Organisation Tags Page', () => { ); }); - test('opens and closes the remove tag modal', async () => { - renderSubTags(link); - - await wait(); - - await waitFor(() => { - expect(screen.getAllByTestId('removeUserTagBtn')[0]).toBeInTheDocument(); - }); - userEvent.click(screen.getAllByTestId('removeUserTagBtn')[0]); - - await waitFor(() => { - return expect( - screen.findByTestId('removeUserTagModalCloseBtn'), - ).resolves.toBeInTheDocument(); - }); - userEvent.click(screen.getByTestId('removeUserTagModalCloseBtn')); - - await waitForElementToBeRemoved(() => - screen.queryByTestId('removeUserTagModalCloseBtn'), - ); - }); - test('navigates to manage tag screen after clicking manage tag option', async () => { renderSubTags(link); @@ -260,66 +236,134 @@ describe('Organisation Tags Page', () => { }); }); - test('paginates between different pages', async () => { + test('searchs for tags where the name matches the provided search input', async () => { + renderSubTags(link); + + await wait(); + + await waitFor(() => { + expect( + screen.getByPlaceholderText(translations.searchByName), + ).toBeInTheDocument(); + }); + const input = screen.getByPlaceholderText(translations.searchByName); + fireEvent.change(input, { target: { value: 'searchSubTag' } }); + + // should render the two searched tags from the mock data + // where name starts with "searchUserTag" + await waitFor(() => { + const buttons = screen.getAllByTestId('manageTagBtn'); + expect(buttons.length).toEqual(2); + }); + }); + + test('fetches the tags by the sort order, i.e. latest or oldest first', async () => { renderSubTags(link); await wait(); await waitFor(() => { - expect(screen.getByTestId('nextPagBtn')).toBeInTheDocument(); + expect( + screen.getByPlaceholderText(translations.searchByName), + ).toBeInTheDocument(); + }); + const input = screen.getByPlaceholderText(translations.searchByName); + fireEvent.change(input, { target: { value: 'searchSubTag' } }); + + // should render the two searched tags from the mock data + // where name starts with "searchUserTag" + await waitFor(() => { + expect(screen.getAllByTestId('tagName')[0]).toHaveTextContent( + 'searchSubTag 1', + ); + }); + + // now change the sorting order + await waitFor(() => { + expect(screen.getByTestId('sortTags')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('sortTags')); + + await waitFor(() => { + expect(screen.getByTestId('oldest')).toBeInTheDocument(); }); - userEvent.click(screen.getByTestId('nextPagBtn')); + userEvent.click(screen.getByTestId('oldest')); + // returns the tags in reverse order await waitFor(() => { - expect(screen.getAllByTestId('tagName')[0]).toHaveTextContent('subTag 6'); + expect(screen.getAllByTestId('tagName')[0]).toHaveTextContent( + 'searchSubTag 2', + ); }); await waitFor(() => { - expect(screen.getByTestId('previousPageBtn')).toBeInTheDocument(); + expect(screen.getByTestId('sortTags')).toBeInTheDocument(); }); - userEvent.click(screen.getByTestId('previousPageBtn')); + userEvent.click(screen.getByTestId('sortTags')); await waitFor(() => { - expect(screen.getAllByTestId('tagName')[0]).toHaveTextContent('subTag 1'); + expect(screen.getByTestId('latest')).toBeInTheDocument(); + }); + userEvent.click(screen.getByTestId('latest')); + + // reverse the order again + await waitFor(() => { + expect(screen.getAllByTestId('tagName')[0]).toHaveTextContent( + 'searchSubTag 1', + ); }); }); - test('adds a new sub tag to the current tag', async () => { - renderSubTags(link); + test('Fetches more sub tags with infinite scroll', async () => { + const { getByText } = renderSubTags(link); await wait(); await waitFor(() => { - expect(screen.getByTestId('addSubTagBtn')).toBeInTheDocument(); + expect(getByText(translations.addChildTag)).toBeInTheDocument(); }); - userEvent.click(screen.getByTestId('addSubTagBtn')); - userEvent.type( - screen.getByPlaceholderText(translations.tagNamePlaceholder), - 'subTag 7', - ); + const subTagsScrollableDiv = screen.getByTestId('subTagsScrollableDiv'); - userEvent.click(screen.getByTestId('addSubTagSubmitBtn')); + // Get the initial number of tags loaded + const initialSubTagsDataLength = + screen.getAllByTestId('manageTagBtn').length; + + // Set scroll position to the bottom + fireEvent.scroll(subTagsScrollableDiv, { + target: { scrollY: subTagsScrollableDiv.scrollHeight }, + }); await waitFor(() => { - expect(toast.success).toBeCalledWith(translations.tagCreationSuccess); + const finalSubTagsDataLength = + screen.getAllByTestId('manageTagBtn').length; + expect(finalSubTagsDataLength).toBeGreaterThan(initialSubTagsDataLength); + + expect(getByText(translations.addChildTag)).toBeInTheDocument(); }); }); - test('removes a sub tag', async () => { + test('adds a new sub tag to the current tag', async () => { renderSubTags(link); await wait(); await waitFor(() => { - expect(screen.getAllByTestId('removeUserTagBtn')[0]).toBeInTheDocument(); + expect(screen.getByTestId('addSubTagBtn')).toBeInTheDocument(); }); - userEvent.click(screen.getAllByTestId('removeUserTagBtn')[0]); + userEvent.click(screen.getByTestId('addSubTagBtn')); + + userEvent.type( + screen.getByPlaceholderText(translations.tagNamePlaceholder), + 'subTag 12', + ); - userEvent.click(screen.getByTestId('removeUserTagSubmitBtn')); + userEvent.click(screen.getByTestId('addSubTagSubmitBtn')); await waitFor(() => { - expect(toast.success).toBeCalledWith(translations.tagRemovalSuccess); + expect(toast.success).toHaveBeenCalledWith( + translations.tagCreationSuccess, + ); }); }); }); diff --git a/src/screens/SubTags/SubTags.tsx b/src/screens/SubTags/SubTags.tsx index b381c9f816..930232aaca 100644 --- a/src/screens/SubTags/SubTags.tsx +++ b/src/screens/SubTags/SubTags.tsx @@ -1,4 +1,4 @@ -import { useMutation, useQuery, type ApolloError } from '@apollo/client'; +import { useMutation, useQuery } from '@apollo/client'; import { Search, WarningAmberRounded } from '@mui/icons-material'; import SortIcon from '@mui/icons-material/Sort'; import Loader from 'components/Loader/Loader'; @@ -14,19 +14,22 @@ import Row from 'react-bootstrap/Row'; import { useTranslation } from 'react-i18next'; import { toast } from 'react-toastify'; import type { InterfaceQueryUserTagChildTags } from 'utils/interfaces'; -import styles from './SubTags.module.css'; +import styles from '../../style/app.module.css'; import { DataGrid } from '@mui/x-data-grid'; -import { dataGridStyle } from 'utils/organizationTagsUtils'; +import type { + InterfaceOrganizationSubTagsQuery, + SortedByType, +} from 'utils/organizationTagsUtils'; +import { + dataGridStyle, + TAGS_QUERY_DATA_CHUNK_SIZE, +} from 'utils/organizationTagsUtils'; import type { GridCellParams, GridColDef } from '@mui/x-data-grid'; import { Stack } from '@mui/material'; -import { - CREATE_USER_TAG, - REMOVE_USER_TAG, -} from 'GraphQl/Mutations/TagMutations'; -import { - USER_TAG_ANCESTORS, - USER_TAG_SUB_TAGS, -} from 'GraphQl/Queries/userTagQueries'; +import { CREATE_USER_TAG } from 'GraphQl/Mutations/TagMutations'; +import { USER_TAG_SUB_TAGS } from 'GraphQl/Queries/userTagQueries'; +import InfiniteScroll from 'react-infinite-scroll-component'; +import InfiniteScrollLoader from 'components/InfiniteScrollLoader/InfiniteScrollLoader'; /** * Component that renders the SubTags screen when the app navigates to '/orgtags/:orgId/subtags/:tagId'. @@ -47,16 +50,10 @@ function SubTags(): JSX.Element { const navigate = useNavigate(); - const [after, setAfter] = useState(null); - const [before, setBefore] = useState(null); - const [first, setFirst] = useState(5); - const [last, setLast] = useState(null); - const [tagName, setTagName] = useState(''); - const [removeUserTagId, setRemoveUserTagId] = useState(null); - const [removeUserTagModalIsOpen, setRemoveUserTagModalIsOpen] = - useState(false); + const [tagSearchName, setTagSearchName] = useState(''); + const [tagSortOrder, setTagSortOrder] = useState('DESCENDING'); const showAddSubTagModal = (): void => { setAddSubTagModalIsOpen(true); @@ -69,45 +66,50 @@ function SubTags(): JSX.Element { const { data: subTagsData, - loading: subTagsLoading, error: subTagsError, + loading: subTagsLoading, refetch: subTagsRefetch, - }: { - data?: { - getUserTag: InterfaceQueryUserTagChildTags; - }; - loading: boolean; - error?: ApolloError; - refetch: () => void; - } = useQuery(USER_TAG_SUB_TAGS, { + fetchMore: fetchMoreSubTags, + }: InterfaceOrganizationSubTagsQuery = useQuery(USER_TAG_SUB_TAGS, { variables: { id: parentTagId, - after: after, - before: before, - first: first, - last: last, + first: TAGS_QUERY_DATA_CHUNK_SIZE, + where: { name: { starts_with: tagSearchName } }, + sortedBy: { id: tagSortOrder }, }, }); - const { - data: orgUserTagAncestorsData, - loading: orgUserTagsAncestorsLoading, - error: orgUserTagsAncestorsError, - }: { - data?: { - getUserTagAncestors: { - _id: string; - name: string; - }[]; - }; - loading: boolean; - error?: ApolloError; - refetch: () => void; - } = useQuery(USER_TAG_ANCESTORS, { - variables: { - id: parentTagId, - }, - }); + const loadMoreSubTags = (): void => { + fetchMoreSubTags({ + variables: { + first: TAGS_QUERY_DATA_CHUNK_SIZE, + after: subTagsData?.getChildTags.childTags.pageInfo.endCursor, + }, + updateQuery: ( + prevResult: { getChildTags: InterfaceQueryUserTagChildTags }, + { + fetchMoreResult, + }: { + fetchMoreResult?: { getChildTags: InterfaceQueryUserTagChildTags }; + }, + ) => { + if (!fetchMoreResult) /* istanbul ignore next */ return prevResult; + + return { + getChildTags: { + ...fetchMoreResult.getChildTags, + childTags: { + ...fetchMoreResult.getChildTags.childTags, + edges: [ + ...prevResult.getChildTags.childTags.edges, + ...fetchMoreResult.getChildTags.childTags.edges, + ], + }, + }, + }; + }, + }); + }; const [create, { loading: createUserTagLoading }] = useMutation(CREATE_USER_TAG); @@ -139,81 +141,41 @@ function SubTags(): JSX.Element { } }; - const [removeUserTag] = useMutation(REMOVE_USER_TAG); - const handleRemoveUserTag = async (): Promise => { - try { - await removeUserTag({ - variables: { - id: removeUserTagId, - }, - }); - - subTagsRefetch(); - toggleRemoveUserTagModal(); - toast.success(t('tagRemovalSuccess') as string); - } catch (error: unknown) { - /* istanbul ignore next */ - if (error instanceof Error) { - toast.error(error.message); - } - } - }; - - if (createUserTagLoading || subTagsLoading || orgUserTagsAncestorsLoading) { - return ; - } - - const handleNextPage = (): void => { - setAfter(subTagsData?.getUserTag.childTags.pageInfo.endCursor); - setBefore(null); - setFirst(5); - setLast(null); - }; - - const handlePreviousPage = (): void => { - setBefore(subTagsData?.getUserTag.childTags.pageInfo.startCursor); - setAfter(null); - setFirst(null); - setLast(5); - }; - - if (subTagsError || orgUserTagsAncestorsError) { + if (subTagsError) { return (
    - Error occured while loading{' '} - {subTagsError ? 'sub tags' : 'tag ancestors'} -
    - {subTagsError - ? subTagsError.message - : orgUserTagsAncestorsError?.message} + Error occured while loading sub tags
    ); } - const userTagsList = subTagsData?.getUserTag.childTags.edges.map( - (edge) => edge.node, - ); + const subTagsList = + subTagsData?.getChildTags.childTags.edges.map((edge) => edge.node) ?? + /* istanbul ignore next */ []; - const orgUserTagAncestors = orgUserTagAncestorsData?.getUserTagAncestors; + const parentTagName = subTagsData?.getChildTags.name; + + // get the ancestorTags array and push the current tag in it + // used for the tag breadcrumbs + const orgUserTagAncestors = [ + ...(subTagsData?.getChildTags.ancestorTags ?? []), + { + _id: parentTagId, + name: parentTagName, + }, + ]; const redirectToManageTag = (tagId: string): void => { navigate(`/orgtags/${orgId}/manageTag/${tagId}`); }; const redirectToSubTags = (tagId: string): void => { - navigate(`/orgtags/${orgId}/subtags/${tagId}`); - }; - - const toggleRemoveUserTagModal = (): void => { - if (removeUserTagModalIsOpen) { - setRemoveUserTagId(null); - } - setRemoveUserTagModalIsOpen(!removeUserTagModalIsOpen); + navigate(`/orgtags/${orgId}/subTags/${tagId}`); }; const columns: GridColDef[] = [ @@ -263,7 +225,7 @@ function SubTags(): JSX.Element { return ( {params.row.childTags.totalCount} @@ -283,7 +245,7 @@ function SubTags(): JSX.Element { return ( {params.row.usersAssignedTo.totalCount} @@ -301,28 +263,14 @@ function SubTags(): JSX.Element { headerClassName: `${styles.tableHeader}`, renderCell: (params: GridCellParams) => { return ( -
    - - - -
    + ); }, }, @@ -330,153 +278,159 @@ function SubTags(): JSX.Element { return ( <> - -
    -
    -
    + +
    +
    +
    setTagSearchName(e.target.value.trim())} data-testid="searchByName" autoComplete="off" - required />
    -
    - + {tCommon('Latest')} + + setTagSortOrder('ASCENDING')} + > + {tCommon('Oldest')} + + + - + - -
    +
    -
    -
    -
    - -
    - -
    navigate(`/orgtags/${orgId}`)} - className={`fs-6 ms-3 my-1 ${styles.tagsBreadCrumbs}`} - data-testid="allTagsBtn" - > - {'Tags'} - -
    + {subTagsLoading || createUserTagLoading ? ( + + ) : ( +
    +
    +
    + +
    - {orgUserTagAncestors?.map((tag, index) => (
    redirectToSubTags(tag._id as string)} - data-testid="redirectToSubTags" + onClick={() => navigate(`/orgtags/${orgId}`)} + className={`fs-6 ms-3 my-1 ${styles.tagsBreadCrumbs}`} + data-testid="allTagsBtn" > - {tag.name} - - {orgUserTagAncestors.length - 1 !== index && ( - - )} + {'Tags'} +
    - ))} -
    - row._id} - slots={{ - noRowsOverlay: /* istanbul ignore next */ () => ( - ( +
    redirectToSubTags(tag._id as string)} + data-testid="redirectToSubTags" > - {t('noTagsFound')} - - ), - }} - sx={dataGridStyle} - getRowClassName={() => `${styles.rowBackground}`} - autoHeight - rowHeight={65} - rows={userTagsList?.map((fund, index) => ({ - id: index + 1, - ...fund, - }))} - columns={columns} - isRowSelectable={() => false} - /> -
    -
    + {tag.name} -
    -
    - -
    -
    - -
    + {orgUserTagAncestors.length - 1 !== index && ( + + )} +
    + ))} +
    +
    + } + scrollableTarget="subTagsScrollableDiv" + > + row.id} + slots={{ + noRowsOverlay: /* istanbul ignore next */ () => ( + + {t('noTagsFound')} + + ), + }} + sx={dataGridStyle} + getRowClassName={() => `${styles.rowBackground}`} + autoHeight + rowHeight={65} + rows={subTagsList?.map((subTag, index) => ({ + id: index + 1, + ...subTag, + }))} + columns={columns} + isRowSelectable={() => false} + /> + +
    +
    + )}
    @@ -489,11 +443,11 @@ function SubTags(): JSX.Element { centered > - {t('tagDetails')} + {t('tagDetails')}
    @@ -518,53 +472,21 @@ function SubTags(): JSX.Element { variant="secondary" onClick={(): void => hideAddSubTagModal()} data-testid="addSubTagModalCloseBtn" + className={styles.closeButton} > {tCommon('cancel')} - - - {/* Remove User Tag Modal */} - - - - {t('removeUserTag')} - - - {t('removeUserTagMessage')} - - - - - ); } diff --git a/src/screens/SubTags/SubTagsMocks.ts b/src/screens/SubTags/SubTagsMocks.ts index 757f3f42ad..5165ea3a53 100644 --- a/src/screens/SubTags/SubTagsMocks.ts +++ b/src/screens/SubTags/SubTagsMocks.ts @@ -1,33 +1,27 @@ -import { - CREATE_USER_TAG, - REMOVE_USER_TAG, -} from 'GraphQl/Mutations/TagMutations'; -import { - USER_TAG_ANCESTORS, - USER_TAG_SUB_TAGS, -} from 'GraphQl/Queries/userTagQueries'; +import { CREATE_USER_TAG } from 'GraphQl/Mutations/TagMutations'; +import { USER_TAG_SUB_TAGS } from 'GraphQl/Queries/userTagQueries'; +import { TAGS_QUERY_DATA_CHUNK_SIZE } from 'utils/organizationTagsUtils'; export const MOCKS = [ { request: { query: USER_TAG_SUB_TAGS, variables: { - id: 'tag1', - after: null, - before: null, - first: 5, - last: null, + id: '1', + first: TAGS_QUERY_DATA_CHUNK_SIZE, + where: { name: { starts_with: '' } }, + sortedBy: { id: 'DESCENDING' }, }, }, result: { data: { - getUserTag: { - name: 'tag1', + getChildTags: { + name: 'userTag 1', childTags: { edges: [ { node: { - _id: '1', + _id: 'subTag1', name: 'subTag 1', usersAssignedTo: { totalCount: 5, @@ -35,12 +29,18 @@ export const MOCKS = [ childTags: { totalCount: 5, }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], }, - cursor: '1', + cursor: 'subTag1', }, { node: { - _id: '2', + _id: 'subTag2', name: 'subTag 2', usersAssignedTo: { totalCount: 5, @@ -48,12 +48,18 @@ export const MOCKS = [ childTags: { totalCount: 0, }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], }, - cursor: '2', + cursor: 'subTag2', }, { node: { - _id: '3', + _id: 'subTag3', name: 'subTag 3', usersAssignedTo: { totalCount: 0, @@ -61,12 +67,18 @@ export const MOCKS = [ childTags: { totalCount: 5, }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], }, - cursor: '3', + cursor: 'subTag3', }, { node: { - _id: '4', + _id: 'subTag4', name: 'subTag 4', usersAssignedTo: { totalCount: 0, @@ -74,12 +86,18 @@ export const MOCKS = [ childTags: { totalCount: 0, }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], }, - cursor: '4', + cursor: 'subTag4', }, { node: { - _id: '5', + _id: 'subTag5', name: 'subTag 5', usersAssignedTo: { totalCount: 5, @@ -87,18 +105,120 @@ export const MOCKS = [ childTags: { totalCount: 5, }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], + }, + cursor: 'subTag5', + }, + { + node: { + _id: 'subTag6', + name: 'subTag 6', + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 5, + }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], + }, + cursor: 'subTag6', + }, + { + node: { + _id: 'subTag7', + name: 'subTag 7', + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 5, + }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], + }, + cursor: 'subTag7', + }, + { + node: { + _id: 'subTag8', + name: 'subTag 8', + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 5, + }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], + }, + cursor: 'subTag8', + }, + { + node: { + _id: 'subTag9', + name: 'subTag 9', + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 5, + }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], + }, + cursor: 'subTag9', + }, + { + node: { + _id: 'subTag10', + name: 'subTag 10', + usersAssignedTo: { + totalCount: 5, + }, + childTags: { + totalCount: 5, + }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], }, - cursor: '5', + cursor: 'subTag10', }, ], pageInfo: { startCursor: '1', - endCursor: '5', + endCursor: '10', hasNextPage: true, hasPreviousPage: false, }, - totalCount: 6, + totalCount: 11, }, + ancestorTags: [], }, }, }, @@ -107,41 +227,48 @@ export const MOCKS = [ request: { query: USER_TAG_SUB_TAGS, variables: { - id: 'tag1', - after: '5', - before: null, - first: 5, - last: null, + id: '1', + after: '10', + first: TAGS_QUERY_DATA_CHUNK_SIZE, + where: { name: { starts_with: '' } }, + sortedBy: { id: 'DESCENDING' }, }, }, result: { data: { - getUserTag: { - name: 'tag1', + getChildTags: { + name: 'userTag 1', childTags: { edges: [ { node: { - _id: '6', - name: 'subTag 6', + _id: 'subTag11', + name: 'subTag 11', usersAssignedTo: { totalCount: 0, }, childTags: { totalCount: 0, }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], }, - cursor: '6', + cursor: 'subTag11', }, ], pageInfo: { - startCursor: '6', - endCursor: '6', + startCursor: '11', + endCursor: '11', hasNextPage: false, hasPreviousPage: true, }, - totalCount: 6, + totalCount: 11, }, + ancestorTags: [], }, }, }, @@ -150,93 +277,124 @@ export const MOCKS = [ request: { query: USER_TAG_SUB_TAGS, variables: { - id: 'tag1', - after: null, - before: '6', - first: null, - last: 5, + id: 'subTag1', + first: TAGS_QUERY_DATA_CHUNK_SIZE, + where: { name: { starts_with: '' } }, + sortedBy: { id: 'DESCENDING' }, }, }, result: { data: { - getUserTag: { - name: 'tag1', + getChildTags: { + name: 'subTag 1', childTags: { edges: [ { node: { - _id: '1', - name: 'subTag 1', + _id: 'subTag1.1', + name: 'subTag 1.1', usersAssignedTo: { totalCount: 5, }, childTags: { totalCount: 5, }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + { + _id: 'subTag1', + name: 'subTag 1', + }, + ], }, - cursor: '1', - }, - { - node: { - _id: '2', - name: 'subTag 2', - usersAssignedTo: { - totalCount: 5, - }, - childTags: { - totalCount: 0, - }, - }, - cursor: '2', + cursor: 'subTag1.1', }, + ], + pageInfo: { + startCursor: 'subTag1.1', + endCursor: 'subTag1.1', + hasNextPage: false, + hasPreviousPage: false, + }, + totalCount: 1, + }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], + }, + }, + }, + }, + { + request: { + query: USER_TAG_SUB_TAGS, + variables: { + id: '1', + first: TAGS_QUERY_DATA_CHUNK_SIZE, + where: { name: { starts_with: 'searchSubTag' } }, + sortedBy: { id: 'DESCENDING' }, + }, + }, + result: { + data: { + getChildTags: { + name: 'userTag 1', + childTags: { + edges: [ { node: { - _id: '3', - name: 'subTag 3', + _id: 'searchSubTag1', + name: 'searchSubTag 1', usersAssignedTo: { totalCount: 0, }, childTags: { - totalCount: 5, + totalCount: 0, }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], }, - cursor: '3', + cursor: 'searchSubTag1', }, { node: { - _id: '4', - name: 'subTag 4', + _id: 'searchSubTag2', + name: 'searchSubTag 2', usersAssignedTo: { totalCount: 0, }, childTags: { totalCount: 0, }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], }, - cursor: '4', - }, - { - node: { - _id: '5', - name: 'subTag 5', - usersAssignedTo: { - totalCount: 5, - }, - childTags: { - totalCount: 5, - }, - }, - cursor: '5', + cursor: 'searchSubTag2', }, ], pageInfo: { - startCursor: '1', - endCursor: '5', - hasNextPage: true, + startCursor: 'searchSubTag1', + endCursor: 'searchSubTag2', + hasNextPage: false, hasPreviousPage: false, }, - totalCount: 6, + totalCount: 2, }, + ancestorTags: [], }, }, }, @@ -246,98 +404,82 @@ export const MOCKS = [ query: USER_TAG_SUB_TAGS, variables: { id: '1', - after: null, - before: null, - first: 5, - last: null, + first: TAGS_QUERY_DATA_CHUNK_SIZE, + where: { name: { starts_with: 'searchSubTag' } }, + sortedBy: { id: 'ASCENDING' }, }, }, result: { data: { - getUserTag: { - name: 'subTag 1', + getChildTags: { + name: 'userTag 1', childTags: { - edges: [], + edges: [ + { + node: { + _id: 'searchSubTag2', + name: 'searchSubTag 2', + usersAssignedTo: { + totalCount: 0, + }, + childTags: { + totalCount: 0, + }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], + }, + cursor: 'searchSubTag2', + }, + { + node: { + _id: 'searchSubTag1', + name: 'searchSubTag 1', + usersAssignedTo: { + totalCount: 0, + }, + childTags: { + totalCount: 0, + }, + ancestorTags: [ + { + _id: '1', + name: 'userTag 1', + }, + ], + }, + cursor: 'searchSubTag1', + }, + ], pageInfo: { - startCursor: null, - endCursor: null, + startCursor: 'searchSubTag2', + endCursor: 'searchSubTag1', hasNextPage: false, hasPreviousPage: false, }, - totalCount: 0, + totalCount: 2, }, + ancestorTags: [], }, }, }, }, - { - request: { - query: USER_TAG_ANCESTORS, - variables: { - id: 'tag1', - }, - }, - result: { - data: { - getUserTagAncestors: [ - { - _id: '1', - name: 'tag1', - }, - ], - }, - }, - }, - { - request: { - query: USER_TAG_ANCESTORS, - variables: { - id: '1', - }, - }, - result: { - data: { - getUserTagAncestors: [ - { - _id: 'tag1', - name: 'tag 1', - }, - { - _id: '1', - name: 'subTag 1', - }, - ], - }, - }, - }, { request: { query: CREATE_USER_TAG, variables: { - name: 'subTag 7', + name: 'subTag 12', organizationId: '123', - parentTagId: 'tag1', + parentTagId: '1', }, }, result: { data: { createUserTag: { - _id: '7', - }, - }, - }, - }, - { - request: { - query: REMOVE_USER_TAG, - variables: { - id: '1', - }, - }, - result: { - data: { - removeUserTag: { - _id: '1', + _id: 'subTag12', }, }, }, @@ -349,65 +491,10 @@ export const MOCKS_ERROR_SUB_TAGS = [ request: { query: USER_TAG_SUB_TAGS, variables: { - id: 'tag1', - after: null, - before: null, - first: 5, - last: null, - }, - }, - error: new Error('Mock Graphql Error'), - }, - { - request: { - query: USER_TAG_ANCESTORS, - variables: { - id: 'tag1', - }, - }, - result: { - data: { - getUserTagAncestors: [], - }, - }, - }, -]; - -export const MOCKS_ERROR_TAG_ANCESTORS = [ - { - request: { - query: USER_TAG_SUB_TAGS, - variables: { - id: 'tag1', - after: null, - before: null, - first: 5, - last: null, - }, - }, - result: { - data: { - getUserTag: { - name: 'tag1', - childTags: { - edges: [], - pageInfo: { - startCursor: '1', - endCursor: '5', - hasNextPage: true, - hasPreviousPage: false, - }, - totalCount: 6, - }, - }, - }, - }, - }, - { - request: { - query: USER_TAG_ANCESTORS, - variables: { - id: 'tag1', + id: '1', + first: TAGS_QUERY_DATA_CHUNK_SIZE, + where: { name: { starts_with: '' } }, + sortedBy: { id: 'DESCENDING' }, }, }, error: new Error('Mock Graphql Error'), diff --git a/src/screens/UserPortal/Campaigns/PledgeModal.test.tsx b/src/screens/UserPortal/Campaigns/PledgeModal.test.tsx index 3f299c5c48..b9fd7a7d4d 100644 --- a/src/screens/UserPortal/Campaigns/PledgeModal.test.tsx +++ b/src/screens/UserPortal/Campaigns/PledgeModal.test.tsx @@ -53,7 +53,7 @@ const pledgeProps: InterfacePledgeModal[] = [ _id: '1', firstName: 'John', lastName: 'Doe', - image: null, + image: undefined, }, ], }, @@ -77,7 +77,7 @@ const pledgeProps: InterfacePledgeModal[] = [ _id: '1', firstName: 'John', lastName: 'Doe', - image: null, + image: undefined, }, ], }, diff --git a/src/screens/UserPortal/Campaigns/PledgeModal.tsx b/src/screens/UserPortal/Campaigns/PledgeModal.tsx index d9076f52c8..44cc82401b 100644 --- a/src/screens/UserPortal/Campaigns/PledgeModal.tsx +++ b/src/screens/UserPortal/Campaigns/PledgeModal.tsx @@ -6,7 +6,7 @@ import { currencyOptions, currencySymbols } from 'utils/currency'; import type { InterfaceCreatePledge, InterfacePledgeInfo, - InterfacePledger, + InterfaceUserInfo, } from 'utils/interfaces'; import styles from './Campaigns.module.css'; import React, { useCallback, useEffect, useState } from 'react'; @@ -77,7 +77,7 @@ const PledgeModal: React.FC = ({ }); // State to manage the list of pledgers (users who are part of the pledge) - const [pledgers, setPledgers] = useState([]); + const [pledgers, setPledgers] = useState([]); // Mutation to update an existing pledge const [updatePledge] = useMutation(UPDATE_PLEDGE); @@ -252,7 +252,7 @@ const PledgeModal: React.FC = ({ readOnly={mode === 'edit' ? true : false} isOptionEqualToValue={(option, value) => option._id === value._id} filterSelectedOptions={true} - getOptionLabel={(member: InterfacePledger): string => + getOptionLabel={(member: InterfaceUserInfo): string => `${member.firstName} ${member.lastName}` } onChange={ diff --git a/src/screens/UserPortal/Chat/Chat.module.css b/src/screens/UserPortal/Chat/Chat.module.css index 3600f6720b..5f9a672dea 100644 --- a/src/screens/UserPortal/Chat/Chat.module.css +++ b/src/screens/UserPortal/Chat/Chat.module.css @@ -78,9 +78,11 @@ border-bottom: 2px solid black; } -.contactListContainer { - /* flex-grow: 1; */ - /* margin: 15px 10px; */ +.contactCardContainer { + padding: 10px 15px; + display: flex; + flex-direction: column; + gap: 5px; } .chatHeadingContainer { diff --git a/src/screens/UserPortal/Chat/Chat.test.tsx b/src/screens/UserPortal/Chat/Chat.test.tsx index 4a0dfbcf4e..660eeaa236 100644 --- a/src/screens/UserPortal/Chat/Chat.test.tsx +++ b/src/screens/UserPortal/Chat/Chat.test.tsx @@ -1,657 +1,28 @@ -import React, { act } from 'react'; -import { fireEvent, render, screen, waitFor } from '@testing-library/react'; -import { MockedProvider } from '@apollo/react-testing'; -import { I18nextProvider, useTranslation } from 'react-i18next'; - -import { - DIRECT_CHATS_LIST, - USERS_CONNECTION_LIST, - USER_JOINED_ORGANIZATIONS, -} from 'GraphQl/Queries/Queries'; -import { BrowserRouter } from 'react-router-dom'; -import { Provider } from 'react-redux'; -import { store } from 'state/store'; -import i18nForTest from 'utils/i18nForTest'; -import Chat from './Chat'; -import { - MESSAGE_SENT_TO_DIRECT_CHAT, - MESSAGE_SENT_TO_GROUP_CHAT, -} from 'GraphQl/Mutations/OrganizationMutations'; -import { - DIRECT_CHAT_BY_ID, - GROUP_CHAT_BY_ID, - GROUP_CHAT_LIST, -} from 'GraphQl/Queries/PlugInQueries'; -import useLocalStorage from 'utils/useLocalstorage'; - -const { setItem } = useLocalStorage(); - -const MOCKS = [ - { - request: { - query: GROUP_CHAT_LIST, - variables: { - id: null, - }, - }, - result: { - data: { - groupChatsByUserId: [ - { - _id: '1', - creator: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - }, - messages: { - _id: '1', - createdAt: '', - messageContent: 'Hello', - sender: { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@email.com', - }, - }, - title: 'Test GroupChat', - organization: { - _id: '1', - name: 'Test Org', - }, - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@email.com', - image: 'img', - }, - ], - }, - { - _id: '2', - creator: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - }, - messages: { - _id: '1', - createdAt: '', - messageContent: 'Hello', - sender: { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@email.com', - }, - }, - title: 'Test GroupChat', - organization: { - _id: '1', - name: 'Test Org', - }, - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@email.com', - image: 'img', - }, - ], - }, - ], - }, - }, - }, - { - request: { - query: GROUP_CHAT_LIST, - variables: { - id: '1', - }, - }, - result: { - data: { - groupChatsByUserId: [ - { - _id: '1', - creator: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - }, - messages: { - _id: '1', - createdAt: '', - messageContent: 'Hello', - sender: { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@email.com', - }, - }, - title: 'Test GroupChat', - organization: { - _id: '1', - name: 'Test Org', - }, - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@email.com', - image: 'img', - }, - ], - }, - { - _id: '2', - creator: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - }, - messages: { - _id: '1', - createdAt: '', - messageContent: 'Hello', - sender: { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@email.com', - }, - }, - title: 'Test GroupChat', - organization: { - _id: '1', - name: 'Test Org', - }, - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@email.com', - image: 'img', - }, - ], - }, - ], - }, - }, - }, - { - request: { - query: GROUP_CHAT_LIST, - variables: { - id: null, - }, - }, - result: { - data: { - groupChatsByUserId: [ - { - _id: '1', - creator: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - }, - messages: { - _id: '1', - createdAt: '', - messageContent: 'Hello', - sender: { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@email.com', - }, - }, - title: 'Test GroupChat', - organization: { - _id: '1', - name: 'Test Org', - }, - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@email.com', - image: 'img', - }, - ], - }, - { - _id: '1', - creator: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - }, - messages: { - _id: '1', - createdAt: '', - messageContent: 'Hello', - sender: { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@email.com', - }, - }, - title: 'Test GroupChat', - organization: { - _id: '1', - name: 'Test Org', - }, - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@email.com', - image: 'img', - }, - ], - }, - ], - }, - }, - }, - { - request: { - query: DIRECT_CHATS_LIST, - variables: { - id: null, - }, - }, - result: { - data: { - directChatsByUserID: [ - { - _id: '666c88dd92e995354d98527c', - creator: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - __typename: 'User', - }, - messages: [ - { - _id: '668930bae43ce54e6e302cf1', - createdAt: '2024-07-06T11:55:38.933Z', - messageContent: 'hJnkank', - receiver: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - __typename: 'User', - }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - __typename: 'User', - }, - __typename: 'DirectChatMessage', - }, - ], - organization: { - _id: '6737904485008f171cf29924', - name: 'Unity Foundation', - __typename: 'Organization', - }, - users: [ - { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - image: null, - __typename: 'User', - }, - { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - image: null, - __typename: 'User', - }, - ], - __typename: 'DirectChat', - }, - { - _id: '666f09c892e995354d98a5ee', - creator: { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - __typename: 'User', - }, - messages: [ - { - _id: '6676932692e995354d98ab7f', - createdAt: '2024-06-22T09:02:30.776Z', - messageContent: 'hii', - receiver: { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - __typename: 'User', - }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - __typename: 'User', - }, - __typename: 'DirectChatMessage', - }, - ], - organization: { - _id: '6737904485008f171cf29924', - name: 'Unity Foundation', - __typename: 'Organization', - }, - users: [ - { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - image: null, - __typename: 'User', - }, - { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - image: null, - __typename: 'User', - }, - ], - __typename: 'DirectChat', - }, - ], - }, - }, - }, - { - request: { - query: DIRECT_CHATS_LIST, - variables: { - id: '1', - }, - }, - result: { - data: { - directChatsByUserID: [ - { - _id: '666c88dd92e995354d98527c', - creator: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - __typename: 'User', - }, - messages: [ - { - _id: '668930bae43ce54e6e302cf1', - createdAt: '2024-07-06T11:55:38.933Z', - messageContent: 'hJnkank', - receiver: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - __typename: 'User', - }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - __typename: 'User', - }, - __typename: 'DirectChatMessage', - }, - ], - organization: { - _id: '6737904485008f171cf29924', - name: 'Unity Foundation', - __typename: 'Organization', - }, - users: [ - { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - image: null, - __typename: 'User', - }, - { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - image: null, - __typename: 'User', - }, - ], - __typename: 'DirectChat', - }, - { - _id: '666f09c892e995354d98a5ee', - creator: { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - __typename: 'User', - }, - messages: [ - { - _id: '6676932692e995354d98ab7f', - createdAt: '2024-06-22T09:02:30.776Z', - messageContent: 'hii', - receiver: { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - __typename: 'User', - }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - __typename: 'User', - }, - __typename: 'DirectChatMessage', - }, - ], - organization: { - _id: '6737904485008f171cf29924', - name: 'Unity Foundation', - __typename: 'Organization', - }, - users: [ - { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - image: null, - __typename: 'User', - }, - { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - image: null, - __typename: 'User', - }, - ], - __typename: 'DirectChat', - }, - ], - }, - }, - }, - { - request: { - query: DIRECT_CHATS_LIST, - variables: { - id: '', - }, - }, - result: { - data: { - directChatsByUserID: [ - { - _id: '666c88dd92e995354d98527c', - creator: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - __typename: 'User', - }, - messages: [ - { - _id: '668930bae43ce54e6e302cf1', - createdAt: '2024-07-06T11:55:38.933Z', - messageContent: 'hJnkank', - receiver: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - __typename: 'User', - }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - __typename: 'User', - }, - __typename: 'DirectChatMessage', - }, - ], - organization: { - _id: '6737904485008f171cf29924', - name: 'Unity Foundation', - __typename: 'Organization', - }, - users: [ - { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - image: null, - __typename: 'User', - }, - { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - email: 'testadmin1@example.com', - image: null, - __typename: 'User', - }, - ], - __typename: 'DirectChat', - }, - { - _id: '666f09c892e995354d98a5ee', - creator: { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - __typename: 'User', - }, - messages: [ - { - _id: '6676932692e995354d98ab7f', - createdAt: '2024-06-22T09:02:30.776Z', - messageContent: 'hii', - receiver: { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - __typename: 'User', - }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - __typename: 'User', - }, - __typename: 'DirectChatMessage', - }, - ], - organization: { - _id: '6737904485008f171cf29924', - name: 'Unity Foundation', - __typename: 'Organization', - }, - users: [ - { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - email: 'testsuperadmin@example.com', - image: null, - __typename: 'User', - }, - { - _id: '67378abd85008f171cf2990d', - firstName: 'Darcy', - lastName: 'Wilf', - email: 'testadmin3@example.com', - image: null, - __typename: 'User', - }, - ], - __typename: 'DirectChat', - }, - ], - }, - }, - }, -]; +import React from 'react'; +import { + act, + fireEvent, + render, + screen, + waitFor, +} from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider } from 'react-i18next'; + +import { + USERS_CONNECTION_LIST, + USER_JOINED_ORGANIZATIONS, +} from 'GraphQl/Queries/Queries'; +import { BrowserRouter } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; +import Chat from './Chat'; +import useLocalStorage from 'utils/useLocalstorage'; +import { MESSAGE_SENT_TO_CHAT } from 'GraphQl/Mutations/OrganizationMutations'; +import { CHATS_LIST, CHAT_BY_ID } from 'GraphQl/Queries/PlugInQueries'; + +const { setItem } = useLocalStorage(); const USER_JOINED_ORG_MOCK = [ { @@ -1291,20 +662,22 @@ const UserConnectionListMock = [ }, ]; -const MESSAGE_SENT_TO_GROUP_CHAT_MOCK = [ +const MESSAGE_SENT_TO_CHAT_MOCK = [ { request: { - query: MESSAGE_SENT_TO_GROUP_CHAT, + query: MESSAGE_SENT_TO_CHAT, variables: { userId: null, }, }, result: { data: { - messageSentToGroupChat: { + messageSentToChat: { _id: '668ec1f1364e03ac47a151', createdAt: '2024-07-10T17:16:33.248Z', messageContent: 'Test ', + type: 'STRING', + replyTo: null, sender: { _id: '64378abd85008f171cf2990d', firstName: 'Wilt', @@ -1318,17 +691,19 @@ const MESSAGE_SENT_TO_GROUP_CHAT_MOCK = [ }, { request: { - query: MESSAGE_SENT_TO_GROUP_CHAT, + query: MESSAGE_SENT_TO_CHAT, variables: { userId: '2', }, }, result: { data: { - messageSentToGroupChat: { + messageSentToChat: { _id: '668ec1f1df364e03ac47a151', createdAt: '2024-07-10T17:16:33.248Z', messageContent: 'Test ', + replyTo: null, + type: 'STRING', sender: { _id: '64378abd85008f171cf2990d', firstName: 'Wilt', @@ -1342,17 +717,19 @@ const MESSAGE_SENT_TO_GROUP_CHAT_MOCK = [ }, { request: { - query: MESSAGE_SENT_TO_GROUP_CHAT, + query: MESSAGE_SENT_TO_CHAT, variables: { userId: '1', }, }, result: { data: { - messageSentToGroupChat: { + messageSentToChat: { _id: '668ec1f13603ac4697a151', createdAt: '2024-07-10T17:16:33.248Z', messageContent: 'Test ', + replyTo: null, + type: 'STRING', sender: { _id: '64378abd85008f171cf2990d', firstName: 'Wilt', @@ -1366,283 +743,38 @@ const MESSAGE_SENT_TO_GROUP_CHAT_MOCK = [ }, ]; -const MESSAGE_SENT_TO_DIRECT_CHAT_MOCK = [ - { - request: { - query: MESSAGE_SENT_TO_DIRECT_CHAT, - variables: { - userId: '1', - }, - }, - result: { - data: { - messageSentToDirectChat: { - _id: '668ec1f1364e03ac4697a151', - createdAt: '2024-07-10T17:16:33.248Z', - messageContent: 'Test ', - receiver: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - image: '', - }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - image: '', - }, - updatedAt: '2024-07-10', - }, - }, - }, - }, - { - request: { - query: MESSAGE_SENT_TO_DIRECT_CHAT, - variables: { - userId: '2', - }, - }, - result: { - data: { - messageSentToDirectChat: { - _id: '668ec1f1364e03ac4697vgfa151', - createdAt: '2024-07-10T17:16:33.248Z', - messageContent: 'Test ', - receiver: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - image: '', - }, - sender: { - _id: '64378abd85008f171cf2990d', - firstName: 'Wilt', - lastName: 'Shepherd', - image: '', - }, - updatedAt: '2024-07-10', - }, - }, - }, - }, +const CHAT_BY_ID_QUERY_MOCK = [ { request: { - query: MESSAGE_SENT_TO_DIRECT_CHAT, + query: CHAT_BY_ID, variables: { - userId: null, + id: '1', }, }, result: { data: { - messageSentToDirectChat: { - _id: '6ec1f1364e03ac4697a151', - createdAt: '2024-07-10T17:16:33.248Z', - messageContent: 'Test ', - receiver: { - _id: '65378abd85008f171cf2990d', - firstName: 'Vyvyan', - lastName: 'Kerry', - image: '', - }, - sender: { + chatById: { + _id: '1', + createdAt: '2345678903456', + isGroup: false, + creator: { _id: '64378abd85008f171cf2990d', firstName: 'Wilt', lastName: 'Shepherd', - image: '', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', }, - updatedAt: '2024-07-10', - }, - }, - }, - }, -]; - -const DIRECT_CHAT_BY_ID_QUERY_MOCK = [ - { - request: { - query: DIRECT_CHAT_BY_ID, - variables: { - id: '1', - }, - }, - result: { - data: { - directChatById: { - _id: '1', - createdAt: '2345678903456', - messages: [ - { - _id: '345678', - createdAt: '345678908765', - messageContent: 'Hello', - receiver: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, - sender: { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@example.com', - image: '', - }, - }, - ], - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, - { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@example.com', - image: '', - }, - ], - }, - }, - }, - }, - { - request: { - query: DIRECT_CHAT_BY_ID, - variables: { - id: '1', - }, - }, - result: { - data: { - directChatById: { - _id: '1', - createdAt: '2345678903456', - messages: [ - { - _id: '345678', - createdAt: '345678908765', - messageContent: 'Hello', - receiver: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, - sender: { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@example.com', - image: '', - }, - }, - ], - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, - { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@example.com', - image: '', - }, - ], - }, - }, - }, - }, - { - request: { - query: DIRECT_CHAT_BY_ID, - variables: { - id: '', - }, - }, - result: { - data: { - directChatById: { - _id: '1', - createdAt: '2345678903456', - messages: [ - { - _id: '345678', - createdAt: '345678908765', - messageContent: 'Hello', - receiver: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, - sender: { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@example.com', - image: '', - }, - }, - ], - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, - { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@example.com', - image: '', - }, - ], - }, - }, - }, - }, - { - request: { - query: DIRECT_CHAT_BY_ID, - variables: { - id: '2', - }, - }, - result: { - data: { - directChatById: { - _id: '65844efc814dd4003db811c4', - createdAt: '2345678903456', + organization: null, + name: '', messages: [ - { - _id: '345678', - createdAt: '345678908765', - messageContent: 'Hello', - receiver: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + replyTo: null, + type: 'STRING', sender: { _id: '2', firstName: 'Test', @@ -1674,28 +806,35 @@ const DIRECT_CHAT_BY_ID_QUERY_MOCK = [ }, { request: { - query: DIRECT_CHAT_BY_ID, + query: CHAT_BY_ID, variables: { - id: null, + id: '1', }, }, result: { data: { - directChatById: { - _id: '65844efc814dd4003db811c4', + chatById: { + _id: '1', + isGroup: false, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: null, + name: '', createdAt: '2345678903456', messages: [ { _id: '345678', createdAt: '345678908765', messageContent: 'Hello', - receiver: { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, + replyTo: null, + type: 'STRING', sender: { _id: '2', firstName: 'Test', @@ -1712,7 +851,34 @@ const DIRECT_CHAT_BY_ID_QUERY_MOCK = [ lastName: 'Talreja', email: 'disha@example.com', image: '', + appUserProfile: { + _id: '64378abd85308f171cf2993d', + adminFor: [], + isSuperAdmin: false, + createdOrganizations: [], + createdEvents: [], + eventAdmin: [], + __typename: 'AppUserProfile', + }, + __typename: 'UserData', }, + ], + }, + }, + }, + }, + { + request: { + query: USERS_CONNECTION_LIST, + variables: { + firstName_contains: '', + lastName_contains: '', + }, + }, + result: { + data: { + users: { + user: [ { _id: '2', firstName: 'Test', @@ -1727,297 +893,518 @@ const DIRECT_CHAT_BY_ID_QUERY_MOCK = [ }, ]; -const GROUP_CHAT_BY_ID_QUERY_MOCK = [ +const CHATS_LIST_MOCK = [ { request: { - query: GROUP_CHAT_BY_ID, + query: CHATS_LIST, variables: { - id: '1', + id: null, }, }, result: { data: { - groupChatById: { - _id: '65844efc814dd4003db811c4', - createdAt: '2345678903456', - title: 'Test Group Chat', - messages: [ - { - _id: '345678', - createdAt: '345678908765', - messageContent: 'Hello', - sender: { + chatsByUserId: [ + { + _id: '65844efc814dd40fgh03db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', + }, + createdAt: '2345678903456', + name: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + replyTo: null, + type: 'STRING', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { _id: '2', firstName: 'Test', lastName: 'User', email: 'test@example.com', image: '', }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + { + _id: '65844efc814ddgh4003db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', }, - ], - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, - { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@example.com', - image: '', - }, - { - _id: '3', - firstName: 'Test', - lastName: 'User1', - email: 'test1@example.com', - image: '', - }, - { - _id: '4', - firstName: 'Test', - lastName: 'User2', - email: 'test2@example.com', - image: '', - }, - { - _id: '5', - firstName: 'Test', - lastName: 'User4', - email: 'test4@example.com', - image: '', + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', }, - ], - }, + createdAt: '2345678903456', + name: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + replyTo: null, + type: 'STRING', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + ], }, }, }, { request: { - query: GROUP_CHAT_BY_ID, + query: CHATS_LIST, variables: { - id: '1', + id: '', }, }, result: { data: { - groupChatById: { - _id: '65844efc814dd4003db811c4', - createdAt: '2345678903456', - title: 'Test Group Chat', - messages: [ - { - _id: '345678', - createdAt: '345678908765', - messageContent: 'Hello', - sender: { + chatsByUserId: [ + { + _id: '65844ghjefc814dd4003db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', + }, + createdAt: '2345678903456', + name: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + replyTo: null, + type: 'STRING', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + { + _id: 'ujhgtrdtyuiop', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', + }, + createdAt: '2345678903456', + name: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + replyTo: null, + type: 'STRING', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { _id: '2', firstName: 'Test', - lastName: 'User', - email: 'test@example.com', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', image: '', }, - }, - ], - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, - { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@example.com', - image: '', - }, - { - _id: '3', - firstName: 'Test', - lastName: 'User1', - email: 'test1@example.com', - image: '', - }, - { - _id: '4', - firstName: 'Test', - lastName: 'User2', - email: 'test2@example.com', - image: '', - }, - { - _id: '5', - firstName: 'Test', - lastName: 'User4', - email: 'test4@example.com', - image: '', - }, - ], - }, + ], + }, + ], }, }, }, { request: { - query: GROUP_CHAT_BY_ID, + query: CHATS_LIST, variables: { - id: '', + id: '1', }, }, result: { data: { - groupChatById: { - _id: '1', - createdAt: '2345678903456', - title: 'Test Group Chat', - messages: [ - { - _id: '345678', - createdAt: '345678908765', - messageContent: 'Hello', - sender: { + chatsByUserId: [ + { + _id: '65844efc814dhjmkdftyd4003db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', + }, + createdAt: '2345678903456', + name: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + replyTo: null, + type: 'STRING', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { _id: '2', firstName: 'Test', lastName: 'User', email: 'test@example.com', image: '', }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + { + _id: '65844ewsedrffc814dd4003db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', }, - ], - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, - { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@example.com', - image: '', - }, - { - _id: '3', - firstName: 'Test', - lastName: 'User1', - email: 'test1@example.com', - image: '', - }, - { - _id: '4', - firstName: 'Test', - lastName: 'User2', - email: 'test2@example.com', - image: '', - }, - { - _id: '5', - firstName: 'Test', - lastName: 'User4', - email: 'test4@example.com', - image: '', + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', }, - ], - }, - }, - }, - }, - { - request: { - query: GROUP_CHAT_BY_ID, - variables: { - id: '2', - }, - }, - result: { - data: { - groupChatById: { - _id: '65844efc814dd4003db811c4', - createdAt: '2345678903456', - title: 'Test Group Chat', - messages: [ - { - _id: '345678', - createdAt: '345678908765', - messageContent: 'Hello', - sender: { + createdAt: '2345678903456', + name: 'Test Group Chat', + messages: [ + { + _id: '345678', + createdAt: '345678908765', + messageContent: 'Hello', + replyTo: null, + type: 'STRING', + sender: { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + image: '', + }, + }, + ], + users: [ + { + _id: '1', + firstName: 'Disha', + lastName: 'Talreja', + email: 'disha@example.com', + image: '', + }, + { _id: '2', firstName: 'Test', lastName: 'User', email: 'test@example.com', image: '', }, - }, - ], - users: [ - { - _id: '1', - firstName: 'Disha', - lastName: 'Talreja', - email: 'disha@example.com', - image: '', - }, - { - _id: '2', - firstName: 'Test', - lastName: 'User', - email: 'test@example.com', - image: '', - }, - { - _id: '3', - firstName: 'Test', - lastName: 'User1', - email: 'test1@example.com', - image: '', - }, - { - _id: '4', - firstName: 'Test', - lastName: 'User2', - email: 'test2@example.com', - image: '', - }, - { - _id: '5', - firstName: 'Test', - lastName: 'User4', - email: 'test4@example.com', - image: '', - }, - ], - }, + { + _id: '3', + firstName: 'Test', + lastName: 'User1', + email: 'test1@example.com', + image: '', + }, + { + _id: '4', + firstName: 'Test', + lastName: 'User2', + email: 'test2@example.com', + image: '', + }, + { + _id: '5', + firstName: 'Test', + lastName: 'User4', + email: 'test4@example.com', + image: '', + }, + ], + }, + ], }, }, }, +]; + +const GROUP_CHAT_BY_ID_QUERY_MOCK = [ { request: { - query: GROUP_CHAT_BY_ID, + query: CHAT_BY_ID, variables: { - id: null, + id: '', }, }, result: { data: { - groupChatById: { + chatById: { _id: '65844efc814dd4003db811c4', + isGroup: true, + creator: { + _id: '64378abd85008f171cf2990d', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + email: 'testsuperadmin@example.com', + createdAt: '2023-04-13T04:53:17.742Z', + __typename: 'User', + }, + organization: { + _id: 'pw3ertyuiophgfre45678', + name: 'rtyu', + }, createdAt: '2345678903456', - title: 'Test Group Chat', + name: 'Test Group Chat', messages: [ { _id: '345678', createdAt: '345678908765', messageContent: 'Hello', + replyTo: null, + type: 'STRING', sender: { _id: '2', firstName: 'Test', @@ -2104,11 +1491,11 @@ describe('Testing Chat Screen [User Portal]', () => { const mock = [ ...USER_JOINED_ORG_MOCK, ...GROUP_CHAT_BY_ID_QUERY_MOCK, - ...DIRECT_CHAT_BY_ID_QUERY_MOCK, - ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, - ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ...MESSAGE_SENT_TO_CHAT_MOCK, + ...UserConnectionListMock, + ...CHAT_BY_ID_QUERY_MOCK, + ...CHATS_LIST_MOCK, ...UserConnectionListMock, - ...MOCKS, ]; render( @@ -2129,11 +1516,12 @@ describe('Testing Chat Screen [User Portal]', () => { const mock = [ ...USER_JOINED_ORG_MOCK, ...GROUP_CHAT_BY_ID_QUERY_MOCK, - ...DIRECT_CHAT_BY_ID_QUERY_MOCK, - ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, - ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ...MESSAGE_SENT_TO_CHAT_MOCK, + ...MESSAGE_SENT_TO_CHAT_MOCK, + ...UserConnectionListMock, + ...CHAT_BY_ID_QUERY_MOCK, + ...CHATS_LIST_MOCK, ...UserConnectionListMock, - ...MOCKS, ]; render( @@ -2151,23 +1539,21 @@ describe('Testing Chat Screen [User Portal]', () => { await wait(); expect(await screen.findByText('Messages')).toBeInTheDocument(); - const contactCards = await screen.findAllByTestId('chatContact'); - console.log(contactCards); - expect(contactCards[0]).toBeInTheDocument(); - act(() => { - fireEvent.click(contactCards[0]); - }); + + expect( + await screen.findByTestId('contactCardContainer'), + ).toBeInTheDocument(); }); test('create new direct chat', async () => { const mock = [ ...USER_JOINED_ORG_MOCK, ...GROUP_CHAT_BY_ID_QUERY_MOCK, - ...DIRECT_CHAT_BY_ID_QUERY_MOCK, - ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, - ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ...MESSAGE_SENT_TO_CHAT_MOCK, + ...MESSAGE_SENT_TO_CHAT_MOCK, + ...CHAT_BY_ID_QUERY_MOCK, + ...CHATS_LIST_MOCK, ...UserConnectionListMock, - ...MOCKS, ]; render( @@ -2203,11 +1589,12 @@ describe('Testing Chat Screen [User Portal]', () => { const mock = [ ...USER_JOINED_ORG_MOCK, ...GROUP_CHAT_BY_ID_QUERY_MOCK, - ...DIRECT_CHAT_BY_ID_QUERY_MOCK, - ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, - ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ...MESSAGE_SENT_TO_CHAT_MOCK, + ...UserConnectionListMock, + ...MESSAGE_SENT_TO_CHAT_MOCK, + ...CHAT_BY_ID_QUERY_MOCK, + ...CHATS_LIST_MOCK, ...UserConnectionListMock, - ...MOCKS, ]; render( @@ -2233,6 +1620,7 @@ describe('Testing Chat Screen [User Portal]', () => { fireEvent.click(newGroupChatBtn); const closeButton = screen.getByRole('button', { name: /close/i }); expect(closeButton).toBeInTheDocument(); + fireEvent.click(closeButton); }); @@ -2240,11 +1628,12 @@ describe('Testing Chat Screen [User Portal]', () => { const mock = [ ...USER_JOINED_ORG_MOCK, ...GROUP_CHAT_BY_ID_QUERY_MOCK, - ...DIRECT_CHAT_BY_ID_QUERY_MOCK, - ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, - ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ...MESSAGE_SENT_TO_CHAT_MOCK, + ...UserConnectionListMock, + ...MESSAGE_SENT_TO_CHAT_MOCK, + ...CHAT_BY_ID_QUERY_MOCK, + ...CHATS_LIST_MOCK, ...UserConnectionListMock, - ...MOCKS, ]; setItem('userId', '1'); @@ -2260,8 +1649,8 @@ describe('Testing Chat Screen [User Portal]', () => { , ); screen.debug(); - await waitFor(() => { - const closeMenuBtn = screen.queryByTestId('closeMenu'); + await waitFor(async () => { + const closeMenuBtn = await screen.findByTestId('closeMenu'); expect(closeMenuBtn).toBeInTheDocument(); if (closeMenuBtn) { closeMenuBtn.click(); @@ -2269,16 +1658,6 @@ describe('Testing Chat Screen [User Portal]', () => { throw new Error('Close menu button not found'); } }); - - await waitFor(() => { - const openMenuBtn = screen.queryByTestId('openMenu'); - expect(openMenuBtn).toBeInTheDocument(); - if (openMenuBtn) { - openMenuBtn.click(); - } else { - throw new Error('Open menu button not found'); - } - }); }); test('Testing sidebar when the screen size is less than or equal to 820px', async () => { @@ -2286,11 +1665,12 @@ describe('Testing Chat Screen [User Portal]', () => { const mock = [ ...USER_JOINED_ORG_MOCK, ...GROUP_CHAT_BY_ID_QUERY_MOCK, - ...DIRECT_CHAT_BY_ID_QUERY_MOCK, - ...MESSAGE_SENT_TO_DIRECT_CHAT_MOCK, - ...MESSAGE_SENT_TO_GROUP_CHAT_MOCK, + ...MESSAGE_SENT_TO_CHAT_MOCK, + ...UserConnectionListMock, + ...MESSAGE_SENT_TO_CHAT_MOCK, + ...CHAT_BY_ID_QUERY_MOCK, + ...CHATS_LIST_MOCK, ...UserConnectionListMock, - ...MOCKS, ]; resizeWindow(800); render( @@ -2304,16 +1684,12 @@ describe('Testing Chat Screen [User Portal]', () => { , ); - screen.debug(); - await waitFor(() => { - expect(screen.getByText('My Organizations')).toBeInTheDocument(); - expect(screen.getByText('Talawa User Portal')).toBeInTheDocument(); - }); - await waitFor(() => { - const chatBtn = screen.getByTestId('chatBtn'); - act(() => { - chatBtn.click(); - }); - }); + await wait(); + expect(screen.getByText('My Organizations')).toBeInTheDocument(); + expect(screen.getByText('Talawa User Portal')).toBeInTheDocument(); + + expect(await screen.findByTestId('openMenu')).toBeInTheDocument(); + fireEvent.click(screen.getByTestId('openMenu')); + expect(await screen.findByTestId('closeMenu')).toBeInTheDocument(); }); }); diff --git a/src/screens/UserPortal/Chat/Chat.tsx b/src/screens/UserPortal/Chat/Chat.tsx index 43e8f5ab61..441ce7d4ba 100644 --- a/src/screens/UserPortal/Chat/Chat.tsx +++ b/src/screens/UserPortal/Chat/Chat.tsx @@ -1,5 +1,4 @@ import React, { useEffect, useState } from 'react'; -import { DIRECT_CHATS_LIST } from 'GraphQl/Queries/Queries'; import { useQuery } from '@apollo/client'; import { useTranslation } from 'react-i18next'; import { Button, Dropdown } from 'react-bootstrap'; @@ -9,22 +8,19 @@ import ContactCard from 'components/UserPortal/ContactCard/ContactCard'; import ChatRoom from 'components/UserPortal/ChatRoom/ChatRoom'; import useLocalStorage from 'utils/useLocalstorage'; import NewChat from 'assets/svgs/newChat.svg?react'; -import Accordion from 'react-bootstrap/Accordion'; import styles from './Chat.module.css'; import UserSidebar from 'components/UserPortal/UserSidebar/UserSidebar'; -import { GROUP_CHAT_LIST } from 'GraphQl/Queries/PlugInQueries'; +import { CHATS_LIST } from 'GraphQl/Queries/PlugInQueries'; import CreateGroupChat from '../../../components/UserPortal/CreateGroupChat/CreateGroupChat'; import CreateDirectChat from 'components/UserPortal/CreateDirectChat/CreateDirectChat'; interface InterfaceContactCardProps { id: string; title: string; - subtitle: string; image: string; selectedContact: string; setSelectedContact: React.Dispatch>; - type: string; - setSelectedChatType: React.Dispatch>; + isGroup: boolean; } /** * The `chat` component provides a user interface for interacting with contacts and chat rooms within an organization. @@ -59,6 +55,10 @@ export default function chat(): JSX.Element { const { t: tCommon } = useTranslation('common'); const [hideDrawer, setHideDrawer] = useState(null); + const [chats, setChats] = useState([]); + const [selectedContact, setSelectedContact] = useState(''); + const { getItem } = useLocalStorage(); + const userId = getItem('userId'); const handleResize = (): void => { if (window.innerWidth <= 820) { @@ -74,13 +74,6 @@ export default function chat(): JSX.Element { }; }, []); - const [selectedContact, setSelectedContact] = useState(''); - const [contacts, setContacts] = useState([]); - const [groupChats, setGroupChats] = useState([]); - const [selectChatType, setSelectedChatType] = useState(''); - const { getItem } = useLocalStorage(); - const userId = getItem('userId'); - const [createDirectChatModalisOpen, setCreateDirectChatModalisOpen] = useState(false); @@ -103,24 +96,20 @@ export default function chat(): JSX.Element { }; const { - data: contactData, - loading: contactLoading, - refetch: contactRefetch, - } = useQuery(DIRECT_CHATS_LIST, { + data: chatsListData, + loading: chatsListLoading, + refetch: chatsListRefetch, + } = useQuery(CHATS_LIST, { variables: { id: userId, }, }); - const { - data: groupChatList, - loading: groupChatListLoading, - refetch: groupChatListRefetch, - } = useQuery(GROUP_CHAT_LIST, { - variables: { - id: userId, - }, - }); + React.useEffect(() => { + if (chatsListData) { + setChats(chatsListData.chatsByUserId); + } + }, [chatsListData]); // const handleSearch = (value: string): void => { // setFilterName(value); @@ -139,18 +128,6 @@ export default function chat(): JSX.Element { // handleSearch(value); // }; - React.useEffect(() => { - if (contactData) { - setContacts(contactData.directChatsByUserID); - } - }, [contactData]); - - React.useEffect(() => { - if (groupChatList) { - setGroupChats(groupChatList.groupChatsByUserId); - } - }, [groupChatList]); - return ( <> {hideDrawer ? ( @@ -209,88 +186,47 @@ export default function chat(): JSX.Element {
    - {contactLoading || groupChatListLoading ? ( + {chatsListLoading ? (
    Loading...
    ) : ( -
    - - {!!contacts.length && ( - - + {!!chats.length && + chats.map((chat: any) => { + const cardProps: InterfaceContactCardProps = { + id: chat._id, + title: !chat.isGroup + ? chat.users[0]?._id === userId + ? `${chat.users[1]?.firstName} ${chat.users[1]?.lastName}` + : `${chat.users[0]?.firstName} ${chat.users[0]?.lastName}` + : chat.name, + image: chat.isGroup + ? userId + ? chat.users[1]?.image + : chat.users[0]?.image + : chat.image, + setSelectedContact, + selectedContact, + isGroup: chat.isGroup, + }; + return ( + - DIRECT CHATS - - - {contacts.map((contact: any) => { - const cardProps: InterfaceContactCardProps = { - id: contact._id, - title: - contact.users[0]?._id === userId - ? `${contact.users[1]?.firstName} ${contact.users[1]?.lastName}` - : `${contact.users[0]?.firstName} ${contact.users[0]?.lastName}`, - subtitle: userId - ? contact.users[1]?.email - : contact.users[0]?.email, - image: userId - ? contact.users[1]?.image - : contact.users[0]?.image, - setSelectedContact, - selectedContact, - type: 'direct', - setSelectedChatType, - }; - return ( - - ); - })} - - - )} - {!!groupChats.length && ( - - - GROUP CHATS - - - {groupChats.map((chat: any) => { - const cardProps: InterfaceContactCardProps = { - id: chat._id, - title: chat.title, - subtitle: `${chat.users.length} ${chat.users.length > 1 ? 'members' : 'member'}`, - image: '', - setSelectedContact, - selectedContact, - type: 'group', - setSelectedChatType, - }; - return ( - - ); - })} - - - )} - + {...cardProps} + key={chat._id} + /> + ); + })}
    )}
    - +
    @@ -298,14 +234,14 @@ export default function chat(): JSX.Element { )} {createDirectChatModalisOpen && ( )} diff --git a/src/screens/UserPortal/Events/Events.test.tsx b/src/screens/UserPortal/Events/Events.test.tsx index e5ef6d2b03..8c0b7c6912 100644 --- a/src/screens/UserPortal/Events/Events.test.tsx +++ b/src/screens/UserPortal/Events/Events.test.tsx @@ -336,7 +336,7 @@ describe('Testing Events Screen [User Portal]', () => { await wait(); - expect(toast.success).toBeCalledWith( + expect(toast.success).toHaveBeenCalledWith( 'Event created and posted successfully.', ); }); @@ -379,7 +379,7 @@ describe('Testing Events Screen [User Portal]', () => { await wait(); - expect(toast.success).toBeCalledWith( + expect(toast.success).toHaveBeenCalledWith( 'Event created and posted successfully.', ); }); diff --git a/src/screens/UserPortal/Pledges/Pledges.tsx b/src/screens/UserPortal/Pledges/Pledges.tsx index 59802be507..33e8bf63c2 100644 --- a/src/screens/UserPortal/Pledges/Pledges.tsx +++ b/src/screens/UserPortal/Pledges/Pledges.tsx @@ -4,7 +4,7 @@ import styles from './Pledges.module.css'; import { useTranslation } from 'react-i18next'; import { Search, Sort, WarningAmberRounded } from '@mui/icons-material'; import useLocalStorage from 'utils/useLocalstorage'; -import type { InterfacePledgeInfo, InterfacePledger } from 'utils/interfaces'; +import type { InterfacePledgeInfo, InterfaceUserInfo } from 'utils/interfaces'; import { Unstable_Popup as BasePopup } from '@mui/base/Unstable_Popup'; import { type ApolloQueryResult, useQuery } from '@apollo/client'; import { USER_PLEDGES } from 'GraphQl/Queries/fundQueries'; @@ -81,7 +81,7 @@ const Pledges = (): JSX.Element => { } const [anchor, setAnchor] = useState(null); - const [extraUsers, setExtraUsers] = useState([]); + const [extraUsers, setExtraUsers] = useState([]); const [searchTerm, setSearchTerm] = useState(''); const [pledges, setPledges] = useState([]); const [pledge, setPledge] = useState(null); @@ -154,7 +154,7 @@ const Pledges = (): JSX.Element => { const handleClick = ( event: React.MouseEvent, - users: InterfacePledger[], + users: InterfaceUserInfo[], ): void => { setExtraUsers(users); setAnchor(anchor ? null : event.currentTarget); @@ -197,7 +197,7 @@ const Pledges = (): JSX.Element => {
    {params.row.users .slice(0, 2) - .map((user: InterfacePledger, index: number) => ( + .map((user: InterfaceUserInfo, index: number) => (
    {user.image ? ( { disablePortal className={`${styles.popup} ${extraUsers.length > 4 ? styles.popupExtra : ''}`} > - {extraUsers.map((user: InterfacePledger, index: number) => ( + {extraUsers.map((user: InterfaceUserInfo, index: number) => (
    { - const singleLike = { - firstName: value.firstName, - lastName: value.lastName, - id: value._id, - }; - allLikes.push(singleLike); - }); - - const postComments: any = []; - - comments.forEach((value: any) => { - const commentLikes: any = []; - value.likedBy.forEach((commentLike: any) => { - const singleLike = { - id: commentLike._id, - }; - commentLikes.push(singleLike); - }); - - const comment = { - id: value._id, - creator: { - firstName: value.creator.firstName, - lastName: value.creator.lastName, - id: value.creator._id, - email: value.creator.email, - }, - likeCount: value.likeCount, - likedBy: commentLikes, - text: value.text, - }; - postComments.push(comment); - }); + const allLikes: InterfacePostLikes = likedBy.map((value) => ({ + firstName: value.firstName, + lastName: value.lastName, + id: value._id, + })); + + const postComments: InterfacePostComments = comments?.map((value) => ({ + id: value.id, + creator: { + firstName: value.creator?.firstName ?? '', + lastName: value.creator?.lastName ?? '', + id: value.creator?.id ?? '', + email: value.creator?.email ?? '', + }, + likeCount: value.likeCount, + likedBy: value.likedBy?.map((like) => ({ id: like?.id ?? '' })) ?? [], + text: value.text, + })); const date = new Date(node.createdAt); const formattedDate = new Intl.DateTimeFormat('en-US', { @@ -311,7 +275,6 @@ export default function home(): JSX.Element { <>
    -

    {t('posts')}

    {t('startPost')}
    diff --git a/src/screens/UserPortal/Settings/Settings.module.css b/src/screens/UserPortal/Settings/Settings.module.css index 323aed3275..2558ea9f63 100644 --- a/src/screens/UserPortal/Settings/Settings.module.css +++ b/src/screens/UserPortal/Settings/Settings.module.css @@ -23,7 +23,11 @@ font-size: 1.2rem; font-weight: 600; } - +.scrollableCardBody { + max-height: min(220px, 50vh); + overflow-y: auto; + scroll-behavior: smooth; +} .cardHeader { padding: 1.25rem 1rem 1rem 1rem; border-bottom: 1px solid var(--bs-gray-200); @@ -36,6 +40,7 @@ padding: 1.25rem 1rem 1.5rem 1rem; display: flex; flex-direction: column; + overflow-y: scroll; } .cardLabel { @@ -137,6 +142,10 @@ padding: 2rem; } + .scrollableCardBody { + max-height: 40vh; + } + .contract, .expand { animation: none; diff --git a/src/screens/UserPortal/Settings/Settings.test.tsx b/src/screens/UserPortal/Settings/Settings.test.tsx index 34aa3711bd..fd9e1ed350 100644 --- a/src/screens/UserPortal/Settings/Settings.test.tsx +++ b/src/screens/UserPortal/Settings/Settings.test.tsx @@ -11,7 +11,6 @@ import { StaticMockLink } from 'utils/StaticMockLink'; import Settings from './Settings'; import userEvent from '@testing-library/user-event'; import { CHECK_AUTH } from 'GraphQl/Queries/Queries'; - const MOCKS = [ { request: { @@ -63,6 +62,7 @@ const Mocks1 = [ countryCode: 'IN', line1: 'random', }, + eventsAttended: [{ _id: 'event1' }, { _id: 'event2' }], phone: { mobile: '+174567890', }, @@ -90,6 +90,7 @@ const Mocks2 = [ maritalStatus: '', educationGrade: '', employmentStatus: '', + eventsAttended: [], birthDate: '', address: { state: '', @@ -107,33 +108,6 @@ const Mocks2 = [ }, ]; -const mockMaritalStatusEnum = [ - { - value: 'SINGLE', - label: 'Single', - }, - { - value: 'ENGAGED', - label: 'Engaged', - }, - { - value: 'MARRIED', - label: 'Married', - }, - { - value: 'DIVORCED', - label: 'Divorced', - }, - { - value: 'WIDOWED', - label: 'Widowed', - }, - { - value: 'SEPARATED', - label: 'Separated', - }, -]; - const link = new StaticMockLink(MOCKS, true); const link1 = new StaticMockLink(Mocks1, true); const link2 = new StaticMockLink(Mocks2, true); @@ -214,7 +188,7 @@ describe('Testing Settings Screen [User Portal]', () => { await wait(); userEvent.type(screen.getByTestId('inputPhoneNumber'), '1234567890'); await wait(); - userEvent.selectOptions(screen.getByTestId('inputGrade'), 'Grade 1'); + userEvent.selectOptions(screen.getByTestId('inputGrade'), 'Grade-1'); await wait(); userEvent.selectOptions(screen.getByTestId('inputEmpStatus'), 'Unemployed'); await wait(); @@ -243,7 +217,7 @@ describe('Testing Settings Screen [User Portal]', () => { const files = [imageFile]; userEvent.upload(fileInp, files); await wait(); - expect(screen.getAllByAltText('profile picture')[0]).toBeInTheDocument(); + expect(screen.getByTestId('profile-picture')).toBeInTheDocument(); }); test('resetChangesBtn works properly', async () => { @@ -262,7 +236,8 @@ describe('Testing Settings Screen [User Portal]', () => { }); await wait(); - + userEvent.type(screen.getByTestId('inputAddress'), 'random'); + await wait(); userEvent.click(screen.getByTestId('resetChangesBtn')); await wait(); expect(screen.getByTestId('inputFirstName')).toHaveValue('John'); @@ -294,7 +269,8 @@ describe('Testing Settings Screen [User Portal]', () => { }); await wait(); - + userEvent.type(screen.getByTestId('inputAddress'), 'random'); + await wait(); userEvent.click(screen.getByTestId('resetChangesBtn')); await wait(); expect(screen.getByTestId('inputFirstName')).toHaveValue(''); @@ -371,4 +347,70 @@ describe('Testing Settings Screen [User Portal]', () => { act(() => closeMenuBtn.click()); } }); + + test('renders events attended card correctly', async () => { + render( + + + + + + + + + , + ); + await wait(); + // Check if the card title is rendered + expect(screen.getByText('Events Attended')).toBeInTheDocument(); + await wait(1000); + // Check for empty state immediately + expect(screen.getByText('No Events Attended')).toBeInTheDocument(); + }); + + test('renders events attended card correctly with events', async () => { + const mockEventsAttended = [ + { _id: '1', title: 'Event 1' }, + { _id: '2', title: 'Event 2' }, + ]; + + const MocksWithEvents = [ + { + ...Mocks1[0], + result: { + data: { + checkAuth: { + ...Mocks1[0].result.data.checkAuth, + eventsAttended: mockEventsAttended, + }, + }, + }, + }, + ]; + + const linkWithEvents = new StaticMockLink(MocksWithEvents, true); + + render( + + + + + + + + + , + ); + + await wait(1000); + + expect(screen.getByText('Events Attended')).toBeInTheDocument(); + const eventsCards = screen.getAllByTestId('usereventsCard'); + expect(eventsCards.length).toBe(2); + + eventsCards.forEach((card) => { + expect(card).toBeInTheDocument(); + expect(card.children.length).toBe(1); + }); + }); }); diff --git a/src/screens/UserPortal/Settings/Settings.tsx b/src/screens/UserPortal/Settings/Settings.tsx index 8b80f8ea1d..6038879b7f 100644 --- a/src/screens/UserPortal/Settings/Settings.tsx +++ b/src/screens/UserPortal/Settings/Settings.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useRef, useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import styles from './Settings.module.css'; import { Button, Card, Col, Form, Row } from 'react-bootstrap'; @@ -10,17 +10,19 @@ import { toast } from 'react-toastify'; import { CHECK_AUTH } from 'GraphQl/Queries/Queries'; import useLocalStorage from 'utils/useLocalstorage'; import { - countryOptions, educationGradeEnum, employmentStatusEnum, genderEnum, maritalStatusEnum, } from 'utils/formEnumFields'; -import UserProfile from 'components/UserProfileSettings/UserProfile'; import DeleteUser from 'components/UserProfileSettings/DeleteUser'; import OtherSettings from 'components/UserProfileSettings/OtherSettings'; import UserSidebar from 'components/UserPortal/UserSidebar/UserSidebar'; import ProfileDropdown from 'components/ProfileDropdown/ProfileDropdown'; +import Avatar from 'components/Avatar/Avatar'; +import type { InterfaceEvent } from 'components/EventManagement/EventAttendance/InterfaceEvents'; +import { EventsAttendedByUser } from 'components/UserPortal/UserProfile/EventsAttendedByUser'; +import UserAddressFields from 'components/UserPortal/UserProfile/UserAddressFields'; /** * The Settings component allows users to view and update their profile settings. @@ -33,6 +35,7 @@ export default function settings(): JSX.Element { keyPrefix: 'settings', }); const { t: tCommon } = useTranslation('common'); + const [isUpdated, setisUpdated] = useState(false); const [hideDrawer, setHideDrawer] = useState(null); /** @@ -56,8 +59,7 @@ export default function settings(): JSX.Element { const { setItem } = useLocalStorage(); const { data } = useQuery(CHECK_AUTH, { fetchPolicy: 'network-only' }); const [updateUserDetails] = useMutation(UPDATE_USER_MUTATION); - - const [userDetails, setUserDetails] = useState({ + const [userDetails, setUserDetails] = React.useState({ firstName: '', lastName: '', createdAt: '', @@ -72,6 +74,7 @@ export default function settings(): JSX.Element { state: '', country: '', image: '', + eventsAttended: [] as InterfaceEvent[], }); /** @@ -88,6 +91,7 @@ export default function settings(): JSX.Element { * This function sends a mutation request to update the user details * and reloads the page on success. */ + /*istanbul ignore next*/ const handleUpdateUserDetails = async (): Promise => { try { let updatedUserDetails = { ...userDetails }; @@ -109,6 +113,7 @@ export default function settings(): JSX.Element { setItem('name', userFullName); } } catch (error: unknown) { + /*istanbul ignore next*/ errorHandler(t, error); } }; @@ -120,6 +125,7 @@ export default function settings(): JSX.Element { * @param value - The new value for the field. */ const handleFieldChange = (fieldName: string, value: string): void => { + setisUpdated(true); setUserDetails((prevState) => ({ ...prevState, [fieldName]: value, @@ -130,6 +136,7 @@ export default function settings(): JSX.Element { * Triggers the file input click event to open the file picker dialog. */ const handleImageUpload = (): void => { + setisUpdated(true); if (fileInputRef.current) { (fileInputRef.current as HTMLInputElement).click(); } @@ -139,6 +146,7 @@ export default function settings(): JSX.Element { * Resets the user details to the values fetched from the server. */ const handleResetChanges = (): void => { + setisUpdated(false); /* istanbul ignore next */ if (data) { const { @@ -188,6 +196,7 @@ export default function settings(): JSX.Element { maritalStatus, address, image, + eventsAttended, } = data.checkAuth; setUserDetails({ @@ -204,12 +213,12 @@ export default function settings(): JSX.Element { address: address?.line1 || '', state: address?.state || '', country: address?.countryCode || '', + eventsAttended, image, }); originalImageState.current = image; } }, [data]); - return ( <> {hideDrawer ? ( @@ -250,17 +259,8 @@ export default function settings(): JSX.Element {
    - - - - - +

    {tCommon('settings')}

    +
    @@ -270,6 +270,70 @@ export default function settings(): JSX.Element {
    + +
    +
    + {userDetails?.image ? ( + User + ) : ( + + )} + e.key === 'Enter' && handleImageUpload() + } + /> +
    +
    + , + ): Promise => { + const file = e.target?.files?.[0]; + if (file) { + const image = await convertToBase64(file); + setUserDetails({ ...userDetails, image }); + } + } + } + style={{ display: 'none' }} + /> + {genderEnum.map((g) => ( ))} @@ -369,49 +433,6 @@ export default function settings(): JSX.Element { data-testid="inputPhoneNumber" /> - - - {tCommon('displayImage')} - -
    - - , - ): Promise => { - const target = e.target as HTMLInputElement; - const file = target.files && target.files[0]; - if (file) { - const image = await convertToBase64(file); - setUserDetails({ ...userDetails, image }); - } - } - } - style={{ display: 'none' }} - /> -
    - -
    - + + - {t(grade.label)} + {grade.label} ))} - - - {t(status.label)} + {status.label} ))} @@ -516,109 +537,46 @@ export default function settings(): JSX.Element { key={status.value.toLowerCase()} value={status.value} > - {t(status.label)} + {status.label} ))} - - - - {tCommon('address')} - - - handleFieldChange('address', e.target.value) - } - className={`${styles.cardControl}`} - data-testid="inputAddress" - /> - - - + {isUpdated && ( +
    + - -
    + {tCommon('saveChanges')} + +
    + )} - @@ -627,6 +585,7 @@ export default function settings(): JSX.Element { +
    diff --git a/src/screens/UserPortal/UserScreen/UserScreen.test.tsx b/src/screens/UserPortal/UserScreen/UserScreen.test.tsx index 96ee9767f2..642b231a66 100644 --- a/src/screens/UserPortal/UserScreen/UserScreen.test.tsx +++ b/src/screens/UserPortal/UserScreen/UserScreen.test.tsx @@ -4,7 +4,7 @@ import { fireEvent, render, screen } from '@testing-library/react'; import { I18nextProvider } from 'react-i18next'; import 'jest-location-mock'; import { Provider } from 'react-redux'; -import { BrowserRouter } from 'react-router-dom'; +import { BrowserRouter, useNavigate } from 'react-router-dom'; import { store } from 'state/store'; import i18nForTest from 'utils/i18nForTest'; import UserScreen from './UserScreen'; @@ -87,7 +87,7 @@ describe('Testing LeftDrawer in OrganizationScreen', () => { ); const titleElement = screen.getByRole('heading', { level: 1 }); - expect(titleElement).toHaveTextContent(''); + expect(titleElement).toHaveTextContent('Posts'); }); test('renders the correct title based on the titleKey', () => { @@ -109,7 +109,7 @@ describe('Testing LeftDrawer in OrganizationScreen', () => { expect(titleElement).toHaveTextContent('People'); }); - test('Testing LeftDrawer in page functionality', async () => { + test('LeftDrawer should toggle correctly based on window size and user interaction', async () => { render( @@ -138,8 +138,10 @@ describe('Testing LeftDrawer in OrganizationScreen', () => { expect(icon).toHaveClass('fa fa-angle-double-left'); }); - test('should be redirected to / if orgId is undefined', async () => { + test('should be redirected to root when orgId is undefined', async () => { mockID = undefined; + const navigate = jest.fn(); + jest.spyOn({ useNavigate }, 'useNavigate').mockReturnValue(navigate); render( diff --git a/src/screens/UserPortal/UserScreen/UserScreen.tsx b/src/screens/UserPortal/UserScreen/UserScreen.tsx index 8543803933..bcb1d867f3 100644 --- a/src/screens/UserPortal/UserScreen/UserScreen.tsx +++ b/src/screens/UserPortal/UserScreen/UserScreen.tsx @@ -19,6 +19,7 @@ const map: InterfaceMapType = { donate: 'donate', campaigns: 'userCampaigns', pledges: 'userPledges', + volunteer: 'userVolunteer', }; /** @@ -130,7 +131,7 @@ const UserScreen = (): JSX.Element => { >
    -

    {titleKey !== 'home' ? t('title') : ''}

    +

    {t('title')}

    diff --git a/src/screens/UserPortal/Volunteer/Actions/Actions.mocks.ts b/src/screens/UserPortal/Volunteer/Actions/Actions.mocks.ts new file mode 100644 index 0000000000..5162134c65 --- /dev/null +++ b/src/screens/UserPortal/Volunteer/Actions/Actions.mocks.ts @@ -0,0 +1,268 @@ +import { ACTION_ITEMS_BY_USER } from 'GraphQl/Queries/ActionItemQueries'; + +const action1 = { + _id: 'actionId1', + assignee: { + _id: 'volunteerId1', + user: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + }, + assigneeGroup: null, + assigneeType: 'EventVolunteer', + assigner: { + _id: 'userId1', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + actionItemCategory: { + _id: 'categoryId1', + name: 'Category 1', + }, + preCompletionNotes: '', + postCompletionNotes: '', + assignmentDate: '2024-10-25', + dueDate: '2025-10-25', + completionDate: '2024-11-01', + isCompleted: false, + event: { + _id: 'eventId1', + title: 'Event 1', + }, + creator: { + _id: 'userId1', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + allottedHours: 8, +}; + +const action2 = { + _id: 'actionId2', + assignee: null, + assigneeGroup: { + _id: 'groupId1', + name: 'Group 1', + }, + assigneeType: 'EventVolunteerGroup', + assigner: { + _id: 'userId1', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + actionItemCategory: { + _id: 'categoryId2', + name: 'Category 2', + }, + preCompletionNotes: '', + postCompletionNotes: '', + assignmentDate: '2024-10-25', + dueDate: '2025-10-26', + completionDate: '2024-11-01', + isCompleted: false, + event: { + _id: 'eventId1', + title: 'Event 1', + }, + creator: { + _id: 'userId1', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + allottedHours: 8, +}; + +const action3 = { + _id: 'actionId3', + assignee: { + _id: 'volunteerId3', + user: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: 'img-url', + }, + }, + assigneeGroup: null, + assigneeType: 'EventVolunteer', + assigner: { + _id: 'userId1', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + actionItemCategory: { + _id: 'categoryId3', + name: 'Category 3', + }, + preCompletionNotes: '', + postCompletionNotes: '', + assignmentDate: '2024-10-25', + dueDate: '2024-10-27', + completionDate: '2024-11-01', + isCompleted: true, + event: { + _id: 'eventId2', + title: 'Event 2', + }, + creator: { + _id: 'userId1', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + allottedHours: null, +}; + +export const MOCKS = [ + { + request: { + query: ACTION_ITEMS_BY_USER, + variables: { + userId: 'userId', + orderBy: null, + where: { + orgId: 'orgId', + assigneeName: '', + }, + }, + }, + result: { + data: { + actionItemsByUser: [action1, action2, action3], + }, + }, + }, + { + request: { + query: ACTION_ITEMS_BY_USER, + variables: { + userId: 'userId', + orderBy: 'dueDate_DESC', + where: { + orgId: 'orgId', + assigneeName: '', + }, + }, + }, + result: { + data: { + actionItemsByUser: [action2, action1], + }, + }, + }, + { + request: { + query: ACTION_ITEMS_BY_USER, + variables: { + userId: 'userId', + orderBy: 'dueDate_ASC', + where: { + orgId: 'orgId', + assigneeName: '', + }, + }, + }, + result: { + data: { + actionItemsByUser: [action1, action2], + }, + }, + }, + { + request: { + query: ACTION_ITEMS_BY_USER, + variables: { + userId: 'userId', + orderBy: null, + where: { + orgId: 'orgId', + assigneeName: '1', + }, + }, + }, + result: { + data: { + actionItemsByUser: [action2], + }, + }, + }, + { + request: { + query: ACTION_ITEMS_BY_USER, + variables: { + userId: 'userId', + orderBy: null, + where: { + orgId: 'orgId', + categoryName: '', + }, + }, + }, + result: { + data: { + actionItemsByUser: [action1, action2], + }, + }, + }, + { + request: { + query: ACTION_ITEMS_BY_USER, + variables: { + userId: 'userId', + orderBy: null, + where: { + orgId: 'orgId', + categoryName: '1', + }, + }, + }, + result: { + data: { + actionItemsByUser: [action1], + }, + }, + }, +]; + +export const EMPTY_MOCKS = [ + { + request: { + query: ACTION_ITEMS_BY_USER, + variables: { + userId: 'userId', + orderBy: null, + where: { + orgId: 'orgId', + assigneeName: '', + }, + }, + }, + result: { + data: { + actionItemsByUser: [], + }, + }, + }, +]; + +export const ERROR_MOCKS = [ + { + request: { + query: ACTION_ITEMS_BY_USER, + variables: { + userId: 'userId', + orderBy: null, + where: { + orgId: 'orgId', + assigneeName: '', + }, + }, + }, + error: new Error('Mock Graphql ACTION_ITEMS_BY_USER Error'), + }, +]; diff --git a/src/screens/UserPortal/Volunteer/Actions/Actions.test.tsx b/src/screens/UserPortal/Volunteer/Actions/Actions.test.tsx new file mode 100644 index 0000000000..ce64d98adf --- /dev/null +++ b/src/screens/UserPortal/Volunteer/Actions/Actions.test.tsx @@ -0,0 +1,221 @@ +import React, { act } from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import type { RenderResult } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18n from 'utils/i18nForTest'; +import Actions from './Actions'; +import type { ApolloLink } from '@apollo/client'; +import { MOCKS, EMPTY_MOCKS, ERROR_MOCKS } from './Actions.mocks'; +import useLocalStorage from 'utils/useLocalstorage'; + +const { setItem } = useLocalStorage(); + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(ERROR_MOCKS); +const link3 = new StaticMockLink(EMPTY_MOCKS); + +const t = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.organizationActionItems ?? {}, + ), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const debounceWait = async (ms = 300): Promise => { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +}; + +const renderActions = (link: ApolloLink): RenderResult => { + return render( + + + + + + + } /> +
    } + /> + + + + + + , + ); +}; + +describe('Testing Actions Screen', () => { + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId' }), + })); + }); + + beforeEach(() => { + setItem('userId', 'userId'); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('should redirect to fallback URL if URL params are undefined', async () => { + setItem('userId', null); + render( + + + + + + } /> +
    } + /> + + + + + , + ); + + await waitFor(() => { + expect(screen.getByTestId('paramsError')).toBeInTheDocument(); + }); + }); + + it('should render Actions screen', async () => { + renderActions(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + const assigneeName = await screen.findAllByTestId('assigneeName'); + expect(assigneeName[0]).toHaveTextContent('Teresa Bradley'); + }); + + it('Check Sorting Functionality', async () => { + renderActions(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + let sortBtn = await screen.findByTestId('sort'); + expect(sortBtn).toBeInTheDocument(); + + // Sort by dueDate_DESC + fireEvent.click(sortBtn); + const dueDateDESC = await screen.findByTestId('dueDate_DESC'); + expect(dueDateDESC).toBeInTheDocument(); + fireEvent.click(dueDateDESC); + + let assigneeName = await screen.findAllByTestId('assigneeName'); + expect(assigneeName[0]).toHaveTextContent('Group 1'); + + // Sort by dueDate_ASC + sortBtn = await screen.findByTestId('sort'); + expect(sortBtn).toBeInTheDocument(); + fireEvent.click(sortBtn); + const dueDateASC = await screen.findByTestId('dueDate_ASC'); + expect(dueDateASC).toBeInTheDocument(); + fireEvent.click(dueDateASC); + + assigneeName = await screen.findAllByTestId('assigneeName'); + expect(assigneeName[0]).toHaveTextContent('Teresa Bradley'); + }); + + it('Search by Assignee name', async () => { + renderActions(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + const searchToggle = await screen.findByTestId('searchByToggle'); + expect(searchToggle).toBeInTheDocument(); + userEvent.click(searchToggle); + + const searchByAssignee = await screen.findByTestId('assignee'); + expect(searchByAssignee).toBeInTheDocument(); + userEvent.click(searchByAssignee); + + userEvent.type(searchInput, '1'); + await debounceWait(); + + const assigneeName = await screen.findAllByTestId('assigneeName'); + expect(assigneeName[0]).toHaveTextContent('Group 1'); + }); + + it('Search by Category name', async () => { + renderActions(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + const searchToggle = await screen.findByTestId('searchByToggle'); + expect(searchToggle).toBeInTheDocument(); + userEvent.click(searchToggle); + + const searchByCategory = await screen.findByTestId('category'); + expect(searchByCategory).toBeInTheDocument(); + userEvent.click(searchByCategory); + + // Search by name on press of ENTER + userEvent.type(searchInput, '1'); + await debounceWait(); + + const assigneeName = await screen.findAllByTestId('assigneeName'); + expect(assigneeName[0]).toHaveTextContent('Teresa Bradley'); + }); + + it('should render screen with No Actions', async () => { + renderActions(link3); + + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + expect(screen.getByText(t.noActionItems)).toBeInTheDocument(); + }); + }); + + it('Error while fetching Actions data', async () => { + renderActions(link2); + + await waitFor(() => { + expect(screen.getByTestId('errorMsg')).toBeInTheDocument(); + }); + }); + + it('Open and close ItemUpdateStatusModal', async () => { + renderActions(link1); + + const checkbox = await screen.findAllByTestId('statusCheckbox'); + userEvent.click(checkbox[0]); + + expect(await screen.findByText(t.actionItemStatus)).toBeInTheDocument(); + userEvent.click(await screen.findByTestId('modalCloseBtn')); + }); + + it('Open and close ItemViewModal', async () => { + renderActions(link1); + + const viewItemBtn = await screen.findAllByTestId('viewItemBtn'); + userEvent.click(viewItemBtn[0]); + + expect(await screen.findByText(t.actionItemDetails)).toBeInTheDocument(); + userEvent.click(await screen.findByTestId('modalCloseBtn')); + }); +}); diff --git a/src/screens/UserPortal/Volunteer/Actions/Actions.tsx b/src/screens/UserPortal/Volunteer/Actions/Actions.tsx new file mode 100644 index 0000000000..36b1f29b83 --- /dev/null +++ b/src/screens/UserPortal/Volunteer/Actions/Actions.tsx @@ -0,0 +1,471 @@ +import React, { useCallback, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Button, Dropdown, Form } from 'react-bootstrap'; +import { Navigate, useParams } from 'react-router-dom'; + +import { Circle, Search, Sort, WarningAmberRounded } from '@mui/icons-material'; +import dayjs from 'dayjs'; + +import { useQuery } from '@apollo/client'; + +import type { InterfaceActionItemInfo } from 'utils/interfaces'; +import styles from 'screens/OrganizationActionItems/OrganizationActionItems.module.css'; +import Loader from 'components/Loader/Loader'; +import { + DataGrid, + type GridCellParams, + type GridColDef, +} from '@mui/x-data-grid'; +import { Chip, debounce, Stack } from '@mui/material'; +import ItemViewModal from 'screens/OrganizationActionItems/ItemViewModal'; +import Avatar from 'components/Avatar/Avatar'; +import ItemUpdateStatusModal from 'screens/OrganizationActionItems/ItemUpdateStatusModal'; +import { ACTION_ITEMS_BY_USER } from 'GraphQl/Queries/ActionItemQueries'; +import useLocalStorage from 'utils/useLocalstorage'; + +enum ModalState { + VIEW = 'view', + STATUS = 'status', +} + +const dataGridStyle = { + '&.MuiDataGrid-root .MuiDataGrid-cell:focus-within': { + outline: 'none !important', + }, + '&.MuiDataGrid-root .MuiDataGrid-columnHeader:focus-within': { + outline: 'none', + }, + '& .MuiDataGrid-row:hover': { + backgroundColor: 'transparent', + }, + '& .MuiDataGrid-row.Mui-hovered': { + backgroundColor: 'transparent', + }, + '& .MuiDataGrid-root': { + borderRadius: '0.5rem', + }, + '& .MuiDataGrid-main': { + borderRadius: '0.5rem', + }, +}; + +/** + * Component for managing and displaying action items within an organization. + * + * This component allows users to view, filter, sort, and create action items. It also handles fetching and displaying related data such as action item categories and members. + * + * @returns The rendered component. + */ +function actions(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'organizationActionItems', + }); + const { t: tCommon } = useTranslation('common'); + const { t: tErrors } = useTranslation('errors'); + + // Get the organization ID from URL parameters + const { orgId } = useParams(); + const { getItem } = useLocalStorage(); + const userId = getItem('userId'); + + if (!orgId || !userId) { + return ; + } + + const [actionItem, setActionItem] = useState( + null, + ); + const [searchValue, setSearchValue] = useState(''); + const [searchTerm, setSearchTerm] = useState(''); + const [sortBy, setSortBy] = useState<'dueDate_ASC' | 'dueDate_DESC' | null>( + null, + ); + const [searchBy, setSearchBy] = useState<'assignee' | 'category'>('assignee'); + const [modalState, setModalState] = useState<{ + [key in ModalState]: boolean; + }>({ + [ModalState.VIEW]: false, + [ModalState.STATUS]: false, + }); + + const debouncedSearch = useMemo( + () => debounce((value: string) => setSearchTerm(value), 300), + [], + ); + + const openModal = (modal: ModalState): void => + setModalState((prevState) => ({ ...prevState, [modal]: true })); + + const closeModal = (modal: ModalState): void => + setModalState((prevState) => ({ ...prevState, [modal]: false })); + + const handleModalClick = useCallback( + (actionItem: InterfaceActionItemInfo | null, modal: ModalState): void => { + setActionItem(actionItem); + openModal(modal); + }, + [openModal], + ); + + /** + * Query to fetch action items for the organization based on filters and sorting. + */ + const { + data: actionItemsData, + loading: actionItemsLoading, + error: actionItemsError, + refetch: actionItemsRefetch, + }: { + data?: { + actionItemsByUser: InterfaceActionItemInfo[]; + }; + loading: boolean; + error?: Error | undefined; + refetch: () => void; + } = useQuery(ACTION_ITEMS_BY_USER, { + variables: { + userId, + orderBy: sortBy, + where: { + orgId, + assigneeName: searchBy === 'assignee' ? searchTerm : undefined, + categoryName: searchBy === 'category' ? searchTerm : undefined, + }, + }, + }); + + const actionItems = useMemo( + () => actionItemsData?.actionItemsByUser || [], + [actionItemsData], + ); + + if (actionItemsLoading) { + return ; + } + + if (actionItemsError) { + return ( +
    + +
    + {tErrors('errorLoading', { entity: 'Action Items' })} +
    +
    + ); + } + + const columns: GridColDef[] = [ + { + field: 'assignee', + headerName: 'Assignee', + flex: 1, + align: 'left', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + const { _id, firstName, lastName, image } = + params.row.assignee?.user || {}; + + return ( + <> + {params.row.assigneeType === 'EventVolunteer' ? ( + <> +
    + {image ? ( + Assignee + ) : ( +
    + +
    + )} + {firstName + ' ' + lastName} +
    + + ) : ( + <> +
    +
    + +
    + {params.row.assigneeGroup?.name as string} +
    + + )} + + ); + }, + }, + { + field: 'itemCategory', + headerName: 'Item Category', + flex: 1, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( +
    + {params.row.actionItemCategory?.name} +
    + ); + }, + }, + { + field: 'status', + headerName: 'Status', + flex: 1, + align: 'center', + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( + } + label={params.row.isCompleted ? 'Completed' : 'Pending'} + variant="outlined" + color="primary" + className={`${styles.chip} ${params.row.isCompleted ? styles.active : styles.pending}`} + /> + ); + }, + }, + { + field: 'allottedHours', + headerName: 'Allotted Hours', + align: 'center', + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + flex: 1, + renderCell: (params: GridCellParams) => { + return ( +
    + {params.row.allottedHours ?? '-'} +
    + ); + }, + }, + { + field: 'dueDate', + headerName: 'Due Date', + align: 'center', + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + flex: 1, + renderCell: (params: GridCellParams) => { + return ( +
    + {dayjs(params.row.dueDate).format('DD/MM/YYYY')} +
    + ); + }, + }, + { + field: 'options', + headerName: 'Options', + align: 'center', + flex: 1, + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( + <> + + + ); + }, + }, + { + field: 'completed', + headerName: 'Completed', + align: 'center', + flex: 1, + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( +
    + handleModalClick(params.row, ModalState.STATUS)} + /> +
    + ); + }, + }, + ]; + + return ( +
    + {/* Header with search, filter and Create Button */} +
    +
    + { + setSearchValue(e.target.value); + debouncedSearch(e.target.value); + }} + data-testid="searchBy" + /> + +
    +
    +
    + + + + {tCommon('searchBy', { item: '' })} + + + setSearchBy('assignee')} + data-testid="assignee" + > + {t('assignee')} + + setSearchBy('category')} + data-testid="category" + > + {t('category')} + + + + + + + {tCommon('sort')} + + + setSortBy('dueDate_DESC')} + data-testid="dueDate_DESC" + > + {t('latestDueDate')} + + setSortBy('dueDate_ASC')} + data-testid="dueDate_ASC" + > + {t('earliestDueDate')} + + + +
    +
    +
    + + {/* Table with Action Items */} + row._id} + slots={{ + noRowsOverlay: () => ( + + {t('noActionItems')} + + ), + }} + sx={dataGridStyle} + getRowClassName={() => `${styles.rowBackground}`} + autoHeight + rowHeight={65} + rows={actionItems} + columns={columns} + isRowSelectable={() => false} + /> + + {/* View Modal */} + {actionItem && ( + <> + closeModal(ModalState.VIEW)} + item={actionItem} + /> + + closeModal(ModalState.STATUS)} + actionItemsRefetch={actionItemsRefetch} + /> + + )} +
    + ); +} + +export default actions; diff --git a/src/screens/UserPortal/Volunteer/Groups/GroupModal.test.tsx b/src/screens/UserPortal/Volunteer/Groups/GroupModal.test.tsx new file mode 100644 index 0000000000..1d83d9a872 --- /dev/null +++ b/src/screens/UserPortal/Volunteer/Groups/GroupModal.test.tsx @@ -0,0 +1,308 @@ +import React from 'react'; +import type { ApolloLink } from '@apollo/client'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import type { RenderResult } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import i18n from 'utils/i18nForTest'; +import { MOCKS, UPDATE_ERROR_MOCKS } from './Groups.mocks'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { toast } from 'react-toastify'; +import type { InterfaceGroupModal } from './GroupModal'; +import GroupModal from './GroupModal'; +import userEvent from '@testing-library/user-event'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(UPDATE_ERROR_MOCKS); +const t = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.eventVolunteers ?? {}, + ), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const itemProps: InterfaceGroupModal[] = [ + { + isOpen: true, + hide: jest.fn(), + eventId: 'eventId', + refetchGroups: jest.fn(), + group: { + _id: 'groupId', + name: 'Group 1', + description: 'desc', + volunteersRequired: null, + createdAt: '2024-10-25T16:16:32.978Z', + creator: { + _id: 'creatorId1', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + leader: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: 'img-url', + }, + volunteers: [ + { + _id: 'volunteerId1', + user: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + }, + ], + assignments: [], + event: { + _id: 'eventId', + }, + }, + }, + { + isOpen: true, + hide: jest.fn(), + eventId: 'eventId', + refetchGroups: jest.fn(), + group: { + _id: 'groupId', + name: 'Group 1', + description: null, + volunteersRequired: null, + createdAt: '2024-10-25T16:16:32.978Z', + creator: { + _id: 'creatorId1', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + leader: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: 'img-url', + }, + volunteers: [], + assignments: [], + event: { + _id: 'eventId', + }, + }, + }, +]; + +const renderGroupModal = ( + link: ApolloLink, + props: InterfaceGroupModal, +): RenderResult => { + return render( + + + + + + + + + + + , + ); +}; + +describe('Testing GroupModal', () => { + it('GroupModal -> Requests -> Accept', async () => { + renderGroupModal(link1, itemProps[0]); + expect(screen.getByText(t.manageGroup)).toBeInTheDocument(); + + const requestsBtn = screen.getByText(t.requests); + expect(requestsBtn).toBeInTheDocument(); + userEvent.click(requestsBtn); + + const userName = await screen.findAllByTestId('userName'); + expect(userName).toHaveLength(2); + expect(userName[0]).toHaveTextContent('John Doe'); + expect(userName[1]).toHaveTextContent('Teresa Bradley'); + + const acceptBtn = screen.getAllByTestId('acceptBtn'); + expect(acceptBtn).toHaveLength(2); + userEvent.click(acceptBtn[0]); + await waitFor(() => { + expect(toast.success).toHaveBeenCalledWith(t.requestAccepted); + }); + }); + + it('GroupModal -> Requests -> Reject', async () => { + renderGroupModal(link1, itemProps[0]); + expect(screen.getByText(t.manageGroup)).toBeInTheDocument(); + + const requestsBtn = screen.getByText(t.requests); + expect(requestsBtn).toBeInTheDocument(); + userEvent.click(requestsBtn); + + const userName = await screen.findAllByTestId('userName'); + expect(userName).toHaveLength(2); + expect(userName[0]).toHaveTextContent('John Doe'); + expect(userName[1]).toHaveTextContent('Teresa Bradley'); + + const rejectBtn = screen.getAllByTestId('rejectBtn'); + expect(rejectBtn).toHaveLength(2); + userEvent.click(rejectBtn[0]); + await waitFor(() => { + expect(toast.success).toHaveBeenCalledWith(t.requestRejected); + }); + }); + + it('GroupModal -> Click Requests -> Click Details', async () => { + renderGroupModal(link1, itemProps[0]); + expect(screen.getByText(t.manageGroup)).toBeInTheDocument(); + + const requestsBtn = screen.getByText(t.requests); + expect(requestsBtn).toBeInTheDocument(); + userEvent.click(requestsBtn); + + const detailsBtn = await screen.findByText(t.details); + expect(detailsBtn).toBeInTheDocument(); + userEvent.click(detailsBtn); + }); + + it('GroupModal -> Details -> Update', async () => { + renderGroupModal(link1, itemProps[0]); + expect(screen.getByText(t.manageGroup)).toBeInTheDocument(); + + const nameInput = screen.getByLabelText(`${t.name} *`); + expect(nameInput).toBeInTheDocument(); + fireEvent.change(nameInput, { target: { value: 'Group 2' } }); + expect(nameInput).toHaveValue('Group 2'); + + const descInput = screen.getByLabelText(t.description); + expect(descInput).toBeInTheDocument(); + fireEvent.change(descInput, { target: { value: 'desc new' } }); + expect(descInput).toHaveValue('desc new'); + + const vrInput = screen.getByLabelText(t.volunteersRequired); + expect(vrInput).toBeInTheDocument(); + fireEvent.change(vrInput, { target: { value: '10' } }); + expect(vrInput).toHaveValue('10'); + + const submitBtn = screen.getByTestId('submitBtn'); + expect(submitBtn).toBeInTheDocument(); + userEvent.click(submitBtn); + + await waitFor(() => { + expect(toast.success).toHaveBeenCalledWith(t.volunteerGroupUpdated); + expect(itemProps[0].refetchGroups).toHaveBeenCalled(); + expect(itemProps[0].hide).toHaveBeenCalled(); + }); + }); + + it('GroupModal -> Details -> Update -> Error', async () => { + renderGroupModal(link2, itemProps[0]); + expect(screen.getByText(t.manageGroup)).toBeInTheDocument(); + + const nameInput = screen.getByLabelText(`${t.name} *`); + expect(nameInput).toBeInTheDocument(); + fireEvent.change(nameInput, { target: { value: 'Group 2' } }); + expect(nameInput).toHaveValue('Group 2'); + + const descInput = screen.getByLabelText(t.description); + expect(descInput).toBeInTheDocument(); + fireEvent.change(descInput, { target: { value: 'desc new' } }); + expect(descInput).toHaveValue('desc new'); + + const vrInput = screen.getByLabelText(t.volunteersRequired); + expect(vrInput).toBeInTheDocument(); + fireEvent.change(vrInput, { target: { value: '10' } }); + expect(vrInput).toHaveValue('10'); + + const submitBtn = screen.getByTestId('submitBtn'); + expect(submitBtn).toBeInTheDocument(); + userEvent.click(submitBtn); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); + + it('GroupModal -> Requests -> Accept -> Error', async () => { + renderGroupModal(link2, itemProps[0]); + expect(screen.getByText(t.manageGroup)).toBeInTheDocument(); + + const requestsBtn = screen.getByText(t.requests); + expect(requestsBtn).toBeInTheDocument(); + userEvent.click(requestsBtn); + + const userName = await screen.findAllByTestId('userName'); + expect(userName).toHaveLength(2); + expect(userName[0]).toHaveTextContent('John Doe'); + expect(userName[1]).toHaveTextContent('Teresa Bradley'); + + const acceptBtn = screen.getAllByTestId('acceptBtn'); + expect(acceptBtn).toHaveLength(2); + userEvent.click(acceptBtn[0]); + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); + + it('Try adding different values for volunteersRequired', async () => { + renderGroupModal(link1, itemProps[1]); + expect(screen.getByText(t.manageGroup)).toBeInTheDocument(); + + const vrInput = screen.getByLabelText(t.volunteersRequired); + expect(vrInput).toBeInTheDocument(); + fireEvent.change(vrInput, { target: { value: '-1' } }); + + await waitFor(() => { + expect(vrInput).toHaveValue(''); + }); + + userEvent.clear(vrInput); + userEvent.type(vrInput, '1{backspace}'); + + await waitFor(() => { + expect(vrInput).toHaveValue(''); + }); + + fireEvent.change(vrInput, { target: { value: '0' } }); + await waitFor(() => { + expect(vrInput).toHaveValue(''); + }); + + fireEvent.change(vrInput, { target: { value: '19' } }); + await waitFor(() => { + expect(vrInput).toHaveValue('19'); + }); + }); + + it('GroupModal -> Details -> No values updated', async () => { + renderGroupModal(link1, itemProps[0]); + expect(screen.getByText(t.manageGroup)).toBeInTheDocument(); + + const submitBtn = screen.getByTestId('submitBtn'); + expect(submitBtn).toBeInTheDocument(); + userEvent.click(submitBtn); + + await waitFor(() => { + expect(toast.success).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx b/src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx new file mode 100644 index 0000000000..4ae162cd70 --- /dev/null +++ b/src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx @@ -0,0 +1,415 @@ +import type { ChangeEvent } from 'react'; +import { Button, Form, Modal } from 'react-bootstrap'; +import type { + InterfaceCreateVolunteerGroup, + InterfaceVolunteerGroupInfo, + InterfaceVolunteerMembership, +} from 'utils/interfaces'; +import styles from 'screens/EventVolunteers/EventVolunteers.module.css'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useMutation, useQuery } from '@apollo/client'; +import { toast } from 'react-toastify'; +import { + FormControl, + Paper, + Stack, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + TextField, +} from '@mui/material'; +import { + UPDATE_VOLUNTEER_GROUP, + UPDATE_VOLUNTEER_MEMBERSHIP, +} from 'GraphQl/Mutations/EventVolunteerMutation'; +import { PiUserListBold } from 'react-icons/pi'; +import { TbListDetails } from 'react-icons/tb'; +import { USER_VOLUNTEER_MEMBERSHIP } from 'GraphQl/Queries/EventVolunteerQueries'; +import Avatar from 'components/Avatar/Avatar'; +import { FaXmark } from 'react-icons/fa6'; + +export interface InterfaceGroupModal { + isOpen: boolean; + hide: () => void; + eventId: string; + group: InterfaceVolunteerGroupInfo; + refetchGroups: () => void; +} + +/** + * A modal dialog for creating or editing a volunteer group. + * + * @param isOpen - Indicates whether the modal is open. + * @param hide - Function to close the modal. + * @param eventId - The ID of the event associated with volunteer group. + * @param orgId - The ID of the organization associated with volunteer group. + * @param group - The volunteer group object to be edited. + * @param refetchGroups - Function to refetch the volunteer groups after creation or update. + * @returns The rendered modal component. + * + * The `VolunteerGroupModal` component displays a form within a modal dialog for creating or editing a Volunteer Group. + * It includes fields for entering the group name, description, volunteersRequired, and selecting volunteers/leaders. + * + * The modal includes: + * - A header with a title indicating the current mode (create or edit) and a close button. + * - A form with: + * - An input field for entering the group name. + * - A textarea for entering the group description. + * - An input field for entering the number of volunteers required. + * - A submit button to create or update the pledge. + * + * On form submission, the component either: + * - Calls `updateVoluneerGroup` mutation to update an existing group, or + * + * Success or error messages are displayed using toast notifications based on the result of the mutation. + */ + +const GroupModal: React.FC = ({ + isOpen, + hide, + eventId, + group, + refetchGroups, +}) => { + const { t } = useTranslation('translation', { + keyPrefix: 'eventVolunteers', + }); + const { t: tCommon } = useTranslation('common'); + + const [modalType, setModalType] = useState<'details' | 'requests'>('details'); + const [formState, setFormState] = useState({ + name: group.name, + description: group.description ?? '', + leader: group.leader, + volunteerUsers: group.volunteers.map((volunteer) => volunteer.user), + volunteersRequired: group.volunteersRequired ?? null, + }); + + const [updateVolunteerGroup] = useMutation(UPDATE_VOLUNTEER_GROUP); + const [updateMembership] = useMutation(UPDATE_VOLUNTEER_MEMBERSHIP); + + const updateMembershipStatus = async ( + id: string, + status: 'accepted' | 'rejected', + ): Promise => { + try { + await updateMembership({ + variables: { + id: id, + status: status, + }, + }); + toast.success( + t( + status === 'accepted' ? 'requestAccepted' : 'requestRejected', + ) as string, + ); + refetchRequests(); + } catch (error: unknown) { + toast.error((error as Error).message); + } + }; + + /** + * Query to fetch volunteer Membership requests for the event. + */ + const { + data: requestsData, + refetch: refetchRequests, + }: { + data?: { + getVolunteerMembership: InterfaceVolunteerMembership[]; + }; + refetch: () => void; + } = useQuery(USER_VOLUNTEER_MEMBERSHIP, { + variables: { + where: { + eventId, + groupId: group._id, + status: 'requested', + }, + }, + }); + + const requests = useMemo(() => { + if (!requestsData) return []; + return requestsData.getVolunteerMembership; + }, [requestsData]); + + useEffect(() => { + setFormState({ + name: group.name, + description: group.description ?? '', + leader: group.leader, + volunteerUsers: group.volunteers.map((volunteer) => volunteer.user), + volunteersRequired: group.volunteersRequired ?? null, + }); + }, [group]); + + const { name, description, volunteersRequired } = formState; + + const updateGroupHandler = useCallback( + async (e: ChangeEvent): Promise => { + e.preventDefault(); + + const updatedFields: { + [key: string]: number | string | undefined | null; + } = {}; + + if (name !== group?.name) { + updatedFields.name = name; + } + if (description !== group?.description) { + updatedFields.description = description; + } + if (volunteersRequired !== group?.volunteersRequired) { + updatedFields.volunteersRequired = volunteersRequired; + } + try { + await updateVolunteerGroup({ + variables: { + id: group?._id, + data: { ...updatedFields, eventId }, + }, + }); + toast.success(t('volunteerGroupUpdated')); + refetchGroups(); + hide(); + } catch (error: unknown) { + console.log(error); + toast.error((error as Error).message); + } + }, + [formState, group], + ); + + return ( + + +

    {t('manageGroup')}

    + +
    + +
    + setModalType('details')} + /> + + + setModalType('requests')} + checked={modalType === 'requests'} + /> + +
    + + {modalType === 'details' ? ( +
    + {/* Input field to enter the group name */} + + + + setFormState({ ...formState, name: e.target.value }) + } + /> + + + {/* Input field to enter the group description */} + + + + setFormState({ ...formState, description: e.target.value }) + } + /> + + + + + + { + if (parseInt(e.target.value) > 0) { + setFormState({ + ...formState, + volunteersRequired: parseInt(e.target.value), + }); + } else if (e.target.value === '') { + setFormState({ + ...formState, + volunteersRequired: null, + }); + } + }} + /> + + + + {/* Button to submit the pledge form */} + +
    + ) : ( +
    + {requests.length === 0 ? ( + + {t('noRequests')} + + ) : ( + + + + + Name + Actions + + + + {requests.map((request, index) => { + const { _id, firstName, lastName, image } = + request.volunteer.user; + return ( + + + {image ? ( + volunteer + ) : ( +
    + +
    + )} + {firstName + ' ' + lastName} +
    + +
    + + +
    +
    +
    + ); + })} +
    +
    +
    + )} +
    + )} +
    +
    + ); +}; +export default GroupModal; diff --git a/src/screens/UserPortal/Volunteer/Groups/Groups.mocks.ts b/src/screens/UserPortal/Volunteer/Groups/Groups.mocks.ts new file mode 100644 index 0000000000..204326ee8d --- /dev/null +++ b/src/screens/UserPortal/Volunteer/Groups/Groups.mocks.ts @@ -0,0 +1,468 @@ +import { + UPDATE_VOLUNTEER_GROUP, + UPDATE_VOLUNTEER_MEMBERSHIP, +} from 'GraphQl/Mutations/EventVolunteerMutation'; +import { + EVENT_VOLUNTEER_GROUP_LIST, + USER_VOLUNTEER_MEMBERSHIP, +} from 'GraphQl/Queries/EventVolunteerQueries'; + +const group1 = { + _id: 'groupId1', + name: 'Group 1', + description: 'desc', + volunteersRequired: null, + createdAt: '2024-10-25T16:16:32.978Z', + creator: { + _id: 'creatorId1', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + leader: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: 'img-url', + }, + volunteers: [ + { + _id: 'volunteerId1', + user: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + }, + ], + assignments: [], + event: { + _id: 'eventId1', + }, +}; + +const group2 = { + _id: 'groupId2', + name: 'Group 2', + description: 'desc', + volunteersRequired: null, + createdAt: '2024-10-27T15:25:13.044Z', + creator: { + _id: 'creatorId2', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + leader: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + volunteers: [ + { + _id: 'volunteerId2', + user: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + }, + ], + assignments: [], + event: { + _id: 'eventId2', + }, +}; + +const group3 = { + _id: 'groupId3', + name: 'Group 3', + description: 'desc', + volunteersRequired: null, + createdAt: '2024-10-27T15:34:15.889Z', + creator: { + _id: 'creatorId3', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + leader: { + _id: 'userId1', + firstName: 'Bruce', + lastName: 'Garza', + image: null, + }, + volunteers: [ + { + _id: 'volunteerId3', + user: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + }, + ], + assignments: [], + event: { + _id: 'eventId3', + }, +}; + +const membership1 = { + _id: 'membershipId1', + status: 'requested', + createdAt: '2024-10-29T10:18:05.851Z', + event: { + _id: 'eventId', + title: 'Event 1', + startDate: '2044-10-31', + }, + volunteer: { + _id: 'volunteerId1', + user: { + _id: 'userId1', + firstName: 'John', + lastName: 'Doe', + image: 'img-url', + }, + }, + group: { + _id: 'groupId', + name: 'Group 1', + }, +}; + +const membership2 = { + _id: 'membershipId2', + status: 'requested', + createdAt: '2024-10-29T10:18:05.851Z', + event: { + _id: 'eventId', + title: 'Event 1', + startDate: '2044-10-31', + }, + volunteer: { + _id: 'volunteerId2', + user: { + _id: 'userId2', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + }, + group: { + _id: 'groupId', + name: 'Group 2', + }, +}; + +export const MOCKS = [ + { + request: { + query: EVENT_VOLUNTEER_GROUP_LIST, + variables: { + where: { + userId: 'userId', + orgId: 'orgId', + leaderName: null, + name_contains: '', + }, + orderBy: null, + }, + }, + result: { + data: { + getEventVolunteerGroups: [group1, group2, group3], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_GROUP_LIST, + variables: { + where: { + userId: 'userId', + orgId: 'orgId', + leaderName: null, + name_contains: '', + }, + orderBy: 'volunteers_DESC', + }, + }, + result: { + data: { + getEventVolunteerGroups: [group1, group2], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_GROUP_LIST, + variables: { + where: { + userId: 'userId', + orgId: 'orgId', + leaderName: null, + name_contains: '', + }, + orderBy: 'volunteers_ASC', + }, + }, + result: { + data: { + getEventVolunteerGroups: [group2, group1], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_GROUP_LIST, + variables: { + where: { + userId: 'userId', + orgId: 'orgId', + leaderName: null, + name_contains: '1', + }, + orderBy: null, + }, + }, + result: { + data: { + getEventVolunteerGroups: [group1], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_GROUP_LIST, + variables: { + where: { + userId: 'userId', + orgId: 'orgId', + leaderName: '', + name_contains: null, + }, + orderBy: null, + }, + }, + result: { + data: { + getEventVolunteerGroups: [group1, group2, group3], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_GROUP_LIST, + variables: { + where: { + userId: 'userId', + orgId: 'orgId', + leaderName: 'Bruce', + name_contains: null, + }, + orderBy: null, + }, + }, + result: { + data: { + getEventVolunteerGroups: [group3], + }, + }, + }, + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + eventId: 'eventId', + groupId: 'groupId', + status: 'requested', + }, + }, + }, + result: { + data: { + getVolunteerMembership: [membership1, membership2], + }, + }, + }, + { + request: { + query: UPDATE_VOLUNTEER_MEMBERSHIP, + variables: { + id: 'membershipId1', + status: 'accepted', + }, + }, + result: { + data: { + updateVolunteerMembership: { + _id: 'membershipId1', + }, + }, + }, + }, + { + request: { + query: UPDATE_VOLUNTEER_MEMBERSHIP, + variables: { + id: 'membershipId1', + status: 'rejected', + }, + }, + result: { + data: { + updateVolunteerMembership: { + _id: 'membershipId1', + }, + }, + }, + }, + { + request: { + query: UPDATE_VOLUNTEER_GROUP, + variables: { + id: 'groupId', + data: { + eventId: 'eventId', + name: 'Group 2', + description: 'desc new', + volunteersRequired: 10, + }, + }, + }, + result: { + data: { + updateEventVolunteerGroup: { + _id: 'groupId', + }, + }, + }, + }, + { + request: { + query: UPDATE_VOLUNTEER_GROUP, + variables: { + id: 'groupId', + data: { + eventId: 'eventId', + }, + }, + }, + result: { + data: { + updateEventVolunteerGroup: { + _id: 'groupId', + }, + }, + }, + }, +]; + +export const EMPTY_MOCKS = [ + { + request: { + query: EVENT_VOLUNTEER_GROUP_LIST, + variables: { + where: { + userId: 'userId', + orgId: 'orgId', + leaderName: null, + name_contains: '', + }, + orderBy: null, + }, + }, + result: { + data: { + getEventVolunteerGroups: [], + }, + }, + }, + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + eventId: 'eventId', + group: 'groupId', + status: 'requested', + }, + }, + }, + result: { + data: { + getVolunteerMembership: [], + }, + }, + }, +]; + +export const ERROR_MOCKS = [ + { + request: { + query: EVENT_VOLUNTEER_GROUP_LIST, + variables: { + where: { + userId: 'userId', + orgId: 'orgId', + leaderName: null, + name_contains: '', + }, + orderBy: null, + }, + }, + error: new Error('Mock Graphql EVENT_VOLUNTEER_GROUP_LIST Error'), + }, +]; + +export const UPDATE_ERROR_MOCKS = [ + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + eventId: 'eventId', + groupId: 'groupId', + status: 'requested', + }, + }, + }, + result: { + data: { + getVolunteerMembership: [membership1, membership2], + }, + }, + }, + { + request: { + query: UPDATE_VOLUNTEER_MEMBERSHIP, + variables: { + id: 'membershipId1', + status: 'accepted', + }, + }, + error: new Error('Mock Graphql UPDATE_VOLUNTEER_MEMBERSHIP Error'), + }, + { + request: { + query: UPDATE_VOLUNTEER_GROUP, + variables: { + id: 'groupId', + data: { + eventId: 'eventId', + name: 'Group 2', + description: 'desc new', + volunteersRequired: 10, + }, + }, + }, + error: new Error('Mock Graphql UPDATE_VOLUNTEER_GROUP Error'), + }, +]; diff --git a/src/screens/UserPortal/Volunteer/Groups/Groups.test.tsx b/src/screens/UserPortal/Volunteer/Groups/Groups.test.tsx new file mode 100644 index 0000000000..bc0a4993b9 --- /dev/null +++ b/src/screens/UserPortal/Volunteer/Groups/Groups.test.tsx @@ -0,0 +1,217 @@ +import React, { act } from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import type { RenderResult } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18n from 'utils/i18nForTest'; +import Groups from './Groups'; +import type { ApolloLink } from '@apollo/client'; +import { MOCKS, EMPTY_MOCKS, ERROR_MOCKS } from './Groups.mocks'; +import useLocalStorage from 'utils/useLocalstorage'; + +const { setItem } = useLocalStorage(); + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(ERROR_MOCKS); +const link3 = new StaticMockLink(EMPTY_MOCKS); +const t = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.eventVolunteers ?? {}, + ), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const debounceWait = async (ms = 300): Promise => { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +}; + +const renderGroups = (link: ApolloLink): RenderResult => { + return render( + + + + + + + } /> +
    } + /> + + + + + + , + ); +}; + +describe('Testing Groups Screen', () => { + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId' }), + })); + }); + + beforeEach(() => { + setItem('userId', 'userId'); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('should redirect to fallback URL if URL params are undefined', async () => { + setItem('userId', null); + render( + + + + + + } /> +
    } + /> + + + + + , + ); + + await waitFor(() => { + expect(screen.getByTestId('paramsError')).toBeInTheDocument(); + }); + }); + + it('should render Groups screen', async () => { + renderGroups(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + }); + + it('Check Sorting Functionality', async () => { + renderGroups(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + let sortBtn = await screen.findByTestId('sort'); + expect(sortBtn).toBeInTheDocument(); + + // Sort by members_DESC + fireEvent.click(sortBtn); + const volunteersDESC = await screen.findByTestId('volunteers_DESC'); + expect(volunteersDESC).toBeInTheDocument(); + fireEvent.click(volunteersDESC); + + let groupName = await screen.findAllByTestId('groupName'); + expect(groupName[0]).toHaveTextContent('Group 1'); + + // Sort by members_ASC + sortBtn = await screen.findByTestId('sort'); + expect(sortBtn).toBeInTheDocument(); + fireEvent.click(sortBtn); + const volunteersASC = await screen.findByTestId('volunteers_ASC'); + expect(volunteersASC).toBeInTheDocument(); + fireEvent.click(volunteersASC); + + groupName = await screen.findAllByTestId('groupName'); + expect(groupName[0]).toHaveTextContent('Group 2'); + }); + + it('Search by Groups', async () => { + renderGroups(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + const searchToggle = await screen.findByTestId('searchByToggle'); + expect(searchToggle).toBeInTheDocument(); + userEvent.click(searchToggle); + + const searchByGroup = await screen.findByTestId('group'); + expect(searchByGroup).toBeInTheDocument(); + userEvent.click(searchByGroup); + + userEvent.type(searchInput, '1'); + await debounceWait(); + + const groupName = await screen.findAllByTestId('groupName'); + expect(groupName[0]).toHaveTextContent('Group 1'); + }); + + it('Search by Leader', async () => { + renderGroups(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + const searchToggle = await screen.findByTestId('searchByToggle'); + expect(searchToggle).toBeInTheDocument(); + userEvent.click(searchToggle); + + const searchByLeader = await screen.findByTestId('leader'); + expect(searchByLeader).toBeInTheDocument(); + userEvent.click(searchByLeader); + + // Search by name on press of ENTER + userEvent.type(searchInput, 'Bruce'); + await debounceWait(); + + const groupName = await screen.findAllByTestId('groupName'); + expect(groupName[0]).toHaveTextContent('Group 1'); + }); + + it('should render screen with No Groups', async () => { + renderGroups(link3); + + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + expect(screen.getByText(t.noVolunteerGroups)).toBeInTheDocument(); + }); + }); + + it('Error while fetching groups data', async () => { + renderGroups(link2); + + await waitFor(() => { + expect(screen.getByTestId('errorMsg')).toBeInTheDocument(); + }); + }); + + it('Open and close ViewModal', async () => { + renderGroups(link1); + + const viewGroupBtn = await screen.findAllByTestId('viewGroupBtn'); + userEvent.click(viewGroupBtn[0]); + + expect(await screen.findByText(t.groupDetails)).toBeInTheDocument(); + userEvent.click(await screen.findByTestId('volunteerViewModalCloseBtn')); + }); + + it('Open and close GroupModal', async () => { + renderGroups(link1); + + const editGroupBtn = await screen.findAllByTestId('editGroupBtn'); + userEvent.click(editGroupBtn[0]); + + expect(await screen.findByText(t.manageGroup)).toBeInTheDocument(); + userEvent.click(await screen.findByTestId('modalCloseBtn')); + }); +}); diff --git a/src/screens/UserPortal/Volunteer/Groups/Groups.tsx b/src/screens/UserPortal/Volunteer/Groups/Groups.tsx new file mode 100644 index 0000000000..3941f461d5 --- /dev/null +++ b/src/screens/UserPortal/Volunteer/Groups/Groups.tsx @@ -0,0 +1,415 @@ +import React, { useCallback, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Button, Dropdown, Form } from 'react-bootstrap'; +import { Navigate, useParams } from 'react-router-dom'; + +import { Search, Sort, WarningAmberRounded } from '@mui/icons-material'; + +import { useQuery } from '@apollo/client'; + +import type { InterfaceVolunteerGroupInfo } from 'utils/interfaces'; +import Loader from 'components/Loader/Loader'; +import { + DataGrid, + type GridCellParams, + type GridColDef, +} from '@mui/x-data-grid'; +import { debounce, Stack } from '@mui/material'; +import Avatar from 'components/Avatar/Avatar'; +import styles from 'screens/EventVolunteers/EventVolunteers.module.css'; +import { EVENT_VOLUNTEER_GROUP_LIST } from 'GraphQl/Queries/EventVolunteerQueries'; +import VolunteerGroupViewModal from 'screens/EventVolunteers/VolunteerGroups/VolunteerGroupViewModal'; +import useLocalStorage from 'utils/useLocalstorage'; +import GroupModal from './GroupModal'; + +enum ModalState { + EDIT = 'edit', + VIEW = 'view', +} + +const dataGridStyle = { + '&.MuiDataGrid-root .MuiDataGrid-cell:focus-within': { + outline: 'none !important', + }, + '&.MuiDataGrid-root .MuiDataGrid-columnHeader:focus-within': { + outline: 'none', + }, + '& .MuiDataGrid-row:hover': { + backgroundColor: 'transparent', + }, + '& .MuiDataGrid-row.Mui-hovered': { + backgroundColor: 'transparent', + }, + '& .MuiDataGrid-root': { + borderRadius: '0.5rem', + }, + '& .MuiDataGrid-main': { + borderRadius: '0.5rem', + }, +}; + +/** + * Component for managing volunteer groups for an event. + * This component allows users to view, filter, sort, and create action items. It also provides a modal for creating and editing action items. + * @returns The rendered component. + */ +function groups(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'eventVolunteers', + }); + const { t: tCommon } = useTranslation('common'); + const { t: tErrors } = useTranslation('errors'); + + const { getItem } = useLocalStorage(); + const userId = getItem('userId'); + + // Get the organization ID from URL parameters + const { orgId } = useParams(); + + if (!orgId || !userId) { + return ; + } + + const [group, setGroup] = useState(null); + const [searchValue, setSearchValue] = useState(''); + const [searchTerm, setSearchTerm] = useState(''); + const [sortBy, setSortBy] = useState< + 'volunteers_ASC' | 'volunteers_DESC' | null + >(null); + const [searchBy, setSearchBy] = useState<'leader' | 'group'>('group'); + const [modalState, setModalState] = useState<{ + [key in ModalState]: boolean; + }>({ + [ModalState.EDIT]: false, + [ModalState.VIEW]: false, + }); + + const debouncedSearch = useMemo( + () => debounce((value: string) => setSearchTerm(value), 300), + [], + ); + + /** + * Query to fetch the list of volunteer groups for the event. + */ + const { + data: groupsData, + loading: groupsLoading, + error: groupsError, + refetch: refetchGroups, + }: { + data?: { + getEventVolunteerGroups: InterfaceVolunteerGroupInfo[]; + }; + loading: boolean; + error?: Error | undefined; + refetch: () => void; + } = useQuery(EVENT_VOLUNTEER_GROUP_LIST, { + variables: { + where: { + eventId: undefined, + userId, + orgId, + leaderName: searchBy === 'leader' ? searchTerm : null, + name_contains: searchBy === 'group' ? searchTerm : null, + }, + orderBy: sortBy, + }, + }); + + const openModal = (modal: ModalState): void => + setModalState((prevState) => ({ ...prevState, [modal]: true })); + + const closeModal = (modal: ModalState): void => + setModalState((prevState) => ({ ...prevState, [modal]: false })); + + const handleModalClick = useCallback( + (group: InterfaceVolunteerGroupInfo | null, modal: ModalState): void => { + setGroup(group); + openModal(modal); + }, + [openModal], + ); + + const groups = useMemo( + () => groupsData?.getEventVolunteerGroups || [], + [groupsData], + ); + + if (groupsLoading) { + return ; + } + + if (groupsError) { + return ( +
    + +
    + {tErrors('errorLoading', { entity: 'Volunteer Groups' })} +
    +
    + ); + } + + const columns: GridColDef[] = [ + { + field: 'group', + headerName: 'Group', + flex: 1, + align: 'left', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( +
    + {params.row.name} +
    + ); + }, + }, + { + field: 'leader', + headerName: 'Leader', + flex: 1, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + const { _id, firstName, lastName, image } = params.row.leader; + return ( +
    + {image ? ( + Assignee + ) : ( +
    + +
    + )} + {firstName + ' ' + lastName} +
    + ); + }, + }, + { + field: 'actions', + headerName: 'Actions Completed', + flex: 1, + align: 'center', + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( +
    + {params.row.assignments.length} +
    + ); + }, + }, + { + field: 'volunteers', + headerName: 'No. of Volunteers', + flex: 1, + align: 'center', + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( +
    + {params.row.volunteers.length} +
    + ); + }, + }, + { + field: 'options', + headerName: 'Options', + align: 'center', + flex: 1, + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( + <> + + {params.row.leader._id === userId && ( + + )} + + ); + }, + }, + ]; + + return ( +
    + {/* Header with search, filter and Create Button */} +
    +
    + { + setSearchValue(e.target.value); + debouncedSearch(e.target.value); + }} + data-testid="searchBy" + /> + +
    +
    +
    + + + + {tCommon('searchBy', { item: '' })} + + + setSearchBy('leader')} + data-testid="leader" + > + {t('leader')} + + setSearchBy('group')} + data-testid="group" + > + {t('group')} + + + + + + + {tCommon('sort')} + + + setSortBy('volunteers_DESC')} + data-testid="volunteers_DESC" + > + {t('mostVolunteers')} + + setSortBy('volunteers_ASC')} + data-testid="volunteers_ASC" + > + {t('leastVolunteers')} + + + +
    +
    +
    + + {/* Table with Volunteer Groups */} + row._id} + slots={{ + noRowsOverlay: () => ( + + {t('noVolunteerGroups')} + + ), + }} + sx={dataGridStyle} + getRowClassName={() => `${styles.rowBackground}`} + autoHeight + rowHeight={65} + rows={groups.map((group, index) => ({ + id: index + 1, + ...group, + }))} + columns={columns} + isRowSelectable={() => false} + /> + + {group && ( + <> + closeModal(ModalState.EDIT)} + refetchGroups={refetchGroups} + group={group} + eventId={group.event._id} + /> + closeModal(ModalState.VIEW)} + group={group} + /> + + )} +
    + ); +} + +export default groups; diff --git a/src/screens/UserPortal/Volunteer/Invitations/Invitations.mocks.ts b/src/screens/UserPortal/Volunteer/Invitations/Invitations.mocks.ts new file mode 100644 index 0000000000..c400d96939 --- /dev/null +++ b/src/screens/UserPortal/Volunteer/Invitations/Invitations.mocks.ts @@ -0,0 +1,263 @@ +import { UPDATE_VOLUNTEER_MEMBERSHIP } from 'GraphQl/Mutations/EventVolunteerMutation'; +import { USER_VOLUNTEER_MEMBERSHIP } from 'GraphQl/Queries/EventVolunteerQueries'; + +const membership1 = { + _id: 'membershipId1', + status: 'invited', + createdAt: '2024-10-29T10:18:05.851Z', + event: { + _id: 'eventId', + title: 'Event 1', + startDate: '2044-10-31', + }, + volunteer: { + _id: 'volunteerId1', + user: { + _id: 'userId', + firstName: 'John', + lastName: 'Doe', + image: 'img-url', + }, + }, + group: null, +}; + +const membership2 = { + _id: 'membershipId2', + status: 'invited', + createdAt: '2024-10-30T10:18:05.851Z', + event: { + _id: 'eventId', + title: 'Event 2', + startDate: '2044-11-31', + }, + volunteer: { + _id: 'volunteerId1', + user: { + _id: 'userId', + firstName: 'John', + lastName: 'Doe', + image: null, + }, + }, + group: { + _id: 'groupId1', + name: 'Group 1', + }, +}; + +export const MOCKS = [ + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + userId: 'userId', + status: 'invited', + filter: null, + }, + }, + }, + result: { + data: { + getVolunteerMembership: [membership1, membership2], + }, + }, + }, + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + userId: 'userId', + status: 'invited', + filter: null, + }, + orderBy: 'createdAt_DESC', + }, + }, + result: { + data: { + getVolunteerMembership: [membership2, membership1], + }, + }, + }, + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + userId: 'userId', + status: 'invited', + filter: null, + }, + orderBy: 'createdAt_ASC', + }, + }, + result: { + data: { + getVolunteerMembership: [membership1, membership2], + }, + }, + }, + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + userId: 'userId', + status: 'invited', + filter: 'group', + }, + }, + }, + result: { + data: { + getVolunteerMembership: [membership2], + }, + }, + }, + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + userId: 'userId', + status: 'invited', + filter: 'individual', + }, + }, + }, + result: { + data: { + getVolunteerMembership: [membership1], + }, + }, + }, + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + userId: 'userId', + status: 'invited', + filter: null, + eventTitle: '1', + }, + }, + }, + result: { + data: { + getVolunteerMembership: [membership1], + }, + }, + }, + { + request: { + query: UPDATE_VOLUNTEER_MEMBERSHIP, + variables: { + id: 'membershipId1', + status: 'accepted', + }, + }, + result: { + data: { + updateVolunteerMembership: { + _id: 'membershipId1', + }, + }, + }, + }, + { + request: { + query: UPDATE_VOLUNTEER_MEMBERSHIP, + variables: { + id: 'membershipId1', + status: 'rejected', + }, + }, + result: { + data: { + updateVolunteerMembership: { + _id: 'membershipId1', + }, + }, + }, + }, +]; + +export const EMPTY_MOCKS = [ + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + userId: 'userId', + status: 'invited', + filter: null, + }, + }, + }, + result: { + data: { + getVolunteerMembership: [], + }, + }, + }, +]; + +export const ERROR_MOCKS = [ + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + userId: 'userId', + status: 'invited', + filter: null, + }, + }, + }, + error: new Error('Mock Graphql USER_VOLUNTEER_MEMBERSHIP Error'), + }, + { + request: { + query: UPDATE_VOLUNTEER_MEMBERSHIP, + variables: { + id: 'membershipId1', + status: 'accepted', + }, + }, + error: new Error('Mock Graphql UPDATE_VOLUNTEER_MEMBERSHIP Error'), + }, +]; + +export const UPDATE_ERROR_MOCKS = [ + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + userId: 'userId', + status: 'invited', + filter: null, + }, + }, + }, + result: { + data: { + getVolunteerMembership: [membership1, membership2], + }, + }, + }, + { + request: { + query: UPDATE_VOLUNTEER_MEMBERSHIP, + variables: { + id: 'membershipId1', + status: 'accepted', + }, + }, + error: new Error('Mock Graphql UPDATE_VOLUNTEER_MEMBERSHIP Error'), + }, +]; diff --git a/src/screens/UserPortal/Volunteer/Invitations/Invitations.test.tsx b/src/screens/UserPortal/Volunteer/Invitations/Invitations.test.tsx new file mode 100644 index 0000000000..2c0cafc6a9 --- /dev/null +++ b/src/screens/UserPortal/Volunteer/Invitations/Invitations.test.tsx @@ -0,0 +1,303 @@ +import React, { act } from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import type { RenderResult } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18n from 'utils/i18nForTest'; +import Invitations from './Invitations'; +import type { ApolloLink } from '@apollo/client'; +import { + MOCKS, + EMPTY_MOCKS, + ERROR_MOCKS, + UPDATE_ERROR_MOCKS, +} from './Invitations.mocks'; +import { toast } from 'react-toastify'; +import useLocalStorage from 'utils/useLocalstorage'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +const { setItem } = useLocalStorage(); + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(ERROR_MOCKS); +const link3 = new StaticMockLink(EMPTY_MOCKS); +const link4 = new StaticMockLink(UPDATE_ERROR_MOCKS); +const t = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.userVolunteer ?? {}, + ), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const debounceWait = async (ms = 300): Promise => { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +}; + +const renderInvitations = (link: ApolloLink): RenderResult => { + return render( + + + + + + + } + /> +
    } + /> + + + + + + , + ); +}; + +describe('Testing Invvitations Screen', () => { + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId' }), + })); + }); + + beforeEach(() => { + setItem('userId', 'userId'); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('should redirect to fallback URL if URL params are undefined', async () => { + setItem('userId', null); + render( + + + + + + } /> +
    } + /> + + + + + , + ); + + await waitFor(() => { + expect(screen.getByTestId('paramsError')).toBeInTheDocument(); + }); + }); + + it('should render Invitations screen', async () => { + renderInvitations(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + }); + + it('Check Sorting Functionality', async () => { + renderInvitations(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + let sortBtn = await screen.findByTestId('sort'); + expect(sortBtn).toBeInTheDocument(); + + // Sort by createdAt_DESC + fireEvent.click(sortBtn); + const createdAtDESC = await screen.findByTestId('createdAt_DESC'); + expect(createdAtDESC).toBeInTheDocument(); + fireEvent.click(createdAtDESC); + + let inviteSubject = await screen.findAllByTestId('inviteSubject'); + expect(inviteSubject[0]).toHaveTextContent( + 'Invitation to join volunteer group', + ); + + // Sort by createdAt_ASC + sortBtn = await screen.findByTestId('sort'); + expect(sortBtn).toBeInTheDocument(); + fireEvent.click(sortBtn); + const createdAtASC = await screen.findByTestId('createdAt_ASC'); + expect(createdAtASC).toBeInTheDocument(); + fireEvent.click(createdAtASC); + + inviteSubject = await screen.findAllByTestId('inviteSubject'); + expect(inviteSubject[0]).toHaveTextContent( + 'Invitation to volunteer for event', + ); + }); + + it('Filter Invitations (all)', async () => { + renderInvitations(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + // Filter by All + const filter = await screen.findByTestId('filter'); + expect(filter).toBeInTheDocument(); + + fireEvent.click(filter); + const filterAll = await screen.findByTestId('filterAll'); + expect(filterAll).toBeInTheDocument(); + + fireEvent.click(filterAll); + const inviteSubject = await screen.findAllByTestId('inviteSubject'); + expect(inviteSubject).toHaveLength(2); + }); + + it('Filter Invitations (group)', async () => { + renderInvitations(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + // Filter by All + const filter = await screen.findByTestId('filter'); + expect(filter).toBeInTheDocument(); + + fireEvent.click(filter); + const filterGroup = await screen.findByTestId('filterGroup'); + expect(filterGroup).toBeInTheDocument(); + + fireEvent.click(filterGroup); + const inviteSubject = await screen.findAllByTestId('inviteSubject'); + expect(inviteSubject).toHaveLength(1); + expect(inviteSubject[0]).toHaveTextContent( + 'Invitation to join volunteer group', + ); + }); + + it('Filter Invitations (individual)', async () => { + renderInvitations(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + // Filter by All + const filter = await screen.findByTestId('filter'); + expect(filter).toBeInTheDocument(); + + fireEvent.click(filter); + const filterIndividual = await screen.findByTestId('filterIndividual'); + expect(filterIndividual).toBeInTheDocument(); + + fireEvent.click(filterIndividual); + const inviteSubject = await screen.findAllByTestId('inviteSubject'); + expect(inviteSubject).toHaveLength(1); + expect(inviteSubject[0]).toHaveTextContent( + 'Invitation to volunteer for event', + ); + }); + + it('Search Invitations', async () => { + renderInvitations(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + // Search by name on press of ENTER + userEvent.type(searchInput, '1'); + await debounceWait(); + + await waitFor(() => { + const inviteSubject = screen.getAllByTestId('inviteSubject'); + expect(inviteSubject).toHaveLength(1); + expect(inviteSubject[0]).toHaveTextContent( + 'Invitation to volunteer for event', + ); + }); + }); + + it('should render screen with No Invitations', async () => { + renderInvitations(link3); + + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + expect(screen.getByText(t.noInvitations)).toBeInTheDocument(); + }); + }); + + it('Error while fetching invitations data', async () => { + renderInvitations(link2); + + await waitFor(() => { + expect(screen.getByTestId('errorMsg')).toBeInTheDocument(); + }); + }); + + it('Accept Invite', async () => { + renderInvitations(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + const acceptBtn = await screen.findAllByTestId('acceptBtn'); + expect(acceptBtn).toHaveLength(2); + + // Accept Request + userEvent.click(acceptBtn[0]); + + await waitFor(() => { + expect(toast.success).toHaveBeenCalledWith(t.invitationAccepted); + }); + }); + + it('Reject Invite', async () => { + renderInvitations(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + const rejectBtn = await screen.findAllByTestId('rejectBtn'); + expect(rejectBtn).toHaveLength(2); + + // Reject Request + userEvent.click(rejectBtn[0]); + + await waitFor(() => { + expect(toast.success).toHaveBeenCalledWith(t.invitationRejected); + }); + }); + + it('Error in Update Invite Mutation', async () => { + renderInvitations(link4); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + const acceptBtn = await screen.findAllByTestId('acceptBtn'); + expect(acceptBtn).toHaveLength(2); + + // Accept Request + userEvent.click(acceptBtn[0]); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/screens/UserPortal/Volunteer/Invitations/Invitations.tsx b/src/screens/UserPortal/Volunteer/Invitations/Invitations.tsx new file mode 100644 index 0000000000..a79b64251d --- /dev/null +++ b/src/screens/UserPortal/Volunteer/Invitations/Invitations.tsx @@ -0,0 +1,297 @@ +import React, { useMemo, useState } from 'react'; +import { Dropdown, Form, Button } from 'react-bootstrap'; +import styles from '../VolunteerManagement.module.css'; +import { useTranslation } from 'react-i18next'; +import { Navigate, useParams } from 'react-router-dom'; +import { + FilterAltOutlined, + Search, + Sort, + WarningAmberRounded, +} from '@mui/icons-material'; +import { TbCalendarEvent } from 'react-icons/tb'; +import { FaUserGroup } from 'react-icons/fa6'; +import { debounce, Stack } from '@mui/material'; + +import useLocalStorage from 'utils/useLocalstorage'; +import { useMutation, useQuery } from '@apollo/client'; +import type { InterfaceVolunteerMembership } from 'utils/interfaces'; +import { FaRegClock } from 'react-icons/fa'; +import Loader from 'components/Loader/Loader'; +import { USER_VOLUNTEER_MEMBERSHIP } from 'GraphQl/Queries/EventVolunteerQueries'; +import { UPDATE_VOLUNTEER_MEMBERSHIP } from 'GraphQl/Mutations/EventVolunteerMutation'; +import { toast } from 'react-toastify'; + +enum ItemFilter { + Group = 'group', + Individual = 'individual', +} + +/** + * The `Invitations` component displays list of invites for the user to volunteer. + * It allows the user to search, sort, and accept/reject invites. + * + * @returns The rendered component displaying the upcoming events. + */ +const Invitations = (): JSX.Element => { + // Retrieves translation functions for various namespaces + const { t } = useTranslation('translation', { + keyPrefix: 'userVolunteer', + }); + const { t: tCommon } = useTranslation('common'); + const { t: tErrors } = useTranslation('errors'); + + // Retrieves stored user ID from local storage + const { getItem } = useLocalStorage(); + const userId = getItem('userId'); + + // Extracts organization ID from the URL parameters + const { orgId } = useParams(); + if (!orgId || !userId) { + // Redirects to the homepage if orgId or userId is missing + return ; + } + + const debouncedSearch = useMemo( + () => debounce((value: string) => setSearchTerm(value), 300), + [], + ); + + const [searchTerm, setSearchTerm] = useState(''); + const [searchValue, setSearchValue] = useState(''); + const [filter, setFilter] = useState(null); + const [sortBy, setSortBy] = useState< + 'createdAt_ASC' | 'createdAt_DESC' | null + >(null); + + const [updateMembership] = useMutation(UPDATE_VOLUNTEER_MEMBERSHIP); + + const updateMembershipStatus = async ( + id: string, + status: 'accepted' | 'rejected', + ): Promise => { + try { + await updateMembership({ + variables: { + id: id, + status: status, + }, + }); + toast.success( + t( + status === 'accepted' ? 'invitationAccepted' : 'invitationRejected', + ) as string, + ); + refetchInvitations(); + } catch (error: unknown) { + toast.error((error as Error).message); + } + }; + + const { + data: invitationData, + loading: invitationLoading, + error: invitationError, + refetch: refetchInvitations, + }: { + data?: { + getVolunteerMembership: InterfaceVolunteerMembership[]; + }; + loading: boolean; + error?: Error | undefined; + refetch: () => void; + } = useQuery(USER_VOLUNTEER_MEMBERSHIP, { + variables: { + where: { + userId: userId, + status: 'invited', + filter: filter, + eventTitle: searchTerm ? searchTerm : undefined, + }, + orderBy: sortBy ? sortBy : undefined, + }, + }); + + const invitations = useMemo(() => { + if (!invitationData) return []; + return invitationData.getVolunteerMembership; + }, [invitationData]); + + // loads the invitations when the component mounts + if (invitationLoading) return ; + if (invitationError) { + // Displays an error message if there is an issue loading the invvitations + return ( +
    +
    + +
    + {tErrors('errorLoading', { entity: 'Volunteership Invitations' })} +
    +
    +
    + ); + } + + // Renders the invitations list and UI elements for searching, sorting, and accepting/rejecting invites + return ( + <> +
    + {/* Search input field and button */} +
    + { + setSearchValue(e.target.value); + debouncedSearch(e.target.value); + }} + data-testid="searchBy" + /> + +
    +
    +
    + {/* Dropdown menu for sorting invitations */} + + + + {tCommon('sort')} + + + setSortBy('createdAt_DESC')} + data-testid="createdAt_DESC" + > + {t('receivedLatest')} + + setSortBy('createdAt_ASC')} + data-testid="createdAt_ASC" + > + {t('receivedEarliest')} + + + + + + + + {t('filter')} + + + setFilter(null)} + data-testid="filterAll" + > + {tCommon('all')} + + setFilter(ItemFilter.Group)} + data-testid="filterGroup" + > + {t('groupInvite')} + + setFilter(ItemFilter.Individual)} + data-testid="filterIndividual" + > + {t('individualInvite')} + + + +
    +
    +
    + {invitations.length < 1 ? ( + + {/* Displayed if no invitations are found */} + {t('noInvitations')} + + ) : ( + invitations.map((invite: InterfaceVolunteerMembership) => ( +
    +
    +
    + {invite.group ? ( + <>{t('groupInvitationSubject')} + ) : ( + <>{t('eventInvitationSubject')} + )} +
    +
    + {invite.group && ( + <> +
    + + Group:{' '} + {invite.group.name} +
    + | + + )} +
    + + Event:{' '} + {invite.event.title} +
    + | +
    + + Received:{' '} + {new Date(invite.createdAt).toLocaleString()} +
    +
    +
    +
    + + +
    +
    + )) + )} + + ); +}; + +export default Invitations; diff --git a/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.mocks.ts b/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.mocks.ts new file mode 100644 index 0000000000..ae00d52dbe --- /dev/null +++ b/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.mocks.ts @@ -0,0 +1,281 @@ +import { CREATE_VOLUNTEER_MEMBERSHIP } from 'GraphQl/Mutations/EventVolunteerMutation'; +import { USER_EVENTS_VOLUNTEER } from 'GraphQl/Queries/PlugInQueries'; + +const event1 = { + _id: 'eventId1', + title: 'Event 1', + startDate: '2044-10-30', + endDate: '2044-10-30', + location: 'Mumbai', + startTime: null, + endTime: null, + allDay: true, + recurring: true, + volunteerGroups: [ + { + _id: 'groupId1', + name: 'Group 1', + volunteersRequired: null, + description: 'desc', + volunteers: [ + { + _id: 'volunteerId1', + }, + { + _id: 'volunteerId2', + }, + ], + }, + ], + volunteers: [ + { + _id: 'volunteerId1', + user: { + _id: 'userId1', + }, + }, + { + _id: 'volunteerId2', + user: { + _id: 'userId2', + }, + }, + ], +}; + +const event2 = { + _id: 'eventId2', + title: 'Event 2', + startDate: '2044-10-31', + endDate: '2044-10-31', + location: 'Pune', + startTime: null, + endTime: null, + allDay: true, + recurring: false, + volunteerGroups: [ + { + _id: 'groupId2', + name: 'Group 2', + volunteersRequired: null, + description: 'desc', + volunteers: [ + { + _id: 'volunteerId3', + }, + ], + }, + ], + volunteers: [ + { + _id: 'volunteerId3', + user: { + _id: 'userId3', + }, + }, + ], +}; + +const event3 = { + _id: 'eventId3', + title: 'Event 3', + startDate: '2044-10-31', + endDate: '2022-10-31', + location: 'Delhi', + startTime: null, + endTime: null, + description: 'desc', + allDay: true, + recurring: true, + volunteerGroups: [ + { + _id: 'groupId3', + name: 'Group 3', + volunteersRequired: null, + description: 'desc', + volunteers: [ + { + _id: 'userId', + }, + ], + }, + ], + volunteers: [ + { + _id: 'volunteerId', + user: { + _id: 'userId', + }, + }, + ], +}; + +export const MOCKS = [ + { + request: { + query: USER_EVENTS_VOLUNTEER, + variables: { + organization_id: 'orgId', + title_contains: '', + location_contains: '', + upcomingOnly: true, + first: null, + skip: null, + }, + }, + result: { + data: { + eventsByOrganizationConnection: [event1, event2, event3], + }, + }, + }, + { + request: { + query: USER_EVENTS_VOLUNTEER, + variables: { + organization_id: 'orgId', + title_contains: '1', + location_contains: '', + upcomingOnly: true, + first: null, + skip: null, + }, + }, + result: { + data: { + eventsByOrganizationConnection: [event1], + }, + }, + }, + { + request: { + query: USER_EVENTS_VOLUNTEER, + variables: { + organization_id: 'orgId', + title_contains: '', + location_contains: 'M', + upcomingOnly: true, + first: null, + skip: null, + }, + }, + result: { + data: { + eventsByOrganizationConnection: [event1], + }, + }, + }, + { + request: { + query: CREATE_VOLUNTEER_MEMBERSHIP, + variables: { + data: { + event: 'eventId1', + group: null, + status: 'requested', + userId: 'userId', + }, + }, + }, + result: { + data: { + createVolunteerMembership: { + _id: 'membershipId1', + }, + }, + }, + }, + { + request: { + query: CREATE_VOLUNTEER_MEMBERSHIP, + variables: { + data: { + event: 'eventId1', + group: 'groupId1', + status: 'requested', + userId: 'userId', + }, + }, + }, + result: { + data: { + createVolunteerMembership: { + _id: 'membershipId1', + }, + }, + }, + }, +]; + +export const EMPTY_MOCKS = [ + { + request: { + query: USER_EVENTS_VOLUNTEER, + variables: { + organization_id: 'orgId', + title_contains: '', + location_contains: '', + upcomingOnly: true, + first: null, + skip: null, + }, + }, + result: { + data: { + eventsByOrganizationConnection: [], + }, + }, + }, +]; + +export const ERROR_MOCKS = [ + { + request: { + query: USER_EVENTS_VOLUNTEER, + variables: { + organization_id: 'orgId', + title_contains: '', + location_contains: '', + upcomingOnly: true, + first: null, + skip: null, + }, + }, + error: new Error('Mock Graphql USER_EVENTS_VOLUNTEER Error'), + }, +]; + +export const CREATE_ERROR_MOCKS = [ + { + request: { + query: USER_EVENTS_VOLUNTEER, + variables: { + organization_id: 'orgId', + title_contains: '', + location_contains: '', + upcomingOnly: true, + first: null, + skip: null, + }, + }, + result: { + data: { + eventsByOrganizationConnection: [event1, event2], + }, + }, + }, + { + request: { + query: CREATE_VOLUNTEER_MEMBERSHIP, + variables: { + data: { + event: 'eventId1', + group: null, + status: 'requested', + userId: 'userId', + }, + }, + }, + error: new Error('Mock Graphql CREATE_VOLUNTEER_MEMBERSHIP Error'), + }, +]; diff --git a/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.test.tsx b/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.test.tsx new file mode 100644 index 0000000000..43e0b15cdb --- /dev/null +++ b/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.test.tsx @@ -0,0 +1,224 @@ +import React, { act } from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import type { RenderResult } from '@testing-library/react'; +import { render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18n from 'utils/i18nForTest'; +import UpcomingEvents from './UpcomingEvents'; +import type { ApolloLink } from '@apollo/client'; +import { + MOCKS, + EMPTY_MOCKS, + ERROR_MOCKS, + CREATE_ERROR_MOCKS, +} from './UpcomingEvents.mocks'; +import { toast } from 'react-toastify'; +import useLocalStorage from 'utils/useLocalstorage'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +const { setItem } = useLocalStorage(); + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(ERROR_MOCKS); +const link3 = new StaticMockLink(EMPTY_MOCKS); +const link4 = new StaticMockLink(CREATE_ERROR_MOCKS); + +const t = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.userVolunteer ?? {}, + ), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const debounceWait = async (ms = 300): Promise => { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +}; + +const renderUpcomingEvents = (link: ApolloLink): RenderResult => { + return render( + + + + + + + } + /> +
    } + /> + + + + + + , + ); +}; + +describe('Testing Upcoming Events Screen', () => { + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId' }), + })); + }); + + beforeEach(() => { + setItem('userId', 'userId'); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('should redirect to fallback URL if URL params are undefined', async () => { + setItem('userId', null); + render( + + + + + + } /> +
    - +// User Portal Components +import UserLoginPage from 'screens/UserPortal/UserLoginPage/UserLoginPage'; +import Organizations from 'screens/UserPortal/Organizations/Organizations'; +import Home from 'screens/UserPortal/Home/Home'; +import People from 'screens/UserPortal/People/People'; +import Settings from 'screens/UserPortal/Settings/Settings'; +import Donate from 'screens/UserPortal/Donate/Donate'; +import Events from 'screens/UserPortal/Events/Events'; +import Tasks from 'screens/UserPortal/Tasks/Tasks'; +// import Chat from 'screens/UserPortal/Chat/Chat'; +import Advertisements from 'components/Advertisements/Advertisements'; + +function app(): JSX.Element { + /*const { updatePluginLinks, updateInstalled } = bindActionCreators( + actionCreators, + dispatch + ); + + const getInstalledPlugins = async () => { + const plugins = await fetchInstalled(); + updateInstalled(plugins); + updatePluginLinks(new PluginHelper().generateLinks(plugins)); + }; + + const fetchInstalled = async () => { + const result = await fetch(`http://localhost:3005/installed`); + return await result.json(); + }; + + useEffect(() => { + getInstalledPlugins(); + }, []);*/ + + // const appRoutes = useSelector((state: RootState) => state.appRoutes); + // const { components } = appRoutes; + + // TODO: Fetch Installed plugin extras and store for use within MainContent and Side Panel Components. + + const { data, loading } = useQuery(CHECK_AUTH); + + useEffect(() => { + if (data) { + localStorage.setItem( + 'name', + `${data.checkAuth.firstName} ${data.checkAuth.lastName}` + ); + localStorage.setItem('id', data.checkAuth._id); + localStorage.setItem('email', data.checkAuth.email); + localStorage.setItem('IsLoggedIn', 'TRUE'); + localStorage.setItem('UserType', data.checkAuth.userType); + localStorage.setItem('FirstName', data.checkAuth.firstName); + localStorage.setItem('LastName', data.checkAuth.lastName); + localStorage.setItem('UserImage', data.checkAuth.image); + localStorage.setItem('Email', data.checkAuth.email); + } + }, [data, loading]); + + const extraRoutes = Object.entries(installedPlugins).map( + (plugin: any, index) => { + const extraComponent = plugin[1]; + return ( + ); -